@pacedyn/mcp 0.399.1 → 0.402.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/cli.js +120 -100
- package/dist/worker.js +7 -7
- package/package.json +1 -1
package/dist/worker.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{parentPort as DT,workerData as B$}from"node:worker_threads";import{readFileSync as _y}from"node:fs";import{join as Ny}from"node:path";var Jc=e=>e.format!=="points"&&!e.field;var bt=e=>e?.kind==="ice";var mx={packVoltageMax:600,segmentVoltageMax:120,powerLimitKw:80};var Ee=e=>typeof e=="number"&&Number.isFinite(e);function IT(e){let{soc:t,ocv:r,r0:n}=e;if(!Array.isArray(t)||t.length<2)return"The curve needs at least two state-of-charge points.";if(!t.every(Ee))return"The state-of-charge axis contains a value that is not a number.";if(t[0]<0||t[t.length-1]>1)return`The state-of-charge axis must lie within 0 to 1 (it runs ${t[0]} to ${t[t.length-1]}).`;for(let o=1;o<t.length;o++)if(!(t[o]>t[o-1]))return`The state-of-charge axis must increase (${t[o-1]} then ${t[o]}).`;if(!Array.isArray(r)||r.length!==t.length)return`The curve has ${Array.isArray(r)?r.length:0} voltages against ${t.length} state-of-charge points.`;if(!r.every(Ee))return"The open-circuit voltage contains a value that is not a number.";if(r.some(o=>o<=0))return"The open-circuit voltage must be positive everywhere.";for(let o=1;o<r.length;o++)if(r[o]<r[o-1])return`The open-circuit voltage must rise with state of charge (${r[o-1]} V at ${t[o-1]} then ${r[o]} V at ${t[o]}).`;if(!Array.isArray(n)||n.length!==t.length)return`The curve has ${Array.isArray(n)?n.length:0} resistances against ${t.length} state-of-charge points.`;if(!n.every(Ee))return"The resistance contains a value that is not a number.";if(n.some(o=>o<0))return"The resistance cannot be negative.";if(e.rTempC!==void 0||e.rGrid!==void 0){let o=e.rTempC,a=e.rGrid;if(!Array.isArray(o)||o.length<1)return"The resistance temperature axis needs at least one temperature.";if(!o.every(Ee))return"The resistance temperature axis contains a value that is not a number.";for(let s=1;s<o.length;s++)if(!(o[s]>o[s-1]))return`The temperature axis must increase (${o[s-1]} then ${o[s]} \xB0C).`;if(!Array.isArray(a)||a.length!==o.length)return`The resistance grid has ${Array.isArray(a)?a.length:0} rows against ${o.length} temperatures.`;for(let s=0;s<a.length;s++){let i=a[s];if(!Array.isArray(i)||i.length!==t.length)return`Resistance row ${s+1} has ${Array.isArray(i)?i.length:0} values against ${t.length} state-of-charge points.`;if(!i.every(Ee))return"The resistance grid contains a value that is not a number.";if(i.some(c=>c<0))return"The resistance grid contains a negative resistance."}}return null}function _T(e){return!e||typeof e!="object"?"The cell has no curve.":e.kind==="table"?IT(e):e.kind==="analytic"?!Ee(e.vCut)||!Ee(e.vNom)||!Ee(e.vFull)?"The cut-off, nominal and full voltages must be numbers.":e.vCut<=0?"The cut-off voltage must be positive.":e.vCut<e.vNom&&e.vNom<e.vFull?!Ee(e.r0)||e.r0<0?"The cell resistance must be a number and cannot be negative.":e.socAtNom!==void 0&&(!Ee(e.socAtNom)||e.socAtNom<=0||e.socAtNom>=1)?"The state of charge the nominal voltage is met at must lie strictly between 0 and 1.":null:`The voltages must order cut-off < nominal < full (given ${e.vCut}, ${e.vNom}, ${e.vFull} V).`:`Unknown cell curve kind "${e.kind}".`}function el(e){if(!e||typeof e!="object")return"Not a battery model.";let t=e.cell;if(!t||typeof t!="object")return"The model has no cell.";if(!Ee(t.capacityAh)||t.capacityAh<=0)return"The cell capacity must be a positive number of amp-hours.";if(!Ee(t.vMin)||t.vMin<0)return"The cut-off voltage must be a number and cannot be negative.";if(!Ee(t.vMax)||t.vMax<=0)return"The maximum cell voltage must be a positive number.";if(!(t.vMin<t.vMax))return`The cut-off voltage (${t.vMin} V) must be below the maximum (${t.vMax} V).`;if(!Ee(t.iMaxA)||t.iMaxA<0)return"The discharge current limit must be a number of amps, 0 for no limit.";if(t.iMaxChargeA!==void 0&&(!Ee(t.iMaxChargeA)||t.iMaxChargeA<0))return"The charge current limit must be a number of amps, 0 for no limit.";if(t.massKg!==void 0&&(!Ee(t.massKg)||t.massKg<0))return"The cell mass must be a number and cannot be negative.";let r=_T(t.curve);if(r)return r;let n=t.curve.kind==="table"?t.curve.ocv[t.curve.ocv.length-1]:t.curve.vFull;if(t.vMin>=n)return`The cut-off voltage (${t.vMin} V) is at or above the cell's voltage at full charge (${n} V), so no power could ever be drawn.`;let o=e.thermal;if(o!==void 0){if(!o||typeof o!="object")return"The thermal model must be an object, or absent.";if(!Ee(o.heatCapacityJPerK)||o.heatCapacityJPerK<=0)return"The cell heat capacity must be a positive number of joules per kelvin.";if(!Ee(o.coolingWPerK)||o.coolingWPerK<0)return"The cooling must be a number of watts per kelvin and cannot be negative.";if(o.startC!==void 0&&!Ee(o.startC))return"The starting temperature must be a number.";if(o.entropicVPerK!==void 0&&!Ee(o.entropicVPerK))return"The entropic coefficient must be a number.";if(o.derateFromC!==void 0){if(!Ee(o.derateFromC))return"The temperature the derate starts at must be a number.";if(o.derateToC!==void 0){if(!Ee(o.derateToC))return"The temperature the derate ends at must be a number.";if(!(o.derateToC>o.derateFromC))return`The derate must end above where it starts (given ${o.derateFromC} then ${o.derateToC} \xB0C).`}}else if(o.derateToC!==void 0)return"The derate has an end temperature but no start; give both or neither."}let a=e.pack;if(!a||typeof a!="object")return"The model has no pack.";if(!Number.isInteger(a.series)||a.series<1)return"The pack needs a whole number of cells in series, at least one.";if(!Number.isInteger(a.parallel)||a.parallel<1)return"The pack needs a whole number of strings in parallel, at least one.";if(!Ee(a.busResistance)||a.busResistance<0)return"The busbar resistance must be a number and cannot be negative.";if(a.seriesPerSegment!==void 0&&a.seriesPerSegment!==0){if(!Number.isInteger(a.seriesPerSegment)||a.seriesPerSegment<1)return"The cells per segment must be a whole number, at least one.";if(a.seriesPerSegment>a.series)return`A segment cannot hold more cells (${a.seriesPerSegment}) than the pack has in series (${a.series}).`}return null}function Nn(e,t){let r=e.length;if(r<=1)return{i:0,t:0,clamped:!1};if(t<=e[0])return{i:0,t:0,clamped:t<e[0]};if(t>=e[r-1])return{i:r-2,t:1,clamped:t>e[r-1]};let n=0,o=r-1;for(;o-n>1;){let a=n+o>>1;e[a]<=t?n=a:o=a}return{i:n,t:(t-e[n])/(e[o]-e[n]),clamped:!1}}function Ge(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function tl(e,t,r,n,o){let a=e.length,s=t.length;if(a===0||s===0)return 0;let i=Nn(e,n),c=Nn(t,o),l=Math.min(i.i+1,a-1),u=Math.min(c.i+1,s-1),m=r[c.i][i.i],d=r[c.i][l],p=r[u][i.i],f=r[u][l],h=m+i.t*(d-m),b=p+i.t*(f-p);return h+c.t*(b-h)}var Ko=[0,.05,.1,.2,.3,.4,.5,.6,.7,.8,.9,1],id={nmc:[0,.29,.4,.483,.525,.567,.608,.667,.733,.8,.892,1],lfp:[0,.478,.591,.626,.652,.67,.678,.696,.704,.722,.757,1],lipo:[0,.333,.433,.517,.575,.625,.667,.717,.775,.833,.908,1],other:[0,.05,.1,.2,.3,.4,.5,.6,.7,.8,.9,1]},px=[0,.05,.1,.2,.5,.8,1],dx=[2.2,1.55,1.3,1.12,1,.97,.98];function fx(e){return Ge(px,dx,e)}var hx=[-20,-10,0,10,25,40,60],bx=[4,2.8,2,1.4,1,.82,.75];function cd(e){return Ge(hx,bx,e)}var gx=.5;function ld(e,t){let{vFull:r,vNom:n,vCut:o,r0:a}=e,s=r-o;if(!(s>0))throw new Error(`The full voltage (${r} V) must be above the cut-off (${o} V).`);let i=(n-o)/s;if(!(i>0&&i<1))throw new Error(`The nominal voltage (${n} V) must lie between the cut-off (${o} V) and full (${r} V).`);let c=id[t]??id.other,l=e.socAtNom??gx,u=Ko.includes(l)?[...Ko]:[...Ko,l].sort((h,b)=>h-b),m=Ge(Ko,c,l),d=m>0&&m<1?Math.log(i)/Math.log(m):1,p=[],f=[];for(let h of u){let b=Ge(Ko,c,h);p.push(o+s*Math.pow(b,d)),f.push(e.constantResistance?a:a*fx(h))}return{kind:"table",soc:u,ocv:p,r0:f}}function ud(e){let t=e.soc,r=e.ocv,n=[0,...t.filter(a=>a>0&&a<1),1],o=0;for(let a=1;a<n.length;a++){let s=n[a-1],i=n[a];o+=(Ge(t,r,s)+Ge(t,r,i))/2*(i-s)}return o}var Ho=25,yx=new WeakMap;function Sr(e){let t=yx.get(e);if(t)return t;let r=el(e);if(r)throw new Error(r);let{cell:n,pack:o}=e,a=n.curve.kind==="table"?n.curve:ld(n.curve,n.chemistry),s=o.series,i=o.parallel,c=s/i,l=a.rTempC,u=a.rGrid,m=i*n.capacityAh,d=s*n.vMin,p=n.iMaxA>0?i*n.iMaxA:1/0,f=n.iMaxChargeA!==void 0&&n.iMaxChargeA>0?n.iMaxChargeA:n.iMaxA/4,h=f>0?i*f:1/0,b=A=>s*Ge(a.soc,a.ocv,A),g=(A,w=Ho)=>{let C=l&&u?tl(a.soc,l,u,A,w):Ge(a.soc,a.r0,A)*cd(w);return c*C+o.busResistance},y=(A,w,C)=>b(A)-w*g(A,C),R=(A,w,C)=>{if(!(A>0))return 0;let T=b(w),F=g(w,C);if(!(F>0))return A/T;let S=T*T-4*F*A;return S<0?NaN:2*A/(T+Math.sqrt(S))},k=(A,w,C)=>{if(!(A>0))return 0;let T=b(w),F=g(w,C);return F>0?2*A/(T+Math.sqrt(T*T+4*F*A)):A/T},v=A=>{let w=e.thermal;if(!w||w.derateFromC===void 0)return 1;let C=w.derateToC??w.derateFromC;return A<=w.derateFromC?1:!(C>w.derateFromC)||A>=C?0:1-(A-w.derateFromC)/(C-w.derateFromC)},x=(A,w,C=0)=>{let T=b(A),F=g(A,w),S=F>0?T/(2*F):1/0,P=G=>{if(!(F>0))return G*T;let K=Math.min(G,S);return K*(T-K*F)},L=F>0?Math.max(0,(T-d)/F):1/0,D=C>0&&Number.isFinite(C)?C:1/0,I=F>0?P(L):1/0,O=Number.isFinite(p)?P(p):1/0,_=F>0?T*T/(4*F):1/0,z=[["rules",D],["voltage-floor",I],["current",O],["matched-load",_]],E=z[0][0],N=z[0][1];for(let[G,K]of z)K<N&&(N=K,E=G);let B=v(w??Ho);B<1&&(N=Number.isFinite(N)?N*B:N,E="temperature");let V=Number.isFinite(N)?R(N,A,w):1/0;return{watts:N,binding:E,rules:D,voltageFloor:I,current:O,matchedLoad:_,derate:B,amps:V,volts:Number.isFinite(V)?T-V*F:T}},M={model:e,table:a,capacityAh:m,chargeC:m*3600,energyKwh:m*(s*ud(a))/1e3,socRange:[a.soc[0],a.soc[a.soc.length-1]],voltageAtFull:s*a.ocv[a.ocv.length-1],voltageCeiling:s*n.vMax,voltageFloor:d,currentCeiling:p,chargeCurrentCeiling:h,massKg:n.massKg!==void 0?s*i*n.massKg:null,thermal:e.thermal?{heatCapacityJPerK:s*i*e.thermal.heatCapacityJPerK,coolingWPerK:s*i*e.thermal.coolingWPerK,...e.thermal.startC!==void 0?{startC:e.thermal.startC}:{},entropicVPerK:s*(e.thermal.entropicVPerK??0)}:null,derateAt:v,ocv:b,resistance:g,terminalVoltage:y,currentFor:R,chargeCurrentFor:k,maxPower:x};return yx.set(e,M),M}function md(e){return{name:e.name,chemistry:e.chemistry,capacityAh:e.capacityAh,curve:{kind:"analytic",vFull:e.vFull,vNom:e.vNom,vCut:e.vCut,r0:e.r0},iMaxA:e.iMaxA,...e.iMaxChargeA!==void 0?{iMaxChargeA:e.iMaxChargeA}:{},vMin:e.vCut,vMax:e.vFull,...e.massKg!==void 0?{massKg:e.massKg}:{}}}var xx={name:"High-power NMC pouch 4.0 Ah",chemistry:"nmc",capacityAh:4,vCut:3,vNom:3.6,vFull:4.2,r0:.0025,iMaxA:100,iMaxChargeA:40,massKg:.09},Rx={name:"LFP prismatic 20 Ah",chemistry:"lfp",capacityAh:20,vCut:2.5,vNom:3.2,vFull:3.65,r0:.002,iMaxA:200,iMaxChargeA:60,massKg:.4},vx={name:"NMC cylindrical 3.4 Ah",chemistry:"nmc",capacityAh:3.4,vCut:3,vNom:3.6,vFull:4.2,r0:.03,iMaxA:10,iMaxChargeA:3,massKg:.048};function pd(){return{name:"Formula Student accumulator",cell:md(xx),pack:{series:140,parallel:2,busResistance:.02,seriesPerSegment:28},provenance:{source:"assumed",note:"Assumed high-power NMC pouch pack sized to the Formula Student rules; the cell curve and resistance are class-level guesses, not a measurement."}}}function dd(){return{name:"LFP pack",cell:md(Rx),pack:{series:160,parallel:1,busResistance:.02,seriesPerSegment:32},provenance:{source:"assumed",note:"Assumed LFP prismatic pack; the flat plateau is the chemistry, the numbers are class-level guesses."}}}function fd(){return{name:"Road car pack",cell:md(vx),pack:{series:96,parallel:74,busResistance:.01},provenance:{source:"assumed",note:"Assumed road-electric pack of cylindrical energy cells; capacity and voltage are class-typical, the resistance is a guess."}}}function hd(e,t,r="Constant pack"){return{name:r,cell:{name:"Constant cell",chemistry:"other",capacityAh:e,curve:{kind:"table",soc:[0,1],ocv:[t,t],r0:[0,0]},iMaxA:0,vMin:0,vMax:t},pack:{series:1,parallel:1,busResistance:0},provenance:{source:"assumed",note:"The constant pack: one open-circuit voltage, no internal resistance and no current limit \u2014 what a car carried before the battery was a model. It cannot sag, so its power never fades."}}}function rl(e){if(e.kind==="ice"){let n=e.gearbox.efficiency;return{model:e,maxTorque:o=>o>e.limitRpm?0:Ge(e.rpm,e.torque,o),efficiency:()=>n}}let t=n=>Ge(e.rpm,e.torque,n),r=e.kind==="simple"?()=>e.efficiency:(n,o)=>tl(e.effRpm,e.effTorque,e.effGrid,n,o);return{model:e,maxTorque:t,efficiency:r}}function bd(e){let t=e.resistanceAtC??20,r=e.torqueConstant,n=e.speedLossW??0,o=e.speedLossAtRpm??0,a=e.speedLossExponent??1.5,s=e.derateFromC,i=e.derateToC,c=f=>Math.max(0,e.terminalResistanceOhm*(1+.00393*(f-t))),l=f=>n>0&&o>0?n*Math.pow(Math.max(0,f)/o,a):0,u=(f,h,b)=>{let g=r>0?Math.abs(h)/r:0;return 1.5*c(b)*g*g+l(f)},m=(f,h)=>{let b=e.coolingWPerK*(h-e.coolantC)-l(f);return!(b>0)||r<=0?0:r*Math.sqrt(b/(1.5*c(h)))},d=e.coolingWPerK>0?e.heatCapacityJPerK/e.coolingWPerK:1/0,p=Number.isFinite(d)?.25*d:1/0;return{spec:e,startC:e.startC??e.coolantC,lossW:u,step(f,h,b){if(!(b>0)||!(e.heatCapacityJPerK>0))return f;let g=Number.isFinite(p)?Math.max(1,Math.ceil(b/p)):1,y=b/g,R=f;for(let k=0;k<g;k++)R+=(h-e.coolingWPerK*(R-e.coolantC))*y/e.heatCapacityJPerK;return R},continuousTorque:m,derate(f,h,b){if(s===void 0||i===void 0||!(i>s)||!(b>0)||h<=s)return 1;let g=Math.min(1,m(f,i)/b);return h>=i?g:1-(1-g)*(h-s)/(i-s)},equilibriumC(f){return e.coolingWPerK>0?e.coolantC+f/e.coolingWPerK:1/0}}}function Xe(e,t){return t==="rear"&&e.tireRateRear!==void 0?e.tireRateRear:e.tireRate}function gd(e,t){let r=e.tyreFreeRadiusRear;return(t==="rear"&&r!==void 0?r:e.tyreFreeRadius)??0}var nl=9.81,kx=(e,t)=>e*(t*t)/2*(Math.PI/180)/1e3,ms=(e,t)=>e+t>0?e*t/(e+t):0,Mx=.5;function ol(e,t,r){if(!(r>0))return 1;let n=e*nl*t*(Math.PI/180)/r;return 1/(1-Math.min(Mx,n))}function yd(e,t,r){return r>0?e*nl*t/(r*r):0}function Sx(e,t,r,n,o){if(!(n>0)||!(o>0))return 1;let a=yd(e,t,r)*(1/n+1/o);return 1/(1-Math.min(Mx,a))}function we(e){let t=4*e.unsprungPerCorner,r=Math.max(0,e.massTotal-t),n=r*e.frontMassFrac,o=r*(1-e.frontMassFrac),a=Xe(e,"front"),s=Xe(e,"rear"),i=e.wheelRateFront+(e.heaveSpringFront??0),c=e.wheelRateRear+(e.heaveSpringRear??0),l=ms(i,a),u=ms(c,s),m=(O,_)=>{let z=_/2;return z>0?1/(2*Math.PI)*Math.sqrt(O*1e3/z):0},d=m(l,n),p=m(u,o),f=ms(e.wheelRateFront+e.arbFront,a),h=ms(e.wheelRateRear+e.arbRear,s),b=kx(f,e.trackFront),g=kx(h,e.trackRear),y=b+g,R=y>0?b/y:.5,k=e.rcHeightFront+(e.rcHeightRear-e.rcHeightFront)*(1-e.frontMassFrac),v=(e.cgHeight-k)/1e3,x=r*nl*v,M=ol(r,v,y),A=y>0?x/y*M:0,w=e.massTotal*nl*e.cgHeight/e.wheelbase,C=2*l,T=2*u,F=Sx(r,e.cgHeight,e.wheelbase,C,T),P=(C>0&&T>0?(w/C+w/T)/e.wheelbase*F:0)*(180/Math.PI),L=e.wheelbase*e.wheelbase*ms(C,T)*(Math.PI/180)/1e3,D=e.damperFront??2.5,I=e.damperRear??2.5;return{sprungMass:r,sprungFront:n,sprungRear:o,rideRateFront:l,rideRateRear:u,rideFreqFront:d,rideFreqRear:p,rollRateFront:b,rollRateRear:g,rollRateTotal:y,rollWheelRateFront:f,rollWheelRateRear:h,frontRollStiffFrac:R,rollGradient:A,pitchGradient:P,pitchRate:L,cgRollGain:M,cgPitchGain:F,rideDampingFront:D+(e.heaveDamperFront??0),rideDampingRear:I+(e.heaveDamperRear??0),rollDampingFront:D+(e.rollDamperFront??0),rollDampingRear:I+(e.rollDamperRear??0)}}var rn=["clFront","clRear","cd"],nn=e=>e.frame?.kind==="pitch";function zo(e){return nn(e)?{x:e.axes.h,y:e.axes.pitch}:{x:e.axes.hFront,y:e.axes.hRear}}var al=e=>e.frame?.kind==="pitch",Ax=e=>e.kind==="map";var sl=45,Ze=e=>typeof e=="number"&&Number.isFinite(e);function il(e,t,r="mm",n="ride height"){if(!Array.isArray(t)||t.length<1)return`The ${e} axis needs at least one ${n}.`;if(!t.every(Ze))return`The ${e} axis contains a value that is not a number.`;for(let o=1;o<t.length;o++)if(!(t[o]>t[o-1]))return`The ${e} axis must increase (${t[o-1]} then ${t[o]} ${r}).`;return null}function Fx(e,t){if(t===void 0)return null;for(let r of rn){let n=t[r];if(!n||!Array.isArray(n.deg)||!Array.isArray(n.factor))return`The ${e} correction of ${r} needs degrees and factors.`;if(n.deg.length<1)return`The ${e} correction of ${r} needs at least one angle.`;if(n.deg.length!==n.factor.length)return`The ${e} correction of ${r} has ${n.factor.length} factors against ${n.deg.length} angles.`;if(!n.deg.every(Ze)||!n.factor.every(Ze))return`The ${e} correction of ${r} contains a value that is not a number.`;if(n.deg[0]<0)return`The ${e} correction of ${r} is against the absolute angle; it cannot start below zero.`;for(let o=1;o<n.deg.length;o++)if(!(n.deg[o]>n.deg[o-1]))return`The ${e} correction of ${r} must increase in angle (${n.deg[o-1]} then ${n.deg[o]}\xB0).`;if(n.factor.some(o=>o<0))return`The ${e} correction of ${r} has a negative factor.`}return null}function wx(e,t){return t===void 0?null:!Ze(t.dCl)||!Ze(t.dBalance)||!Ze(t.dCd)?`The ${e} slopes must be numbers.`:!Ze(t.maxDeg)||!(t.maxDeg>0)?`The ${e} response needs a positive angle to be valid to.`:null}function ps(e){if(!e||typeof e!="object")return"Not an aero model.";if(!Ze(e.area)||e.area<=0)return"The reference area must be a positive number of square metres.";if(e.kind==="map"){let t,r,n,o;if(e.frame==null){let i=il("front ride-height",e.axes?.hFront);if(i)return i;let c=il("rear ride-height",e.axes?.hRear);if(c)return c;[t,r,n,o]=[e.axes.hFront,e.axes.hRear,"front ride heights","rear ride heights"]}else if(e.frame?.kind==="pitch"){if(!Ze(e.frame.refX))return"The point the ride height is read at must be a number of millimetres aft of the front axle.";let i=il("ride-height",e.axes?.h);if(i)return i;let c=il("pitch",e.axes?.pitch,"\xB0","pitch");if(c)return c;let l=e.axes.pitch.find(u=>Math.abs(u)>=sl);if(l!==void 0)return`A pitch of ${l}\xB0 is not a car's attitude \u2014 is the axis a rake in millimetres? Pitch is in degrees.`;[t,r,n,o]=[e.axes.h,e.axes.pitch,"ride heights","pitches"]}else return`Unknown aero map frame "${e.frame.kind}".`;let a=t.length,s=r.length;for(let i of rn){let c=e[i];if(!Array.isArray(c)||c.length!==s)return`${i} has ${Array.isArray(c)?c.length:0} rows against ${s} ${o} \u2014 they must match.`;for(let l=0;l<s;l++){let u=c[l];if(!Array.isArray(u)||u.length!==a)return`${i} row ${l+1} has ${Array.isArray(u)?u.length:0} values against ${a} ${n}.`;if(!u.every(Ze))return`${i} contains a value that is not a number.`}}return Fx("yaw",e.attitude?.yaw)??Fx("roll",e.attitude?.roll)}if(e.kind==="sensitivity"){let t;if(e.frame==null)t=["hFront","hRear"];else if(e.frame?.kind==="pitch"){if(!Ze(e.frame.refX))return"The point the ride height is read at must be a number of millimetres aft of the front axle.";t=["h","pitch"]}else return`Unknown aero sensitivity frame "${e.frame.kind}".`;let r=e.ref,n=e.slope,o=e.range,a=s=>s==="pitch"?"\xB0":" mm";if(!r||!Ze(r[t[0]])||!Ze(r[t[1]]))return e.frame?"The reference ride height and pitch must be numbers.":"The reference ride heights must be numbers.";for(let s of rn){if(!e.at||!Ze(e.at[s]))return`${s} at the reference must be a number.`;let i=n?.[s];if(!i||!Ze(i[t[0]])||!Ze(i[t[1]]))return`The slopes of ${s} must be numbers.`}for(let s of t){let i=o?.[s],c=r[s];if(!i||!Ze(i[0])||!Ze(i[1]))return`The ${s} range must be two numbers.`;if(!(i[1]>i[0]))return`The ${s} range must run from low to high (${i[0]} to ${i[1]}${a(s)}).`;if(c<i[0]||c>i[1])return`The reference ${s} of ${c}${a(s)} lies outside its range ${i[0]}\u2013${i[1]}${a(s)}.`;if(s==="pitch"&&(Math.abs(i[0])>=sl||Math.abs(i[1])>=sl))return`A pitch range reaching ${Math.abs(i[0])>=sl?i[0]:i[1]}\xB0 is not a car's attitude. Pitch is in degrees.`}return wx("yaw",e.attitude?.yaw)??wx("roll",e.attitude?.roll)}return`Unknown aero model kind "${e.kind}".`}var Cx=180/Math.PI;function Yo(e,t,r,n){let o=(n-r)/t;return{h:r+e.refX*o,pitch:Math.atan(o)*Cx}}function Wo(e,t,r,n){let o=Math.tan(n/Cx);return{hFront:r-e.refX*o,hRear:r+(t-e.refX)*o}}var AG=180/Math.PI,NT=["hFront","hRear"],OT=["h","pitch"],vd=e=>e?.kind==="pitch"?OT:NT,Ft=(e,t)=>e[t],cl=(e,t)=>e[t],xd=(e,t)=>({[e[0]]:t(e[0]),[e[1]]:t(e[1])});function VT(e){if(!(!e.yaw&&!e.roll))return{...e.yaw?{yaw:{...e.yaw}}:{},...e.roll?{roll:{...e.roll}}:{}}}function kd(e){let t=vd(e.frame),r=e.balanceFront,n=e.cl*r,o=e.cl*(1-r),a=xd(t,c=>Ft(e.dCl,c)*r+e.cl*Ft(e.dBalance,c)),s=xd(t,c=>Ft(e.dCl,c)*(1-r)-e.cl*Ft(e.dBalance,c)),i=VT(e);return{kind:"sensitivity",name:e.name,area:e.area,...e.frame?{frame:{...e.frame}}:{},ref:{...e.ref},at:{clFront:n,clRear:o,cd:e.cd},slope:{clFront:a,clRear:s,cd:xd(t,c=>Ft(e.dCd,c))},range:{[t[0]]:[...cl(e.range,t[0])],[t[1]]:[...cl(e.range,t[1])]},provenance:{...e.provenance},...i?{attitude:i}:{}}}function ll(e,t,r){let n=Math.min(Math.abs(r),t.maxDeg),o=e.clFront+e.clRear,a=o!==0?e.clFront/o:.5,s=o+t.dCl*n,i=a+t.dBalance*n,c=e.clFront!==0?s*i/e.clFront:1,l=e.clRear!==0?s*(1-i)/e.clRear:1,u=e.cd!==0?(e.cd+t.dCd*n)/e.cd:1;return{clFront:c,clRear:l,cd:u}}function Rd(e,t,r=11){let n=Array.from({length:r},(a,s)=>t.maxDeg*s/(r-1)),o=n.map(a=>ll(e,t,a));return{clFront:{deg:[...n],factor:o.map(a=>a.clFront)},clRear:{deg:[...n],factor:o.map(a=>a.clRear)},cd:{deg:[...n],factor:o.map(a=>a.cd)}}}function Tx(e){if(!(!e.attitude?.yaw&&!e.attitude?.roll))return{...e.attitude.yaw?{yaw:Rd(e.at,e.attitude.yaw)}:{},...e.attitude.roll?{roll:Rd(e.at,e.attitude.roll)}:{}}}function Px(e,t,r,n=0,o=0){let[a,s]=vd(e.frame),i=t-Ft(e.ref,a),c=r-Ft(e.ref,s),l={clFront:e.at.clFront+Ft(e.slope.clFront,a)*i+Ft(e.slope.clFront,s)*c,clRear:e.at.clRear+Ft(e.slope.clRear,a)*i+Ft(e.slope.clRear,s)*c,cd:e.at.cd+Ft(e.slope.cd,a)*i+Ft(e.slope.cd,s)*c},u=e.attitude?.yaw?ll(e.at,e.attitude.yaw,n):{clFront:1,clRear:1,cd:1},m=e.attitude?.roll?ll(e.at,e.attitude.roll,o):{clFront:1,clRear:1,cd:1};return{clFront:l.clFront*u.clFront*m.clFront,clRear:l.clRear*u.clRear*m.clRear,cd:l.cd*u.cd*m.cd}}function Md(e){let[t,r]=vd(e.frame),n=[...cl(e.range,t)],o=[...cl(e.range,r)],a=i=>o.map(c=>n.map(l=>i(Px(e,l,c)))),s=Tx(e);return{kind:"map",name:e.name,area:e.area,...e.frame?{frame:{...e.frame}}:{},axes:{[t]:n,[r]:o},clFront:a(i=>i.clFront),clRear:a(i=>i.clRear),cd:a(i=>i.cd),provenance:{...e.provenance},...s?{attitude:s}:{}}}var Sd=180/Math.PI,Lx=new WeakMap,Dx=new WeakMap,Ad=new WeakMap;function on(e,t){let r=Dx.get(e);if(r)return r;let n=t?.wheelbase,o=n!==void 0?Ad.get(e)?.get(n):void 0;if(o)return o;let a=BT(e),s=a.map;if(!nn(s)){let l=$T(e,a);return Dx.set(e,l),l}if(n===void 0||!Number.isFinite(n)||n<=0)throw new Error("A ride-height-and-pitch aero map is read with the car\u2019s wheelbase, and none was given.");let i=GT(e,a,s.frame,n),c=Ad.get(e);return c||(c=new Map,Ad.set(e,c)),c.set(n,i),i}function BT(e){let t=Lx.get(e);if(t)return t;let r=ps(e);if(r)throw new Error(r);let n=e.kind==="map"?e:Md(e),{x:o,y:a}=zo(n),s=o.length,i=a.length,c=n.attitude?.yaw,l=n.attitude?.roll,u=!!(c||l),m={clFront:1,clRear:1,cd:1,clamped:!1},d=(y,R)=>{let k=Math.abs(R),v=y.clFront.deg[y.clFront.deg.length-1];return{clFront:Ge(y.clFront.deg,y.clFront.factor,k),clRear:Ge(y.clRear.deg,y.clRear.factor,k),cd:Ge(y.cd.deg,y.cd.factor,k),clamped:k>v}},p=(y,R)=>{if(!u)return m;let k=c?d(c,y):m,v=l?d(l,R):m;return{clFront:k.clFront*v.clFront,clRear:k.clRear*v.clRear,cd:k.cd*v.cd,clamped:k.clamped||v.clamped}},f=(y,R,k=0,v=0)=>{let x=Nn(o,y),M=Nn(a,R),A=Math.min(x.i+1,s-1),w=Math.min(M.i+1,i-1),C=F=>{let S=F[M.i][x.i],P=F[M.i][A],L=F[w][x.i],D=F[w][A],I=S+x.t*(P-S),O=L+x.t*(D-L);return I+M.t*(O-I)},T=p(k,v);return{clFront:u?C(n.clFront)*T.clFront:C(n.clFront),clRear:u?C(n.clRear)*T.clRear:C(n.clRear),cd:u?C(n.cd)*T.cd:C(n.cd),clampedRide:x.clamped||M.clamped,clampedAttitude:T.clamped}},h={x:[o[0],o[s-1]],y:[a[0],a[i-1]]},b=(y,R,k=!1,v=0,x=0)=>{let M=p(v,x),A=Nn(o,k?Math.min(Math.max(y,h.x[0]),h.x[1]):y),w=Nn(a,k?Math.min(Math.max(R,h.y[0]),h.y[1]):R),C=Math.min(A.i+1,s-1),T=Math.min(w.i+1,i-1),F=C>A.i?o[C]-o[A.i]:0,S=T>w.i?a[T]-a[w.i]:0,P={};for(let L of rn){let D=n[L],I=D[w.i][A.i],O=D[w.i][C],_=D[T][A.i],z=D[T][C],E=A.clamped||F===0?0:((O-I)*(1-w.t)+(z-_)*w.t)/F,N=w.clamped||S===0?0:((_-I)*(1-A.t)+(z-O)*A.t)/S;P[L]=u?{x:E*M[L],y:N*M[L]}:{x:E,y:N}}return P},g={map:n,x:h.x,y:h.y,hasAttitude:u,factors:p,at:f,slopes:b};return Lx.set(e,g),g}function $T(e,t){let r={x:t.x,y:t.y,at:t.at,toAxles:(o,a)=>({hFront:o,hRear:a}),fromAxles:(o,a)=>({x:o,y:a})},n=(o,a,s=!1,i=0,c=0)=>{let l=t.slopes(o,a,s,i,c),u={};for(let m of rn)u[m]={hFront:l[m].x,hRear:l[m].y};return u};return{model:e,map:t.map,area:t.map.area,grid:r,hasAttitude:t.hasAttitude,at:t.at,slopes:n,factors:t.factors}}function GT(e,t,r,n){let o=r.refX,a=o/n,s=(l,u,m=0,d=0)=>{let p=(u-l)/n;return t.at(l+o*p,Math.atan(p)*Sd,m,d)},i=(l,u,m=!1,d=0,p=0)=>{let f=(u-l)/n,h=t.slopes(l+o*f,Math.atan(f)*Sd,m,d,p),b=Sd/(n*(1+f*f)),g={};for(let y of rn)g[y]={hFront:h[y].x*(1-a)-h[y].y*b,hRear:h[y].x*a+h[y].y*b};return g},c={frame:r,x:t.x,y:t.y,at:t.at,toAxles:(l,u)=>Wo(r,n,l,u),fromAxles:(l,u)=>{let m=Yo(r,n,l,u);return{x:m.h,y:m.pitch}}};return{model:e,map:t.map,area:t.map.area,grid:c,hasAttitude:t.hasAttitude,at:s,slopes:i,factors:t.factors}}function Fd(e){let t=e.clFront+e.clRear;return{cl:t,balanceFront:t!==0?e.clFront/t:.5}}var he=(e,t)=>e*t/100,qe=e=>e/100,Ex={name:"Formula Student aero",area:1,cl:3,balanceFront:.45,cd:1.3,ref:{hFront:30,hRear:35},range:{hFront:[5,60],hRear:[10,70]},dCl:{hFront:he(3,-.4),hRear:he(3,.1)},dBalance:{hFront:qe(-.3),hRear:qe(.15)},dCd:{hFront:he(1.3,-.1),hRear:he(1.3,.05)},yaw:{dCl:he(3,-1),dBalance:qe(-.3),dCd:he(1.3,.5),maxDeg:10},roll:{dCl:he(3,-.5),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for an undertray-and-wings Formula Student car, ride height, yaw and roll; not measured."},Ix={name:"Formula 1 aero",area:1.5,cl:3,balanceFront:.44,cd:.9,ref:{hFront:35,hRear:70},range:{hFront:[0,60],hRear:[20,100]},dCl:{hFront:he(3,-.3),hRear:he(3,-.15)},dBalance:{hFront:qe(-.15),hRear:qe(.15)},dCd:{hFront:he(.9,-.15),hRear:he(.9,-.05)},yaw:{dCl:he(3,-1.5),dBalance:qe(.2),dCd:he(.9,.8),maxDeg:8},roll:{dCl:he(3,-1),dBalance:qe(-.3),dCd:0,maxDeg:2},note:"Assumed class-level sensitivities for a ground-effect floor, ride height, yaw and roll; not measured."},_x={name:"GT car aero",area:2,cl:1.4,balanceFront:.42,cd:.42,ref:{hFront:55,hRear:75},range:{hFront:[10,90],hRear:[10,110]},dCl:{hFront:he(1.4,-.3),hRear:he(1.4,.05)},dBalance:{hFront:qe(-.25),hRear:qe(.15)},dCd:{hFront:he(.42,-.1),hRear:0},yaw:{dCl:he(1.4,-.8),dBalance:qe(-.2),dCd:he(.42,.6),maxDeg:10},roll:{dCl:he(1.4,-.3),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a splitter-and-wing GT car, ride height, yaw and roll; not measured."},Nx={name:"Sports car aero",area:2.2,cl:-.1,balanceFront:.5,cd:.3,ref:{hFront:130,hRear:140},range:{hFront:[80,180],hRear:[100,200]},dCl:{hFront:-5e-4,hRear:0},dBalance:{hFront:0,hRear:0},dCd:{hFront:2e-4,hRear:0},yaw:{dCl:0,dBalance:0,dCd:he(.3,.5),maxDeg:10},note:"Assumed class-level sensitivities for a road car with no aero devices; not measured."},Ox={name:"Cup car aero",area:2.1,cl:.45,balanceFront:.45,cd:.4,ref:{hFront:64,hRear:78},range:{hFront:[20,100],hRear:[30,120]},dCl:{hFront:he(.45,-.4),hRear:he(.45,.05)},dBalance:{hFront:qe(-.25),hRear:qe(.15)},dCd:{hFront:he(.4,-.1),hRear:0},yaw:{dCl:he(.45,-1.2),dBalance:qe(-.2),dCd:he(.4,.6),maxDeg:10},roll:{dCl:he(.45,-.3),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a splitter-and-wing cup hatchback, ride height, yaw and roll; not measured."},Vx={name:"Stock car aero",area:2.2,cl:.6,balanceFront:.45,cd:.45,ref:{hFront:75,hRear:90},range:{hFront:[20,110],hRear:[30,130]},dCl:{hFront:he(.6,-.35),hRear:he(.6,.05)},dBalance:{hFront:qe(-.25),hRear:qe(.15)},dCd:{hFront:he(.45,-.1),hRear:0},yaw:{dCl:he(.6,-1),dBalance:qe(-.2),dCd:he(.45,.6),maxDeg:10},roll:{dCl:he(.6,-.3),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a splitter-and-spoiler stock car, ride height, yaw and roll; not measured."},Bx={name:"Hill-climb prototype aero",area:1.2,cl:2.5,balanceFront:.42,cd:.9,ref:{hFront:45,hRear:55},range:{hFront:[10,80],hRear:[15,95]},dCl:{hFront:he(2.5,-.35),hRear:he(2.5,.05)},dBalance:{hFront:qe(-.25),hRear:qe(.15)},dCd:{hFront:he(.9,-.1),hRear:he(.9,.05)},yaw:{dCl:he(2.5,-1),dBalance:qe(-.3),dCd:he(.9,.5),maxDeg:10},roll:{dCl:he(2.5,-.5),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a winged sports prototype with a flat floor and diffuser, ride height, yaw and roll; not measured."},$x={name:"Race truck aero",area:6.2,cl:-.1,balanceFront:.6,cd:.65,ref:{hFront:110,hRear:240},range:{hFront:[60,160],hRear:[180,300]},dCl:{hFront:-5e-4,hRear:0},dBalance:{hFront:0,hRear:0},dCd:{hFront:2e-4,hRear:0},yaw:{dCl:0,dBalance:0,dCd:he(.65,.5),maxDeg:10},note:"Assumed class-level sensitivities for a cab-over race truck with a chin spoiler and deflectors, ride height and yaw; not measured."};function Ar(e){return kd({name:e.name,area:e.area,cl:e.cl,balanceFront:e.balanceFront,cd:e.cd,ref:e.ref,range:e.range,dCl:e.dCl,dBalance:e.dBalance,dCd:e.dCd,...e.yaw?{yaw:e.yaw}:{},...e.roll?{roll:e.roll}:{},provenance:{source:"assumed",note:e.note}})}var wd=()=>Ar(Ex),Cd=()=>Ar(Ix),Td=()=>Ar(_x),Pd=()=>Ar(Nx),Ld=()=>Ar(Ox),Dd=()=>Ar(Vx),Ed=()=>Ar(Bx),Id=()=>Ar($x);function On(e,t){let r=.5*e.rho*e.area*t*t,n=e.cl*r,o=e.cw*r,a=n*e.copLongFront;return{downforce:n,drag:o,downFront:a,downRear:n-a}}function ul(e,t){let r=e.massTotal;if(!(r>0))return{front:0,rear:0};let n=Math.max(0,Math.min(1,e.frontMassFrac)),o=2*e.unsprungPerCorner,a=(s,i)=>i>0?Math.min(1,s/i):0;return{front:(t.sprungMass*n+o*a(t.rideRateFront,Xe(e,"front")))/r,rear:(t.sprungMass*(1-n)+o*a(t.rideRateRear,Xe(e,"rear")))/r}}function ml(e,t,r,n){let o=t.front*r+t.rear*n;return o===0?e:Math.max(Math.min(1,e),e-o)}function _d(e,t){return e.wheelbase>0?e.massTotal*t*9.81/e.wheelbase:0}function jo(e,t,r){let n=2*t.rideRateFront,o=2*t.rideRateRear;return!(n>0)||!(o>0)?0:Math.min(yd(t.sprungMass,r,e.wheelbase),.5*n*o/(n+o))}function ds(e,t,r,n,o){let a=e.cgHeight,s=_d(e,r);if(n===0&&o===0&&s===0)return{height:a,forward:0,noseLoad:0,dropFront:0,dropRear:0};let i=ul(e,t),c=2*t.rideRateFront,l=2*t.rideRateRear,u=a,m=0,d=0,p=0;for(let h=0;h<6;h++){p=jo(e,t,u);let b=n-s*u,g=o+s*u;if(p>0){let k=c*l-p*(c+l);m=(b*(l-p)-p*g)/k,d=(g*(c-p)-p*b)/k}else m=c>0?b/c:0,d=l>0?g/l:0;let y=ml(a,i,m,d),R=Math.abs(y-u);if(u=y,R<1e-9)break}let f=m-d;return{height:u,forward:e.wheelbase>0?u*f/e.wheelbase:0,noseLoad:p*f,dropFront:m,dropRear:d}}var Nd={yawDeg:0,rollDeg:0},Gx=1e-4,KT=40,Kx=50;function an(e,t,r=0){let n=e.aero?.model;if(!(!n||!on(n,e).hasAttitude))return{yawDeg:r,rollDeg:we(e).rollGradient*t}}function Uo(e,t){if(e.rideHeightFront!=null&&e.rideHeightRear!=null)return{hFront:e.rideHeightFront,hRear:e.rideHeightRear};let r=e.model,n=(a,s,i)=>{if(t!==void 0&&t>0)return Wo(a,t,s,i);throw new Error("A ride-height-and-pitch aero model is read with the car\u2019s wheelbase, and none was given.")},o={hFront:0,hRear:0};if(r?.kind==="sensitivity")o=al(r)?n(r.frame,r.ref.h,r.ref.pitch):r.ref;else if(r){let{x:a,y:s}=zo(r),i=(a[0]+a[a.length-1])/2,c=(s[0]+s[s.length-1])/2;o=nn(r)?n(r.frame,i,c):{hFront:i,hRear:c}}return{hFront:e.rideHeightFront??o.hFront,hRear:e.rideHeightRear??o.hRear}}var Hx=new WeakMap;function Fr(e,t,r=0,n){let o=e.aero;if(!o?.model)return null;let a=Hx.get(e);a||(a=new Map,Hx.set(e,a));let s=n&&on(o.model,e).hasAttitude?n:Nd,i=s===Nd?`${t}|${r}`:`${t}|${r}|${s.yawDeg.toFixed(3)}|${s.rollDeg.toFixed(3)}`,c=a.get(i);if(c)return c;let l=HT(e,o,t,r,s);return a.size>4096&&a.clear(),a.set(i,l),l}function HT(e,t,r,n,o){let a=on(t.model,e),s=we(e),i=2*s.rideRateFront,c=2*s.rideRateRear,l=Uo(t,e.wheelbase),u=.5*t.rho*r*r,m=a.area,d=e.wheelbase>0?t.copHeight/e.wheelbase:0,p=ul(e,s),f=_d(e,n),h=(C,T)=>ml(e.cgHeight,p,l.hFront-C,l.hRear-T),b=(C,T)=>l.hFront-C-(l.hRear-T),g=(C,T)=>{let F=a.at(C,T,o.yawDeg,o.rollDeg),S=u*m*F.clFront,P=u*m*F.clRear,L=u*m*F.cd,D=L*d,I=h(C,T),O=f*I,_=jo(e,s,I)*b(C,T),z=S-O-D+_,E=P+O+D-_,N=C-l.hFront+(i>0?z/i:0),B=T-l.hRear+(c>0?E/c:0);return{c:F,downFront:S,downRear:P,drag:L,rF:N,rR:B,norm:Math.hypot(N,B)}},y=(C,T,F=!1)=>{let S=a.slopes(C,T,F,o.yawDeg,o.rollDeg),P=i>0?u*m/i:0,L=c>0?u*m/c:0;return[[P*(S.clFront.hFront-d*S.cd.hFront),P*(S.clFront.hRear-d*S.cd.hRear)],[L*(S.clRear.hFront+d*S.cd.hFront),L*(S.clRear.hRear+d*S.cd.hRear)]]},R=l.hFront,k=l.hRear,v=g(R,k),x=0;for(;v.norm>=Gx&&x<KT;){x++;let C=y(R,k),T=i>0?f/i:0,F=c>0?f/c:0,S=jo(e,s,h(R,k)),P=i>0?S/i:0,L=c>0?S/c:0,D=1+C[0][0]-T*p.front-P,I=C[0][1]-T*p.rear+P,O=C[1][0]+F*p.front+L,_=1+C[1][1]+F*p.rear-L,z=D*_-I*O,E,N;Math.abs(z)>1e-9?(E=-(_*v.rF-I*v.rR)/z,N=-(-O*v.rF+D*v.rR)/z):(E=-.5*v.rF,N=-.5*v.rR);let B=Math.max(1,Math.abs(E)/Kx,Math.abs(N)/Kx);E/=B,N/=B;let V=1;for(let G=0;G<6;G++){let K=g(R+V*E,k+V*N);if(K.norm<=v.norm||G===5){R+=V*E,k+=V*N,v=K;break}V*=.5}}let M=y(R,k,!0),A=2+M[0][0]+M[1][1],w=(1+M[0][0])*(1+M[1][1])-M[0][1]*M[1][0];return{v:r,axG:n,hFront:R,hRear:k,cgHeight:h(R,k),cgForward:e.wheelbase>0?h(R,k)*b(R,k)/e.wheelbase:0,cgNoseLoad:jo(e,s,h(R,k))*b(R,k),clFront:v.c.clFront,clRear:v.c.clRear,cd:v.c.cd,area:m,downforce:v.downFront+v.downRear,drag:v.drag,downFront:v.downFront,downRear:v.downRear,gain:zT(M),stable:w>0&&A>0,converged:v.norm<Gx,iterations:x,clampedRide:v.c.clampedRide,yawDeg:o.yawDeg,rollDeg:o.rollDeg,clampedAttitude:v.c.clampedAttitude}}function zT(e){let t=e[0][0]+e[1][1],r=e[0][0]*e[1][1]-e[0][1]*e[1][0],n=t*t-4*r;if(n>=0){let o=Math.sqrt(n);return Math.max(Math.abs((t+o)/2),Math.abs((t-o)/2))}return Math.sqrt(r)}function fs(e,t,r=0,n){let o=Fr(e,t,r,n);return o?{downforce:o.downforce,drag:o.drag,downFront:o.downFront,downRear:o.downRear}:e.aero?On(e.aero,t):{downforce:0,drag:0,downFront:0,downRear:0}}function YT(e,t,r,n){let o=On(t,r),a=we(e),s=Uo(t,e.wheelbase),i=e.wheelbase>0?o.drag*t.copHeight/e.wheelbase:0,c=ds(e,a,n,o.downFront-i,o.downRear+i),l=o.downforce;return{v:r,axG:n,hFront:s.hFront-c.dropFront,hRear:s.hRear-c.dropRear,cgHeight:c.height,cgForward:c.forward,cgNoseLoad:c.noseLoad,clFront:t.cl*t.copLongFront,clRear:t.cl*(1-t.copLongFront),cd:t.cw,area:t.area,downforce:l,drag:o.drag,downFront:o.downFront,downRear:o.downRear,gain:0,stable:!0,converged:!0,iterations:0,clampedRide:!1,yawDeg:0,rollDeg:0,clampedAttitude:!1}}function Od(e,t,r=0,n){let o=Fr(e,t,r,n);return o||(e.aero?YT(e,e.aero,t,r):null)}function pl(e,t=0,r=0,n,o){if(e.aero&&t>0){if(e.aero.model){let i=Fr(e,t,r,n);return{height:i.cgHeight,forward:i.cgForward,noseLoad:i.cgNoseLoad}}let a=On(e.aero,t),s=e.wheelbase>0?a.drag*e.aero.copHeight/e.wheelbase:0;return ds(e,o??we(e),r,a.downFront-s,a.downRear+s)}return r===0?{height:e.cgHeight,forward:0,noseLoad:0}:ds(e,o??we(e),r,0,0)}var zx=[0,1,0],Vd=[0,0,1],ee=(e,t)=>[e[0]+t[0],e[1]+t[1],e[2]+t[2]],H=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],U=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],Bd=e=>[-e[0],-e[1],-e[2]],X=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],ae=(e,t)=>[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]],WT=e=>X(e,e),sn=e=>Math.sqrt(X(e,e)),hs=(e,t)=>WT(H(e,t)),ve=(e,t)=>sn(H(e,t)),q=e=>{let t=sn(e);return t<1e-12?[0,0,0]:[e[0]/t,e[1]/t,e[2]/t]};var cn=(e,t,r)=>{let n=q(r),o=H(e,t);return ee(t,U(n,X(o,n)))},Yx=(e,t,r)=>ve(e,cn(e,t,r));var UT=1e-6;function XT(e){if(e<UT){let n=e*e;return[1-n/6,.5-n/24]}let t=Math.sin(e),r=Math.cos(e);return[t/e,(1-r)/(e*e)]}function at(e,t){let r=Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]);if(r<1e-14)return t;let[n,o]=XT(r),a=ae(e,t),s=ae(e,a);return ee(t,ee(U(a,n),U(s,o)))}function Ot(e,t,r){let n=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);if(n<1e-14)return e;let o=[t[0]/n,t[1]/n,t[2]/n];return at(U(o,r),e)}function or(e,t){let r=t.length,n=e.map(a=>a.slice()),o=t.slice();return jx(n,o,r,new Array(r).fill(0))}function Wx(e,t,r){return jx(e,t,t.length,r)}function jx(e,t,r,n){let o=1/0,a=0;for(let s=0;s<r;s++){let i=s,c=Math.abs(e[s][s]);for(let u=s+1;u<r;u++){let m=Math.abs(e[u][s]);m>c&&(c=m,i=u)}if(c<1e-14){for(let u=0;u<r;u++)n[u]=NaN;return{x:n,condProxy:1/0,singular:!0}}if(o=Math.min(o,c),a=Math.max(a,c),i!==s){let u=e[s];e[s]=e[i],e[i]=u;let m=t[s];t[s]=t[i],t[i]=m}let l=e[s][s];for(let u=s+1;u<r;u++){let m=e[u][s]/l;if(m!==0){for(let d=s;d<r;d++)e[u][d]-=m*e[s][d];t[u]-=m*t[s]}}}for(let s=r-1;s>=0;s--){let i=t[s];for(let c=s+1;c<r;c++)i-=e[s][c]*n[c];n[s]=i/e[s][s]}return{x:n,condProxy:a/o,singular:!1}}var Ux=e=>{let t=0;for(let r of e)t=Math.max(t,Math.abs(r));return t},Xx=e=>{let t=0;for(let r of e)t+=r*r;return t},qT=Math.sqrt(Number.EPSILON);function qx(e,t,r={}){let n=r.maxIter??60,o=r.tol??1e-10,a=t.length,s=r.scales??new Array(a).fill(1),i=t.slice(),c=e(i),l=Ux(c),u=Xx(c),m=.001,d=1,p=c.length,f=Array.from({length:p},()=>new Array(a).fill(0)),h=Array.from({length:a},()=>new Array(a).fill(0)),b=Array.from({length:a},()=>new Array(a).fill(0)),g=new Array(a).fill(0),y=new Array(a).fill(0),R=new Array(a).fill(0),k=new Array(a).fill(0),v=new Array(a).fill(0);for(let x=0;x<n;x++){if(l<o)return{x:i,residualNorm:l,iterations:x,converged:!0,condProxy:d};for(let C=0;C<a;C++){let T=qT*Math.max(Math.abs(i[C]),s[C]);for(let S=0;S<a;S++)k[S]=i[S];k[C]+=T;let F=e(k);for(let S=0;S<p;S++)f[S][C]=(F[S]-c[S])/T}let M=0;for(let C=0;C<a;C++){for(let F=0;F<a;F++){let S=0;for(let P=0;P<p;P++)S+=f[P][C]*f[P][F];h[C][F]=S}let T=0;for(let F=0;F<p;F++)T+=f[F][C]*c[F];g[C]=T,M=Math.max(M,h[C][C])}let A=Math.max(M,1e-9),w=!1;for(let C=0;C<18;C++){let T=m*A;for(let S=0;S<a;S++){let P=h[S],L=b[S];for(let D=0;D<a;D++)L[D]=S===D?P[D]+T:P[D];y[S]=-g[S]}let F=Wx(b,y,R);if(d=Math.max(d,F.condProxy),!F.singular){for(let L=0;L<a;L++)v[L]=i[L]+R[L];let S=e(v),P=Xx(S);if(P<u){for(let L=0;L<a;L++)i[L]=v[L];c=S,u=P,l=Ux(c),m=Math.max(m*.3,1e-12),w=!0;break}}m=Math.min(m*4,1e12)}if(!w)break}return{x:i,residualNorm:l,iterations:n,converged:l<o,condProxy:d}}function bs(e,t,r,n){let o=e*e+t*t,a=Math.sqrt(o);if(!(a>1e-12*n))return{c1:1,s1:0,c2:1,s2:0,margin:0,ok:!1,free:!0};let s=Math.abs(r),i=1-s/a;if(i<0){let l=r>=0?1:-1,u=l*e/a,m=l*t/a;return{c1:u,s1:m,c2:u,s2:m,margin:i,ok:i>=-1e-12,free:!1}}let c=Math.sqrt((a-s)*(a+s));return{c1:(e*r-t*c)/o,s1:(t*r+e*c)/o,c2:(e*r+t*c)/o,s2:(t*r-e*c)/o,margin:i,ok:!0,free:!1}}function $d(e,t){return[e[0]*t[0]-e[1]*t[1]-e[2]*t[2]-e[3]*t[3],e[0]*t[1]+e[1]*t[0]+e[2]*t[3]-e[3]*t[2],e[0]*t[2]-e[1]*t[3]+e[2]*t[0]+e[3]*t[1],e[0]*t[3]+e[1]*t[2]-e[2]*t[1]+e[3]*t[0]]}var Qx=e=>[e[0],-e[1],-e[2],-e[3]];function Zx(e,t){let[r,n,o,a]=e,s=2*(o*t[2]-a*t[1]),i=2*(a*t[0]-n*t[2]),c=2*(n*t[1]-o*t[0]);return[t[0]+r*s+(o*c-a*i),t[1]+r*i+(a*s-n*c),t[2]+r*c+(n*i-o*s)]}function Jx(e,t){let r=e[0]*t[0]+e[1]*t[1]+e[2]*t[2];if(1+r<1e-14){let o=Math.abs(e[0])<.6?[1,0,0]:[0,1,0],a=e[1]*o[2]-e[2]*o[1],s=e[2]*o[0]-e[0]*o[2],i=e[0]*o[1]-e[1]*o[0],c=Math.hypot(a,s,i);return[0,a/c,s/c,i/c]}let n=Math.sqrt(2*(1+r));return[(1+r)/n,(e[1]*t[2]-e[2]*t[1])/n,(e[2]*t[0]-e[0]*t[2])/n,(e[0]*t[1]-e[1]*t[0])/n]}function eR(e,t,r){let n,o;return t>=0?(n=Math.sqrt((1+t)/2),o=r/(2*n)):(o=(r>=0?1:-1)*Math.sqrt((1-t)/2),n=r/(2*o)),[n,o*e[0],o*e[1],o*e[2]]}function Gd(e,t,r){let n=e[0],o=e[1],a=e[2],s=t[0],i=t[1],c=t[2],l=r[0],u=r[1],m=r[2],d=n+i+m;if(d>=n&&d>=i&&d>=m){let h=Math.sqrt(1+d),b=.5/h;return[.5*h,(c-u)*b,(l-a)*b,(o-s)*b]}if(n>=i&&n>=m){let h=Math.sqrt(1+n-i-m),b=.5/h;return[(c-u)*b,.5*h,(s+o)*b,(l+a)*b]}if(i>=m){let h=Math.sqrt(1-n+i-m),b=.5/h;return[(l-a)*b,(s+o)*b,.5*h,(u+c)*b]}let p=Math.sqrt(1-n-i+m),f=.5/p;return[(o-s)*f,(l+a)*f,(u+c)*f,.5*p]}function tR(e){let t=Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]);if(t===0)return[1,0,0,0];let r=Math.sin(t/2)/t;return[Math.cos(t/2),r*e[0],r*e[1],r*e[2]]}function rR(e){let[t,r,n,o]=e;t<0&&(t=-t,r=-r,n=-n,o=-o);let a=Math.sqrt(r*r+n*n+o*o);if(a===0)return[0,0,0];let s=2*Math.atan2(a,t)/a;return[s*r,s*n,s*o]}function QT(e){let t=Math.abs(e[0])<.6?[1,0,0]:[0,1,0],r=q(ae(e,t));return[r,ae(e,r)]}function ZT(e){let t=e.hardpoints,r=q(H(t.damperChassis,t.pushrodOuter)),[n,o]=QT(r);return{top:t.damperChassis,lower0:t.pushrodOuter,axis0:r,e1:n,e2:o}}function Kd(e){let t=e.hardpoints,r=t.wheelCenter,n=q(H(t.ucaRear,t.ucaFront)),o=H(t.uprightUpper,t.ucaFront),a=X(o,n),s=H(o,U(n,a)),i=X(s,s),c=q(H(t.lcaRear,t.lcaFront)),l=H(t.uprightLower,t.lcaFront),u=hs(t.tieOuter,t.tieInner);return{c0:r,ucaFront:t.ucaFront,ucaDir:n,ubj0:t.uprightUpper,ubjAxial0:a,ubjRadius2:i,lcaFront:t.lcaFront,lcaDir:c,lbj0:t.uprightLower,lbjRel0:l,tro0:t.tieOuter,tieInner0:t.tieInner,tieLen2:u,rackAxis:q(e.config.rackAxis),steerMovesRack:e.config.steerMode==="rack",ubjRadiusRef:Math.max(1,2*Math.sqrt(i)),tieLenRef:Math.max(1,2*Math.sqrt(u)),...e.config.layout==="mcpherson"?{strut:ZT(e)}:{}}}function Vt(e,t,r){let n=[t[3],t[4],t[5]],o=[t[0],t[1],t[2]],a=H(r,e.c0);return ee(ee(at(n,a),e.c0),o)}function Hd(e,t){return ee(e.lcaFront,Ot(e.lbjRel0,e.lcaDir,t))}function Vn(e,t){return e.steerMovesRack?ee(e.tieInner0,U(e.rackAxis,t)):e.tieInner0}function zd(e,t,r,n){let o=Vt(e,t,e.lbj0),a=Hd(e,r),s=o[0]-a[0],i=o[1]-a[1],c=o[2]-a[2],l,u;if(e.strut){let f=e.strut,h=[t[3],t[4],t[5]],b=H(f.top,Vt(e,t,f.lower0));l=X(b,at(h,f.e1)),u=X(b,at(h,f.e2))}else{let f=Vt(e,t,e.ubj0),h=H(f,e.ucaFront),b=X(h,e.ucaDir),g=H(h,U(e.ucaDir,b));l=b-e.ubjAxial0,u=(X(g,g)-e.ubjRadius2)/e.ubjRadiusRef}let m=Vt(e,t,e.tro0),d=Vn(e,n),p=(hs(m,d)-e.tieLen2)/e.tieLenRef;return[s,i,c,l,u,p]}var gs=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]),dl=e=>{let t=gs(e);return[e[0]/t,e[1]/t,e[2]/t]},JT=(e,t)=>H(e,U(t,X(e,t))),Yd=e=>dl(ae(e,Math.abs(e[0])<.6?[1,0,0]:[0,1,0]));function eP(e,t){let r=e.ucaDir,n=ee(e.ucaFront,U(r,e.ubjAxial0)),o=Math.sqrt(e.ubjRadius2),a=JT(H(e.ubj0,e.ucaFront),r),s=gs(a)>1e-9?dl(a):Yd(r),i=ae(r,s),c=H(e.ubj0,e.lbj0),l=X(c,c);if(!(l>1e-18))return"free";let u=H(n,t),m=X(u,u),d=bs(2*o*X(s,u),2*o*X(i,u),l-m-o*o,2*o*Math.sqrt(m));if(d.free)return"free";let p=dl(c),f=(h,b)=>{let g=ee(n,ee(U(s,o*h),U(i,o*b))),y=dl(H(g,t));return{q1:Jx(p,y),k:y,margin:d.margin,ok:d.ok}};return d.margin>0?[f(d.c1,d.s1),f(d.c2,d.s2)]:[f(d.c1,d.s1)]}function tP(e,t,r){let n=t.axis0,o=ee(t.lower0,U(n,X(H(e.lbj0,t.lower0),n))),a=H(o,e.lbj0),s=gs(a),i=s>1e-9?U(a,1/s):Yd(n),c=H(t.top,r),l=gs(c);if(!(l>1e-9))return"free";let u=U(c,1/l),m=s/l,d=1-m,p=d>=0?Math.sqrt((1-m)*(1+m)):0,f=Yd(u),h=b=>{let g=b*p,y=ee(U(u,g),U(f,Math.min(m,1))),R=H(U(u,Math.min(m,1)),U(f,g));return{q1:$d(Gd(R,y,ae(R,y)),Qx(Gd(i,n,ae(i,n)))),k:u,margin:d,ok:d>=0}};return d>0?[h(1),h(-1)]:[h(1)]}function rP(e,t,r,n){let{k:o}=n,a=Zx(n.q1,H(e.tro0,e.lbj0)),s=X(a,o),i=H(a,U(o,s)),c=gs(i);if(!(c>1e-9))return"free";let l=U(i,1/c),u=ae(o,l),m=ee(t,U(o,s)),d=H(m,r),p=X(d,d),f=bs(2*c*X(d,l),2*c*X(d,u),e.tieLen2-p-c*c,2*c*Math.sqrt(p));if(f.free)return"free";let h=(g,y)=>({q:$d(eR(o,g,y),n.q1)});return{roots:f.margin>0?[h(f.c1,f.s1),h(f.c2,f.s2)]:[h(f.c1,f.s1)],margin:f.margin,ok:f.ok}}function nR(e,t,r,n=[0,0,0,0,0,0]){let o=Hd(e,t),a=Vn(e,r),s=tR([n[3],n[4],n[5]]),i=h=>Math.abs(h[0]*s[0]+h[1]*s[1]+h[2]*s[2]+h[3]*s[3]),c=e.strut?tP(e,e.strut,o):eP(e,o);if(c==="free")return{x:n.slice(),converged:!1,margin:0,free:!0};let l=null,u=null;for(let h of c){let b=rP(e,o,a,h);if(b==="free")return{x:n.slice(),converged:!1,margin:0,free:!0};let g=Math.min(h.margin,b.margin),y=b.ok&&h.ok;for(let{q:R}of b.roots){let k=i(R);y&&(!l||k>l.near)&&(l={q:R,margin:g,near:k}),!y&&(!u||k>u.near)&&(u={q:R,margin:g,near:k})}}let{q:m,margin:d}=l??u,p=rR(m),f=H(H(o,e.c0),at(p,H(e.lbj0,e.c0)));return{x:[f[0],f[1],f[2],p[0],p[1],p[2]],converged:l!==null,margin:d,free:!1}}function aR(e){let t=q(H(e.rockerPivotB,e.rockerPivotA));return{pivotA:e.rockerPivotA,axis:t,rprRel0:H(e.rockerToPushrod,e.rockerPivotA),rdmRel0:H(e.rockerToDamper,e.rockerPivotA),damperChassis:e.damperChassis,rodLen2:hs(e.pushrodOuter,e.rockerToPushrod),damperLen0:ve(e.rockerToDamper,e.damperChassis)}}var nP=(e,t)=>ee(e.pivotA,Ot(e.rprRel0,e.axis,t)),Wd=(e,t)=>ee(e.pivotA,Ot(e.rdmRel0,e.axis,t));function Xo(e,t){return{pushrod:nP(e,t),damper:Wd(e,t)}}function sR(e,t,r=0){let n=X(e.rprRel0,e.axis),o=H(e.rprRel0,U(e.axis,n)),a=ae(e.axis,o),s=H(ee(e.pivotA,U(e.axis,n)),t),i=X(o,o),c=X(s,s),l=bs(2*X(s,o),2*X(s,a),e.rodLen2-c-i,2*Math.sqrt(i*c));if(l.free){let p=Math.abs(e.rodLen2-c-i)<=1e-9*e.rodLen2;return{phi:r,damperLength:ve(Wd(e,r),e.damperChassis),converged:p,margin:0}}let u=oR(Math.atan2(l.s1,l.c1),r),m=oR(Math.atan2(l.s2,l.c2),r),d=Math.abs(m-r)<Math.abs(u-r)?m:u;return{phi:d,damperLength:ve(Wd(e,d),e.damperChassis),converged:l.ok,margin:l.margin}}function oR(e,t){let r=2*Math.PI;return e+r*Math.round((t-e)/r)}function iR(e,t,r,n){return ee(t,at(U(q(r),n),H(e,t)))}function cR(e,t,r,n){let o=q(n),a=d=>{let p=H(d,r);return H(p,U(o,X(p,o)))},s=a(e),i=a(t),c=Math.hypot(s[0],s[1],s[2]),l=Math.hypot(i[0],i[1],i[2]);if(c<1e-9||l<1e-9)return 0;let u=Math.min(1,Math.max(-1,X(s,i)/(c*l))),m=X(ae(s,i),o)/(c*l);return Math.atan2(m,u)}function lR(e,t,r,n){return ee(t,at(U(q(r),n),H(e,t)))}var fl=180/Math.PI,oP=(e,t,r)=>Math.max(t,Math.min(r,e)),uR=[NaN,NaN,NaN];function ys(e){let t=q(e.spinAxis),r=q(H(e.uprightUpper,e.uprightLower)),n=-Math.asin(oP(t[2],-1,1))*fl,o=Math.atan2(t[0],t[1])*fl,a=Math.atan2(-r[0],r[2])*fl,s=Math.atan2(-r[1],r[2])*fl,i=q(ee([0,0,-1],U(t,t[2]))),c=ee(e.wheelCenter,U(i,e.loadedRadius)),l=e.patchShift?[c[0]+e.patchShift.x,c[1]+e.patchShift.y,c[2]]:c,u=e.uprightLower,m=Math.abs(r[2])>1e-9,d=w=>ee(u,U(r,(w-u[2])/r[2])),p=m?d(l[2]):uR,f=m?d(e.wheelCenter[2]):uR,h=l[1]-p[1],b=p[0]-l[0],g=q(ae(t,[0,0,1])),y=ae([0,0,1],g),R=H(l,p),k=X(R,y),v=-X(R,g),x=e.wheelCenter[1]-f[1],M=f[0]-e.wheelCenter[0],A=Yx(e.tieOuter,u,r);return{camber:n,toe:o,caster:a,kpi:s,scrubRadius:h,mechanicalTrail:b,scrubAtWheel:k,trailAtWheel:v,kingpinOffset:x,casterOffset:M,steeringArm:A,contactPatch:l,kingpinGround:p,kingpinAtHub:f}}function tt(e){return{corner:e,inv:Kd(e),rocker:aR(e.hardpoints)}}var aP=[20,20,20,.2,.2,.2];function pR(e,t,r,n=[0,0,0,0,0,0]){let o=nR(e,t,r,n);if(!o.free)return o;let a=sP(e,t,r,n);return{x:a.x,converged:a.converged,margin:0}}function sP(e,t,r,n=[0,0,0,0,0,0]){return qx(o=>zd(e,o,t,r),n,{scales:aP,tol:1e-10,maxIter:40})}var iP=.01,hl=1.2,mt=e=>e.ok?e.state:null,st=e=>e.ok?e.state:e.nearest;function ge(e,t,r,n,o){let a=0,s=Ie(e,a,r,n,o);if(Math.abs(s.travel-t)<1e-4)return mR(s,t,!1);let c=(Ie(e,.02,r,jd(s),o).travel-s.travel)/.02;(!Number.isFinite(c)||Math.abs(c)<1e-6)&&(c=1);let l=d=>Math.max(-hl,Math.min(hl,d)),u=l((t-s.travel)/c),m=Ie(e,u,r,jd(s),o);for(let d=0;d<12&&!(Math.abs(m.travel-t)<1e-4);d++){let p=m.travel-s.travel,f=Math.abs(p)<1e-9?u:u-(m.travel-t)*((u-a)/p);a=u,s=m,u=l(f),m=Ie(e,u,r,jd(s),o)}return mR(m,t,Math.abs(u)===hl)}function mR(e,t,r){let n=e.travel-t,o=Math.abs(n)<=iP,a=r&&!o;return e.converged&&o?{ok:!0,reached:!0,travelMiss:n,clamped:!1,state:e}:{ok:!1,why:e.converged?"unreached":"unconverged",reached:o,travelMiss:n,clamped:a,nearest:e}}function jd(e){return{q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle}}function cP(e,t,r,n,o){switch(e){case"upright":return Vt(t,r,o.pushrodOuter);case"upperArm":{let a=Vt(t,r,t.ubj0),s=cR(t.ubj0,a,t.ucaFront,t.ucaDir);return lR(o.pushrodOuter,t.ucaFront,t.ucaDir,s)}default:return iR(o.pushrodOuter,t.lcaFront,t.lcaDir,n)}}function Ie(e,t,r,n,o){let{inv:a,corner:s}=e,i=n?.q??[0,0,0,0,0,0],c=pR(a,t,r,i),l=c.x,u=[l[3],l[4],l[5]],m={t:[l[0],l[1],l[2]],omega:u},d=s.hardpoints,p=s.config,f=a.strut,h=f?f.top:Vt(a,l,d.uprightUpper),b=Vt(a,l,d.uprightLower),g=Vt(a,l,d.tieOuter),y=Vt(a,l,d.wheelCenter),R=q(at(u,p.spinAxis)),k=cP(f?"upright":p.pushrodAttach,a,l,t,d),v=f?f.top:d.damperChassis,x=f||p.actuation==="direct"?{phi:0,damperLength:ve(k,v),converged:!0,margin:1}:sR(e.rocker,k,n?.phi??0),M=ys({uprightUpper:h,uprightLower:b,wheelCenter:y,spinAxis:R,tieOuter:g,loadedRadius:o?.loadedRadius??p.loadedRadius,patchShift:o?.patchShift});return{pose:m,beta:t,travel:l[2],steer:r,points:{uprightUpper:h,uprightLower:b,tieOuter:g,wheelCenter:y,pushrodOuter:k,spinAxis:R,contactPatch:M.contactPatch,kingpinGround:M.kingpinGround,kingpinAtHub:M.kingpinAtHub,rockerAngle:x.phi,damperLength:x.damperLength},metrics:{camber:M.camber,toe:M.toe,caster:M.caster,kpi:M.kpi,scrubRadius:M.scrubRadius,mechanicalTrail:M.mechanicalTrail,scrubAtWheel:M.scrubAtWheel,trailAtWheel:M.trailAtWheel,kingpinOffset:M.kingpinOffset,casterOffset:M.casterOffset,steeringArm:M.steeringArm,damperLength:x.damperLength},converged:c.converged&&x.converged,margin:Math.min(c.margin,x.margin)}}var qo=e=>e==="FL"||e==="FR"?"front":"rear",fR=e=>e==="FL"||e==="RL"?"left":"right";function _e(e,t){return e.corners?.[t]??lP(e[qo(t)],fR(t))}function hR(e){let t=e.config.springSplit;return e.config.actuation==="decoupled"||t===void 0||!Number.isFinite(t)||Math.abs(t)>=1?0:t}var dR=new WeakMap;function lP(e,t){let r=hR(e);if(r===0)return e;let n=dR.get(e);if(!n){let o=a=>{let{springSplit:s,...i}=e.config;return{...e,config:{...i,springRate:e.config.springRate*a},...e.measured?{measured:{...e.measured,springRate:e.measured.springRate*a}}:{}}};n={left:o(1-r),right:o(1+r)},dR.set(e,n)}return n[t]}var ar=["FL","FR","RL","RR"],gt=e=>2*e.hardpoints.wheelCenter[1],Bt=(e,t)=>t?gt(_e(e,"FL"))/2+gt(_e(e,"FR"))/2:gt(_e(e,"RL"))/2+gt(_e(e,"RR"))/2;function Qe(e,t){let r=e==="FL"||e==="FR";return{axleX:r?t.frontAxleX:t.frontAxleX-t.wheelbase,sideSign:e==="FR"||e==="RR"?1:-1,isFront:r}}function wt(e,t){return[t.axleX+e[0],t.sideSign*e[1],e[2]]}function wr(e,t){return[e[0],t.sideSign*e[1],e[2]]}function ln(e){return e.frontAxleX-e.wheelbase/2}function Ud(e,t,r){return t[2]+e.heave+(t[0]-r)*Math.sin(e.pitch)-t[1]*Math.sin(e.roll)}function un(e,t,r,n){let o=Qe(e,t),a=(n?Bt(n,o.isFront):o.isFront?t.trackFront:t.trackRear)/2,s=o.sideSign*a,i=o.axleX-ln(t),c=-r.heave-i*Math.sin(r.pitch)+s*Math.sin(r.roll),l=o.isFront?o.sideSign*r.steer:0;return{travel:c,steer:l}}var uP={travelMin:-40,travelMax:40,steps:41,steer:0};function xs(e){return{q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle}}function Ke(e,t={}){let r={...uP,...t},n=tt(e);return Qo(n,r)}function Qo(e,t){let r=t.steer,n=.01,o=Ie(e,n,r),a=Ie(e,-n,r),s=(o.travel-a.travel)/(2*n);(!Number.isFinite(s)||Math.abs(s)<1e-6)&&(s=1);let i=Math.max(Math.abs(t.travelMax),Math.abs(t.travelMin)),c=Math.min(1.2,1.5*i/Math.abs(s)),l=Math.max(20,t.steps*2),u=[],m=Ie(e,0,r);u.push({beta:0,travel:m.travel,warm:xs(m),converged:m.converged});let d=xs(m);for(let R=1;R<=l;R++){let k=c*R/l,v=Ie(e,k,r,d);d=xs(v),u.push({beta:k,travel:v.travel,warm:d,converged:v.converged})}d=xs(m);for(let R=1;R<=l;R++){let k=-c*R/l,v=Ie(e,k,r,d);d=xs(v),u.push({beta:k,travel:v.travel,warm:d,converged:v.converged})}u.sort((R,k)=>R.beta-k.beta);let p=u[u.length-1].travel>=u[0].travel,f=!1;for(let R=1;R<u.length;R++){let k=u[R].travel-u[R-1].travel;(p&&k<-1e-6||!p&&k>1e-6)&&(f=!0)}let h=u.filter(R=>R.converged).map(R=>R.travel),b=h.length?[Math.min(...h),Math.max(...h)]:[0,0],g=h.length>0&&b[0]<=t.travelMin+1e-6&&b[1]>=t.travelMax-1e-6,y=[];for(let R=0;R<t.steps;R++){let k=t.steps===1?t.travelMin:t.travelMin+(t.travelMax-t.travelMin)*R/(t.steps-1),v=mP(u,k,p),x=pP(u,v);y.push(Ie(e,v,r,x))}return dP(y,e.corner.config.actuation==="decoupled"?0:e.corner.config.springRate),{samples:y,covered:g,reach:b,fold:f,unconverged:y.filter(R=>!R.converged).length}}function mP(e,t,r){let n=r?e.slice():e.slice().reverse();if(t<=n[0].travel)return n[0].beta;if(t>=n[n.length-1].travel)return n[n.length-1].beta;for(let o=1;o<n.length;o++){let a=n[o-1],s=n[o];if(t>=Math.min(a.travel,s.travel)&&t<=Math.max(a.travel,s.travel)){let i=s.travel-a.travel,c=Math.abs(i)<1e-9?0:(t-a.travel)/i;return a.beta+c*(s.beta-a.beta)}}return n[n.length-1].beta}function pP(e,t){let r=e[0],n=1/0;for(let o of e){let a=Math.abs(o.beta-t);a<n&&(n=a,r=o)}return r.warm}function Xd(e,t,r){return r===0?(e[1]-e[0])/(t[1]-t[0]):r===e.length-1?(e[r]-e[r-1])/(t[r]-t[r-1]):(e[r+1]-e[r-1])/(t[r+1]-t[r-1])}function dP(e,t){if(e.length<2)return;let r=e.map(s=>s.travel),n=e.map(s=>s.metrics.camber),o=e.map(s=>s.metrics.toe),a=e.map(s=>s.metrics.damperLength);for(let s=0;s<e.length;s++){let i=Xd(n,r,s),c=Xd(o,r,s),l=-Xd(a,r,s);e[s].metrics.camberGain=i,e[s].metrics.bumpSteer=c,e[s].metrics.motionRatio=l,e[s].metrics.wheelRate=t*l*l}}var bl=e=>e!==void 0&&Number.isFinite(e)&&e>0;function fP(e){return e&&bl(e.helperRate)&&bl(e.helperTravel)?{rate:e.helperRate,travel:e.helperTravel}:null}function qd(e,t,r){let n=t/e;return r?n+Math.min(t/r.rate,r.travel):n}function Rs(e,t,r,n){if(!(e>0)||!Number.isFinite(e)||!(t>0)||!Number.isFinite(t))return null;let o=fP(n),a=-qd(e,t,o),s=Zo(r,n);return{rate:e,preload:t,helper:o,free:a,pull:null,droop:s.droop??a,droopStated:s.droop!==null,bump:s.bump,holdsLoad:!0}}function Zo(e,t){if(!Number.isFinite(e))return{droop:null,bump:null};let r=bl(t?.extended)&&t.extended>e?t.extended:null,n=r!==null&&bl(t?.stroke)?r-t.stroke:null;return{droop:r!==null?e-r:null,bump:n!==null&&n<e?e-n:null}}function Qd(e,t){if(!(e>0)||!Number.isFinite(e))return null;let r=Zo(t.length0,t.coilover),n=t.free===-1/0||t.pull!==null&&t.pull>=t.free;if(n&&r.droop===null&&r.bump===null)return null;let o=n?-1/0:t.free;return{rate:e,preload:o===-1/0?0:-e*o,helper:null,free:o,pull:n?null:t.pull,droop:r.droop??-1/0,droopStated:r.droop!==null,bump:r.bump,holdsLoad:!1}}function hP(e,t){let{rate:r,preload:n,helper:o}=e;if(!o)return t>e.free-1e-9?n+r*t:e.pull!==null&&t<e.pull+1e-9?r*(t-e.pull):0;let a=qd(r,n,o)+t;if(a<=0)return 0;let s=o.rate*o.travel;return a>=s/r+o.travel?n>=s?n+r*t:r*(a-o.travel):a*r*o.rate/(r+o.rate)}function bP(e,t){let{rate:r,preload:n,helper:o}=e;if(!o)return t>e.free-1e-9||e.pull!==null&&t<e.pull+1e-9?r:0;let a=qd(r,n,o)+t;return a<=0?0:a>=o.rate*o.travel/r+o.travel?r:r*o.rate/(r+o.rate)}function Jo(e,t){let r=hP(e,t),n=e.free;return e.holdsLoad&&t<n&&e.droop<n&&(r+=.001*e.rate*(Math.max(t,e.droop)-n)),t<e.droop&&(r+=1e3*e.rate*(t-e.droop)),e.bump!==null&&t>e.bump&&(r+=1e3*e.rate*(t-e.bump)),r}function Zd(e,t){let r=bP(e,t),n=e.free;return e.holdsLoad&&t<n&&t>e.droop&&(r+=.001*e.rate),t<e.droop&&(r+=1e3*e.rate),e.bump!==null&&t>e.bump&&(r+=1e3*e.rate),r}function Jd(e){let t=e.free,r=[t,e.droop];return e.helper&&r.push(e.helper.rate*e.helper.travel/e.rate+e.helper.travel+t),e.bump!==null&&r.push(e.bump),e.pull!==null&&r.push(e.pull),[...new Set(r.filter(Number.isFinite))].sort((n,o)=>n-o)}var gl={min:-60,max:60,steps:61},ef=e=>({travel:[e.min,e.max],force:[0,0],motionRatio:[0,0],spring:null}),bR=new WeakMap;function gP(e,t){let r=bR.get(e.corner);r||bR.set(e.corner,r=new Map);let n=`${t.min}|${t.max}|${t.steps}`,o=r.get(n);return o||r.set(n,o=Qo(e,{travelMin:t.min,travelMax:t.max,steps:t.steps,steer:0})),o}function ks(e,t,r=gl,n=e.corner.config.coilover){let o=e.corner.config;if(o.actuation==="decoupled")return ef(r);let a=gP(e,r),s=xP(e,o.springRate,a.samples),i=[];for(let h of a.samples){let b=h.metrics.motionRatio;!h.converged||b===void 0||!Number.isFinite(b)||!Number.isFinite(h.metrics.damperLength)||i.length>0&&h.travel<=i[i.length-1].t+1e-6||i.push({t:h.travel,L:h.metrics.damperLength,mr:b})}if(i.length<2)return ef(r);let c=vP(i,0);if(!(Math.abs(c.mr)>1e-6))return ef(r);let l=t/c.mr,u=Rs(s,l,c.L,n),m=u?yP(i,Jd(u).map(h=>c.L-h)):i,d=m.map(h=>(u?Jo(u,c.L-h.L):l+s*(c.L-h.L))*h.mr-t),p=h=>h===null?null:m.find(b=>b.L===c.L-h)?.t??null,f=u?Jd(u).map(p).filter(h=>h!==null):[];return{travel:m.map(h=>h.t),force:d,motionRatio:m.map(h=>h.mr),spring:{rate:s,preload:l,length0:c.L,law:u},...u?{stops:{droop:p(u.droop),bump:p(u.bump)}}:{},...f.length?{kinks:f}:{},length:m.map(h=>h.L)}}function tf(e,t){if(!e.spring)return null;let r=e.travel.length,n=e.length;if(n&&n.length===r&&r>=2){let s=sr(e.travel,t),i=(t-e.travel[s])/(e.travel[s+1]-e.travel[s]);return e.spring.length0-(n[s]+i*(n[s+1]-n[s]))}if(r<2)return 0;let o=64,a=0;for(let s=0;s<o;s++){let i=t*s/o,c=t*(s+1)/o;a+=(vs(e,i)+vs(e,c))/2*(c-i)}return a}function yP(e,t){let r=[...e];for(let n of t)for(let o=0;o+1<e.length;o++){let a=e[o],s=e[o+1];if(a.L===n)break;if((a.L-n)*(s.L-n)>=0)continue;let i=(n-a.L)/(s.L-a.L);r.push({t:a.t+i*(s.t-a.t),L:n,mr:a.mr+i*(s.mr-a.mr)});break}return r.sort((n,o)=>n.t-o.t),r.filter((n,o)=>o===0||n.t>r[o-1].t+1e-6)}function xP(e,t,r){let n=e.corner.compliance?.links?.pushRod;if(n===void 0||!(n>0)||!Number.isFinite(n)||!(t>0))return t;let o=e.corner.config.actuation==="direct"?n:RP(e,n,r);return!(o>0)||!Number.isFinite(o)?t:t*o/(t+o)}function RP(e,t,r){let n;for(let m of r)m.converged&&(!n||Math.abs(m.travel)<Math.abs(n.travel))&&(n=m);if(!n)return t;let o=e.corner.hardpoints,a=Xo(e.rocker,n.points.rockerAngle),s=q(H(o.rockerPivotB,o.rockerPivotA)),i=(m,d)=>Math.abs(X(s,ae(H(m,o.rockerPivotA),q(H(d,m))))),c=i(a.pushrod,n.points.pushrodOuter),l=i(a.damper,o.damperChassis);if(!(l>1e-9)||!(c>1e-9))return t;let u=c/l;return t*u*u}function vs(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.motionRatio[0];let n=sr(e.travel,t),o=(t-e.travel[n])/(e.travel[n+1]-e.travel[n]);return e.motionRatio[n]+o*(e.motionRatio[n+1]-e.motionRatio[n])}function Cr(e,t,r){if(!e.spring)return Ut(e,t);let{rate:n,preload:o,length0:a,law:s}=e.spring,i=vs(e,0),c=a-r;return(s?Jo(s,c):o+n*c)*vs(e,t)-o*i}function vP(e,t){let r=sr(e.map(s=>s.t),t),n=e[r],o=e[r+1],a=(t-n.t)/(o.t-n.t);return{L:n.L+a*(o.L-n.L),mr:n.mr+a*(o.mr-n.mr)}}function sr(e,t){let r=e.length;if(t<=e[0])return 0;if(t>=e[r-1])return r-2;let n=0,o=r-1;for(;o-n>1;){let a=n+o>>1;e[a]<=t?n=a:o=a}return n}function Ut(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.force[0];let n=sr(e.travel,t),o=(t-e.travel[n])/(e.travel[n+1]-e.travel[n]);return e.force[n]+o*(e.force[n+1]-e.force[n])}function ea(e,t){let r=e.travel.length;if(r<3)return Ms(e,t);let n=sr(e.travel,t),o=(e.force[n+1]-e.force[n])/(e.travel[n+1]-e.travel[n]),a=i=>i===0||i===r-1||e.kinks?.includes(e.travel[i])?o:(e.force[i+1]-e.force[i-1])/(e.travel[i+1]-e.travel[i-1]),s=Math.max(0,Math.min(1,(t-e.travel[n])/(e.travel[n+1]-e.travel[n])));return a(n)+s*(a(n+1)-a(n))}function Ms(e,t){if(e.travel.length<2)return 0;let n=sr(e.travel,t);return(e.force[n+1]-e.force[n])/(e.travel[n+1]-e.travel[n])}function De(e,t,r){let n=e.hardpoints;switch(t.attach){case"upright":{let o=H(t.outer,n.wheelCenter);return ee(ee(at(r.pose.omega,o),n.wheelCenter),r.pose.t)}case"lowerArm":{let o=q(H(n.lcaRear,n.lcaFront));return ee(n.lcaFront,at(U(o,r.beta),H(t.outer,n.lcaFront)))}case"rocker":{let o=q(H(n.rockerPivotB,n.rockerPivotA));return ee(n.rockerPivotA,Ot(H(t.outer,n.rockerPivotA),o,r.points.rockerAngle))}}}function mn(e,t,r){return e.config.actuation==="decoupled"&&t.attach==="rocker"&&r==="coil"}function rf(e,t,r){return mn(e,t,r)?[t.inner[0],-t.inner[1],t.inner[2]]:t.inner}function ta(e,t,r){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return nf(e,t,r.kind,Ke(e,{travelMin:n,travelMax:o,steps:a}).samples)}function nf(e,t,r,n){let o=q(H(t.outer,rf(e,t,r))),a=[],s=[],i=t.outer;for(let p of n)a.push(p.travel),s.push(X(H(De(e,t,p),i),o));let c=a.length,l=new Array(c).fill(0);for(let p=0;p<c;p++){let f=Math.max(0,p-1),h=Math.min(c-1,p+1),b=a[h]-a[f];l[p]=b!==0?(s[h]-s[f])/b:0}let u=l[0];for(let p=1;p<c;p++)if(a[p]>=0){let f=a[p]-a[p-1],h=f!==0?(0-a[p-1])/f:0;u=l[p-1]+h*(l[p]-l[p-1]);break}let m=l.filter(p=>Math.abs(p)>1e-9).map(Math.sign),d=m.length>0&&m.some(p=>p!==m[0]);return{travel:a,ratio:l,linkTravel:s,atDesign:u,reverses:d}}function of(e,t){let{travel:r,ratio:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}function af(e,t){let{travel:r,linkTravel:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}var Ss=e=>e.mount??{kind:"rockerToRocker"},RR=e=>[e[0],0,e[2]],kP=e=>2*Math.abs(e[1]),MP=(e,t)=>Math.hypot(e[0]-t[0],e[2]-t[2]);function xl(e,t){return t.kind==="chassis"?MP(e,t.anchor):kP(e)}function As(e,t,r){if(r.kind==="chassis"){let s=[(e[0]+t[0])/2,(e[1]-t[1])/2,(e[2]+t[2])/2];return Math.hypot(s[0]-r.anchor[0],s[1],s[2]-r.anchor[2])}let n=e[0]-t[0],o=e[1]+t[1],a=e[2]-t[2];return Math.hypot(n,o,a)}function Bn(e,t,r={}){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return sf(e,t,Ke(e,{travelMin:n,travelMax:o,steps:a}).samples)}function sf(e,t,r){let n=Ss(t),o=f=>De(e,{...t,inner:t.outer},r[f]),a=[],s=[],i=[];for(let f=0;f<r.length;f++)a.push(r[f].travel),i.push(xl(o(f),n));let c=yR(a,i,0);for(let f of i)s.push(c-f);let l=a.length,u=new Array(l).fill(0);for(let f=0;f<l;f++){let h=Math.max(0,f-1),b=Math.min(l-1,f+1),g=a[b]-a[h];u[f]=g!==0?(s[b]-s[h])/g:0}let m=gR(a,20),d=gR(a,-20),p=As(o(m),o(d),n);return{travel:a,ratio:u,springTravel:s,atDesign:yR(a,u,0),installedLength:c,rollSensitivity:c-p}}function gR(e,t){let r=0,n=1/0;for(let o=0;o<e.length;o++){let a=Math.abs(e[o]-t);a<n&&(n=a,r=o)}return r}function yR(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];for(let o=1;o<n;o++)if(e[o]>=r){let a=e[o]-e[o-1],s=a!==0?(r-e[o-1])/a:0;return t[o-1]+s*(t[o]-t[o-1])}return t[n-1]}function cf(e,t,r){let n={outer:t.outer,attach:t.attach},o=Ke(e,{travelMin:-5,travelMax:5,steps:3}),a=f=>RR(De(e,{...n,inner:n.outer},o.samples[f])),s=a(1),i=a(2),c=a(0),l=i[0]-c[0],u=i[2]-c[2],m=Math.hypot(l,u),d=m>1e-9?[l/m,u/m]:[0,1],p=r??Math.max(80,2*Math.abs(t.outer[1])*.5);return[s[0]+d[0]*p,0,s[2]+d[1]*p]}function lf(e,t){let r=e.hardpoints,n=r.rockerPivotA,o=xR(yl(r.rockerPivotB,r.rockerPivotA)),a=Math.max(30,.6*vR(yl(r.rockerToDamper,n))),s=yl(r.rockerToDamper,n),i=xR(yl(s,SP(o,AP(s,o)))),c=FP(o,i),l=null,u=-1/0;for(let m=0;m<360;m+=10){let d=m*Math.PI/180,f={outer:[n[0]+a*(Math.cos(d)*i[0]+Math.sin(d)*c[0]),n[1]+a*(Math.cos(d)*i[1]+Math.sin(d)*c[1]),n[2]+a*(Math.cos(d)*i[2]+Math.sin(d)*c[2])],attach:"rocker"},h=t==="chassis"?{...f,mount:{kind:"chassis",anchor:cf(e,f)}}:f,b;try{b=Bn(e,h,{travelMin:-20,travelMax:20,steps:9})}catch{continue}let g=b.atDesign/(1+4*Math.abs(b.rollSensitivity));Number.isFinite(g)&&g>u&&(u=g,l=h)}return l??{outer:r.rockerToDamper,attach:"rocker"}}var yl=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],SP=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],AP=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],vR=e=>Math.hypot(e[0],e[1],e[2]),xR=e=>{let t=vR(e)||1;return[e[0]/t,e[1]/t,e[2]/t]},FP=(e,t)=>[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]];var uf=.001,wP=e=>({outer:e.outer,inner:e.outer,attach:e.attach}),TR=(e,t,r)=>(xl(e.at0,t)-xl(r,t))/2,CP=(e,t)=>X(H(t,e.pickup.at0),e.axis);function mf(e,t){let r=e.length;return t.map((n,o)=>{let a=Math.max(0,o-1),s=Math.min(r-1,o+1);return(t[s]-t[a])/(e[s]-e[a])})}function kR(e,t){let r=[0,1,2].map(n=>mf(e,t.map(o=>o[n])));return t.map((n,o)=>[r[0][o],r[1][o],r[2][o]])}function pf(e){return{travel:e,heave:e.map(t=>t/2),heaveRatio:e.map(()=>.5),roll:[...e],rollRatio:e.map(()=>1)}}function MR(e,t,r,n){let o=e.corner;if(!t.heave&&!t.roll)return{side:pf([n.min,n.max]),pickups:{}};let a=st(ge(e,0,0)),s={};if(t.heave&&r){let h=wP(t.heave);s.heave={corner:o,link:h,at0:De(o,h,a)}}if(t.roll){let h=t.roll;s.roll={pickup:{corner:o,link:h,at0:De(o,h,a)},axis:q(H(h.outer,rf(o,h,t.rollKind??"coil")))}}let i=t.roll&&mn(o,t.roll,t.rollKind??"coil")?{near:t.roll,far:{...t.roll,outer:t.roll.inner}}:null,c=Qo(e,{travelMin:n.min,travelMax:n.max,steps:n.steps,steer:0}),l=[],u=[],m=[],d=[],p=[];for(let h of c.samples)!h.converged||l.length>0&&h.travel<=l[l.length-1]+1e-6||(l.push(h.travel),u.push(s.heave&&r?TR(s.heave,r,De(o,s.heave.link,h)):h.travel/2),m.push(s.roll?CP(s.roll,De(o,s.roll.pickup.link,h)):h.travel),i&&(d.push(De(o,i.near,h)),p.push(De(o,i.far,h))));if(l.length<2)return{side:pf([n.min,n.max]),pickups:{}};let f={travel:l,heave:u,heaveRatio:mf(l,u),roll:m,rollRatio:mf(l,m)};return i&&(f.eyes={near:d,nearRatio:kR(l,d),far:p,farRatio:kR(l,p)}),{side:f,pickups:s}}function Rl(e,t,r){let n=sr(e,r);return t[n]+(r-e[n])/(e[n+1]-e[n])*(t[n+1]-t[n])}function SR(e,t,r){let n=sr(e,r);return(t[n+1]-t[n])/(e[n+1]-e[n])}function Ne(e,t){return{h:Rl(e.travel,e.heave,t),dh:Rl(e.travel,e.heaveRatio,t),ddh:SR(e.travel,e.heaveRatio,t),r:Rl(e.travel,e.roll,t),dr:Rl(e.travel,e.rollRatio,t),ddr:SR(e.travel,e.rollRatio,t)}}function AR(e,t,r,n){let o=sr(e,n),a=e[o+1]-e[o],s=(n-e[o])/a,i=(u,m)=>[u[0]+s*(m[0]-u[0]),u[1]+s*(m[1]-u[1]),u[2]+s*(m[2]-u[2])],c=r[o],l=r[o+1];return{p:i(t[o],t[o+1]),d:i(c,l),dd:[(l[0]-c[0])/a,(l[1]-c[1])/a,(l[2]-c[2])/a]}}var df=(e,t)=>Math.hypot(e[0]-t[0],e[1]+t[1],e[2]-t[2]);function ff(e,t){let r=e.side[0].eyes,n=e.side[1].eyes;if(!r||!n)return null;let o=AR(e.side[0].travel,r.near,r.nearRatio,t[0]),a=AR(e.side[1].travel,n.far,n.farRatio,t[1]),s=[o.p[0]-a.p[0],o.p[1]+a.p[1],o.p[2]-a.p[2]],i=Math.hypot(s[0],s[1],s[2]),c=[s[0]/i,s[1]/i,s[2]/i],l=o.d,u=[-a.d[0],a.d[1],-a.d[2]],m=[-a.dd[0],a.dd[1],-a.dd[2]],d=X(c,l),p=X(c,u),f=(X(l,u)-d*p)/i;return{L:i,dL:[d,p],ddL:[[(X(l,l)-d*d)/i+X(c,o.dd),f],[f,(X(u,u)-p*p)/i+X(c,m)]]}}var PR=(e,t)=>e.bump!==null&&t>e.bump?e.rate*(t-e.bump):e.droop!==null&&t<e.droop?e.rate*(t-e.droop):0,TP=(e,t)=>e.bump!==null&&t>e.bump||e.droop!==null&&t<e.droop?e.rate:0;function Fs(e,t,r,n,o=0){let a=e.rollStop;if(!a)return r;let s=ff(e,t);if(!s)return r;let i=PR(a,a.length0-(n??s.L+o));return i===0?r:[r[0]-i*s.dL[0],r[1]-i*s.dL[1]]}function vl(e,t){let r=pf(e.travel);return t==="heave"?{...e,heave:r.heave,heaveRatio:r.heaveRatio}:{...e,roll:r.roll,rollRatio:r.rollRatio}}var kl=(e,t)=>e?e.law?Jo(e.law,t):e.preload+e.rate*t:0,FR=(e,t)=>e?e.law?Zd(e.law,t):e.rate:0;function ws(e,t,r,n,o){let a=kl(e.heave,n),s=kl(e.roll,o);return[a*t.dh+s*t.dr,a*r.dh-s*r.dr]}var wR=(e,t)=>Ne(e[0],t).h+Ne(e[1],t).h;function PP(e,t){let r=e.gap>0?wR(t,e.gap):0;return e.bothWays?{free:r,pull:e.gap>0?wR(t,-e.gap):0}:{free:r,pull:null}}function LP(e,t,r){let n={...t,outer:t.inner},o=(u,m)=>{let d=mt(ge(e[0],u,0)),p=mt(ge(e[1],m,0));if(!d||!p)return NaN;let f=De(e[0].corner,t,d),h=De(e[1].corner,n,p);return Math.hypot(f[0]-h[0],f[1]+h[1],f[2]-h[2])},a=1,s=o(0,0),i=o(-a,a)-o(a,-a),c=Ne(r[0],a).r-Ne(r[1],-a).r-(Ne(r[0],-a).r-Ne(r[1],a).r),l=i/c;return Number.isFinite(s)&&s>0&&Number.isFinite(l)&&Math.abs(l)>uf?{length0:s,scale:l}:null}function LR(e,t,r,n=gl){let o=r.heave?Ss(r.heave):void 0,a=MR(e[0],r,o,n),s=e[1].corner===e[0].corner?a:MR(e[1],r,o,n),i=[a.side,s.side],c=!!(a.pickups.heave&&s.pickups.heave),l=!!(a.pickups.roll&&s.pickups.roll),u=r.carriesLoad?void 0:r.heaveSeat,m=u?u.rate:(t[0].heaveRate+t[1].heaveRate)/2,d=(t[0].arbRate+t[1].arbRate)/2,p=i.map(S=>Ne(S,0));c&&!(Math.abs(p[0].dh+p[1].dh)>uf)&&(i=[vl(i[0],"heave"),vl(i[1],"heave")],c=!1),l&&!(Math.abs(p[0].dr+p[1].dr)>uf)&&(i=[vl(i[0],"roll"),vl(i[1],"roll")],l=!1),p=i.map(S=>Ne(S,0));let f=p[0].dh+p[1].dh,h=p[0].dr+p[1].dr,b=m>0?2*m/(f*f):0,g=d>0?2*d/(h*h):0,y=0,R=0;if(r.carriesLoad){let S=[t[0].springLoad,t[1].springLoad];if(b>0&&g>0){let P=-p[0].dh*p[1].dr-p[1].dh*p[0].dr;Math.abs(P)>1e-12&&(y=(-S[0]*p[1].dr-S[1]*p[0].dr)/P,R=(p[0].dh*S[1]-p[1].dh*S[0])/P)}else b>0?y=(S[0]+S[1])/f:g>0&&(R=(S[0]-S[1])/h)}let k={};if(c&&o){let S=[a.pickups.heave,s.pickups.heave];k.heave={pickups:S,mount:o,span0:As(S[0].at0,S[1].at0,o)}}let v=k.heave?k.heave.span0:NaN,x=k.heave?r.coilover:void 0,M=r.carriesLoad?Rs(b,y,v,x):u?Qd(b,{...PP(u,i),length0:v,coilover:x}):null,A=b>0?{rate:b,preload:y,...M?{law:M}:{}}:null;if(l&&(k.roll={pickups:[a.pickups.roll.pickup,s.pickups.roll.pickup],axes:[a.pickups.roll.axis,s.pickups.roll.axis]},r.roll&&mn(e[0].corner,r.roll,r.rollKind??"coil"))){let S=LP(e,r.roll,i);S&&(k.roll.unit=S)}let w=g>0?{rate:g,preload:R}:null,C={side:i,heave:A,roll:w,force0:[0,0],carriesLoad:r.carriesLoad,read:k},T=k.roll?.unit,F=T&&g>0&&i[0].eyes&&i[1].eyes?Zo(T.length0,r.rollCoilover):null;return T&&F&&(F.droop!==null||F.bump!==null)&&(C.rollStop={length0:T.length0,rate:1e3*g/(T.scale*T.scale),...F}),C.force0=Fs(C,[0,0],ws(C,p[0],p[1],p[0].h+p[1].h,p[0].r-p[1].r)),C}function Cs(e,t,r){let n=Ne(e.side[0],t[0]),o=Ne(e.side[1],t[1]),a=r?Fs(e,t,ws(e,n,o,n.h+o.h+r.heave,n.r-o.r+r.roll),void 0,r.unit):Fs(e,t,ws(e,n,o,n.h+o.h,n.r-o.r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function hf(e,t,r){let n=Ne(e.side[0],t[0]),o=Ne(e.side[1],t[1]),a=r?n.h+o.h+r.heave:n.h+o.h,s=r?n.r-o.r+r.roll:n.r-o.r,i=FR(e.heave,a),c=FR(e.roll,s),l=kl(e.heave,a),u=kl(e.roll,s),m=i*n.dh*o.dh-c*n.dr*o.dr,d=[[i*n.dh*n.dh+l*n.ddh+c*n.dr*n.dr+u*n.ddr,m],[m,i*o.dh*o.dh+l*o.ddh+c*o.dr*o.dr-u*o.ddr]],p=e.rollStop,f=p?ff(e,t):null;if(!p||!f)return d;let h=p.length0-(r?f.L+r.unit:f.L),b=TP(p,h);if(b===0)return d;let g=PR(p,h),y=(k,v)=>b*f.dL[k]*f.dL[v]-g*f.ddL[k][v],R=m+y(0,1);return[[d[0][0]+y(0,0),R],[R,d[1][1]+y(1,1)]]}function bf(e,t,r){let n=hf(e,t);return n[r][0]+n[r][1]}function DP(e,t,r){let n=e.read.heave;if(!n)return Ne(e.side[0],t[0]).h+Ne(e.side[1],t[1]).h;let[o,a]=n.pickups;return n.span0-As(De(o.corner,o.link,r[0]),De(a.corner,a.link,r[1]),n.mount)}function EP(e,t,r){let n=e.read.roll;if(!n)return Ne(e.side[0],t[0]).r-Ne(e.side[1],t[1]).r;let o=a=>X(H(De(n.pickups[a].corner,n.pickups[a].link,r[a]),n.pickups[a].at0),n.axes[a]);return o(0)-o(1)}function IP(e,t){let r=e.read.roll;if(!e.rollStop||!r)return;let[n,o]=r.pickups;return df(De(n.corner,n.link,t[0]),De(o.corner,{...o.link,outer:o.link.inner},t[1]))}function Ts(e,t,r){let n=Ne(e.side[0],t[0]),o=Ne(e.side[1],t[1]),a=Fs(e,t,ws(e,n,o,DP(e,t,r),EP(e,t,r)),IP(e,r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function gf(e,t,r,n){let o=Ne(e.side[0],r),a=Ne(e.side[1],r),s=e.read.heave,i=s?.pickups[t],c=s&&i&&n?2*TR(i,s.mount,De(i.corner,i.link,n)):o.h+a.h,l=e.rollStop&&n?e.read.roll?.pickups[t]:void 0,u=l&&n?df(De(l.corner,l.link,n),De(l.corner,{...l.link,outer:l.link.inner},n)):void 0;return Fs(e,[r,r],ws(e,o,a,c,n?0:o.r-a.r),u)[t]-e.force0[t]}function yf(e,t,r,n){let o=ea(e,r[n]);return t?.carriesLoad?o+bf(t,r,n):o}function DR(e,t){return Ne(e.side[0],t[0]).h+Ne(e.side[1],t[1]).h}function ER(e,t){return ff(e,t)?.L??null}var xf=e=>e==="FR"||e==="RR"?1:0,Ml=(e,t)=>e.elements?.[t==="FL"||t==="FR"?"front":"rear"]??null;var IR=e=>Number.isFinite(e)&&e>0?1/e:0;var _R=(e,t)=>{let r=e[0][0]*e[1][1]-e[0][1]*e[1][0];return Math.abs(r)>1e-14?[(t[0]*e[1][1]-t[1]*e[0][1])/r,(e[0][0]*t[1]-e[1][0]*t[0])/r]:null},_P=(e,t)=>[e[0][0]*t[0]+e[0][1]*t[1],e[1][0]*t[0]+e[1][1]*t[1]],NR=1e-8,NP=40;function OP(e,t,r,n){return{force:(s,i)=>{if(r){let u=Cs(r,s,n);return[Ut(t[0],s[0])+i[0]+u[0],Ut(t[1],s[1])+i[1]+u[1]]}let c=(s[0]+s[1])/2,l=(s[0]-s[1])/2;return[Ut(t[0],s[0])+i[0]+e[0].heaveRate*c+e[0].arbRate*l,Ut(t[1],s[1])+i[1]+e[1].heaveRate*c-e[1].arbRate*l]},stiffness:(s,i=Ms)=>{if(r){let c=hf(r,s,n);return[[i(t[0],s[0])+c[0][0],c[0][1]],[c[1][0],i(t[1],s[1])+c[1][1]]]}return[[i(t[0],s[0])+e[0].heaveRate/2+e[0].arbRate/2,e[0].heaveRate/2-e[0].arbRate/2],[e[1].heaveRate/2-e[1].arbRate/2,i(t[1],s[1])+e[1].heaveRate/2+e[1].arbRate/2]]}}}function ra(e,t,r,n,o,a=[0,0],s=[0,0],i=null,c){let l=[IR(r[0].tyreRate),IR(r[1].tyreRate)],u=[r[0].staticLoad,r[1].staticLoad],m=OP(r,n,i,c),d=P=>m.force(P,a),p=m.stiffness([0,0]),f=[l[0]>0?l[0]:1/Math.max(1,Math.abs(p[0][0])),l[1]>0?l[1]:1/Math.max(1,Math.abs(p[1][1]))],h=(P,L)=>{let D=L===1?d(P):m.force(P,[a[0]*L,a[1]*L]),I=[D[0]+s[0]*L,D[1]+s[1]*L],O=[P[0]+t[0]*L+I[0]*l[0]-e[0]*L,P[1]+t[1]*L+I[1]*l[1]-e[1]*L],_=[f[0]*(u[0]+I[0]),f[1]*(u[1]+I[1])],z=[_[0]<O[0],_[1]<O[1]];return{f:I,on:O,off:_,lifted:z,r:[Math.min(O[0],_[0]),Math.min(O[1],_[1])]}},b=(P,L)=>[L[0]?[f[0]*P[0][0],f[0]*P[0][1]]:[1+P[0][0]*l[0],P[0][1]*l[0]],L[1]?[f[1]*P[1][0],f[1]*P[1][1]]:[P[1][0]*l[1],1+P[1][1]*l[1]]],g=P=>Math.max(Math.abs(P[0]),Math.abs(P[1])),y=(P,L)=>{let D=[P[0],P[1]],I=h(D,L),O=!1,_=0;for(;_<NP;_++){if(g(I.r)<NR){O=!0;break}let z=_R(b(m.stiffness(D),I.lifted),[-I.r[0],-I.r[1]]);if(!z)break;let E=1,N=[D[0]+z[0],D[1]+z[1]],B=h(N,L);for(let V=0;V<8&&g(B.r)>g(I.r);V++)E/=2,N=[D[0]+E*z[0],D[1]+E*z[1]],B=h(N,L);D=N,I=B}return!O&&g(I.r)<NR&&(O=!0),{t:D,b:I,converged:O,it:_}},R=y(o?[o[0],o[1]]:[e[0]-t[0],e[1]-t[1]],1),k=R.it;if(!R.converged){let P=0,L=[0,0],D=.25;for(;P<1&&D>=1/256;){let I=Math.min(1,P+D),O=y(L,I);k+=O.it,O.converged?(P=I,L=O.t,I===1&&(R=O)):D/=2}}let{t:v,b:x,converged:M}=R,A=x.lifted,w=[A[0]?-u[0]:x.f[0],A[1]?-u[1]:x.f[1]],C=[A[0]?Math.max(0,x.on[0]):0,A[1]?Math.max(0,x.on[1]):0],T=m.stiffness(v,ea),F=b(T,A);return{t:v,dF:w,lifted:A,clearance:C,converged:M,iterations:k,respond:(P,L,D=[0,0])=>{let I=[A[0]?-f[0]*D[0]:P[0]-L[0]-D[0]*l[0],A[1]?-f[1]*D[1]:P[1]-L[1]-D[1]*l[1]],O=_R(F,I);if(!O)return[NaN,NaN];let _=_P(T,O);return[A[0]?0:_[0]+D[0],A[1]?0:_[1]+D[1]]}}}var $n=e=>!(Number.isFinite(e.tyreRate)&&e.tyreRate>0);function $t(e,t,r){return t?.input.corners[r].staticLoadedRadius??e}var Rf=["FL","FR","RL","RR"],BR={front:["FL","FR"],rear:["RL","RR"]},VP=512,BP=5e-4,$P=8;function Sl(e,t){let r={},n={},o=new Map;for(let s of Rf){let i=e.ctx[s],c=t.corners[s],l=c.staticLoadedRadius;n[s]=st(ge(i,0,0,void 0,l===void 0?void 0:{loadedRadius:l})).points.contactPatch[2];let u=t.cornerCoilover?.[s==="FL"||s==="FR"?"front":"rear"],m=`${Rf.findIndex(p=>_e(e.vehicle,p)===_e(e.vehicle,s))}|${c.springLoad}|${u?`${u.extended}/${u.stroke}`:""}`,d=o.get(m);d?r[s]=d:(r[s]=u?ks(i,c.springLoad,void 0,u):ks(i,c.springLoad),o.set(m,r[s]))}let a={front:null,rear:null};for(let s of["front","rear"]){let i=t.elements?.[s];if(!i)continue;let c=BR[s];a[s]=LR([e.ctx[c[0]],e.ctx[c[1]]],[t.corners[c[0]],t.corners[c[1]]],i)}return{input:t,curve:r,elements:a,ground0:n,memo:new Map}}function $R(e,t,r){if(!(r>0)||!Number.isFinite(r)||!Number.isFinite(t)||t<=0)return 0;let n=Math.min(t/r,e);return 2*Math.sqrt(Math.max(0,2*e*n-n*n))}var GP=e=>`${e.heave}|${e.pitch}|${e.roll}|${e.steer}`;function vf(e,t,r){return{travel:r.travel,steer:r.steer,ground:r.travel,tyreDeflection:0,load:NaN,loadedRadius:$t(_e(e.vehicle,t).config.loadedRadius,e.kc,t),lifted:!1,contactLength:0,converged:!0,rigid:!0,rideRate:NaN,wheelRateAtLoad:NaN}}var KP=e=>e?{q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle}:void 0;function OR(e,t,r,n){let o=BR[n],a=e.vehicle.config,s=o.map(w=>un(w,a,r,e.vehicle)),i=[t.input.corners[o[0]],t.input.corners[o[1]]],c=t.loadCase;if(!c&&i.every($n))return{corners:[vf(e,o[0],s[0]),vf(e,o[1],s[1])],respond:null};let l=o.map(w=>t.curve[w]),u=t.elements?.[n]??null,m=o.map(w=>$t(_e(e.vehicle,w).config.loadedRadius,t,w)),d=[s[0].travel+(c?.ground[o[0]]??0),s[1].travel+(c?.ground[o[1]]??0)],p=[c?.linkLoad[o[0]]??0,c?.linkLoad[o[1]]??0],f=[c?.patchShift[o[0]],c?.patchShift[o[1]]],h=[0,0],b=[0,0],g,y=ra(d,h,i,l,void 0,void 0,p,u),R=[void 0,void 0],k=[!0,!0],v=[0,0],x=!1;for(let w=0;w<$P;w++){w>0&&(y=ra(d,h,i,l,g,b,p,u)),v=[Number.isFinite(i[0].tyreRate)&&i[0].tyreRate>0?y.dF[0]/i[0].tyreRate:0,Number.isFinite(i[1].tyreRate)&&i[1].tyreRate>0?y.dF[1]/i[1].tyreRate:0];let C=[0,0],T=[0,0];for(let S=0;S<2;S++){let P=ge(e.ctx[o[S]],y.t[S],s[S].steer,KP(R[S]),{loadedRadius:m[S]-v[S],patchShift:f[S]}),L=st(P);R[S]=L,k[S]=P.ok,C[S]=L.points.contactPatch[2]-t.ground0[o[S]]-y.t[S]-v[S],T[S]=Cr(l[S],y.t[S],L.points.damperLength)-Ut(l[S],y.t[S])}if(u){let S=Ts(u,y.t,[R[0],R[1]]),P=Cs(u,y.t);T[0]+=S[0]-P[0],T[1]+=S[1]-P[1]}let F=Math.max(Math.abs(C[0]-h[0]),Math.abs(C[1]-h[1]),Math.abs(T[0]-b[0])/Math.max(1,i[0].tyreRate),Math.abs(T[1]-b[1])/Math.max(1,i[1].tyreRate));if(h=C,b=T,g=y.t,F<BP){x=!0;break}}let M=y.respond([1,1],[0,0]);return{corners:[0,1].map(w=>{let C=R[w];return{travel:y.t[w],steer:s[w].steer,ground:d[w],tyreDeflection:v[w],load:i[w].staticLoad+y.dF[w],loadedRadius:m[w]-v[w],lifted:y.lifted[w],clearance:y.clearance[w],contactLength:$R(m[w]-v[w],i[w].staticLoad+y.dF[w],i[w].tyreRate),converged:y.converged&&x&&k[w],rigid:!1,state:C,solved:k[w],rideRate:M[w],wheelRateAtLoad:yf(l[w],u,y.t,w)}}),respond:y.respond}}function GR(e,t){let r=e.kc,n=GP(t),o=r.memo.get(n);if(o)return o;let a=OR(e,r,t,"front"),s=OR(e,r,t,"rear"),i={corners:{FL:a.corners[0],FR:a.corners[1],RL:s.corners[0],RR:s.corners[1]},respond:{front:a.respond,rear:s.respond}};return r.memo.size>=VP&&r.memo.clear(),r.memo.set(n,i),i}function yt(e,t){if(!e.kc){let r={};for(let n of Rf)r[n]=vf(e,n,un(n,e.vehicle.config,t,e.vehicle));return r}return GR(e,t).corners}function Al(e,t,r){return e.kc?GR(e,t).respond[r]:null}function Ps(e,t,r,n=0){let o=e.kc;if(!o)return r;let a=o.input.corners[t];if($n(a))return r;let s=un(t,e.vehicle.config,{heave:0,pitch:0,roll:0,steer:n},e.vehicle).steer,i=$t(_e(e.vehicle,t).config.loadedRadius,o,t),c=o.loadCase,l=c?.linkLoad[t]??0,u=c?.patchShift[t],m=st(ge(e.ctx[t],r,s,void 0,{loadedRadius:i,patchShift:u})),d=Ml(o,t),p=Cr(o.curve[t],r,m.points.damperLength)+(d?gf(d,xf(t),r,m):a.heaveRate*r),h=Math.max(p+l,-a.staticLoad)/a.tyreRate;return(h===0?m:st(ge(e.ctx[t],r,s,void 0,{loadedRadius:i-h,patchShift:u}))).points.contactPatch[2]-o.ground0[t]-(c?.ground[t]??0)}var HP=180/Math.PI,zP=[0,0,1];function YP(e,t){let r=wr(e,t),n=U(ae(zP,r),-t.sideSign);return-Math.atan2(n[1],n[0])*HP}var KR=e=>1/Math.tan(e*Math.PI/180),HR=.05,zR=.001;function YR(e,t,r){if(!Number.isFinite(e)||!Number.isFinite(t))return NaN;if(!(Math.abs(e)<zR&&Math.abs(t)<zR))return e>0&&t>0?100*(KR(t)-KR(e))/r:NaN}function WP(e,t){let r=Bt(e.vehicle,!0)/e.vehicle.config.wheelbase,n=t("FL",0).deg,o=t("FR",0).deg,a=(c,l)=>{let u=c+l>=0;return{left:u,inner:u?c:-l,outer:u?l:-c}},s,i=()=>{if(s===void 0){let c=[HR,-HR].map(l=>{let{inner:u,outer:m}=a(t("FL",l).deg-n,t("FR",l).deg-o);return YR(u,m,r)??NaN});s=(c[0]+c[1])/2}return s};return c=>{let l=t("FL",c),u=t("FR",c),{left:m,inner:d,outer:p}=a(l.deg-n,u.deg-o),f=YR(d,p,r);return{steerL:l.deg,steerR:u.deg,inner:d,outer:p,toeDiff:d-p,ackermannPct:f??i(),inside:f===void 0?null:m?"left":"right",converged:l.ok&&u.ok}}}function kf(e,t){let r=e.vehicle.config,n={FL:Qe("FL",r),FR:Qe("FR",r)},o=t.travel??0,a=WP(e,(i,c)=>{let l=mt(ge(e.ctx[i],o,n[i].sideSign*c));return{deg:l?YP(l.points.spinAxis,n[i]):NaN,ok:l!==null}}),s=[];for(let i=0;i<t.steps;i++){let c=t.steps===1?0:-t.steerMax+2*t.steerMax*i/(t.steps-1),{inside:l,...u}=a(c);s.push({steerInput:c,...u})}return s}var WR=35,jR=55,xt=e=>e.rackTravel&&e.rackTravel>0?e.rackTravel:WR,Mf=e=>e.rackRatio&&e.rackRatio>0?e.rackRatio:jR;var Sf=e=>({q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle});function UR(e,t,r,n,o){let a=ge(e,n,0,void 0,o),s=st(a),i=a.ok?0:1,c=s.points.contactPatch[2],l={steer:s.metrics.toe,camber:s.metrics.camber,lift:0,contactPatch:s.points.contactPatch,spinAxis:s.points.spinAxis,yaw:-s.metrics.toe*Math.PI/180},u=p=>{let f=[l],h=Sf(s);for(let b=1;b<=r;b++){let g=p*(t*b)/r,y=Ie(e,s.beta,g,h,o),R=mt(ge(e,n,g,Sf(y),o));if(!R||!y.converged){i++,f.push({...f[f.length-1]});continue}f.push({steer:R.metrics.toe,camber:R.metrics.camber,lift:-(y.points.contactPatch[2]-c),contactPatch:y.points.contactPatch,spinAxis:y.points.spinAxis,yaw:-y.metrics.toe*Math.PI/180}),h=Sf(y)}return f},m=u(1),d=u(-1);return{travelMm:n,unsolved:i,centre:l,positive:m,negative:d}}function jP(e,t){return e.map((r,n)=>{let o=n===0?0:n-1,a=n===e.length-1?e.length-1:n+1,s=t[a]-t[o];if(!(s>0))return{longitudinal:0,lateral:0,vertical:0,yaw:0};let i=U(H(e[a].contactPatch,e[o].contactPatch),1/s),c=q(ae(r.spinAxis,[0,0,1])),l=ae([0,0,1],c);return{longitudinal:X(i,c),lateral:X(i,l),vertical:i[2],yaw:(e[a].yaw-e[o].yaw)/s}})}function XR(e,t,r){let n=o=>({steerDeg:o.map(a=>Math.abs(a.steer-e.centre.steer)),camberDeg:o.map(a=>a.camber-e.centre.camber),liftMm:o.map(a=>a.lift),jacobian:jP(o,t)});return{travelMm:e.travelMm,inner:n(r?e.positive:e.negative),outer:n(r?e.negative:e.positive)}}function UP(e){return e.positive[1].steer-e.centre.steer<0}function XP(e,t,r){return{meanDeg:t.map((n,o)=>.5*(r.inner.steerDeg[o]+r.outer.steerDeg[o])),innerDeg:r.inner.steerDeg,outerDeg:r.outer.steerDeg,innerCamber:r.inner.camberDeg,outerCamber:r.outer.camberDeg,innerLift:r.inner.liftMm,outerLift:r.outer.liftMm,rackRatioMmPerRev:Mf(e.config),innerJacobian:r.inner.jacobian,outerJacobian:r.outer.jacobian}}function Af(e,t,r=13,n=-40,o=40,a=5,s){let i=tt(e),c=Array.from({length:r+1},(b,g)=>t*g/r),l=UR(i,t,r,0,s),u=UP(l),m=XR(l,c,u),d=Math.max(2,Math.floor(a)),p=Array.from({length:d},(b,g)=>n+(o-n)*g/(d-1));p.some(b=>Math.abs(b)<1e-9)||p.push(0),p.sort((b,g)=>b-g);let f=l.unsolved,h=p.map(b=>{if(Math.abs(b)<1e-9)return m;let g=UR(i,t,r,b,s);return f+=g.unsolved,XR(g,c,u)});return{...XP(e,c,m),...qR(l.unsolved),travelSurface:{rackMm:c,rows:h,...qR(f)}}}var qR=e=>e>0?{unsolved:e}:{};function ir(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function Fl(e,t,r){let n=e.length;if(n===0)return{longitudinal:0,lateral:0,vertical:0,yaw:0};let o,a;if(r<=e[0])o=a=0;else if(r>=e[n-1])o=a=n-1;else for(o=0,a=n-1;a-o>1;){let l=o+a>>1;e[l]<=r?o=l:a=l}let s=t[o];if(o===a)return{longitudinal:s.longitudinal,lateral:s.lateral,vertical:s.vertical,yaw:s.yaw};let i=t[a],c=(r-e[o])/(e[a]-e[o]);return{longitudinal:s.longitudinal+c*(i.longitudinal-s.longitudinal),lateral:s.lateral+c*(i.lateral-s.lateral),vertical:s.vertical+c*(i.vertical-s.vertical),yaw:s.yaw+c*(i.yaw-s.yaw)}}function QR(e,t){let r=e.rows;if(r.length<=1||t<=r[0].travelMm)return{lo:0,hi:0,t:0};let n=r.length-1;if(t>=r[n].travelMm)return{lo:n,hi:n,t:0};let o=0,a=n;for(;a-o>1;){let s=o+a>>1;r[s].travelMm<=t?o=s:a=s}return{lo:o,hi:a,t:(t-r[o].travelMm)/(r[a].travelMm-r[o].travelMm)}}var Gn=(e,t,r)=>e+r*(t-e);function na(e,t,r,n,o){let a=ir(e.rackMm,e.rows[n.lo][t][r],o);if(n.lo===n.hi)return a;let s=ir(e.rackMm,e.rows[n.hi][t][r],o);return Gn(a,s,n.t)}function ZR(e,t,r,n){let o=Fl(e.rackMm,e.rows[r.lo][t].jacobian,n);if(r.lo===r.hi)return o;let a=Fl(e.rackMm,e.rows[r.hi][t].jacobian,n);return{longitudinal:Gn(o.longitudinal,a.longitudinal,r.t),lateral:Gn(o.lateral,a.lateral,r.t),vertical:Gn(o.vertical,a.vertical,r.t),yaw:Gn(o.yaw,a.yaw,r.t)}}function oa(e,t,r,n){let o=e.travelSurface;if(!o||o.rackMm.length<2||o.rows.length===0)return aa(e,t);let a=QR(o,r),s=QR(o,n),i=(p,f,h)=>{let b=o.rows[f.lo][p].steerDeg[h];return f.lo===f.hi?b:Gn(b,o.rows[f.hi][p].steerDeg[h],f.t)},c=new Array(o.rackMm.length);for(let p=0;p<c.length;p++)c[p]=.5*(i("inner",a,p)+i("outer",s,p));let l=Math.max(0,t),u=c.length-1,m=o.rackMm[u],d=l>c[u];if(l<=c[0])m=o.rackMm[0],d=!1;else if(!d){let p=1;for(;p<c.length-1&&c[p]<l;)p++;let f=p-1,h=c[p]-c[f],b=Math.abs(h)>1e-12?(l-c[f])/h:0;m=Gn(o.rackMm[f],o.rackMm[p],b)}return{innerDeg:na(o,"inner","steerDeg",a,m),outerDeg:na(o,"outer","steerDeg",s,m),innerCamber:na(o,"inner","camberDeg",a,m),outerCamber:na(o,"outer","camberDeg",s,m),innerLift:na(o,"inner","liftMm",a,m),outerLift:na(o,"outer","liftMm",s,m),innerJacobian:ZR(o,"inner",a,m),outerJacobian:ZR(o,"outer",s,m),atLock:d}}function aa(e,t){let r=e.meanDeg.length-1;return{innerDeg:ir(e.meanDeg,e.innerDeg,t),outerDeg:ir(e.meanDeg,e.outerDeg,t),innerCamber:ir(e.meanDeg,e.innerCamber,t),outerCamber:ir(e.meanDeg,e.outerCamber,t),innerLift:e.innerLift?ir(e.meanDeg,e.innerLift,t):0,outerLift:e.outerLift?ir(e.meanDeg,e.outerLift,t):0,...e.innerJacobian&&e.outerJacobian?{innerJacobian:Fl(e.meanDeg,e.innerJacobian,t),outerJacobian:Fl(e.meanDeg,e.outerJacobian,t)}:{},atLock:r>=0&&t>e.meanDeg[r]}}var qP=()=>({lift:{FL:0,FR:0,RL:0,RR:0},travel:{FL:0,FR:0,RL:0,RR:0},load:{FL:0,FR:0,RL:0,RR:0},rollDeg:0});function sa(e,t,r=we(e),n){let o=e.steerFront;if(!o?.innerLift||!o.outerLift||o.meanDeg.length<2||Math.abs(t)<1e-12)return qP();let a=Math.abs(t),s=t>0,i=n&&o.travelSurface?oa(o,a,s?n.FL:n.FR,s?n.FR:n.FL):null,c=i?.innerLift??ir(o.meanDeg,o.innerLift,a),l=i?.outerLift??ir(o.meanDeg,o.outerLift,a),u=s?c:l,m=s?l:c,d=.5*(u+m),p=r.rollWheelRateFront,f=r.rollWheelRateRear,h=e.trackFront,b=e.trackRear,g=p*h*h+f*b*b,y=g>0?p*h*(m-u)/g:0,R={FL:u-d+.5*h*y,FR:m-d-.5*h*y,RL:.5*b*y,RR:-.5*b*y};return{lift:{FL:u,FR:m,RL:0,RR:0},travel:R,load:{FL:p*R.FL,FR:p*R.FR,RL:f*R.RL,RR:f*R.RR},rollDeg:y===0?0:-Math.atan(y)*180/Math.PI}}function Ff(e,t,r){let n=t/r,o=a=>1/Math.tan(a*Math.PI/180);for(let a=0;a<e.meanDeg.length;a++)if(e.outerDeg[a]>.3&&e.innerDeg[a]>.3)return 100*(o(e.outerDeg[a])-o(e.innerDeg[a]))/n;return NaN}var Ls=9.81;function ia(e,t,r=0,n=0,o=0){if(!e.aero||t<=0)return{FL:0,FR:0,RL:0,RR:0};let a=e.aero.model?Fr(e,t,r,an(e,n,o)):On(e.aero,t),s=a.downFront/2,i=a.downRear/2,c=a.drag*(e.aero.copHeight/1e3)/(e.wheelbase/1e3)/2;return{FL:s-c,FR:s-c,RL:i+c,RR:i+c}}function wf(e,t,r=0,n=0,o=0){if(!e.aero?.model||t<=0)return!1;let a=Fr(e,t,r,an(e,n,o));return a!=null&&(a.clampedRide||a.clampedAttitude)}function Kn(e){let t=e.loadFactor===void 0?e.massTotal*Ls:e.massTotal*Ls*e.loadFactor,r=t*e.frontMassFrac,n=t*(1-e.frontMassFrac);return{FL:r/2,FR:r/2,RL:n/2,RR:n/2}}function JR(e,t=we(e),r=e.cgHeight){let n=e.trackFront/1e3,o=e.trackRear/1e3,a=e.rcHeightFront/1e3,s=e.rcHeightRear/1e3,i=(e.rcHeightFront+(e.rcHeightRear-e.rcHeightFront)*(1-e.frontMassFrac))/1e3,c=r/1e3-i,l=2*e.unsprungPerCorner,u=e.unsprungCgHeight/1e3,m=t.sprungMass*c*ol(t.sprungMass,c,t.rollRateTotal),d=(m*t.frontRollStiffFrac+t.sprungFront*a+l*u)/n,p=(m*(1-t.frontRollStiffFrac)+t.sprungRear*s+l*u)/o;return{cf:d,cr:p}}function Cf(e){let{cf:t,cr:r}=JR(e);return t+r>0?t/(t+r):.5}function ev(e,t,r){if(e.FL>=0&&e.FR>=0&&e.RL>=0&&e.RR>=0)return{loads:{FL:Math.max(0,e.FL),FR:Math.max(0,e.FR),RL:Math.max(0,e.RL),RR:Math.max(0,e.RR)},lifted:{FL:!1,FR:!1,RL:!1,RR:!1},overturned:!1};let n=e.FL+e.FR+e.RL+e.RR;if(!(n>0))return{loads:{FL:0,FR:0,RL:0,RR:0},lifted:{FL:!0,FR:!0,RL:!0,RR:!0},overturned:!0};let o=!1,a=e.FL+e.FR,s=e.RL+e.RR;a<0?(a=0,s=n,o=!0):s<0&&(s=0,a=n,o=!0);let i=(e.FR-e.FL)*t+(e.RR-e.RL)*r,c=Math.min(a,Math.max(-a,e.FR-e.FL)),l=Math.min(s,Math.max(-s,e.RR-e.RL)),u=i-(c*t+l*r);if(u!==0){let d=u>0?1:-1,p=(d*a-c)*t;d*u>=d*p?(c=d*a,u-=p):(c+=u/t,u=0);let f=(d*s-l)*r;u!==0&&(d*u>=d*f?(l=d*s,u-=f):(l+=u/r,u=0)),Math.abs(u)>1e-9*(Math.abs(i)+n*(t+r))&&(o=!0)}let m={FL:Math.max(0,(a-c)/2),FR:Math.max(0,(a+c)/2),RL:Math.max(0,(s-l)/2),RR:Math.max(0,(s+l)/2)};return{loads:m,lifted:{FL:m.FL===0,FR:m.FR===0,RL:m.RL===0,RR:m.RR===0},overturned:o}}function Ce(e,t,r,n=0,o=0,a=0,s,i){return wl(e,t,r,n,o,a,s,i).loads}function wl(e,t,r,n=0,o=0,a=0,s,i){let c=Kn(e),l=we(e),u=pl(e,n,r,an(e,t,o),l),{cf:m,cr:d}=JR(e,l,u.height),p=m*t*Ls,f=d*t*Ls,h=e.massTotal*(r*Ls)*u.height/e.wheelbase-u.noseLoad,b=ia(e,n,r,t,o),g=(i??sa(e,a,l,s)).load,y={FL:c.FL-p-h/2+b.FL+g.FL,FR:c.FR+p-h/2+b.FR+g.FR,RL:c.RL-f+h/2+b.RL+g.RL,RR:c.RR+f+h/2+b.RR+g.RR};return ev(y,e.trackFront,e.trackRear)}var Tf=Math.PI/180;function Tl(e,t){let r=8*Tf,n=0,o=0;for(let a=1;a<=90;a++){let s=a*.5,i=Math.abs(e.Fy(s*Tf,t,0));if(i>n&&(n=i,r=s*Tf,o=a),a>o+12&&i<.995*n)break}return{aPeak:r,fyPeak:n}}function tv(e,t,r,n,o){if(n===t)return r;let a=(o-t)/(n-t);return a<=0?e:a>=1?r:e+a*(r-e)}var Es=.999;function Ct(e,t,r,n,o){if(t<=0)return 0;let{aPeak:a,fyPeak:s}=o??Tl(e,t),i=Math.min(Math.abs(r),Es*s),c=n?-1:1,l=(v,x)=>Math.abs(e.forces({Fz:t,kappa:c*v,alpha:x}).Fy),u=.3,m=u,d=l(u,a);if(d<i){let v=0,x=u,M=NaN,A=d;for(let w=0;w<9;w++){let C=.5*(v+x),T=l(C,a);T>=i?(v=C,M=T):(x=C,A=T)}Number.isNaN(M)&&(M=l(0,a)),m=M<i?0:tv(v,M,x,A,i)}if(m<=0)return 0;let p=v=>{if(i===0)return c*e.forces({Fz:t,kappa:c*v,alpha:0}).Fx;let x=0,M=a,A=NaN,w=NaN;for(let C=0;C<5;C++){let T=.5*(x+M),F=l(v,T);F<i?(x=T,A=F):(M=T,w=F)}return Number.isNaN(A)&&(A=l(v,0)),Number.isNaN(w)&&(w=l(v,a)),c*e.forces({Fz:t,kappa:c*v,alpha:tv(x,A,M,w,i)}).Fx},f=4,h=v=>m*v/f,b=[0],g=1;for(let v=1;v<=f;v++)b.push(p(h(v))),b[v]>b[g]&&(g=v);let[y,R]=g===f?[f-1,f-2]:b[g-1]>=b[g+1]?[g-1,g+1]:[g+1,g-1],k=eL(p,h(g-1),h(Math.min(f,g+1)),h(g),b[g],h(y),b[y],h(R),b[R],QP);return c*Math.max(0,k)}var QP=.01,ZP=20,JP=(3-Math.sqrt(5))/2;function eL(e,t,r,n,o,a,s,i,c,l){o=-o,s=-s,c=-c;let u=r-t,m=0;for(let d=0;d<ZP;d++){let p=l*Math.abs(n)+1e-10,f=.5*(t+r);if(Math.abs(n-f)<=2*p-.5*(r-t))break;let h=!0;if(Math.abs(u)>p){let y=(n-a)*(o-c),R=(n-i)*(o-s),k=(n-i)*R-(n-a)*y;R=2*(R-y),R>0&&(k=-k),R=Math.abs(R);let v=u;if(u=m,Math.abs(k)<Math.abs(.5*R*v)&&k>R*(t-n)&&k<R*(r-n)){m=k/R;let x=n+m;(x-t<2*p||r-x<2*p)&&(m=f>=n?p:-p),h=!1}}h&&(u=n>=f?t-n:r-n,m=JP*u);let b=Math.abs(m)>=p?n+m:n+(m>=0?p:-p),g=-e(b);g<=o?(b>=n?t=n:r=n,i=a,c=s,a=n,s=o,n=b,o=g):(b<n?t=b:r=b,g<=s||a===n?(i=a,c=s,a=b,s=g):(g<=c||i===n||i===a)&&(i=b,c=g))}return-o}function Df(e,t){return e.model?.kind==="simple"?null:ov(e,t)}var rv=new WeakMap,Pf=100,nv=1.35,Lf=18,cr=41,Cl=41,Ds=65;function ov(e,t){let r=rv.get(e);if(r)return r;let n=Math.log(nv),o=(p,f)=>{let h=M=>Math.abs(Ct(e,p,M,f)),b=h(0),g=t.muY(p)*p,y=new Float64Array(cr),R=b>0&&g>0?Math.max(1,t.muX(p)*p/b):1;if(!(b>0)||!(g>0))y.fill(1);else{let M=[],A=[];for(let C=0;C<Cl;C++){let T=Math.sin(.5*Math.PI*C/(Cl-1));M.push(T),A.push(C===0?1:C===Cl-1?0:Math.min(A[C-1],h(T*g)/b))}let w=Cl-1;for(let C=0;C<cr;C++){let T=C/(cr-1);for(;w>0&&A[w-1]<T;)w--;let F=w>0?A[w-1]-A[w]:0;y[C]=w===0?M[0]:M[w]+(F>0?(T-A[w])/F:0)*(M[w-1]-M[w])}y[0]=1,y[cr-1]=0}let k=new Float64Array(Ds),v=M=>Math.atan2(y[M],M/(cr-1)/R),x=cr-2;for(let M=0;M<Ds;M++){let A=.5*Math.PI*M/(Ds-1),w=Math.cos(A),C=Math.sin(A);for(;x>0&&v(x)<A;)x--;let T=x/(cr-1)/R,F=y[x],S=(x+1)/(cr-1)/R,P=y[x+1],L=w*(P-F)-C*(S-T),D=Math.abs(L)>1e-12?(T*(P-F)-F*(S-T))/L:Math.hypot(T,F);k[M]=D>0?D:Math.hypot(T,F)}return{room:y,scale:R,edge:k}},a=Array.from({length:Lf},(p,f)=>Pf*nv**f),s=a.map(p=>o(p,!1)),i=a.map(p=>o(p,!0)),c=(p,f)=>{let h=Math.min(1,Math.abs(f)*p.scale)*(cr-1),b=Math.min(cr-2,Math.floor(h));return p.room[b]+(h-b)*(p.room[b+1]-p.room[b])},l=p=>{let f=p>Pf?Math.log(p/Pf)/n:0;if(f>=Lf-1)return[Lf-2,1];let h=Math.floor(f);return[h,f-h]},u=(p,f,h)=>{if(h===0)return 1;let b=h<0?i:s,g=c(b[p],h);return f>0?g+f*(c(b[p+1],h)-g):g},m=(p,f,h)=>{let b=f<0?i:s,[g,y]=l(p),R=Math.atan2(Math.abs(h),Math.abs(f))/(.5*Math.PI)*(Ds-1),k=Math.min(Ds-2,Math.floor(R)),v=M=>M.edge[k]+(R-k)*(M.edge[k+1]-M.edge[k]),x=v(b[g]);return y>0?x+y*(v(b[g+1])-x):x},d={keeps(p,f){if(f===0)return 1;let[h,b]=l(p);return u(h,b,f)},atLoad(p){let[f,h]=l(p);return b=>u(f,h,b)},use(p,f,h){let b=Math.hypot(f,h);return b>0?Math.min(1,b/m(p,f,h)):0},reach:m};return rv.set(e,d),d}var tL=[["front","FL","FR"],["rear","RL","RR"]];function ca(e,t,r,n){let o={...e},a=0,s=Es;for(let[i,c,l]of tL){let u=(k,v)=>n(i,Math.max(0,v[k])).fyPeak,m=Math.min(s,e[c]),d=Math.min(s,e[l]),p=m*u(c,r)+d*u(l,r);if(!(p>0))continue;let f=u(c,t),h=u(l,t),b=m*f+d*h,g=b>0?p/b:1/0,y=m*g,R=d*g;y<=s?R<=s||(R=s,y=f>0?(p-s*h)/f:1/0):(y=s,R=h>0?(p-s*f)/h:1/0),(!(y<=s)||!(R<=s))&&(a+=Math.max(0,p-s*(f+h)),y=Math.min(s,y),R=Math.min(s,R)),o[c]=y,o[l]=R}return{util:o,short:a}}var av=.001,rL=1e-5,sv=100;function nL(e,t,r,n){if(!(n>av))return r;let o=t,a=Math.abs(r-t)<sv?t+Math.sign(r-t)*sv:r;for(let s=0;s<60&&Math.abs(a-o)>rL;s++){let i=.5*(o+a);e(i)>av?a=i:o=i}return o}function Pl(e,t,r){let n;return{at:o=>{if(n!==void 0)return r<0?Math.max(o,n):Math.min(o,n);if(!((o-t)*r>0))return o;let a=nL(e,t,o,e(o));return a!==o&&(n=a),a},edge:()=>n}}function Ll(e,t){let r=n=>{try{return ge(e,0,n).ok}catch{return!1}};for(let n of[1,-1]){if(r(n*t))continue;let o=0;for(let a=1;a<=6;a++){let s=n*t*a/6;if(!r(s))break;o=Math.abs(s)}return{lock:t,reached:o,side:n}}return null}var Ef=40;function Dl(e){return{violation:Math.max(0,e.lock-e.reached),reason:`the steering reaches only ${e.reached.toFixed(0)} mm of the ${e.lock.toFixed(0)} mm rack travel${e.side<0?" (other side)":""}`}}var iv=[0,0,0];function oL(e,t){let r=q(H(e.rockerPivotB,e.rockerPivotA)),n=q(H(e.rockerToPushrod,e.pushrodOuter)),o=q(H(e.damperChassis,e.rockerToDamper)),a=Math.abs(X(r,ae(H(e.rockerToPushrod,e.rockerPivotA),n))),s=Math.abs(X(r,ae(H(e.rockerToDamper,e.rockerPivotA),o)));return s<1e-9?0:t*a/s}function El(e,t,r){if(e.mcpherson)return aL(e,t,r);let n=[{r:e.uprightUpper,c:e.ucaFront},{r:e.uprightUpper,c:e.ucaRear},{r:e.uprightLower,c:e.lcaFront},{r:e.uprightLower,c:e.lcaRear},{r:e.tieOuter,c:e.tieInner},{r:e.pushrodOuter,c:e.direct?e.damperChassis:e.rockerToPushrod}],o=e.wheelCenter,a=[[],[],[],[],[],[]];for(let m=0;m<6;m++){let d=q(H(n[m].c,n[m].r)),p=ae(H(n[m].r,o),d);a[0][m]=d[0],a[1][m]=d[1],a[2][m]=d[2],a[3][m]=p[0],a[4][m]=p[1],a[5][m]=p[2]}let s=ae(H(e.contactPatch,o),t),i=r??iv,c=[-t[0],-t[1],-t[2],-(s[0]+i[0]),-(s[1]+i[1]),-(s[2]+i[2])],l=or(a,c),u=l.x;return{ucaFront:u[0],ucaRear:u[1],lcaFront:u[2],lcaRear:u[3],tieRod:u[4],pushRod:u[5],damper:l.singular||e.decoupled?NaN:e.direct?u[5]:oL(e,u[5]),condProxy:l.condProxy,singular:l.singular}}function aL(e,t,r){let n=e.wheelCenter,o=e.damperChassis,a=[{at:e.uprightLower,dir:q(H(e.lcaFront,e.uprightLower))},{at:e.uprightLower,dir:q(H(e.lcaRear,e.uprightLower))},{at:e.tieOuter,dir:q(H(e.tieInner,e.tieOuter))},{at:o,dir:[1,0,0]},{at:o,dir:[0,1,0]},{at:o,dir:[0,0,1]}],s=[[],[],[],[],[],[]];for(let b=0;b<6;b++){let g=a[b].dir,y=ae(H(a[b].at,n),g);s[0][b]=g[0],s[1][b]=g[1],s[2][b]=g[2],s[3][b]=y[0],s[4][b]=y[1],s[5][b]=y[2]}let i=ae(H(e.contactPatch,n),t),c=r??iv,l=[-t[0],-t[1],-t[2],-(i[0]+c[0]),-(i[1]+c[1]),-(i[2]+c[2])],u=or(s,l),m=u.x,d=[m[3],m[4],m[5]],p=q(H(o,e.pushrodOuter)),f=X(d,p),h=Math.hypot(d[0]-f*p[0],d[1]-f*p[1],d[2]-f*p[2]);return{ucaFront:NaN,ucaRear:NaN,lcaFront:m[0],lcaRear:m[1],tieRod:m[2],pushRod:u.singular?NaN:f,damper:u.singular?NaN:f,condProxy:u.condProxy,singular:u.singular,strutSide:u.singular?NaN:h,topMount:d}}function If(e,t){let r=q(e.spinAxis),n=ae(H(e.contactPatch,e.wheelCenter),t),o=X(n,r);return[-o*r[0],-o*r[1],-o*r[2]]}var sL=[0,0,0];function Is(e,t,r,n){let o=e.direct?e.damperChassis:e.rockerToPushrod;if(e.mcpherson)return{...El(e,r,n),armResidual:0};if(t==="upright")return{...El(e,r,n),armResidual:0};let a=t==="lowerArm",s=a?{bj:e.uprightUpper,front:e.ucaFront,rear:e.ucaRear}:{bj:e.uprightLower,front:e.lcaFront,rear:e.lcaRear},i=a?{bj:e.uprightLower,front:e.lcaFront,rear:e.lcaRear}:{bj:e.uprightUpper,front:e.ucaFront,rear:e.ucaRear},c=e.wheelCenter,l=q(H(s.front,s.bj)),u=q(H(s.rear,s.bj)),m=q(H(e.tieInner,e.tieOuter)),d=[{at:s.bj,dir:l},{at:s.bj,dir:u},{at:e.tieOuter,dir:m},{at:i.bj,dir:[1,0,0]},{at:i.bj,dir:[0,1,0]},{at:i.bj,dir:[0,0,1]}],p=[[],[],[],[],[],[]];for(let Z=0;Z<6;Z++){let ne=d[Z].dir,te=ae(H(d[Z].at,c),ne);p[0][Z]=ne[0],p[1][Z]=ne[1],p[2][Z]=ne[2],p[3][Z]=te[0],p[4][Z]=te[1],p[5][Z]=te[2]}let f=ae(H(e.contactPatch,c),r),h=n??sL,b=[-r[0],-r[1],-r[2],-(f[0]+h[0]),-(f[1]+h[1]),-(f[2]+h[2])],g=or(p,b),y=g.singular,R=g.x,k=R[0],v=R[1],x=R[2],M=[R[3],R[4],R[5]],A=q(H(i.rear,i.front)),w=q(H(o,e.pushrodOuter)),C=U(M,-1),T=(Z,ne)=>X(A,ae(H(Z,i.front),ne)),F=T(e.pushrodOuter,w),S=Math.abs(F)>1e-9?-T(i.bj,C)/F:NaN,P=ee(C,U(w,S)),L=U(P,-1),D=q(H(i.front,i.bj)),I=q(H(i.rear,i.bj)),O=X(D,D),_=X(D,I),z=X(I,I),E=X(D,L),N=X(I,L),B=O*z-_*_,V=NaN,G=NaN,K=NaN;if(Math.abs(B)>1e-12){V=(E*z-N*_)/B,G=(O*N-_*E)/B;let Z=ee(U(D,V),U(I,G)),ne=H(L,Z);K=Math.hypot(ne[0],ne[1],ne[2])}let Y=a?{f:k,r:v}:{f:V,r:G},j=a?{f:V,r:G}:{f:k,r:v};return{ucaFront:Y.f,ucaRear:Y.r,lcaFront:j.f,lcaRear:j.r,tieRod:x,pushRod:S,damper:y||!Number.isFinite(S)||e.decoupled?NaN:e.direct?S:iL(e,S),condProxy:g.condProxy,singular:y,armResidual:K}}function iL(e,t){let r=q(H(e.rockerPivotB,e.rockerPivotA)),n=q(H(e.rockerToPushrod,e.pushrodOuter)),o=q(H(e.damperChassis,e.rockerToDamper)),a=Math.abs(X(r,ae(H(e.rockerToPushrod,e.rockerPivotA),n))),s=Math.abs(X(r,ae(H(e.rockerToDamper,e.rockerPivotA),o)));return s<1e-9?0:t*a/s}var Z4=Math.PI/180;function _s(e,t){let r=Math.min(Math.max(t,e.range[0]),e.range[1])-e.reference;return Math.max(.2,1+e.perDegC*r+e.perDegC2*r*r)}var lv=["QSX3","QSX8","QSX13","QSX14"],cL=["QSX1"],Il=["PHY1","PHY2","PHY3","PKY6","PKY7","PVY1","PVY2","PVY3","PVY4","PEY3","PEY4","QHZ1","QHZ2","QHZ3","QHZ4","QEZ4","QEZ5","QDZ6","QDZ7","QDZ8","QDZ9","QDZ10","QDZ11","SSZ1","SSZ3","SSZ4","RBY3","RHX1","RVY1","RVY2","RVY3",...lv];function lL(e){let t=["PKY6","PKY7","PVY3","PVY4","PHY3","PEY4","RVY3","QHZ3","QHZ4","QEZ5","QDZ8","QDZ9","QDZ10","QDZ11","SSZ3","SSZ4"];return e==="5.2"?[...t,"QBZ4","QDZ3"]:t}function uL(e){let t=new Set(lL(e)),r=Il.filter(n=>!lv.includes(n));return[...r.filter(n=>!t.has(n)),...[...t].filter(n=>!r.includes(n)),...cL]}function mL(e,t){let r={...e};for(let n of t)r[n]!==void 0&&r[n]!==0&&(r[n]=-r[n]);return r}var Tr=(e,t,r)=>Number.isFinite(e[t])?e[t]:r;function uv(e,t){return t!=="5.2"?Tr(e,"PKY6",0)*Tr(e,"LKYC",1):Tr(e,"PKY1",-15)*Math.sin(Tr(e,"PKY4",2)*Math.atan(1/Tr(e,"PKY2",2)))*Tr(e,"LKY",1)*Tr(e,"PHY3",0)+Tr(e,"PVY3",0)*Tr(e,"LMUY",1)}var cv=.1;function mv(e){if(e.fitData)return"sae";let t=uv(e.coeffs,e.version);return t>cv?"sae":t<-cv?"iso":null}function Ns(e){return e.axisSystem??mv(e)??"sae"}function _l(e){let t=new Set,r=n=>{for(let o of n)t.has(o)?t.delete(o):t.add(o)};return Ns(e)==="iso"&&r(Il),e.axisSystem&&e.side==="left"&&r(uL(e.version)),t.size?mL(e.coeffs,t):e.coeffs}var eH=Math.PI/180;var $=(e,t)=>Number.isFinite(e)?e:t;function dv(e){let t=_l(e);return{PCX1:$(t.PCX1,1.65),PDX1:$(t.PDX1,1),PDX2:$(t.PDX2,0),PDX3:$(t.PDX3,0),PEX1:$(t.PEX1,0),PEX2:$(t.PEX2,0),PEX3:$(t.PEX3,0),PEX4:$(t.PEX4,0),PHX1:$(t.PHX1,0),PHX2:$(t.PHX2,0),PKX1:$(t.PKX1,20),PKX2:$(t.PKX2,0),PKX3:$(t.PKX3,0),PPX1:$(t.PPX1,0),PPX2:$(t.PPX2,0),PPX3:$(t.PPX3,0),PPX4:$(t.PPX4,0),PVX1:$(t.PVX1,0),PVX2:$(t.PVX2,0),PCY1:$(t.PCY1,1.3),PDY1:$(t.PDY1,1),PDY2:$(t.PDY2,0),PDY3:$(t.PDY3,0),PEY1:$(t.PEY1,0),PEY2:$(t.PEY2,0),PEY3:$(t.PEY3,0),PEY4:$(t.PEY4,0),PEY5:$(t.PEY5,0),PHY1:$(t.PHY1,0),PHY2:$(t.PHY2,0),PHY3:$(t.PHY3,0),PKY1:$(t.PKY1,-15),PKY2:$(t.PKY2,2),PKY3:$(t.PKY3,0),PKY4:$(t.PKY4,2),PKY5:$(t.PKY5,0),PKY6:$(t.PKY6,0),PKY7:$(t.PKY7,0),PPY1:$(t.PPY1,0),PPY2:$(t.PPY2,0),PPY3:$(t.PPY3,0),PPY4:$(t.PPY4,0),PPY5:$(t.PPY5,0),PVY1:$(t.PVY1,0),PVY2:$(t.PVY2,0),PVY3:$(t.PVY3,0),PVY4:$(t.PVY4,0),RBX1:$(t.RBX1,0),RBX2:$(t.RBX2,0),RBX3:$(t.RBX3,0),RBY1:$(t.RBY1,0),RBY2:$(t.RBY2,0),RBY3:$(t.RBY3,0),RBY4:$(t.RBY4,0),RCX1:$(t.RCX1,1),RCY1:$(t.RCY1,1),REX1:$(t.REX1,0),REX2:$(t.REX2,0),REY1:$(t.REY1,0),REY2:$(t.REY2,0),RHX1:$(t.RHX1,0),RHY1:$(t.RHY1,0),RHY2:$(t.RHY2,0),RVY1:$(t.RVY1,0),RVY2:$(t.RVY2,0),RVY3:$(t.RVY3,0),RVY4:$(t.RVY4,0),RVY5:$(t.RVY5,1),RVY6:$(t.RVY6,0),PPZ1:$(t.PPZ1,0),PPZ2:$(t.PPZ2,0),QBZ1:$(t.QBZ1,8),QBZ2:$(t.QBZ2,0),QBZ3:$(t.QBZ3,0),QBZ4:$(t.QBZ4,0),QBZ5:$(t.QBZ5,0),QBZ6:$(t.QBZ6,0),QBZ9:$(t.QBZ9,0),QBZ10:$(t.QBZ10,0),QCZ1:$(t.QCZ1,1.1),QDZ1:$(t.QDZ1,.1),QDZ2:$(t.QDZ2,0),QDZ3:$(t.QDZ3,0),QDZ4:$(t.QDZ4,0),QDZ6:$(t.QDZ6,0),QDZ7:$(t.QDZ7,0),QDZ8:$(t.QDZ8,0),QDZ9:$(t.QDZ9,0),QDZ10:$(t.QDZ10,0),QDZ11:$(t.QDZ11,0),QEZ1:$(t.QEZ1,0),QEZ2:$(t.QEZ2,0),QEZ3:$(t.QEZ3,0),QEZ4:$(t.QEZ4,0),QEZ5:$(t.QEZ5,0),QHZ1:$(t.QHZ1,0),QHZ2:$(t.QHZ2,0),QHZ3:$(t.QHZ3,0),QHZ4:$(t.QHZ4,0),SSZ1:$(t.SSZ1,0),SSZ2:$(t.SSZ2,0),SSZ3:$(t.SSZ3,0),SSZ4:$(t.SSZ4,0),QSX1:$(t.QSX1,0),QSX2:$(t.QSX2,0),QSX3:$(t.QSX3,0),QSX4:$(t.QSX4,0),QSX5:$(t.QSX5,0),QSX6:$(t.QSX6,0),QSX7:$(t.QSX7,0),QSX8:$(t.QSX8,0),QSX9:$(t.QSX9,0),QSX10:$(t.QSX10,0),QSX11:$(t.QSX11,0),QSX12:$(t.QSX12,0),QSX13:$(t.QSX13,0),QSX14:$(t.QSX14,0),PPMX1:$(t.PPMX1,0),QSY1:$(t.QSY1,0),QSY2:$(t.QSY2,0),QSY3:$(t.QSY3,0),QSY4:$(t.QSY4,0),QSY5:$(t.QSY5,0),QSY6:$(t.QSY6,0),QSY7:$(t.QSY7,0),QSY8:$(t.QSY8,0),LONGVL:t.LONGVL!==void 0&&t.LONGVL>0?t.LONGVL:16.7,LCX:$(t.LCX,1),LCY:$(t.LCY,1),LEX:$(t.LEX,1),LEY:$(t.LEY,1),LFZO:$(t.LFZO,1),LHX:$(t.LHX,1),LHY:$(t.LHY,1),LKX:$(t.LKX,1),LKY:$(t.LKY,1),LKYC:$(t.LKYC,1),LKZC:$(t.LKZC,1),LMUX:$(t.LMUX,1),LMUY:$(t.LMUY,1),LMX:$(t.LMX,1),LMY:$(t.LMY,1),LVMX:$(t.LVMX,1),LRES:$(t.LRES,1),LS:$(t.LS,1),LTR:$(t.LTR,1),LVX:$(t.LVX,1),LVY:$(t.LVY,1),LVYKA:$(t.LVYKA,1),LXAL:$(t.LXAL,1),LYKA:$(t.LYKA,1)}}var pv=new WeakMap;function Os(e){let t=pv.get(e);return t===void 0&&(t=dv(e),pv.set(e,t)),t}var fv=e=>e>=0?1:-1;function Nl(e,t,r=0,n){let o=Os(e),a=Math.max(1,t),s=r,i=o.LFZO*e.fnomin,c=(a-i)/i,l=e.nomPressure>0&&n?(n-e.nomPressure)/e.nomPressure:0,u=e.unloadedR0,m=(o.PDY1+o.PDY2*c)*(1+o.PPY3*l+o.PPY4*l*l)*(1-o.PDY3*s*s)*o.LMUY,d=o.PCY1*o.LCY,p=m*a,f=o.PKY1*i*(1+o.PPY1*l)*Math.sin(o.PKY4*Math.atan(a/((o.PKY2+o.PKY5*s*s)*(1+o.PPY2*l)*i)))*(1-o.PKY3*Math.abs(s))*o.LKY,h=e.version!=="5.2",b=a*(o.PKY6+o.PKY7*c)*(1+o.PPY5*l)*o.LKYC,g=a*(o.PVY3+o.PVY4*c)*s*o.LKYC*o.LMUY,y=Math.abs(f)>1e-6?f:1e-6*(f<0?-1:1),R=h?(o.PHY1+o.PHY2*c)*o.LHY+(b*s-g)/y:(o.PHY1+o.PHY2*c)*o.LHY+o.PHY3*s,k=h?a*(o.PVY1+o.PVY2*c)*o.LVY*o.LMUY+g:a*((o.PVY1+o.PVY2*c)*o.LVY+(o.PVY3+o.PVY4*c)*s)*o.LMUY,v=d*p!==0?f/(d*p):0;return{Fz:a,g:s,dfz:c,dpi:l,Fz0p:i,R0:u,Cy:d,Dy:p,By:v,SHy:R,SVy:k,Kya:f,muy:m,EyA:o.PEY1+o.PEY2*c,EyG:1+o.PEY5*s*s,EyS:o.PEY3+o.PEY4*s,LEY:o.LEY}}function Ol(e,t,r=0,n){let o=Nl(e,t,r,n),a=Os(e),{Fz:s,g:i,dfz:c,dpi:l,Fz0p:u,R0:m,muy:d,Kya:p,SVy:f,By:h,Cy:b,Dy:g,SHy:y}=o,R=(a.PHX1+a.PHX2*c)*a.LHX,k=(a.PDX1+a.PDX2*c)*(1+a.PPX3*l+a.PPX4*l*l)*(1-a.PDX3*i*i)*a.LMUX,v=a.PCX1*a.LCX,x=k*s,M=s*(a.PKX1+a.PKX2*c)*Math.exp(a.PKX3*c)*(1+a.PPX1*l+a.PPX2*l*l)*a.LKX,A=v*x!==0?M/(v*x):0,w=Math.abs(p)>1e-6?p:1e-6*(p<0?-1:1),C=e.version!=="5.2",T=s*(a.PVX1+a.PVX2*c)*a.LVX*a.LMUX,F=a.REX1+a.REX2*c;F>1&&(F=1);let S=a.REY1+a.REY2*c;return S>1&&(S=1),{Fz:s,g:i,dfz:c,dpi:l,Fz0p:u,R0:m,Cy:b,Dy:g,By:h,SHy:y,SVy:f,Kya:p,muy:d,EyA:o.EyA,EyG:o.EyG,EyS:o.EyS,LEY:o.LEY,SHx:R,Cx:v,Dx:x,Bx:A,SVx:T,ExA:a.PEX1+a.PEX2*c+a.PEX3*c*c,PEX4:a.PEX4,LEX:a.LEX,SHxa:a.RHX1,Bxa0:a.RBX1+a.RBX3*i*i,RBX2:a.RBX2,LXAL:a.LXAL,Cxa:a.RCX1,Exa:F,SHyk:a.RHY1+a.RHY2*c,Byk0:a.RBY1+a.RBY4*i*i,RBY2:a.RBY2,RBY3:a.RBY3,LYKA:a.LYKA,Cyk:a.RCY1,Eyk:S,DVykA:d*s*(a.RVY1+a.RVY2*c+a.RVY3*i),RVY4:a.RVY4,RVY5:a.RVY5,RVY6:a.RVY6,LVYKA:a.LVYKA,SHt:a.QHZ1+a.QHZ2*c+(a.QHZ3+a.QHZ4*c)*i,Bt:C?(a.QBZ1+a.QBZ2*c+a.QBZ3*c*c)*(1+a.QBZ5*Math.abs(i)+a.QBZ6*i*i)*(a.LKY/a.LMUY):(a.QBZ1+a.QBZ2*c+a.QBZ3*c*c)*(1+a.QBZ4*i+a.QBZ5*Math.abs(i))*(a.LKY/a.LMUY),Ct:a.QCZ1,Dt:C?s*(m/u)*(a.QDZ1+a.QDZ2*c)*(1-a.PPZ1*l)*(1+a.QDZ3*Math.abs(i)+a.QDZ4*i*i)*a.LTR:s*(m/u)*(a.QDZ1+a.QDZ2*c)*(1-a.PPZ1*l)*(1+a.QDZ3*i+a.QDZ4*i*i)*a.LTR,EtA:a.QEZ1+a.QEZ2*c+a.QEZ3*c*c,EtG:a.QEZ4+a.QEZ5*i,Br:a.QBZ9*(a.LKY/a.LMUY)+a.QBZ10*h*b,Dr:C?s*m*((a.QDZ6+a.QDZ7*c)*a.LRES+((a.QDZ8+a.QDZ9*c)*(1+a.PPZ2*l)+(a.QDZ10+a.QDZ11*c)*Math.abs(i))*i*a.LKZC)*a.LMUY:s*m*((a.QDZ6+a.QDZ7*c)*a.LRES+(a.QDZ8+a.QDZ9*c)*(1+a.PPZ2*l)*i)*a.LMUY,arOff:p!==0?f/p:0,sixOne:C,kk:M/w*(M/w),sS0:m*(a.SSZ1+(a.SSZ3+a.SSZ4*c)*i)*a.LS,sS2:m*a.SSZ2*a.LS/u}}function Vs(e,t){let r=t+e.SHy,n=e.EyA*(e.EyG-e.EyS*fv(r))*e.LEY;n>1&&(n=1);let o=e.By*r;return e.Dy*Math.sin(e.Cy*Math.atan(o-n*(o-Math.atan(o))))+e.SVy}function Vl(e,t){let r=t+e.SHx,n=e.ExA*(1-e.PEX4*fv(r))*e.LEX;n>1&&(n=1);let o=e.Bx*r;return e.Dx*Math.sin(e.Cx*Math.atan(o-n*(o-Math.atan(o))))+e.SVx}function hv(e,t,r){if(r===0)return t;if(e.sixOne)return Math.sqrt(t*t+e.kk*r*r)*Math.sign(t);let n=Math.tan(t);return Math.atan(Math.sqrt(n*n+e.kk*r*r))*Math.sign(t)}function pL(e,t,r,n){let o=t+e.SHt,a=e.EtA*(1+e.EtG*(2/Math.PI)*Math.atan(e.Bt*e.Ct*o));a>1&&(a=1);let s=hv(e,o,r),i=e.Bt*s;return e.Dt*Math.cos(e.Ct*Math.atan(i-a*(i-Math.atan(i))))*n}function dL(e,t,r,n){return e.Dr*Math.cos(Math.atan(e.Br*hv(e,t+e.SHy+e.arOff,r)))*n}function bv(e,t,r,n,o,a){let s=Math.cos(t),i=pL(e,t,r,s),c=dL(e,t,r,s);return-i*(o-a)+c+(e.sS0+e.sS2*o)*n}function gv(e,t,r){let n=e.Bxa0*Math.cos(Math.atan(e.RBX2*t))*e.LXAL,o=r+e.SHxa,a=Math.cos(e.Cxa*Math.atan(n*e.SHxa-e.Exa*(n*e.SHxa-Math.atan(n*e.SHxa))))||1;return Math.cos(e.Cxa*Math.atan(n*o-e.Exa*(n*o-Math.atan(n*o))))/a*Vl(e,t)}function _f(e,t){let r=e.sS0===0&&e.sS2===0?0:gv(e,0,t);return bv(e,t,0,r,Vs(e,t),0)}function Bl(e,t,r){let n=Vs(e,r),o=gv(e,t,r),a=e.Byk0*Math.cos(Math.atan(e.RBY2*(r-e.RBY3)))*e.LYKA,s=t+e.SHyk,i=Math.cos(e.Cyk*Math.atan(a*e.SHyk-e.Eyk*(a*e.SHyk-Math.atan(a*e.SHyk))))||1,c=Math.cos(e.Cyk*Math.atan(a*s-e.Eyk*(a*s-Math.atan(a*s))))/i,u=e.DVykA*Math.cos(Math.atan(e.RVY4*r))*Math.sin(e.RVY5*Math.atan(e.RVY6*t))*e.LVYKA,m=c*n+u;return{Fx:o,Fy:m,Mz:bv(e,r,t,o,m,u)}}var Bs=(e,t)=>Math.max(.1,e.muY0+e.loadSensY*(t-e.nominalLoad)),$s=(e,t)=>Math.max(.1,e.muX0+e.loadSensX*(t-e.nominalLoad)),yv=(e,t,r)=>Bs(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cy*Math.atan(e.By*r)),xv=(e,t,r)=>$s(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cx*Math.atan(e.Bx*r));function Nf(e,t){let r=Math.max(1,t.Fz),n=Bs(e,r)*r,o=$s(e,r)*r,a=n*Math.sin(e.Cy*Math.atan(e.By*t.alpha)),s=o*Math.sin(e.Cx*Math.atan(e.Bx*t.kappa)),i=Math.hypot(o>0?s/o:0,n>0?a/n:0);return i>1&&(s/=i,a/=i),{Fx:s,Fy:a,Mz:0}}var la=Math.PI/180;function pn(e){if(e.kind==="simple")return"none";let t=e.missing?.some(n=>/^aligning moment Mz\b/i.test(n))??!1,r=["QBZ1","QCZ1","QDZ1"].every(n=>Number.isFinite(e.coeffs[n]));return t||!r?"assumed":"model"}function Rv(e){let t=e.thermal?.operating;if(t===void 0||!e.thermal)return e;let{lateral:r,longitudinal:n,aligning:o}=e.thermal,a=r?_s(r,t):1,s=n?_s(n,t):1,i=o?_s(o,t):1;if(a===1&&s===1&&i===1)return e;if(e.kind==="simple")return{...e,muY0:e.muY0*a,muX0:e.muX0*s};let c={...e.coeffs},l=(u,m)=>{c[u]=(c[u]??1)*m};return l("LMUY",a),l("LMUX",s),l("LTR",i),l("LRES",i),{...e,coeffs:c}}function ua(e,t,r){let n=0,o=0;for(let s=r;s<=t;s+=r){let i=Math.abs(e(s));i>o&&(o=i,n=s)}let a=r/10;for(let s=Math.max(a,n-r);s<=n+r;s+=a)o=Math.max(o,Math.abs(e(s)));return o}function Pe(e){let t=Rv(e),r=t,n=t,o=null,a=NaN,s=NaN,i=NaN,c=(v,x,M)=>(o!==null&&v===a&&x===s&&M===i||(o=Ol(r,v,x,M),a=v,s=x,i=M),o),l=null,u=NaN,m=NaN,d=NaN,p=(v,x,M)=>(l!==null&&v===u&&x===m&&M===d||(l=Nl(r,v,x,M),u=v,m=x,d=M),l),f=v=>e.kind==="magic"?Bl(c(v.Fz,v.gamma??0,v.p),v.kappa,v.alpha):Nf(n,v),h=(v,x,M=0,A)=>e.kind==="magic"?Vs(p(x,M,A),v):yv(n,x,v),b=(v,x,M=0,A)=>e.kind==="magic"?Vl(c(x,M,A),v):xv(n,x,v),g=(v,x,M=0,A)=>e.kind==="magic"?_f(c(x,M,A),v):f({Fz:x,kappa:0,alpha:v,gamma:M,p:A}).Mz,y=v=>e.kind==="simple"?Bs(n,v):ua(x=>h(x*la,v),45,1)/Math.max(1,v),R=v=>e.kind==="simple"?$s(n,v):ua(x=>b(x,v),.6,.02)/Math.max(1,v),k=v=>{let x=.1*la;return Math.abs((h(x,v)-h(-x,v))/(2*x))};return{model:e,forces:f,Fx:b,Fy:h,Mz:g,muX:R,muY:y,corneringStiffness:k,verticalStiffness:()=>e.verticalStiffness,rollingRadius:v=>{if(e.kind==="magic"&&e.missing?.includes("UNLOADED_RADIUS"))return 0;let x=e.unloadedR0??0;if(!(x>0))return 0;let M=e.verticalStiffness*1e3;if(!(M>0))return x;let A=e.rollingFraction??.306;return x-A*Math.max(0,v)/M},relaxationLength:v=>{let x=e.relaxation;if(!x)return 0;let M=x.carcassStiffness??0;if(!(M>0))return x.sigma;let A=k(Math.max(0,v));return A>0?A/(M*1e3):x.sigma}}}function ma(e){let t=Math.max(1,e.model.kind==="magic"?e.model.fnomin:e.model.nominalLoad);return e.Fy(2*la,t,0)-e.Fy(-2*la,t,0)>=0?1:-1}function Gs(e,t=e.kind==="magic"?e.fnomin:e.nominalLoad){let r=Pe(e),n=2*la,o=3*la,a=r.Fy(n,t,0),s=r.Fy(n,t,o);return!Number.isFinite(a)||!Number.isFinite(s)?!1:Math.abs(s-a)>1}var fL=Math.PI/180;function ye(e,t){return e.axle?e.axle(t):e}function Gl(e,t){if(e===t)return e;let r=ma(e)*ma(t),n=(l,u)=>.5*(l+u),o=(l,u)=>l>0&&u>0?n(l,u):l>0?l:u>0?u:0,a=l=>{let u=e.forces(l),m=t.forces(l);return{Fx:n(u.Fx,m.Fx),Fy:n(u.Fy,r*m.Fy),Mz:n(u.Mz,r*m.Mz)}},s=(l,u,m=0,d)=>n(e.Fx(l,u,m,d),t.Fx(l,u,m,d)),i=(l,u,m=0,d)=>n(e.Fy(l,u,m,d),r*t.Fy(l,u,m,d)),c=(l,u,m=0,d)=>n(e.Mz(l,u,m,d),r*t.Mz(l,u,m,d));return{model:e.model,forces:a,Fx:s,Fy:i,Mz:c,muX:l=>ua(u=>s(u,l),.6,.02)/Math.max(1,l),muY:l=>ua(u=>i(u*fL,l),45,1)/Math.max(1,l),corneringStiffness:l=>n(e.corneringStiffness(l),t.corneringStiffness(l)),verticalStiffness:()=>o(e.verticalStiffness(),t.verticalStiffness()),rollingRadius:l=>o(e.rollingRadius(l),t.rollingRadius(l)),relaxationLength:l=>o(e.relaxationLength(l),t.relaxationLength(l)),axle:l=>l==="front"?e:t}}function pt(e){if(vv.has(e))return e;let t=kv.get(e);if(t)return t;let r;if(e.axle){let n=e.axle("front"),o=e.axle("rear"),a=pt(n),s=pt(o);r=a===n&&s===o?e:Gl(a,s)}else ma(e)>0?r=e:r={...e,forces:n=>{let o=e.forces(n);return{Fx:o.Fx,Fy:-o.Fy,Mz:-o.Mz}},Fy:(n,o,a,s)=>-e.Fy(n,o,a,s),Mz:(n,o,a,s)=>-e.Mz(n,o,a,s)};return vv.add(r),r!==e&&kv.set(e,r),r}var vv=new WeakSet,kv=new WeakMap;var Kl=25*(Math.PI/180);function hL(e){let t=.6180339887,r=0,n=Kl,o=n-t*(n-r),a=r+t*(n-r),s=e(o),i=e(a);for(let l=0;l<12;l++)s>i?(n=a,a=o,i=s,o=n-t*(n-r),s=e(o)):(r=o,o=a,s=i,a=r+t*(n-r),i=e(a));return{alpha:s>i?o:a,force:Math.max(s,i)}}function Ks(e,t,r,n,o=0){let a=Math.abs(t);if(!(a>0))return 0;let s=u=>Math.abs(e.Fy(u,r,0))+Math.abs(e.Fy(u,n,0)),i=0,c=Kl;if(s(Kl)<=a){let u=hL(s);if(u.force<=a)return u.alpha;c=u.alpha}else if(o>0){let u=Math.max(0,o*.6),m=Math.min(Kl,o*1.6+.001);s(u)<a&&s(m)>=a&&(i=u,c=m)}let l=.001*a;for(let u=0;u<12;u++){let m=.5*(i+c),d=s(m)-a;if(d<0?i=m:c=m,Math.abs(d)<=l)return m}return c}var Of={shaft:!1,trail:0,hub:[0,0,0]};function Sv(e){let t=e.spinAxis,r=Math.hypot(t[0],t[1]);if(r<1e-9)return[1,0,0];let n=[-t[1]/r,t[0]/r,0];return n[0]<0?[-n[0],-n[1],0]:n}function Vf(e,t,r){let n=r.shaft?If(e,t):[0,0,0];if(r.trail!==0){let a=Sv(e),s=[t[0],t[1],0],i=H(s,U(a,X(s,a)));n=ee(n,ae(U(a,-r.trail),i))}let o=r.hub;return(o[0]!==0||o[1]!==0||o[2]!==0)&&(n=H(n,ae(H(e.contactPatch,e.wheelCenter),o))),{force:ee(t,o),moment:n}}var bL=(e,t)=>{let r=e!==void 0&&e>0?1/e:0,n=t!==void 0&&t>0?1/t:0;return r+n},Hl={ucaFront:0,ucaRear:0,lcaFront:0,lcaRear:0,tieRod:0,pushRod:0,rack:0};function Hn(e){return!e.measured}function zn(e){if(!e)return!1;let t=r=>!!r&&Object.values(r).some(n=>n!==void 0&&n>0&&Number.isFinite(n));return t(e.links)||t(e.bushings)||e.rack!==void 0&&e.rack>0}function Hs(e,t){let r=e.corner.hardpoints,n=Xo(e.rocker,t.points.rockerAngle);return{ucaFront:r.ucaFront,ucaRear:r.ucaRear,lcaFront:r.lcaFront,lcaRear:r.lcaRear,tieInner:Vn(e.inv,t.steer),rockerPivotA:r.rockerPivotA,rockerPivotB:r.rockerPivotB,damperChassis:e.inv.strut?t.points.uprightUpper:r.damperChassis,uprightUpper:t.points.uprightUpper,uprightLower:t.points.uprightLower,tieOuter:t.points.tieOuter,wheelCenter:t.points.wheelCenter,pushrodOuter:t.points.pushrodOuter,contactPatch:t.points.contactPatch,kingpinGround:t.points.kingpinGround,kingpinAtHub:t.points.kingpinAtHub,rockerToPushrod:n.pushrod,rockerToDamper:n.damper,spinAxis:t.points.spinAxis,direct:e.corner.config.actuation==="direct",decoupled:e.corner.config.actuation==="decoupled",mcpherson:e.inv.strut!==void 0,loadedRadius:e.corner.config.loadedRadius,tyreDeflection:0,load:NaN,lifted:!1,clearance:0,contactLength:0}}function Bf(e,t,r=0){let n=t.links??{},o=t.bushings??{},a=(l,u,m)=>{let d=bL(u,m);return d>0&&Number.isFinite(l)?l*d:0},s=o.topMount,i=e.topMount,c=i&&s!==void 0&&s>0&&i.every(Number.isFinite)?[-i[0]/s,-i[1]/s,-i[2]/s]:void 0;return{...c?{topMount:c}:{},ucaFront:a(e.ucaFront,n.ucaFront,o.ucaFront),ucaRear:a(e.ucaRear,n.ucaRear,o.ucaRear),lcaFront:a(e.lcaFront,n.lcaFront,o.lcaFront),lcaRear:a(e.lcaRear,n.lcaRear,o.lcaRear),tieRod:a(e.tieRod,n.tieRod,o.tieInner),pushRod:a(e.pushRod,n.pushRod,void 0),rack:r}}function Av(e,t,r,n){let o=ve(e,t);if(!(o>1e-9))return{axial:r,radius2:0};let a=(r*r-n*n+o*o)/(2*o);return{axial:a,radius2:Math.max(0,r*r-a*a)}}function zs(e,t){let r=e.corner.hardpoints,n=e.inv,o={...n};if(n.strut&&t.topMount&&t.topMount.some(i=>i!==0)&&(o.strut={...n.strut,top:ee(n.strut.top,t.topMount)}),t.ucaFront!==0||t.ucaRear!==0){let i=Av(r.ucaFront,r.ucaRear,ve(r.uprightUpper,r.ucaFront)+t.ucaFront,ve(r.uprightUpper,r.ucaRear)+t.ucaRear);o.ubjAxial0=i.axial,o.ubjRadius2=i.radius2}if(t.lcaFront!==0||t.lcaRear!==0){let i=Av(r.lcaFront,r.lcaRear,ve(r.uprightLower,r.lcaFront)+t.lcaFront,ve(r.uprightLower,r.lcaRear)+t.lcaRear),c=X(n.lbjRel0,n.lcaDir),l=H(n.lbjRel0,U(n.lcaDir,c)),u=Math.hypot(l[0],l[1],l[2]);o.lbjRel0=u>1e-9?ee(U(n.lcaDir,i.axial),U(l,Math.sqrt(i.radius2)/u)):ee(U(n.lcaDir,i.axial),l)}if(t.tieRod!==0){let i=Math.sqrt(n.tieLen2)+t.tieRod;o.tieLen2=i*i}if(t.rack!==0&&(o.tieInner0=ee(n.tieInner0,U(n.rackAxis,t.rack))),t.pushRod===0)return{corner:e.corner,inv:o,rocker:e.rocker};let a=Math.sqrt(e.rocker.rodLen2)+t.pushRod,s={...e.rocker,rodLen2:a*a};return{corner:e.corner,inv:o,rocker:s}}var gL=8,yL=1e-5,xL=e=>({q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle});function $f(e,t,r){let n=Vf(e,r.force,r.extras??Of),o=r.alignMoment?ee(n.moment,[0,0,r.alignMoment]):n.moment;return Is(e,t,n.force,o)}function Yl(e,t,r,n,o,a,s=0){let i=Ie(e,t,r,o,a),c=e.corner.compliance;if(!(zn(c)&&Hn(e.corner)))return{state:i,forces:$f(Hs(e,i),e.corner.config.pushrodAttach,n),deflection:Hl,rigid:i,iterations:0,converged:!0,bypassed:!0};let u=i,m=e,d=e.corner.config.pushrodAttach,p=$f(Hs(e,i),d,n),f=Hl,h=!1,b=0;for(;b<gL;b++){let g=Hs(m,u);if(p=$f(g,d,n),p.singular)break;f=Bf(p,c,s),m=zs(e,f);let y=Ie(m,t,r,xL(u),a),R=ve(y.points.wheelCenter,u.points.wheelCenter);if(u=y,R<yL){h=!0;break}}return{state:u,forces:p,deflection:f,rigid:i,iterations:b+1,converged:h&&u.converged,bypassed:!1}}var zl=1e3,Fv=1e5;function wv(e,t,r,n,o){let a=Yl(e,t,r,n,void 0,o);return{toe:a.state.metrics.toe,camber:a.state.metrics.camber,patch:a.state.points.contactPatch,converged:a.converged,bypassed:a.bypassed}}function Wl(e,t,r,n,o){let a={force:[0,0,n]},s=(b,g=0)=>wv(e,t,r,{force:b,alignMoment:g},o),i=wv(e,t,r,a,o);if(i.bypassed)return{toePerLateral:0,camberPerLateral:0,toePerLongitudinal:0,camberPerLongitudinal:0,toePerAligning:0,lateralPatch:0,longitudinalPatch:0,bypassed:!0,converged:!0};let c=s([0,zl,n]),l=s([0,-zl,n]),u=s([zl,0,n]),m=s([-zl,0,n]),d=s([0,0,n],Fv),p=s([0,0,n],-Fv),f=(b,g)=>(b-g)/2,h=[i,c,l,u,m,d,p].every(b=>b.converged);return{toePerLateral:f(c.toe,l.toe),camberPerLateral:f(c.camber,l.camber),toePerLongitudinal:f(u.toe,m.toe),camberPerLongitudinal:f(u.camber,m.camber),toePerAligning:f(d.toe,p.toe),lateralPatch:f(c.patch[1],l.patch[1]),longitudinalPatch:f(u.patch[0],m.patch[0]),bypassed:!1,converged:h}}var RL=1e3;function Gf(e,t=RL){if(!zn(e.compliance)||!Hn(e))return;let r=tt(e),n=Ie(r,0,0),o=Wl(r,n.beta,0,t);if(!o.bypassed)return{toePerFy:o.toePerLateral/1e3,camberPerFy:o.camberPerLateral/1e3,toePerFx:o.toePerLongitudinal/1e3,camberPerFx:o.camberPerLongitudinal/1e3,toePerMz:o.toePerAligning/1e5}}function pa(e,t=-Ef,r=Ef,n=21){let o=e.measured;if(o)return{travel:[...o.travel],motionRatio:[...o.motionRatio],camber:[...o.camber],toe:[...o.toe],damperLen:o.damperLen?[...o.damperLen]:o.travel.map(()=>0)};let a=Ke(e,{travelMin:t,travelMax:r,steps:n}),s=Gf(e);return{travel:a.samples.map(i=>i.travel),motionRatio:a.samples.map(i=>i.metrics.motionRatio??1),camber:a.samples.map(i=>i.metrics.camber),toe:a.samples.map(i=>i.metrics.toe),damperLen:a.samples.map(i=>i.metrics.damperLength),...s?{compliance:s}:{}}}function jl(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function dn(e,t){return{motionRatio:jl(e.travel,e.motionRatio,t),camber:jl(e.travel,e.camber,t),toe:jl(e.travel,e.toe,t),damperLen:jl(e.travel,e.damperLen,t)}}var Cv=Math.PI/180,vL=9.81;function fn(e,t,r,n=0){let o=we(e),a=e.wheelbase*(1-e.frontMassFrac),s=e.wheelbase*e.frontMassFrac,i=ia(e,n),c=e.aero?.model?(k,v,x)=>ia(e,n,v,k,x):()=>i,l=dn(t,0),u=dn(r,0),m=e.loadFactor,d=m!==void 0&&m!==1?(m-1)*e.massTotal*vL:0,p=d*e.frontMassFrac/2,f=d*(1-e.frontMassFrac)/2,h=(k,v)=>v>0&&Number.isFinite(v)&&k+v>0?v/(k+v):1,b=Xe(e,"front"),g=Xe(e,"rear"),y={F:h(e.wheelRateFront+(e.heaveSpringFront??0),b),R:h(e.wheelRateRear+(e.heaveSpringRear??0),g)},R={F:h(e.wheelRateFront+e.arbFront,b),R:h(e.wheelRateRear+e.arbRear,g)};return(k,v,x=0,M=0)=>{let A=c(k,v,x),w=o.rollGradient*k,C=w*Cv,T=o.pitchGradient*v*Cv,F=(O,_)=>{let z=_==="F"?e.trackFront:e.trackRear,E=_==="F"?o.rideRateFront:o.rideRateRear,N=(O==="R"?1:-1)*(z/2)*Math.tan(C),B=(_==="R"?s:-a)*Math.tan(T),V=`${_}${O}`,G=d?A[V]+(_==="F"?p:f):A[V],K=E>0?G/E:0;return{anti:N,sym:B+K}},S={FL:F("L","F"),FR:F("R","F"),RL:F("L","R"),RR:F("R","R")},P=O=>{let _=O[0];return S[O].sym*y[_]+S[O].anti*R[_]},L=sa(e,M,o,{FL:P("FL"),FR:P("FR")}),D=w+L.rollDeg,I=(O,_)=>{let z=_==="F"?t:r,E=_==="F"?l:u,N=`${_==="F"?"F":"R"}${O}`,B=S[N].sym+S[N].anti+L.travel[N],V=P(N)+L.travel[N]*R[_],G=B-V,K=dn(z,V),Y=(O==="R"?1:-1)*K.camber;return{travel:V,tyre:G,ground:B,camber:Y,camberRoad:Y+D,toe:K.toe,bumpToe:K.toe-E.toe,damperTravel:E.damperLen-K.damperLen}};return{FL:I("L","F"),FR:I("R","F"),RL:I("L","R"),RR:I("R","R"),steeringJacking:L}}}var Kf=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function Yn(e){return{enabled:e?.enabled===!0,roadFeedbackGain:Math.min(2,Math.max(0,Kf(e?.roadFeedbackGain,1))),turnInFrictionNm:Math.max(0,Kf(e?.turnInFrictionNm,0)),columnStiffnessNmPerRad:Math.max(0,Kf(e?.columnStiffnessNmPerRad,0))}}function Hf(e,t,r){let n=Yn(r);if(!n.enabled)return{roadNm:e,assistanceNm:0,frictionNm:0,columnTwistDeg:0,driverNm:e};let o=e*(n.roadFeedbackGain-1),a=t===0?0:Math.sign(t)*n.turnInFrictionNm,s=e+o+a,i=n.columnStiffnessNmPerRad>0?s/n.columnStiffnessNmPerRad*(180/Math.PI):0;return{roadNm:e,assistanceNm:o,frictionNm:a,columnTwistDeg:i,driverNm:s}}var Tv=()=>({totalNm:0,aligningNm:0,lateralNm:0,longitudinalNm:0,jackingNm:0});function Wn(e){let t=e.steerFront;return!!(t?.rackRatioMmPerRev&&t.innerJacobian&&t.innerJacobian.length>=2&&t.outerJacobian&&t.outerJacobian.length>=2&&t.meanDeg.length>=2)}function Ys(e,t,r,n="model",o){let a=e.steerFront;if(!Wn(e)||!a)return null;let s=t<0?-1:1,c=a.rackRatioMmPerRev/(2*Math.PI)/1e3,l=t>=0,u=o&&a.travelSurface?oa(a,Math.abs(t),l?o.FL:o.FR,l?o.FR:o.FL):aa(a,Math.abs(t));if(!u.innerJacobian||!u.outerJacobian)return null;let m=(b,g)=>{let y=r[b],R=b==="FL"?-1:1,k=-R*y.Fy,x={aligning:1e3*(-R*y.Mz)*g.yaw,lateral:k*g.lateral,longitudinal:y.Fx*g.longitudinal,jacking:y.Fz*g.vertical},M=Tv();M.aligningNm=-s*x.aligning*c,M.lateralNm=-s*x.lateral*c,M.longitudinalNm=-s*x.longitudinal*c,M.jackingNm=-s*x.jacking*c,M.totalNm=M.aligningNm+M.lateralNm+M.longitudinalNm+M.jackingNm;let A=-s*(x.aligning+x.lateral+x.longitudinal+x.jacking);return{moment:M,rackN:A}},d=m("FL",l?u.innerJacobian:u.outerJacobian),p=m("FR",l?u.outerJacobian:u.innerJacobian),f=Tv();for(let b of[d.moment,p.moment])f.aligningNm+=b.aligningNm,f.lateralNm+=b.lateralNm,f.longitudinalNm+=b.longitudinalNm,f.jackingNm+=b.jackingNm,f.totalNm+=b.totalNm;let h=Hf(f.totalNm,t,e.steeringSystem);return f.totalNm=h.driverNm,{...f,roadNm:h.roadNm,assistanceNm:h.assistanceNm,frictionNm:h.frictionNm,columnTwistDeg:h.columnTwistDeg,rackForceN:d.rackN+p.rackN,aligningSource:n,perWheel:{FL:d.moment,FR:p.moment}}}var kL=e=>"front"in e&&"rear"in e;function da(e,t){return kL(e)?e[t]:e}function Yf(e,t,r=24){let n=Math.max(1,t),o=n/Math.max(1,r-1),a=[],s=[],i=[];for(let l=0;l<r;l++){let u=l*o;a.push(u),s.push(e.muX(u)),i.push(e.muY(u))}let c=(l,u)=>{if(!(u>0))return l[0];if(u>=n)return l[r-1];let m=Math.min(r-2,Math.floor(u/o)),d=(u-a[m])/o;return l[m]+d*(l[m+1]-l[m])};return{muX:l=>c(s,l),muY:l=>c(i,l)}}function zf(e,t){let r=Math.max(0,t.Fz),n=e.muY(r)*r,o=e.muX(r)*r;if(!(n>0))return{fyUsed:0,fyMax:0,fyRes:0};let a=o>0?Math.min(1,Math.abs(t.Fx)/o):0,s=n*Math.sqrt(Math.max(0,1-a*a)),i=Math.abs(t.Fy);return{fyUsed:i,fyMax:s,fyRes:Math.max(0,s-i)}}function Pv(e,t,r){let n=zf(e,t),o=zf(e,r);return{left:n,right:o,fyRes:n.fyRes+o.fyRes}}function Pr(e,t,r){let n=Pv(da(e,"front"),t.FL,t.FR),o=Pv(da(e,"rear"),t.RL,t.RR),a=r.lf>0&&Number.isFinite(r.lf)?r.lf:0,s=r.lr>0&&Number.isFinite(r.lr)?r.lr:0,i=o.fyRes*s,c=n.fyRes*a,l=i-c,u=Math.max(Math.abs(i),Math.abs(c));return{stabil:i,agil:c,diff:l,rel:u>0?l/u:0,front:n,rear:o}}var Ws=[{q:"p",section:"INFLATION_PRESSURE_RANGE",min:"PRESMIN",max:"PRESMAX",what:"pressure"},{q:"fz",section:"VERTICAL_FORCE_RANGE",min:"FZMIN",max:"FZMAX",what:"load"},{q:"kappa",section:"LONG_SLIP_RANGE",min:"KPUMIN",max:"KPUMAX",what:"slip ratio"},{q:"alpha",section:"SLIP_ANGLE_RANGE",min:"ALPMIN",max:"ALPMAX",what:"slip angle"},{q:"gamma",section:"INCLINATION_ANGLE_RANGE",min:"CAMMIN",max:"CAMMAX",what:"inclination"}],SL=Ws.flatMap(e=>[e.min,e.max]);function AL(e){let t={};for(let r of Ws){let n=e[r.min],o=e[r.max],a={};Number.isFinite(n)&&(a.min=n),Number.isFinite(o)&&(a.max=o),(a.min!==void 0||a.max!==void 0)&&(t[r.q]=a)}return Object.keys(t).length?t:void 0}function Ul(e){if(e.kind==="magic")return e.range??AL(e.coeffs)}function Wf(e){return Math.max(1,e.kind==="magic"?e.fnomin:e.nominalLoad)}function Lv(e,t,r,n,o){let a=(r-t)/n,s=t,i=e(t);for(let c=t+a;c<=r;c+=a){let l=e(c);o(l,i)&&(i=l,s=c)}return s}function Xt(e){let t=Dv.get(e);if(t!==void 0)return t;let r=10*Wf(e.model),{turnover:n,collapse:o}=wL(e,r),a=n??o??r;return Dv.set(e,a),a}var Dv=new WeakMap;function wL(e,t){let r=Wf(e.model),n=m=>e.muY(m),o=m=>n(m)*m,a=80,s=t/a,i=null,c=o(s);for(let m=2;m<=a;m++){let d=o(m*s);if(d<c){i=Lv(o,(m-2)*s,m*s,20,(p,f)=>p>f);break}c=d}let l=null,u=n(s);for(let m=2;m<=a;m++){let d=n(m*s);if(d>u){let p=Lv(n,(m-2)*s,m*s,40,(f,h)=>f<h);n(p)<.05*n(r)&&(l=p);break}u=d}return{turnover:i,collapse:l}}var Ev=.1;function Xl(e,t=Wf(e)){let r=Pe(e).muX(t);return{muX:r,none:Number.isFinite(r)&&r<Ev}}var Iv=["FL","FR","RL","RR"],CL=e=>e==="FL"||e==="RL",TL=e=>e==="FL"||e==="FR"?"front":"rear";function ql(e,t,r,n){if(!(e.full>e.open)||n.ayDir===0)return e.full;let o=n.halfTrack[e.axle],a={};for(let l of Iv)a[l]={...t[l]};let s=l=>{let u=0;for(let d of Iv)TL(d)===e.axle&&(a[d].Fx=e.sense*(d===e.strong?l-e.open/2:e.open/2),u-=(CL(d)?o:-o)*a[d].Fx);let m=Pr(r,a,n.arms);return u*n.ayDir>=0?Math.abs(u)<=m.stabil:Math.abs(u)<=m.agil};if(s(e.full))return e.full;let i=e.open,c=e.full;for(let l=0;l<20&&c-i>.001*e.full;l++){let u=.5*(i+c);s(u)?i=u:c=u}return i}var PL=[["PCY1","Shape factor Cfy for lateral forces",1.3],["PDY1","Lateral friction Muy",1],["PDY2","Variation of friction Muy with load",0],["PDY3","Variation of friction Muy with squared camber",0],["PEY1","Lateral curvature Efy at Fznom",0],["PEY2","Variation of curvature Efy with load",0],["PEY3","Zero order camber dependency of curvature Efy",0],["PEY4","Variation of curvature Efy with camber",0],["PEY5","Variation of curvature Efy with camber squared",0],["PKY1","Maximum value of stiffness Kfy/Fznom",-15],["PKY2","Load at which Kfy reaches maximum value",2],["PKY3","Variation of Kfy/Fznom with camber",0],["PKY4","Curvature of stiffness Kfy",2],["PKY5","Peak stiffness variation with camber squared",0],["PKY6","Fy camber stiffness factor",0],["PKY7","Vertical load dependency of camber stiffness",0],["PHY1","Horizontal shift Shy at Fznom",0],["PHY2","Variation of shift Shy with load",0],["PHY3","Variation of shift Shy with camber",0],["PVY1","Vertical shift in Svy/Fz at Fznom",0],["PVY2","Variation of shift Svy/Fz with load",0],["PVY3","Variation of shift Svy/Fz with camber",0],["PVY4","Variation of shift Svy/Fz with camber and load",0],["PPY1","Influence of inflation pressure on cornering stiffness",0],["PPY2","Influence of inflation pressure on dependency of nominal tyre load on cornering stiffness",0],["PPY3","Linear influence of inflation pressure on lateral peak friction",0],["PPY4","Quadratic influence of inflation pressure on lateral peak friction",0],["PPY5","Influence of inflation pressure on camber stiffness",0]],LL=[["PCX1","Shape factor Cfx for longitudinal force",1.65],["PDX1","Longitudinal friction Mux at Fznom",1],["PDX2","Variation of friction Mux with load",0],["PDX3","Variation of friction Mux with camber squared",0],["PEX1","Longitudinal curvature Efx at Fznom",0],["PEX2","Variation of curvature Efx with load",0],["PEX3","Variation of curvature Efx with load squared",0],["PEX4","Factor in curvature Efx while driving",0],["PKX1","Longitudinal slip stiffness Kfx/Fz at Fznom",20],["PKX2","Variation of slip stiffness Kfx/Fz with load",0],["PKX3","Exponent in slip stiffness Kfx/Fz with load",0],["PHX1","Horizontal shift Shx at Fznom",0],["PHX2","Variation of shift Shx with load",0],["PVX1","Vertical shift Svx/Fz at Fznom",0],["PVX2","Variation of shift Svx/Fz with load",0],["PPX1","Linear influence of inflation pressure on longitudinal slip stiffness",0],["PPX2","Quadratic influence of inflation pressure on longitudinal slip stiffness",0],["PPX3","Linear influence of inflation pressure on peak longitudinal friction",0],["PPX4","Quadratic influence of inflation pressure on peak longitudinal friction",0]],DL=[["QBZ1","Trail slope factor for trail Bpt at Fznom",8],["QBZ2","Variation of slope Bpt with load",0],["QBZ3","Variation of slope Bpt with load squared",0],["QBZ4","Variation of slope Bpt with camber",0],["QBZ5","Variation of slope Bpt with absolute camber",0],["QBZ6","Camber influence Bt",0],["QBZ9","Factor for scaling factors of slope factor Br of Mzr",0],["QBZ10","Factor for dimensionless cornering stiffness of Br of Mzr",0],["QCZ1","Shape factor Cpt for pneumatic trail",1.1],["QDZ1","Peak trail Dpt = Dpt*(Fz/Fznom*R0)",.1],["QDZ2","Variation of peak Dpt with load",0],["QDZ3","Variation of peak Dpt with camber",0],["QDZ4","Variation of peak Dpt with camber squared",0],["QDZ6","Peak residual torque Dmr = Dmr/(Fz*R0)",0],["QDZ7","Variation of peak factor Dmr with load",0],["QDZ8","Variation of peak factor Dmr with camber",0],["QDZ9","Variation of peak factor Dmr with camber and load",0],["QDZ10","Variation of peak factor Dmr with camber squared",0],["QDZ11","Variation of Dmr with camber squared and load",0],["QEZ1","Trail curvature Ept at Fznom",0],["QEZ2","Variation of curvature Ept with load",0],["QEZ3","Variation of curvature Ept with load squared",0],["QEZ4","Variation of curvature Ept with sign of Alpha-t",0],["QEZ5","Variation of Ept with camber and sign Alpha-t",0],["QHZ1","Trail horizontal shift Sht at Fznom",0],["QHZ2","Variation of shift Sht with load",0],["QHZ3","Variation of shift Sht with camber",0],["QHZ4","Variation of shift Sht with camber and load",0],["PPZ1","Effect of inflation pressure on length of pneumatic trail",0],["PPZ2","Influence of inflation pressure on residual aligning torque",0],["SSZ1","Nominal value of s/R0: effect of Fx on Mz",0],["SSZ2","Variation of distance s/R0 with Fy/Fznom",0],["SSZ3","Variation of distance s/R0 with camber",0],["SSZ4","Variation of distance s/R0 with load and camber",0]],EL=[["RBX1","Slope factor for combined slip Fx reduction",0],["RBX2","Variation of slope Fx reduction with kappa",0],["RBX3","Influence of camber on stiffness for Fx combined",0],["RCX1","Shape factor for combined slip Fx reduction",1],["REX1","Curvature factor of combined Fx",0],["REX2","Curvature factor of combined Fx with load",0],["RHX1","Shift factor for combined slip Fx reduction",0],["RBY1","Slope factor for combined Fy reduction",0],["RBY2","Variation of slope Fy reduction with alpha",0],["RBY3","Shift term for alpha in slope Fy reduction",0],["RBY4","Influence of camber on stiffness of Fy combined",0],["RCY1","Shape factor for combined Fy reduction",1],["REY1","Curvature factor of combined Fy",0],["REY2","Curvature factor of combined Fy with load",0],["RHY1","Shift factor for combined Fy reduction",0],["RHY2","Shift factor for combined Fy reduction with load",0],["RVY1","Kappa induced side force Svyk/Muy*Fz at Fznom",0],["RVY2","Variation of Svyk/Muy*Fz with load",0],["RVY3","Variation of Svyk/Muy*Fz with camber",0],["RVY4","Variation of Svyk/Muy*Fz with alpha",0],["RVY5","Variation of Svyk/Muy*Fz with kappa",1],["RVY6","Variation of Svyk/Muy*Fz with atan(kappa)",0]],IL=[["LFZO","Scale factor of nominal (rated) load",1],["LCX","Scale factor of Fx shape factor",1],["LMUX","Scale factor of Fx peak friction coefficient",1],["LEX","Scale factor of Fx curvature factor",1],["LKX","Scale factor of Fx slip stiffness",1],["LHX","Scale factor of Fx horizontal shift",1],["LVX","Scale factor of Fx vertical shift",1],["LCY","Scale factor of Fy shape factor",1],["LMUY","Scale factor of Fy peak friction coefficient",1],["LEY","Scale factor of Fy curvature factor",1],["LKY","Scale factor of Fy cornering stiffness",1],["LKYC","Scale factor of camber force stiffness",1],["LKZC","Scale factor of camber torque stiffness",1],["LHY","Scale factor of Fy horizontal shift",1],["LVY","Scale factor of Fy vertical shift",1],["LTR","Scale factor of peak of pneumatic trail",1],["LRES","Scale factor for offset of residual torque",1],["LXAL","Scale factor of alpha influence on Fx",1],["LYKA","Scale factor of kappa influence on Fy",1],["LVYKA","Scale factor of kappa induced Fy",1],["LS","Scale factor of moment arm of Fx",1]],Nv=[["lateral",PL],["longitudinal",LL],["aligning",DL],["combined",EL],["scaling",IL]].flatMap(([e,t])=>t.map(([r,n,o])=>({key:r,section:e,text:n,fallback:o}))),nz=new Map(Nv.map(e=>[e.key,e]));var _L=/^\$\s*EDITED\s+([A-Z][A-Z0-9_]*)\s+was\s+(absent|[-+0-9.eE]+)\s*$/;function Ov(e){let t={};for(let r of e.split(/\r?\n/)){let n=r.trim().match(_L);if(!n)continue;let o=n[2]==="absent"?null:parseFloat(n[2]);(o===null||Number.isFinite(o))&&(t[n[1]]=o)}return Object.keys(t).length?t:void 0}var OL=/^\s*\$\s*UNLOADED_RADIUS_STAND_IN\s*=\s*([0-9.eE+-]+)/,VL=/^\$-+ written by (?:PaceDynamics|PaceLab)\b/m,BL=/^\$\s*AXIS_SYSTEM\s*=\s*(ISO-W|SAE)\b/m;function $L(e){let t=e.match(BL);return t?{axisSystem:t[1]==="SAE"?"sae":"iso",trustSide:!0}:VL.test(e)?{axisSystem:"sae",trustSide:!1}:{axisSystem:"iso",trustSide:!0}}function GL(e){return e>=62?"6.2":e>=61?"6.1":"5.2"}var Vv=new Map([["pa",1],["pascal",1],["kpa",1e3],["kilopascal",1e3],["mpa",1e6],["megapascal",1e6],["bar",1e5],["psi",6894.757293168]]);function KL(e,t,r){let n=r.PRESSURE?.trim().toLowerCase(),o=n===void 0?1:Vv.get(n);if(o===void 0)return;let a=(c,l)=>l===1?c:Number((c*l).toPrecision(12)),s=e.NOMPRES??e.INFLPRES;if(s!==void 0)return a(s,o);let i=e.INFLATION_PRESSURE;if(i!==void 0)return n!==void 0?a(i,o):t.PROPERTY_FILE_FORMAT?.trim().toUpperCase()==="MF_05"?a(i,1e5):void 0}var HL=new Map([["radians",1],["radian",1],["rad",1],["degrees",Math.PI/180],["degree",Math.PI/180],["deg",Math.PI/180]]);function zL(e,t){let r=(s,i)=>s===void 0?1:i.get(s.trim().toLowerCase()),n=r(t.ANGLE,HL),o={fz:1,kappa:1,alpha:n,gamma:n,p:r(t.PRESSURE,Vv)},a={};for(let s of Ws){let i=o[s.q];if(i===void 0)continue;let c={};for(let[l,u]of[["min",s.min],["max",s.max]]){let m=e[u];Number.isFinite(m)&&(c[l]=i===1?m:Number((m*i).toPrecision(12)),delete e[u])}(c.min!==void 0||c.max!==void 0)&&(a[s.q]=c)}return Object.keys(a).length?a:void 0}function js(e,t="imported",r={}){let n=$L(e),o=r.axisSystem??n.axisSystem,a={},s={},i={},c="",l;for(let g of e.split(/\r?\n/)){let y=g.match(OL);y&&(l=parseFloat(y[1]));let R=g.replace(/[$!].*$/,"").trim();if(!R)continue;if(R.startsWith("[")){c=(R.match(/^\[([^\]]*)/)?.[1]??"").trim().toUpperCase();continue}let k=R.indexOf("=");if(k<0)continue;let v=R.slice(0,k).trim().toUpperCase(),x=R.slice(k+1).trim(),M=x.match(/^'([^']*)'|^"([^"]*)"/);if(M){s[v]=M[1]??M[2]??"",c==="UNITS"&&(i[v]=s[v]);continue}let A=parseFloat(x);Number.isFinite(A)&&(a[v]=A)}let u=GL(a.FITTYP??62),m=Ov(e),d=m?Object.fromEntries(Object.entries(m).filter(([g])=>a[g]!==void 0)):void 0,p=a.VERTICAL_STIFFNESS??a.KZ??0,f=KL(a,s,i),h=zL(a,i),b=[];return a.UNLOADED_RADIUS===void 0&&a.R0===void 0&&b.push("UNLOADED_RADIUS"),p<=0&&b.push("VERTICAL_STIFFNESS"),a.FNOMIN===void 0&&b.push("FNOMIN"),f===void 0&&b.push("NOMPRES"),{kind:"magic",name:t,version:u,coeffs:a,axisSystem:o,side:n.trustSide?s.TYRESIDE==="RIGHT"?"right":s.TYRESIDE==="LEFT"?"left":void 0:void 0,fnomin:a.FNOMIN??5e3,unloadedR0:a.UNLOADED_RADIUS??a.R0??(l!==void 0&&l>0?l:.3),...a.WIDTH!==void 0&&a.WIDTH>0?{sectionWidth:a.WIDTH}:{},verticalStiffness:p>0?p/1e3:0,...a.FREFF!==void 0&&!a.DREFF?{rollingFraction:a.FREFF}:{},...a.LATERAL_STIFFNESS!==void 0&&a.LATERAL_STIFFNESS>0?{relaxation:{sigma:0,carcassStiffness:a.LATERAL_STIFFNESS/1e3,source:"fitted"}}:{},nomPressure:f??0,missing:b,...d&&Object.keys(d).length?{edited:d}:{},...h?{range:h}:{}}}function lr(e){if(!e)return null;let t=e.unloadedR0;return t===void 0||!(t>0)||e.kind==="magic"&&e.missing?.includes("UNLOADED_RADIUS")?null:t*1e3}function Ql(e){if(!e)return null;let t=e.sectionWidth;return t!==void 0&&t>0?t:null}var mz=Math.PI/180;var bz=Math.PI/180,gz=180/Math.PI;function Us(){return{kind:"simple",name:"Simple (default)",Bx:11,Cx:1.6,muX0:1.7,loadSensX:-8e-5,By:9,Cy:1.4,muY0:1.6,loadSensY:-1e-4,nominalLoad:1500,verticalStiffness:120}}var Gv=`$ AXIS_SYSTEM = SAE (authored in the evaluation frame: y right)
|
|
2
|
+
import{parentPort as VT,workerData as j$}from"node:worker_threads";import{readFileSync as Oy}from"node:fs";import{join as Vy}from"node:path";var rl=e=>e.format!=="points"&&!e.field;var xt=e=>e?.kind==="ice";var fx={packVoltageMax:600,segmentVoltageMax:120,powerLimitKw:80};var Ee=e=>typeof e=="number"&&Number.isFinite(e);function $T(e){let{soc:t,ocv:r,r0:n}=e;if(!Array.isArray(t)||t.length<2)return"The curve needs at least two state-of-charge points.";if(!t.every(Ee))return"The state-of-charge axis contains a value that is not a number.";if(t[0]<0||t[t.length-1]>1)return`The state-of-charge axis must lie within 0 to 1 (it runs ${t[0]} to ${t[t.length-1]}).`;for(let o=1;o<t.length;o++)if(!(t[o]>t[o-1]))return`The state-of-charge axis must increase (${t[o-1]} then ${t[o]}).`;if(!Array.isArray(r)||r.length!==t.length)return`The curve has ${Array.isArray(r)?r.length:0} voltages against ${t.length} state-of-charge points.`;if(!r.every(Ee))return"The open-circuit voltage contains a value that is not a number.";if(r.some(o=>o<=0))return"The open-circuit voltage must be positive everywhere.";for(let o=1;o<r.length;o++)if(r[o]<r[o-1])return`The open-circuit voltage must rise with state of charge (${r[o-1]} V at ${t[o-1]} then ${r[o]} V at ${t[o]}).`;if(!Array.isArray(n)||n.length!==t.length)return`The curve has ${Array.isArray(n)?n.length:0} resistances against ${t.length} state-of-charge points.`;if(!n.every(Ee))return"The resistance contains a value that is not a number.";if(n.some(o=>o<0))return"The resistance cannot be negative.";if(e.rTempC!==void 0||e.rGrid!==void 0){let o=e.rTempC,a=e.rGrid;if(!Array.isArray(o)||o.length<1)return"The resistance temperature axis needs at least one temperature.";if(!o.every(Ee))return"The resistance temperature axis contains a value that is not a number.";for(let s=1;s<o.length;s++)if(!(o[s]>o[s-1]))return`The temperature axis must increase (${o[s-1]} then ${o[s]} \xB0C).`;if(!Array.isArray(a)||a.length!==o.length)return`The resistance grid has ${Array.isArray(a)?a.length:0} rows against ${o.length} temperatures.`;for(let s=0;s<a.length;s++){let i=a[s];if(!Array.isArray(i)||i.length!==t.length)return`Resistance row ${s+1} has ${Array.isArray(i)?i.length:0} values against ${t.length} state-of-charge points.`;if(!i.every(Ee))return"The resistance grid contains a value that is not a number.";if(i.some(c=>c<0))return"The resistance grid contains a negative resistance."}}return null}function GT(e){return!e||typeof e!="object"?"The cell has no curve.":e.kind==="table"?$T(e):e.kind==="analytic"?!Ee(e.vCut)||!Ee(e.vNom)||!Ee(e.vFull)?"The cut-off, nominal and full voltages must be numbers.":e.vCut<=0?"The cut-off voltage must be positive.":e.vCut<e.vNom&&e.vNom<e.vFull?!Ee(e.r0)||e.r0<0?"The cell resistance must be a number and cannot be negative.":e.socAtNom!==void 0&&(!Ee(e.socAtNom)||e.socAtNom<=0||e.socAtNom>=1)?"The state of charge the nominal voltage is met at must lie strictly between 0 and 1.":null:`The voltages must order cut-off < nominal < full (given ${e.vCut}, ${e.vNom}, ${e.vFull} V).`:`Unknown cell curve kind "${e.kind}".`}function nl(e){if(!e||typeof e!="object")return"Not a battery model.";let t=e.cell;if(!t||typeof t!="object")return"The model has no cell.";if(!Ee(t.capacityAh)||t.capacityAh<=0)return"The cell capacity must be a positive number of amp-hours.";if(!Ee(t.vMin)||t.vMin<0)return"The cut-off voltage must be a number and cannot be negative.";if(!Ee(t.vMax)||t.vMax<=0)return"The maximum cell voltage must be a positive number.";if(!(t.vMin<t.vMax))return`The cut-off voltage (${t.vMin} V) must be below the maximum (${t.vMax} V).`;if(!Ee(t.iMaxA)||t.iMaxA<0)return"The discharge current limit must be a number of amps, 0 for no limit.";if(t.iMaxChargeA!==void 0&&(!Ee(t.iMaxChargeA)||t.iMaxChargeA<0))return"The charge current limit must be a number of amps, 0 for no limit.";if(t.massKg!==void 0&&(!Ee(t.massKg)||t.massKg<0))return"The cell mass must be a number and cannot be negative.";let r=GT(t.curve);if(r)return r;let n=t.curve.kind==="table"?t.curve.ocv[t.curve.ocv.length-1]:t.curve.vFull;if(t.vMin>=n)return`The cut-off voltage (${t.vMin} V) is at or above the cell's voltage at full charge (${n} V), so no power could ever be drawn.`;let o=e.thermal;if(o!==void 0){if(!o||typeof o!="object")return"The thermal model must be an object, or absent.";if(!Ee(o.heatCapacityJPerK)||o.heatCapacityJPerK<=0)return"The cell heat capacity must be a positive number of joules per kelvin.";if(!Ee(o.coolingWPerK)||o.coolingWPerK<0)return"The cooling must be a number of watts per kelvin and cannot be negative.";if(o.startC!==void 0&&!Ee(o.startC))return"The starting temperature must be a number.";if(o.entropicVPerK!==void 0&&!Ee(o.entropicVPerK))return"The entropic coefficient must be a number.";if(o.derateFromC!==void 0){if(!Ee(o.derateFromC))return"The temperature the derate starts at must be a number.";if(o.derateToC!==void 0){if(!Ee(o.derateToC))return"The temperature the derate ends at must be a number.";if(!(o.derateToC>o.derateFromC))return`The derate must end above where it starts (given ${o.derateFromC} then ${o.derateToC} \xB0C).`}}else if(o.derateToC!==void 0)return"The derate has an end temperature but no start; give both or neither."}let a=e.pack;if(!a||typeof a!="object")return"The model has no pack.";if(!Number.isInteger(a.series)||a.series<1)return"The pack needs a whole number of cells in series, at least one.";if(!Number.isInteger(a.parallel)||a.parallel<1)return"The pack needs a whole number of strings in parallel, at least one.";if(!Ee(a.busResistance)||a.busResistance<0)return"The busbar resistance must be a number and cannot be negative.";if(a.seriesPerSegment!==void 0&&a.seriesPerSegment!==0){if(!Number.isInteger(a.seriesPerSegment)||a.seriesPerSegment<1)return"The cells per segment must be a whole number, at least one.";if(a.seriesPerSegment>a.series)return`A segment cannot hold more cells (${a.seriesPerSegment}) than the pack has in series (${a.series}).`}return null}function Vn(e,t){let r=e.length;if(r<=1)return{i:0,t:0,clamped:!1};if(t<=e[0])return{i:0,t:0,clamped:t<e[0]};if(t>=e[r-1])return{i:r-2,t:1,clamped:t>e[r-1]};let n=0,o=r-1;for(;o-n>1;){let a=n+o>>1;e[a]<=t?n=a:o=a}return{i:n,t:(t-e[n])/(e[o]-e[n]),clamped:!1}}function Ge(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function ol(e,t,r,n,o){let a=e.length,s=t.length;if(a===0||s===0)return 0;let i=Vn(e,n),c=Vn(t,o),l=Math.min(i.i+1,a-1),u=Math.min(c.i+1,s-1),m=r[c.i][i.i],f=r[c.i][l],p=r[u][i.i],d=r[u][l],h=m+i.t*(f-m),b=p+i.t*(d-p);return h+c.t*(b-h)}var Yo=[0,.05,.1,.2,.3,.4,.5,.6,.7,.8,.9,1],ld={nmc:[0,.29,.4,.483,.525,.567,.608,.667,.733,.8,.892,1],lfp:[0,.478,.591,.626,.652,.67,.678,.696,.704,.722,.757,1],lipo:[0,.333,.433,.517,.575,.625,.667,.717,.775,.833,.908,1],other:[0,.05,.1,.2,.3,.4,.5,.6,.7,.8,.9,1]},hx=[0,.05,.1,.2,.5,.8,1],bx=[2.2,1.55,1.3,1.12,1,.97,.98];function gx(e){return Ge(hx,bx,e)}var yx=[-20,-10,0,10,25,40,60],xx=[4,2.8,2,1.4,1,.82,.75];function ud(e){return Ge(yx,xx,e)}var Rx=.5;function md(e,t){let{vFull:r,vNom:n,vCut:o,r0:a}=e,s=r-o;if(!(s>0))throw new Error(`The full voltage (${r} V) must be above the cut-off (${o} V).`);let i=(n-o)/s;if(!(i>0&&i<1))throw new Error(`The nominal voltage (${n} V) must lie between the cut-off (${o} V) and full (${r} V).`);let c=ld[t]??ld.other,l=e.socAtNom??Rx,u=Yo.includes(l)?[...Yo]:[...Yo,l].sort((h,b)=>h-b),m=Ge(Yo,c,l),f=m>0&&m<1?Math.log(i)/Math.log(m):1,p=[],d=[];for(let h of u){let b=Ge(Yo,c,h);p.push(o+s*Math.pow(b,f)),d.push(e.constantResistance?a:a*gx(h))}return{kind:"table",soc:u,ocv:p,r0:d}}function pd(e){let t=e.soc,r=e.ocv,n=[0,...t.filter(a=>a>0&&a<1),1],o=0;for(let a=1;a<n.length;a++){let s=n[a-1],i=n[a];o+=(Ge(t,r,s)+Ge(t,r,i))/2*(i-s)}return o}var Wo=25,vx=new WeakMap;function Fr(e){let t=vx.get(e);if(t)return t;let r=nl(e);if(r)throw new Error(r);let{cell:n,pack:o}=e,a=n.curve.kind==="table"?n.curve:md(n.curve,n.chemistry),s=o.series,i=o.parallel,c=s/i,l=a.rTempC,u=a.rGrid,m=i*n.capacityAh,f=s*n.vMin,p=n.iMaxA>0?i*n.iMaxA:1/0,d=n.iMaxChargeA!==void 0&&n.iMaxChargeA>0?n.iMaxChargeA:n.iMaxA/4,h=d>0?i*d:1/0,b=F=>s*Ge(a.soc,a.ocv,F),g=(F,w=Wo)=>{let T=l&&u?ol(a.soc,l,u,F,w):Ge(a.soc,a.r0,F)*ud(w);return c*T+o.busResistance},y=(F,w,T)=>b(F)-w*g(F,T),R=(F,w,T)=>{if(!(F>0))return 0;let P=b(w),A=g(w,T);if(!(A>0))return F/P;let S=P*P-4*A*F;return S<0?NaN:2*F/(P+Math.sqrt(S))},k=(F,w,T)=>{if(!(F>0))return 0;let P=b(w),A=g(w,T);return A>0?2*F/(P+Math.sqrt(P*P+4*A*F)):F/P},v=F=>{let w=e.thermal;if(!w||w.derateFromC===void 0)return 1;let T=w.derateToC??w.derateFromC;return F<=w.derateFromC?1:!(T>w.derateFromC)||F>=T?0:1-(F-w.derateFromC)/(T-w.derateFromC)},x=(F,w,T=0)=>{let P=b(F),A=g(F,w),S=A>0?P/(2*A):1/0,C=G=>{if(!(A>0))return G*P;let K=Math.min(G,S);return K*(P-K*A)},L=A>0?Math.max(0,(P-f)/A):1/0,D=T>0&&Number.isFinite(T)?T:1/0,I=A>0?C(L):1/0,O=Number.isFinite(p)?C(p):1/0,N=A>0?P*P/(4*A):1/0,z=[["rules",D],["voltage-floor",I],["current",O],["matched-load",N]],E=z[0][0],_=z[0][1];for(let[G,K]of z)K<_&&(_=K,E=G);let B=v(w??Wo);B<1&&(_=Number.isFinite(_)?_*B:_,E="temperature");let V=Number.isFinite(_)?R(_,F,w):1/0;return{watts:_,binding:E,rules:D,voltageFloor:I,current:O,matchedLoad:N,derate:B,amps:V,volts:Number.isFinite(V)?P-V*A:P}},M={model:e,table:a,capacityAh:m,chargeC:m*3600,energyKwh:m*(s*pd(a))/1e3,socRange:[a.soc[0],a.soc[a.soc.length-1]],voltageAtFull:s*a.ocv[a.ocv.length-1],voltageCeiling:s*n.vMax,voltageFloor:f,currentCeiling:p,chargeCurrentCeiling:h,massKg:n.massKg!==void 0?s*i*n.massKg:null,thermal:e.thermal?{heatCapacityJPerK:s*i*e.thermal.heatCapacityJPerK,coolingWPerK:s*i*e.thermal.coolingWPerK,...e.thermal.startC!==void 0?{startC:e.thermal.startC}:{},entropicVPerK:s*(e.thermal.entropicVPerK??0)}:null,derateAt:v,ocv:b,resistance:g,terminalVoltage:y,currentFor:R,chargeCurrentFor:k,maxPower:x};return vx.set(e,M),M}function dd(e){return{name:e.name,chemistry:e.chemistry,capacityAh:e.capacityAh,curve:{kind:"analytic",vFull:e.vFull,vNom:e.vNom,vCut:e.vCut,r0:e.r0},iMaxA:e.iMaxA,...e.iMaxChargeA!==void 0?{iMaxChargeA:e.iMaxChargeA}:{},vMin:e.vCut,vMax:e.vFull,...e.massKg!==void 0?{massKg:e.massKg}:{}}}var kx={name:"High-power NMC pouch 4.0 Ah",chemistry:"nmc",capacityAh:4,vCut:3,vNom:3.6,vFull:4.2,r0:.0025,iMaxA:100,iMaxChargeA:40,massKg:.09},Mx={name:"LFP prismatic 20 Ah",chemistry:"lfp",capacityAh:20,vCut:2.5,vNom:3.2,vFull:3.65,r0:.002,iMaxA:200,iMaxChargeA:60,massKg:.4},Sx={name:"NMC cylindrical 3.4 Ah",chemistry:"nmc",capacityAh:3.4,vCut:3,vNom:3.6,vFull:4.2,r0:.03,iMaxA:10,iMaxChargeA:3,massKg:.048};function fd(){return{name:"Formula Student accumulator",cell:dd(kx),pack:{series:140,parallel:2,busResistance:.02,seriesPerSegment:28},provenance:{source:"assumed",note:"Assumed high-power NMC pouch pack sized to the Formula Student rules; the cell curve and resistance are class-level guesses, not a measurement."}}}function hd(){return{name:"LFP pack",cell:dd(Mx),pack:{series:160,parallel:1,busResistance:.02,seriesPerSegment:32},provenance:{source:"assumed",note:"Assumed LFP prismatic pack; the flat plateau is the chemistry, the numbers are class-level guesses."}}}function bd(){return{name:"Road car pack",cell:dd(Sx),pack:{series:96,parallel:74,busResistance:.01},provenance:{source:"assumed",note:"Assumed road-electric pack of cylindrical energy cells; capacity and voltage are class-typical, the resistance is a guess."}}}function gd(e,t,r="Constant pack"){return{name:r,cell:{name:"Constant cell",chemistry:"other",capacityAh:e,curve:{kind:"table",soc:[0,1],ocv:[t,t],r0:[0,0]},iMaxA:0,vMin:0,vMax:t},pack:{series:1,parallel:1,busResistance:0},provenance:{source:"assumed",note:"The constant pack: one open-circuit voltage, no internal resistance and no current limit \u2014 what a car carried before the battery was a model. It cannot sag, so its power never fades."}}}function al(e){if(e.kind==="ice"){let n=e.gearbox.efficiency;return{model:e,maxTorque:o=>o>e.limitRpm?0:Ge(e.rpm,e.torque,o),efficiency:()=>n}}let t=n=>Ge(e.rpm,e.torque,n),r=e.kind==="simple"?()=>e.efficiency:(n,o)=>ol(e.effRpm,e.effTorque,e.effGrid,n,o);return{model:e,maxTorque:t,efficiency:r}}function yd(e){let t=e.resistanceAtC??20,r=e.torqueConstant,n=e.speedLossW??0,o=e.speedLossAtRpm??0,a=e.speedLossExponent??1.5,s=e.derateFromC,i=e.derateToC,c=d=>Math.max(0,e.terminalResistanceOhm*(1+.00393*(d-t))),l=d=>n>0&&o>0?n*Math.pow(Math.max(0,d)/o,a):0,u=(d,h,b)=>{let g=r>0?Math.abs(h)/r:0;return 1.5*c(b)*g*g+l(d)},m=(d,h)=>{let b=e.coolingWPerK*(h-e.coolantC)-l(d);return!(b>0)||r<=0?0:r*Math.sqrt(b/(1.5*c(h)))},f=e.coolingWPerK>0?e.heatCapacityJPerK/e.coolingWPerK:1/0,p=Number.isFinite(f)?.25*f:1/0;return{spec:e,startC:e.startC??e.coolantC,lossW:u,step(d,h,b){if(!(b>0)||!(e.heatCapacityJPerK>0))return d;let g=Number.isFinite(p)?Math.max(1,Math.ceil(b/p)):1,y=b/g,R=d;for(let k=0;k<g;k++)R+=(h-e.coolingWPerK*(R-e.coolantC))*y/e.heatCapacityJPerK;return R},continuousTorque:m,derate(d,h,b){if(s===void 0||i===void 0||!(i>s)||!(b>0)||h<=s)return 1;let g=Math.min(1,m(d,i)/b);return h>=i?g:1-(1-g)*(h-s)/(i-s)},equilibriumC(d){return e.coolingWPerK>0?e.coolantC+d/e.coolingWPerK:1/0}}}function qe(e,t){return t==="rear"&&e.tireRateRear!==void 0?e.tireRateRear:e.tireRate}function xd(e,t){let r=e.tyreFreeRadiusRear;return(t==="rear"&&r!==void 0?r:e.tyreFreeRadius)??0}var sl=9.81,Ax=(e,t)=>e*(t*t)/2*(Math.PI/180)/1e3,bs=(e,t)=>e+t>0?e*t/(e+t):0,Fx=.5;function il(e,t,r){if(!(r>0))return 1;let n=e*sl*t*(Math.PI/180)/r;return 1/(1-Math.min(Fx,n))}function Rd(e,t,r){return r>0?e*sl*t/(r*r):0}function wx(e,t,r,n,o){if(!(n>0)||!(o>0))return 1;let a=Rd(e,t,r)*(1/n+1/o);return 1/(1-Math.min(Fx,a))}function we(e){let t=4*e.unsprungPerCorner,r=Math.max(0,e.massTotal-t),n=r*e.frontMassFrac,o=r*(1-e.frontMassFrac),a=qe(e,"front"),s=qe(e,"rear"),i=e.wheelRateFront+(e.heaveSpringFront??0),c=e.wheelRateRear+(e.heaveSpringRear??0),l=bs(i,a),u=bs(c,s),m=(O,N)=>{let z=N/2;return z>0?1/(2*Math.PI)*Math.sqrt(O*1e3/z):0},f=m(l,n),p=m(u,o),d=bs(e.wheelRateFront+e.arbFront,a),h=bs(e.wheelRateRear+e.arbRear,s),b=Ax(d,e.trackFront),g=Ax(h,e.trackRear),y=b+g,R=y>0?b/y:.5,k=e.rcHeightFront+(e.rcHeightRear-e.rcHeightFront)*(1-e.frontMassFrac),v=(e.cgHeight-k)/1e3,x=r*sl*v,M=il(r,v,y),F=y>0?x/y*M:0,w=e.massTotal*sl*e.cgHeight/e.wheelbase,T=2*l,P=2*u,A=wx(r,e.cgHeight,e.wheelbase,T,P),C=(T>0&&P>0?(w/T+w/P)/e.wheelbase*A:0)*(180/Math.PI),L=e.wheelbase*e.wheelbase*bs(T,P)*(Math.PI/180)/1e3,D=e.damperFront??2.5,I=e.damperRear??2.5;return{sprungMass:r,sprungFront:n,sprungRear:o,rideRateFront:l,rideRateRear:u,rideFreqFront:f,rideFreqRear:p,rollRateFront:b,rollRateRear:g,rollRateTotal:y,rollWheelRateFront:d,rollWheelRateRear:h,frontRollStiffFrac:R,rollGradient:F,pitchGradient:C,pitchRate:L,cgRollGain:M,cgPitchGain:A,rideDampingFront:D+(e.heaveDamperFront??0),rideDampingRear:I+(e.heaveDamperRear??0),rollDampingFront:D+(e.rollDamperFront??0),rollDampingRear:I+(e.rollDamperRear??0)}}var nn=["clFront","clRear","cd"],on=e=>e.frame?.kind==="pitch";function jo(e){return on(e)?{x:e.axes.h,y:e.axes.pitch}:{x:e.axes.hFront,y:e.axes.hRear}}var cl=e=>e.frame?.kind==="pitch",Cx=e=>e.kind==="map";var ll=45,Je=e=>typeof e=="number"&&Number.isFinite(e);function ul(e,t,r="mm",n="ride height"){if(!Array.isArray(t)||t.length<1)return`The ${e} axis needs at least one ${n}.`;if(!t.every(Je))return`The ${e} axis contains a value that is not a number.`;for(let o=1;o<t.length;o++)if(!(t[o]>t[o-1]))return`The ${e} axis must increase (${t[o-1]} then ${t[o]} ${r}).`;return null}function Tx(e,t){if(t===void 0)return null;for(let r of nn){let n=t[r];if(!n||!Array.isArray(n.deg)||!Array.isArray(n.factor))return`The ${e} correction of ${r} needs degrees and factors.`;if(n.deg.length<1)return`The ${e} correction of ${r} needs at least one angle.`;if(n.deg.length!==n.factor.length)return`The ${e} correction of ${r} has ${n.factor.length} factors against ${n.deg.length} angles.`;if(!n.deg.every(Je)||!n.factor.every(Je))return`The ${e} correction of ${r} contains a value that is not a number.`;if(n.deg[0]<0)return`The ${e} correction of ${r} is against the absolute angle; it cannot start below zero.`;for(let o=1;o<n.deg.length;o++)if(!(n.deg[o]>n.deg[o-1]))return`The ${e} correction of ${r} must increase in angle (${n.deg[o-1]} then ${n.deg[o]}\xB0).`;if(n.factor.some(o=>o<0))return`The ${e} correction of ${r} has a negative factor.`}return null}function Px(e,t){return t===void 0?null:!Je(t.dCl)||!Je(t.dBalance)||!Je(t.dCd)?`The ${e} slopes must be numbers.`:!Je(t.maxDeg)||!(t.maxDeg>0)?`The ${e} response needs a positive angle to be valid to.`:null}function gs(e){if(!e||typeof e!="object")return"Not an aero model.";if(!Je(e.area)||e.area<=0)return"The reference area must be a positive number of square metres.";if(e.kind==="map"){let t,r,n,o;if(e.frame==null){let i=ul("front ride-height",e.axes?.hFront);if(i)return i;let c=ul("rear ride-height",e.axes?.hRear);if(c)return c;[t,r,n,o]=[e.axes.hFront,e.axes.hRear,"front ride heights","rear ride heights"]}else if(e.frame?.kind==="pitch"){if(!Je(e.frame.refX))return"The point the ride height is read at must be a number of millimetres aft of the front axle.";let i=ul("ride-height",e.axes?.h);if(i)return i;let c=ul("pitch",e.axes?.pitch,"\xB0","pitch");if(c)return c;let l=e.axes.pitch.find(u=>Math.abs(u)>=ll);if(l!==void 0)return`A pitch of ${l}\xB0 is not a car's attitude \u2014 is the axis a rake in millimetres? Pitch is in degrees.`;[t,r,n,o]=[e.axes.h,e.axes.pitch,"ride heights","pitches"]}else return`Unknown aero map frame "${e.frame.kind}".`;let a=t.length,s=r.length;for(let i of nn){let c=e[i];if(!Array.isArray(c)||c.length!==s)return`${i} has ${Array.isArray(c)?c.length:0} rows against ${s} ${o} \u2014 they must match.`;for(let l=0;l<s;l++){let u=c[l];if(!Array.isArray(u)||u.length!==a)return`${i} row ${l+1} has ${Array.isArray(u)?u.length:0} values against ${a} ${n}.`;if(!u.every(Je))return`${i} contains a value that is not a number.`}}return Tx("yaw",e.attitude?.yaw)??Tx("roll",e.attitude?.roll)}if(e.kind==="sensitivity"){let t;if(e.frame==null)t=["hFront","hRear"];else if(e.frame?.kind==="pitch"){if(!Je(e.frame.refX))return"The point the ride height is read at must be a number of millimetres aft of the front axle.";t=["h","pitch"]}else return`Unknown aero sensitivity frame "${e.frame.kind}".`;let r=e.ref,n=e.slope,o=e.range,a=s=>s==="pitch"?"\xB0":" mm";if(!r||!Je(r[t[0]])||!Je(r[t[1]]))return e.frame?"The reference ride height and pitch must be numbers.":"The reference ride heights must be numbers.";for(let s of nn){if(!e.at||!Je(e.at[s]))return`${s} at the reference must be a number.`;let i=n?.[s];if(!i||!Je(i[t[0]])||!Je(i[t[1]]))return`The slopes of ${s} must be numbers.`}for(let s of t){let i=o?.[s],c=r[s];if(!i||!Je(i[0])||!Je(i[1]))return`The ${s} range must be two numbers.`;if(!(i[1]>i[0]))return`The ${s} range must run from low to high (${i[0]} to ${i[1]}${a(s)}).`;if(c<i[0]||c>i[1])return`The reference ${s} of ${c}${a(s)} lies outside its range ${i[0]}\u2013${i[1]}${a(s)}.`;if(s==="pitch"&&(Math.abs(i[0])>=ll||Math.abs(i[1])>=ll))return`A pitch range reaching ${Math.abs(i[0])>=ll?i[0]:i[1]}\xB0 is not a car's attitude. Pitch is in degrees.`}return Px("yaw",e.attitude?.yaw)??Px("roll",e.attitude?.roll)}return`Unknown aero model kind "${e.kind}".`}var Lx=180/Math.PI;function Uo(e,t,r,n){let o=(n-r)/t;return{h:r+e.refX*o,pitch:Math.atan(o)*Lx}}function Xo(e,t,r,n){let o=Math.tan(n/Lx);return{hFront:r-e.refX*o,hRear:r+(t-e.refX)*o}}var EG=180/Math.PI,KT=["hFront","hRear"],HT=["h","pitch"],Md=e=>e?.kind==="pitch"?HT:KT,Ct=(e,t)=>e[t],ml=(e,t)=>e[t],vd=(e,t)=>({[e[0]]:t(e[0]),[e[1]]:t(e[1])});function zT(e){if(!(!e.yaw&&!e.roll))return{...e.yaw?{yaw:{...e.yaw}}:{},...e.roll?{roll:{...e.roll}}:{}}}function Sd(e){let t=Md(e.frame),r=e.balanceFront,n=e.cl*r,o=e.cl*(1-r),a=vd(t,c=>Ct(e.dCl,c)*r+e.cl*Ct(e.dBalance,c)),s=vd(t,c=>Ct(e.dCl,c)*(1-r)-e.cl*Ct(e.dBalance,c)),i=zT(e);return{kind:"sensitivity",name:e.name,area:e.area,...e.frame?{frame:{...e.frame}}:{},ref:{...e.ref},at:{clFront:n,clRear:o,cd:e.cd},slope:{clFront:a,clRear:s,cd:vd(t,c=>Ct(e.dCd,c))},range:{[t[0]]:[...ml(e.range,t[0])],[t[1]]:[...ml(e.range,t[1])]},provenance:{...e.provenance},...i?{attitude:i}:{}}}function pl(e,t,r){let n=Math.min(Math.abs(r),t.maxDeg),o=e.clFront+e.clRear,a=o!==0?e.clFront/o:.5,s=o+t.dCl*n,i=a+t.dBalance*n,c=e.clFront!==0?s*i/e.clFront:1,l=e.clRear!==0?s*(1-i)/e.clRear:1,u=e.cd!==0?(e.cd+t.dCd*n)/e.cd:1;return{clFront:c,clRear:l,cd:u}}function kd(e,t,r=11){let n=Array.from({length:r},(a,s)=>t.maxDeg*s/(r-1)),o=n.map(a=>pl(e,t,a));return{clFront:{deg:[...n],factor:o.map(a=>a.clFront)},clRear:{deg:[...n],factor:o.map(a=>a.clRear)},cd:{deg:[...n],factor:o.map(a=>a.cd)}}}function Dx(e){if(!(!e.attitude?.yaw&&!e.attitude?.roll))return{...e.attitude.yaw?{yaw:kd(e.at,e.attitude.yaw)}:{},...e.attitude.roll?{roll:kd(e.at,e.attitude.roll)}:{}}}function Ex(e,t,r,n=0,o=0){let[a,s]=Md(e.frame),i=t-Ct(e.ref,a),c=r-Ct(e.ref,s),l={clFront:e.at.clFront+Ct(e.slope.clFront,a)*i+Ct(e.slope.clFront,s)*c,clRear:e.at.clRear+Ct(e.slope.clRear,a)*i+Ct(e.slope.clRear,s)*c,cd:e.at.cd+Ct(e.slope.cd,a)*i+Ct(e.slope.cd,s)*c},u=e.attitude?.yaw?pl(e.at,e.attitude.yaw,n):{clFront:1,clRear:1,cd:1},m=e.attitude?.roll?pl(e.at,e.attitude.roll,o):{clFront:1,clRear:1,cd:1};return{clFront:l.clFront*u.clFront*m.clFront,clRear:l.clRear*u.clRear*m.clRear,cd:l.cd*u.cd*m.cd}}function Ad(e){let[t,r]=Md(e.frame),n=[...ml(e.range,t)],o=[...ml(e.range,r)],a=i=>o.map(c=>n.map(l=>i(Ex(e,l,c)))),s=Dx(e);return{kind:"map",name:e.name,area:e.area,...e.frame?{frame:{...e.frame}}:{},axes:{[t]:n,[r]:o},clFront:a(i=>i.clFront),clRear:a(i=>i.clRear),cd:a(i=>i.cd),provenance:{...e.provenance},...s?{attitude:s}:{}}}var Fd=180/Math.PI,Ix=new WeakMap,_x=new WeakMap,wd=new WeakMap;function an(e,t){let r=_x.get(e);if(r)return r;let n=t?.wheelbase,o=n!==void 0?wd.get(e)?.get(n):void 0;if(o)return o;let a=YT(e),s=a.map;if(!on(s)){let l=WT(e,a);return _x.set(e,l),l}if(n===void 0||!Number.isFinite(n)||n<=0)throw new Error("A ride-height-and-pitch aero map is read with the car\u2019s wheelbase, and none was given.");let i=jT(e,a,s.frame,n),c=wd.get(e);return c||(c=new Map,wd.set(e,c)),c.set(n,i),i}function YT(e){let t=Ix.get(e);if(t)return t;let r=gs(e);if(r)throw new Error(r);let n=e.kind==="map"?e:Ad(e),{x:o,y:a}=jo(n),s=o.length,i=a.length,c=n.attitude?.yaw,l=n.attitude?.roll,u=!!(c||l),m={clFront:1,clRear:1,cd:1,clamped:!1},f=(y,R)=>{let k=Math.abs(R),v=y.clFront.deg[y.clFront.deg.length-1];return{clFront:Ge(y.clFront.deg,y.clFront.factor,k),clRear:Ge(y.clRear.deg,y.clRear.factor,k),cd:Ge(y.cd.deg,y.cd.factor,k),clamped:k>v}},p=(y,R)=>{if(!u)return m;let k=c?f(c,y):m,v=l?f(l,R):m;return{clFront:k.clFront*v.clFront,clRear:k.clRear*v.clRear,cd:k.cd*v.cd,clamped:k.clamped||v.clamped}},d=(y,R,k=0,v=0)=>{let x=Vn(o,y),M=Vn(a,R),F=Math.min(x.i+1,s-1),w=Math.min(M.i+1,i-1),T=A=>{let S=A[M.i][x.i],C=A[M.i][F],L=A[w][x.i],D=A[w][F],I=S+x.t*(C-S),O=L+x.t*(D-L);return I+M.t*(O-I)},P=p(k,v);return{clFront:u?T(n.clFront)*P.clFront:T(n.clFront),clRear:u?T(n.clRear)*P.clRear:T(n.clRear),cd:u?T(n.cd)*P.cd:T(n.cd),clampedRide:x.clamped||M.clamped,clampedAttitude:P.clamped}},h={x:[o[0],o[s-1]],y:[a[0],a[i-1]]},b=(y,R,k=!1,v=0,x=0)=>{let M=p(v,x),F=Vn(o,k?Math.min(Math.max(y,h.x[0]),h.x[1]):y),w=Vn(a,k?Math.min(Math.max(R,h.y[0]),h.y[1]):R),T=Math.min(F.i+1,s-1),P=Math.min(w.i+1,i-1),A=T>F.i?o[T]-o[F.i]:0,S=P>w.i?a[P]-a[w.i]:0,C={};for(let L of nn){let D=n[L],I=D[w.i][F.i],O=D[w.i][T],N=D[P][F.i],z=D[P][T],E=F.clamped||A===0?0:((O-I)*(1-w.t)+(z-N)*w.t)/A,_=w.clamped||S===0?0:((N-I)*(1-F.t)+(z-O)*F.t)/S;C[L]=u?{x:E*M[L],y:_*M[L]}:{x:E,y:_}}return C},g={map:n,x:h.x,y:h.y,hasAttitude:u,factors:p,at:d,slopes:b};return Ix.set(e,g),g}function WT(e,t){let r={x:t.x,y:t.y,at:t.at,toAxles:(o,a)=>({hFront:o,hRear:a}),fromAxles:(o,a)=>({x:o,y:a})},n=(o,a,s=!1,i=0,c=0)=>{let l=t.slopes(o,a,s,i,c),u={};for(let m of nn)u[m]={hFront:l[m].x,hRear:l[m].y};return u};return{model:e,map:t.map,area:t.map.area,grid:r,hasAttitude:t.hasAttitude,at:t.at,slopes:n,factors:t.factors}}function jT(e,t,r,n){let o=r.refX,a=o/n,s=(l,u,m=0,f=0)=>{let p=(u-l)/n;return t.at(l+o*p,Math.atan(p)*Fd,m,f)},i=(l,u,m=!1,f=0,p=0)=>{let d=(u-l)/n,h=t.slopes(l+o*d,Math.atan(d)*Fd,m,f,p),b=Fd/(n*(1+d*d)),g={};for(let y of nn)g[y]={hFront:h[y].x*(1-a)-h[y].y*b,hRear:h[y].x*a+h[y].y*b};return g},c={frame:r,x:t.x,y:t.y,at:t.at,toAxles:(l,u)=>Xo(r,n,l,u),fromAxles:(l,u)=>{let m=Uo(r,n,l,u);return{x:m.h,y:m.pitch}}};return{model:e,map:t.map,area:t.map.area,grid:c,hasAttitude:t.hasAttitude,at:s,slopes:i,factors:t.factors}}function Cd(e){let t=e.clFront+e.clRear;return{cl:t,balanceFront:t!==0?e.clFront/t:.5}}var he=(e,t)=>e*t/100,Qe=e=>e/100,Nx={name:"Formula Student aero",area:1,cl:3,balanceFront:.45,cd:1.3,ref:{hFront:30,hRear:35},range:{hFront:[5,60],hRear:[10,70]},dCl:{hFront:he(3,-.4),hRear:he(3,.1)},dBalance:{hFront:Qe(-.3),hRear:Qe(.15)},dCd:{hFront:he(1.3,-.1),hRear:he(1.3,.05)},yaw:{dCl:he(3,-1),dBalance:Qe(-.3),dCd:he(1.3,.5),maxDeg:10},roll:{dCl:he(3,-.5),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for an undertray-and-wings Formula Student car, ride height, yaw and roll; not measured."},Ox={name:"Formula 1 aero",area:1.5,cl:3,balanceFront:.44,cd:.9,ref:{hFront:35,hRear:70},range:{hFront:[0,60],hRear:[20,100]},dCl:{hFront:he(3,-.3),hRear:he(3,-.15)},dBalance:{hFront:Qe(-.15),hRear:Qe(.15)},dCd:{hFront:he(.9,-.15),hRear:he(.9,-.05)},yaw:{dCl:he(3,-1.5),dBalance:Qe(.2),dCd:he(.9,.8),maxDeg:8},roll:{dCl:he(3,-1),dBalance:Qe(-.3),dCd:0,maxDeg:2},note:"Assumed class-level sensitivities for a ground-effect floor, ride height, yaw and roll; not measured."},Vx={name:"GT car aero",area:2,cl:1.4,balanceFront:.42,cd:.42,ref:{hFront:55,hRear:75},range:{hFront:[10,90],hRear:[10,110]},dCl:{hFront:he(1.4,-.3),hRear:he(1.4,.05)},dBalance:{hFront:Qe(-.25),hRear:Qe(.15)},dCd:{hFront:he(.42,-.1),hRear:0},yaw:{dCl:he(1.4,-.8),dBalance:Qe(-.2),dCd:he(.42,.6),maxDeg:10},roll:{dCl:he(1.4,-.3),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a splitter-and-wing GT car, ride height, yaw and roll; not measured."},Bx={name:"Sports car aero",area:2.2,cl:-.1,balanceFront:.5,cd:.3,ref:{hFront:130,hRear:140},range:{hFront:[80,180],hRear:[100,200]},dCl:{hFront:-5e-4,hRear:0},dBalance:{hFront:0,hRear:0},dCd:{hFront:2e-4,hRear:0},yaw:{dCl:0,dBalance:0,dCd:he(.3,.5),maxDeg:10},note:"Assumed class-level sensitivities for a road car with no aero devices; not measured."},$x={name:"Cup car aero",area:2.1,cl:.45,balanceFront:.45,cd:.4,ref:{hFront:64,hRear:78},range:{hFront:[20,100],hRear:[30,120]},dCl:{hFront:he(.45,-.4),hRear:he(.45,.05)},dBalance:{hFront:Qe(-.25),hRear:Qe(.15)},dCd:{hFront:he(.4,-.1),hRear:0},yaw:{dCl:he(.45,-1.2),dBalance:Qe(-.2),dCd:he(.4,.6),maxDeg:10},roll:{dCl:he(.45,-.3),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a splitter-and-wing cup hatchback, ride height, yaw and roll; not measured."},Gx={name:"Stock car aero",area:2.2,cl:.6,balanceFront:.45,cd:.45,ref:{hFront:75,hRear:90},range:{hFront:[20,110],hRear:[30,130]},dCl:{hFront:he(.6,-.35),hRear:he(.6,.05)},dBalance:{hFront:Qe(-.25),hRear:Qe(.15)},dCd:{hFront:he(.45,-.1),hRear:0},yaw:{dCl:he(.6,-1),dBalance:Qe(-.2),dCd:he(.45,.6),maxDeg:10},roll:{dCl:he(.6,-.3),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a splitter-and-spoiler stock car, ride height, yaw and roll; not measured."},Kx={name:"Hill-climb prototype aero",area:1.2,cl:2.5,balanceFront:.42,cd:.9,ref:{hFront:45,hRear:55},range:{hFront:[10,80],hRear:[15,95]},dCl:{hFront:he(2.5,-.35),hRear:he(2.5,.05)},dBalance:{hFront:Qe(-.25),hRear:Qe(.15)},dCd:{hFront:he(.9,-.1),hRear:he(.9,.05)},yaw:{dCl:he(2.5,-1),dBalance:Qe(-.3),dCd:he(.9,.5),maxDeg:10},roll:{dCl:he(2.5,-.5),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a winged sports prototype with a flat floor and diffuser, ride height, yaw and roll; not measured."},Hx={name:"Race truck aero",area:6.2,cl:-.1,balanceFront:.6,cd:.65,ref:{hFront:110,hRear:240},range:{hFront:[60,160],hRear:[180,300]},dCl:{hFront:-5e-4,hRear:0},dBalance:{hFront:0,hRear:0},dCd:{hFront:2e-4,hRear:0},yaw:{dCl:0,dBalance:0,dCd:he(.65,.5),maxDeg:10},note:"Assumed class-level sensitivities for a cab-over race truck with a chin spoiler and deflectors, ride height and yaw; not measured."};function wr(e){return Sd({name:e.name,area:e.area,cl:e.cl,balanceFront:e.balanceFront,cd:e.cd,ref:e.ref,range:e.range,dCl:e.dCl,dBalance:e.dBalance,dCd:e.dCd,...e.yaw?{yaw:e.yaw}:{},...e.roll?{roll:e.roll}:{},provenance:{source:"assumed",note:e.note}})}var Td=()=>wr(Nx),Pd=()=>wr(Ox),Ld=()=>wr(Vx),Dd=()=>wr(Bx),Ed=()=>wr($x),Id=()=>wr(Gx),_d=()=>wr(Kx),Nd=()=>wr(Hx);function Bn(e,t){let r=.5*e.rho*e.area*t*t,n=e.cl*r,o=e.cw*r,a=n*e.copLongFront;return{downforce:n,drag:o,downFront:a,downRear:n-a}}function dl(e,t){let r=e.massTotal;if(!(r>0))return{front:0,rear:0};let n=Math.max(0,Math.min(1,e.frontMassFrac)),o=2*e.unsprungPerCorner,a=(s,i)=>i>0?Math.min(1,s/i):0;return{front:(t.sprungMass*n+o*a(t.rideRateFront,qe(e,"front")))/r,rear:(t.sprungMass*(1-n)+o*a(t.rideRateRear,qe(e,"rear")))/r}}function fl(e,t,r,n){let o=t.front*r+t.rear*n;return o===0?e:Math.max(Math.min(1,e),e-o)}function Od(e,t){return e.wheelbase>0?e.massTotal*t*9.81/e.wheelbase:0}function qo(e,t,r){let n=2*t.rideRateFront,o=2*t.rideRateRear;return!(n>0)||!(o>0)?0:Math.min(Rd(t.sprungMass,r,e.wheelbase),.5*n*o/(n+o))}function ys(e,t,r,n,o){let a=e.cgHeight,s=Od(e,r);if(n===0&&o===0&&s===0)return{height:a,forward:0,noseLoad:0,dropFront:0,dropRear:0};let i=dl(e,t),c=2*t.rideRateFront,l=2*t.rideRateRear,u=a,m=0,f=0,p=0;for(let h=0;h<6;h++){p=qo(e,t,u);let b=n-s*u,g=o+s*u;if(p>0){let k=c*l-p*(c+l);m=(b*(l-p)-p*g)/k,f=(g*(c-p)-p*b)/k}else m=c>0?b/c:0,f=l>0?g/l:0;let y=fl(a,i,m,f),R=Math.abs(y-u);if(u=y,R<1e-9)break}let d=m-f;return{height:u,forward:e.wheelbase>0?u*d/e.wheelbase:0,noseLoad:p*d,dropFront:m,dropRear:f}}var Vd={yawDeg:0,rollDeg:0},zx=1e-4,UT=40,Yx=50;function sn(e,t,r=0){let n=e.aero?.model;if(!(!n||!an(n,e).hasAttitude))return{yawDeg:r,rollDeg:we(e).rollGradient*t}}function Qo(e,t){if(e.rideHeightFront!=null&&e.rideHeightRear!=null)return{hFront:e.rideHeightFront,hRear:e.rideHeightRear};let r=e.model,n=(a,s,i)=>{if(t!==void 0&&t>0)return Xo(a,t,s,i);throw new Error("A ride-height-and-pitch aero model is read with the car\u2019s wheelbase, and none was given.")},o={hFront:0,hRear:0};if(r?.kind==="sensitivity")o=cl(r)?n(r.frame,r.ref.h,r.ref.pitch):r.ref;else if(r){let{x:a,y:s}=jo(r),i=(a[0]+a[a.length-1])/2,c=(s[0]+s[s.length-1])/2;o=on(r)?n(r.frame,i,c):{hFront:i,hRear:c}}return{hFront:e.rideHeightFront??o.hFront,hRear:e.rideHeightRear??o.hRear}}var Wx=new WeakMap;function Cr(e,t,r=0,n){let o=e.aero;if(!o?.model)return null;let a=Wx.get(e);a||(a=new Map,Wx.set(e,a));let s=n&&an(o.model,e).hasAttitude?n:Vd,i=s===Vd?`${t}|${r}`:`${t}|${r}|${s.yawDeg.toFixed(3)}|${s.rollDeg.toFixed(3)}`,c=a.get(i);if(c)return c;let l=XT(e,o,t,r,s);return a.size>4096&&a.clear(),a.set(i,l),l}function XT(e,t,r,n,o){let a=an(t.model,e),s=we(e),i=2*s.rideRateFront,c=2*s.rideRateRear,l=Qo(t,e.wheelbase),u=.5*t.rho*r*r,m=a.area,f=e.wheelbase>0?t.copHeight/e.wheelbase:0,p=dl(e,s),d=Od(e,n),h=(T,P)=>fl(e.cgHeight,p,l.hFront-T,l.hRear-P),b=(T,P)=>l.hFront-T-(l.hRear-P),g=(T,P)=>{let A=a.at(T,P,o.yawDeg,o.rollDeg),S=u*m*A.clFront,C=u*m*A.clRear,L=u*m*A.cd,D=L*f,I=h(T,P),O=d*I,N=qo(e,s,I)*b(T,P),z=S-O-D+N,E=C+O+D-N,_=T-l.hFront+(i>0?z/i:0),B=P-l.hRear+(c>0?E/c:0);return{c:A,downFront:S,downRear:C,drag:L,rF:_,rR:B,norm:Math.hypot(_,B)}},y=(T,P,A=!1)=>{let S=a.slopes(T,P,A,o.yawDeg,o.rollDeg),C=i>0?u*m/i:0,L=c>0?u*m/c:0;return[[C*(S.clFront.hFront-f*S.cd.hFront),C*(S.clFront.hRear-f*S.cd.hRear)],[L*(S.clRear.hFront+f*S.cd.hFront),L*(S.clRear.hRear+f*S.cd.hRear)]]},R=l.hFront,k=l.hRear,v=g(R,k),x=0;for(;v.norm>=zx&&x<UT;){x++;let T=y(R,k),P=i>0?d/i:0,A=c>0?d/c:0,S=qo(e,s,h(R,k)),C=i>0?S/i:0,L=c>0?S/c:0,D=1+T[0][0]-P*p.front-C,I=T[0][1]-P*p.rear+C,O=T[1][0]+A*p.front+L,N=1+T[1][1]+A*p.rear-L,z=D*N-I*O,E,_;Math.abs(z)>1e-9?(E=-(N*v.rF-I*v.rR)/z,_=-(-O*v.rF+D*v.rR)/z):(E=-.5*v.rF,_=-.5*v.rR);let B=Math.max(1,Math.abs(E)/Yx,Math.abs(_)/Yx);E/=B,_/=B;let V=1;for(let G=0;G<6;G++){let K=g(R+V*E,k+V*_);if(K.norm<=v.norm||G===5){R+=V*E,k+=V*_,v=K;break}V*=.5}}let M=y(R,k,!0),F=2+M[0][0]+M[1][1],w=(1+M[0][0])*(1+M[1][1])-M[0][1]*M[1][0];return{v:r,axG:n,hFront:R,hRear:k,cgHeight:h(R,k),cgForward:e.wheelbase>0?h(R,k)*b(R,k)/e.wheelbase:0,cgNoseLoad:qo(e,s,h(R,k))*b(R,k),clFront:v.c.clFront,clRear:v.c.clRear,cd:v.c.cd,area:m,downforce:v.downFront+v.downRear,drag:v.drag,downFront:v.downFront,downRear:v.downRear,gain:qT(M),stable:w>0&&F>0,converged:v.norm<zx,iterations:x,clampedRide:v.c.clampedRide,yawDeg:o.yawDeg,rollDeg:o.rollDeg,clampedAttitude:v.c.clampedAttitude}}function qT(e){let t=e[0][0]+e[1][1],r=e[0][0]*e[1][1]-e[0][1]*e[1][0],n=t*t-4*r;if(n>=0){let o=Math.sqrt(n);return Math.max(Math.abs((t+o)/2),Math.abs((t-o)/2))}return Math.sqrt(r)}function xs(e,t,r=0,n){let o=Cr(e,t,r,n);return o?{downforce:o.downforce,drag:o.drag,downFront:o.downFront,downRear:o.downRear}:e.aero?Bn(e.aero,t):{downforce:0,drag:0,downFront:0,downRear:0}}function QT(e,t,r,n){let o=Bn(t,r),a=we(e),s=Qo(t,e.wheelbase),i=e.wheelbase>0?o.drag*t.copHeight/e.wheelbase:0,c=ys(e,a,n,o.downFront-i,o.downRear+i),l=o.downforce;return{v:r,axG:n,hFront:s.hFront-c.dropFront,hRear:s.hRear-c.dropRear,cgHeight:c.height,cgForward:c.forward,cgNoseLoad:c.noseLoad,clFront:t.cl*t.copLongFront,clRear:t.cl*(1-t.copLongFront),cd:t.cw,area:t.area,downforce:l,drag:o.drag,downFront:o.downFront,downRear:o.downRear,gain:0,stable:!0,converged:!0,iterations:0,clampedRide:!1,yawDeg:0,rollDeg:0,clampedAttitude:!1}}function Bd(e,t,r=0,n){let o=Cr(e,t,r,n);return o||(e.aero?QT(e,e.aero,t,r):null)}function hl(e,t=0,r=0,n,o){if(e.aero&&t>0){if(e.aero.model){let i=Cr(e,t,r,n);return{height:i.cgHeight,forward:i.cgForward,noseLoad:i.cgNoseLoad}}let a=Bn(e.aero,t),s=e.wheelbase>0?a.drag*e.aero.copHeight/e.wheelbase:0;return ys(e,o??we(e),r,a.downFront-s,a.downRear+s)}return r===0?{height:e.cgHeight,forward:0,noseLoad:0}:ys(e,o??we(e),r,0,0)}var jx=[0,1,0],$d=[0,0,1],ee=(e,t)=>[e[0]+t[0],e[1]+t[1],e[2]+t[2]],H=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],U=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],Gd=e=>[-e[0],-e[1],-e[2]],X=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],ae=(e,t)=>[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]],ZT=e=>X(e,e),cn=e=>Math.sqrt(X(e,e)),Rs=(e,t)=>ZT(H(e,t)),ve=(e,t)=>cn(H(e,t)),q=e=>{let t=cn(e);return t<1e-12?[0,0,0]:[e[0]/t,e[1]/t,e[2]/t]};var ln=(e,t,r)=>{let n=q(r),o=H(e,t);return ee(t,U(n,X(o,n)))},Ux=(e,t,r)=>ve(e,ln(e,t,r));var eP=1e-6;function tP(e){if(e<eP){let n=e*e;return[1-n/6,.5-n/24]}let t=Math.sin(e),r=Math.cos(e);return[t/e,(1-r)/(e*e)]}function st(e,t){let r=Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]);if(r<1e-14)return t;let[n,o]=tP(r),a=ae(e,t),s=ae(e,a);return ee(t,ee(U(a,n),U(s,o)))}function Bt(e,t,r){let n=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);if(n<1e-14)return e;let o=[t[0]/n,t[1]/n,t[2]/n];return st(U(o,r),e)}function sr(e,t){let r=t.length,n=e.map(a=>a.slice()),o=t.slice();return qx(n,o,r,new Array(r).fill(0))}function Xx(e,t,r){return qx(e,t,t.length,r)}function qx(e,t,r,n){let o=1/0,a=0;for(let s=0;s<r;s++){let i=s,c=Math.abs(e[s][s]);for(let u=s+1;u<r;u++){let m=Math.abs(e[u][s]);m>c&&(c=m,i=u)}if(c<1e-14){for(let u=0;u<r;u++)n[u]=NaN;return{x:n,condProxy:1/0,singular:!0}}if(o=Math.min(o,c),a=Math.max(a,c),i!==s){let u=e[s];e[s]=e[i],e[i]=u;let m=t[s];t[s]=t[i],t[i]=m}let l=e[s][s];for(let u=s+1;u<r;u++){let m=e[u][s]/l;if(m!==0){for(let f=s;f<r;f++)e[u][f]-=m*e[s][f];t[u]-=m*t[s]}}}for(let s=r-1;s>=0;s--){let i=t[s];for(let c=s+1;c<r;c++)i-=e[s][c]*n[c];n[s]=i/e[s][s]}return{x:n,condProxy:a/o,singular:!1}}var Qx=e=>{let t=0;for(let r of e)t=Math.max(t,Math.abs(r));return t},Zx=e=>{let t=0;for(let r of e)t+=r*r;return t},rP=Math.sqrt(Number.EPSILON);function Jx(e,t,r={}){let n=r.maxIter??60,o=r.tol??1e-10,a=t.length,s=r.scales??new Array(a).fill(1),i=t.slice(),c=e(i),l=Qx(c),u=Zx(c),m=.001,f=1,p=c.length,d=Array.from({length:p},()=>new Array(a).fill(0)),h=Array.from({length:a},()=>new Array(a).fill(0)),b=Array.from({length:a},()=>new Array(a).fill(0)),g=new Array(a).fill(0),y=new Array(a).fill(0),R=new Array(a).fill(0),k=new Array(a).fill(0),v=new Array(a).fill(0);for(let x=0;x<n;x++){if(l<o)return{x:i,residualNorm:l,iterations:x,converged:!0,condProxy:f};for(let T=0;T<a;T++){let P=rP*Math.max(Math.abs(i[T]),s[T]);for(let S=0;S<a;S++)k[S]=i[S];k[T]+=P;let A=e(k);for(let S=0;S<p;S++)d[S][T]=(A[S]-c[S])/P}let M=0;for(let T=0;T<a;T++){for(let A=0;A<a;A++){let S=0;for(let C=0;C<p;C++)S+=d[C][T]*d[C][A];h[T][A]=S}let P=0;for(let A=0;A<p;A++)P+=d[A][T]*c[A];g[T]=P,M=Math.max(M,h[T][T])}let F=Math.max(M,1e-9),w=!1;for(let T=0;T<18;T++){let P=m*F;for(let S=0;S<a;S++){let C=h[S],L=b[S];for(let D=0;D<a;D++)L[D]=S===D?C[D]+P:C[D];y[S]=-g[S]}let A=Xx(b,y,R);if(f=Math.max(f,A.condProxy),!A.singular){for(let L=0;L<a;L++)v[L]=i[L]+R[L];let S=e(v),C=Zx(S);if(C<u){for(let L=0;L<a;L++)i[L]=v[L];c=S,u=C,l=Qx(c),m=Math.max(m*.3,1e-12),w=!0;break}}m=Math.min(m*4,1e12)}if(!w)break}return{x:i,residualNorm:l,iterations:n,converged:l<o,condProxy:f}}function vs(e,t,r,n){let o=e*e+t*t,a=Math.sqrt(o);if(!(a>1e-12*n))return{c1:1,s1:0,c2:1,s2:0,margin:0,ok:!1,free:!0};let s=Math.abs(r),i=1-s/a;if(i<0){let l=r>=0?1:-1,u=l*e/a,m=l*t/a;return{c1:u,s1:m,c2:u,s2:m,margin:i,ok:i>=-1e-12,free:!1}}let c=Math.sqrt((a-s)*(a+s));return{c1:(e*r-t*c)/o,s1:(t*r+e*c)/o,c2:(e*r+t*c)/o,s2:(t*r-e*c)/o,margin:i,ok:!0,free:!1}}function Kd(e,t){return[e[0]*t[0]-e[1]*t[1]-e[2]*t[2]-e[3]*t[3],e[0]*t[1]+e[1]*t[0]+e[2]*t[3]-e[3]*t[2],e[0]*t[2]-e[1]*t[3]+e[2]*t[0]+e[3]*t[1],e[0]*t[3]+e[1]*t[2]-e[2]*t[1]+e[3]*t[0]]}var eR=e=>[e[0],-e[1],-e[2],-e[3]];function tR(e,t){let[r,n,o,a]=e,s=2*(o*t[2]-a*t[1]),i=2*(a*t[0]-n*t[2]),c=2*(n*t[1]-o*t[0]);return[t[0]+r*s+(o*c-a*i),t[1]+r*i+(a*s-n*c),t[2]+r*c+(n*i-o*s)]}function rR(e,t){let r=e[0]*t[0]+e[1]*t[1]+e[2]*t[2];if(1+r<1e-14){let o=Math.abs(e[0])<.6?[1,0,0]:[0,1,0],a=e[1]*o[2]-e[2]*o[1],s=e[2]*o[0]-e[0]*o[2],i=e[0]*o[1]-e[1]*o[0],c=Math.hypot(a,s,i);return[0,a/c,s/c,i/c]}let n=Math.sqrt(2*(1+r));return[(1+r)/n,(e[1]*t[2]-e[2]*t[1])/n,(e[2]*t[0]-e[0]*t[2])/n,(e[0]*t[1]-e[1]*t[0])/n]}function nR(e,t,r){let n,o;return t>=0?(n=Math.sqrt((1+t)/2),o=r/(2*n)):(o=(r>=0?1:-1)*Math.sqrt((1-t)/2),n=r/(2*o)),[n,o*e[0],o*e[1],o*e[2]]}function Hd(e,t,r){let n=e[0],o=e[1],a=e[2],s=t[0],i=t[1],c=t[2],l=r[0],u=r[1],m=r[2],f=n+i+m;if(f>=n&&f>=i&&f>=m){let h=Math.sqrt(1+f),b=.5/h;return[.5*h,(c-u)*b,(l-a)*b,(o-s)*b]}if(n>=i&&n>=m){let h=Math.sqrt(1+n-i-m),b=.5/h;return[(c-u)*b,.5*h,(s+o)*b,(l+a)*b]}if(i>=m){let h=Math.sqrt(1-n+i-m),b=.5/h;return[(l-a)*b,(s+o)*b,.5*h,(u+c)*b]}let p=Math.sqrt(1-n-i+m),d=.5/p;return[(o-s)*d,(l+a)*d,(u+c)*d,.5*p]}function oR(e){let t=Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]);if(t===0)return[1,0,0,0];let r=Math.sin(t/2)/t;return[Math.cos(t/2),r*e[0],r*e[1],r*e[2]]}function aR(e){let[t,r,n,o]=e;t<0&&(t=-t,r=-r,n=-n,o=-o);let a=Math.sqrt(r*r+n*n+o*o);if(a===0)return[0,0,0];let s=2*Math.atan2(a,t)/a;return[s*r,s*n,s*o]}function nP(e){let t=Math.abs(e[0])<.6?[1,0,0]:[0,1,0],r=q(ae(e,t));return[r,ae(e,r)]}function oP(e){let t=e.hardpoints,r=q(H(t.damperChassis,t.pushrodOuter)),[n,o]=nP(r);return{top:t.damperChassis,lower0:t.pushrodOuter,axis0:r,e1:n,e2:o}}function zd(e){let t=e.hardpoints,r=t.wheelCenter,n=q(H(t.ucaRear,t.ucaFront)),o=H(t.uprightUpper,t.ucaFront),a=X(o,n),s=H(o,U(n,a)),i=X(s,s),c=q(H(t.lcaRear,t.lcaFront)),l=H(t.uprightLower,t.lcaFront),u=Rs(t.tieOuter,t.tieInner);return{c0:r,ucaFront:t.ucaFront,ucaDir:n,ubj0:t.uprightUpper,ubjAxial0:a,ubjRadius2:i,lcaFront:t.lcaFront,lcaDir:c,lbj0:t.uprightLower,lbjRel0:l,tro0:t.tieOuter,tieInner0:t.tieInner,tieLen2:u,rackAxis:q(e.config.rackAxis),steerMovesRack:e.config.steerMode==="rack",ubjRadiusRef:Math.max(1,2*Math.sqrt(i)),tieLenRef:Math.max(1,2*Math.sqrt(u)),...e.config.layout==="mcpherson"?{strut:oP(e)}:{}}}function $t(e,t,r){let n=[t[3],t[4],t[5]],o=[t[0],t[1],t[2]],a=H(r,e.c0);return ee(ee(st(n,a),e.c0),o)}function Yd(e,t){return ee(e.lcaFront,Bt(e.lbjRel0,e.lcaDir,t))}function $n(e,t){return e.steerMovesRack?ee(e.tieInner0,U(e.rackAxis,t)):e.tieInner0}function Wd(e,t,r,n){let o=$t(e,t,e.lbj0),a=Yd(e,r),s=o[0]-a[0],i=o[1]-a[1],c=o[2]-a[2],l,u;if(e.strut){let d=e.strut,h=[t[3],t[4],t[5]],b=H(d.top,$t(e,t,d.lower0));l=X(b,st(h,d.e1)),u=X(b,st(h,d.e2))}else{let d=$t(e,t,e.ubj0),h=H(d,e.ucaFront),b=X(h,e.ucaDir),g=H(h,U(e.ucaDir,b));l=b-e.ubjAxial0,u=(X(g,g)-e.ubjRadius2)/e.ubjRadiusRef}let m=$t(e,t,e.tro0),f=$n(e,n),p=(Rs(m,f)-e.tieLen2)/e.tieLenRef;return[s,i,c,l,u,p]}var ks=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]),bl=e=>{let t=ks(e);return[e[0]/t,e[1]/t,e[2]/t]},aP=(e,t)=>H(e,U(t,X(e,t))),jd=e=>bl(ae(e,Math.abs(e[0])<.6?[1,0,0]:[0,1,0]));function sP(e,t){let r=e.ucaDir,n=ee(e.ucaFront,U(r,e.ubjAxial0)),o=Math.sqrt(e.ubjRadius2),a=aP(H(e.ubj0,e.ucaFront),r),s=ks(a)>1e-9?bl(a):jd(r),i=ae(r,s),c=H(e.ubj0,e.lbj0),l=X(c,c);if(!(l>1e-18))return"free";let u=H(n,t),m=X(u,u),f=vs(2*o*X(s,u),2*o*X(i,u),l-m-o*o,2*o*Math.sqrt(m));if(f.free)return"free";let p=bl(c),d=(h,b)=>{let g=ee(n,ee(U(s,o*h),U(i,o*b))),y=bl(H(g,t));return{q1:rR(p,y),k:y,margin:f.margin,ok:f.ok}};return f.margin>0?[d(f.c1,f.s1),d(f.c2,f.s2)]:[d(f.c1,f.s1)]}function iP(e,t,r){let n=t.axis0,o=ee(t.lower0,U(n,X(H(e.lbj0,t.lower0),n))),a=H(o,e.lbj0),s=ks(a),i=s>1e-9?U(a,1/s):jd(n),c=H(t.top,r),l=ks(c);if(!(l>1e-9))return"free";let u=U(c,1/l),m=s/l,f=1-m,p=f>=0?Math.sqrt((1-m)*(1+m)):0,d=jd(u),h=b=>{let g=b*p,y=ee(U(u,g),U(d,Math.min(m,1))),R=H(U(u,Math.min(m,1)),U(d,g));return{q1:Kd(Hd(R,y,ae(R,y)),eR(Hd(i,n,ae(i,n)))),k:u,margin:f,ok:f>=0}};return f>0?[h(1),h(-1)]:[h(1)]}function cP(e,t,r,n){let{k:o}=n,a=tR(n.q1,H(e.tro0,e.lbj0)),s=X(a,o),i=H(a,U(o,s)),c=ks(i);if(!(c>1e-9))return"free";let l=U(i,1/c),u=ae(o,l),m=ee(t,U(o,s)),f=H(m,r),p=X(f,f),d=vs(2*c*X(f,l),2*c*X(f,u),e.tieLen2-p-c*c,2*c*Math.sqrt(p));if(d.free)return"free";let h=(g,y)=>({q:Kd(nR(o,g,y),n.q1)});return{roots:d.margin>0?[h(d.c1,d.s1),h(d.c2,d.s2)]:[h(d.c1,d.s1)],margin:d.margin,ok:d.ok}}function sR(e,t,r,n=[0,0,0,0,0,0]){let o=Yd(e,t),a=$n(e,r),s=oR([n[3],n[4],n[5]]),i=h=>Math.abs(h[0]*s[0]+h[1]*s[1]+h[2]*s[2]+h[3]*s[3]),c=e.strut?iP(e,e.strut,o):sP(e,o);if(c==="free")return{x:n.slice(),converged:!1,margin:0,free:!0};let l=null,u=null;for(let h of c){let b=cP(e,o,a,h);if(b==="free")return{x:n.slice(),converged:!1,margin:0,free:!0};let g=Math.min(h.margin,b.margin),y=b.ok&&h.ok;for(let{q:R}of b.roots){let k=i(R);y&&(!l||k>l.near)&&(l={q:R,margin:g,near:k}),!y&&(!u||k>u.near)&&(u={q:R,margin:g,near:k})}}let{q:m,margin:f}=l??u,p=aR(m),d=H(H(o,e.c0),st(p,H(e.lbj0,e.c0)));return{x:[d[0],d[1],d[2],p[0],p[1],p[2]],converged:l!==null,margin:f,free:!1}}function cR(e){let t=q(H(e.rockerPivotB,e.rockerPivotA));return{pivotA:e.rockerPivotA,axis:t,rprRel0:H(e.rockerToPushrod,e.rockerPivotA),rdmRel0:H(e.rockerToDamper,e.rockerPivotA),damperChassis:e.damperChassis,rodLen2:Rs(e.pushrodOuter,e.rockerToPushrod),damperLen0:ve(e.rockerToDamper,e.damperChassis)}}var lP=(e,t)=>ee(e.pivotA,Bt(e.rprRel0,e.axis,t)),Ud=(e,t)=>ee(e.pivotA,Bt(e.rdmRel0,e.axis,t));function Zo(e,t){return{pushrod:lP(e,t),damper:Ud(e,t)}}function lR(e,t,r=0){let n=X(e.rprRel0,e.axis),o=H(e.rprRel0,U(e.axis,n)),a=ae(e.axis,o),s=H(ee(e.pivotA,U(e.axis,n)),t),i=X(o,o),c=X(s,s),l=vs(2*X(s,o),2*X(s,a),e.rodLen2-c-i,2*Math.sqrt(i*c));if(l.free){let p=Math.abs(e.rodLen2-c-i)<=1e-9*e.rodLen2;return{phi:r,damperLength:ve(Ud(e,r),e.damperChassis),converged:p,margin:0}}let u=iR(Math.atan2(l.s1,l.c1),r),m=iR(Math.atan2(l.s2,l.c2),r),f=Math.abs(m-r)<Math.abs(u-r)?m:u;return{phi:f,damperLength:ve(Ud(e,f),e.damperChassis),converged:l.ok,margin:l.margin}}function iR(e,t){let r=2*Math.PI;return e+r*Math.round((t-e)/r)}function uR(e,t,r,n){return ee(t,st(U(q(r),n),H(e,t)))}function mR(e,t,r,n){let o=q(n),a=f=>{let p=H(f,r);return H(p,U(o,X(p,o)))},s=a(e),i=a(t),c=Math.hypot(s[0],s[1],s[2]),l=Math.hypot(i[0],i[1],i[2]);if(c<1e-9||l<1e-9)return 0;let u=Math.min(1,Math.max(-1,X(s,i)/(c*l))),m=X(ae(s,i),o)/(c*l);return Math.atan2(m,u)}function pR(e,t,r,n){return ee(t,st(U(q(r),n),H(e,t)))}var gl=180/Math.PI,uP=(e,t,r)=>Math.max(t,Math.min(r,e)),dR=[NaN,NaN,NaN];function Ms(e){let t=q(e.spinAxis),r=q(H(e.uprightUpper,e.uprightLower)),n=-Math.asin(uP(t[2],-1,1))*gl,o=Math.atan2(t[0],t[1])*gl,a=Math.atan2(-r[0],r[2])*gl,s=Math.atan2(-r[1],r[2])*gl,i=q(ee([0,0,-1],U(t,t[2]))),c=ee(e.wheelCenter,U(i,e.loadedRadius)),l=e.patchShift?[c[0]+e.patchShift.x,c[1]+e.patchShift.y,c[2]]:c,u=e.uprightLower,m=Math.abs(r[2])>1e-9,f=w=>ee(u,U(r,(w-u[2])/r[2])),p=m?f(l[2]):dR,d=m?f(e.wheelCenter[2]):dR,h=l[1]-p[1],b=p[0]-l[0],g=q(ae(t,[0,0,1])),y=ae([0,0,1],g),R=H(l,p),k=X(R,y),v=-X(R,g),x=e.wheelCenter[1]-d[1],M=d[0]-e.wheelCenter[0],F=Ux(e.tieOuter,u,r);return{camber:n,toe:o,caster:a,kpi:s,scrubRadius:h,mechanicalTrail:b,scrubAtWheel:k,trailAtWheel:v,kingpinOffset:x,casterOffset:M,steeringArm:F,contactPatch:l,kingpinGround:p,kingpinAtHub:d}}function rt(e){return{corner:e,inv:zd(e),rocker:cR(e.hardpoints)}}var mP=[20,20,20,.2,.2,.2];function hR(e,t,r,n=[0,0,0,0,0,0]){let o=sR(e,t,r,n);if(!o.free)return o;let a=pP(e,t,r,n);return{x:a.x,converged:a.converged,margin:0}}function pP(e,t,r,n=[0,0,0,0,0,0]){return Jx(o=>Wd(e,o,t,r),n,{scales:mP,tol:1e-10,maxIter:40})}var dP=.01,yl=1.2,dt=e=>e.ok?e.state:null,it=e=>e.ok?e.state:e.nearest;function ge(e,t,r,n,o){let a=0,s=Ie(e,a,r,n,o);if(Math.abs(s.travel-t)<1e-4)return fR(s,t,!1);let c=(Ie(e,.02,r,Xd(s),o).travel-s.travel)/.02;(!Number.isFinite(c)||Math.abs(c)<1e-6)&&(c=1);let l=f=>Math.max(-yl,Math.min(yl,f)),u=l((t-s.travel)/c),m=Ie(e,u,r,Xd(s),o);for(let f=0;f<12&&!(Math.abs(m.travel-t)<1e-4);f++){let p=m.travel-s.travel,d=Math.abs(p)<1e-9?u:u-(m.travel-t)*((u-a)/p);a=u,s=m,u=l(d),m=Ie(e,u,r,Xd(s),o)}return fR(m,t,Math.abs(u)===yl)}function fR(e,t,r){let n=e.travel-t,o=Math.abs(n)<=dP,a=r&&!o;return e.converged&&o?{ok:!0,reached:!0,travelMiss:n,clamped:!1,state:e}:{ok:!1,why:e.converged?"unreached":"unconverged",reached:o,travelMiss:n,clamped:a,nearest:e}}function Xd(e){return{q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle}}function fP(e,t,r,n,o){switch(e){case"upright":return $t(t,r,o.pushrodOuter);case"upperArm":{let a=$t(t,r,t.ubj0),s=mR(t.ubj0,a,t.ucaFront,t.ucaDir);return pR(o.pushrodOuter,t.ucaFront,t.ucaDir,s)}default:return uR(o.pushrodOuter,t.lcaFront,t.lcaDir,n)}}function Ie(e,t,r,n,o){let{inv:a,corner:s}=e,i=n?.q??[0,0,0,0,0,0],c=hR(a,t,r,i),l=c.x,u=[l[3],l[4],l[5]],m={t:[l[0],l[1],l[2]],omega:u},f=s.hardpoints,p=s.config,d=a.strut,h=d?d.top:$t(a,l,f.uprightUpper),b=$t(a,l,f.uprightLower),g=$t(a,l,f.tieOuter),y=$t(a,l,f.wheelCenter),R=q(st(u,p.spinAxis)),k=fP(d?"upright":p.pushrodAttach,a,l,t,f),v=d?d.top:f.damperChassis,x=d||p.actuation==="direct"?{phi:0,damperLength:ve(k,v),converged:!0,margin:1}:lR(e.rocker,k,n?.phi??0),M=Ms({uprightUpper:h,uprightLower:b,wheelCenter:y,spinAxis:R,tieOuter:g,loadedRadius:o?.loadedRadius??p.loadedRadius,patchShift:o?.patchShift});return{pose:m,beta:t,travel:l[2],steer:r,points:{uprightUpper:h,uprightLower:b,tieOuter:g,wheelCenter:y,pushrodOuter:k,spinAxis:R,contactPatch:M.contactPatch,kingpinGround:M.kingpinGround,kingpinAtHub:M.kingpinAtHub,rockerAngle:x.phi,damperLength:x.damperLength},metrics:{camber:M.camber,toe:M.toe,caster:M.caster,kpi:M.kpi,scrubRadius:M.scrubRadius,mechanicalTrail:M.mechanicalTrail,scrubAtWheel:M.scrubAtWheel,trailAtWheel:M.trailAtWheel,kingpinOffset:M.kingpinOffset,casterOffset:M.casterOffset,steeringArm:M.steeringArm,damperLength:x.damperLength},converged:c.converged&&x.converged,margin:Math.min(c.margin,x.margin)}}var Jo=e=>e==="FL"||e==="FR"?"front":"rear",gR=e=>e==="FL"||e==="RL"?"left":"right";function _e(e,t){return e.corners?.[t]??hP(e[Jo(t)],gR(t))}function yR(e){let t=e.config.springSplit;return e.config.actuation==="decoupled"||t===void 0||!Number.isFinite(t)||Math.abs(t)>=1?0:t}var bR=new WeakMap;function hP(e,t){let r=yR(e);if(r===0)return e;let n=bR.get(e);if(!n){let o=a=>{let{springSplit:s,...i}=e.config;return{...e,config:{...i,springRate:e.config.springRate*a},...e.measured?{measured:{...e.measured,springRate:e.measured.springRate*a}}:{}}};n={left:o(1-r),right:o(1+r)},bR.set(e,n)}return n[t]}var ir=["FL","FR","RL","RR"],Rt=e=>2*e.hardpoints.wheelCenter[1],Gt=(e,t)=>t?Rt(_e(e,"FL"))/2+Rt(_e(e,"FR"))/2:Rt(_e(e,"RL"))/2+Rt(_e(e,"RR"))/2;function Ze(e,t){let r=e==="FL"||e==="FR";return{axleX:r?t.frontAxleX:t.frontAxleX-t.wheelbase,sideSign:e==="FR"||e==="RR"?1:-1,isFront:r}}function Tt(e,t){return[t.axleX+e[0],t.sideSign*e[1],e[2]]}function Tr(e,t){return[e[0],t.sideSign*e[1],e[2]]}function un(e){return e.frontAxleX-e.wheelbase/2}function qd(e,t,r){return t[2]+e.heave+(t[0]-r)*Math.sin(e.pitch)-t[1]*Math.sin(e.roll)}function mn(e,t,r,n){let o=Ze(e,t),a=(n?Gt(n,o.isFront):o.isFront?t.trackFront:t.trackRear)/2,s=o.sideSign*a,i=o.axleX-un(t),c=-r.heave-i*Math.sin(r.pitch)+s*Math.sin(r.roll),l=o.isFront?o.sideSign*r.steer:0;return{travel:c,steer:l}}var bP={travelMin:-40,travelMax:40,steps:41,steer:0};function Ss(e){return{q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle}}function Ke(e,t={}){let r={...bP,...t},n=rt(e);return ea(n,r)}function ea(e,t){let r=t.steer,n=.01,o=Ie(e,n,r),a=Ie(e,-n,r),s=(o.travel-a.travel)/(2*n);(!Number.isFinite(s)||Math.abs(s)<1e-6)&&(s=1);let i=Math.max(Math.abs(t.travelMax),Math.abs(t.travelMin)),c=Math.min(1.2,1.5*i/Math.abs(s)),l=Math.max(20,t.steps*2),u=[],m=Ie(e,0,r);u.push({beta:0,travel:m.travel,warm:Ss(m),converged:m.converged});let f=Ss(m);for(let R=1;R<=l;R++){let k=c*R/l,v=Ie(e,k,r,f);f=Ss(v),u.push({beta:k,travel:v.travel,warm:f,converged:v.converged})}f=Ss(m);for(let R=1;R<=l;R++){let k=-c*R/l,v=Ie(e,k,r,f);f=Ss(v),u.push({beta:k,travel:v.travel,warm:f,converged:v.converged})}u.sort((R,k)=>R.beta-k.beta);let p=u[u.length-1].travel>=u[0].travel,d=!1;for(let R=1;R<u.length;R++){let k=u[R].travel-u[R-1].travel;(p&&k<-1e-6||!p&&k>1e-6)&&(d=!0)}let h=u.filter(R=>R.converged).map(R=>R.travel),b=h.length?[Math.min(...h),Math.max(...h)]:[0,0],g=h.length>0&&b[0]<=t.travelMin+1e-6&&b[1]>=t.travelMax-1e-6,y=[];for(let R=0;R<t.steps;R++){let k=t.steps===1?t.travelMin:t.travelMin+(t.travelMax-t.travelMin)*R/(t.steps-1),v=gP(u,k,p),x=yP(u,v);y.push(Ie(e,v,r,x))}return xP(y,e.corner.config.actuation==="decoupled"?0:e.corner.config.springRate),{samples:y,covered:g,reach:b,fold:d,unconverged:y.filter(R=>!R.converged).length}}function gP(e,t,r){let n=r?e.slice():e.slice().reverse();if(t<=n[0].travel)return n[0].beta;if(t>=n[n.length-1].travel)return n[n.length-1].beta;for(let o=1;o<n.length;o++){let a=n[o-1],s=n[o];if(t>=Math.min(a.travel,s.travel)&&t<=Math.max(a.travel,s.travel)){let i=s.travel-a.travel,c=Math.abs(i)<1e-9?0:(t-a.travel)/i;return a.beta+c*(s.beta-a.beta)}}return n[n.length-1].beta}function yP(e,t){let r=e[0],n=1/0;for(let o of e){let a=Math.abs(o.beta-t);a<n&&(n=a,r=o)}return r.warm}function Qd(e,t,r){return r===0?(e[1]-e[0])/(t[1]-t[0]):r===e.length-1?(e[r]-e[r-1])/(t[r]-t[r-1]):(e[r+1]-e[r-1])/(t[r+1]-t[r-1])}function xP(e,t){if(e.length<2)return;let r=e.map(s=>s.travel),n=e.map(s=>s.metrics.camber),o=e.map(s=>s.metrics.toe),a=e.map(s=>s.metrics.damperLength);for(let s=0;s<e.length;s++){let i=Qd(n,r,s),c=Qd(o,r,s),l=-Qd(a,r,s);e[s].metrics.camberGain=i,e[s].metrics.bumpSteer=c,e[s].metrics.motionRatio=l,e[s].metrics.wheelRate=t*l*l}}var xl=e=>e!==void 0&&Number.isFinite(e)&&e>0;function RP(e){return e&&xl(e.helperRate)&&xl(e.helperTravel)?{rate:e.helperRate,travel:e.helperTravel}:null}function Zd(e,t,r){let n=t/e;return r?n+Math.min(t/r.rate,r.travel):n}function As(e,t,r,n){if(!(e>0)||!Number.isFinite(e)||!(t>0)||!Number.isFinite(t))return null;let o=RP(n),a=-Zd(e,t,o),s=ta(r,n);return{rate:e,preload:t,helper:o,free:a,pull:null,droop:s.droop??a,droopStated:s.droop!==null,bump:s.bump,holdsLoad:!0}}function ta(e,t){if(!Number.isFinite(e))return{droop:null,bump:null};let r=xl(t?.extended)&&t.extended>e?t.extended:null,n=r!==null&&xl(t?.stroke)?r-t.stroke:null;return{droop:r!==null?e-r:null,bump:n!==null&&n<e?e-n:null}}function Jd(e,t){if(!(e>0)||!Number.isFinite(e))return null;let r=ta(t.length0,t.coilover),n=t.free===-1/0||t.pull!==null&&t.pull>=t.free;if(n&&r.droop===null&&r.bump===null)return null;let o=n?-1/0:t.free;return{rate:e,preload:o===-1/0?0:-e*o,helper:null,free:o,pull:n?null:t.pull,droop:r.droop??-1/0,droopStated:r.droop!==null,bump:r.bump,holdsLoad:!1}}function vP(e,t){let{rate:r,preload:n,helper:o}=e;if(!o)return t>e.free-1e-9?n+r*t:e.pull!==null&&t<e.pull+1e-9?r*(t-e.pull):0;let a=Zd(r,n,o)+t;if(a<=0)return 0;let s=o.rate*o.travel;return a>=s/r+o.travel?n>=s?n+r*t:r*(a-o.travel):a*r*o.rate/(r+o.rate)}function kP(e,t){let{rate:r,preload:n,helper:o}=e;if(!o)return t>e.free-1e-9||e.pull!==null&&t<e.pull+1e-9?r:0;let a=Zd(r,n,o)+t;return a<=0?0:a>=o.rate*o.travel/r+o.travel?r:r*o.rate/(r+o.rate)}function ra(e,t){let r=vP(e,t),n=e.free;return e.holdsLoad&&t<n&&e.droop<n&&(r+=.001*e.rate*(Math.max(t,e.droop)-n)),t<e.droop&&(r+=1e3*e.rate*(t-e.droop)),e.bump!==null&&t>e.bump&&(r+=1e3*e.rate*(t-e.bump)),r}function ef(e,t){let r=kP(e,t),n=e.free;return e.holdsLoad&&t<n&&t>e.droop&&(r+=.001*e.rate),t<e.droop&&(r+=1e3*e.rate),e.bump!==null&&t>e.bump&&(r+=1e3*e.rate),r}function tf(e){let t=e.free,r=[t,e.droop];return e.helper&&r.push(e.helper.rate*e.helper.travel/e.rate+e.helper.travel+t),e.bump!==null&&r.push(e.bump),e.pull!==null&&r.push(e.pull),[...new Set(r.filter(Number.isFinite))].sort((n,o)=>n-o)}var Rl={min:-60,max:60,steps:61},rf=e=>({travel:[e.min,e.max],force:[0,0],motionRatio:[0,0],spring:null}),xR=new WeakMap;function MP(e,t){let r=xR.get(e.corner);r||xR.set(e.corner,r=new Map);let n=`${t.min}|${t.max}|${t.steps}`,o=r.get(n);return o||r.set(n,o=ea(e,{travelMin:t.min,travelMax:t.max,steps:t.steps,steer:0})),o}function ws(e,t,r=Rl,n=e.corner.config.coilover){let o=e.corner.config;if(o.actuation==="decoupled")return rf(r);let a=MP(e,r),s=AP(e,o.springRate,a.samples),i=[];for(let h of a.samples){let b=h.metrics.motionRatio;!h.converged||b===void 0||!Number.isFinite(b)||!Number.isFinite(h.metrics.damperLength)||i.length>0&&h.travel<=i[i.length-1].t+1e-6||i.push({t:h.travel,L:h.metrics.damperLength,mr:b})}if(i.length<2)return rf(r);let c=wP(i,0);if(!(Math.abs(c.mr)>1e-6))return rf(r);let l=t/c.mr,u=As(s,l,c.L,n),m=u?SP(i,tf(u).map(h=>c.L-h)):i,f=m.map(h=>(u?ra(u,c.L-h.L):l+s*(c.L-h.L))*h.mr-t),p=h=>h===null?null:m.find(b=>b.L===c.L-h)?.t??null,d=u?tf(u).map(p).filter(h=>h!==null):[];return{travel:m.map(h=>h.t),force:f,motionRatio:m.map(h=>h.mr),spring:{rate:s,preload:l,length0:c.L,law:u},...u?{stops:{droop:p(u.droop),bump:p(u.bump)}}:{},...d.length?{kinks:d}:{},length:m.map(h=>h.L)}}function nf(e,t){if(!e.spring)return null;let r=e.travel.length,n=e.length;if(n&&n.length===r&&r>=2){let s=cr(e.travel,t),i=(t-e.travel[s])/(e.travel[s+1]-e.travel[s]);return e.spring.length0-(n[s]+i*(n[s+1]-n[s]))}if(r<2)return 0;let o=64,a=0;for(let s=0;s<o;s++){let i=t*s/o,c=t*(s+1)/o;a+=(Fs(e,i)+Fs(e,c))/2*(c-i)}return a}function SP(e,t){let r=[...e];for(let n of t)for(let o=0;o+1<e.length;o++){let a=e[o],s=e[o+1];if(a.L===n)break;if((a.L-n)*(s.L-n)>=0)continue;let i=(n-a.L)/(s.L-a.L);r.push({t:a.t+i*(s.t-a.t),L:n,mr:a.mr+i*(s.mr-a.mr)});break}return r.sort((n,o)=>n.t-o.t),r.filter((n,o)=>o===0||n.t>r[o-1].t+1e-6)}function AP(e,t,r){let n=e.corner.compliance?.links?.pushRod;if(n===void 0||!(n>0)||!Number.isFinite(n)||!(t>0))return t;let o=e.corner.config.actuation==="direct"?n:FP(e,n,r);return!(o>0)||!Number.isFinite(o)?t:t*o/(t+o)}function FP(e,t,r){let n;for(let m of r)m.converged&&(!n||Math.abs(m.travel)<Math.abs(n.travel))&&(n=m);if(!n)return t;let o=e.corner.hardpoints,a=Zo(e.rocker,n.points.rockerAngle),s=q(H(o.rockerPivotB,o.rockerPivotA)),i=(m,f)=>Math.abs(X(s,ae(H(m,o.rockerPivotA),q(H(f,m))))),c=i(a.pushrod,n.points.pushrodOuter),l=i(a.damper,o.damperChassis);if(!(l>1e-9)||!(c>1e-9))return t;let u=c/l;return t*u*u}function Fs(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.motionRatio[0];let n=cr(e.travel,t),o=(t-e.travel[n])/(e.travel[n+1]-e.travel[n]);return e.motionRatio[n]+o*(e.motionRatio[n+1]-e.motionRatio[n])}function Pr(e,t,r){if(!e.spring)return qt(e,t);let{rate:n,preload:o,length0:a,law:s}=e.spring,i=Fs(e,0),c=a-r;return(s?ra(s,c):o+n*c)*Fs(e,t)-o*i}function wP(e,t){let r=cr(e.map(s=>s.t),t),n=e[r],o=e[r+1],a=(t-n.t)/(o.t-n.t);return{L:n.L+a*(o.L-n.L),mr:n.mr+a*(o.mr-n.mr)}}function cr(e,t){let r=e.length;if(t<=e[0])return 0;if(t>=e[r-1])return r-2;let n=0,o=r-1;for(;o-n>1;){let a=n+o>>1;e[a]<=t?n=a:o=a}return n}function qt(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.force[0];let n=cr(e.travel,t),o=(t-e.travel[n])/(e.travel[n+1]-e.travel[n]);return e.force[n]+o*(e.force[n+1]-e.force[n])}function na(e,t){let r=e.travel.length;if(r<3)return Cs(e,t);let n=cr(e.travel,t),o=(e.force[n+1]-e.force[n])/(e.travel[n+1]-e.travel[n]),a=i=>i===0||i===r-1||e.kinks?.includes(e.travel[i])?o:(e.force[i+1]-e.force[i-1])/(e.travel[i+1]-e.travel[i-1]),s=Math.max(0,Math.min(1,(t-e.travel[n])/(e.travel[n+1]-e.travel[n])));return a(n)+s*(a(n+1)-a(n))}function Cs(e,t){if(e.travel.length<2)return 0;let n=cr(e.travel,t);return(e.force[n+1]-e.force[n])/(e.travel[n+1]-e.travel[n])}function De(e,t,r){let n=e.hardpoints;switch(t.attach){case"upright":{let o=H(t.outer,n.wheelCenter);return ee(ee(st(r.pose.omega,o),n.wheelCenter),r.pose.t)}case"lowerArm":{let o=q(H(n.lcaRear,n.lcaFront));return ee(n.lcaFront,st(U(o,r.beta),H(t.outer,n.lcaFront)))}case"rocker":{let o=q(H(n.rockerPivotB,n.rockerPivotA));return ee(n.rockerPivotA,Bt(H(t.outer,n.rockerPivotA),o,r.points.rockerAngle))}}}function pn(e,t,r){return e.config.actuation==="decoupled"&&t.attach==="rocker"&&r==="coil"}function of(e,t,r){return pn(e,t,r)?[t.inner[0],-t.inner[1],t.inner[2]]:t.inner}function oa(e,t,r){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return af(e,t,r.kind,Ke(e,{travelMin:n,travelMax:o,steps:a}).samples)}function af(e,t,r,n){let o=q(H(t.outer,of(e,t,r))),a=[],s=[],i=t.outer;for(let p of n)a.push(p.travel),s.push(X(H(De(e,t,p),i),o));let c=a.length,l=new Array(c).fill(0);for(let p=0;p<c;p++){let d=Math.max(0,p-1),h=Math.min(c-1,p+1),b=a[h]-a[d];l[p]=b!==0?(s[h]-s[d])/b:0}let u=l[0];for(let p=1;p<c;p++)if(a[p]>=0){let d=a[p]-a[p-1],h=d!==0?(0-a[p-1])/d:0;u=l[p-1]+h*(l[p]-l[p-1]);break}let m=l.filter(p=>Math.abs(p)>1e-9).map(Math.sign),f=m.length>0&&m.some(p=>p!==m[0]);return{travel:a,ratio:l,linkTravel:s,atDesign:u,reverses:f}}function sf(e,t){let{travel:r,ratio:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}function cf(e,t){let{travel:r,linkTravel:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}var Ts=e=>e.mount??{kind:"rockerToRocker"},MR=e=>[e[0],0,e[2]],CP=e=>2*Math.abs(e[1]),TP=(e,t)=>Math.hypot(e[0]-t[0],e[2]-t[2]);function kl(e,t){return t.kind==="chassis"?TP(e,t.anchor):CP(e)}function Ps(e,t,r){if(r.kind==="chassis"){let s=[(e[0]+t[0])/2,(e[1]-t[1])/2,(e[2]+t[2])/2];return Math.hypot(s[0]-r.anchor[0],s[1],s[2]-r.anchor[2])}let n=e[0]-t[0],o=e[1]+t[1],a=e[2]-t[2];return Math.hypot(n,o,a)}function Gn(e,t,r={}){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return lf(e,t,Ke(e,{travelMin:n,travelMax:o,steps:a}).samples)}function lf(e,t,r){let n=Ts(t),o=d=>De(e,{...t,inner:t.outer},r[d]),a=[],s=[],i=[];for(let d=0;d<r.length;d++)a.push(r[d].travel),i.push(kl(o(d),n));let c=vR(a,i,0);for(let d of i)s.push(c-d);let l=a.length,u=new Array(l).fill(0);for(let d=0;d<l;d++){let h=Math.max(0,d-1),b=Math.min(l-1,d+1),g=a[b]-a[h];u[d]=g!==0?(s[b]-s[h])/g:0}let m=RR(a,20),f=RR(a,-20),p=Ps(o(m),o(f),n);return{travel:a,ratio:u,springTravel:s,atDesign:vR(a,u,0),installedLength:c,rollSensitivity:c-p}}function RR(e,t){let r=0,n=1/0;for(let o=0;o<e.length;o++){let a=Math.abs(e[o]-t);a<n&&(n=a,r=o)}return r}function vR(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];for(let o=1;o<n;o++)if(e[o]>=r){let a=e[o]-e[o-1],s=a!==0?(r-e[o-1])/a:0;return t[o-1]+s*(t[o]-t[o-1])}return t[n-1]}function uf(e,t,r){let n={outer:t.outer,attach:t.attach},o=Ke(e,{travelMin:-5,travelMax:5,steps:3}),a=d=>MR(De(e,{...n,inner:n.outer},o.samples[d])),s=a(1),i=a(2),c=a(0),l=i[0]-c[0],u=i[2]-c[2],m=Math.hypot(l,u),f=m>1e-9?[l/m,u/m]:[0,1],p=r??Math.max(80,2*Math.abs(t.outer[1])*.5);return[s[0]+f[0]*p,0,s[2]+f[1]*p]}function mf(e,t){let r=e.hardpoints,n=r.rockerPivotA,o=kR(vl(r.rockerPivotB,r.rockerPivotA)),a=Math.max(30,.6*SR(vl(r.rockerToDamper,n))),s=vl(r.rockerToDamper,n),i=kR(vl(s,PP(o,LP(s,o)))),c=DP(o,i),l=null,u=-1/0;for(let m=0;m<360;m+=10){let f=m*Math.PI/180,d={outer:[n[0]+a*(Math.cos(f)*i[0]+Math.sin(f)*c[0]),n[1]+a*(Math.cos(f)*i[1]+Math.sin(f)*c[1]),n[2]+a*(Math.cos(f)*i[2]+Math.sin(f)*c[2])],attach:"rocker"},h=t==="chassis"?{...d,mount:{kind:"chassis",anchor:uf(e,d)}}:d,b;try{b=Gn(e,h,{travelMin:-20,travelMax:20,steps:9})}catch{continue}let g=b.atDesign/(1+4*Math.abs(b.rollSensitivity));Number.isFinite(g)&&g>u&&(u=g,l=h)}return l??{outer:r.rockerToDamper,attach:"rocker"}}var vl=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],PP=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],LP=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],SR=e=>Math.hypot(e[0],e[1],e[2]),kR=e=>{let t=SR(e)||1;return[e[0]/t,e[1]/t,e[2]/t]},DP=(e,t)=>[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]];var pf=.001,EP=e=>({outer:e.outer,inner:e.outer,attach:e.attach}),DR=(e,t,r)=>(kl(e.at0,t)-kl(r,t))/2,IP=(e,t)=>X(H(t,e.pickup.at0),e.axis);function df(e,t){let r=e.length;return t.map((n,o)=>{let a=Math.max(0,o-1),s=Math.min(r-1,o+1);return(t[s]-t[a])/(e[s]-e[a])})}function AR(e,t){let r=[0,1,2].map(n=>df(e,t.map(o=>o[n])));return t.map((n,o)=>[r[0][o],r[1][o],r[2][o]])}function ff(e){return{travel:e,heave:e.map(t=>t/2),heaveRatio:e.map(()=>.5),roll:[...e],rollRatio:e.map(()=>1)}}function FR(e,t,r,n){let o=e.corner;if(!t.heave&&!t.roll)return{side:ff([n.min,n.max]),pickups:{}};let a=it(ge(e,0,0)),s={};if(t.heave&&r){let h=EP(t.heave);s.heave={corner:o,link:h,at0:De(o,h,a)}}if(t.roll){let h=t.roll;s.roll={pickup:{corner:o,link:h,at0:De(o,h,a)},axis:q(H(h.outer,of(o,h,t.rollKind??"coil")))}}let i=t.roll&&pn(o,t.roll,t.rollKind??"coil")?{near:t.roll,far:{...t.roll,outer:t.roll.inner}}:null,c=ea(e,{travelMin:n.min,travelMax:n.max,steps:n.steps,steer:0}),l=[],u=[],m=[],f=[],p=[];for(let h of c.samples)!h.converged||l.length>0&&h.travel<=l[l.length-1]+1e-6||(l.push(h.travel),u.push(s.heave&&r?DR(s.heave,r,De(o,s.heave.link,h)):h.travel/2),m.push(s.roll?IP(s.roll,De(o,s.roll.pickup.link,h)):h.travel),i&&(f.push(De(o,i.near,h)),p.push(De(o,i.far,h))));if(l.length<2)return{side:ff([n.min,n.max]),pickups:{}};let d={travel:l,heave:u,heaveRatio:df(l,u),roll:m,rollRatio:df(l,m)};return i&&(d.eyes={near:f,nearRatio:AR(l,f),far:p,farRatio:AR(l,p)}),{side:d,pickups:s}}function Ml(e,t,r){let n=cr(e,r);return t[n]+(r-e[n])/(e[n+1]-e[n])*(t[n+1]-t[n])}function wR(e,t,r){let n=cr(e,r);return(t[n+1]-t[n])/(e[n+1]-e[n])}function Ne(e,t){return{h:Ml(e.travel,e.heave,t),dh:Ml(e.travel,e.heaveRatio,t),ddh:wR(e.travel,e.heaveRatio,t),r:Ml(e.travel,e.roll,t),dr:Ml(e.travel,e.rollRatio,t),ddr:wR(e.travel,e.rollRatio,t)}}function CR(e,t,r,n){let o=cr(e,n),a=e[o+1]-e[o],s=(n-e[o])/a,i=(u,m)=>[u[0]+s*(m[0]-u[0]),u[1]+s*(m[1]-u[1]),u[2]+s*(m[2]-u[2])],c=r[o],l=r[o+1];return{p:i(t[o],t[o+1]),d:i(c,l),dd:[(l[0]-c[0])/a,(l[1]-c[1])/a,(l[2]-c[2])/a]}}var hf=(e,t)=>Math.hypot(e[0]-t[0],e[1]+t[1],e[2]-t[2]);function bf(e,t){let r=e.side[0].eyes,n=e.side[1].eyes;if(!r||!n)return null;let o=CR(e.side[0].travel,r.near,r.nearRatio,t[0]),a=CR(e.side[1].travel,n.far,n.farRatio,t[1]),s=[o.p[0]-a.p[0],o.p[1]+a.p[1],o.p[2]-a.p[2]],i=Math.hypot(s[0],s[1],s[2]),c=[s[0]/i,s[1]/i,s[2]/i],l=o.d,u=[-a.d[0],a.d[1],-a.d[2]],m=[-a.dd[0],a.dd[1],-a.dd[2]],f=X(c,l),p=X(c,u),d=(X(l,u)-f*p)/i;return{L:i,dL:[f,p],ddL:[[(X(l,l)-f*f)/i+X(c,o.dd),d],[d,(X(u,u)-p*p)/i+X(c,m)]]}}var ER=(e,t)=>e.bump!==null&&t>e.bump?e.rate*(t-e.bump):e.droop!==null&&t<e.droop?e.rate*(t-e.droop):0,_P=(e,t)=>e.bump!==null&&t>e.bump||e.droop!==null&&t<e.droop?e.rate:0;function Ls(e,t,r,n,o=0){let a=e.rollStop;if(!a)return r;let s=bf(e,t);if(!s)return r;let i=ER(a,a.length0-(n??s.L+o));return i===0?r:[r[0]-i*s.dL[0],r[1]-i*s.dL[1]]}function Sl(e,t){let r=ff(e.travel);return t==="heave"?{...e,heave:r.heave,heaveRatio:r.heaveRatio}:{...e,roll:r.roll,rollRatio:r.rollRatio}}var Al=(e,t)=>e?e.law?ra(e.law,t):e.preload+e.rate*t:0,TR=(e,t)=>e?e.law?ef(e.law,t):e.rate:0;function Ds(e,t,r,n,o){let a=Al(e.heave,n),s=Al(e.roll,o);return[a*t.dh+s*t.dr,a*r.dh-s*r.dr]}var PR=(e,t)=>Ne(e[0],t).h+Ne(e[1],t).h;function NP(e,t){let r=e.gap>0?PR(t,e.gap):0;return e.bothWays?{free:r,pull:e.gap>0?PR(t,-e.gap):0}:{free:r,pull:null}}function OP(e,t,r){let n={...t,outer:t.inner},o=(u,m)=>{let f=dt(ge(e[0],u,0)),p=dt(ge(e[1],m,0));if(!f||!p)return NaN;let d=De(e[0].corner,t,f),h=De(e[1].corner,n,p);return Math.hypot(d[0]-h[0],d[1]+h[1],d[2]-h[2])},a=1,s=o(0,0),i=o(-a,a)-o(a,-a),c=Ne(r[0],a).r-Ne(r[1],-a).r-(Ne(r[0],-a).r-Ne(r[1],a).r),l=i/c;return Number.isFinite(s)&&s>0&&Number.isFinite(l)&&Math.abs(l)>pf?{length0:s,scale:l}:null}function IR(e,t,r,n=Rl){let o=r.heave?Ts(r.heave):void 0,a=FR(e[0],r,o,n),s=e[1].corner===e[0].corner?a:FR(e[1],r,o,n),i=[a.side,s.side],c=!!(a.pickups.heave&&s.pickups.heave),l=!!(a.pickups.roll&&s.pickups.roll),u=r.carriesLoad?void 0:r.heaveSeat,m=u?u.rate:(t[0].heaveRate+t[1].heaveRate)/2,f=(t[0].arbRate+t[1].arbRate)/2,p=i.map(S=>Ne(S,0));c&&!(Math.abs(p[0].dh+p[1].dh)>pf)&&(i=[Sl(i[0],"heave"),Sl(i[1],"heave")],c=!1),l&&!(Math.abs(p[0].dr+p[1].dr)>pf)&&(i=[Sl(i[0],"roll"),Sl(i[1],"roll")],l=!1),p=i.map(S=>Ne(S,0));let d=p[0].dh+p[1].dh,h=p[0].dr+p[1].dr,b=m>0?2*m/(d*d):0,g=f>0?2*f/(h*h):0,y=0,R=0;if(r.carriesLoad){let S=[t[0].springLoad,t[1].springLoad];if(b>0&&g>0){let C=-p[0].dh*p[1].dr-p[1].dh*p[0].dr;Math.abs(C)>1e-12&&(y=(-S[0]*p[1].dr-S[1]*p[0].dr)/C,R=(p[0].dh*S[1]-p[1].dh*S[0])/C)}else b>0?y=(S[0]+S[1])/d:g>0&&(R=(S[0]-S[1])/h)}let k={};if(c&&o){let S=[a.pickups.heave,s.pickups.heave];k.heave={pickups:S,mount:o,span0:Ps(S[0].at0,S[1].at0,o)}}let v=k.heave?k.heave.span0:NaN,x=k.heave?r.coilover:void 0,M=r.carriesLoad?As(b,y,v,x):u?Jd(b,{...NP(u,i),length0:v,coilover:x}):null,F=b>0?{rate:b,preload:y,...M?{law:M}:{}}:null;if(l&&(k.roll={pickups:[a.pickups.roll.pickup,s.pickups.roll.pickup],axes:[a.pickups.roll.axis,s.pickups.roll.axis]},r.roll&&pn(e[0].corner,r.roll,r.rollKind??"coil"))){let S=OP(e,r.roll,i);S&&(k.roll.unit=S)}let w=g>0?{rate:g,preload:R}:null,T={side:i,heave:F,roll:w,force0:[0,0],carriesLoad:r.carriesLoad,read:k},P=k.roll?.unit,A=P&&g>0&&i[0].eyes&&i[1].eyes?ta(P.length0,r.rollCoilover):null;return P&&A&&(A.droop!==null||A.bump!==null)&&(T.rollStop={length0:P.length0,rate:1e3*g/(P.scale*P.scale),...A}),T.force0=Ls(T,[0,0],Ds(T,p[0],p[1],p[0].h+p[1].h,p[0].r-p[1].r)),T}function Es(e,t,r){let n=Ne(e.side[0],t[0]),o=Ne(e.side[1],t[1]),a=r?Ls(e,t,Ds(e,n,o,n.h+o.h+r.heave,n.r-o.r+r.roll),void 0,r.unit):Ls(e,t,Ds(e,n,o,n.h+o.h,n.r-o.r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function gf(e,t,r){let n=Ne(e.side[0],t[0]),o=Ne(e.side[1],t[1]),a=r?n.h+o.h+r.heave:n.h+o.h,s=r?n.r-o.r+r.roll:n.r-o.r,i=TR(e.heave,a),c=TR(e.roll,s),l=Al(e.heave,a),u=Al(e.roll,s),m=i*n.dh*o.dh-c*n.dr*o.dr,f=[[i*n.dh*n.dh+l*n.ddh+c*n.dr*n.dr+u*n.ddr,m],[m,i*o.dh*o.dh+l*o.ddh+c*o.dr*o.dr-u*o.ddr]],p=e.rollStop,d=p?bf(e,t):null;if(!p||!d)return f;let h=p.length0-(r?d.L+r.unit:d.L),b=_P(p,h);if(b===0)return f;let g=ER(p,h),y=(k,v)=>b*d.dL[k]*d.dL[v]-g*d.ddL[k][v],R=m+y(0,1);return[[f[0][0]+y(0,0),R],[R,f[1][1]+y(1,1)]]}function yf(e,t,r){let n=gf(e,t);return n[r][0]+n[r][1]}function VP(e,t,r){let n=e.read.heave;if(!n)return Ne(e.side[0],t[0]).h+Ne(e.side[1],t[1]).h;let[o,a]=n.pickups;return n.span0-Ps(De(o.corner,o.link,r[0]),De(a.corner,a.link,r[1]),n.mount)}function BP(e,t,r){let n=e.read.roll;if(!n)return Ne(e.side[0],t[0]).r-Ne(e.side[1],t[1]).r;let o=a=>X(H(De(n.pickups[a].corner,n.pickups[a].link,r[a]),n.pickups[a].at0),n.axes[a]);return o(0)-o(1)}function $P(e,t){let r=e.read.roll;if(!e.rollStop||!r)return;let[n,o]=r.pickups;return hf(De(n.corner,n.link,t[0]),De(o.corner,{...o.link,outer:o.link.inner},t[1]))}function Is(e,t,r){let n=Ne(e.side[0],t[0]),o=Ne(e.side[1],t[1]),a=Ls(e,t,Ds(e,n,o,VP(e,t,r),BP(e,t,r)),$P(e,r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function xf(e,t,r,n){let o=Ne(e.side[0],r),a=Ne(e.side[1],r),s=e.read.heave,i=s?.pickups[t],c=s&&i&&n?2*DR(i,s.mount,De(i.corner,i.link,n)):o.h+a.h,l=e.rollStop&&n?e.read.roll?.pickups[t]:void 0,u=l&&n?hf(De(l.corner,l.link,n),De(l.corner,{...l.link,outer:l.link.inner},n)):void 0;return Ls(e,[r,r],Ds(e,o,a,c,n?0:o.r-a.r),u)[t]-e.force0[t]}function Rf(e,t,r,n){let o=na(e,r[n]);return t?.carriesLoad?o+yf(t,r,n):o}function _R(e,t){return Ne(e.side[0],t[0]).h+Ne(e.side[1],t[1]).h}function NR(e,t){return bf(e,t)?.L??null}var vf=e=>e==="FR"||e==="RR"?1:0,Fl=(e,t)=>e.elements?.[t==="FL"||t==="FR"?"front":"rear"]??null;var OR=e=>Number.isFinite(e)&&e>0?1/e:0;var VR=(e,t)=>{let r=e[0][0]*e[1][1]-e[0][1]*e[1][0];return Math.abs(r)>1e-14?[(t[0]*e[1][1]-t[1]*e[0][1])/r,(e[0][0]*t[1]-e[1][0]*t[0])/r]:null},GP=(e,t)=>[e[0][0]*t[0]+e[0][1]*t[1],e[1][0]*t[0]+e[1][1]*t[1]],BR=1e-8,KP=40;function HP(e,t,r,n){return{force:(s,i)=>{if(r){let u=Es(r,s,n);return[qt(t[0],s[0])+i[0]+u[0],qt(t[1],s[1])+i[1]+u[1]]}let c=(s[0]+s[1])/2,l=(s[0]-s[1])/2;return[qt(t[0],s[0])+i[0]+e[0].heaveRate*c+e[0].arbRate*l,qt(t[1],s[1])+i[1]+e[1].heaveRate*c-e[1].arbRate*l]},stiffness:(s,i=Cs)=>{if(r){let c=gf(r,s,n);return[[i(t[0],s[0])+c[0][0],c[0][1]],[c[1][0],i(t[1],s[1])+c[1][1]]]}return[[i(t[0],s[0])+e[0].heaveRate/2+e[0].arbRate/2,e[0].heaveRate/2-e[0].arbRate/2],[e[1].heaveRate/2-e[1].arbRate/2,i(t[1],s[1])+e[1].heaveRate/2+e[1].arbRate/2]]}}}function aa(e,t,r,n,o,a=[0,0],s=[0,0],i=null,c){let l=[OR(r[0].tyreRate),OR(r[1].tyreRate)],u=[r[0].staticLoad,r[1].staticLoad],m=HP(r,n,i,c),f=C=>m.force(C,a),p=m.stiffness([0,0]),d=[l[0]>0?l[0]:1/Math.max(1,Math.abs(p[0][0])),l[1]>0?l[1]:1/Math.max(1,Math.abs(p[1][1]))],h=(C,L)=>{let D=L===1?f(C):m.force(C,[a[0]*L,a[1]*L]),I=[D[0]+s[0]*L,D[1]+s[1]*L],O=[C[0]+t[0]*L+I[0]*l[0]-e[0]*L,C[1]+t[1]*L+I[1]*l[1]-e[1]*L],N=[d[0]*(u[0]+I[0]),d[1]*(u[1]+I[1])],z=[N[0]<O[0],N[1]<O[1]];return{f:I,on:O,off:N,lifted:z,r:[Math.min(O[0],N[0]),Math.min(O[1],N[1])]}},b=(C,L)=>[L[0]?[d[0]*C[0][0],d[0]*C[0][1]]:[1+C[0][0]*l[0],C[0][1]*l[0]],L[1]?[d[1]*C[1][0],d[1]*C[1][1]]:[C[1][0]*l[1],1+C[1][1]*l[1]]],g=C=>Math.max(Math.abs(C[0]),Math.abs(C[1])),y=(C,L)=>{let D=[C[0],C[1]],I=h(D,L),O=!1,N=0;for(;N<KP;N++){if(g(I.r)<BR){O=!0;break}let z=VR(b(m.stiffness(D),I.lifted),[-I.r[0],-I.r[1]]);if(!z)break;let E=1,_=[D[0]+z[0],D[1]+z[1]],B=h(_,L);for(let V=0;V<8&&g(B.r)>g(I.r);V++)E/=2,_=[D[0]+E*z[0],D[1]+E*z[1]],B=h(_,L);D=_,I=B}return!O&&g(I.r)<BR&&(O=!0),{t:D,b:I,converged:O,it:N}},R=y(o?[o[0],o[1]]:[e[0]-t[0],e[1]-t[1]],1),k=R.it;if(!R.converged){let C=0,L=[0,0],D=.25;for(;C<1&&D>=1/256;){let I=Math.min(1,C+D),O=y(L,I);k+=O.it,O.converged?(C=I,L=O.t,I===1&&(R=O)):D/=2}}let{t:v,b:x,converged:M}=R,F=x.lifted,w=[F[0]?-u[0]:x.f[0],F[1]?-u[1]:x.f[1]],T=[F[0]?Math.max(0,x.on[0]):0,F[1]?Math.max(0,x.on[1]):0],P=m.stiffness(v,na),A=b(P,F);return{t:v,dF:w,lifted:F,clearance:T,converged:M,iterations:k,respond:(C,L,D=[0,0])=>{let I=[F[0]?-d[0]*D[0]:C[0]-L[0]-D[0]*l[0],F[1]?-d[1]*D[1]:C[1]-L[1]-D[1]*l[1]],O=VR(A,I);if(!O)return[NaN,NaN];let N=GP(P,O);return[F[0]?0:N[0]+D[0],F[1]?0:N[1]+D[1]]}}}var Kn=e=>!(Number.isFinite(e.tyreRate)&&e.tyreRate>0);function Kt(e,t,r){return t?.input.corners[r].staticLoadedRadius??e}var kf=["FL","FR","RL","RR"],KR={front:["FL","FR"],rear:["RL","RR"]},zP=512,YP=5e-4,WP=8;function wl(e,t){let r={},n={},o=new Map;for(let s of kf){let i=e.ctx[s],c=t.corners[s],l=c.staticLoadedRadius;n[s]=it(ge(i,0,0,void 0,l===void 0?void 0:{loadedRadius:l})).points.contactPatch[2];let u=t.cornerCoilover?.[s==="FL"||s==="FR"?"front":"rear"],m=`${kf.findIndex(p=>_e(e.vehicle,p)===_e(e.vehicle,s))}|${c.springLoad}|${u?`${u.extended}/${u.stroke}`:""}`,f=o.get(m);f?r[s]=f:(r[s]=u?ws(i,c.springLoad,void 0,u):ws(i,c.springLoad),o.set(m,r[s]))}let a={front:null,rear:null};for(let s of["front","rear"]){let i=t.elements?.[s];if(!i)continue;let c=KR[s];a[s]=IR([e.ctx[c[0]],e.ctx[c[1]]],[t.corners[c[0]],t.corners[c[1]]],i)}return{input:t,curve:r,elements:a,ground0:n,memo:new Map}}function HR(e,t,r){if(!(r>0)||!Number.isFinite(r)||!Number.isFinite(t)||t<=0)return 0;let n=Math.min(t/r,e);return 2*Math.sqrt(Math.max(0,2*e*n-n*n))}var jP=e=>`${e.heave}|${e.pitch}|${e.roll}|${e.steer}`;function Mf(e,t,r){return{travel:r.travel,steer:r.steer,ground:r.travel,tyreDeflection:0,load:NaN,loadedRadius:Kt(_e(e.vehicle,t).config.loadedRadius,e.kc,t),lifted:!1,contactLength:0,converged:!0,rigid:!0,rideRate:NaN,wheelRateAtLoad:NaN}}var UP=e=>e?{q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle}:void 0;function $R(e,t,r,n){let o=KR[n],a=e.vehicle.config,s=o.map(w=>mn(w,a,r,e.vehicle)),i=[t.input.corners[o[0]],t.input.corners[o[1]]],c=t.loadCase;if(!c&&i.every(Kn))return{corners:[Mf(e,o[0],s[0]),Mf(e,o[1],s[1])],respond:null};let l=o.map(w=>t.curve[w]),u=t.elements?.[n]??null,m=o.map(w=>Kt(_e(e.vehicle,w).config.loadedRadius,t,w)),f=[s[0].travel+(c?.ground[o[0]]??0),s[1].travel+(c?.ground[o[1]]??0)],p=[c?.linkLoad[o[0]]??0,c?.linkLoad[o[1]]??0],d=[c?.patchShift[o[0]],c?.patchShift[o[1]]],h=[0,0],b=[0,0],g,y=aa(f,h,i,l,void 0,void 0,p,u),R=[void 0,void 0],k=[!0,!0],v=[0,0],x=!1;for(let w=0;w<WP;w++){w>0&&(y=aa(f,h,i,l,g,b,p,u)),v=[Number.isFinite(i[0].tyreRate)&&i[0].tyreRate>0?y.dF[0]/i[0].tyreRate:0,Number.isFinite(i[1].tyreRate)&&i[1].tyreRate>0?y.dF[1]/i[1].tyreRate:0];let T=[0,0],P=[0,0];for(let S=0;S<2;S++){let C=ge(e.ctx[o[S]],y.t[S],s[S].steer,UP(R[S]),{loadedRadius:m[S]-v[S],patchShift:d[S]}),L=it(C);R[S]=L,k[S]=C.ok,T[S]=L.points.contactPatch[2]-t.ground0[o[S]]-y.t[S]-v[S],P[S]=Pr(l[S],y.t[S],L.points.damperLength)-qt(l[S],y.t[S])}if(u){let S=Is(u,y.t,[R[0],R[1]]),C=Es(u,y.t);P[0]+=S[0]-C[0],P[1]+=S[1]-C[1]}let A=Math.max(Math.abs(T[0]-h[0]),Math.abs(T[1]-h[1]),Math.abs(P[0]-b[0])/Math.max(1,i[0].tyreRate),Math.abs(P[1]-b[1])/Math.max(1,i[1].tyreRate));if(h=T,b=P,g=y.t,A<YP){x=!0;break}}let M=y.respond([1,1],[0,0]);return{corners:[0,1].map(w=>{let T=R[w];return{travel:y.t[w],steer:s[w].steer,ground:f[w],tyreDeflection:v[w],load:i[w].staticLoad+y.dF[w],loadedRadius:m[w]-v[w],lifted:y.lifted[w],clearance:y.clearance[w],contactLength:HR(m[w]-v[w],i[w].staticLoad+y.dF[w],i[w].tyreRate),converged:y.converged&&x&&k[w],rigid:!1,state:T,solved:k[w],rideRate:M[w],wheelRateAtLoad:Rf(l[w],u,y.t,w)}}),respond:y.respond}}function zR(e,t){let r=e.kc,n=jP(t),o=r.memo.get(n);if(o)return o;let a=$R(e,r,t,"front"),s=$R(e,r,t,"rear"),i={corners:{FL:a.corners[0],FR:a.corners[1],RL:s.corners[0],RR:s.corners[1]},respond:{front:a.respond,rear:s.respond}};return r.memo.size>=zP&&r.memo.clear(),r.memo.set(n,i),i}function vt(e,t){if(!e.kc){let r={};for(let n of kf)r[n]=Mf(e,n,mn(n,e.vehicle.config,t,e.vehicle));return r}return zR(e,t).corners}function Cl(e,t,r){return e.kc?zR(e,t).respond[r]:null}function _s(e,t,r,n=0){let o=e.kc;if(!o)return r;let a=o.input.corners[t];if(Kn(a))return r;let s=mn(t,e.vehicle.config,{heave:0,pitch:0,roll:0,steer:n},e.vehicle).steer,i=Kt(_e(e.vehicle,t).config.loadedRadius,o,t),c=o.loadCase,l=c?.linkLoad[t]??0,u=c?.patchShift[t],m=it(ge(e.ctx[t],r,s,void 0,{loadedRadius:i,patchShift:u})),f=Fl(o,t),p=Pr(o.curve[t],r,m.points.damperLength)+(f?xf(f,vf(t),r,m):a.heaveRate*r),h=Math.max(p+l,-a.staticLoad)/a.tyreRate;return(h===0?m:it(ge(e.ctx[t],r,s,void 0,{loadedRadius:i-h,patchShift:u}))).points.contactPatch[2]-o.ground0[t]-(c?.ground[t]??0)}var XP=180/Math.PI,qP=[0,0,1];function QP(e,t){let r=Tr(e,t),n=U(ae(qP,r),-t.sideSign);return-Math.atan2(n[1],n[0])*XP}var YR=e=>1/Math.tan(e*Math.PI/180),WR=.05,jR=.001;function UR(e,t,r){if(!Number.isFinite(e)||!Number.isFinite(t))return NaN;if(!(Math.abs(e)<jR&&Math.abs(t)<jR))return e>0&&t>0?100*(YR(t)-YR(e))/r:NaN}function ZP(e,t){let r=Gt(e.vehicle,!0)/e.vehicle.config.wheelbase,n=t("FL",0).deg,o=t("FR",0).deg,a=(c,l)=>{let u=c+l>=0;return{left:u,inner:u?c:-l,outer:u?l:-c}},s,i=()=>{if(s===void 0){let c=[WR,-WR].map(l=>{let{inner:u,outer:m}=a(t("FL",l).deg-n,t("FR",l).deg-o);return UR(u,m,r)??NaN});s=(c[0]+c[1])/2}return s};return c=>{let l=t("FL",c),u=t("FR",c),{left:m,inner:f,outer:p}=a(l.deg-n,u.deg-o),d=UR(f,p,r);return{steerL:l.deg,steerR:u.deg,inner:f,outer:p,toeDiff:f-p,ackermannPct:d??i(),inside:d===void 0?null:m?"left":"right",converged:l.ok&&u.ok}}}function Sf(e,t){let r=e.vehicle.config,n={FL:Ze("FL",r),FR:Ze("FR",r)},o=t.travel??0,a=ZP(e,(i,c)=>{let l=dt(ge(e.ctx[i],o,n[i].sideSign*c));return{deg:l?QP(l.points.spinAxis,n[i]):NaN,ok:l!==null}}),s=[];for(let i=0;i<t.steps;i++){let c=t.steps===1?0:-t.steerMax+2*t.steerMax*i/(t.steps-1),{inside:l,...u}=a(c);s.push({steerInput:c,...u})}return s}var XR=35,qR=55,kt=e=>e.rackTravel&&e.rackTravel>0?e.rackTravel:XR,Af=e=>e.rackRatio&&e.rackRatio>0?e.rackRatio:qR;var Ff=e=>({q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle});function QR(e,t,r,n,o){let a=ge(e,n,0,void 0,o),s=it(a),i=a.ok?0:1,c=s.points.contactPatch[2],l={steer:s.metrics.toe,camber:s.metrics.camber,lift:0,contactPatch:s.points.contactPatch,spinAxis:s.points.spinAxis,yaw:-s.metrics.toe*Math.PI/180},u=p=>{let d=[l],h=Ff(s);for(let b=1;b<=r;b++){let g=p*(t*b)/r,y=Ie(e,s.beta,g,h,o),R=dt(ge(e,n,g,Ff(y),o));if(!R||!y.converged){i++,d.push({...d[d.length-1]});continue}d.push({steer:R.metrics.toe,camber:R.metrics.camber,lift:-(y.points.contactPatch[2]-c),contactPatch:y.points.contactPatch,spinAxis:y.points.spinAxis,yaw:-y.metrics.toe*Math.PI/180}),h=Ff(y)}return d},m=u(1),f=u(-1);return{travelMm:n,unsolved:i,centre:l,positive:m,negative:f}}function JP(e,t){return e.map((r,n)=>{let o=n===0?0:n-1,a=n===e.length-1?e.length-1:n+1,s=t[a]-t[o];if(!(s>0))return{longitudinal:0,lateral:0,vertical:0,yaw:0};let i=U(H(e[a].contactPatch,e[o].contactPatch),1/s),c=q(ae(r.spinAxis,[0,0,1])),l=ae([0,0,1],c);return{longitudinal:X(i,c),lateral:X(i,l),vertical:i[2],yaw:(e[a].yaw-e[o].yaw)/s}})}function ZR(e,t,r){let n=o=>({steerDeg:o.map(a=>Math.abs(a.steer-e.centre.steer)),camberDeg:o.map(a=>a.camber-e.centre.camber),liftMm:o.map(a=>a.lift),jacobian:JP(o,t)});return{travelMm:e.travelMm,inner:n(r?e.positive:e.negative),outer:n(r?e.negative:e.positive)}}function eL(e){return e.positive[1].steer-e.centre.steer<0}function tL(e,t,r){return{meanDeg:t.map((n,o)=>.5*(r.inner.steerDeg[o]+r.outer.steerDeg[o])),innerDeg:r.inner.steerDeg,outerDeg:r.outer.steerDeg,innerCamber:r.inner.camberDeg,outerCamber:r.outer.camberDeg,innerLift:r.inner.liftMm,outerLift:r.outer.liftMm,rackRatioMmPerRev:Af(e.config),innerJacobian:r.inner.jacobian,outerJacobian:r.outer.jacobian}}function wf(e,t,r=13,n=-40,o=40,a=5,s){let i=rt(e),c=Array.from({length:r+1},(b,g)=>t*g/r),l=QR(i,t,r,0,s),u=eL(l),m=ZR(l,c,u),f=Math.max(2,Math.floor(a)),p=Array.from({length:f},(b,g)=>n+(o-n)*g/(f-1));p.some(b=>Math.abs(b)<1e-9)||p.push(0),p.sort((b,g)=>b-g);let d=l.unsolved,h=p.map(b=>{if(Math.abs(b)<1e-9)return m;let g=QR(i,t,r,b,s);return d+=g.unsolved,ZR(g,c,u)});return{...tL(e,c,m),...JR(l.unsolved),travelSurface:{rackMm:c,rows:h,...JR(d)}}}var JR=e=>e>0?{unsolved:e}:{};function lr(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function Tl(e,t,r){let n=e.length;if(n===0)return{longitudinal:0,lateral:0,vertical:0,yaw:0};let o,a;if(r<=e[0])o=a=0;else if(r>=e[n-1])o=a=n-1;else for(o=0,a=n-1;a-o>1;){let l=o+a>>1;e[l]<=r?o=l:a=l}let s=t[o];if(o===a)return{longitudinal:s.longitudinal,lateral:s.lateral,vertical:s.vertical,yaw:s.yaw};let i=t[a],c=(r-e[o])/(e[a]-e[o]);return{longitudinal:s.longitudinal+c*(i.longitudinal-s.longitudinal),lateral:s.lateral+c*(i.lateral-s.lateral),vertical:s.vertical+c*(i.vertical-s.vertical),yaw:s.yaw+c*(i.yaw-s.yaw)}}function ev(e,t){let r=e.rows;if(r.length<=1||t<=r[0].travelMm)return{lo:0,hi:0,t:0};let n=r.length-1;if(t>=r[n].travelMm)return{lo:n,hi:n,t:0};let o=0,a=n;for(;a-o>1;){let s=o+a>>1;r[s].travelMm<=t?o=s:a=s}return{lo:o,hi:a,t:(t-r[o].travelMm)/(r[a].travelMm-r[o].travelMm)}}var Hn=(e,t,r)=>e+r*(t-e);function sa(e,t,r,n,o){let a=lr(e.rackMm,e.rows[n.lo][t][r],o);if(n.lo===n.hi)return a;let s=lr(e.rackMm,e.rows[n.hi][t][r],o);return Hn(a,s,n.t)}function tv(e,t,r,n){let o=Tl(e.rackMm,e.rows[r.lo][t].jacobian,n);if(r.lo===r.hi)return o;let a=Tl(e.rackMm,e.rows[r.hi][t].jacobian,n);return{longitudinal:Hn(o.longitudinal,a.longitudinal,r.t),lateral:Hn(o.lateral,a.lateral,r.t),vertical:Hn(o.vertical,a.vertical,r.t),yaw:Hn(o.yaw,a.yaw,r.t)}}function ia(e,t,r,n){let o=e.travelSurface;if(!o||o.rackMm.length<2||o.rows.length===0)return ca(e,t);let a=ev(o,r),s=ev(o,n),i=(p,d,h)=>{let b=o.rows[d.lo][p].steerDeg[h];return d.lo===d.hi?b:Hn(b,o.rows[d.hi][p].steerDeg[h],d.t)},c=new Array(o.rackMm.length);for(let p=0;p<c.length;p++)c[p]=.5*(i("inner",a,p)+i("outer",s,p));let l=Math.max(0,t),u=c.length-1,m=o.rackMm[u],f=l>c[u];if(l<=c[0])m=o.rackMm[0],f=!1;else if(!f){let p=1;for(;p<c.length-1&&c[p]<l;)p++;let d=p-1,h=c[p]-c[d],b=Math.abs(h)>1e-12?(l-c[d])/h:0;m=Hn(o.rackMm[d],o.rackMm[p],b)}return{innerDeg:sa(o,"inner","steerDeg",a,m),outerDeg:sa(o,"outer","steerDeg",s,m),innerCamber:sa(o,"inner","camberDeg",a,m),outerCamber:sa(o,"outer","camberDeg",s,m),innerLift:sa(o,"inner","liftMm",a,m),outerLift:sa(o,"outer","liftMm",s,m),innerJacobian:tv(o,"inner",a,m),outerJacobian:tv(o,"outer",s,m),atLock:f}}function ca(e,t){let r=e.meanDeg.length-1;return{innerDeg:lr(e.meanDeg,e.innerDeg,t),outerDeg:lr(e.meanDeg,e.outerDeg,t),innerCamber:lr(e.meanDeg,e.innerCamber,t),outerCamber:lr(e.meanDeg,e.outerCamber,t),innerLift:e.innerLift?lr(e.meanDeg,e.innerLift,t):0,outerLift:e.outerLift?lr(e.meanDeg,e.outerLift,t):0,...e.innerJacobian&&e.outerJacobian?{innerJacobian:Tl(e.meanDeg,e.innerJacobian,t),outerJacobian:Tl(e.meanDeg,e.outerJacobian,t)}:{},atLock:r>=0&&t>e.meanDeg[r]}}var rL=()=>({lift:{FL:0,FR:0,RL:0,RR:0},travel:{FL:0,FR:0,RL:0,RR:0},load:{FL:0,FR:0,RL:0,RR:0},rollDeg:0});function la(e,t,r=we(e),n){let o=e.steerFront;if(!o?.innerLift||!o.outerLift||o.meanDeg.length<2||Math.abs(t)<1e-12)return rL();let a=Math.abs(t),s=t>0,i=n&&o.travelSurface?ia(o,a,s?n.FL:n.FR,s?n.FR:n.FL):null,c=i?.innerLift??lr(o.meanDeg,o.innerLift,a),l=i?.outerLift??lr(o.meanDeg,o.outerLift,a),u=s?c:l,m=s?l:c,f=.5*(u+m),p=r.rollWheelRateFront,d=r.rollWheelRateRear,h=e.trackFront,b=e.trackRear,g=p*h*h+d*b*b,y=g>0?p*h*(m-u)/g:0,R={FL:u-f+.5*h*y,FR:m-f-.5*h*y,RL:.5*b*y,RR:-.5*b*y};return{lift:{FL:u,FR:m,RL:0,RR:0},travel:R,load:{FL:p*R.FL,FR:p*R.FR,RL:d*R.RL,RR:d*R.RR},rollDeg:y===0?0:-Math.atan(y)*180/Math.PI}}function Cf(e,t,r){let n=t/r,o=a=>1/Math.tan(a*Math.PI/180);for(let a=0;a<e.meanDeg.length;a++)if(e.outerDeg[a]>.3&&e.innerDeg[a]>.3)return 100*(o(e.outerDeg[a])-o(e.innerDeg[a]))/n;return NaN}var Ns=9.81;function ua(e,t,r=0,n=0,o=0){if(!e.aero||t<=0)return{FL:0,FR:0,RL:0,RR:0};let a=e.aero.model?Cr(e,t,r,sn(e,n,o)):Bn(e.aero,t),s=a.downFront/2,i=a.downRear/2,c=a.drag*(e.aero.copHeight/1e3)/(e.wheelbase/1e3)/2;return{FL:s-c,FR:s-c,RL:i+c,RR:i+c}}function Tf(e,t,r=0,n=0,o=0){if(!e.aero?.model||t<=0)return!1;let a=Cr(e,t,r,sn(e,n,o));return a!=null&&(a.clampedRide||a.clampedAttitude)}function zn(e){let t=e.loadFactor===void 0?e.massTotal*Ns:e.massTotal*Ns*e.loadFactor,r=t*e.frontMassFrac,n=t*(1-e.frontMassFrac);return{FL:r/2,FR:r/2,RL:n/2,RR:n/2}}function rv(e,t=we(e),r=e.cgHeight){let n=e.trackFront/1e3,o=e.trackRear/1e3,a=e.rcHeightFront/1e3,s=e.rcHeightRear/1e3,i=(e.rcHeightFront+(e.rcHeightRear-e.rcHeightFront)*(1-e.frontMassFrac))/1e3,c=r/1e3-i,l=2*e.unsprungPerCorner,u=e.unsprungCgHeight/1e3,m=t.sprungMass*c*il(t.sprungMass,c,t.rollRateTotal),f=(m*t.frontRollStiffFrac+t.sprungFront*a+l*u)/n,p=(m*(1-t.frontRollStiffFrac)+t.sprungRear*s+l*u)/o;return{cf:f,cr:p}}function Pf(e){let{cf:t,cr:r}=rv(e);return t+r>0?t/(t+r):.5}function nv(e,t,r){if(e.FL>=0&&e.FR>=0&&e.RL>=0&&e.RR>=0)return{loads:{FL:Math.max(0,e.FL),FR:Math.max(0,e.FR),RL:Math.max(0,e.RL),RR:Math.max(0,e.RR)},lifted:{FL:!1,FR:!1,RL:!1,RR:!1},overturned:!1};let n=e.FL+e.FR+e.RL+e.RR;if(!(n>0))return{loads:{FL:0,FR:0,RL:0,RR:0},lifted:{FL:!0,FR:!0,RL:!0,RR:!0},overturned:!0};let o=!1,a=e.FL+e.FR,s=e.RL+e.RR;a<0?(a=0,s=n,o=!0):s<0&&(s=0,a=n,o=!0);let i=(e.FR-e.FL)*t+(e.RR-e.RL)*r,c=Math.min(a,Math.max(-a,e.FR-e.FL)),l=Math.min(s,Math.max(-s,e.RR-e.RL)),u=i-(c*t+l*r);if(u!==0){let f=u>0?1:-1,p=(f*a-c)*t;f*u>=f*p?(c=f*a,u-=p):(c+=u/t,u=0);let d=(f*s-l)*r;u!==0&&(f*u>=f*d?(l=f*s,u-=d):(l+=u/r,u=0)),Math.abs(u)>1e-9*(Math.abs(i)+n*(t+r))&&(o=!0)}let m={FL:Math.max(0,(a-c)/2),FR:Math.max(0,(a+c)/2),RL:Math.max(0,(s-l)/2),RR:Math.max(0,(s+l)/2)};return{loads:m,lifted:{FL:m.FL===0,FR:m.FR===0,RL:m.RL===0,RR:m.RR===0},overturned:o}}function Ce(e,t,r,n=0,o=0,a=0,s,i){return Pl(e,t,r,n,o,a,s,i).loads}function Pl(e,t,r,n=0,o=0,a=0,s,i){let c=zn(e),l=we(e),u=hl(e,n,r,sn(e,t,o),l),{cf:m,cr:f}=rv(e,l,u.height),p=m*t*Ns,d=f*t*Ns,h=e.massTotal*(r*Ns)*u.height/e.wheelbase-u.noseLoad,b=ua(e,n,r,t,o),g=(i??la(e,a,l,s)).load,y={FL:c.FL-p-h/2+b.FL+g.FL,FR:c.FR+p-h/2+b.FR+g.FR,RL:c.RL-d+h/2+b.RL+g.RL,RR:c.RR+d+h/2+b.RR+g.RR};return nv(y,e.trackFront,e.trackRear)}var Lf=Math.PI/180;function Dl(e,t){let r=8*Lf,n=0,o=0;for(let a=1;a<=90;a++){let s=a*.5,i=Math.abs(e.Fy(s*Lf,t,0));if(i>n&&(n=i,r=s*Lf,o=a),a>o+12&&i<.995*n)break}return{aPeak:r,fyPeak:n}}function ov(e,t,r,n,o){if(n===t)return r;let a=(o-t)/(n-t);return a<=0?e:a>=1?r:e+a*(r-e)}var Vs=.999;function Pt(e,t,r,n,o){if(t<=0)return 0;let{aPeak:a,fyPeak:s}=o??Dl(e,t),i=Math.min(Math.abs(r),Vs*s),c=n?-1:1,l=(v,x)=>Math.abs(e.forces({Fz:t,kappa:c*v,alpha:x}).Fy),u=.3,m=u,f=l(u,a);if(f<i){let v=0,x=u,M=NaN,F=f;for(let w=0;w<9;w++){let T=.5*(v+x),P=l(T,a);P>=i?(v=T,M=P):(x=T,F=P)}Number.isNaN(M)&&(M=l(0,a)),m=M<i?0:ov(v,M,x,F,i)}if(m<=0)return 0;let p=v=>{if(i===0)return c*e.forces({Fz:t,kappa:c*v,alpha:0}).Fx;let x=0,M=a,F=NaN,w=NaN;for(let T=0;T<5;T++){let P=.5*(x+M),A=l(v,P);A<i?(x=P,F=A):(M=P,w=A)}return Number.isNaN(F)&&(F=l(v,0)),Number.isNaN(w)&&(w=l(v,a)),c*e.forces({Fz:t,kappa:c*v,alpha:ov(x,F,M,w,i)}).Fx},d=4,h=v=>m*v/d,b=[0],g=1;for(let v=1;v<=d;v++)b.push(p(h(v))),b[v]>b[g]&&(g=v);let[y,R]=g===d?[d-1,d-2]:b[g-1]>=b[g+1]?[g-1,g+1]:[g+1,g-1],k=sL(p,h(g-1),h(Math.min(d,g+1)),h(g),b[g],h(y),b[y],h(R),b[R],nL);return c*Math.max(0,k)}var nL=.01,oL=20,aL=(3-Math.sqrt(5))/2;function sL(e,t,r,n,o,a,s,i,c,l){o=-o,s=-s,c=-c;let u=r-t,m=0;for(let f=0;f<oL;f++){let p=l*Math.abs(n)+1e-10,d=.5*(t+r);if(Math.abs(n-d)<=2*p-.5*(r-t))break;let h=!0;if(Math.abs(u)>p){let y=(n-a)*(o-c),R=(n-i)*(o-s),k=(n-i)*R-(n-a)*y;R=2*(R-y),R>0&&(k=-k),R=Math.abs(R);let v=u;if(u=m,Math.abs(k)<Math.abs(.5*R*v)&&k>R*(t-n)&&k<R*(r-n)){m=k/R;let x=n+m;(x-t<2*p||r-x<2*p)&&(m=d>=n?p:-p),h=!1}}h&&(u=n>=d?t-n:r-n,m=aL*u);let b=Math.abs(m)>=p?n+m:n+(m>=0?p:-p),g=-e(b);g<=o?(b>=n?t=n:r=n,i=a,c=s,a=n,s=o,n=b,o=g):(b<n?t=b:r=b,g<=s||a===n?(i=a,c=s,a=b,s=g):(g<=c||i===n||i===a)&&(i=b,c=g))}return-o}function If(e,t){return e.model?.kind==="simple"?null:iv(e,t)}var av=new WeakMap,Df=100,sv=1.35,Ef=18,ur=41,Ll=41,Os=65;function iv(e,t){let r=av.get(e);if(r)return r;let n=Math.log(sv),o=(p,d)=>{let h=M=>Math.abs(Pt(e,p,M,d)),b=h(0),g=t.muY(p)*p,y=new Float64Array(ur),R=b>0&&g>0?Math.max(1,t.muX(p)*p/b):1;if(!(b>0)||!(g>0))y.fill(1);else{let M=[],F=[];for(let T=0;T<Ll;T++){let P=Math.sin(.5*Math.PI*T/(Ll-1));M.push(P),F.push(T===0?1:T===Ll-1?0:Math.min(F[T-1],h(P*g)/b))}let w=Ll-1;for(let T=0;T<ur;T++){let P=T/(ur-1);for(;w>0&&F[w-1]<P;)w--;let A=w>0?F[w-1]-F[w]:0;y[T]=w===0?M[0]:M[w]+(A>0?(P-F[w])/A:0)*(M[w-1]-M[w])}y[0]=1,y[ur-1]=0}let k=new Float64Array(Os),v=M=>Math.atan2(y[M],M/(ur-1)/R),x=ur-2;for(let M=0;M<Os;M++){let F=.5*Math.PI*M/(Os-1),w=Math.cos(F),T=Math.sin(F);for(;x>0&&v(x)<F;)x--;let P=x/(ur-1)/R,A=y[x],S=(x+1)/(ur-1)/R,C=y[x+1],L=w*(C-A)-T*(S-P),D=Math.abs(L)>1e-12?(P*(C-A)-A*(S-P))/L:Math.hypot(P,A);k[M]=D>0?D:Math.hypot(P,A)}return{room:y,scale:R,edge:k}},a=Array.from({length:Ef},(p,d)=>Df*sv**d),s=a.map(p=>o(p,!1)),i=a.map(p=>o(p,!0)),c=(p,d)=>{let h=Math.min(1,Math.abs(d)*p.scale)*(ur-1),b=Math.min(ur-2,Math.floor(h));return p.room[b]+(h-b)*(p.room[b+1]-p.room[b])},l=p=>{let d=p>Df?Math.log(p/Df)/n:0;if(d>=Ef-1)return[Ef-2,1];let h=Math.floor(d);return[h,d-h]},u=(p,d,h)=>{if(h===0)return 1;let b=h<0?i:s,g=c(b[p],h);return d>0?g+d*(c(b[p+1],h)-g):g},m=(p,d,h)=>{let b=d<0?i:s,[g,y]=l(p),R=Math.atan2(Math.abs(h),Math.abs(d))/(.5*Math.PI)*(Os-1),k=Math.min(Os-2,Math.floor(R)),v=M=>M.edge[k]+(R-k)*(M.edge[k+1]-M.edge[k]),x=v(b[g]);return y>0?x+y*(v(b[g+1])-x):x},f={keeps(p,d){if(d===0)return 1;let[h,b]=l(p);return u(h,b,d)},atLoad(p){let[d,h]=l(p);return b=>u(d,h,b)},use(p,d,h){let b=Math.hypot(d,h);return b>0?Math.min(1,b/m(p,d,h)):0},reach:m};return av.set(e,f),f}var iL=[["front","FL","FR"],["rear","RL","RR"]];function ma(e,t,r,n){let o={...e},a=0,s=Vs;for(let[i,c,l]of iL){let u=(k,v)=>n(i,Math.max(0,v[k])).fyPeak,m=Math.min(s,e[c]),f=Math.min(s,e[l]),p=m*u(c,r)+f*u(l,r);if(!(p>0))continue;let d=u(c,t),h=u(l,t),b=m*d+f*h,g=b>0?p/b:1/0,y=m*g,R=f*g;y<=s?R<=s||(R=s,y=d>0?(p-s*h)/d:1/0):(y=s,R=h>0?(p-s*d)/h:1/0),(!(y<=s)||!(R<=s))&&(a+=Math.max(0,p-s*(d+h)),y=Math.min(s,y),R=Math.min(s,R)),o[c]=y,o[l]=R}return{util:o,short:a}}var cv=.001,cL=1e-5,lv=100;function lL(e,t,r,n){if(!(n>cv))return r;let o=t,a=Math.abs(r-t)<lv?t+Math.sign(r-t)*lv:r;for(let s=0;s<60&&Math.abs(a-o)>cL;s++){let i=.5*(o+a);e(i)>cv?a=i:o=i}return o}function El(e,t,r){let n;return{at:o=>{if(n!==void 0)return r<0?Math.max(o,n):Math.min(o,n);if(!((o-t)*r>0))return o;let a=lL(e,t,o,e(o));return a!==o&&(n=a),a},edge:()=>n}}function Il(e,t){let r=n=>{try{return ge(e,0,n).ok}catch{return!1}};for(let n of[1,-1]){if(r(n*t))continue;let o=0;for(let a=1;a<=6;a++){let s=n*t*a/6;if(!r(s))break;o=Math.abs(s)}return{lock:t,reached:o,side:n}}return null}var _f=40;function _l(e){return{violation:Math.max(0,e.lock-e.reached),reason:`the steering reaches only ${e.reached.toFixed(0)} mm of the ${e.lock.toFixed(0)} mm rack travel${e.side<0?" (other side)":""}`}}var uv=[0,0,0];function uL(e,t){let r=q(H(e.rockerPivotB,e.rockerPivotA)),n=q(H(e.rockerToPushrod,e.pushrodOuter)),o=q(H(e.damperChassis,e.rockerToDamper)),a=Math.abs(X(r,ae(H(e.rockerToPushrod,e.rockerPivotA),n))),s=Math.abs(X(r,ae(H(e.rockerToDamper,e.rockerPivotA),o)));return s<1e-9?0:t*a/s}function Nl(e,t,r){if(e.mcpherson)return mL(e,t,r);let n=[{r:e.uprightUpper,c:e.ucaFront},{r:e.uprightUpper,c:e.ucaRear},{r:e.uprightLower,c:e.lcaFront},{r:e.uprightLower,c:e.lcaRear},{r:e.tieOuter,c:e.tieInner},{r:e.pushrodOuter,c:e.direct?e.damperChassis:e.rockerToPushrod}],o=e.wheelCenter,a=[[],[],[],[],[],[]];for(let m=0;m<6;m++){let f=q(H(n[m].c,n[m].r)),p=ae(H(n[m].r,o),f);a[0][m]=f[0],a[1][m]=f[1],a[2][m]=f[2],a[3][m]=p[0],a[4][m]=p[1],a[5][m]=p[2]}let s=ae(H(e.contactPatch,o),t),i=r??uv,c=[-t[0],-t[1],-t[2],-(s[0]+i[0]),-(s[1]+i[1]),-(s[2]+i[2])],l=sr(a,c),u=l.x;return{ucaFront:u[0],ucaRear:u[1],lcaFront:u[2],lcaRear:u[3],tieRod:u[4],pushRod:u[5],damper:l.singular||e.decoupled?NaN:e.direct?u[5]:uL(e,u[5]),condProxy:l.condProxy,singular:l.singular}}function mL(e,t,r){let n=e.wheelCenter,o=e.damperChassis,a=[{at:e.uprightLower,dir:q(H(e.lcaFront,e.uprightLower))},{at:e.uprightLower,dir:q(H(e.lcaRear,e.uprightLower))},{at:e.tieOuter,dir:q(H(e.tieInner,e.tieOuter))},{at:o,dir:[1,0,0]},{at:o,dir:[0,1,0]},{at:o,dir:[0,0,1]}],s=[[],[],[],[],[],[]];for(let b=0;b<6;b++){let g=a[b].dir,y=ae(H(a[b].at,n),g);s[0][b]=g[0],s[1][b]=g[1],s[2][b]=g[2],s[3][b]=y[0],s[4][b]=y[1],s[5][b]=y[2]}let i=ae(H(e.contactPatch,n),t),c=r??uv,l=[-t[0],-t[1],-t[2],-(i[0]+c[0]),-(i[1]+c[1]),-(i[2]+c[2])],u=sr(s,l),m=u.x,f=[m[3],m[4],m[5]],p=q(H(o,e.pushrodOuter)),d=X(f,p),h=Math.hypot(f[0]-d*p[0],f[1]-d*p[1],f[2]-d*p[2]);return{ucaFront:NaN,ucaRear:NaN,lcaFront:m[0],lcaRear:m[1],tieRod:m[2],pushRod:u.singular?NaN:d,damper:u.singular?NaN:d,condProxy:u.condProxy,singular:u.singular,strutSide:u.singular?NaN:h,topMount:f}}function Nf(e,t){let r=q(e.spinAxis),n=ae(H(e.contactPatch,e.wheelCenter),t),o=X(n,r);return[-o*r[0],-o*r[1],-o*r[2]]}var pL=[0,0,0];function Bs(e,t,r,n){let o=e.direct?e.damperChassis:e.rockerToPushrod;if(e.mcpherson)return{...Nl(e,r,n),armResidual:0};if(t==="upright")return{...Nl(e,r,n),armResidual:0};let a=t==="lowerArm",s=a?{bj:e.uprightUpper,front:e.ucaFront,rear:e.ucaRear}:{bj:e.uprightLower,front:e.lcaFront,rear:e.lcaRear},i=a?{bj:e.uprightLower,front:e.lcaFront,rear:e.lcaRear}:{bj:e.uprightUpper,front:e.ucaFront,rear:e.ucaRear},c=e.wheelCenter,l=q(H(s.front,s.bj)),u=q(H(s.rear,s.bj)),m=q(H(e.tieInner,e.tieOuter)),f=[{at:s.bj,dir:l},{at:s.bj,dir:u},{at:e.tieOuter,dir:m},{at:i.bj,dir:[1,0,0]},{at:i.bj,dir:[0,1,0]},{at:i.bj,dir:[0,0,1]}],p=[[],[],[],[],[],[]];for(let Z=0;Z<6;Z++){let ne=f[Z].dir,te=ae(H(f[Z].at,c),ne);p[0][Z]=ne[0],p[1][Z]=ne[1],p[2][Z]=ne[2],p[3][Z]=te[0],p[4][Z]=te[1],p[5][Z]=te[2]}let d=ae(H(e.contactPatch,c),r),h=n??pL,b=[-r[0],-r[1],-r[2],-(d[0]+h[0]),-(d[1]+h[1]),-(d[2]+h[2])],g=sr(p,b),y=g.singular,R=g.x,k=R[0],v=R[1],x=R[2],M=[R[3],R[4],R[5]],F=q(H(i.rear,i.front)),w=q(H(o,e.pushrodOuter)),T=U(M,-1),P=(Z,ne)=>X(F,ae(H(Z,i.front),ne)),A=P(e.pushrodOuter,w),S=Math.abs(A)>1e-9?-P(i.bj,T)/A:NaN,C=ee(T,U(w,S)),L=U(C,-1),D=q(H(i.front,i.bj)),I=q(H(i.rear,i.bj)),O=X(D,D),N=X(D,I),z=X(I,I),E=X(D,L),_=X(I,L),B=O*z-N*N,V=NaN,G=NaN,K=NaN;if(Math.abs(B)>1e-12){V=(E*z-_*N)/B,G=(O*_-N*E)/B;let Z=ee(U(D,V),U(I,G)),ne=H(L,Z);K=Math.hypot(ne[0],ne[1],ne[2])}let Y=a?{f:k,r:v}:{f:V,r:G},j=a?{f:V,r:G}:{f:k,r:v};return{ucaFront:Y.f,ucaRear:Y.r,lcaFront:j.f,lcaRear:j.r,tieRod:x,pushRod:S,damper:y||!Number.isFinite(S)||e.decoupled?NaN:e.direct?S:dL(e,S),condProxy:g.condProxy,singular:y,armResidual:K}}function dL(e,t){let r=q(H(e.rockerPivotB,e.rockerPivotA)),n=q(H(e.rockerToPushrod,e.pushrodOuter)),o=q(H(e.damperChassis,e.rockerToDamper)),a=Math.abs(X(r,ae(H(e.rockerToPushrod,e.rockerPivotA),n))),s=Math.abs(X(r,ae(H(e.rockerToDamper,e.rockerPivotA),o)));return s<1e-9?0:t*a/s}var sH=Math.PI/180;function $s(e,t){let r=Math.min(Math.max(t,e.range[0]),e.range[1])-e.reference;return Math.max(.2,1+e.perDegC*r+e.perDegC2*r*r)}var pv=["QSX3","QSX8","QSX13","QSX14"],fL=["QSX1"],Ol=["PHY1","PHY2","PHY3","PKY6","PKY7","PVY1","PVY2","PVY3","PVY4","PEY3","PEY4","QHZ1","QHZ2","QHZ3","QHZ4","QEZ4","QEZ5","QDZ6","QDZ7","QDZ8","QDZ9","QDZ10","QDZ11","SSZ1","SSZ3","SSZ4","RBY3","RHX1","RVY1","RVY2","RVY3",...pv];function hL(e){let t=["PKY6","PKY7","PVY3","PVY4","PHY3","PEY4","RVY3","QHZ3","QHZ4","QEZ5","QDZ8","QDZ9","QDZ10","QDZ11","SSZ3","SSZ4"];return e==="5.2"?[...t,"QBZ4","QDZ3"]:t}function bL(e){let t=new Set(hL(e)),r=Ol.filter(n=>!pv.includes(n));return[...r.filter(n=>!t.has(n)),...[...t].filter(n=>!r.includes(n)),...fL]}function gL(e,t){let r={...e};for(let n of t)r[n]!==void 0&&r[n]!==0&&(r[n]=-r[n]);return r}var Lr=(e,t,r)=>Number.isFinite(e[t])?e[t]:r;function dv(e,t){return t!=="5.2"?Lr(e,"PKY6",0)*Lr(e,"LKYC",1):Lr(e,"PKY1",-15)*Math.sin(Lr(e,"PKY4",2)*Math.atan(1/Lr(e,"PKY2",2)))*Lr(e,"LKY",1)*Lr(e,"PHY3",0)+Lr(e,"PVY3",0)*Lr(e,"LMUY",1)}var mv=.1;function fv(e){if(e.fitData)return"sae";let t=dv(e.coeffs,e.version);return t>mv?"sae":t<-mv?"iso":null}function Gs(e){return e.axisSystem??fv(e)??"sae"}function Vl(e){let t=new Set,r=n=>{for(let o of n)t.has(o)?t.delete(o):t.add(o)};return Gs(e)==="iso"&&r(Ol),e.axisSystem&&e.side==="left"&&r(bL(e.version)),t.size?gL(e.coeffs,t):e.coeffs}var cH=Math.PI/180;var $=(e,t)=>Number.isFinite(e)?e:t;function bv(e){let t=Vl(e);return{PCX1:$(t.PCX1,1.65),PDX1:$(t.PDX1,1),PDX2:$(t.PDX2,0),PDX3:$(t.PDX3,0),PEX1:$(t.PEX1,0),PEX2:$(t.PEX2,0),PEX3:$(t.PEX3,0),PEX4:$(t.PEX4,0),PHX1:$(t.PHX1,0),PHX2:$(t.PHX2,0),PKX1:$(t.PKX1,20),PKX2:$(t.PKX2,0),PKX3:$(t.PKX3,0),PPX1:$(t.PPX1,0),PPX2:$(t.PPX2,0),PPX3:$(t.PPX3,0),PPX4:$(t.PPX4,0),PVX1:$(t.PVX1,0),PVX2:$(t.PVX2,0),PCY1:$(t.PCY1,1.3),PDY1:$(t.PDY1,1),PDY2:$(t.PDY2,0),PDY3:$(t.PDY3,0),PEY1:$(t.PEY1,0),PEY2:$(t.PEY2,0),PEY3:$(t.PEY3,0),PEY4:$(t.PEY4,0),PEY5:$(t.PEY5,0),PHY1:$(t.PHY1,0),PHY2:$(t.PHY2,0),PHY3:$(t.PHY3,0),PKY1:$(t.PKY1,-15),PKY2:$(t.PKY2,2),PKY3:$(t.PKY3,0),PKY4:$(t.PKY4,2),PKY5:$(t.PKY5,0),PKY6:$(t.PKY6,0),PKY7:$(t.PKY7,0),PPY1:$(t.PPY1,0),PPY2:$(t.PPY2,0),PPY3:$(t.PPY3,0),PPY4:$(t.PPY4,0),PPY5:$(t.PPY5,0),PVY1:$(t.PVY1,0),PVY2:$(t.PVY2,0),PVY3:$(t.PVY3,0),PVY4:$(t.PVY4,0),RBX1:$(t.RBX1,0),RBX2:$(t.RBX2,0),RBX3:$(t.RBX3,0),RBY1:$(t.RBY1,0),RBY2:$(t.RBY2,0),RBY3:$(t.RBY3,0),RBY4:$(t.RBY4,0),RCX1:$(t.RCX1,1),RCY1:$(t.RCY1,1),REX1:$(t.REX1,0),REX2:$(t.REX2,0),REY1:$(t.REY1,0),REY2:$(t.REY2,0),RHX1:$(t.RHX1,0),RHY1:$(t.RHY1,0),RHY2:$(t.RHY2,0),RVY1:$(t.RVY1,0),RVY2:$(t.RVY2,0),RVY3:$(t.RVY3,0),RVY4:$(t.RVY4,0),RVY5:$(t.RVY5,1),RVY6:$(t.RVY6,0),PPZ1:$(t.PPZ1,0),PPZ2:$(t.PPZ2,0),QBZ1:$(t.QBZ1,8),QBZ2:$(t.QBZ2,0),QBZ3:$(t.QBZ3,0),QBZ4:$(t.QBZ4,0),QBZ5:$(t.QBZ5,0),QBZ6:$(t.QBZ6,0),QBZ9:$(t.QBZ9,0),QBZ10:$(t.QBZ10,0),QCZ1:$(t.QCZ1,1.1),QDZ1:$(t.QDZ1,.1),QDZ2:$(t.QDZ2,0),QDZ3:$(t.QDZ3,0),QDZ4:$(t.QDZ4,0),QDZ6:$(t.QDZ6,0),QDZ7:$(t.QDZ7,0),QDZ8:$(t.QDZ8,0),QDZ9:$(t.QDZ9,0),QDZ10:$(t.QDZ10,0),QDZ11:$(t.QDZ11,0),QEZ1:$(t.QEZ1,0),QEZ2:$(t.QEZ2,0),QEZ3:$(t.QEZ3,0),QEZ4:$(t.QEZ4,0),QEZ5:$(t.QEZ5,0),QHZ1:$(t.QHZ1,0),QHZ2:$(t.QHZ2,0),QHZ3:$(t.QHZ3,0),QHZ4:$(t.QHZ4,0),SSZ1:$(t.SSZ1,0),SSZ2:$(t.SSZ2,0),SSZ3:$(t.SSZ3,0),SSZ4:$(t.SSZ4,0),QSX1:$(t.QSX1,0),QSX2:$(t.QSX2,0),QSX3:$(t.QSX3,0),QSX4:$(t.QSX4,0),QSX5:$(t.QSX5,0),QSX6:$(t.QSX6,0),QSX7:$(t.QSX7,0),QSX8:$(t.QSX8,0),QSX9:$(t.QSX9,0),QSX10:$(t.QSX10,0),QSX11:$(t.QSX11,0),QSX12:$(t.QSX12,0),QSX13:$(t.QSX13,0),QSX14:$(t.QSX14,0),PPMX1:$(t.PPMX1,0),QSY1:$(t.QSY1,0),QSY2:$(t.QSY2,0),QSY3:$(t.QSY3,0),QSY4:$(t.QSY4,0),QSY5:$(t.QSY5,0),QSY6:$(t.QSY6,0),QSY7:$(t.QSY7,0),QSY8:$(t.QSY8,0),LONGVL:t.LONGVL!==void 0&&t.LONGVL>0?t.LONGVL:16.7,LCX:$(t.LCX,1),LCY:$(t.LCY,1),LEX:$(t.LEX,1),LEY:$(t.LEY,1),LFZO:$(t.LFZO,1),LHX:$(t.LHX,1),LHY:$(t.LHY,1),LKX:$(t.LKX,1),LKY:$(t.LKY,1),LKYC:$(t.LKYC,1),LKZC:$(t.LKZC,1),LMUX:$(t.LMUX,1),LMUY:$(t.LMUY,1),LMX:$(t.LMX,1),LMY:$(t.LMY,1),LVMX:$(t.LVMX,1),LRES:$(t.LRES,1),LS:$(t.LS,1),LTR:$(t.LTR,1),LVX:$(t.LVX,1),LVY:$(t.LVY,1),LVYKA:$(t.LVYKA,1),LXAL:$(t.LXAL,1),LYKA:$(t.LYKA,1)}}var hv=new WeakMap;function Ks(e){let t=hv.get(e);return t===void 0&&(t=bv(e),hv.set(e,t)),t}var gv=e=>e>=0?1:-1;function Bl(e,t,r=0,n){let o=Ks(e),a=Math.max(1,t),s=r,i=o.LFZO*e.fnomin,c=(a-i)/i,l=e.nomPressure>0&&n?(n-e.nomPressure)/e.nomPressure:0,u=e.unloadedR0,m=(o.PDY1+o.PDY2*c)*(1+o.PPY3*l+o.PPY4*l*l)*(1-o.PDY3*s*s)*o.LMUY,f=o.PCY1*o.LCY,p=m*a,d=o.PKY1*i*(1+o.PPY1*l)*Math.sin(o.PKY4*Math.atan(a/((o.PKY2+o.PKY5*s*s)*(1+o.PPY2*l)*i)))*(1-o.PKY3*Math.abs(s))*o.LKY,h=e.version!=="5.2",b=a*(o.PKY6+o.PKY7*c)*(1+o.PPY5*l)*o.LKYC,g=a*(o.PVY3+o.PVY4*c)*s*o.LKYC*o.LMUY,y=Math.abs(d)>1e-6?d:1e-6*(d<0?-1:1),R=h?(o.PHY1+o.PHY2*c)*o.LHY+(b*s-g)/y:(o.PHY1+o.PHY2*c)*o.LHY+o.PHY3*s,k=h?a*(o.PVY1+o.PVY2*c)*o.LVY*o.LMUY+g:a*((o.PVY1+o.PVY2*c)*o.LVY+(o.PVY3+o.PVY4*c)*s)*o.LMUY,v=f*p!==0?d/(f*p):0;return{Fz:a,g:s,dfz:c,dpi:l,Fz0p:i,R0:u,Cy:f,Dy:p,By:v,SHy:R,SVy:k,Kya:d,muy:m,EyA:o.PEY1+o.PEY2*c,EyG:1+o.PEY5*s*s,EyS:o.PEY3+o.PEY4*s,LEY:o.LEY}}function $l(e,t,r=0,n){let o=Bl(e,t,r,n),a=Ks(e),{Fz:s,g:i,dfz:c,dpi:l,Fz0p:u,R0:m,muy:f,Kya:p,SVy:d,By:h,Cy:b,Dy:g,SHy:y}=o,R=(a.PHX1+a.PHX2*c)*a.LHX,k=(a.PDX1+a.PDX2*c)*(1+a.PPX3*l+a.PPX4*l*l)*(1-a.PDX3*i*i)*a.LMUX,v=a.PCX1*a.LCX,x=k*s,M=s*(a.PKX1+a.PKX2*c)*Math.exp(a.PKX3*c)*(1+a.PPX1*l+a.PPX2*l*l)*a.LKX,F=v*x!==0?M/(v*x):0,w=Math.abs(p)>1e-6?p:1e-6*(p<0?-1:1),T=e.version!=="5.2",P=s*(a.PVX1+a.PVX2*c)*a.LVX*a.LMUX,A=a.REX1+a.REX2*c;A>1&&(A=1);let S=a.REY1+a.REY2*c;return S>1&&(S=1),{Fz:s,g:i,dfz:c,dpi:l,Fz0p:u,R0:m,Cy:b,Dy:g,By:h,SHy:y,SVy:d,Kya:p,muy:f,EyA:o.EyA,EyG:o.EyG,EyS:o.EyS,LEY:o.LEY,SHx:R,Cx:v,Dx:x,Bx:F,SVx:P,ExA:a.PEX1+a.PEX2*c+a.PEX3*c*c,PEX4:a.PEX4,LEX:a.LEX,SHxa:a.RHX1,Bxa0:a.RBX1+a.RBX3*i*i,RBX2:a.RBX2,LXAL:a.LXAL,Cxa:a.RCX1,Exa:A,SHyk:a.RHY1+a.RHY2*c,Byk0:a.RBY1+a.RBY4*i*i,RBY2:a.RBY2,RBY3:a.RBY3,LYKA:a.LYKA,Cyk:a.RCY1,Eyk:S,DVykA:f*s*(a.RVY1+a.RVY2*c+a.RVY3*i),RVY4:a.RVY4,RVY5:a.RVY5,RVY6:a.RVY6,LVYKA:a.LVYKA,SHt:a.QHZ1+a.QHZ2*c+(a.QHZ3+a.QHZ4*c)*i,Bt:T?(a.QBZ1+a.QBZ2*c+a.QBZ3*c*c)*(1+a.QBZ5*Math.abs(i)+a.QBZ6*i*i)*(a.LKY/a.LMUY):(a.QBZ1+a.QBZ2*c+a.QBZ3*c*c)*(1+a.QBZ4*i+a.QBZ5*Math.abs(i))*(a.LKY/a.LMUY),Ct:a.QCZ1,Dt:T?s*(m/u)*(a.QDZ1+a.QDZ2*c)*(1-a.PPZ1*l)*(1+a.QDZ3*Math.abs(i)+a.QDZ4*i*i)*a.LTR:s*(m/u)*(a.QDZ1+a.QDZ2*c)*(1-a.PPZ1*l)*(1+a.QDZ3*i+a.QDZ4*i*i)*a.LTR,EtA:a.QEZ1+a.QEZ2*c+a.QEZ3*c*c,EtG:a.QEZ4+a.QEZ5*i,Br:a.QBZ9*(a.LKY/a.LMUY)+a.QBZ10*h*b,Dr:T?s*m*((a.QDZ6+a.QDZ7*c)*a.LRES+((a.QDZ8+a.QDZ9*c)*(1+a.PPZ2*l)+(a.QDZ10+a.QDZ11*c)*Math.abs(i))*i*a.LKZC)*a.LMUY:s*m*((a.QDZ6+a.QDZ7*c)*a.LRES+(a.QDZ8+a.QDZ9*c)*(1+a.PPZ2*l)*i)*a.LMUY,arOff:p!==0?d/p:0,sixOne:T,kk:M/w*(M/w),sS0:m*(a.SSZ1+(a.SSZ3+a.SSZ4*c)*i)*a.LS,sS2:m*a.SSZ2*a.LS/u}}function Hs(e,t){let r=t+e.SHy,n=e.EyA*(e.EyG-e.EyS*gv(r))*e.LEY;n>1&&(n=1);let o=e.By*r;return e.Dy*Math.sin(e.Cy*Math.atan(o-n*(o-Math.atan(o))))+e.SVy}function Gl(e,t){let r=t+e.SHx,n=e.ExA*(1-e.PEX4*gv(r))*e.LEX;n>1&&(n=1);let o=e.Bx*r;return e.Dx*Math.sin(e.Cx*Math.atan(o-n*(o-Math.atan(o))))+e.SVx}function yv(e,t,r){if(r===0)return t;if(e.sixOne)return Math.sqrt(t*t+e.kk*r*r)*Math.sign(t);let n=Math.tan(t);return Math.atan(Math.sqrt(n*n+e.kk*r*r))*Math.sign(t)}function yL(e,t,r,n){let o=t+e.SHt,a=e.EtA*(1+e.EtG*(2/Math.PI)*Math.atan(e.Bt*e.Ct*o));a>1&&(a=1);let s=yv(e,o,r),i=e.Bt*s;return e.Dt*Math.cos(e.Ct*Math.atan(i-a*(i-Math.atan(i))))*n}function xL(e,t,r,n){return e.Dr*Math.cos(Math.atan(e.Br*yv(e,t+e.SHy+e.arOff,r)))*n}function xv(e,t,r,n,o,a){let s=Math.cos(t),i=yL(e,t,r,s),c=xL(e,t,r,s);return-i*(o-a)+c+(e.sS0+e.sS2*o)*n}function Rv(e,t,r){let n=e.Bxa0*Math.cos(Math.atan(e.RBX2*t))*e.LXAL,o=r+e.SHxa,a=Math.cos(e.Cxa*Math.atan(n*e.SHxa-e.Exa*(n*e.SHxa-Math.atan(n*e.SHxa))))||1;return Math.cos(e.Cxa*Math.atan(n*o-e.Exa*(n*o-Math.atan(n*o))))/a*Gl(e,t)}function Of(e,t){let r=e.sS0===0&&e.sS2===0?0:Rv(e,0,t);return xv(e,t,0,r,Hs(e,t),0)}function Kl(e,t,r){let n=Hs(e,r),o=Rv(e,t,r),a=e.Byk0*Math.cos(Math.atan(e.RBY2*(r-e.RBY3)))*e.LYKA,s=t+e.SHyk,i=Math.cos(e.Cyk*Math.atan(a*e.SHyk-e.Eyk*(a*e.SHyk-Math.atan(a*e.SHyk))))||1,c=Math.cos(e.Cyk*Math.atan(a*s-e.Eyk*(a*s-Math.atan(a*s))))/i,u=e.DVykA*Math.cos(Math.atan(e.RVY4*r))*Math.sin(e.RVY5*Math.atan(e.RVY6*t))*e.LVYKA,m=c*n+u;return{Fx:o,Fy:m,Mz:xv(e,r,t,o,m,u)}}var zs=(e,t)=>Math.max(.1,e.muY0+e.loadSensY*(t-e.nominalLoad)),Ys=(e,t)=>Math.max(.1,e.muX0+e.loadSensX*(t-e.nominalLoad)),vv=(e,t,r)=>zs(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cy*Math.atan(e.By*r)),kv=(e,t,r)=>Ys(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cx*Math.atan(e.Bx*r));function Vf(e,t){let r=Math.max(1,t.Fz),n=zs(e,r)*r,o=Ys(e,r)*r,a=n*Math.sin(e.Cy*Math.atan(e.By*t.alpha)),s=o*Math.sin(e.Cx*Math.atan(e.Bx*t.kappa)),i=Math.hypot(o>0?s/o:0,n>0?a/n:0);return i>1&&(s/=i,a/=i),{Fx:s,Fy:a,Mz:0}}var pa=Math.PI/180;function dn(e){if(e.kind==="simple")return"none";let t=e.missing?.some(n=>/^aligning moment Mz\b/i.test(n))??!1,r=["QBZ1","QCZ1","QDZ1"].every(n=>Number.isFinite(e.coeffs[n]));return t||!r?"assumed":"model"}function Mv(e){let t=e.thermal?.operating;if(t===void 0||!e.thermal)return e;let{lateral:r,longitudinal:n,aligning:o}=e.thermal,a=r?$s(r,t):1,s=n?$s(n,t):1,i=o?$s(o,t):1;if(a===1&&s===1&&i===1)return e;if(e.kind==="simple")return{...e,muY0:e.muY0*a,muX0:e.muX0*s};let c={...e.coeffs},l=(u,m)=>{c[u]=(c[u]??1)*m};return l("LMUY",a),l("LMUX",s),l("LTR",i),l("LRES",i),{...e,coeffs:c}}function da(e,t,r){let n=0,o=0;for(let s=r;s<=t;s+=r){let i=Math.abs(e(s));i>o&&(o=i,n=s)}let a=r/10;for(let s=Math.max(a,n-r);s<=n+r;s+=a)o=Math.max(o,Math.abs(e(s)));return o}function Pe(e){let t=Mv(e),r=t,n=t,o=null,a=NaN,s=NaN,i=NaN,c=(v,x,M)=>(o!==null&&v===a&&x===s&&M===i||(o=$l(r,v,x,M),a=v,s=x,i=M),o),l=null,u=NaN,m=NaN,f=NaN,p=(v,x,M)=>(l!==null&&v===u&&x===m&&M===f||(l=Bl(r,v,x,M),u=v,m=x,f=M),l),d=v=>e.kind==="magic"?Kl(c(v.Fz,v.gamma??0,v.p),v.kappa,v.alpha):Vf(n,v),h=(v,x,M=0,F)=>e.kind==="magic"?Hs(p(x,M,F),v):vv(n,x,v),b=(v,x,M=0,F)=>e.kind==="magic"?Gl(c(x,M,F),v):kv(n,x,v),g=(v,x,M=0,F)=>e.kind==="magic"?Of(c(x,M,F),v):d({Fz:x,kappa:0,alpha:v,gamma:M,p:F}).Mz,y=v=>e.kind==="simple"?zs(n,v):da(x=>h(x*pa,v),45,1)/Math.max(1,v),R=v=>e.kind==="simple"?Ys(n,v):da(x=>b(x,v),.6,.02)/Math.max(1,v),k=v=>{let x=.1*pa;return Math.abs((h(x,v)-h(-x,v))/(2*x))};return{model:e,forces:d,Fx:b,Fy:h,Mz:g,muX:R,muY:y,corneringStiffness:k,verticalStiffness:()=>e.verticalStiffness,rollingRadius:v=>{if(e.kind==="magic"&&e.missing?.includes("UNLOADED_RADIUS"))return 0;let x=e.unloadedR0??0;if(!(x>0))return 0;let M=e.verticalStiffness*1e3;if(!(M>0))return x;let F=e.rollingFraction??.306;return x-F*Math.max(0,v)/M},relaxationLength:v=>{let x=e.relaxation;if(!x)return 0;let M=x.carcassStiffness??0;if(!(M>0))return x.sigma;let F=k(Math.max(0,v));return F>0?F/(M*1e3):x.sigma}}}function fa(e){let t=Math.max(1,e.model.kind==="magic"?e.model.fnomin:e.model.nominalLoad);return e.Fy(2*pa,t,0)-e.Fy(-2*pa,t,0)>=0?1:-1}function Ws(e,t=e.kind==="magic"?e.fnomin:e.nominalLoad){let r=Pe(e),n=2*pa,o=3*pa,a=r.Fy(n,t,0),s=r.Fy(n,t,o);return!Number.isFinite(a)||!Number.isFinite(s)?!1:Math.abs(s-a)>1}var RL=Math.PI/180;function ye(e,t){return e.axle?e.axle(t):e}function zl(e,t){if(e===t)return e;let r=fa(e)*fa(t),n=(l,u)=>.5*(l+u),o=(l,u)=>l>0&&u>0?n(l,u):l>0?l:u>0?u:0,a=l=>{let u=e.forces(l),m=t.forces(l);return{Fx:n(u.Fx,m.Fx),Fy:n(u.Fy,r*m.Fy),Mz:n(u.Mz,r*m.Mz)}},s=(l,u,m=0,f)=>n(e.Fx(l,u,m,f),t.Fx(l,u,m,f)),i=(l,u,m=0,f)=>n(e.Fy(l,u,m,f),r*t.Fy(l,u,m,f)),c=(l,u,m=0,f)=>n(e.Mz(l,u,m,f),r*t.Mz(l,u,m,f));return{model:e.model,forces:a,Fx:s,Fy:i,Mz:c,muX:l=>da(u=>s(u,l),.6,.02)/Math.max(1,l),muY:l=>da(u=>i(u*RL,l),45,1)/Math.max(1,l),corneringStiffness:l=>n(e.corneringStiffness(l),t.corneringStiffness(l)),verticalStiffness:()=>o(e.verticalStiffness(),t.verticalStiffness()),rollingRadius:l=>o(e.rollingRadius(l),t.rollingRadius(l)),relaxationLength:l=>o(e.relaxationLength(l),t.relaxationLength(l)),axle:l=>l==="front"?e:t}}function ft(e){if(Sv.has(e))return e;let t=Av.get(e);if(t)return t;let r;if(e.axle){let n=e.axle("front"),o=e.axle("rear"),a=ft(n),s=ft(o);r=a===n&&s===o?e:zl(a,s)}else fa(e)>0?r=e:r={...e,forces:n=>{let o=e.forces(n);return{Fx:o.Fx,Fy:-o.Fy,Mz:-o.Mz}},Fy:(n,o,a,s)=>-e.Fy(n,o,a,s),Mz:(n,o,a,s)=>-e.Mz(n,o,a,s)};return Sv.add(r),r!==e&&Av.set(e,r),r}var Sv=new WeakSet,Av=new WeakMap;var Yl=25*(Math.PI/180);function vL(e){let t=.6180339887,r=0,n=Yl,o=n-t*(n-r),a=r+t*(n-r),s=e(o),i=e(a);for(let l=0;l<12;l++)s>i?(n=a,a=o,i=s,o=n-t*(n-r),s=e(o)):(r=o,o=a,s=i,a=r+t*(n-r),i=e(a));return{alpha:s>i?o:a,force:Math.max(s,i)}}function js(e,t,r,n,o=0){let a=Math.abs(t);if(!(a>0))return 0;let s=u=>Math.abs(e.Fy(u,r,0))+Math.abs(e.Fy(u,n,0)),i=0,c=Yl;if(s(Yl)<=a){let u=vL(s);if(u.force<=a)return u.alpha;c=u.alpha}else if(o>0){let u=Math.max(0,o*.6),m=Math.min(Yl,o*1.6+.001);s(u)<a&&s(m)>=a&&(i=u,c=m)}let l=.001*a;for(let u=0;u<12;u++){let m=.5*(i+c),f=s(m)-a;if(f<0?i=m:c=m,Math.abs(f)<=l)return m}return c}var Bf={shaft:!1,trail:0,hub:[0,0,0]};function wv(e){let t=e.spinAxis,r=Math.hypot(t[0],t[1]);if(r<1e-9)return[1,0,0];let n=[-t[1]/r,t[0]/r,0];return n[0]<0?[-n[0],-n[1],0]:n}function $f(e,t,r){let n=r.shaft?Nf(e,t):[0,0,0];if(r.trail!==0){let a=wv(e),s=[t[0],t[1],0],i=H(s,U(a,X(s,a)));n=ee(n,ae(U(a,-r.trail),i))}let o=r.hub;return(o[0]!==0||o[1]!==0||o[2]!==0)&&(n=H(n,ae(H(e.contactPatch,e.wheelCenter),o))),{force:ee(t,o),moment:n}}var kL=(e,t)=>{let r=e!==void 0&&e>0?1/e:0,n=t!==void 0&&t>0?1/t:0;return r+n},Wl={ucaFront:0,ucaRear:0,lcaFront:0,lcaRear:0,tieRod:0,pushRod:0,rack:0};function Yn(e){return!e.measured}function Wn(e){if(!e)return!1;let t=r=>!!r&&Object.values(r).some(n=>n!==void 0&&n>0&&Number.isFinite(n));return t(e.links)||t(e.bushings)||e.rack!==void 0&&e.rack>0}function Us(e,t){let r=e.corner.hardpoints,n=Zo(e.rocker,t.points.rockerAngle);return{ucaFront:r.ucaFront,ucaRear:r.ucaRear,lcaFront:r.lcaFront,lcaRear:r.lcaRear,tieInner:$n(e.inv,t.steer),rockerPivotA:r.rockerPivotA,rockerPivotB:r.rockerPivotB,damperChassis:e.inv.strut?t.points.uprightUpper:r.damperChassis,uprightUpper:t.points.uprightUpper,uprightLower:t.points.uprightLower,tieOuter:t.points.tieOuter,wheelCenter:t.points.wheelCenter,pushrodOuter:t.points.pushrodOuter,contactPatch:t.points.contactPatch,kingpinGround:t.points.kingpinGround,kingpinAtHub:t.points.kingpinAtHub,rockerToPushrod:n.pushrod,rockerToDamper:n.damper,spinAxis:t.points.spinAxis,direct:e.corner.config.actuation==="direct",decoupled:e.corner.config.actuation==="decoupled",mcpherson:e.inv.strut!==void 0,loadedRadius:e.corner.config.loadedRadius,tyreDeflection:0,load:NaN,lifted:!1,clearance:0,contactLength:0}}function Gf(e,t,r=0){let n=t.links??{},o=t.bushings??{},a=(l,u,m)=>{let f=kL(u,m);return f>0&&Number.isFinite(l)?l*f:0},s=o.topMount,i=e.topMount,c=i&&s!==void 0&&s>0&&i.every(Number.isFinite)?[-i[0]/s,-i[1]/s,-i[2]/s]:void 0;return{...c?{topMount:c}:{},ucaFront:a(e.ucaFront,n.ucaFront,o.ucaFront),ucaRear:a(e.ucaRear,n.ucaRear,o.ucaRear),lcaFront:a(e.lcaFront,n.lcaFront,o.lcaFront),lcaRear:a(e.lcaRear,n.lcaRear,o.lcaRear),tieRod:a(e.tieRod,n.tieRod,o.tieInner),pushRod:a(e.pushRod,n.pushRod,void 0),rack:r}}function Cv(e,t,r,n){let o=ve(e,t);if(!(o>1e-9))return{axial:r,radius2:0};let a=(r*r-n*n+o*o)/(2*o);return{axial:a,radius2:Math.max(0,r*r-a*a)}}function Xs(e,t){let r=e.corner.hardpoints,n=e.inv,o={...n};if(n.strut&&t.topMount&&t.topMount.some(i=>i!==0)&&(o.strut={...n.strut,top:ee(n.strut.top,t.topMount)}),t.ucaFront!==0||t.ucaRear!==0){let i=Cv(r.ucaFront,r.ucaRear,ve(r.uprightUpper,r.ucaFront)+t.ucaFront,ve(r.uprightUpper,r.ucaRear)+t.ucaRear);o.ubjAxial0=i.axial,o.ubjRadius2=i.radius2}if(t.lcaFront!==0||t.lcaRear!==0){let i=Cv(r.lcaFront,r.lcaRear,ve(r.uprightLower,r.lcaFront)+t.lcaFront,ve(r.uprightLower,r.lcaRear)+t.lcaRear),c=X(n.lbjRel0,n.lcaDir),l=H(n.lbjRel0,U(n.lcaDir,c)),u=Math.hypot(l[0],l[1],l[2]);o.lbjRel0=u>1e-9?ee(U(n.lcaDir,i.axial),U(l,Math.sqrt(i.radius2)/u)):ee(U(n.lcaDir,i.axial),l)}if(t.tieRod!==0){let i=Math.sqrt(n.tieLen2)+t.tieRod;o.tieLen2=i*i}if(t.rack!==0&&(o.tieInner0=ee(n.tieInner0,U(n.rackAxis,t.rack))),t.pushRod===0)return{corner:e.corner,inv:o,rocker:e.rocker};let a=Math.sqrt(e.rocker.rodLen2)+t.pushRod,s={...e.rocker,rodLen2:a*a};return{corner:e.corner,inv:o,rocker:s}}var ML=8,SL=1e-5,AL=e=>({q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle});function Kf(e,t,r){let n=$f(e,r.force,r.extras??Bf),o=r.alignMoment?ee(n.moment,[0,0,r.alignMoment]):n.moment;return Bs(e,t,n.force,o)}function Ul(e,t,r,n,o,a,s=0){let i=Ie(e,t,r,o,a),c=e.corner.compliance;if(!(Wn(c)&&Yn(e.corner)))return{state:i,forces:Kf(Us(e,i),e.corner.config.pushrodAttach,n),deflection:Wl,rigid:i,iterations:0,converged:!0,bypassed:!0};let u=i,m=e,f=e.corner.config.pushrodAttach,p=Kf(Us(e,i),f,n),d=Wl,h=!1,b=0;for(;b<ML;b++){let g=Us(m,u);if(p=Kf(g,f,n),p.singular)break;d=Gf(p,c,s),m=Xs(e,d);let y=Ie(m,t,r,AL(u),a),R=ve(y.points.wheelCenter,u.points.wheelCenter);if(u=y,R<SL){h=!0;break}}return{state:u,forces:p,deflection:d,rigid:i,iterations:b+1,converged:h&&u.converged,bypassed:!1}}var jl=1e3,Tv=1e5;function Pv(e,t,r,n,o){let a=Ul(e,t,r,n,void 0,o);return{toe:a.state.metrics.toe,camber:a.state.metrics.camber,patch:a.state.points.contactPatch,converged:a.converged,bypassed:a.bypassed}}function Xl(e,t,r,n,o){let a={force:[0,0,n]},s=(b,g=0)=>Pv(e,t,r,{force:b,alignMoment:g},o),i=Pv(e,t,r,a,o);if(i.bypassed)return{toePerLateral:0,camberPerLateral:0,toePerLongitudinal:0,camberPerLongitudinal:0,toePerAligning:0,lateralPatch:0,longitudinalPatch:0,bypassed:!0,converged:!0};let c=s([0,jl,n]),l=s([0,-jl,n]),u=s([jl,0,n]),m=s([-jl,0,n]),f=s([0,0,n],Tv),p=s([0,0,n],-Tv),d=(b,g)=>(b-g)/2,h=[i,c,l,u,m,f,p].every(b=>b.converged);return{toePerLateral:d(c.toe,l.toe),camberPerLateral:d(c.camber,l.camber),toePerLongitudinal:d(u.toe,m.toe),camberPerLongitudinal:d(u.camber,m.camber),toePerAligning:d(f.toe,p.toe),lateralPatch:d(c.patch[1],l.patch[1]),longitudinalPatch:d(u.patch[0],m.patch[0]),bypassed:!1,converged:h}}var FL=1e3;function Hf(e,t=FL){if(!Wn(e.compliance)||!Yn(e))return;let r=rt(e),n=Ie(r,0,0),o=Xl(r,n.beta,0,t);if(!o.bypassed)return{toePerFy:o.toePerLateral/1e3,camberPerFy:o.camberPerLateral/1e3,toePerFx:o.toePerLongitudinal/1e3,camberPerFx:o.camberPerLongitudinal/1e3,toePerMz:o.toePerAligning/1e5}}function ha(e,t=-_f,r=_f,n=21){let o=e.measured;if(o)return{travel:[...o.travel],motionRatio:[...o.motionRatio],camber:[...o.camber],toe:[...o.toe],damperLen:o.damperLen?[...o.damperLen]:o.travel.map(()=>0)};let a=Ke(e,{travelMin:t,travelMax:r,steps:n}),s=Hf(e);return{travel:a.samples.map(i=>i.travel),motionRatio:a.samples.map(i=>i.metrics.motionRatio??1),camber:a.samples.map(i=>i.metrics.camber),toe:a.samples.map(i=>i.metrics.toe),damperLen:a.samples.map(i=>i.metrics.damperLength),...s?{compliance:s}:{}}}function ql(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function fn(e,t){return{motionRatio:ql(e.travel,e.motionRatio,t),camber:ql(e.travel,e.camber,t),toe:ql(e.travel,e.toe,t),damperLen:ql(e.travel,e.damperLen,t)}}var Lv=Math.PI/180,wL=9.81;function hn(e,t,r,n=0){let o=we(e),a=e.wheelbase*(1-e.frontMassFrac),s=e.wheelbase*e.frontMassFrac,i=ua(e,n),c=e.aero?.model?(k,v,x)=>ua(e,n,v,k,x):()=>i,l=fn(t,0),u=fn(r,0),m=e.loadFactor,f=m!==void 0&&m!==1?(m-1)*e.massTotal*wL:0,p=f*e.frontMassFrac/2,d=f*(1-e.frontMassFrac)/2,h=(k,v)=>v>0&&Number.isFinite(v)&&k+v>0?v/(k+v):1,b=qe(e,"front"),g=qe(e,"rear"),y={F:h(e.wheelRateFront+(e.heaveSpringFront??0),b),R:h(e.wheelRateRear+(e.heaveSpringRear??0),g)},R={F:h(e.wheelRateFront+e.arbFront,b),R:h(e.wheelRateRear+e.arbRear,g)};return(k,v,x=0,M=0)=>{let F=c(k,v,x),w=o.rollGradient*k,T=w*Lv,P=o.pitchGradient*v*Lv,A=(O,N)=>{let z=N==="F"?e.trackFront:e.trackRear,E=N==="F"?o.rideRateFront:o.rideRateRear,_=(O==="R"?1:-1)*(z/2)*Math.tan(T),B=(N==="R"?s:-a)*Math.tan(P),V=`${N}${O}`,G=f?F[V]+(N==="F"?p:d):F[V],K=E>0?G/E:0;return{anti:_,sym:B+K}},S={FL:A("L","F"),FR:A("R","F"),RL:A("L","R"),RR:A("R","R")},C=O=>{let N=O[0];return S[O].sym*y[N]+S[O].anti*R[N]},L=la(e,M,o,{FL:C("FL"),FR:C("FR")}),D=w+L.rollDeg,I=(O,N)=>{let z=N==="F"?t:r,E=N==="F"?l:u,_=`${N==="F"?"F":"R"}${O}`,B=S[_].sym+S[_].anti+L.travel[_],V=C(_)+L.travel[_]*R[N],G=B-V,K=fn(z,V),Y=(O==="R"?1:-1)*K.camber;return{travel:V,tyre:G,ground:B,camber:Y,camberRoad:Y+D,toe:K.toe,bumpToe:K.toe-E.toe,damperTravel:E.damperLen-K.damperLen}};return{FL:I("L","F"),FR:I("R","F"),RL:I("L","R"),RR:I("R","R"),steeringJacking:L}}}var zf=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function jn(e){return{enabled:e?.enabled===!0,roadFeedbackGain:Math.min(2,Math.max(0,zf(e?.roadFeedbackGain,1))),turnInFrictionNm:Math.max(0,zf(e?.turnInFrictionNm,0)),columnStiffnessNmPerRad:Math.max(0,zf(e?.columnStiffnessNmPerRad,0))}}function Yf(e,t,r){let n=jn(r);if(!n.enabled)return{roadNm:e,assistanceNm:0,frictionNm:0,columnTwistDeg:0,driverNm:e};let o=e*(n.roadFeedbackGain-1),a=t===0?0:Math.sign(t)*n.turnInFrictionNm,s=e+o+a,i=n.columnStiffnessNmPerRad>0?s/n.columnStiffnessNmPerRad*(180/Math.PI):0;return{roadNm:e,assistanceNm:o,frictionNm:a,columnTwistDeg:i,driverNm:s}}var Dv=()=>({totalNm:0,aligningNm:0,lateralNm:0,longitudinalNm:0,jackingNm:0});function Un(e){let t=e.steerFront;return!!(t?.rackRatioMmPerRev&&t.innerJacobian&&t.innerJacobian.length>=2&&t.outerJacobian&&t.outerJacobian.length>=2&&t.meanDeg.length>=2)}function qs(e,t,r,n="model",o){let a=e.steerFront;if(!Un(e)||!a)return null;let s=t<0?-1:1,c=a.rackRatioMmPerRev/(2*Math.PI)/1e3,l=t>=0,u=o&&a.travelSurface?ia(a,Math.abs(t),l?o.FL:o.FR,l?o.FR:o.FL):ca(a,Math.abs(t));if(!u.innerJacobian||!u.outerJacobian)return null;let m=(b,g)=>{let y=r[b],R=b==="FL"?-1:1,k=-R*y.Fy,x={aligning:1e3*(-R*y.Mz)*g.yaw,lateral:k*g.lateral,longitudinal:y.Fx*g.longitudinal,jacking:y.Fz*g.vertical},M=Dv();M.aligningNm=-s*x.aligning*c,M.lateralNm=-s*x.lateral*c,M.longitudinalNm=-s*x.longitudinal*c,M.jackingNm=-s*x.jacking*c,M.totalNm=M.aligningNm+M.lateralNm+M.longitudinalNm+M.jackingNm;let F=-s*(x.aligning+x.lateral+x.longitudinal+x.jacking);return{moment:M,rackN:F}},f=m("FL",l?u.innerJacobian:u.outerJacobian),p=m("FR",l?u.outerJacobian:u.innerJacobian),d=Dv();for(let b of[f.moment,p.moment])d.aligningNm+=b.aligningNm,d.lateralNm+=b.lateralNm,d.longitudinalNm+=b.longitudinalNm,d.jackingNm+=b.jackingNm,d.totalNm+=b.totalNm;let h=Yf(d.totalNm,t,e.steeringSystem);return d.totalNm=h.driverNm,{...d,roadNm:h.roadNm,assistanceNm:h.assistanceNm,frictionNm:h.frictionNm,columnTwistDeg:h.columnTwistDeg,rackForceN:f.rackN+p.rackN,aligningSource:n,perWheel:{FL:f.moment,FR:p.moment}}}var CL=e=>"front"in e&&"rear"in e;function ba(e,t){return CL(e)?e[t]:e}function jf(e,t,r=24){let n=Math.max(1,t),o=n/Math.max(1,r-1),a=[],s=[],i=[];for(let l=0;l<r;l++){let u=l*o;a.push(u),s.push(e.muX(u)),i.push(e.muY(u))}let c=(l,u)=>{if(!(u>0))return l[0];if(u>=n)return l[r-1];let m=Math.min(r-2,Math.floor(u/o)),f=(u-a[m])/o;return l[m]+f*(l[m+1]-l[m])};return{muX:l=>c(s,l),muY:l=>c(i,l)}}function Wf(e,t){let r=Math.max(0,t.Fz),n=e.muY(r)*r,o=e.muX(r)*r;if(!(n>0))return{fyUsed:0,fyMax:0,fyRes:0};let a=o>0?Math.min(1,Math.abs(t.Fx)/o):0,s=n*Math.sqrt(Math.max(0,1-a*a)),i=Math.abs(t.Fy);return{fyUsed:i,fyMax:s,fyRes:Math.max(0,s-i)}}function Ev(e,t,r){let n=Wf(e,t),o=Wf(e,r);return{left:n,right:o,fyRes:n.fyRes+o.fyRes}}function Dr(e,t,r){let n=Ev(ba(e,"front"),t.FL,t.FR),o=Ev(ba(e,"rear"),t.RL,t.RR),a=r.lf>0&&Number.isFinite(r.lf)?r.lf:0,s=r.lr>0&&Number.isFinite(r.lr)?r.lr:0,i=o.fyRes*s,c=n.fyRes*a,l=i-c,u=Math.max(Math.abs(i),Math.abs(c));return{stabil:i,agil:c,diff:l,rel:u>0?l/u:0,front:n,rear:o}}var Qs=[{q:"p",section:"INFLATION_PRESSURE_RANGE",min:"PRESMIN",max:"PRESMAX",what:"pressure"},{q:"fz",section:"VERTICAL_FORCE_RANGE",min:"FZMIN",max:"FZMAX",what:"load"},{q:"kappa",section:"LONG_SLIP_RANGE",min:"KPUMIN",max:"KPUMAX",what:"slip ratio"},{q:"alpha",section:"SLIP_ANGLE_RANGE",min:"ALPMIN",max:"ALPMAX",what:"slip angle"},{q:"gamma",section:"INCLINATION_ANGLE_RANGE",min:"CAMMIN",max:"CAMMAX",what:"inclination"}],PL=Qs.flatMap(e=>[e.min,e.max]);function LL(e){let t={};for(let r of Qs){let n=e[r.min],o=e[r.max],a={};Number.isFinite(n)&&(a.min=n),Number.isFinite(o)&&(a.max=o),(a.min!==void 0||a.max!==void 0)&&(t[r.q]=a)}return Object.keys(t).length?t:void 0}function Ql(e){if(e.kind==="magic")return e.range??LL(e.coeffs)}function Uf(e){return Math.max(1,e.kind==="magic"?e.fnomin:e.nominalLoad)}function Iv(e,t,r,n,o){let a=(r-t)/n,s=t,i=e(t);for(let c=t+a;c<=r;c+=a){let l=e(c);o(l,i)&&(i=l,s=c)}return s}function Qt(e){let t=_v.get(e);if(t!==void 0)return t;let r=10*Uf(e.model),{turnover:n,collapse:o}=EL(e,r),a=n??o??r;return _v.set(e,a),a}var _v=new WeakMap;function EL(e,t){let r=Uf(e.model),n=m=>e.muY(m),o=m=>n(m)*m,a=80,s=t/a,i=null,c=o(s);for(let m=2;m<=a;m++){let f=o(m*s);if(f<c){i=Iv(o,(m-2)*s,m*s,20,(p,d)=>p>d);break}c=f}let l=null,u=n(s);for(let m=2;m<=a;m++){let f=n(m*s);if(f>u){let p=Iv(n,(m-2)*s,m*s,40,(d,h)=>d<h);n(p)<.05*n(r)&&(l=p);break}u=f}return{turnover:i,collapse:l}}var Nv=.1;function Zl(e,t=Uf(e)){let r=Pe(e).muX(t);return{muX:r,none:Number.isFinite(r)&&r<Nv}}var Ov=["FL","FR","RL","RR"],IL=e=>e==="FL"||e==="RL",_L=e=>e==="FL"||e==="FR"?"front":"rear";function Jl(e,t,r,n){if(!(e.full>e.open)||n.ayDir===0)return e.full;let o=n.halfTrack[e.axle],a={};for(let l of Ov)a[l]={...t[l]};let s=l=>{let u=0;for(let f of Ov)_L(f)===e.axle&&(a[f].Fx=e.sense*(f===e.strong?l-e.open/2:e.open/2),u-=(IL(f)?o:-o)*a[f].Fx);let m=Dr(r,a,n.arms);return u*n.ayDir>=0?Math.abs(u)<=m.stabil:Math.abs(u)<=m.agil};if(s(e.full))return e.full;let i=e.open,c=e.full;for(let l=0;l<20&&c-i>.001*e.full;l++){let u=.5*(i+c);s(u)?i=u:c=u}return i}var NL=[["PCY1","Shape factor Cfy for lateral forces",1.3],["PDY1","Lateral friction Muy",1],["PDY2","Variation of friction Muy with load",0],["PDY3","Variation of friction Muy with squared camber",0],["PEY1","Lateral curvature Efy at Fznom",0],["PEY2","Variation of curvature Efy with load",0],["PEY3","Zero order camber dependency of curvature Efy",0],["PEY4","Variation of curvature Efy with camber",0],["PEY5","Variation of curvature Efy with camber squared",0],["PKY1","Maximum value of stiffness Kfy/Fznom",-15],["PKY2","Load at which Kfy reaches maximum value",2],["PKY3","Variation of Kfy/Fznom with camber",0],["PKY4","Curvature of stiffness Kfy",2],["PKY5","Peak stiffness variation with camber squared",0],["PKY6","Fy camber stiffness factor",0],["PKY7","Vertical load dependency of camber stiffness",0],["PHY1","Horizontal shift Shy at Fznom",0],["PHY2","Variation of shift Shy with load",0],["PHY3","Variation of shift Shy with camber",0],["PVY1","Vertical shift in Svy/Fz at Fznom",0],["PVY2","Variation of shift Svy/Fz with load",0],["PVY3","Variation of shift Svy/Fz with camber",0],["PVY4","Variation of shift Svy/Fz with camber and load",0],["PPY1","Influence of inflation pressure on cornering stiffness",0],["PPY2","Influence of inflation pressure on dependency of nominal tyre load on cornering stiffness",0],["PPY3","Linear influence of inflation pressure on lateral peak friction",0],["PPY4","Quadratic influence of inflation pressure on lateral peak friction",0],["PPY5","Influence of inflation pressure on camber stiffness",0]],OL=[["PCX1","Shape factor Cfx for longitudinal force",1.65],["PDX1","Longitudinal friction Mux at Fznom",1],["PDX2","Variation of friction Mux with load",0],["PDX3","Variation of friction Mux with camber squared",0],["PEX1","Longitudinal curvature Efx at Fznom",0],["PEX2","Variation of curvature Efx with load",0],["PEX3","Variation of curvature Efx with load squared",0],["PEX4","Factor in curvature Efx while driving",0],["PKX1","Longitudinal slip stiffness Kfx/Fz at Fznom",20],["PKX2","Variation of slip stiffness Kfx/Fz with load",0],["PKX3","Exponent in slip stiffness Kfx/Fz with load",0],["PHX1","Horizontal shift Shx at Fznom",0],["PHX2","Variation of shift Shx with load",0],["PVX1","Vertical shift Svx/Fz at Fznom",0],["PVX2","Variation of shift Svx/Fz with load",0],["PPX1","Linear influence of inflation pressure on longitudinal slip stiffness",0],["PPX2","Quadratic influence of inflation pressure on longitudinal slip stiffness",0],["PPX3","Linear influence of inflation pressure on peak longitudinal friction",0],["PPX4","Quadratic influence of inflation pressure on peak longitudinal friction",0]],VL=[["QBZ1","Trail slope factor for trail Bpt at Fznom",8],["QBZ2","Variation of slope Bpt with load",0],["QBZ3","Variation of slope Bpt with load squared",0],["QBZ4","Variation of slope Bpt with camber",0],["QBZ5","Variation of slope Bpt with absolute camber",0],["QBZ6","Camber influence Bt",0],["QBZ9","Factor for scaling factors of slope factor Br of Mzr",0],["QBZ10","Factor for dimensionless cornering stiffness of Br of Mzr",0],["QCZ1","Shape factor Cpt for pneumatic trail",1.1],["QDZ1","Peak trail Dpt = Dpt*(Fz/Fznom*R0)",.1],["QDZ2","Variation of peak Dpt with load",0],["QDZ3","Variation of peak Dpt with camber",0],["QDZ4","Variation of peak Dpt with camber squared",0],["QDZ6","Peak residual torque Dmr = Dmr/(Fz*R0)",0],["QDZ7","Variation of peak factor Dmr with load",0],["QDZ8","Variation of peak factor Dmr with camber",0],["QDZ9","Variation of peak factor Dmr with camber and load",0],["QDZ10","Variation of peak factor Dmr with camber squared",0],["QDZ11","Variation of Dmr with camber squared and load",0],["QEZ1","Trail curvature Ept at Fznom",0],["QEZ2","Variation of curvature Ept with load",0],["QEZ3","Variation of curvature Ept with load squared",0],["QEZ4","Variation of curvature Ept with sign of Alpha-t",0],["QEZ5","Variation of Ept with camber and sign Alpha-t",0],["QHZ1","Trail horizontal shift Sht at Fznom",0],["QHZ2","Variation of shift Sht with load",0],["QHZ3","Variation of shift Sht with camber",0],["QHZ4","Variation of shift Sht with camber and load",0],["PPZ1","Effect of inflation pressure on length of pneumatic trail",0],["PPZ2","Influence of inflation pressure on residual aligning torque",0],["SSZ1","Nominal value of s/R0: effect of Fx on Mz",0],["SSZ2","Variation of distance s/R0 with Fy/Fznom",0],["SSZ3","Variation of distance s/R0 with camber",0],["SSZ4","Variation of distance s/R0 with load and camber",0]],BL=[["RBX1","Slope factor for combined slip Fx reduction",0],["RBX2","Variation of slope Fx reduction with kappa",0],["RBX3","Influence of camber on stiffness for Fx combined",0],["RCX1","Shape factor for combined slip Fx reduction",1],["REX1","Curvature factor of combined Fx",0],["REX2","Curvature factor of combined Fx with load",0],["RHX1","Shift factor for combined slip Fx reduction",0],["RBY1","Slope factor for combined Fy reduction",0],["RBY2","Variation of slope Fy reduction with alpha",0],["RBY3","Shift term for alpha in slope Fy reduction",0],["RBY4","Influence of camber on stiffness of Fy combined",0],["RCY1","Shape factor for combined Fy reduction",1],["REY1","Curvature factor of combined Fy",0],["REY2","Curvature factor of combined Fy with load",0],["RHY1","Shift factor for combined Fy reduction",0],["RHY2","Shift factor for combined Fy reduction with load",0],["RVY1","Kappa induced side force Svyk/Muy*Fz at Fznom",0],["RVY2","Variation of Svyk/Muy*Fz with load",0],["RVY3","Variation of Svyk/Muy*Fz with camber",0],["RVY4","Variation of Svyk/Muy*Fz with alpha",0],["RVY5","Variation of Svyk/Muy*Fz with kappa",1],["RVY6","Variation of Svyk/Muy*Fz with atan(kappa)",0]],$L=[["LFZO","Scale factor of nominal (rated) load",1],["LCX","Scale factor of Fx shape factor",1],["LMUX","Scale factor of Fx peak friction coefficient",1],["LEX","Scale factor of Fx curvature factor",1],["LKX","Scale factor of Fx slip stiffness",1],["LHX","Scale factor of Fx horizontal shift",1],["LVX","Scale factor of Fx vertical shift",1],["LCY","Scale factor of Fy shape factor",1],["LMUY","Scale factor of Fy peak friction coefficient",1],["LEY","Scale factor of Fy curvature factor",1],["LKY","Scale factor of Fy cornering stiffness",1],["LKYC","Scale factor of camber force stiffness",1],["LKZC","Scale factor of camber torque stiffness",1],["LHY","Scale factor of Fy horizontal shift",1],["LVY","Scale factor of Fy vertical shift",1],["LTR","Scale factor of peak of pneumatic trail",1],["LRES","Scale factor for offset of residual torque",1],["LXAL","Scale factor of alpha influence on Fx",1],["LYKA","Scale factor of kappa influence on Fy",1],["LVYKA","Scale factor of kappa induced Fy",1],["LS","Scale factor of moment arm of Fx",1]],Bv=[["lateral",NL],["longitudinal",OL],["aligning",VL],["combined",BL],["scaling",$L]].flatMap(([e,t])=>t.map(([r,n,o])=>({key:r,section:e,text:n,fallback:o}))),mz=new Map(Bv.map(e=>[e.key,e]));var GL=/^\$\s*EDITED\s+([A-Z][A-Z0-9_]*)\s+was\s+(absent|[-+0-9.eE]+)\s*$/;function $v(e){let t={};for(let r of e.split(/\r?\n/)){let n=r.trim().match(GL);if(!n)continue;let o=n[2]==="absent"?null:parseFloat(n[2]);(o===null||Number.isFinite(o))&&(t[n[1]]=o)}return Object.keys(t).length?t:void 0}var HL=/^\s*\$\s*UNLOADED_RADIUS_STAND_IN\s*=\s*([0-9.eE+-]+)/,zL=/^\$-+ written by (?:PaceDynamics|PaceLab)\b/m,YL=/^\$\s*AXIS_SYSTEM\s*=\s*(ISO-W|SAE)\b/m;function WL(e){let t=e.match(YL);return t?{axisSystem:t[1]==="SAE"?"sae":"iso",trustSide:!0}:zL.test(e)?{axisSystem:"sae",trustSide:!1}:{axisSystem:"iso",trustSide:!0}}function jL(e){return e>=62?"6.2":e>=61?"6.1":"5.2"}var Gv=new Map([["pa",1],["pascal",1],["kpa",1e3],["kilopascal",1e3],["mpa",1e6],["megapascal",1e6],["bar",1e5],["psi",6894.757293168]]);function UL(e,t,r){let n=r.PRESSURE?.trim().toLowerCase(),o=n===void 0?1:Gv.get(n);if(o===void 0)return;let a=(c,l)=>l===1?c:Number((c*l).toPrecision(12)),s=e.NOMPRES??e.INFLPRES;if(s!==void 0)return a(s,o);let i=e.INFLATION_PRESSURE;if(i!==void 0)return n!==void 0?a(i,o):t.PROPERTY_FILE_FORMAT?.trim().toUpperCase()==="MF_05"?a(i,1e5):void 0}var XL=new Map([["radians",1],["radian",1],["rad",1],["degrees",Math.PI/180],["degree",Math.PI/180],["deg",Math.PI/180]]);function qL(e,t){let r=(s,i)=>s===void 0?1:i.get(s.trim().toLowerCase()),n=r(t.ANGLE,XL),o={fz:1,kappa:1,alpha:n,gamma:n,p:r(t.PRESSURE,Gv)},a={};for(let s of Qs){let i=o[s.q];if(i===void 0)continue;let c={};for(let[l,u]of[["min",s.min],["max",s.max]]){let m=e[u];Number.isFinite(m)&&(c[l]=i===1?m:Number((m*i).toPrecision(12)),delete e[u])}(c.min!==void 0||c.max!==void 0)&&(a[s.q]=c)}return Object.keys(a).length?a:void 0}function Zs(e,t="imported",r={}){let n=WL(e),o=r.axisSystem??n.axisSystem,a={},s={},i={},c="",l;for(let g of e.split(/\r?\n/)){let y=g.match(HL);y&&(l=parseFloat(y[1]));let R=g.replace(/[$!].*$/,"").trim();if(!R)continue;if(R.startsWith("[")){c=(R.match(/^\[([^\]]*)/)?.[1]??"").trim().toUpperCase();continue}let k=R.indexOf("=");if(k<0)continue;let v=R.slice(0,k).trim().toUpperCase(),x=R.slice(k+1).trim(),M=x.match(/^'([^']*)'|^"([^"]*)"/);if(M){s[v]=M[1]??M[2]??"",c==="UNITS"&&(i[v]=s[v]);continue}let F=parseFloat(x);Number.isFinite(F)&&(a[v]=F)}let u=jL(a.FITTYP??62),m=$v(e),f=m?Object.fromEntries(Object.entries(m).filter(([g])=>a[g]!==void 0)):void 0,p=a.VERTICAL_STIFFNESS??a.KZ??0,d=UL(a,s,i),h=qL(a,i),b=[];return a.UNLOADED_RADIUS===void 0&&a.R0===void 0&&b.push("UNLOADED_RADIUS"),p<=0&&b.push("VERTICAL_STIFFNESS"),a.FNOMIN===void 0&&b.push("FNOMIN"),d===void 0&&b.push("NOMPRES"),{kind:"magic",name:t,version:u,coeffs:a,axisSystem:o,side:n.trustSide?s.TYRESIDE==="RIGHT"?"right":s.TYRESIDE==="LEFT"?"left":void 0:void 0,fnomin:a.FNOMIN??5e3,unloadedR0:a.UNLOADED_RADIUS??a.R0??(l!==void 0&&l>0?l:.3),...a.WIDTH!==void 0&&a.WIDTH>0?{sectionWidth:a.WIDTH}:{},verticalStiffness:p>0?p/1e3:0,...a.FREFF!==void 0&&!a.DREFF?{rollingFraction:a.FREFF}:{},...a.LATERAL_STIFFNESS!==void 0&&a.LATERAL_STIFFNESS>0?{relaxation:{sigma:0,carcassStiffness:a.LATERAL_STIFFNESS/1e3,source:"fitted"}}:{},nomPressure:d??0,missing:b,...f&&Object.keys(f).length?{edited:f}:{},...h?{range:h}:{}}}function mr(e){if(!e)return null;let t=e.unloadedR0;return t===void 0||!(t>0)||e.kind==="magic"&&e.missing?.includes("UNLOADED_RADIUS")?null:t*1e3}function eu(e){if(!e)return null;let t=e.sectionWidth;return t!==void 0&&t>0?t:null}var xz=Math.PI/180;var Sz=Math.PI/180,Az=180/Math.PI;function Js(){return{kind:"simple",name:"Simple (default)",Bx:11,Cx:1.6,muX0:1.7,loadSensX:-8e-5,By:9,Cy:1.4,muY0:1.6,loadSensY:-1e-4,nominalLoad:1500,verticalStiffness:120}}var zv=`$ AXIS_SYSTEM = SAE (authored in the evaluation frame: y right)
|
|
3
3
|
[MODEL]
|
|
4
4
|
FITTYP = 62
|
|
5
5
|
[DIMENSION]
|
|
@@ -108,7 +108,7 @@ QHZ1 = 0
|
|
|
108
108
|
QHZ2 = 0
|
|
109
109
|
QHZ3 = 0
|
|
110
110
|
QHZ4 = 0
|
|
111
|
-
`;function
|
|
111
|
+
`;function Xf(){return Zs(zv,"Example MF6.2")}var ZL=Math.PI/180,Yv=2,Wv=2;function jv(e){let t=Math.sin(Wv*Math.atan(1/Yv)),r=-e.corneringStiffness/(e.Fz0*t),n=e.camberStiffness/ZL/e.Fz0,o=(a,s=5)=>Number(a.toFixed(s)).toString();return`$ AXIS_SYSTEM = SAE (authored in the evaluation frame: y right, +inclination gives +Fy)
|
|
112
112
|
[MODEL]
|
|
113
113
|
FITTYP = 62
|
|
114
114
|
[DIMENSION]
|
|
@@ -170,9 +170,9 @@ PEY3 = 0.1
|
|
|
170
170
|
PEY4 = -4
|
|
171
171
|
PEY5 = 0
|
|
172
172
|
PKY1 = ${o(r)}
|
|
173
|
-
PKY2 = ${o(
|
|
173
|
+
PKY2 = ${o(Yv)}
|
|
174
174
|
PKY3 = 0.8
|
|
175
|
-
PKY4 = ${o(
|
|
175
|
+
PKY4 = ${o(Wv)}
|
|
176
176
|
PKY5 = 0
|
|
177
177
|
PKY6 = ${o(n)}
|
|
178
178
|
PKY7 = 0
|
|
@@ -220,7 +220,7 @@ QHZ1 = 0
|
|
|
220
220
|
QHZ2 = 0
|
|
221
221
|
QHZ3 = 0
|
|
222
222
|
QHZ4 = 0
|
|
223
|
-
`}function Lr(e){let t=js(zv(e),e.name);return{...t,missing:[...t.missing??[],"a particular tyre \u2014 every coefficient is derived from class-level targets stated in generic.ts, on the road; run it with grip_scale = stiffness_scale = 1"]}}var Yv={name:"Formula Student 18x6-10",R0:.228,width:.1524,Fz0:950,Kz:110,pressure:83,muY:1.8,muX:1.7,muYLoad:-.2,muXLoad:-.15,corneringStiffness:26e3,slipStiffnessPerLoad:32,camberStiffness:45,Cy:1.5,Cx:1.6,RBY1:12,RBY2:12,RBX1:13,RBX2:10,trail:.08},Wv={name:"Formula 1 slick 18in",R0:.36,width:.305,Fz0:5e3,Kz:300,pressure:150,muY:1.8,muX:1.7,muYLoad:-.15,muXLoad:-.12,corneringStiffness:15e4,slipStiffnessPerLoad:28,camberStiffness:260,Cy:1.45,Cx:1.6,RBY1:12,RBY2:12,RBX1:13,RBX2:10,trail:.09},jv={name:"GT slick 18in",R0:.33,width:.3,Fz0:4e3,Kz:280,pressure:180,muY:1.45,muX:1.4,muYLoad:-.12,muXLoad:-.1,corneringStiffness:11e4,slipStiffnessPerLoad:24,camberStiffness:190,Cy:1.4,Cx:1.6,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.09},Uv={name:"Street tyre 245/40 R18",R0:.325,width:.245,Fz0:4e3,Kz:220,pressure:240,muY:1.05,muX:1,muYLoad:-.1,muXLoad:-.08,corneringStiffness:75e3,slipStiffnessPerLoad:20,camberStiffness:100,Cy:1.3,Cx:1.55,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.12},Xv={name:"Cup slick 18in",R0:.32,width:.25,Fz0:3500,Kz:280,pressure:180,muY:1.42,muX:1.38,muYLoad:-.12,muXLoad:-.1,corneringStiffness:9e4,slipStiffnessPerLoad:24,camberStiffness:160,Cy:1.4,Cx:1.6,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.09},qv={name:"Stock car slick 18in",R0:.357,width:.32,Fz0:4500,Kz:320,pressure:200,muY:1.35,muX:1.3,muYLoad:-.12,muXLoad:-.1,corneringStiffness:125e3,slipStiffnessPerLoad:22,camberStiffness:170,Cy:1.4,Cx:1.6,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.09},Qv={name:"Hill-climb slick 13in",R0:.3,width:.3,Fz0:2e3,Kz:200,pressure:150,muY:1.75,muX:1.65,muYLoad:-.18,muXLoad:-.14,corneringStiffness:6e4,slipStiffnessPerLoad:28,camberStiffness:90,Cy:1.45,Cx:1.6,RBY1:12,RBY2:12,RBX1:13,RBX2:10,trail:.085},Zv={name:"Race truck tyre 315/70 R22.5",R0:.506,width:.315,Fz0:13e3,Kz:1e3,pressure:800,muY:1.1,muX:1.05,muYLoad:-.1,muXLoad:-.08,corneringStiffness:15e4,slipStiffnessPerLoad:14,camberStiffness:200,Cy:1.3,Cx:1.55,RBY1:10,RBY2:10,RBX1:11,RBX2:10,trail:.1},Uf=()=>Lr(Yv),Xf=()=>Lr(Wv),qf=()=>Lr(jv),Qf=()=>Lr(Uv),Zf=()=>Lr(Xv),Jf=()=>Lr(qv),eh=()=>Lr(Qv),th=()=>Lr(Zv);var Jv=e=>Number.isFinite(e)&&e>0;function Zl(e,t){let r=Jv(t.grip)?t.grip:1,n=Jv(t.stiffness)?t.stiffness:1;if(r===1&&n===1)return e;if(e.kind==="simple"){let o=n/r;return{...e,muX0:e.muX0*r,muY0:e.muY0*r,loadSensX:e.loadSensX*r,loadSensY:e.loadSensY*r,Bx:e.Bx*o,By:e.By*o}}return{...e,coeffs:{...e.coeffs,LMUX:(e.coeffs.LMUX??1)*r,LMUY:(e.coeffs.LMUY??1)*r,LKX:(e.coeffs.LKX??1)*n,LKY:(e.coeffs.LKY??1)*n}}}var Xs={ok:!0,violation:0},jn=1e7;function Dr(e,t){let r;try{r=e.build(t)}catch(s){return{total:jn*2,feasible:!1,terms:[],reason:`build failed: ${String(s)}`}}let n=e.feasible(r);if(!n.ok)return{total:jn+Math.max(0,n.violation),feasible:!1,terms:[],reason:n.reason};let o;try{o=e.terms(r)}catch(s){return{total:jn*2,feasible:!1,terms:[],reason:`objective threw: ${String(s)}`}}let a=0;for(let s of o)a+=s.contribution;return Number.isFinite(a)?{total:a,feasible:!0,terms:o}:{total:jn*2,feasible:!1,terms:o,reason:"objective was not finite"}}var qs=(e,t)=>!t||(e.feasible!==t.feasible?e.feasible:e.total<t.total);function rh(e,t){return t.map((r,n)=>Math.min(e[n].hi,Math.max(e[n].lo,r)))}var Er=e=>e.map(t=>t.start);function Jl(e){let t=e>>>0;return()=>{t=t+1831565813>>>0;let r=Math.imul(t^t>>>15,1|t);return r=r+Math.imul(r^r>>>7,61|r)^r,((r^r>>>14)>>>0)/4294967296}}function jL(e){let t=0;for(;t===0;)t=e();return Math.sqrt(-2*Math.log(t))*Math.cos(2*Math.PI*e())}function nh(e,t){let{budget:r}=t,n=Math.max(1,Math.floor(t.progressEvery??1)),o=e.variables,a=p=>rh(o,p.map((f,h)=>o[h].lo+f*(o[h].hi-o[h].lo))),s=p=>p.map((f,h)=>(f-o[h].lo)/(o[h].hi-o[h].lo)),i=0,c=0,l=null,u=null,m=[];return{vars:o,denorm:a,norm:s,evaluate:p=>{if(i>=r)return l?.total??Number.POSITIVE_INFINITY;i++;let f=p.map(g=>Math.min(1,Math.max(0,g))),h=Dr(e,a(f));h.feasible||c++;let b=qs(h,l)?h:l;return b===h&&(l=h,u=f),m.push(b.total),t.onProgress&&(i%n===0||i===r)&&t.onProgress({evaluations:i,budget:r,x:a(u),score:b,infeasible:c}),h.total},left:()=>r-i,result:p=>({method:p,x:u?a(u):Er(o),score:l??Dr(e,Er(o)),evaluations:i,history:m,infeasible:c})}}var oh=(e,t,r,n=0,o)=>{let a=t?r.norm(Er(e.variables)):e.variables.map(()=>.5);return!(n>0)||!o?a:a.map(s=>Math.min(1,Math.max(0,s+n*2*(o()-.5))))};function e1(e,t){let r=nh(e,t),n=Jl(t.seed??1),o=e.variables.length;for(r.evaluate(oh(e,t.warmStart!==!1,r,t.startJitter,n));r.left()>0;){let a=[];for(let s=0;s<o;s++)a.push(n());r.evaluate(a)}return r.result("random")}function fa(e,t){let r=nh(e,t),n=e.variables.length,o=Jl(t.seed??1),a=1,s=2,i=.5,c=.5,l=oh(e,t.warmStart!==!1,r,t.startJitter,o),u=.25;for(;r.left()>0;){let m=[{u:l,f:r.evaluate(l)}];for(let d=0;d<n&&r.left()>0;d++){let p=l.slice();p[d]+=p[d]+u>1?-u:u,m.push({u:p,f:r.evaluate(p)})}for(;r.left()>0;){m.sort((g,y)=>g.f-y.f);let d=m[n],p=new Array(n).fill(0);for(let g=0;g<n;g++)for(let y=0;y<n;y++)p[y]+=m[g].u[y]/n;let f=g=>p.map((y,R)=>y+g*(y-d.u[R])),h=f(a),b=r.evaluate(h);if(b<m[0].f){let g=f(s),y=r.evaluate(g);m[n]=y<b?{u:g,f:y}:{u:h,f:b}}else if(b<m[n-1].f)m[n]={u:h,f:b};else{let g=f(-i),y=r.evaluate(g);if(y<d.f)m[n]={u:g,f:y};else{let R=m[0],k=0;for(let v=1;v<=n;v++)for(let x=0;x<n;x++)k=Math.max(k,Math.abs(m[v].u[x]-R.u[x]));if(k<1e-4)break;for(let v=1;v<=n&&r.left()>0;v++){let x=m[v].u.map((M,A)=>R.u[A]+c*(M-R.u[A]));m[v]={u:x,f:r.evaluate(x)}}}}}m.sort((d,p)=>d.f-p.f),l=m[0].u.map(d=>Math.min(1,Math.max(0,d+.05*(o()-.5)))),u=Math.max(.02,u*.5)}return r.result("nelder-mead")}function t1(e,t){let r=nh(e,t),n=e.variables.length,o=Jl(t.seed??1),a=4+Math.floor(3*Math.log(n)),s=Math.floor(a/2),i=[];for(let M=1;M<=s;M++)i.push(Math.log(s+.5)-Math.log(M));let c=i.reduce((M,A)=>M+A,0);for(let M=0;M<s;M++)i[M]/=c;let l=1/i.reduce((M,A)=>M+A*A,0),u=(l+2)/(n+l+5),m=1+2*Math.max(0,Math.sqrt((l-1)/(n+1))-1)+u,d=(4+l/n)/(n+4+2*l/n),p=(n+2)/3,f=Math.min(1,p*2/((n+1.3)**2+l)),h=Math.min(1-f,p*2*(l-2+1/l)/((n+2)**2+l)),b=Math.sqrt(n)*(1-1/(4*n)+1/(21*n*n)),g=oh(e,t.warmStart!==!1,r,t.startJitter,o),y=.25,R=new Array(n).fill(1),k=new Array(n).fill(0),v=new Array(n).fill(0),x=0;for(;r.left()>0;){x++;let M=[];for(let F=0;F<a&&r.left()>0;F++){let S=[];for(let L=0;L<n;L++)S.push(jL(o));let P=g.map((L,D)=>L+y*R[D]*S[D]);M.push({z:S,u:P,f:r.evaluate(P)})}if(M.length<s)break;M.sort((F,S)=>F.f-S.f);let A=g.slice(),w=new Array(n).fill(0);g=new Array(n).fill(0);for(let F=0;F<s;F++)for(let S=0;S<n;S++)g[S]+=i[F]*M[F].u[S],w[S]+=i[F]*M[F].z[S];g=g.map(F=>Math.min(1,Math.max(0,F)));for(let F=0;F<n;F++)k[F]=(1-u)*k[F]+Math.sqrt(u*(2-u)*l)*w[F];let C=Math.sqrt(k.reduce((F,S)=>F+S*S,0)),T=C/Math.sqrt(1-(1-u)**(2*x))/b<1.4+2/(n+1)?1:0;for(let F=0;F<n;F++){let S=(g[F]-A[F])/(y*R[F]);v[F]=(1-d)*v[F]+T*Math.sqrt(d*(2-d)*l)*S}for(let F=0;F<n;F++){let S=0;for(let D=0;D<s;D++)S+=i[D]*M[D].z[F]*M[D].z[F];let P=R[F]*R[F],L=(1-f-h)*P+f*(v[F]*v[F]+(1-T)*d*(2-d)*P)+h*S*P;R[F]=Math.sqrt(Math.max(1e-12,L))}if(y*=Math.exp(u/m*(C/b-1)),y<1e-6||y>10)break}return r.result("sep-cma-es")}var ha=[{name:"random",run:e1},{name:"nelder-mead",run:fa},{name:"sep-cma-es",run:t1}];var Iz=Math.PI/180;var eu=Math.PI/180;var Vz={Fz:100,alpha:.25*eu,kappa:.005,gamma:.5*eu,p:6900},r1={Fz:100,alpha:1*eu,kappa:.02,gamma:.5*eu,p:6900};var n1=Math.PI/180,zz={t:{s:1,sec:1,ms:.001},v:{"m/s":1,"km/h":1/3.6,"km/hr":1/3.6,kph:1/3.6},alpha:{rad:1,deg:n1},gamma:{rad:1,deg:n1},p:{pa:1,kpa:1e3,bar:1e5,mpa:1e6},rl:{m:1,mm:.001,cm:.01},Fz:{n:1},Fx:{n:1},Fy:{n:1},Mz:{nm:1,"n-m":1}};var Xz=Math.PI/180;var aD=Math.PI/180;var r6=3*aD;var i6=Math.PI/180;var x6=Math.PI/180;var dD={RCX1:1,RCY1:1,REX1:0,REY1:0,RBY3:0,RHX1:0,RHY1:0},s1={RBX1:15,RBX2:15,RBY1:18,RBY2:19,...dD};var P6=Math.PI/180;var yD=Math.PI/180,tu=[{id:"alpha",symbol:"\u03B1",name:"Slip angle",group:"inputs",unit:"rad"},{id:"kappa",symbol:"\u03BA",name:"Slip ratio",group:"inputs",unit:"-"},{id:"gamma",symbol:"\u03B3",name:"Inclination",group:"inputs",unit:"rad"},{id:"Fz",symbol:"Fz",name:"Vertical load",group:"inputs",unit:"N",quantity:"force"},{id:"p",symbol:"p",name:"Inflation pressure",group:"inputs",unit:"Pa",quantity:"pressure"},{id:"V",symbol:"V",name:"Speed",group:"inputs",unit:"m/s",quantity:"speed"},{id:"Fx",symbol:"Fx",name:"Longitudinal force",group:"forces",unit:"N",quantity:"force"},{id:"Fy",symbol:"Fy",name:"Lateral force",group:"forces",unit:"N",quantity:"force"},{id:"Mx",symbol:"Mx",name:"Overturning moment",group:"moments",unit:"N\xB7m"},{id:"My",symbol:"My",name:"Rolling-resistance moment",group:"moments",unit:"N\xB7m"},{id:"Mz",symbol:"Mz",name:"Aligning moment",group:"moments",unit:"N\xB7m"},{id:"t",symbol:"t",name:"Pneumatic trail",group:"aligning",unit:"m",quantity:"length"},{id:"Mzr",symbol:"Mzr",name:"Residual aligning moment",group:"aligning",unit:"N\xB7m"},{id:"s",symbol:"s",name:"Lever arm of Fx",group:"aligning",unit:"m",quantity:"length"},{id:"muX",symbol:"\u03BCx",name:"Longitudinal friction Fx/Fz",group:"friction",unit:"-"},{id:"muY",symbol:"\u03BCy",name:"Lateral friction Fy/Fz",group:"friction",unit:"-"},{id:"use",symbol:"use",name:"Friction ellipse used",group:"friction",unit:"-"},{id:"FyRel",symbol:"Fy/Fy,peak",name:"Lateral force over its peak at this load",group:"friction",unit:"-"},{id:"FxRel",symbol:"Fx/Fx,peak",name:"Driving force over its peak at this load",group:"friction",unit:"-"},{id:"dFyda",symbol:"\u2202Fy/\u2202\u03B1",name:"Cornering stiffness at the point",group:"stiffness",unit:"N/rad"},{id:"dFxdk",symbol:"\u2202Fx/\u2202\u03BA",name:"Slip stiffness at the point",group:"stiffness",unit:"N"},{id:"dFydg",symbol:"\u2202Fy/\u2202\u03B3",name:"Camber stiffness at the point",group:"stiffness",unit:"N/rad"},{id:"kz",symbol:"kz",name:"Vertical stiffness",group:"stiffness",unit:"N/mm",quantity:"springRate"},{id:"FxPeak",symbol:"Fx,peak",name:"Peak driving force",group:"characteristics",unit:"N",quantity:"force",characteristic:!0},{id:"FyPeak",symbol:"Fy,peak",name:"Peak lateral force",group:"characteristics",unit:"N",quantity:"force",characteristic:!0},{id:"muXPeak",symbol:"\u03BCx,peak",name:"Peak longitudinal friction",group:"characteristics",unit:"-",characteristic:!0},{id:"muYPeak",symbol:"\u03BCy,peak",name:"Peak lateral friction",group:"characteristics",unit:"-",characteristic:!0},{id:"kappaPeak",symbol:"\u03BA at peak",name:"Slip ratio at peak driving force",group:"characteristics",unit:"-",characteristic:!0},{id:"alphaPeak",symbol:"\u03B1 at peak",name:"Slip angle at peak lateral force",group:"characteristics",unit:"rad",characteristic:!0},{id:"Calpha",symbol:"C\u03B1",name:"Cornering stiffness at zero slip",group:"characteristics",unit:"N/rad",characteristic:!0},{id:"bestCamber",symbol:"\u03B3 best",name:"Camber for the most side force",group:"characteristics",unit:"rad",characteristic:!0},{id:"R0",symbol:"R0",name:"Free radius",group:"geometry",unit:"m",quantity:"length",characteristic:!0},{id:"Rl",symbol:"Rl",name:"Loaded radius",group:"geometry",unit:"m",quantity:"length",characteristic:!0},{id:"Re",symbol:"Re",name:"Effective rolling radius",group:"geometry",unit:"m",quantity:"length",characteristic:!0},{id:"width",symbol:"w",name:"Section width",group:"geometry",unit:"m",quantity:"length",characteristic:!0},{id:"sigmaA",symbol:"\u03C3\u03B1",name:"Lateral relaxation length",group:"transient",unit:"m",quantity:"length",characteristic:!0},{id:"Fr",symbol:"Fr",name:"Rolling-resistance force My/Re",group:"power",unit:"N",quantity:"force"},{id:"cr",symbol:"cr",name:"Rolling-resistance coefficient Fr/Fz",group:"power",unit:"-"},{id:"Pslip",symbol:"P slip",name:"Slip power |Fx\xB7Vsx| + |Fy\xB7Vsy|",group:"power",unit:"W"},{id:"Proll",symbol:"P roll",name:"Rolling power My\xB7\u03A9",group:"power",unit:"W"}],Y6=new Map(tu.map(e=>[e.id,e]));var W6=.01*yD;var We=Math.PI/180;var l1=new Set(tu.filter(e=>e.group!=="inputs"&&(e.unit==="N"||e.unit==="N\xB7m"||e.unit==="N/rad")).map(e=>e.id)),u1={alpha:{from:-15*We,to:15*We,n:61},kappa:{from:-.25,to:.25,n:61},gamma:{from:-6*We,to:6*We,n:49},Fz:{from:200,to:3e3,n:40,follow:!0},p:{from:5e4,to:15e4,n:21},V:{from:0,to:40,n:41,follow:!0}},lh={alpha:{from:0,to:12*We,n:7},kappa:{from:-.2,to:.2,n:9},gamma:{from:-4*We,to:4*We,n:5},Fz:{from:400,to:1600,n:5},p:{from:6e4,to:12e4,n:4},V:{from:5,to:35,n:4}};var uh={alpha:{from:0,to:12*We,n:25},kappa:{from:-.2,to:.2,n:25},gamma:{from:-4*We,to:4*We,n:17},Fz:{from:300,to:1800,n:16},p:{from:6e4,to:12e4,n:13},V:{from:5,to:35,n:13}};var ke=(e,t,r,n={},o={})=>({id:e,form:"curves",sweep:[{input:t,...u1[t],...o}],x:t,y:r,...n}),ru=(e,[t,r],n,o,a={})=>({id:e,form:"carpet",sweep:[{input:t,...lh[t]},{input:r,...lh[r]}],x:n,y:[o],...a}),Ir=(e,t)=>({id:e,fixed:t}),Gt={input:"Fz",values:"car"},ch={alpha:0,kappa:0},Rt={kappa:0},i1={alpha:0},RD={input:"Fz",values:[500,1e3,1500]},vD=[{id:"overview",name:"Overview",cards:[Ir("tyre","tyre"),ke("fy","alpha",["Fy"],{title:"Lateral force",hold:Rt}),ke("mz","alpha",["Mz"],{title:"Aligning moment",hold:Rt}),ke("fx","kappa",["Fx"],{title:"Longitudinal force",hold:i1}),ru("combined-carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Ir("ellipse","ellipse")]},{id:"lateral",name:"Lateral",cards:[ke("fy-load","alpha",["Fy"],{title:"Lateral force per wheel load",series:Gt,hold:Rt}),ke("muy-load","alpha",["muY"],{title:"Lateral force per unit load",series:Gt,hold:Rt}),ke("fy-peak","alpha",["Fy"],{title:"Lateral force over its peak",series:Gt,hold:Rt,scale:{per:"peak"}},{from:0,to:15*We,n:61}),ke("muy-peak","Fz",["muYPeak"],{title:"Peak lateral \u03BC over load"}),ke("calpha","Fz",["Calpha"],{title:"Cornering stiffness over load"}),ke("alpha-peak","Fz",["alphaPeak"],{title:"Slip angle at the peak over load"})]},{id:"aligning",name:"Aligning",cards:[ke("mz-load","alpha",["Mz"],{title:"Aligning moment per wheel load",series:Gt,hold:Rt}),ke("trail","alpha",["t"],{title:"Pneumatic trail",series:Gt,hold:Rt},{from:0,to:12*We,n:49}),ke("mzr","alpha",["Mzr"],{title:"Residual aligning moment",series:Gt,hold:Rt},{from:0,to:12*We,n:49}),ru("gough",["alpha","Fz"],"Fy","Mz",{title:"Gough plot",hold:Rt}),ke("steering-feel","alpha",["t"],{title:"Steering feel",x:"FyRel",series:Gt,hold:Rt},{from:0,to:12*We,n:49})]},{id:"longitudinal",name:"Longitudinal",cards:[ke("fx-load","kappa",["Fx"],{title:"Longitudinal force per wheel load",series:Gt,hold:i1}),ke("mux-peak","Fz",["muXPeak"],{title:"Peak longitudinal \u03BC over load"}),ke("kx","Fz",["dFxdk"],{title:"Slip stiffness at zero slip over load",hold:ch}),ke("kappa-peak","Fz",["kappaPeak"],{title:"Slip ratio at the peak over load"})]},{id:"combined",name:"Combined",cards:[ru("carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),ru("envelope-load",["kappa","alpha"],"Fy","Fx",{title:"Friction envelope per load",scale:{per:"Fz"},facet:RD}),ke("fy-kappa","kappa",["Fy"],{title:"Side force while driving or braking",series:{input:"alpha",values:[2*We,4*We,8*We]}}),ke("fx-kappa","kappa",["Fx"],{title:"Driving force while cornering",series:{input:"alpha",values:[0,4*We,8*We]}}),Ir("ellipse","ellipse")]},{id:"camber",name:"Camber",cards:[ke("fy-gamma","alpha",["Fy"],{title:"Lateral force per inclination",series:{input:"gamma",values:[-4,-2,0,2,4].map(e=>e*We)},hold:Rt}),ke("camber-sweep","gamma",["FyPeak","Fy"],{title:"Peak, and camber thrust at zero slip",hold:{alpha:0}}),{id:"camber-map",title:"Camber map",form:"map",sweep:[{input:"gamma",...uh.gamma},{input:"Fz",...uh.Fz,follow:!0}],x:"gamma",y:["Fz"],z:"muYPeak"},ke("camber-stiffness","alpha",["dFydg"],{title:"Camber stiffness at the point",series:Gt,hold:Rt}),ke("mx","alpha",["Mx"],{title:"Overturning moment",series:Gt,hold:Rt})]},{id:"rolling",name:"Rolling and radius",cards:[ke("my","V",["My"],{title:"Rolling-resistance moment",series:Gt,hold:ch}),ke("radius","Fz",["R0","Rl","Re"],{title:"Radius over load"},{from:0}),ke("p-roll","V",["Proll"],{title:"Rolling power",series:Gt,hold:ch})]},{id:"transient",name:"Transient",cards:[ke("sigma","Fz",["sigmaA"],{title:"Relaxation length over load"})]},{id:"tyres",name:"Side by side",cards:[{id:"trade-off",title:"Grip against cornering stiffness",form:"points",sweep:[],x:"Calpha",y:["muYPeak"]},{id:"pressure-family",title:"Peak \u03BCy over pressure, by family",form:"points",sweep:[],x:"p",y:["muYPeak"],family:!0},ke("delta-fy","alpha",["Fy"],{title:"Lateral force, minus the reference",hold:Rt,scale:{delta:!0}}),ke("delta-mu","Fz",["muYPeak"],{title:"Peak lateral \u03BC over load, minus the reference",scale:{delta:!0}}),ke("delta-calpha","Fz",["Calpha"],{title:"Cornering stiffness over load, minus the reference",scale:{delta:!0}})]},{id:"car",name:"Car",cards:[Ir("operating","operating"),Ir("wheels","wheels")]},{id:"fit",name:"Fit check",cards:[Ir("fitLateral","fitLateral"),Ir("fitLongitudinal","fitLongitudinal"),Ir("fitCoupling","fitCoupling"),Ir("fitEnvelope","fitEnvelope")]}];var CD=5670374e-14,mh=273.15,d1=.95,f1=60,nu=10,TD=.55,Tt=25,ph=-20,dh=50,Zs={tempC:[20,100,200,550,650,750],factor:[.8,.92,1,1,.85,.65]},Js={discMassKg:.5,discOuterMm:220,specificHeatJPerKgK:460,emissivity:.6,coolingWPerM2K:200,padCurve:{tempC:[...Zs.tempC],factor:[...Zs.factor]}},ou={...Js,discMassKg:.4,discOuterMm:200,padCurve:{tempC:[...Zs.tempC],factor:[...Zs.factor]}};function fh(e,t){let r=t==="front"?Js:ou,n=Math.round(2*e.effRadiusMm+40);return{...r,discOuterMm:n,discMassKg:Math.round(100*r.discMassKg*(n/r.discOuterMm)**2)/100,padCurve:{tempC:[...r.padCurve.tempC],factor:[...r.padCurve.factor]}}}var PD=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},Qs=(e,t,r,n)=>Math.min(r,Math.max(t,PD(e,n)));function LD(e,t){let r=e,n=Array.isArray(r?.tempC)?r.tempC:[],o=Array.isArray(r?.factor)?r.factor:[],a=[];for(let i=0;i<Math.min(n.length,o.length);i++){let c=Number(n[i]),l=Number(o[i]);Number.isFinite(c)&&Number.isFinite(l)&&a.push([Math.min(1500,Math.max(-50,c)),Math.min(2,Math.max(.05,l))])}a.sort((i,c)=>i[0]-c[0]);let s=a.filter((i,c)=>c===0||i[0]>a[c-1][0]);return s.length?{tempC:s.map(i=>i[0]),factor:s.map(i=>i[1])}:{tempC:[...t.tempC],factor:[...t.factor]}}function hh(e,t){return{discMassKg:Qs(e?.discMassKg,.05,20,t.discMassKg),discOuterMm:Qs(e?.discOuterMm,50,600,t.discOuterMm),specificHeatJPerKgK:Qs(e?.specificHeatJPerKgK,100,3e3,t.specificHeatJPerKgK),emissivity:Qs(e?.emissivity,.02,1,t.emissivity),coolingWPerM2K:Qs(e?.coolingWPerM2K,nu,5e3,t.coolingWPerM2K),padCurve:LD(e?.padCurve,t.padCurve)}}function au(e,t){let r=e.tempC,n=e.factor,o=Math.min(r.length,n.length);if(o===0)return 1;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=1;for(;a<o-1&&r[a]<t;)a++;return n[a-1]+(t-r[a-1])/(r[a]-r[a-1])*(n[a]-n[a-1])}function bh(e,t=1){let r=e.discMassKg*e.specificHeatJPerKgK,n=e.discOuterMm*.001/2,o=2*Math.PI*n*n,a=f1/3.6,s=e.emissivity*CD*o,i=m=>nu+(e.coolingWPerM2K-nu)*Math.pow(Math.max(0,m)*t/a,TD),c=(m,d,p)=>{let f=m+mh,h=p+mh;return i(d)*o*(m-p)+s*(f**4-h**4)},l=(m,d)=>i(d)*o+4*s*Math.max(0,m+mh)**3,u=(m,d)=>r/l(d,m);return{heatCapacityJPerK:r,areaM2:o,convectionAt:i,coolingW:c,timeConstantS:u,step(m,d,p,f,h){if(!(f>0))return m+d/r;let b=u(p,m+Math.max(0,d)/r),g=Math.max(1,Math.ceil(f/(.25*b))),y=f/g,R=d/g;for(let k=0;k<g;k++)m+=(R-c(m,p,h)*y)/r;return m},padFactor:m=>au(e.padCurve,m),window:h1(e.padCurve)}}function su(e,t,r,n,o,a,s=Tt){let i=n.length,c=new Array(i),l=new Array(i),u=new Array(i),m=d1/Math.max(1,t),d=a,p=d,f=0,h=0,b=0;for(let g=0;g<i;g++){let y=Math.max(0,r[g]??0);c[g]=d,l[g]=y*n[g],u[g]=e.padFactor(d);let R=y*(o[g]??0);f+=R,d<e.window.fromC?h+=R:d>e.window.toC&&(b+=R);let k=g+1<i?n[g+1]:n[g],v=.5*(n[g]+k),x=v>0?(o[g]??0)/v:0;d=e.step(d,m*R,v,x,s),d>p&&(p=d)}return{tempC:c,heatW:l,padFactor:u,startC:a,endC:d,maxC:p,workJ:f,coldWorkJ:h,hotWorkJ:b}}function h1(e){let t=e.tempC,r=Math.min(t.length,e.factor.length);if(r===0)return{fromC:-1/0,toC:1/0};let n=Math.max(...e.factor.slice(0,r)),o=null;for(let c=0;c<r;c++){if(e.factor[c]<n-1e-9)continue;let l=c;for(;l+1<r&&e.factor[l+1]>=n-1e-9;)l++;l>c&&(!o||t[l]-t[c]>o.toC-o.fromC)&&(o={fromC:t[c],toC:t[l]}),c=l}if(o)return o;let a=NaN,s=NaN,i=NaN;for(let c=Math.floor(t[0]);c<=Math.ceil(t[r-1])+1;c++){let l=c<=Math.ceil(t[r-1])&&au(e,c)>=.98*n;l&&Number.isNaN(i)&&(i=c),!l&&!Number.isNaN(i)&&((Number.isNaN(a)||c-1-i>s-a)&&(a=i,s=c-1),i=NaN)}return{fromC:a,toC:s}}var gh=1e5,x1=.001,Un={pedalRatio:4,pedalForceMaxN:0,barFront:.5,masterFrontMm:15.875,masterRearMm:15.875,valve:"none",valveKneeBar:20,valveSlope:.3,front:{location:"outboard",discs:2,pistonsPerSide:2,pistonDiaMm:25.4,padMu:.45,effRadiusMm:90,ratio:1},rear:{location:"outboard",discs:2,pistonsPerSide:1,pistonDiaMm:25.4,padMu:.45,effRadiusMm:80,ratio:1},adjusterPitchMm:1,barLengthMm:0},xh={fullAtBar:10,maxPowerKw:0,fadeBelowKmh:0,distribution:"equal"};var Rh=v1(cu(Un,"Formula Student brakes")),vh=40,R1={ideal:!1,barFront:Un.barFront,pedalForceMaxN:0,testSpeedKmh:vh,regen:xh};function b1(e){let{heat:t,...r}=e;return t?{...r,heat:{...t,padCurve:{tempC:[...t.padCurve.tempC],factor:[...t.padCurve.factor]}}}:r}function v1(e){let t=(r,n)=>r.heat?r:{...r,heat:fh(r,n)};return{...e,front:t(e.front,"front"),rear:t(e.rear,"rear")}}function cu(e,t){return{name:t,pedalRatio:e.pedalRatio,masterFrontMm:e.masterFrontMm,masterRearMm:e.masterRearMm,valve:e.valve,valveKneeBar:e.valveKneeBar,valveSlope:e.valveSlope,front:b1(e.front),rear:b1(e.rear),adjusterPitchMm:e.adjusterPitchMm,barLengthMm:e.barLengthMm}}function kh(e,t){return k1({...e,barFront:t.barFront,pedalForceMaxN:t.pedalForceMaxN})}function Mh(e,t){let r=Nr(t),n=e?ur(e):void 0;return{mode:r.ideal?"tyre":n?"hydraulic":"balance",hydraulic:n?kh(n,r):Un,regen:r.regen}}var DD=["none","proportioning","limiter"],iu=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},Je=(e,t,r,n)=>Math.min(r,Math.max(t,iu(e,n))),ED=(e,t)=>{let r=iu(e,t);return r>0?r:t};function g1(e,t,r){let n=e?.location==="inboard"?"inboard":e?.location==="outboard"?"outboard":t.location;return{location:n,discs:Math.max(1,Math.min(4,Math.round(iu(e?.discs,n==="inboard"?1:t.discs)))),pistonsPerSide:Math.max(1,Math.min(6,Math.round(iu(e?.pistonsPerSide,t.pistonsPerSide)))),pistonDiaMm:Je(e?.pistonDiaMm,5,80,t.pistonDiaMm),padMu:Je(e?.padMu,.05,1.5,t.padMu),effRadiusMm:Je(e?.effRadiusMm,20,300,t.effRadiusMm),ratio:n==="inboard"?Je(e?.ratio,1,20,t.ratio):1,...e?.heat&&typeof e.heat=="object"?{heat:hh(e.heat,t.heat??r)}:{}}}function k1(e){let t=Un;return{pedalRatio:Je(e?.pedalRatio,.5,15,t.pedalRatio),pedalForceMaxN:Je(e?.pedalForceMaxN,0,5e3,t.pedalForceMaxN),barFront:Je(e?.barFront,.05,.95,t.barFront),masterFrontMm:Je(e?.masterFrontMm,8,40,t.masterFrontMm),masterRearMm:Je(e?.masterRearMm,8,40,t.masterRearMm),valve:DD.includes(e?.valve)?e?.valve:t.valve,valveKneeBar:Je(e?.valveKneeBar,0,200,t.valveKneeBar),valveSlope:Je(e?.valveSlope,0,1,t.valveSlope),front:g1(e?.front,t.front,Js),rear:g1(e?.rear,t.rear,ou),adjusterPitchMm:ED(e?.adjusterPitchMm,t.adjusterPitchMm),barLengthMm:Je(e?.barLengthMm,0,500,t.barLengthMm)}}function ID(e){let t=xh;return{fullAtBar:Je(e?.fullAtBar,0,200,t.fullAtBar),maxPowerKw:Je(e?.maxPowerKw,0,1e3,t.maxPowerKw),fadeBelowKmh:Je(e?.fadeBelowKmh,0,100,t.fadeBelowKmh),distribution:e?.distribution==="wheel"?"wheel":"equal"}}function ur(e){let t=k1(e??void 0),r=typeof e?.name=="string"&&e.name.trim()?e.name:_D;return cu(t,r)}function Nr(e){return{ideal:e?.ideal===!0,barFront:Je(e?.barFront,.05,.95,Un.barFront),pedalForceMaxN:Je(e?.pedalForceMaxN,0,5e3,0),testSpeedKmh:Je(e?.testSpeedKmh,5,150,vh),regen:ID(e?.regen)}}var _D="Formula Student brakes";var yh=e=>Math.PI/4*(e*x1)**2;function hn(e,t){let r=e.pistonsPerSide*yh(e.pistonDiaMm)*gh;return e.discs*2*e.padMu*r*e.effRadiusMm*x1*e.ratio/Math.max(.05,t)}function M1(e,t){if(e.valve==="none"||t<=e.valveKneeBar)return t;let r=e.valve==="limiter"?0:e.valveSlope;return e.valveKneeBar+r*(t-e.valveKneeBar)}function ei(e,t){let r=Math.max(0,t)*e.pedalRatio,n=e.barFront*r/yh(e.masterFrontMm)/gh,o=(1-e.barFront)*r/yh(e.masterRearMm)/gh;return{front:n,rearIn:o,rear:M1(e,o)}}function ND(e,t){let r=ei(e,1);return{front:hn(e.front,t)*r.front,rear:hn(e.rear,t)*r.rearIn}}function ti(e,t){let r=ND(e,t);return r.front/Math.max(1e-12,r.front+r.rear)}function ri(e,t){let r=[],n=[],o=[],a=e.vVehicle.length,s=Math.max(1,Math.floor(a/60));for(let c=0;c<a;c+=s)i(c);return(a-1)%s!==0&&i(a-1),{v:r,front:n,rear:o};function i(c){let l=e.vVehicle[c],u=S1(t,l),m=t.maxPowerKw>0&&l>0?t.maxPowerKw*1e3/l:1/0,d=Math.max(0,e.fFront[c]),p=Math.max(0,e.fRear[c]),f=d+p>0?Math.min(1,m/(d+p)):1;r.push(l),n.push(d*f*u),o.push(p*f*u)}}function S1(e,t){let r=e.fadeBelowKmh/3.6;return r>0?Math.max(0,Math.min(1,t/r)):1}function _r(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]||1);return t[o]+s*(t[a]-t[o])}var y1=new WeakMap;function Xn(e){let t=y1.get(e);return t||(t=e.mode==="hydraulic"&&e.hydraulic?VD(e,e.hydraulic):OD(e),y1.set(e,t)),t}function OD(e){let t=Math.min(.99,Math.max(.01,e.balanceFront));return{mode:e.mode,equalLeftRight:e.mode!=="tyre",uMax:1/0,shares:{front:t,rear:1-t},demand:r=>({front:t*r,rear:(1-t)*r,regenFront:0,regenRear:0,pFront:0,pRear:0,pedalN:0}),controlFor:r=>Math.max(0,r)}}function VD(e,t){let r=hn(t.front,e.tyreRadiusM),n=hn(t.rear,e.tyreRadiusM),o=e.regen,a=(c,l)=>{let u=ei(t,c),m=0,d=0;if(o&&u.front>0){let p=o.fullAtBar>0?Math.min(1,u.front/o.fullAtBar):1;m=p*_r(o.v,o.front,l),d=p*_r(o.v,o.rear,l)}return{front:r*u.front+m,rear:n*u.rear+d,regenFront:m,regenRear:d,pFront:u.front,pRear:u.rear,pedalN:c}},s=t.pedalForceMaxN>0?t.pedalForceMaxN:1/0,i=(c,l)=>{let u=a(c,l);return u.front+u.rear};return{mode:"hydraulic",equalLeftRight:!0,uMax:s,demand:a,controlFor:(c,l)=>{if(!(c>0))return 0;let u=100;for(;i(u,l)<c&&u<1e6;)u*=2;if(u=Math.min(u,s),i(u,l)<=c)return u;let m=0;for(let d=0;d<60;d++){let p=.5*(m+u);i(p,l)<c?m=p:u=p}return u}}}function Sh(e,t,r){let n=t>0?e.controlFor(t,r):0,o=e.demand(n>0?n:1,r),a=o.front+o.rear;return a>0?o.front/a:.5}var lu=Es,BD=.1,qn=(e,t)=>e.a*Math.sqrt(Math.max(0,1-(t/Math.max(1e-9,e.b))**2));function uu(e,t,r){if(!(r>t))return t;let n=(Math.sqrt(5)-1)/2,o=t,a=r,s=a-n*(a-o),i=o+n*(a-o),c=e(s),l=e(i);for(let d=0;d<48;d++)c<l?(o=s,s=i,c=l,i=o+n*(a-o),l=e(i)):(a=i,i=s,l=c,s=a-n*(a-o),c=e(s));let u=.5*(o+a),m=e(u);for(let d of[t,r]){let p=e(d);p>m&&(u=d,m=p)}return u}function wh(e,t,r){let n=Math.max(0,r-lu*t.b),o=Math.min(r,lu*e.b);if(!(n<=o))return;let a=(c,l)=>c.a*c.a*Math.max(0,1-(l/Math.max(1e-9,c.b))**2),s=c=>a(e,c)-a(t,r-c),i;if(s(n)<=0)i=n;else if(s(o)>=0)i=o;else{let c=n,l=o;for(let u=0;u<40;u++){let m=.5*(c+l);s(m)>0?c=m:l=m}i=.5*(c+l)}return{lo:n,hi:o,y1:i,c1:e.cap(i),c2:t.cap(r-i)}}function Ch(e,t,r,n,o=0){let a=Math.max(0,r),s=wh(e,t,a),i=s?s.c1:0,c=s?s.c2:0,l=s?Math.min(i,c):0,[u,m]=e.a<=t.a?[e,t]:[t,e],d=u.Fz/Math.max(1e-9,u.Fz+m.Fz),p=Math.max(0,Math.min(1,1-d/BD)),f=p>0&&a<lu*m.b?m.cap(a):0,h=f>l?l+p*(f-l):0,b=Math.max(0,Math.min(u.slide,u.a)),g={xNoLock:l,xLock:h,slide:b,ceiling:Math.max(0,n)},y=Math.max(0,o);if(!(y>0)||!s)return{...g,regenWheel:s?y:0,mixedMax:2*l,regenRoom:T=>2*Math.max(0,l-T)};let{lo:R,hi:k}=s,v=uu(T=>{let F=qn(e,T),S=qn(t,a-T);return Math.min(F+S,2*Math.min(F,S)+y)},R,k),x=e.cap(v),M=t.cap(a-v),A=Math.max(2*l,Math.min(x+M,2*Math.min(x,M)+y)),w=(T,F,S)=>Math.min(y,Math.max(0,T-S))+Math.min(y,Math.max(0,F-S));return{...g,regenWheel:y,mixedMax:A,regenRoom:T=>{let F=w(i,c,T);if(!(a>0))return F;let S=I=>lu*I.b*Math.sqrt(Math.max(0,1-(T/Math.max(1e-9,I.a))**2)),P=Math.max(R,a-S(t)),L=Math.min(k,S(e));if(!(P<=L))return F;let D=uu(I=>Math.min(y,qn(e,I)-T)+Math.min(y,qn(t,a-I)-T),P,L);return Math.max(F,w(e.cap(D),t.cap(a-D),T))}}}var Ah=e=>Math.max(e.xNoLock,e.xLock),Fh=e=>Math.max(e.mixedMax,2*e.xLock);function ba(e,t,r=0){let n=1e-9*Math.max(1,t),o=Math.max(0,r);if(t<=e.xNoLock+n)return Math.min(2*t+(o>0?Math.min(o,e.regenRoom(t)):0),e.ceiling);if(t<=e.xLock+n){let a=o>0?Math.min(e.regenWheel>0?Math.min(o,e.regenWheel):o/2,Math.max(0,e.xLock-t)):0;return Math.min(t+e.slide+a,e.ceiling)}return NaN}function ga(e,t){let r=t/2,n=1e-9*Math.max(1,r);return r<=e.mixedMax/2+n?Math.min(t,e.ceiling):r<=e.xLock+n?Math.min(r+e.slide,e.ceiling):NaN}function ni(e,t,r,n){return e.shares?$D(e,e.shares,t,r,n):GD(e,t,r,n)}function A1(e,t){let r=e[0],n=t(r.u);for(let o of e.slice(1)){let a=t(o.u);a>n&&(r=o,n=a)}return{cand:r,force:n}}function $D(e,t,r,n,o){let a=Fh(r),s=Fh(n),i=Math.min(t.front>0?a/t.front:1/0,t.rear>0?s/t.rear:1/0,e.uMax),c=Number.isFinite(e.uMax)&&i>=e.uMax,l=b=>{let g=ga(r,t.front*b),y=ga(n,t.rear*b);return Number.isFinite(g)&&Number.isFinite(y)?g+y:-1/0},u=a>0?t.front*i/a:1/0,m=s>0?t.rear*i/s:1/0,d=[{u:i,by:c?"pedal":u>=m?"front":"rear"}];if(r.xLock>r.xNoLock){let b=t.front>0?r.mixedMax/t.front:1/0;b<i&&d.push({u:b,by:"front"})}if(n.xLock>n.xNoLock){let b=t.rear>0?n.mixedMax/t.rear:1/0;b<i&&d.push({u:b,by:"rear"})}let{cand:p,force:f}=A1(d,l),h=e.demand(p.u,o);return{force:Math.max(0,Number.isFinite(f)?f:0),control:p.u,demand:h,limitedBy:p.by,lockFront:h.front/2>r.mixedMax/2*(1+1e-9),lockRear:h.rear/2>n.mixedMax/2*(1+1e-9)}}function GD(e,t,r,n){let o=Ah(t),a=Ah(r),s=v=>(v.front-v.regenFront)/2,i=v=>(v.rear-v.regenRear)/2,c=v=>{let x=e.demand(v,n);return s(x)<=o*(1+1e-12)&&i(x)<=a*(1+1e-12)},l=(v,x)=>{if(v(e.demand(x,n)))return x;let M=0,A=x;for(let w=0;w<60;w++){let C=.5*(M+A);v(e.demand(C,n))?M=C:A=C}return M},u=Number.isFinite(e.uMax)?e.uMax:100;if(!Number.isFinite(e.uMax))for(;c(u)&&u<1e7;)u*=2;let m=c(u)?u:l(v=>s(v)<=o&&i(v)<=a,u),d=Number.isFinite(e.uMax)&&m>=e.uMax,p=v=>{let x=e.demand(v,n),M=ba(t,s(x),x.regenFront),A=ba(r,i(x),x.regenRear);return Number.isFinite(M)&&Number.isFinite(A)?M+A:-1/0},f=e.demand(m,n),h=o>0?s(f)/o:1/0,b=a>0?i(f)/a:1/0,g=[{u:m,by:d?"pedal":h>=b?"front":"rear"}];if(t.xLock>t.xNoLock){let v=l(x=>s(x)<=t.xNoLock,m);v<m&&g.push({u:v,by:"front"})}if(r.xLock>r.xNoLock){let v=l(x=>i(x)<=r.xNoLock,m);v<m&&g.push({u:v,by:"rear"})}let{cand:y,force:R}=A1(g,p),k=e.demand(y.u,n);return{force:Math.max(0,Number.isFinite(R)?R:0),control:y.u,demand:k,limitedBy:y.by,lockFront:s(k)>t.xNoLock*(1+1e-9),lockRear:i(k)>r.xNoLock*(1+1e-9)}}var Or={regen:!0,regenEfficiency:.6};function Vr(e,t){let r=e.energy??t??Or;return{regen:r.regen===!0,regenEfficiency:Math.min(1,Math.max(0,Number.isFinite(r.regenEfficiency)?r.regenEfficiency:0))}}function Br(e,t,r){let n=Math.max(0,Math.floor(r));if(n===0)return[];if(n===1)return[e];let o=new Array(n),a=(t-e)/(n-1);for(let s=0;s<n;s++)o[s]=e+a*s;return o[n-1]=t,o}function F1(e,t,r){let n=[],o=Math.floor((r-e)/t+1e-9);for(let a=0;a<=o;a++)n.push(e+t*a);return n}function dt(e,t,r){let n=e.length;if(r<e[0]||r>e[n-1])return NaN;if(r===e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function mu(e,t,r){let n=e.length;if(!(r>=e[0]&&r<=e[n-1]))return NaN;if(n<3)return n===1?t[0]:t[0]+(r-e[0])/(e[1]-e[0])*(t[1]-t[0]);let o=0,a=n-1;for(;a-o>1;){let f=o+a>>1;e[f]<=r?o=f:a=f}if(o===n-1)return t[n-1];let s=f=>e[f+1]-e[f],i=f=>(t[f+1]-t[f])/s(f),c=f=>{if(f===0||f===n-1){let[y,R]=f===0?[0,1]:[n-2,n-3],k=i(y)*(1+s(y)/(s(y)+s(R)))-i(R)*(s(y)/(s(y)+s(R)));return k*i(y)<=0?0:Math.abs(k)>2*Math.abs(i(y))?2*i(y):k}let h=i(f-1),b=i(f),g=(h*s(f)+b*s(f-1))/(s(f-1)+s(f));return(Math.sign(h)+Math.sign(b))*Math.min(Math.abs(h),Math.abs(b),.5*Math.abs(g))},l=s(o),u=i(o),m=c(o),d=c(o+1),p=r-e[o];return t[o]+p*(m+p*((3*u-2*m-d)/l+p*(m+d-2*u)/(l*l)))}function oi(e,t,r){return r.map(n=>dt(e,t,n))}var ai=e=>e.reduce((t,r)=>r>t?r:t,-1/0),ya=e=>e.reduce((t,r)=>r<t?r:t,1/0);var KD=[-.906179845938664,-.538469310105683,0,.538469310105683,.906179845938664],HD=[.236926885056189,.478628670499366,.568888888888889,.478628670499366,.236926885056189];function Th(e,t,r){let n=.5*(r-t),o=.5*(t+r),a=0;for(let s=0;s<5;s++)a+=HD[s]*e(n*KD[s]+o);return n*a}var zD=Math.PI*2,YD=.5/3.6;function si(e,t){let r=Math.max(0,Math.round(e));if(t==="front")return{front:r,rear:0};if(t==="rear")return{front:0,rear:r};let n=Math.floor(r/2);return{front:n,rear:r-n}}function Ph(e,t,r,n,o){let a=e.rpm,s=e.torque,i=a.length,c=new Array(i),l=new Array(i);for(let g=0;g<i;g++){let y=a[g]/60*zD;c[g]=y*o/n,l[g]=s[g]*n/o}let u=ai(c),m=Br(ya(c),u,u/YD),d=oi(c,l,m),{front:p,rear:f}=si(t,r),h=d.map(g=>g*p),b=d.map(g=>g*f);return{vVehicle:m,fFront:h,fRear:b,vMax:u}}var w1=60/(2*Math.PI),C1=.1,T1=.08,P1=0;function Lh(e){let t=(r,n)=>r===void 0||!Number.isFinite(r)?n:Math.max(0,r);return{up:t(e.upshiftTime,C1),down:t(e.downshiftTime,T1)}}function Dh(e){let t=e.driveKept;return t===void 0||!Number.isFinite(t)?P1:Math.max(0,Math.min(1,t))}function Eh(e,t,r){let{primary:n,ratios:o,efficiency:a}=e.gearbox,s=t>0&&r>0&&n>0,i=(b,g)=>b/w1*r/g,c=s?o.filter(b=>b>0).map(b=>{let g=n*b*t;return{ratio:g,vIdle:i(e.idleRpm,g),vLimit:i(e.limitRpm,g)}}):[],l=Math.max(0,Math.min(1,a)),u=Math.max(0,e.inertia),m=b=>b>e.limitRpm?0:Math.max(0,Ge(e.rpm,e.torque,b)),d=(b,g)=>{let y=c[g];return y?b*y.ratio/r*w1:0},p=(b,g)=>g===0&&c.length>0&&b<c[0].vIdle,f=(b,g)=>{let y=c[g];return y?p(b,g)?m(e.idleRpm)*y.ratio*l/r:b<y.vIdle||b>y.vLimit?0:m(d(b,g))*y.ratio*l/r:0},h=(b,g)=>{let y=c[g];return!y||p(b,g)?0:u*y.ratio*y.ratio/(r*r)};return{engine:e,gears:c,efficiency:l,rDyn:r,vMax:c.length?c[c.length-1].vLimit:0,rpm:d,torque:m,force:f,inertiaMass:h,slipping:p}}function xa(e,t,r,n=0,o=1){let a=-1,s=-1/0;for(let i=0;i<e.gears.length;i++){let c=(o*e.force(t,i)+n)/(r+e.inertiaMass(t,i));c>=s&&(s=c,a=i)}return{gear:a,accel:s}}function Ih(e,t){let r=0;for(let n=0;n<e.gears.length;n++)r=Math.max(r,e.force(t,n));return r}var L1=9.81,D1=Math.PI*2;function Pt(e){let t=e.motor.rpm,r=e.motor.torque,n=t.length,o=new Array(n),a=new Array(n),s=new Array(n),i=new Array(n),c=new Array(n),l=e.gear_ratio.value,u=e.r_dyn.value;for(let v=0;v<n;v++)o[v]=r[v]*t[v]*(D1/60),a[v]=t[v]/60*D1,s[v]=a[v]*u/l,i[v]=r[v]*l,c[v]=i[v]/u;let m=ai(s),d=m,p=.5/3.6,f=Br(ya(s),m,m/p),h=oi(s,c,f),b=Br(ya(t),ai(t),250),g=oi(t,o,b).map(v=>v*e.power_scale.value),y,R=d,k;if(e.motorModel?.kind==="ice"){k=Eh(e.motorModel,l,u);let v=Br(0,k.vMax,Math.max(2,Math.ceil(k.vMax/p)+1)),x=v.map(w=>Ih(k,w)),M=v.map(()=>0),A=e.motorPlacement==="front";y={vVehicle:v,fFront:A?x:M,fRear:A?M:x,vMax:k.vMax},R=k.vMax}else e.motorModel&&(y=Ph(e.motorModel,Math.max(1,Math.round(e.motorCount??e.driven_wheels.value)),e.motorPlacement??"rear",l,u),R=y.vMax);return{params:e,g:L1,FG:e.m.value*L1,vMax:R,vVehicle:f,fRad:h,uMotor:b,pMotor:g,vRad:s,fAxle:y,...k?{engine:k}:{}}}var bn=e=>e.motorModel?.kind==="ice"?si(1,e.motorPlacement==="front"?"front":"rear"):si(Math.max(1,Math.round(e.motorCount??e.driven_wheels?.value??2)),e.motorPlacement??"rear");function E1(e){let t=bn(e);return t.front>=2||t.rear>=2}function I1(e){return E1(e)?e.motorMount??"hub":"chassis"}function _h(e){if(!e.motorModel)return{front:!1,rear:!0};let t=bn(e);return{front:t.front>0,rear:t.rear>0}}function Nh(e){let t=bn(e),r=t.front>0,n=t.rear>0,o=e.front_mass_diss?.value??.5,a=Math.max(0,Math.min(1,o>1?o/100:o)),s=I1(e)==="chassis",i=c=>c===1||c>1&&s;return{front:r&&n?a:r?1:0,inboard:{front:i(t.front),rear:i(t.rear)}}}function ft(e){return Mh(e.brakeModel,e.brakeSetup)}function pu(e){return Nr(e.brakeSetup).ideal?"tyre":e.brakeModel||e.brakeModelId?"hydraulic":"balance"}function _1(e,t){if(!(bt(e.motorModel)||!Vr(e).regen))return ri(du(Pt(e)),t??ft(e).regen)}function du(e){return e.fAxle??{vVehicle:e.vVehicle,fFront:e.vVehicle.map(()=>0),fRear:e.fRad.map(t=>t*e.params.driven_wheels.value)}}function Oh(e,t=ft(e)){if(t.mode==="hydraulic")return ti(t.hydraulic,e.r_dyn.value);if(t.mode==="tyre"){let r=e.front_mass_diss.value>1?e.front_mass_diss.value/100:e.front_mass_diss.value;return Math.min(.95,Math.max(.05,r+Q(e,"cg_height")/Math.max(1,Q(e,"wheelbase"))))}return Q(e,"brake_balance")}function Vh(e,t=ft(e)){return{front:t.hydraulic.front.location==="inboard",rear:t.hydraulic.rear.location==="inboard"}}function Bh(e){let t=ft(e);return{brakeBalanceFront:Oh(e,t),brakeInboard:Vh(e,t)}}function N1(e,t=ft(e)){if(t.mode==="tyre"||t.regen.distribution!=="wheel"||bt(e.motorModel))return;let r=bn(e),n={front:r.front>=2,rear:r.rear>=2};return n.front||n.rear?n:void 0}function ii(e){let t=ft(e),r=e.r_dyn.value,n=Vh(e,t),o=Oh(e,t),a=N1(e,t),s=t.mode==="hydraulic"||a?_1(e,t.regen):void 0;return{mode:t.mode,balanceFront:o,...t.mode==="hydraulic"?{hydraulic:t.hydraulic}:{},tyreRadiusM:r,inboard:n,...s?{regen:{...s,fullAtBar:t.regen.fullAtBar}}:{},...s&&a?{regenPerWheel:a}:{}}}var jD=9.81;function $h(e,t){if(bt(e.motorModel))return()=>0;let r=ft(e),n=ri(t,r.regen);if(r.mode==="hydraulic"){let a=Xn({mode:"hydraulic",balanceFront:ti(r.hydraulic,e.r_dyn.value),hydraulic:r.hydraulic,tyreRadiusM:e.r_dyn.value,regen:{...n,fullAtBar:r.regen.fullAtBar}});return(s,i)=>{if(!(s>0))return 0;let c=a.demand(a.controlFor(s,i),i);return Math.min(s,c.regenFront+c.regenRear)}}let o=r.mode==="tyre"?UD(e):()=>Math.min(.99,Math.max(.01,Q(e,"brake_balance")));return(a,s,i)=>{if(!(a>0))return 0;let c=o(s,i);return Math.min(c*a,_r(n.v,n.front,s))+Math.min((1-c)*a,_r(n.v,n.rear,s))}}function UD(e){let t=e.m.value*jD,r=e.front_mass_diss.value>1?e.front_mass_diss.value/100:e.front_mass_diss.value,n=Q(e,"cg_height")/Math.max(1,Q(e,"wheelbase")),o=1-Math.max(0,Math.min(1,Q(e,"cop_long"))),a=.5*e.rho.value*e.c_l.value*e.A.value;return(s,i)=>{let c=Math.max(0,a*s*s),l=t*(r+Math.abs(i)*n)+c*o;return Math.min(.99,Math.max(.01,l/(t+c)))}}function O1(e){let t=e==="front"?"Front axle":"Rear axle";return{[`${e}.location`]:{section:t,label:"Disc location",control:"Mounting"},[`${e}.discs`]:{section:t,label:"Discs",control:"Mounting"},[`${e}.ratio`]:{section:t,label:"Reduction to the wheel",unit:": 1"},[`${e}.pistonsPerSide`]:{section:t,label:"Pistons a side"},[`${e}.pistonDiaMm`]:{section:t,label:"Piston bore",unit:"mm"},[`${e}.padMu`]:{section:t,label:"Pad friction \u03BC"},[`${e}.effRadiusMm`]:{section:t,label:"Effective radius",unit:"mm"},[`${e}.heat.discMassKg`]:{section:t,label:"Disc mass",unit:"kg"},[`${e}.heat.discOuterMm`]:{section:t,label:"Disc diameter",unit:"mm"},[`${e}.heat.specificHeatJPerKgK`]:{section:t,label:"Specific heat",unit:"J/(kg\xB7K)"},[`${e}.heat.emissivity`]:{section:t,label:"Emissivity"},[`${e}.heat.coolingWPerM2K`]:{section:t,label:"Cooling at 60 km/h",unit:"W/(m\xB2\xB7K)"},[`${e}.heat.padCurve.tempC`]:{section:t,label:"Pad curve temperature",unit:"\xB0C"},[`${e}.heat.padCurve.factor`]:{section:t,label:"Pad curve friction"}}}var Gh={pedalRatio:{section:"Pedal box & bar",label:"Pedal ratio",unit:": 1"},barLengthMm:{section:"Pedal box & bar",label:"Bar length, clevis to clevis",unit:"mm"},adjusterPitchMm:{section:"Pedal box & bar",label:"Adjuster pitch",unit:"mm/turn"},masterFrontMm:{section:"Master cylinders",label:"Front bore",unit:"mm"},masterRearMm:{section:"Master cylinders",label:"Rear bore",unit:"mm"},valve:{section:"Rear valve",label:"Valve"},valveKneeBar:{section:"Rear valve",label:"Knee",unit:"bar"},valveSlope:{section:"Rear valve",label:"Gain above the knee"},...O1("front"),...O1("rear")},Kh={ideal:{label:"Ideal brakes"},barFront:{label:"Balance bar"},pedalForceMaxN:{label:"Pedal force",unit:"N"},testSpeedKmh:{section:"Brake test",label:"Speed",unit:"km/h"},"regen.maxPowerKw":{section:"Regen",label:"Power ceiling",unit:"kW"},"regen.fadeBelowKmh":{section:"Regen",label:"Fades out below",unit:"km/h"},"regen.fullAtBar":{section:"Regen",label:"Full at",unit:"bar"},"regen.distribution":{section:"Regen",label:"Wheel by wheel"}};function Hh(e){let t=Gh[e];return`${t.label}, ${t.section}`.toLowerCase()}function zh(e){let t=Kh[e];return t.section?`${t.section} ${t.label.charAt(0).toLowerCase()}${t.label.slice(1)}`:t.label}var V1=new WeakMap;function mr(e){if(e.brakes)return e.brakes;let t=V1.get(e);if(!t){let r=Math.max(.05,(e.unsprungCgHeight||230)/1e3);t=e.brakeBalanceFront!=null?{mode:"balance",balanceFront:e.brakeBalanceFront,tyreRadiusM:r}:{mode:"tyre",balanceFront:e.frontMassFrac,tyreRadiusM:r},V1.set(e,t)}return t}var $r=e=>Xn(mr(e));var ZD=Math.PI/180,Ra=Object.freeze({tbr:1,preloadN:0}),fu=Object.freeze({tbr:1/0,preloadN:0}),Wh=e=>e.faces*e.muClutch*e.rFrictionMm/e.rRampMm;function jh(e,t){if(!(e>0)||Number.isNaN(t))return 0;let r=Math.tan(Math.min(90,t)*ZD);return r>0?Math.min(1,e/r):1}function $1(e){if(e>=1)return 1/0;let t=e>0?e:0;return(1+t)/(1-t)}function hu(e){return e===1/0?1:e>1?(e-1)/(e+1):0}function va(e,t){return e.tbr===1/0?1/0:(e.preloadN>0?e.preloadN:0)+hu(e.tbr)*Math.abs(t)}function li(e,t,r){let n=o=>o!==void 0&&o>0&&r>0?o/r:0;switch(e.kind){case"open":return Ra;case"spool":return fu;case"independent":return t==="hubs"?Ra:fu;case"clutch":{let o=n(e.preloadNm);return t==="hubs"?{tbr:1,preloadN:o}:{tbr:$1(jh(Wh(e),t==="drive"?e.rampDriveDeg:e.rampCoastDeg)),preloadN:o}}case"torsen":{let o=n(e.preloadNm);if(t==="hubs")return{tbr:1,preloadN:o};let a=t==="drive"?e.tbrDrive:e.tbrCoast;return{tbr:a>1?a:1,preloadN:o}}}}function ci(e,t,r){let n=Math.max(0,Math.min(e,t)),o=Math.max(0,Math.max(e,t)),a=r.tbr>1?r.tbr:1,s=r.preloadN>0?r.preloadN:0;return a===1/0||s===1/0?n+o:n+Math.min(o,a*n+s*(1+a)/2)}var B1=4;function Yh(e,t){let r=0;for(let a of e)r=Math.max(r,ci(a.m1,a.m2,t));let n=t.tbr>1?t.tbr:1,o=(t.preloadN>0?t.preloadN:0)*(1+n)/2;if(n===1/0||o===1/0)return r;for(let a=0;a+1<e.length;a++){let s=e[a],i=e[a+1].m1-s.m1,c=e[a+1].m2-s.m2,l=d=>{d>0&&d<1&&(r=Math.max(r,ci(s.m1+d*i,s.m2+d*c,t)))};i!==c&&l((s.m2-s.m1)/(i-c));let u=i+c-(1+n)*i,m=i+c-(1+n)*c;u!==0&&l(((1+n)*s.m1+o-s.m1-s.m2)/u),m!==0&&l(((1+n)*s.m2+o-s.m1-s.m2)/m)}return r}function ui(e,t,r,n,o){let a=Math.max(0,o),s=n.tbr>1?n.tbr:1,i=n.preloadN>0?n.preloadN:0;if(s===1/0||i===1/0)return a;let c=Math.max(0,r),l=wh(e,t,c),u=l?2*Math.min(l.c1,l.c2):0;if(!l||s===1&&i===0||!(a>u))return Math.min(u,a);let m=uu(b=>qn(e,b)+qn(t,c-b),l.lo,l.hi),d=[{m1:l.c1,m2:l.c2}];for(let b=1;b<=B1&&m!==l.y1;b++){let g=l.y1+(m-l.y1)*b/B1;d.push({m1:e.cap(g),m2:t.cap(c-g)})}let p=Yh(d,Ra),f=Yh(d,fu);if(!(f>p))return u;let h=(Yh(d,{tbr:s,preloadN:i})-p)/(f-p);return Math.min(a,u+(a-u)*Math.min(1,Math.max(0,h)))}function G1(e,t,r,n,o,a){return Uh(e,o,ui(t,r,n,o,a))}function Uh(e,t,r){let n=Math.max(e.xNoLock,r/2),o=t.tbr===1/0||!(e.xLock>n)?0:e.xLock;return e.regenWheel>0?{...e,xNoLock:n,xLock:o,mixedMax:Math.max(e.mixedMax,2*n)}:{...e,xNoLock:n,xLock:o,mixedMax:2*n,regenRoom:a=>2*Math.max(0,n-a)}}function Xh(e,t,r,n=30){let o=t,a=e(o),s=a-o;if(!(Math.abs(s)>r))return{x:o,fx:a,evals:1};let i=a,c=e(i),l=c-i,u=2;for(;Math.abs(l)>r&&u<n;){let m=s<0!=l<0,d=l-s,p=d!==0?i-l*(i-o)/d:NaN;m?p>Math.min(o,i)&&p<Math.max(o,i)||(p=.5*(o+i)):Number.isFinite(p)?Math.abs(p-i)>10*Math.abs(l)&&(p=i+Math.sign(p-i)*10*Math.abs(l)):p=c;let f=e(p),h=f-p;if(u++,m&&h<0==l<0?s*=.5:(o=i,s=l),i=p,c=f,l=h,s<0!=l<0&&Math.abs(i-o)<=r)break}return{x:i,fx:c,evals:u}}function K1(e,t,r,n,o,a=60){let s=t,i=e(s),c=i-s,l=1;if(!(Math.abs(c)>n))return{x:s,fx:i,evals:l};let u=Math.sign(r-t),m=Math.abs(r-t),d=0;for(let p=o;l<a;p*=2){if(d=Math.min(d+p,m),d>m-n)return null;let f=t+u*d,h=e(f),b=h-f;if(l++,!(Math.abs(b)>n))return{x:f,fx:h,evals:l};if(c<0!=b<0)return z1(e,s,c,f,h,b,n,l,a);s=f,c=b}return null}function H1(e,t,r,n=60){let o=t,a=e(o),s=a-o;if(!(Math.abs(s)>r))return{x:o,fx:a,evals:1};let i=Math.sign(s),c=a;for(let l=2;;l++){let u=e(c),m=u-c;if(!(Math.abs(m)>r))return{x:c,fx:u,evals:l};if(s<0!=m<0)return z1(e,o,s,c,u,m,r,l,n);if(l>=n)return{x:c,fx:u,evals:l};let d=Math.abs(c-o),p=s!==m?m*(c-o)/(s-m):NaN,f=p*i>0?Math.min(Math.abs(p),10*Math.abs(m),2*d):2*d;o=c,s=m,c+=i*f}}function z1(e,t,r,n,o,a,s,i,c){let l=t,u=r,m=n,d=a,p=n,f=o,h=0;for(;i<c&&Math.abs(m-l)>s;){p=(l*d-m*u)/(d-u),f=e(p);let b=f-p;if(i++,!(Math.abs(b)>s))break;b<0==u<0?(l=p,u=b,h===-1&&(d*=.5),h=-1):(m=p,d=b,h===1&&(u*=.5),h=1)}return{x:p,fx:f,evals:i}}function bu(e,t){return Math.abs(e.fx-e.x)>t?e.x:e.fx}var JD=(e,t)=>{let r=e.brakes?.hydraulic?.[t];return!!r&&r.location==="inboard"&&r.discs===1};function Kt(e,t,r){let n=e.driveline?.[t];if(n)return r>=0?n.drive:JD(e,t)?n.coast:n.hubs}var Y1=e=>e.tbr>1||e.preloadN>0;var eE=9.81,W1=["FL","FR","RL","RR"],qh=e=>e==="FL"||e==="FR",gu=e=>qh(e)?"front":"rear",j1={front:["FL","FR"],rear:["RL","RR"]},di=()=>({peak:new Map,freeBrake:new Map}),pi=25;function mi(e,t){let r=Math.max(0,e)/pi,n=Math.floor(r),o=r-n,a=t(n);return o>0?a+o*(t(n+1)-a):a}var gn=1e-4,tE=.05;function Gr(e,t,r,n=di(),o=!1){let a=r,s=e.massTotal,i=n.peak,c=(F,S)=>{let P=`${F}:${S}`,L=i.get(P);return L||(L=Tl(ye(t,F),Math.max(1,S*pi)),i.set(P,L)),L},l=(F,S)=>({aPeak:mi(S,P=>c(F,P).aPeak),fyPeak:mi(S,P=>c(F,P).fyPeak)}),u=n.freeBrake,m=(F,S)=>{let P=`${F}:${S}`,L=u.get(P);if(L===void 0){let D=Math.max(1,S*pi);L=Ct(ye(t,F),D,0,!0,c(F,S)),u.set(P,L)}return L},d=(F,S)=>S>0?mi(S,P=>m(F,P)):0,p=$r(e),f=mr(e),h=F=>f.regen&&f.regenPerWheel?.[F]?_r(f.regen.v,f.regen[F],a)/2:0,b=h("front"),g=h("rear"),y=(F,S,P)=>{let L=Math.max(0,S[F]),D=l(gu(F),L);return Ct(ye(t,gu(F)),L,P[F]*D.fyPeak,!0,D)},R=(F,S,P,L,D=!0)=>{let I=te=>{let fe=Math.max(0,S[te]),W=ye(t,F),J=l(F,fe);return{Fz:fe,a:Math.abs(d(F,fe)),b:J.fyPeak,slide:fe>0?Math.abs(W.forces({Fz:fe,kappa:-1,alpha:0}).Fx):0,cap:re=>Math.abs(Ct(W,fe,re,!0,J))}},O=te=>Math.abs(P[te])*l(gu(te),Math.max(0,S[te])).fyPeak,[_,z]=j1[F],E=I(_),N=I(z),B=O(_)+O(z),V=Ch(E,N,B,L,F==="front"?b:g),G=D?V:{...V,xLock:0},K=Kt(e,F,-1),Y=K&&Y1(K)?K:void 0;if(!Y)return{axle:F,eq:G,cap:G};let j=Number.isFinite(L)?L:E.cap(O(_))+N.cap(O(z)),Z=G1(G,E,N,B,Y,j);return{axle:F,eq:G,cap:Z,law:Y,strong:()=>E.cap(O(_))>=N.cap(O(z))?_:z}},k=(F,S,P,L)=>R(F,S,P,L).cap,v=(F,S,P)=>{let L=F.demand,D=p.shares?ga(S,L.front):ba(S,(L.front-L.regenFront)/2,L.regenFront),I=p.shares?ga(P,L.rear):ba(P,(L.rear-L.regenRear)/2,L.regenRear);return{front:Number.isFinite(D)?D:0,rear:Number.isFinite(I)?I:0}},x=F=>({muX:S=>S>0?Math.abs(d(F,S))/S:0,muY:S=>S>0?l(F,S).fyPeak/S:0}),M={front:x("front"),rear:x("rear")},A={lf:e.wheelbase/1e3*(1-e.frontMassFrac),lr:e.wheelbase/1e3*e.frontMassFrac},w={front:e.trackFront/2e3,rear:e.trackRear/2e3},C=(F,S,P,L,D)=>{let I=L.cap,O=D.cap,_=ni(p,I,O,a),z={arms:A,halfTrack:w,ayDir:Math.sign(F)};for(let E=0;E<2;E++){let N=v(_,I,O),B={};for(let G of W1){let K=Math.max(0,S[G]);B[G]={Fz:K,Fy:Math.abs(P[G])*l(gu(G),K).fyPeak,Fx:-(qh(G)?N.front:N.rear)/2}}let V=G=>{if(!G.law||!G.strong)return G.cap;let K={axle:G.axle,strong:G.strong(),full:2*G.cap.xNoLock,open:2*G.eq.xNoLock,sense:-1};return Uh(G.eq,G.law,ql(K,B,M,z))};I=V(L),O=V(D),_=ni(p,I,O,a)}return{limit:_,front:I,rear:O}};return{peakAt:l,axle:k,ceiling:(F,S,P)=>{let[L,D]=j1[F];return Math.abs(y(L,S,P)+y(D,S,P))},limitAt:(F,S,P,L=0)=>{let D={FL:0,FR:0,RL:0,RR:0},I=Ce(e,F,0,a,0,S),O,_=fe=>(O?.ax!==fe&&(O={ax:fe,loads:Ce(e,F,(fe+L)/eE,a,0,S)}),O.loads),z=Pl(fe=>ca(P,_(fe),I,l).short,-L,-1),E=P,N={front:0,rear:0},B,V,G=(fe,W=!0)=>{let J=z.at(fe);D=_(J),E=ca(P,D,I,l).util;let re=0,pe=0,de=0;for(let ie of W1){let oe=y(ie,D,E);re+=oe,qh(ie)?pe+=oe:de+=oe}if(N={front:Math.abs(pe),rear:Math.abs(de)},p.mode!=="tyre"){let ie=R("front",D,E,Math.abs(pe),W),oe=R("rear",D,E,Math.abs(de),W);if(o&&(ie.law||oe.law)){let ue=C(F,D,E,ie,oe);B=ue.limit,V={front:ue.front,rear:ue.rear}}else B=ni(p,ie.cap,oe.cap,a),V={front:ie.cap,rear:oe.cap};re=-B.force}return re/s},K=Xh(G,0,gn),Y=bu(K,gn),j=Y;if(B?.lockFront||B?.lockRear){let fe=Xh(J=>G(J,!1),0,gn);j=bu(fe,gn);let W=K1(G,fe.x,K.x,gn,tE);W||G(K.x),Y=bu(W??K,gn)}let Z=z.edge(),ne=Z!==void 0&&Y<Z;ne&&(Y=Math.min(0,Z),G(Y),j=Math.max(j,Y));let te={loads:D,ceiling:N,limit:B,axles:V};return{ax:Y,axUnlocked:j,...ne?{edge:Z}:{},...te,split:()=>te.limit&&te.axles?v(te.limit,te.axles.front,te.axles.rear):{...te.ceiling}}}}}var xu=9.81;function rE(e,t,r){let n=Ce(e,0,t,r),o=Math.max(0,n.FL)+Math.max(0,n.FR),a=Math.max(0,n.RL)+Math.max(0,n.RR);return o+a>0?o/(o+a):e.frontMassFrac}var q1=(e,t)=>t.mode==="hydraulic"&&!!mr(e).regen;function ka(e,t,r=0,n,o=0){if(!e.brakes&&e.brakeBalanceFront==null)return e.frontMassFrac;let a=$r(e);if(a.shares&&a.mode!=="tyre")return a.shares.front;let s=n&&q1(e,a)?Q1(e,n):void 0,i=s?.shares??U1.get(e);i||U1.set(e,i=new Map);let c=Math.round(Math.abs(t)/.005),l=Math.round(Math.max(0,r)/.25),u=s?Math.round(o/.01):0,m=Z1(c,l,u),d=i.get(m);if(d===void 0){let p=-c*.005,f=l*.25,h=e.massTotal*Math.abs(p)*xu;if(s){let b=ek(a,J1(e,s,c,l,u),h,f);d=b.front+b.rear>0?b.front/(b.front+b.rear):.5}else d=a.mode==="tyre"?rE(e,p,f):Sh(a,h,f);i.size>5e4&&i.clear(),i.set(m,d)}return d}var U1=new WeakMap;function Ru(e,t,r,n,o=0){let a=$r(e);if(!q1(e,a))return;let s=Math.round(Math.max(0,r)/(e.massTotal*xu)/.005),i=Math.round(Math.max(0,n)/.25);return ek(a,J1(e,Q1(e,t),s,i,Math.round(o/.01)),Math.max(0,r),n)}var X1=new WeakMap;function Q1(e,t){let r=X1.get(e);r||X1.set(e,r=new WeakMap);let n=r.get(t);return n||r.set(t,n={ev:t,tyres:di(),shares:new Map,rooms:new Map,speeds:new Map}),n}var Z1=(e,t,r)=>(r*1001+e)*100003+t;function J1(e,t,r,n,o){let a=Z1(r,n,o),s=t.rooms.get(a);if(!s){let i=n*.25,c=o*.01,l=t.speeds.get(n);l||(l={cap:Gr(e,t.ev,i,t.tyres),dragG:-Math.max(0,fs(e,i).drag)/(e.massTotal*xu)},t.speeds.set(n,l));let{cap:u}=l,m=Ce(e,c,-r*.005+l.dragG,i),d=Math.abs(c)*e.massTotal*xu,p=b=>{let[g,y]=b==="front"?["FL","FR"]:["RL","RR"],R=d*(b==="front"?e.frontMassFrac:1-e.frontMassFrac),k=u.peakAt(b,Math.max(0,m[g])).fyPeak+u.peakAt(b,Math.max(0,m[y])).fyPeak,v=R>0&&k>0?Math.min(1,R/k):0;return u.axle(b,m,{FL:v,FR:v,RL:v,RR:v},1/0)},f,h;s=(b,g)=>(b==="front"?f??=p("front"):h??=p("rear")).regenRoom(g),t.rooms.size>5e4&&t.rooms.clear(),t.rooms.set(a,s)}return s}function yu(e,t,r,n){let o=e.demand(r,n),a=o.front-o.regenFront,s=o.rear-o.regenRear,i=o.regenFront>0?Math.min(o.regenFront,t("front",a/2)):0,c=o.regenRear>0?Math.min(o.regenRear,t("rear",s/2)):0;return{front:i===o.regenFront?o.front:a+i,rear:c===o.regenRear?o.rear:s+c,regenFront:i,regenRear:c,demand:o}}function ek(e,t,r,n){if(!(r>0))return yu(e,t,1,n);let o=c=>c.front+c.rear,a=e.controlFor(r,n),s=yu(e,t,a,n);if(o(s)>=r||!(a<e.uMax))return s;let i=a;for(;o(s)<r&&i<e.uMax&&i<1e7;)a=i,i=Math.min(e.uMax,2*i),s=yu(e,t,i,n);if(o(s)<r)return s;for(let c=0;c<60&&i-a>1e-10*i;c++){let l=.5*(a+i),u=yu(e,t,l,n);o(u)<r?a=l:(i=l,s=u)}return s}var Ma={rel:.003,abs:2,kappa:1e-5,iters:12},Qh={rel:1e-6,abs:.001,kappa:1e-12,iters:40};function Qn(e,t,r,n=Ma){let o=t>=0?1:-1,a=Math.abs(t),s=Math.max(n.abs,n.rel*a),i=e(0);if(Math.abs(i.Fx)-a>=0)return{kappa:0,forces:i};let c=0,l=i,u=Math.abs(i.Fx)-a,m=Math.min(.3,Math.max(.004,Math.abs(r)||.02)),d=e(o*m),p=Math.abs(d.Fx)-a,f=null;for(;p<0&&m<.3;){let g=Math.min(.3,m*1.9),y=e(o*g),R=Math.abs(y.Fx);if(R<Math.abs(d.Fx)){f={kappa:g,forces:y};break}c=m,l=d,u=p,m=g,d=y,p=R-a}if(p<0){let g=aE(e,o,c,l,m,d,f),y=Math.abs(g.forces.Fx);if(y<a)return{kappa:o*g.kappa,forces:g.forces};m=g.kappa,d=g.forces,p=y-a}let h=d,b=o*m;for(let g=0;g<n.iters&&m-c>n.kappa;g++){let y=p-u,R=Math.abs(y)>1e-12?(c*p-m*u)/y:.5*(c+m);R>c&&R<m||(R=.5*(c+m));let k=e(o*R),v=Math.abs(k.Fx)-a;if(h=k,b=o*R,Math.abs(v)<s)break;v<0?(c=R,u=v,p*=.5):(m=R,p=v,u*=.5)}return{kappa:b,forces:h}}var tk=1e-6,nE=40,oE=(3-Math.sqrt(5))/2;function aE(e,t,r,n,o,a,s){let i=a,c,l,u,m=-Math.abs(a.Fx),d,p,f=-Math.abs(n.Fx);if(s){c=s.kappa;let g=-Math.abs(s.forces.Fx);[l,d,u,p]=g<=f?[c,g,r,f]:[r,f,c,g]}else{c=.3;let g=.3*(1-tk),y=e(t*g),R=-Math.abs(y.Fx);if(R>=m)return{kappa:o,forces:a};[l,d,u,p]=[o,m,r,f],o=g,m=R,i=y}f<m&&([l,d]=[o,m],o=r,m=f,i=n);let h=c-r,b=0;for(let g=0;g<nE;g++){let y=tk*Math.abs(o)+1e-10,R=.5*(r+c);if(Math.abs(o-R)<=2*y-.5*(c-r))break;let k=!0;if(Math.abs(h)>y){let A=(o-l)*(m-p),w=(o-u)*(m-d),C=(o-u)*w-(o-l)*A;w=2*(w-A),w>0&&(C=-C),w=Math.abs(w);let T=h;if(h=b,Math.abs(C)<Math.abs(.5*w*T)&&C>w*(r-o)&&C<w*(c-o)){b=C/w;let F=o+b;(F-r<2*y||c-F<2*y)&&(b=R>=o?y:-y),k=!1}}k&&(h=o>=R?r-o:c-o,b=oE*h);let v=Math.abs(b)>=y?o+b:o+(b>=0?y:-y),x=e(t*v),M=-Math.abs(x.Fx);M<=m?(v>=o?r=o:c=o,u=l,p=d,l=o,d=m,o=v,m=M,i=x):(v<o?r=v:c=v,M<=d||l===o?(u=l,p=d,l=v,d=M):(M<=p||u===o||u===l)&&(u=v,p=M))}return{kappa:o,forces:i}}var vu=e=>Math.max(2,.003*Math.abs(e)),sE=(e,t)=>Math.max(t.abs,t.rel*Math.abs(e)),Zh=.5,iE=.03;function cE(e,t,r,n,o){let a=.5*(e.vx+t.vx),s=v=>{let x=(1+v)*a/e.vx-1,M=(1+v)*a/t.vx-1,A=e.at(x),w=t.at(M);return{kappaM:v,kl:x,kr:M,fl:A,fr:w,g:A.Fx+w.Fx-r}},i=sE(r,o),c=Math.max(-Zh,Math.min(Zh,n)),l=s(c);if(Math.abs(c)>iE){let v=s(.8*c);(l.g-v.g)/(c-v.kappaM)>0||(l=s(0))}if(Math.abs(l.g)<i)return l;let u=l.g<0?1:-1,m=l,d=l,p=.004,f=l;for(let v=0;v<12;v++){let x=m.kappaM+u*p;if(Math.abs(x)>Zh)break;let M=s(x);if(Math.abs(M.g)<i)return M;if(Math.abs(M.g)<Math.abs(f.g)&&(f=M),Math.sign(M.g)!==Math.sign(m.g)){d=M;break}if(u*(M.g-m.g)<=0)return f;m=M,p*=1.9}if(d===l)return f;let h=m,b=d,g=h.g,y=b.g,R=Math.abs(g)<Math.abs(y)?h:b,k=Math.min(1e-7,o.kappa);for(let v=0;v<30&&Math.abs(b.kappaM-h.kappaM)>k;v++){let x=y-g,M=Math.abs(x)>1e-12?(h.kappaM*y-b.kappaM*g)/x:.5*(h.kappaM+b.kappaM),A=Math.min(h.kappaM,b.kappaM),w=Math.max(h.kappaM,b.kappaM);M>A&&M<w||(M=.5*(A+w));let C=s(M);if(R=C,Math.abs(C.g)<i)break;Math.sign(C.g)===Math.sign(g)?(h=C,g=C.g,y*=.5):(b=C,y=C.g,g*=.5)}return R}function rk(e,t,r,n){let o=(e*(1+t*n)+t*r)/(1-t*n);return e+o>=0?o:(e*(1-t*n)+t*r)/(1+t*n)}function Jh(e,t,r,n,o,a=Ma){let s=cE(e,t,r,o,a),i=s.fr.Fx-s.fl.Fx,c=va(n,r);if(Math.abs(i)<=c){let R=r-(s.fl.Fx+s.fr.Fx),k=Math.max(0,Math.abs(R)-vu(r))/2;return{left:{kappa:s.kl,forces:s.fl,want:s.fl.Fx+R/2,short:k},right:{kappa:s.kr,forces:s.fr,want:s.fr.Fx+R/2,short:k},locked:!0,spoolKappa:s.kappaM}}let l=Math.sign(i),u=r/2-l*c/2,m=r/2+l*c/2,d=Qn(e.at,u,e.seed||s.kl,a),p=Qn(t.at,m,t.seed||s.kr,a),f=Math.abs(u-d.forces.Fx)>vu(u),h=Math.abs(m-p.forces.Fx)>vu(m),b=Math.max(0,n.preloadN),g=hu(n.tbr);f&&!h?p=Qn(t.at,rk(d.forces.Fx,l,b,g),p.kappa,a):h&&!f&&(d=Qn(e.at,rk(p.forces.Fx,-l,b,g),d.kappa,a));let y=(R,k)=>({kappa:R.kappa,forces:R.forces,want:k,short:Math.max(0,Math.abs(k-R.forces.Fx)-vu(k))});return{left:y(d,u),right:y(p,m),locked:!1,spoolKappa:s.kappaM}}var lE={front:["FL","FR"],rear:["RL","RR"]},uE=Object.freeze({Fx:0,Fy:0,Mz:0});function ku(e,t,r,n){let o=r;for(let a of["front","rear"]){let[s,i]=lE[a],c=r[s]+r[i],l=Kt(e,a,c);if(!l||!(va(l,c)>0))continue;let u=ye(t,a),m=n.alpha[a],d=(a==="front"?e.trackFront:e.trackRear)/2e3,p=(h,b)=>{let g=Math.max(0,n.Fz[h]);return{at:g>0?y=>u.forces({Fz:g,kappa:y,alpha:m,gamma:0}):()=>uE,vx:Math.max(.05,1-b*n.curvature),seed:0}},f=Jh(p(s,d),p(i,-d),c,l,n.seed?.[a]??0);n.seed&&(n.seed[a]=f.spoolKappa),o===r&&(o={...r}),o[s]=f.left.want,o[i]=f.right.want}return o}var Me=9.81,se=Math.PI/180,mE=8,pE=1e-6,xn=["FL","FR","RL","RR"],qt=e=>e==="FL"||e==="FR",yn=e=>qt(e)?"front":"rear";function hi(e,t){let r=ye(e,"front"),n=ye(e,"rear");return r===n?Jn(r,t):{front:Jn(r,t),rear:Jn(n,t)}}function Jn(e,t){return Yf(e,Math.min(t,Xt(e)))}var Su=e=>e==="FL"||e==="RL";function Aa(e,t,r=0,n,o=0){let a=t?.axG??0,s=Number.isFinite(t?.tvRearDiffN)?t?.tvRearDiffN:0;if(!(!!a&&Number.isFinite(a))&&!s)return null;let c=e.massTotal*a*Me,l=a>=0?Math.min(1,Math.max(0,t?.driveFrontFrac??0)):Math.min(.99,Math.max(.01,ka(e,a,r,n,o))),u=c*l/2,m=c*(1-l)/2;return{axG:a,fx:{FL:u,FR:u,RL:m-s/2,RR:m+s/2}}}function sb(e,t,r,n){return Math.abs(eo(e,t,r,n!==void 0?{steerMaxDeg:n}:{}).peak.steerDeg)}function ib(e,t,r,n){let o=e.tv;if(!o?.enabled)return 0;let a=Mk(o)(t,Math.abs(r),n);return r<0?-a:a}function cb(e,t,r=0,n,o=0,a=0,s){let i=Aa(e,{axG:t,driveFrontFrac:a},r,n,o),c=i?i.fx:{FL:0,FR:0,RL:0,RR:0};return i&&s&&n?ku(e,n,c,s):c}var bi=e=>Su(e)?-1:1,lb=(e,t,r,n,o)=>t*e.Fy(t*r,n,t*o);function ob(e){let t=e.wheelbase/1e3,r=t*(1-e.frontMassFrac),n=t*e.frontMassFrac;return{wb:t,lf:r,lr:n,m:e.massTotal}}function dE(e,t,r){let n=Math.abs(t),o=e.steerFront;if(o&&o.meanDeg.length>1){let u=t>=0,m=r&&o.travelSurface?oa(o,n/se,u?r.FL:r.FR,u?r.FR:r.FL):aa(o,n/se);return{innerMag:m.innerDeg*se,outerMag:m.outerDeg*se,innerCamber:m.innerCamber,outerCamber:m.outerCamber,atLock:m.atLock}}let a=e.trackFront/1e3,s=e.wheelbase/1e3,i=(e.ackermannPct??0)/100,c=n,l=n;if(n>1e-4){let u=s/Math.tan(n),m=Math.atan(s/Math.max(.05,u-a/2)),d=Math.atan(s/(u+a/2));c=n+i*(m-n),l=n+i*(d-n)}return{innerMag:c,outerMag:l,innerCamber:0,outerCamber:0,atLock:!1}}function to(e,t,r){let n=(e.toeFrontDeg??0)*se,o=(e.toeRearDeg??0)*se,a=dE(e,t,r),s=t>=0?1:-1,i=t>=0,c=s*(i?a.innerMag:a.outerMag),l=s*(i?a.outerMag:a.innerMag);return{steer:{FL:c-n,FR:l+n,RL:-o,RR:o},camber:{FL:i?a.innerCamber:a.outerCamber,FR:i?a.outerCamber:a.innerCamber,RL:0,RR:0},atLock:a.atLock}}function ub(e,t,r){if(r.Fz<=0)return 0;let n=pt(ye(e,yn(t))),o=bi(t),a=Math.abs(r.kappa)<1e-12?n.Mz(o*r.slipRad,r.Fz,o*r.camberRad):n.forces({Fz:r.Fz,kappa:r.kappa,alpha:o*r.slipRad,gamma:o*r.camberRad}).Mz;return o*a}function nk(e,t,r,n){if(!Wn(e))return null;let o=pt(ye(t,"front")),a={};for(let s of["FL","FR"]){let i=n[s];a[s]={Fz:i.Fz,Fx:i.Fx,Fy:i.Fy,Mz:ub(o,s,i)}}return Ys(e,r/se,a,pn(o.model),{FL:n.FL.travelMm,FR:n.FR.travelMm})}var ok=()=>({totalNm:[],aligningNm:[],lateralNm:[],longitudinalNm:[],jackingNm:[]});function ak(e,t){e.totalNm.push(t.totalNm),e.aligningNm.push(t.aligningNm),e.lateralNm.push(t.lateralNm),e.longitudinalNm.push(t.longitudinalNm),e.jackingNm.push(t.jackingNm)}var fE=Object.freeze({Fx:0,Fy:0,Mz:0});function sk(e,t,r){let n=t==="front"?(r?.FL??0)+(r?.FR??0):(r?.RL??0)+(r?.RR??0),o=Kt(e,t,n);return o&&va(o,n)>0?{F:n,law:o}:null}function Lt(e,t,r,n,o,a,s,i,c){let l=s?.fx,u=s?.axG??0,{wb:m,lf:d,lr:p,m:f}=ob(e),h=sk(e,"front",l),b=sk(e,"rear",l),g={front:0,rear:0},y=i!==void 0&&i>0&&Number.isFinite(i)?i:null,R=W=>y===null?r:Math.sqrt(Math.max(0,W)*y),k=pt(ye(t,"front")),v=pt(ye(t,"rear")),x=e.trackFront/2e3,M=e.trackRear/2e3,A=!!(e.kinFront&&e.kinRear),w=A&&y===null?fn(e,e.kinFront,e.kinRear,r):null,C=NaN,T=null,F=W=>{if(!A)return null;if(y===null)return w;let J=R(W);return J!==C&&(C=J,T=fn(e,e.kinFront,e.kinRear,J)),T},S={},P={FL:0,FR:0,RL:0,RR:0},L=e.kinFront?.compliance,D=e.kinRear?.compliance,I=!!(L||D),O=!!(L?.toePerMz||D?.toePerMz),_=W=>qt(W)?L:D,z={FL:{fy:0,fx:0,mz:0},FR:{fy:0,fx:0,mz:0},RL:{fy:0,fx:0,mz:0},RR:{fy:0,fx:0,mz:0}},E=!1,N=W=>{let J=W/r,re=y===null?n+d*J/r:n+d/y,pe=y===null?n-p*J/r:n-p/y,de=F(W),ie=R(W),oe=de?de(W/Me,u,n/se,o/se):null,ue=oe?{FL:oe.FL.travel,FR:oe.FR.travel}:void 0,$e=wl(e,W/Me,u,ie,n/se,o/se,ue,oe?.steeringJacking),Ae=$e.loads;E=$e.overturned;let le=to(e,o,ue),Re=le.steer,Te=0,ze=be=>{let Fe=Math.max(0,Ae[be]),xe=bi(be),me=qt(be)?k:v,Le=_(be),Se=0,Ye=0;if(Le){let _n=z[be];Se=Le.toePerFy*_n.fy+Le.toePerFx*_n.fx+Le.toePerMz*_n.mz,Ye=Le.camberPerFy*_n.fy+Le.camberPerFx*_n.fx}let Ue=Re[be]+(oe?xe*oe[be].bumpToe*se:0)+xe*Se*se,jt=Ue-(qt(be)?re:pe),In=(oe?oe[be].camberRoad:0)*se+xe*(le.camber[be]+Ye)*se;return{Fz:Fe,mir:xe,t:me,gains:Le,complianceToe:Se,steerK:Ue,slip:jt,camberRad:In}},je=(be,Fe)=>{let xe=y===null?J/r:1/y,me=qt(be)?d:-p,Le=(Su(be)?1:-1)*(qt(be)?x:M),Se=(Math.cos(n)-Le*xe)*Math.cos(Fe.steerK)+(Math.sin(n)+me*xe)*Math.sin(Fe.steerK);return{at:Fe.Fz>0?Ye=>Fe.t.forces({Fz:Fe.Fz,kappa:Ye,alpha:Fe.mir*Fe.slip,gamma:Fe.mir*Fe.camberRad}):()=>fE,vx:Math.max(.05,Se),seed:P[be]}};for(let be=0;be<(I?mE:1);be++){Te=0;let Fe=0,xe={};for(let me of xn){let Le=qt(me)?h:b;if(Le&&!xe[me]){let[Go,Nt]=qt(me)?["FL","FR"]:["RL","RR"],Zc=ze(Go),lx=ze(Nt),ux=yn(me),sd=Jh(je(Go,Zc),je(Nt,lx),Le.F,Le.law,g[ux],Qh);g[ux]=sd.spoolKappa,xe[Go]={w:Zc,share:sd.left},xe[Nt]={w:lx,share:sd.right}}let Se=xe[me]?.w??ze(me),{Fz:Ye,mir:Ue,t:jt,gains:In,complianceToe:_n,steerK:rd,slip:nd,camberRad:od}=Se,us=l?.[me]??0,Vo,Bo=0,ad=0,Qc=0,$o=xe[me]?.share;if($o)P[me]=$o.kappa,ad=$o.kappa,Bo=$o.forces.Fx,Qc=$o.short,Vo=Ue*$o.forces.Fy;else if(us===0||Ye<=0)Vo=lb(jt,Ue,nd,Ye,od),Qc=Ye<=0?Math.abs(us):0;else{let Nt=Qn(Zc=>jt.forces({Fz:Ye,kappa:Zc,alpha:Ue*nd,gamma:Ue*od}),us,P[me],Qh);P[me]=Nt.kappa,ad=Nt.kappa,Bo=Nt.forces.Fx,Qc=Math.max(0,Math.abs(us-Bo)-Math.max(Ma.abs,Ma.rel*Math.abs(us))),Vo=Ue*Nt.forces.Fy}if(S[me]={Fz:Ye,travelMm:oe?.[me].travel??0,steerRad:rd,slipRad:nd,camberRad:od,Fy:Vo,Fx:Bo,kappa:ad,fxShort:Qc,lifted:$e.lifted[me]},In){let Go=O&&In.toePerMz?ub(jt,me,S[me]):0;z[me]={fy:-Ue*Vo,fx:Bo,mz:-Ue*Go*1e3};let Nt=z[me];Fe=Math.max(Fe,Math.abs(In.toePerFy*Nt.fy+In.toePerFx*Nt.fx+In.toePerMz*Nt.mz-_n))}Te+=Vo*Math.cos(rd)+Bo*Math.sin(rd)}if(Fe<pE)break}return Te/f},B=W=>{let J=Ce(e,0,u,W,0,o/se);return J.FL+J.FR+J.RL+J.RR},V=Math.max(20,3.5*B(r)/f);if(y!==null){V=4*Me;for(let W=0;W<8;W++){let J=Math.min(40*Me,3.5*B(R(V))/f);if(J<=V)break;V=J}V=Math.max(20,V)}let G=W=>N(W)-W,K=Math.max(.001,V*1e-4),Y=(W,J,re,pe)=>{let de=W,ie=re,oe=J,ue=pe,$e=de;for(let Ae=0;Ae<40;Ae++){let le=ue-oe,Re=Math.abs(le)>1e-12?(de*ue-ie*oe)/le:.5*(de+ie),Te=Math.min(de,ie),ze=Math.max(de,ie);Re>Te&&Re<ze||(Re=.5*(de+ie));let je=G(Re);if($e=Re,Math.abs(je)<1e-4||ze-Te<1e-6)break;je<0==oe<0?(de=Re,oe=je,ue*=.5):(ie=Re,ue=je,oe*=.5)}return $e},j=(W,J,re,pe=!1)=>{let de=(Ae,le)=>re>0?Ae>0&&le<0:le>0&&Ae<0,ie=W,oe=J,ue=W+re*Math.min(Math.abs(J),V);if(!pe&&Math.abs(ue-W)>K){let Ae=G(ue);if(de(oe,Ae))return{root:Y(ie,oe,ue,Ae),last:ie};ie=ue,oe=Ae}let $e=pe?V/24:Math.max(V/24,Math.abs(ue-W)/4);for(let Ae=1;Ae<=24;Ae++){let le=ie+re*$e;if(Math.abs(le)>V)break;let Re=G(le);if(de(oe,Re))return{root:Y(ie,oe,le,Re),last:ie};if(pe&&Re*re<0&&(Re-oe)*re<0)break;ie=le,oe=Re}return{root:null,last:ie}},Z=c??null;if(c===void 0&&a!==void 0&&Number.isFinite(a)&&Math.abs(a)<=V){let W=G(a);if(Math.abs(W)<=1e-4)G(a+K)<0&&G(a-K)>0&&(Z=a);else{let J=j(a,W,Math.sign(W)).root;Z=J!==null&&(J===0||Math.sign(J)===Math.sign(a))?J:null}}let ne=Z===null;if(Z===null){let W=G(0),J=G(K),re=Math.abs(W)<=1e-4,pe=re?y!==null?1:o!==0?Math.sign(o):J>0?1:-1:Math.sign(W),de=re?pe*K:0,ie=re?pe>0?J:G(-K):W,oe=j(de,ie,pe);Z=oe.root??(re?0:oe.last)}let te=N(Z);if(ne&&o!==0&&y===null){let W=Math.sign(o);if(Z*W<=0||(S.RL.Fy+S.RR.Fy)*W<0){let J={...S},re=E,pe=W*Math.max(Z*W+K,n*W*r*r/p),de=null;if(pe*W<V){let ie=G(pe);if(ie*W>0)de=j(pe,ie,W).root;else{let oe=pe+W*V/24,ue=G(oe);(ue-ie)*W>0&&(de=j(oe,ue,W,ue*W<=0).root)}}de!==null&&de*W>0?(Z=de,te=N(Z)):(Object.assign(S,J),E=re)}}let fe=d*(S.FL.Fy*Math.cos(S.FL.steerRad)+S.FR.Fy*Math.cos(S.FR.steerRad))-p*(S.RL.Fy+S.RR.Fy);if(s||h||b){let W=J=>(Su(J)?1:-1)*(qt(J)?x:M);for(let J of xn){let re=S[J],pe=qt(J)?d:-p;fe+=pe*re.Fx*Math.sin(re.steerRad)-W(J)*re.Fx*Math.cos(re.steerRad)}}return y!==null&&Z<-1e-6?{ay:NaN,cn:NaN,wheels:S,overturned:E,res:NaN}:{ay:Z/Me,cn:fe/(f*Me*m),wheels:S,overturned:E,res:te-Z}}function hE(e,t,r,n,o,a,s,i=0){let c=20*se,l=.001,u=(h,b)=>{let g=Lt(e,t,r,h,n,b,s);return{cn:g.cn-i,ay:g.ay*Me}},m=h=>n===0||i!==0||Math.abs(h)<.05||Math.sign(h)===Math.sign(n),d=(h,b,g,y)=>{let R=u(h,y);if(Math.abs(R.cn)<1e-5)return{beta:h,trimmed:!0};let k=y===void 0?void 0:R.ay,v={pos:{b:h,cn:R.cn,ay:k},neg:{b:h,cn:R.cn,ay:k}},x=null,M=h,A=Math.abs(R.cn);for(let w=0;w<b.length&&!x;w++)for(let C of[v.pos,v.neg]){let T=C===v.pos?1:-1,F=h+T*b[w];if(Math.abs(F)>c)continue;let S=u(F,C.ay);if(Math.abs(S.cn)<A&&m(S.ay)&&(A=Math.abs(S.cn),M=F),S.cn===0&&m(S.ay))return{beta:F,trimmed:!0};if(S.cn<0!=C.cn<0){let P={lo:C.b,hi:F,ayLo:C.ay},L=ik(u,P),D=u(L,C.ay);if(Math.abs(D.cn)<l&&m(D.ay))return x=P,{beta:L,trimmed:!0}}C.b=F,C.cn=S.cn,y!==void 0&&(C.ay=S.ay)}return x?{beta:ik(u,x),trimmed:!0}:g?{beta:M,trimmed:!1}:null},p=[.25,.75,2,5].map(h=>h*se);if(o!==void 0&&Number.isFinite(o)&&Math.abs(o)<=c){let h=d(o,p,!1,a);if(h)return h;if(!s&&i===0&&a!==void 0&&Number.isFinite(a)){let b=bE(e,t,r,n,o,a,c);if(b&&m(b.ay))return{beta:b.beta,trimmed:!0,ay:b.ay}}}let f=[1,3,7,15,20].map(h=>h*se).filter(h=>h<=c);return d(0,f,!0)??{beta:0,trimmed:!1}}function ik(e,t){let{lo:r,hi:n}=t,o=t.ayLo,a=e(r,o).cn,s=e(n,o).cn,i=r;for(let c=0;c<40;c++){let l=s-a,u=Math.abs(l)>1e-12?(r*s-n*a)/l:.5*(r+n);u>Math.min(r,n)&&u<Math.max(r,n)||(u=.5*(r+n));let m=e(u,o),d=m.cn;if(o!==void 0&&(o=m.ay),i=u,Math.abs(d)<1e-5||Math.abs(n-r)<1e-5)break;d<0==a<0?(r=u,a=d,s*=.5):(n=u,s=d,a*=.5)}return i}function bE(e,t,r,n,o,a,s){let i=(d,p)=>{let f=Lt(e,t,r,d,n,void 0,null,void 0,p);return{r:f.res,c:f.cn}},c=o,l=a,u=i(c,l),m=0;for(let d=0;d<gE;d++){let p=i(c+eb,l),f=i(c,l+tb),h=(p.r-u.r)/eb,b=(f.r-u.r)/tb,g=(p.c-u.c)/eb,y=(f.c-u.c)/tb,R=h*y-b*g;if(!Number.isFinite(R)||R===0||Math.abs(R)<vE*(Math.abs(h*y)+Math.abs(b*g)))return null;if(d===0)m=Math.sign(R);else if(Math.sign(R)!==m)return null;if(Math.abs(u.r)<=1e-4&&Math.abs(u.c)<=1e-5)return{beta:c,ay:l};let k=(u.c*b-u.r*y)/R,v=(u.r*g-u.c*h)/R,x=Math.min(1,yE/Math.max(Math.abs(k),1e-300),xE/Math.max(Math.abs(v),1e-300));if(c+=x*k,l+=x*v,Math.abs(c-o)>RE||Math.abs(c)>s||l*a<0)return null;u=i(c,l)}return null}var gE=8,eb=1e-5,tb=.001,yE=1*se,xE=2,RE=5*se,vE=.5;function fk(e,t,r,n,o,a,s,i){let c=Lt(e,t,r,n,o,a,s,void 0,i),l=c.ay*Me/r,u={},m=0;for(let f of xn){let h=c.wheels[f],b=ye(t,yn(f)),g=Xt(b),y=b.muY(Math.min(h.Fz,g)),R=b.muX(Math.min(h.Fz,g));m+=h.fxShort,u[f]={Fz:h.Fz,steerDeg:h.steerRad/se,slipDeg:h.slipRad/se,camberDeg:h.camberRad/se,Fy:h.Fy,Fx:h.Fx,Mz:ub(b,f,h),gripUtil:y*h.Fz>0?Math.hypot(h.Fy/(y*h.Fz),R*h.Fz>0?h.Fx/(R*h.Fz):0):0,...h.Fz>g?{pastTurnover:!0}:{},lifted:h.lifted}}let d=Ys(e,o/se,u,pn(ye(t,"front").model),{FL:c.wheels.FL.travelMm,FR:c.wheels.FR.travelMm}),p=to(e,o,e.kinFront&&e.kinRear?{FL:c.wheels.FL.travelMm,FR:c.wheels.FR.travelMm}:void 0);return{wheels:u,ay:c.ay,ax:s?.axG??0,beta:n/se,yawRate:l*180/Math.PI,steerDeg:o/se,...p.atLock?{lockDeg:(p.steer.FL+p.steer.FR)/2/se}:{},converged:!0,trimmed:!c.overturned,overturned:c.overturned,driving:!1,fxShortfall:m,...d?{steering:d}:{}}}function Hr(e,t,r,n,o,a,s=0){let i=Math.max(8,r),c=Zn(e,t,i,n,o,a,s);return n!==0&&o?.driving===void 0&&(c.driving=NE(e,t,i,c,a,s)),c}function Zn(e,t,r,n,o,a,s){let i=n*se,c=Aa(e,a,r,t),l=o&&Number.isFinite(o.ay)?o.ay*Me:void 0,u=o&&Number.isFinite(o.beta)?o.beta*se:void 0,{beta:m,trimmed:d,ay:p}=hE(e,t,r,i,u,l,c,s),f=fk(e,t,r,m,i,l,c,p),h={...f,trimmed:d&&!f.overturned};return h.driving=n===0?h.trimmed:o?.driving!==void 0&&o.driving&&h.trimmed&&Math.abs(h.beta-o.beta)<=kE,h}var kE=3;function eo(e,t,r,n={}){let o=Math.max(8,r),a=n.direction??1,s=n.yawDemandCn??0,i=n.steerMaxDeg??ME,c=typeof n.op=="function"?n.op:()=>n.op,l=typeof n.op=="function"?null:`${o}|${a}|${s}|${i}|${n.op?`${n.op.axG}|${n.op.driveFrontFrac??""}|${n.op.tvRearDiffN??""}`:""}`;if(l!==null){let x=rb.get(e)?.get(t)?.get(l);if(x)return x}let u=(x,M)=>M.trimmed&&Math.abs(M.beta-x.beta)<=Au&&Math.abs(M.ay-x.ay)*Me<=Fu,m=!1,d=(x,M)=>{let A=Zn(e,t,o,a*x,M,c(a*x),s);return u(M,A)?(A.driving=!0,A):(m=A.overturned,null)},p=[Zn(e,t,o,0,void 0,c(0),s)],f=null,h=!1,b,g=x=>{let M=p.length-1;for(;M>1&&x.sb*(p[M].beta-p[M-1].beta)>=0;)M--;let A=a*(x.state.ay-p[M].ay)>0,w=C=>x.sb*(C.beta-x.state.beta)>0||a*C.steerDeg>=a*x.state.steerDeg||A&&a*C.ay>=a*x.state.ay;for(;p.length>Math.max(2,M)&&w(p[p.length-1]);)p.pop();b={state:x.state,stall:p[p.length-1]},p.push(x.state),f=Math.abs(x.state.steerDeg)},y=(x,M=!1)=>M||EE(p[p.length-1],x)?IE(e,t,o,a,p,x,c,s):null,R=p[0].trimmed?p[0]:null;if(!R){let x=0;for(let M=ck;M<=i&&!R;M+=ck){let A=Zn(e,t,o,a*M,void 0,c(a*M),s);if(A.trimmed){let w=M;R=A;for(let C=0;C<6;C++){let T=.5*(x+w),F=Zn(e,t,o,a*T,void 0,c(a*T),s);F.trimmed?(w=T,R=F):x=T}}else x=M}R&&(R.driving=!0,p.push(R))}if(R){let x=Math.abs(R.steerDeg),M=Math.min(nb,100/(o*o)),A=R;for(;x<i;){let w=Math.min(i,x+M),C=d(w,A);if(C){let L=y(C);if(L){g(L);break}if(p.push(C),w>=i||kk(e,a*w))break;Math.abs(C.beta-A.beta)<.5*Au&&Math.abs(C.ay-A.ay)*Me<.5*Fu&&(M=Math.min(nb,1.5*M)),x=w,A=C;continue}if(M>SE){M*=.5;continue}let T=m,F=!1,S=null;for(let L of AE){let D=Math.min(i,x+L);if(D<=x)continue;let I=d(D,A);if(I){if(S=y(I,!0),S)break;p.push(I),x=D,A=I,M=Math.min(nb,100/(o*o)),F=!0;break}}if(F)continue;if(S){g(S);break}f=x,h=T;let P=T?null:DE(e,t,o,a,p,c,s);P&&g(P);break}}else f=0;let k=p[0];for(let x of p)a*x.ay>a*k.ay&&(k=x);let v={states:p,foldDeg:f,rollover:h,peak:k,...b?{fold:b}:{}};if(l!==null){let x=rb.get(e);x||(x=new WeakMap,rb.set(e,x));let M=x.get(t);M||(M=new Map,x.set(t,M)),M.size>256&&M.clear(),M.set(l,v)}return v}var rb=new WeakMap,ME=90,Au=1.5,Fu=2.5,nb=5,SE=.002,AE=[.5,1],ck=2.5,hk=.01,Kr=.001,FE=.05,wE=.25,CE=5,TE=2,lk=1e-8,PE=1e-7,LE=1e-6;function bk(e,t,r,n,o,a,s){let i=n*se,c=o.ay*Me,l=b=>{let g=Lt(e,t,r,i,b*se,c,Aa(e,a(b),r,t));return{g:g.cn-s,ay:g.ay}},u=o.steerDeg,m=l(u),d=u+(u<0?-.001:.001),p=l(d),f=()=>p.g===0||Math.abs(d-u)<lk;for(let b=0;b<40&&Math.sign(m.g)===Math.sign(p.g)&&!f();b++){let g=(p.g-m.g)/(d-u),y=g!==0?d-p.g/g:d+2*(d-u);if(!Number.isFinite(y))return null;let R=2*Math.abs(d-u)+.001;if(y=d+Math.max(-R,Math.min(R,y-d)),u=d,m=p,d=y,p=l(d),Math.abs(d-o.steerDeg)>TE)return null}let h={x:d,ay:p.ay};if(Math.sign(m.g)!==Math.sign(p.g)){let b=u,g=m.g,y=d,R=p.g;for(let k=0;k<60&&R!==0&&Math.abs(y-b)>lk;k++){let v=(b*R-y*g)/(R-g),x=l(v);if(h={x:v,ay:x.ay},x.g===0)break;Math.sign(x.g)===Math.sign(g)?(b=v,g=x.g,R*=.5):(y=v,R=x.g,g*=.5)}}else if(!f())return null;return Math.abs(h.ay-o.ay)*Me>Fu?null:{steerDeg:h.x,ay:h.ay}}function fi(e,t,r,n,o){let a=fk(e,t,r,n.beta*se,n.steerDeg*se,n.ay*Me,Aa(e,o(n.steerDeg),r,t));return{...a,trimmed:!a.overturned,driving:!a.overturned}}function DE(e,t,r,n,o,a,s){let i=o.length;if(i<3)return null;let c=o[i-1],l=i-2;for(;l>1&&o[l].beta===c.beta;)l--;let u=o[l],m=Math.sign(c.beta-u.beta);if(m===0||!u.driving)return null;let d=gk(e,t,r,a,s),p=d(u.beta,u),f=d(c.beta,c);if(!p||!f)return null;let h=n*f.steerDeg>=n*p.steerDeg,b=h?p:f,g=h?f:p,y=h?m:-m,R=null;for(let x=hk;Math.abs(g.beta-c.beta)<=Au;x*=1.5){let M=d(g.beta+y*x);if(!M)return null;if(n*M.steerDeg<=n*g.steerDeg){R=M;break}b=g,g=M}if(!R)return null;let k=yk(d,n,b,g,R);if(!k)return null;let v=fi(e,t,r,k,a);return!v.trimmed||Math.abs(v.beta-c.beta)>Au||Math.abs(v.ay-c.ay)*Me>Fu?null:{state:v,sb:m}}function gk(e,t,r,n,o){let a=[];return(s,i)=>{if(!i){i=a[0];for(let u of a)Math.abs(u.beta-s)<Math.abs(i.beta-s)&&(i=u)}let c=bk(e,t,r,s,i,n,o);if(!c)return null;let l={beta:s,...c};return a.push(l),l}}function EE(e,t){let r=Math.abs(t.beta-e.beta);return r>wE&&r>CE*Math.abs(t.steerDeg-e.steerDeg)}function IE(e,t,r,n,o,a,s,i){let c=o.length;if(c<2)return null;let l=o[c-1],u=c-2;for(;u>0&&o[u].beta===l.beta;)u--;let m=o[u],d=Math.sign(a.beta-l.beta);if(d===0||Math.sign(l.beta-m.beta)!==d||!m.driving)return null;let p=gk(e,t,r,s,i),f=p(m.beta,m),h=p(l.beta,l);if(!f||!h||n*h.steerDeg<n*f.steerDeg)return null;let b=f,g=h,y=null;for(let R=hk;d*(a.beta-g.beta)>0;R=Math.min(FE,1.5*R)){let k=p(d*(a.beta-g.beta)>R?g.beta+d*R:a.beta);if(!k)return null;let v=n*k.steerDeg<=n*g.steerDeg;if(!y)v&&(y=[b,g,k]);else if(!v){let x=yk(p,n,...y);if(!x)return null;let M=fi(e,t,r,x,s);return M.trimmed?{state:M,sb:d}:null}b=g,g=k}return null}function yk(e,t,r,n,o){let a=p=>-t*p.steerDeg,s=Math.min(r.beta,o.beta),i=Math.max(r.beta,o.beta),c=n,l=a(r)<=a(o)?r:o,u=l===r?o:r,m=i-s,d=0;for(let p=0;p<100;p++){let f=.5*(s+i);if(Math.abs(c.beta-f)<=2*Kr-.5*(i-s))break;let h=!0;if(Math.abs(m)>Kr){let g=(c.beta-l.beta)*(a(c)-a(u)),y=(c.beta-u.beta)*(a(c)-a(l)),R=(c.beta-u.beta)*y-(c.beta-l.beta)*g;y=2*(y-g),y>0&&(R=-R),y=Math.abs(y);let k=m;if(m=d,Math.abs(R)<Math.abs(.5*y*k)&&R>y*(s-c.beta)&&R<y*(i-c.beta)){d=R/y;let v=c.beta+d;(v-s<2*Kr||i-v<2*Kr)&&(d=f>=c.beta?Kr:-Kr),h=!1}}h&&(m=c.beta>=f?s-c.beta:i-c.beta,d=Rk*m);let b=e(Math.abs(d)>=Kr?c.beta+d:c.beta+(d>=0?Kr:-Kr));if(!b)return null;a(b)<=a(c)?(b.beta>=c.beta?s=c.beta:i=c.beta,u=l,l=c,c=b):(b.beta<c.beta?s=b.beta:i=b.beta,a(b)<=a(l)||l===c?(u=l,l=b):(a(b)<=a(u)||u===c||u===l)&&(u=b))}return c}function mb(e,t,r,n,o,a,s=[n.stall]){let i=typeof o.op=="function"?o.op:()=>o.op,c=o.yawDemandCn??0,l="steerDeg"in a?b=>Math.abs(b.steerDeg)-Math.abs(a.steerDeg):b=>Math.abs(b.ay)-Math.abs(a.ayG),u=[...s,n.state].map(b=>({beta:b.beta,steerDeg:b.steerDeg,ay:b.ay})),m=u[0],d=u[u.length-1],p=l(m),f=l(d);if(p>0||f<0)return null;if(f===0)return fi(e,t,r,d,i);let h=m;for(let b=0;b<60&&Math.abs(d.beta-m.beta)>1e-9;b++){let g=(m.beta*f-d.beta*p)/(f-p),y=u[0];for(let x of u)Math.abs(x.beta-g)<Math.abs(y.beta-g)&&(y=x);let R=bk(e,t,r,g,y,i,c);if(!R)return null;let k={beta:g,...R};u.push(k),h=k;let v=l(k);if(Math.abs(v)<("steerDeg"in a?PE:LE))break;v<0?(m=k,p=v,f*=.5):(d=k,f=v,p*=.5)}return fi(e,t,r,h,i)}function _E(e,t,r,n,o,a){let s=Math.abs(o),{states:i}=n;if(s>Math.abs(i[i.length-1].steerDeg)+1e-9)return null;let c=0;for(;c<i.length-1&&Math.abs(i[c+1].steerDeg)<=s;)c++;let l=i[c];if(Math.abs(Math.abs(l.steerDeg)-s)<1e-9)return l;if(n.fold&&l===n.fold.stall)return mb(e,t,r,n.fold,a,{steerDeg:o});let u=typeof a.op=="function"?a.op(o):a.op,m=Zn(e,t,r,o,l,u,a.yawDemandCn??0);return m.driving?m:null}function NE(e,t,r,n,o,a){if(!n.trimmed)return!1;let s=n.steerDeg<0?-1:1,{states:i}=eo(e,t,r,{direction:s,op:o,yawDemandCn:a}),c=Math.abs(n.steerDeg);if(c>Math.abs(i[i.length-1].steerDeg)+1e-9)return!1;let l=0;for(;l<i.length-2&&Math.abs(i[l+1].steerDeg)<c;)l++;let u=i[l],m=i[Math.min(l+1,i.length-1)],d=Math.abs(m.steerDeg)-Math.abs(u.steerDeg),p=d>0?Math.min(1,Math.max(0,(c-Math.abs(u.steerDeg))/d)):0,f=u.beta+p*(m.beta-u.beta),h=u.ay+p*(m.ay-u.ay);return Math.abs(n.beta-f)<=1&&Math.abs(n.ay-h)<=.05}function Rn(e,t,r,n,o){let a=Math.max(8,r),s=n>=0?1:-1,i=Math.abs(n),c=(b,g)=>Hr(e,t,a,s*b,g,o),l=eo(e,t,a,{direction:s,op:o}),{fold:u}=l;if(u&&Math.abs(u.state.steerDeg)<=Sa){if(i>Math.abs(u.state.ay))return mk(e,t,a,s,i,o);if(i>Math.abs(u.stall.ay)){let b=mb(e,t,a,u,{direction:s,op:o},{ayG:i});if(b)return b}}let m=l.states.filter(b=>Math.abs(b.steerDeg)<=Sa),d=m[m.length-1],p=l.states.length>m.length;p&&Math.abs(d.steerDeg)<Sa&&m.push(c(Sa,d));let f=m.findIndex(b=>Math.abs(b.ay)>=i);if(f===0)return Hr(e,t,a,0,void 0,o);if(f>0)return uk(m[f-1],m[f],i,c);let h=xk(m,c,void 0,p||l.foldDeg===null);return h.ay>=i?uk(h.below,h.state,i,c):l.foldDeg!==null&&l.foldDeg<Sa?mk(e,t,a,s,i,o):h.state}var Sa=20;function uk(e,t,r,n){let o={steer:Math.abs(e.steerDeg),f:Math.abs(e.ay)-r},a={steer:Math.abs(t.steerDeg),f:Math.abs(t.ay)-r},s=a.f===o.f?.5:-o.f/(a.f-o.f),i={ay:e.ay+s*(t.ay-e.ay),beta:e.beta+s*(t.beta-e.beta),driving:e.driving},c=0,l=null,u=1/0;for(let m=0;m<60;m++){let d=a.f===o.f?.5*(o.steer+a.steer):o.steer-o.f*(a.steer-o.steer)/(a.f-o.f),p=n(d,i),f=Math.abs(p.ay)-r;if(Math.abs(f)<u&&(l=p,u=Math.abs(f)),Math.abs(f)<=OE||a.steer-o.steer<=VE)break;f<0?(o={steer:d,f},c===-1&&(a.f*=.5),c=-1):(a={steer:d,f},c===1&&(o.f*=.5),c=1)}return l}var OE=1e-9,VE=1e-7;function xk(e,t,r,n=!1){let o=r??0;if(r===void 0)for(let x=1;x<e.length;x++)Math.abs(e[x].ay)>Math.abs(e[o].ay)&&(o=x);let a=e[Math.max(0,o-1)],s=Math.abs(e[o].steerDeg),i=BE/4,c,l,u,m,d,p,f,h,b=null,g;if(o>0&&o<e.length-1){let x=e[o+1];g=w=>{if(w<s)return t(w,a);let C=t(w,e[o]);return C.ay===e[o].ay?t(w,a):C},c=Math.abs(a.steerDeg),l=Math.abs(x.steerDeg),u=s,m=-Math.abs(e[o].ay);let[M,A]=Math.abs(a.ay)>=Math.abs(x.ay)?[a,x]:[x,a];d=Math.abs(M.steerDeg),p=-Math.abs(M.ay),f=Math.abs(A.steerDeg),h=-Math.abs(A.ay)}else{let x=Math.abs(e[o].lockDeg??e[o].steerDeg),M=x-$E,A=o>0&&n&&M>Math.abs(a.steerDeg)?t(M,a):null;if(!A||Math.abs(A.ay)<=Math.abs(e[o].ay)){let w=t(s,a);return{state:w,below:a,ay:Math.abs(w.ay)}}g=w=>t(w,a),c=Math.abs(a.steerDeg),l=x,u=M,m=-Math.abs(A.ay),b=A,d=x,p=-Math.abs(e[o].ay),f=c,h=-Math.abs(a.ay)}let y=l-c,R=0;for(let x=0;x<100;x++){let M=.5*(c+l);if(Math.abs(u-M)<=2*i-.5*(l-c))break;let A=!0;if(Math.abs(y)>i){let F=(u-d)*(m-h),S=(u-f)*(m-p),P=(u-f)*S-(u-d)*F;S=2*(S-F),S>0&&(P=-P),S=Math.abs(S);let L=y;if(y=R,Math.abs(P)<Math.abs(.5*S*L)&&P>S*(c-u)&&P<S*(l-u)){R=P/S;let D=u+R;(D-c<2*i||l-D<2*i)&&(R=M>=u?i:-i),A=!1}}A&&(y=u>=M?c-u:l-u,R=Rk*y);let w=Math.abs(R)>=i?u+R:u+(R>=0?i:-i),C=g(w),T=-Math.abs(C.ay);T<=m?(w>=u?c=u:l=u,f=d,h=p,d=u,p=m,u=w,m=T,b=C):(w<u?c=w:l=w,T<=p||d===u?(f=d,h=p,d=w,p=T):(T<=h||f===u||f===d)&&(f=w,h=T))}let k=b??t(s,a),v=Math.abs(k.steerDeg)>s?e[o]:a;return{state:k,below:v,ay:Math.abs(k.ay)}}var BE=.001,$E=.01,Rk=(3-Math.sqrt(5))/2;function mk(e,t,r,n,o,a){let s=l=>Math.abs(Hr(e,t,r,n*l,void 0,a).ay),i=0,c=Sa;if(s(c)<o)return Hr(e,t,r,n*c,void 0,a);for(let l=0;l<28;l++){let u=.5*(i+c);s(u)<o?i=u:c=u}return Hr(e,t,r,n*.5*(i+c),void 0,a)}function pb(e,t,r,n,o){let a=Rn(e,t,r,n,o);return a.steering?Math.abs(a.steering.totalNm):NaN}function db(e,t,r,n,o){if(!Wn(e))return NaN;let a=n<0?-1:1,s=Math.abs(n),i=Rn(e,t,r,a*s,o);if(!i.steering)return NaN;let c=Math.abs(i.steerDeg);for(let l of[.05,.1,.2,.4]){let u=Math.max(0,c-l),m=c+l,d=Hr(e,t,r,a*u,void 0,o),p=Hr(e,t,r,a*m,void 0,o),f=d.steering?Math.abs(d.steering.totalNm):NaN,h=p.steering?Math.abs(p.steering.totalNm):NaN,b=Math.abs(p.ay)-Math.abs(d.ay);if(Number.isFinite(f)&&Number.isFinite(h)&&b>=.01||l===.4&&Number.isFinite(f)&&Number.isFinite(h)&&b>.001)return(h-f)/b}return NaN}function ab(e,t,r,n,o,a){let s=Math.max(8,r),i=Lt(e,t,s,n*se,o*se,void 0,Aa(e,a,s,t));return{ay:i.ay,cn:i.cn}}function fb(e,t,r,n,o){let a=Math.max(8,r),s=Rn(e,t,a,n,o),i=.5,c=ab(e,t,a,s.beta+i,s.steerDeg,o).cn,l=ab(e,t,a,s.beta-i,s.steerDeg,o).cn;return(c-l)/(2*i*se)*e.massTotal*Me*(e.wheelbase/1e3)}function hb(e,t,r,n){let o=Math.max(8,r),{branch:a,opts:s}=GE(e,t,o,n);return vk(e,t,o,a,s)}function GE(e,t,r,n){if(!e.tv?.enabled){let s=n?{op:n}:{};return{branch:eo(e,t,r,s),opts:s}}let o=sb(e,t,r),a={op:s=>{let i=ib(e,r,s,o);return i===0?n:{axG:n?.axG??0,driveFrontFrac:n?.driveFrontFrac,tvRearDiffN:i}}};return{branch:eo(e,t,r,a),opts:a}}function vk(e,t,r,n,o){let a=typeof o.op=="function"?o.op:()=>o.op,s=o.yawDemandCn??0;if(n.fold&&n.peak===n.fold.state)return fi(e,t,r,n.peak,a);let i=(l,u)=>Zn(e,t,r,l,u,a(l),s),c=n.states[0].driving||!n.peak.driving?n.states:n.states.slice(1);return xk(c,i,c.indexOf(n.peak),n.foldDeg===null).state}function bb(e,t,r,n={}){let o=n.radius!==void 0&&n.radius>0&&Number.isFinite(n.radius)?n.radius:void 0,a=o===void 0?Math.max(8,r):Math.max(8,Math.sqrt(Me*o)),s=(n.betaMaxDeg??10)*se,i=(n.deltaMaxDeg??10)*se,[c,l]=n.betaRangeDeg?[n.betaRangeDeg[0]*se,n.betaRangeDeg[1]*se]:[-s,s],[u,m]=n.deltaRangeDeg?[n.deltaRangeDeg[0]*se,n.deltaRangeDeg[1]*se]:[-i,i],{lf:d,lr:p}=ob(e),f=o===void 0?0:p/o,h=o===void 0?0:(d+p)/o,b=n.nLines??9,g=n.nPts??21,y=n.steering!==!1&&Wn(e),R=y?pn(ye(t,"front").model):void 0,k=(E,N,B,V)=>B===1?E:E+(N-E)*V/(B-1),v=e.tv?.enabled?sb(e,t,a):0,x=E=>{let N=ib(e,a,E/se,v);return!n.axG&&N===0?null:Aa(e,{axG:n.axG??0,driveFrontFrac:n.driveFrontFrac,tvRearDiffN:N},a,t)},{lf:M,lr:A}=ob(e),w=n.reserves?hi(t,e.massTotal*Me*1.2):null,C=E=>w?Pr(w,{FL:E.FL,FR:E.FR,RL:E.RL,RR:E.RR},{lf:M,lr:A}):null,T=[],F={ay:[],cn:[]},S=0;for(let E=0;E<b;E++){let N=k(u,m,b,E),B=x(N),V=[],G=[],K=[],Y=[],j=w?{stabil:[],agil:[]}:void 0,Z=y?ok():void 0,ne;for(let W=0;W<g;W++){let J=k(c,l,g,W),re=Lt(e,t,a,J,N,ne,B,o);if(ne=Number.isFinite(re.ay)?re.ay*Me:void 0,V.push(re.ay),G.push(re.cn),K.push(J/se),Y.push(N/se),j){let pe=C(re.wheels);j.stabil.push(pe.stabil),j.agil.push(pe.agil)}Z&&ak(Z,nk(e,t,N,re.wheels)),Math.abs(re.ay)>S&&(S=Math.abs(re.ay))}T.push({label:`\u03B4 ${(N/se).toFixed(0)}\xB0`,ay:V,cn:G,betaDeg:K,deltaDeg:Y,reserve:j,steering:Z});let te=null,fe=1/0;for(let W=1;W<G.length;W++){if(!Number.isFinite(G[W-1])||!Number.isFinite(G[W])||G[W-1]!==0&&G[W-1]<0==G[W]<0)continue;let J=G[W-1]===G[W]?0:G[W-1]/(G[W-1]-G[W]),re=V[W-1]+J*(V[W]-V[W-1]);if(o===void 0&&N!==0&&Math.abs(re)>=.05&&Math.sign(re)!==Math.sign(N))continue;let pe=Math.abs(K[W-1]+J*(K[W]-K[W-1])-f/se);pe<fe&&(fe=pe,te=re)}te!==null&&(F.ay.push(te),F.cn.push(0))}let P=[];for(let E=0;E<b;E++){let N=k(c,l,b,E),B=[],V=[],G=[],K=[],Y=w?{stabil:[],agil:[]}:void 0,j=y?ok():void 0,Z;for(let ne=0;ne<g;ne++){let te=k(u,m,g,ne),fe=Lt(e,t,a,N,te,Z,x(te),o);if(Z=Number.isFinite(fe.ay)?fe.ay*Me:void 0,B.push(fe.ay),V.push(fe.cn),G.push(N/se),K.push(te/se),Y){let W=C(fe.wheels);Y.stabil.push(W.stabil),Y.agil.push(W.agil)}j&&ak(j,nk(e,t,te,fe.wheels))}P.push({label:`\u03B2 ${(N/se).toFixed(0)}\xB0`,ay:B,cn:V,betaDeg:G,deltaDeg:K,reserve:Y,steering:j})}let L=.5*se,D=x(h),I,O;if(o===void 0)I=(Lt(e,t,a,f+L,h,void 0,D,o).cn-Lt(e,t,a,f-L,h,void 0,D,o).cn)/(2*L),O=(Lt(e,t,a,f,h+L,void 0,x(h+L),o).cn-Lt(e,t,a,f,h-L,void 0,x(h-L),o).cn)/(2*L);else{let E=(V,G)=>Lt(e,t,a,V,G,void 0,x(G),o).cn,N=(V,G,K)=>Number.isFinite(V)?(-3*V+4*G-K)/(2*L):(K-G)/L,B=E(f,h);I=-N(B,E(f-L,h),E(f-2*L,h)),O=N(B,E(f,h+L),E(f,h+2*L))}let _=0;if(D&&D.axG){let E=Lt(e,t,a,f,h,void 0,D,o),N=0;for(let B of xn)N+=E.wheels[B].fxShort;_=N/Math.abs(e.massTotal*D.axG*Me)}let z=F.ay.reduce((E,N)=>Math.max(E,Math.abs(N)),0);return{isoBeta:P,isoDelta:T,trim:F,maxAy:S,stability:I,control:O,speed:o===void 0?a:Math.sqrt(z*Me*o),...o!==void 0?{radius:o}:{},axG:D?.axG??0,axShortfall:_,...R?{steeringAligningSource:R}:{}}}function kk(e,t){return to(e,t*se).atLock}function KE(e,t,r,n,o=Gr(e,t,r)){let a=r,s=e.massTotal,i=xn.filter(g=>qt(g)?n.drivenFront:n.drivenRear),c=o.peakAt,l={front:n.drivenFront?Kt(e,"front",1):void 0,rear:n.drivenRear?Kt(e,"rear",1):void 0},u=new Map,m=(g,y)=>{let R=`${g}:${y}`,k=u.get(R);if(k===void 0){let v=Math.max(1,y*pi);k=Ct(ye(t,g),v,0,!1,c(g,v)),u.set(R,k)}return k},d=(g,y)=>y>0?mi(y,R=>m(g,R)):0,p=(g,y,R,k)=>{let v=ye(t,g),x=D=>{let I=Math.max(0,R[D]),O=c(g,I);return{Fz:I,a:d(g,I),b:O.fyPeak,slide:0,cap:_=>I>0?Ct(v,I,_,!1,O):0}},[M,A]=g==="front"?["FL","FR"]:["RL","RR"],w=x(M),C=x(A),T=k[M]*w.b,F=k[A]*C.b,S=w.cap(T)+C.cap(F),P=ui(w,C,T+F,y,S);return{l:M,r:A,full:P,asHeld:()=>({axle:g,strong:w.cap(T)>=C.cap(F)?M:A,full:P,open:ui(w,C,T+F,Ra,S),sense:1})}},f=g=>({muX:y=>y>0?d(g,y)/y:0,muY:y=>y>0?c(g,y).fyPeak/y:0}),h={front:f("front"),rear:f("rear")},b=g=>({arms:{lf:e.wheelbase/1e3*(1-e.frontMassFrac),lr:e.wheelbase/1e3*e.frontMassFrac},halfTrack:{front:e.trackFront/2e3,rear:e.trackRear/2e3},ayDir:Math.sign(g)});return{limitAt:(g,y,R,k=0)=>{let v={FL:0,FR:0,RL:0,RR:0},x=Ce(e,g,0,a,0,y),M,A=P=>(M?.ax!==P&&(M={ax:P,loads:Ce(e,g,(P+k)/Me,a,0,y)}),M.loads),w=Pl(P=>ca(R,A(P),x,c).short,-k,1),C=R,T=P=>{let L=w.at(P);v=A(L),C=ca(R,v,x,c).util;let D=0,I=n.diffYaw?{fx:{FL:0,FR:0,RL:0,RR:0},axles:[]}:null;for(let O of i){let _=l[yn(O)];if(_){if(Su(O)){let B=p(yn(O),_,v,C);D+=B.full,I&&(I.fx[B.l]=I.fx[B.r]=B.full/2,I.axles.push(B.asHeld()))}continue}let z=Math.max(0,v[O]),E=c(yn(O),z),N=Ct(ye(t,yn(O)),z,C[O]*E.fyPeak,!1,E);D+=N,I&&(I.fx[O]=N)}if(I){let O={};for(let _ of xn){let z=Math.max(0,v[_]);O[_]={Fz:z,Fy:C[_]*c(yn(_),z).fyPeak,Fx:I.fx[_]}}for(let _ of I.axles)D+=ql(_,O,h,b(g))-_.full}return D/s},F=H1(T,-k,gn).fx,S=w.edge();return S!==void 0&&F>S&&(F=S,T(F)),{ax:F,loads:v}}}}var Mu=.05,pk=.001,dk=16,wu=8;function gb(e,t,r,n){let o=Math.max(wu,r),a=n.nSteer??7,s=e.tv?.enabled?sb(e,t,o,n.steerMaxDeg):0,i=E=>{let N=ib(e,o,E,s);return N===0?void 0:{axG:0,tvRearDiffN:N}},c=n.yawDemandCn??0,l={op:i,yawDemandCn:c,...n.steerMaxDeg!==void 0?{steerMaxDeg:n.steerMaxDeg}:{}},u=eo(e,t,o,l),m=E=>{let N={},B={};for(let V of xn)N[V]=E.wheels[V].slipDeg*se,B[V]=Math.min(1,E.wheels[V].gripUtil);return{steerDeg:E.steerDeg,ayMs:Math.max(0,E.ay*Me),ayG:E.ay,slip:N,util:B,scrub:E.ay>0?HE(E,e.massTotal):0}},d=null,p=E=>{if(d&&E===d.steerDeg)return m(d);let N=_E(e,t,o,u,E,l);if(N)return m(N);let B=u.states[0];for(let V of u.states)V.steerDeg<=E&&(B=V);return m(B)},f=u.peak.driving&&u.peak.ay>0?vk(e,t,o,u,l):null,h=f?Math.max(0,f.ay*Me):0,b=f?[...u.states.filter(E=>E.steerDeg<f.steerDeg),f]:u.states,g=f?b.findIndex(E=>E.ay*Me>=.995*h):0,y=b[g].steerDeg,{fold:R}=u;if(f&&R&&u.peak===R.state){let E=.995*h/Me,N=u.states.indexOf(R.stall),B=N-1;for(;B>0&&u.states[B].beta===R.stall.beta;)B--;let V=Math.sign(R.stall.beta-u.states[B].beta),G=N;for(;G>0&&u.states[G].ay>=E&&Math.sign(u.states[G].beta-u.states[G-1].beta)!==-V;)G--;u.states[G].ay<E&&(d=mb(e,t,o,R,l,{ayG:E},u.states.slice(G,N+1)))}if(d)y=d.steerDeg;else if(g>0){let E=b[g-1].steerDeg,N=y;for(let B=0;B<8&&N-E>.001;B++){let V=.5*(E+N);p(V).ayMs>=.995*h?N=V:E=V}y=N}let k=[];for(let E=0;E<(h>0?a:1);E++){let N=E/(a-1);k.push(p(y*(N+Math.sin(Math.PI/2*N))/2))}k[0].ayMs=0;let v=[],x=[],M=[],A=[],w=Gr(e,t,o,void 0,n.diffYaw===!0),C=KE(e,t,o,n,w),T=n.axDrag??0,F=E=>{let N=w.limitAt(E.ayMs/Me,E.steerDeg,E.util,T+E.scrub);return{axD:N.edge!==void 0&&N.edge>0?N.edge:N.ax,locked:N.axUnlocked-N.ax>Mu}},S=E=>C.limitAt(E.ayMs/Me,E.steerDeg,E.util,T+E.scrub).ax,P=k.map(E=>({p:E,axA:S(E),...F(E)})),L=[];for(let E=0;E+1<P.length;E++){let N=P[E],B=P[E+1],V=[];N.locked!==B.locked?V.push({read:F,past:G=>G.locked===B.locked,braking:!0}):(B.axA>N.axA+Mu&&V.push({read:G=>({axA:S(G)}),past:G=>(G.axA??-1/0)>N.axA}),-B.axD>-N.axD+Mu&&V.push({read:F,past:G=>-(G.axD??0)>-N.axD}));for(let{read:G,past:K,braking:Y}of V){let j=N.p.steerDeg,Z=B.p.steerDeg,ne=null,te=N.axD,fe=B.axD;for(let W=0;W<dk&&Z-j>pk&&!(Y&&Math.abs(fe-te)<=Mu);W++){let J=.5*(j+Z),re=p(J),pe=G(re);K(pe)?(Z=J,ne={p:re,r:pe},fe=pe.axD??fe):(j=J,te=pe.axD??te)}if(ne){let{p:W,r:J}=ne,re=J.axD!==void 0&&J.locked!==void 0?{axD:J.axD,locked:J.locked}:F(W);L.push({p:W,axA:J.axA??S(W),...re})}}}P.push(...L),P.sort((E,N)=>E.p.steerDeg-N.p.steerDeg);let D=E=>E.axA+T+E.p.scrub,I=.001*Math.max(1,k[k.length-1].ayMs),O=[];for(let E=0;E+1<P.length;E++){let N=P[E],B=P[E+1];if(!(D(N)>=0&&D(B)<0))continue;let V=N.p.steerDeg,G=B.p.steerDeg,K=null,Y=null;for(let Z=0;Z<dk&&G-V>pk;Z++){let ne=.5*(V+G),te=p(ne);D({p:te,axA:S(te)})>=0?(V=ne,K=te):(G=ne,Y=te)}let j=K??Y;j&&j.ayMs>N.p.ayMs&&j.ayMs<B.p.ayMs&&O.push({p:j,axA:-(T+j.scrub),steady:!0,...F(j)})}P.push(...O),P.sort((E,N)=>E.p.steerDeg-N.p.steerDeg);let _=!1;for(let{p:E,axA:N,axD:B,steady:V}of P){let G=v.length-1,K=G>=0&&(V||_?!(E.ayMs>v[G]):E.ayMs-v[G]<I);_=V===!0&&!K,K?(x[G]=Math.max(x[G],N),M[G]=Math.min(M[G],B)):(v.push(E.ayMs),x.push(N),M.push(B),A.push(E.scrub))}for(let E=v.length-2;E>=0;E--)x[E]=Math.max(x[E],x[E+1]),M[E]=Math.min(M[E],M[E+1]);return{ayMax:v[v.length-1],ay:v,axAccel:x,axDecel:M,axScrub:A,rollover:u.rollover,atLock:f!==null&&kk(e,f.steerDeg)}}function HE(e,t){let r=e.beta*se,n=0;for(let o of xn){let a=e.wheels[o],s=a.steerDeg*se-r;n+=a.Fx*(Math.cos(s)-1)-a.Fy*Math.sin(s)}return n/t}var l9=Math.PI/180,u9={speeds:Array.from({length:23},(e,t)=>8+t),steerMaxDeg:14,steerSteps:29};function Sk(e=150,t=300,r=18,n=25){return(o,a,s)=>{let i=Math.min(1,Math.max(0,(o-r)/(n-r))),c=s>0?Math.min(1,a/s):0;return(e+i*(t-e))*c}}var Fa={enabled:!1,kp:3e3,ffLow:150,ffHigh:300,vLow:18,vHigh:25},Mk=e=>Sk(e.ffLow,e.ffHigh,e.vLow,e.vHigh);var pr={power_limit_kw:{value:0,label:"battery power limit (0 = none)",unit:"kW"},v_limit_endurance:{value:0,label:"endurance speed limit (0 = none)",unit:"km/h"},endurance_reserve:{value:0,label:"endurance energy reserve (0 = flat out)",unit:"%"},grip_scale:{value:1,label:"grip scale (rig \u2192 road)",unit:"-"},stiffness_scale:{value:1,label:"stiffness scale (rig \u2192 road)",unit:"-"},camber_front_deg:{value:0,label:"static camber front (\u2212 top in)",unit:"\xB0"},camber_rear_deg:{value:0,label:"static camber rear (\u2212 top in)",unit:"\xB0"},cg_height:{value:300,label:"CG height",unit:"mm"},tire_vertical_rate:{value:100,label:"tyre vertical rate",unit:"N/mm"},tire_vertical_damping:{value:0,label:"tyre vertical damping",unit:"N\xB7s/mm"},arb_front:{value:20,label:"ARB front (@wheel)",unit:"N/mm"},arb_rear:{value:15,label:"ARB rear (@wheel)",unit:"N/mm"},heave_spring_front:{value:0,label:"Heave spring front (@wheel)",unit:"N/mm"},heave_spring_rear:{value:0,label:"Heave spring rear (@wheel)",unit:"N/mm"},unsprung_mass:{value:8,label:"unsprung mass/corner",unit:"kg"},brake_balance:{value:.6,label:"brake balance (front)",unit:"-"},damper_front:{value:2.5,label:"damper front",unit:"N\xB7s/mm"},damper_rear:{value:2.5,label:"damper rear",unit:"N\xB7s/mm"},cop_long:{value:.5,label:"CoP aft of front",unit:"\xB7wb"},cop_height:{value:300,label:"CoP height",unit:"mm"},ride_height_front:{value:30,label:"static ride height front (laden)",unit:"mm"},ride_height_rear:{value:35,label:"static ride height rear (laden)",unit:"mm"},I_yaw:{value:295,label:"yaw inertia Izz",unit:"kg\xB7m\xB2"},I_roll:{value:95,label:"roll inertia Ixx",unit:"kg\xB7m\xB2"},I_pitch:{value:380,label:"pitch inertia Iyy",unit:"kg\xB7m\xB2"},I_wheel:{value:0,label:"rotating inertia per wheel",unit:"kg\xB7m\xB2"},I_rotor:{value:0,label:"driveline inertia at the motor",unit:"kg\xB7m\xB2"},ackermann_pct:{value:50,label:"Ackermann",unit:"%"},toe_front_deg:{value:0,label:"static toe front (+ in)",unit:"\xB0"},toe_rear_deg:{value:0,label:"static toe rear (+ in)",unit:"\xB0"},spring_front:{value:35,label:"spring front (@spring)",unit:"N/mm"},spring_rear:{value:40,label:"spring rear (@spring)",unit:"N/mm"},mr_front:{value:1,label:"motion ratio front",unit:"-"},mr_rear:{value:1,label:"motion ratio rear",unit:"-"},track_front:{value:1200,label:"track front",unit:"mm"},track_rear:{value:1200,label:"track rear",unit:"mm"},wheelbase:{value:1535,label:"wheelbase",unit:"mm"},rc_front:{value:30,label:"roll centre front",unit:"mm"},rc_rear:{value:40,label:"roll centre rear",unit:"mm"},tv_enabled:{value:0,label:"torque vectoring",unit:"0/1"},tv_kp:{value:3e3,label:"TV yaw-rate gain",unit:"N per rad/s"},tv_ff_low:{value:150,label:"TV feedforward, low speed",unit:"N"},tv_ff_high:{value:300,label:"TV feedforward, high speed",unit:"N"},tv_v_low:{value:18,label:"TV feedforward ramp start",unit:"m/s"},tv_v_high:{value:25,label:"TV feedforward ramp end",unit:"m/s"}},zE=["k_yaw","k_roll","k_pitch"];function gi(e){for(let t of zE)delete e[t];for(let t of Object.keys(pr)){let r=e[t];if(!r){e[t]={...pr[t]};continue}e[t]={...r,label:pr[t].label,unit:pr[t].unit}}return e}function Q(e,t){return e[t]?.value??pr[t].value}function Cu(e){let t=(r,n)=>e[r]?.value??n;return{enabled:t("tv_enabled",0)>=.5,kp:t("tv_kp",Fa.kp),ffLow:t("tv_ff_low",Fa.ffLow),ffHigh:t("tv_ff_high",Fa.ffHigh),vLow:t("tv_v_low",Fa.vLow),vHigh:t("tv_v_high",Fa.vHigh)}}var Ak=[10,25,50,100,200,300];function yb(e,t,r,n,o){let s=Ak.map(i=>Math.round(i<=25?r*i:r*25+n*(i-25)));return{id:e,label:t,speedMmS:[...Ak],reboundN:s,bumpN:s.map(i=>Math.round(i*o))}}var Tu={name:"Generic FS damper",curves:[yb("c1","Soft",1.6,1,.65),yb("c2","Medium",3,1.6,.65),yb("c3","Firm",8,2.4,.65)]};function Pu(e){let t=e.curves.length;return t>0?e.curves[Math.floor((t-1)/2)].id:""}var vn=25;function wa(e,t){let r=e.speedMmS,n=e.forceN,o=Math.min(r.length,n.length);if(o===0||!(t>0))return 0;let a=0,s=0;for(let i=0;i<o;i++){let c=r[i],l=n[i];if(t<=c)return s+(l-s)*(t-a)/(c-a);if(i===o-1)return l+Math.max(0,(l-s)/(c-a))*(t-c);a=c,s=l}return 0}function Fk(e,t){return t>=0?wa(e.rebound,t):-wa(e.bump,-t)}function wk(e,t,r){return t*Fk(e,t*r)}var xb=(e,t)=>e.curves.find(r=>r.id===t);function yi(e,t){let r=xb(e,Pu(e)),n=(t&&xb(e,t.bump))??r,o=(t&&xb(e,t.rebound))??r;return{bump:{speedMmS:n?.speedMmS??[],forceN:n?.bumpN??[]},rebound:{speedMmS:o?.speedMmS??[],forceN:o?.reboundN??[]}}}var Lu=5e3;function xi(e,t){let r=t>0?t:1,n=[],o=[],a=e.bump.speedMmS.map(c=>c/r).filter(c=>c<Lu),s=e.rebound.speedMmS.map(c=>c/r).filter(c=>c<Lu),i=c=>{n.push(c),o.push(wk(e,r,c))};i(-Lu);for(let c=a.length-1;c>=0;c--)i(-a[c]);i(0);for(let c of s)i(c);return i(Lu),{kind:"map",input:"velocity",x:n,y:o}}var Rb=64;function Ri(e,t,r){let n=t>0?t:1,o=Math.max(r,1e-6),a=0;for(let s=0;s<Rb;s++){let i=Math.sin((s+.5)*Math.PI/Rb),c=n*o*i;a+=n*(wa(e.rebound,c)+wa(e.bump,c))*i}return a*(Math.PI/Rb)/(Math.PI*o)}function ro(e,t,r,n,o=e){let a=(c,l,u)=>{if(!c||c.curves.length===0)return;let m=yi(c,l);return{law:m,curve:xi(m,u),rate:Ri(m,u,vn)}},s=a(e,t?.front,r),i=a(o??e,t?.rear,n);return!s&&!i?null:{...s?{front:s}:{},...i?{rear:i}:{}}}var Ck=(e,t)=>({...e,y:e.y.map(r=>r*t)}),YE=e=>({...e,x:e.x.map(t=>-t).reverse(),y:e.y.map(t=>-t).reverse()});function vb(e,t,r){let n=Math.abs(r)>0?Math.abs(r):1,o=yi(e,t);return{law:o,curve:Ck(xi(o,n),.5),rate:Ri(o,n,vn)/2,mr:n,ratio:n,share:.5}}function kb(e,t,r,n,o){let a=n*(Math.abs(r)>0?Math.abs(r):1),s=yi(e,t),i=Ck(xi(s,a),1/n);return{law:s,curve:o?YE(i):i,rate:Ri(s,a,vn)/n,mr:a/n,ratio:a,share:1/n}}function vi(e,t){let r=e.damperModelIdRear?t(e.damperModelIdRear):void 0,n=e.heaveDamperModelId?t(e.heaveDamperModelId):void 0,o=e.rollDamperModelId?t(e.rollDamperModelId):void 0;return{...r?{damperModelRear:r}:{},...n?{heaveDamperModel:n}:{},...o?{rollDamperModel:o}:{}}}var Du=["front","rear","heaveFront","heaveRear","rollFront","rollRear"];function ki(e,t){if(t?.body){let{extended:n,stroke:o,...a}=e??{},{extended:s,stroke:i}=t.body;return{coilover:{...a,extended:s,...i!==void 0?{stroke:i}:{}},source:"part",part:t}}let r=e?.extended!==void 0&&e.extended>0;return{...e?{coilover:e}:{},source:r?"suspension":"none"}}function zr(e,t){if(typeof e=="number")return e;let{x:r,y:n}=e,o=r.length;if(o===0)return 0;if(o===1||t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}function Si(e){return e.kind==="coil"?2:1}function Mi(e){let t=Math.max(0,e.od),r=Math.max(0,Math.min(e.id,t));return Math.PI*(t**4-r**4)/32}function Pk(e){return Mi(e)/2}function Lk(e){let t=Math.max(0,e.width),r=Math.max(0,e.thickness),n=t*r**3/12,o=r*t**3/12,a=e.angleDeg*Math.PI/180;return n*Math.cos(a)**2+o*Math.sin(a)**2}function Tk(e){let t=0;for(let r of e)if(Number.isFinite(r)){if(r<=0)return 0;t+=1/r}return t>0?1/t:1/0}function WE(e,t,r){let n=Math.min(e.length,t.length);if(n<2)return 0;let o=Math.abs(r);if(o<=e[0])return(t[1]-t[0])/(e[1]-e[0]);for(let a=1;a<n;a++)if(o<=e[a])return(t[a]-t[a-1])/(e[a]-e[a-1]);return(t[n-1]-t[n-2])/(e[n-1]-e[n-2])}function Ai(e,t=0){let r={rateAtLink:0,contributions:{},torsional:0};switch(e.kind){case"none":return r;case"ubar":{let n=e.armLength;if(n<=0||e.barLength<=0)return r;let o=e.G*Mi(e.section)/e.barLength,a=2*o/(n*n),s=Pk(e.armSection??e.section),i=3*e.E*s/n**3,c=e.dropLinkRate??1/0;return{rateAtLink:Tk([a,i,c]),contributions:{barTwist:a,armBending:i,dropLink:c},torsional:o}}case"blade":{let n=e.armLength;if(n<=0||e.barLength<=0)return r;let o=e.G*Mi(e.section)/e.barLength,a=2*o/(n*n),s=3*e.E*Lk(e.blade)/n**3,i=e.dropLinkRate??1/0;return{rateAtLink:Tk([a,s,i]),contributions:{barTwist:a,armBending:s,dropLink:i},torsional:o}}case"torsionTube":{let n=e.leverArm;if(n<=0||e.length<=0)return r;let o=e.G*Mi(e.section)/e.length,a=2*o/(n*n);return{rateAtLink:a,contributions:{barTwist:a},torsional:o}}case"coil":{let n=zr(e.rate,2*Math.abs(t)),o=2*Math.max(0,n);return{rateAtLink:o,contributions:{spring:o},torsional:0}}case"direct":return{rateAtLink:e.wheelRate,contributions:{},torsional:0};case"tabulated":{let n=WE(e.linkTravel,e.force,t);return{rateAtLink:Math.max(0,n),contributions:{},torsional:0}}}}function Eu(e,t,r=0){if(e.kind==="none")return{wheelRate:0,motionRatio:0,rateAtLink:0};if(e.kind==="direct")return{wheelRate:Math.max(0,e.wheelRate),motionRatio:1,rateAtLink:0};let n=t?of(t,r):1,o=t?af(t,r):0,a=Ai(e,o).rateAtLink;return{wheelRate:Math.max(0,a*n*n),motionRatio:n,rateAtLink:a}}function Fi(e,t){let r=e.damper??0;return!r||e.design.kind==="none"?0:Si(e.design)*r*t*t}var jE=150;function UE(e){return X(e,[0,-.5,1])<-1e-9?U(e,-1):e}function Dk(e){let t=e.hardpoints,r=H(t.rockerPivotB,t.rockerPivotA),n=ee(t.rockerPivotA,U(H(t.rockerToDamper,t.rockerPivotA),.6)),o=UE(q(ae(r,H(t.rockerToDamper,t.rockerPivotA))));return{outer:n,inner:ee(n,U(o,jE)),attach:"rocker"}}function Dt(e,t){let r={};for(let o of ar)r[o]=tt(_e(e,o));let n={vehicle:e,ctx:r};return t&&(n.kc=Sl(n,t)),n}function XE(e,t,r,n){let o=e.corner.hardpoints,a=Xo(e.rocker,t.points.rockerAngle),s=i=>wt(i,r);return{ucaFront:s(o.ucaFront),ucaRear:s(o.ucaRear),lcaFront:s(o.lcaFront),lcaRear:s(o.lcaRear),tieInner:s(Vn(e.inv,t.steer)),rockerPivotA:s(o.rockerPivotA),rockerPivotB:s(o.rockerPivotB),damperChassis:s(e.inv.strut?t.points.uprightUpper:o.damperChassis),uprightUpper:s(t.points.uprightUpper),uprightLower:s(t.points.uprightLower),tieOuter:s(t.points.tieOuter),wheelCenter:s(t.points.wheelCenter),pushrodOuter:s(t.points.pushrodOuter),contactPatch:s(t.points.contactPatch),kingpinGround:s(t.points.kingpinGround),kingpinAtHub:s(t.points.kingpinAtHub),rockerToPushrod:s(a.pushrod),rockerToDamper:s(a.damper),spinAxis:wr(t.points.spinAxis,r),direct:e.corner.config.actuation==="direct",decoupled:e.corner.config.actuation==="decoupled",mcpherson:e.inv.strut!==void 0,loadedRadius:n.loadedRadius,tyreDeflection:n.tyreDeflection,load:n.load,lifted:n.lifted,clearance:n.clearance??0,contactLength:n.contactLength}}function Iu(e,t,r,n){let o=Qe(t,e.vehicle.config),a=o.isFront?o.sideSign*n:0,s;try{s=mt(ge(e.ctx[t],r,a))}catch{return null}if(!s)return null;let i=_e(e.vehicle,t).config.loadedRadius,c=XE(e.ctx[t],s,o,{loadedRadius:i,tyreDeflection:0,load:NaN,lifted:!1,contactLength:0});return c.wheelCenter.every(Number.isFinite)?{id:t,placement:o,solved:!0,state:s,geometry:c}:null}var _u=.5;function qE(e,t){let r=([i,c,l])=>{let u=q(H(c,i)),m=H(l,i),d=q(H(m,U(u,X(m,u))));return[u,d,ae(u,d)]},n=r(e),o=r(t),a=[0,1,2].map(i=>[0,1,2].map(c=>o[0][i]*n[0][c]+o[1][i]*n[1][c]+o[2][i]*n[2][c]));return{rot:a,move:i=>{let c=H(i,e[0]);return ee(t[0],[0,1,2].map(l=>a[l][0]*c[0]+a[l][1]*c[1]+a[l][2]*c[2]))}}}var Ek=e=>[(e[2][1]-e[1][2])/2,(e[0][2]-e[2][0])/2,(e[1][0]-e[0][1])/2];function Nu(e,t,r){let n=Qe(t,e.vehicle.config),o=e.ctx[t],a=r.rigid?void 0:{loadedRadius:r.loadedRadius},s=r.state?null:ge(o,r.travel,r.steer,void 0,a),i=r.state??st(s),c=ge(o,r.travel+_u,r.steer,void 0,a),l=ge(o,r.travel-_u,r.steer,void 0,a),u=(s?s.ok:r.converged)&&c.ok&&l.ok,m=st(c),d=st(l),p=(C,T)=>wt(C.points[T],n),f=o.inv.strut?"pushrodOuter":"uprightUpper",h=p(i,f),b=p(i,"uprightLower"),g=C=>{let T=H(b,h);return Math.hypot(...ae(T,H(p(i,C),h)))/Math.hypot(...T)},y=g("tieOuter")>=g("wheelCenter")?"tieOuter":"wheelCenter",R=[h,b,p(i,y)],k=C=>qE(R,[p(C,f),p(C,"uprightLower"),p(C,y)]),v=k(m),x=k(d),M=Ek(v.rot),A=Ek(x.rot),w=[NaN,NaN,NaN];return{solved:u,state:i,at:C=>p(i,C),velocity:C=>u?U(H(v.move(C),x.move(C)),1/(2*_u)):w,omega:u?U(H(M,A),1/(2*_u)):w}}function Mb(e,t,r,n){let o=t[0]*-n[1]-t[1]*-n[0];if(Math.abs(o)<1e-9)return null;let a=r[0]-e[0],s=r[1]-e[1],i=(a*-n[1]-s*-n[0])/o;return[e[0]+i*t[0],e[1]+i*t[1]]}function Ik(e,t,r){let n=Nu(e,t,yt(e,r)[t]),o=n.at("contactPatch"),a=n.velocity(o);return{solved:n.solved,cp:[o[1],o[2]],vCp:[a[1],a[2]],wx:n.omega[0]}}function _k(e){let t=Math.hypot(e.vCp[0],e.vCp[1]);return Math.abs(e.wx)*1e9>t?[e.cp[0]-e.vCp[1]/e.wx,e.cp[1]+e.vCp[0]/e.wx]:null}function Nk(e,t){let r=Math.hypot(e.vCp[0],e.vCp[1]);if(!(r>1e-9))return null;let n=[-e.vCp[1]/r,e.vCp[0]/r],o=t?[t[0]-e.cp[0],t[1]-e.cp[1]]:[e.cp[0]>0?-1:1,0];return n[0]*o[0]+n[1]*o[1]<0?[-n[0],-n[1]]:n}function QE(e,t,r){return Math.abs(t[0]*(r[1]-e[1])-t[1]*(r[0]-e[0]))<=1e-6*Math.max(1,Math.hypot(r[0]-e[0],r[1]-e[1]))?[(e[0]+r[0])/2,(e[1]+r[1])/2]:null}var ZE=.1*Math.PI/180;function Ok(e,t,r,n,o){return Math.max(Math.hypot(e[0]-t[0],e[1]-t[1]),Math.hypot(e[0]-r[0],e[1]-r[1]))*ZE<=o*n}function Ou(e,t){return!e.valid||!e.cpLeft||!e.cpRight?!1:Ok([e.lateral,e.height],e.cpLeft,e.cpRight,e.sinAngle,t)}function wi(e){let t=(o,a,s)=>{let i=o&&a?[a[0]-o[0],a[1]-o[1]]:s;return!o||!i||!(Math.abs(i[0])>1e-9)?Number.NaN:o[1]-o[0]*i[1]/i[0]},r=t(e.cpLeft,e.icLeft,e.lineLeft),n=t(e.cpRight,e.icRight,e.lineRight);return Number.isFinite(r)&&Number.isFinite(n)?{left:r,right:n}:null}var JE=1;function Vk(e){let t=wi(e);if(!t||!e.cpLeft||!e.cpRight||Math.abs(t.left-t.right)>JE)return null;let r=(t.left+t.right)/2,n=e.cpRight[0]-e.cpLeft[0],o=e.cpRight[1]-e.cpLeft[1],a=Math.hypot(n,o)||1;return{height:r,heightAboveGround:(0-e.cpLeft[0])*(-o/a)+(r-e.cpLeft[1])*(n/a)}}function Ca(e){let t=(n,o,a)=>{if(!n)return Number.NaN;if(!o)return a?0:Number.NaN;let s=n[0]-o[0];return Math.abs(s)>1e-9?n[0]/s:Number.NaN},r=(t(e.cpLeft,e.icLeft,e.lineLeft)+t(e.cpRight,e.icRight,e.lineRight))/2;return e.valid&&Number.isFinite(r)?r:0}function dr(e,t,r){let n=r==="front"?"FL":"RL",o=r==="front"?"FR":"RR",a=Ik(e,n,t),s=Ik(e,o,t);if(!a.solved||!s.solved)return{height:0,lateral:0,heightAboveGround:0,lateralAlongGround:0,valid:!1,unsolved:!0,icLeft:null,icRight:null,lineLeft:null,lineRight:null,sinAngle:0,cpLeft:a.cp,cpRight:s.cp};let i=_k(a),c=_k(s),l=Nk(a,i),u=Nk(s,c),m={height:0,lateral:0,heightAboveGround:0,lateralAlongGround:0,valid:!1,icLeft:i,icRight:c,lineLeft:l,lineRight:u,sinAngle:0,cpLeft:a.cp,cpRight:s.cp};if(!l||!u)return m;let d=i?[i[0]-a.cp[0],i[1]-a.cp[1]]:l,p=c?[c[0]-s.cp[0],c[1]-s.cp[1]]:u,f=Math.hypot(d[0],d[1]),h=Math.hypot(p[0],p[1]),b=f>0&&h>0?Math.abs(d[0]*p[1]-d[1]*p[0])/(f*h):0,g=Mb(a.cp,d,s.cp,p)??QE(a.cp,l,s.cp);if(!g)return{...m,sinAngle:b};let y=s.cp[0]-a.cp[0],R=s.cp[1]-a.cp[1],k=Math.hypot(y,R)||1,v=y/k,x=R/k,M=(a.cp[0]+s.cp[0])/2,A=(a.cp[1]+s.cp[1])/2,w=(g[0]-a.cp[0])*-x+(g[1]-a.cp[1])*v,C=(g[0]-M)*v+(g[1]-A)*x;return{lateral:g[0],height:g[1],heightAboveGround:w,lateralAlongGround:C,valid:!0,icLeft:i,icRight:c,lineLeft:l,lineRight:u,sinAngle:b,cpLeft:a.cp,cpRight:s.cp}}function Yr(e,t){return{front:dr(e,t,"front"),rear:dr(e,t,"rear")}}function Vu(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function eI(e,t){return{camber:Vu(e.travel,e.camber,t),toe:Vu(e.travel,e.toe,t),motionRatio:Vu(e.travel,e.motionRatio,t),damperLen:e.damperLen?Vu(e.travel,e.damperLen,t):0}}var Bk=e=>eI(e,0).motionRatio;function Sb(e,t){if(e.kind!=="coil")return null;let r=t??e.motionRatio,n=zr(e.rate,0)*r*r/2;return n>0&&Number.isFinite(n)?{rate:n,gap:Math.max(0,e.gap??0),bothWays:!!e.bothWays}:null}function Bu(e,t){if(e.kind==="none")return 0;if(e.kind==="tabulated"){let n=a=>tI(e,a);return(n(.5)-n(-.5))/(2*.5)/2}if((e.gap??0)>0)return 0;let r=t??e.motionRatio;return zr(e.rate,0)*r*r/2}function Ci(e,t){let r=e.damper??0;if(!r||e.design.kind==="none"||e.design.kind==="coil"&&(e.design.gap??0)>0)return 0;let n=t??(e.design.kind==="coil"?e.design.motionRatio:1);return r*n*n/2}function tI(e,t){let{travel:r,force:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}var Ab={kind:"coil",rate:120,motionRatio:.7,gap:5,bothWays:!1};var $k=new WeakMap;function Gu(e,t){let r=$k.get(e);r||(r=new Map,$k.set(e,r));let n=`${t.attach}|${t.outer.join(",")}|${JSON.stringify(t.mount??null)}`,o=r.get(n);if(o)return o;let a=Bn(e,t);return r.set(n,a),a}var rI=32,Ti=new Map,Gk=new WeakMap,nI=1;function oI(e){let t=Gk.get(e);return t===void 0&&(t=nI++,Gk.set(e,t)),t}function Fb(e,t){if(!t.linkage)return null;let r=mn(e,t.linkage,t.design.kind),n=`${oI(e)}|${r?"unit":"bar"}|${JSON.stringify(t.linkage)}`,o=Ti.get(n);if(o)return o;let a=ta(e,t.linkage,{kind:t.design.kind});return Ti.size>=rI&&Ti.delete(Ti.keys().next().value),Ti.set(n,a),a}function oo(e,t,r=0){let n=(o,a)=>{if(!(!o||o.design.kind==="none"))return Eu(o.design,Fb(a,o),r).wheelRate};return{front:n(t.arbFrontDesign,e.front),rear:n(t.arbRearDesign,e.rear)}}function Ta(e,t){let r=(n,o)=>{if(!n||n.design.kind==="none")return;let a=n.linkage?Gu(o,n.linkage).atDesign:void 0;return Bu(n.design,a)};return{front:r(t.heaveFrontDesign,e.front),rear:r(t.heaveRearDesign,e.rear)}}function Wk(e,t){let r=(a,s)=>{if(!a||a.design.kind!=="coil")return;let i=a.linkage?Gu(s,a.linkage).atDesign:void 0;return Sb(a.design,i)??void 0},n=r(t.heaveFrontDesign,e.front),o=r(t.heaveRearDesign,e.rear);return{...n?{front:n}:{},...o?{rear:o}:{}}}function Ku(e,t){let r=(o,a)=>o?Ci(o,wb(o,a)):0,n=(o,a)=>o?Fi(o,Cb(o,a)):0;return{heaveFront:r(t.heaveFrontDesign,e.front),heaveRear:r(t.heaveRearDesign,e.rear),rollFront:n(t.arbFrontDesign,e.front),rollRear:n(t.arbRearDesign,e.rear)}}var wb=(e,t)=>e.linkage?Gu(t,e.linkage).atDesign:void 0,Cb=(e,t)=>Eu(e.design,Fb(t,e),0).motionRatio;function jk(e,t){let r=t.damperSetup,n=t.heaveDamperModel??t.damperModel,o=t.rollDamperModel??t.damperModel,a=(d,p,f)=>{if(!d||!n?.curves.length)return;let h=wb(d,p);if(Ci(d,h)>0)return vb(n,r?.[f],h??(d.design.kind==="coil"?d.design.motionRatio:1))},s=(d,p,f)=>{if(!d||!o?.curves.length)return;let h=Cb(d,p);if(!(Fi(d,h)>0))return;let b=Fb(p,d)!==null;return kb(o,r?.[f],h,Si(d.design),b&&h>0)},i={},c=a(t.heaveFrontDesign,e.front,"heaveFront"),l=a(t.heaveRearDesign,e.rear,"heaveRear"),u=s(t.arbFrontDesign,e.front,"rollFront"),m=s(t.arbRearDesign,e.rear,"rollRear");return c&&(i.heaveFront=c),l&&(i.heaveRear=l),u&&(i.rollFront=u),m&&(i.rollRear=m),i}function Hu(e,t){let r=t.heaveDamperModel??t.damperModel,n=t.rollDamperModel??t.damperModel,o=(i,c)=>no(i)?{source:"none"}:ki(i.config.coilover,c),a=(i,c)=>{if(!i)return{source:"none"};let l=Ci(i,wb(i,c))>0;return ki(i.coilover,l?r:void 0)},s=(i,c)=>{if(!i||i.design.kind!=="coil")return{source:"none"};let l=Fi(i,Cb(i,c))>0;return ki(i.coilover,l?n:void 0)};return{front:o(e.front,t.damperModel),rear:o(e.rear,t.damperModelRear??t.damperModel),heaveFront:a(t.heaveFrontDesign,e.front),heaveRear:a(t.heaveRearDesign,e.rear),rollFront:s(t.arbFrontDesign,e.front),rollRear:s(t.arbRearDesign,e.rear)}}function Uk(e){let t=(r,n)=>{let o={};return r?.linkage&&r.design.kind==="coil"&&(o.heave=r.linkage),n?.linkage&&n.design.kind!=="none"&&n.design.kind!=="direct"&&(o.roll=n.linkage,o.rollKind=n.design.kind),o.heave||o.roll?o:void 0};return{front:t(e.heaveFrontDesign,e.arbFrontDesign),rear:t(e.heaveRearDesign,e.arbRearDesign)}}var no=e=>e.config.actuation==="decoupled",ao="a decoupled axle damps in its heave and roll elements, set below";function Xk(e,t,r={}){let n={...t},o=(m,d)=>{let p=n[m];p&&typeof p=="object"&&"value"in p&&(n[m]={...p,value:d})},{front:a,rear:s}=oo(e,t);a!==void 0&&o("arb_front",a),s!==void 0&&o("arb_rear",s);for(let[m,d,p]of[[t.heaveFrontDesign,e.front,"heave_spring_front"],[t.heaveRearDesign,e.rear,"heave_spring_rear"]]){if(!m||m.design.kind==="none")continue;let f=m.linkage?Gu(d,m.linkage).atDesign:void 0;o(p,Bu(m.design,f))}let i=sI(e,t,r),c=aI(e,i);n.kinFront=c.kinFront,n.kinRear=c.kinRear;let l=lI(e,i);n.steerFront=c.steerFront,Number.isFinite(l.ackermannPct)&&o("ackermann_pct",l.ackermannPct);let u=m=>no(m)?0:m.measured?.springRate??m.config.springRate;o("spring_front",u(e.front)),o("spring_rear",u(e.rear));for(let[m,d]of[[e.front,"spring_front"],[e.rear,"spring_rear"]])no(m)&&(n.readouts={...n.readouts,[d]:"a decoupled axle has no corner spring; its heave and roll elements carry the car"});for(let[m,d]of[[e.front,"damper_front"],[e.rear,"damper_rear"]])no(m)&&(o(d,0),n.readouts={...n.readouts,[d]:ao});return o("mr_front",l.mrFront),o("mr_rear",l.mrRear),o("wheelbase",l.wheelbase),o("track_front",l.trackFront),o("track_rear",l.trackRear),o("rc_front",l.rcFront),o("rc_rear",l.rcRear),n.surveyedRadiusFront=e.front.config.loadedRadius,n.surveyedRadiusRear=e.rear.config.loadedRadius,n.rcRoad={radiusFront:e.front.config.loadedRadius,radiusRear:e.rear.config.loadedRadius,gainFront:l.rcGainFront,gainRear:l.rcGainRear},n}function aI(e,t){return{kinFront:Hk(e.front),kinRear:Hk(e.rear),steerFront:e.front.measured?void 0:zu(e.front,t)}}var Kk=new WeakMap;function Hk(e){let t=Kk.get(e);return t||Kk.set(e,t=pa(e)),t}function sI(e,t,r={}){return iI(e,t,r.front,r.rear)}function iI(e,t,r,n){let o=e.front.config.loadedRadius;if(!((lr(r??t.tireModel)??0)>0))return o;let a={...t,surveyedRadiusFront:o,surveyedRadiusRear:e.rear.config.loadedRadius};return Yu(a,r,n).front??o}var zk=new WeakMap;function zu(e,t=e.config.loadedRadius){let r=zk.get(e);r||(r=new Map,zk.set(e,r));let n=r.get(t);if(n)return n;let o=t===e.config.loadedRadius?void 0:{loadedRadius:t},a=Af(e,xt(e.config),void 0,void 0,void 0,void 0,o);return r.size>=4&&r.clear(),r.set(t,a),a}var Yk=new WeakMap;function cI(e){return Ke(e,{travelMin:-1,travelMax:1,steps:3}).samples[1].metrics.motionRatio??1}var $u=e=>e.measured?Bk(e.measured):cI(e);function lI(e,t=e.front.config.loadedRadius){let r=()=>e.front.measured?void 0:zu(e.front,t);return{...uI(e),get steerFront(){return r()},get ackermannPct(){let n=r();return n?Ff(n,gt(e.front),e.config.wheelbase):Number.NaN}}}function uI(e){let t=Yk.get(e);if(t)return t;let r=e.front.measured,n=e.rear.measured,a=!r||!n?Yr(Dt(e),{heave:0,pitch:0,roll:0,steer:0}):null,s={wheelbase:e.config.wheelbase,trackFront:r?r.track:gt(e.front),trackRear:n?n.track:gt(e.rear),mrFront:$u(e.front),mrRear:$u(e.rear),rcFront:r?r.rollCentreHeight:a&&a.front.valid?a.front.heightAboveGround:0,rcRear:n?n.rollCentreHeight:a&&a.rear.valid?a.rear.heightAboveGround:0,rcGainFront:r||!a?0:Ca(a.front),rcGainRear:n||!a?0:Ca(a.rear),rcFrontValid:r?!0:!!a?.front.valid,rcRearValid:n?!0:!!a?.rear.valid};return Yk.set(e,s),s}var vt={open:{kind:"open"},spool:{kind:"spool"},clutch:{kind:"clutch",preloadNm:30,rampDriveDeg:40,rampCoastDeg:50,faces:6,muClutch:.1,rFrictionMm:30.4,rRampMm:36},torsen:{kind:"torsen",tbrDrive:3,tbrCoast:3}},Zk=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),fr=(e,t,r,n=1/0)=>typeof e=="number"&&Number.isFinite(e)?Math.min(n,Math.max(r,e)):t;function so(e){if(Zk(e))switch(e.kind){case"open":case"spool":return{kind:e.kind};case"clutch":{let t=vt.clutch;return{kind:"clutch",preloadNm:fr(e.preloadNm,t.preloadNm,0),rampDriveDeg:fr(e.rampDriveDeg,t.rampDriveDeg,1,90),rampCoastDeg:fr(e.rampCoastDeg,t.rampCoastDeg,1,90),faces:Math.round(fr(e.faces,t.faces,0)),muClutch:fr(e.muClutch,t.muClutch,0,1),rFrictionMm:fr(e.rFrictionMm,t.rFrictionMm,1),rRampMm:fr(e.rRampMm,t.rRampMm,1)}}case"torsen":{let t=vt.torsen,r=fr(e.preloadNm,0,0);return{kind:"torsen",tbrDrive:fr(e.tbrDrive,t.tbrDrive,1),tbrCoast:fr(e.tbrCoast,t.tbrCoast,1),...r>0?{preloadNm:r}:{}}}default:return}}function Wu(e){if(!Zk(e))return;let t=so(e.front),r=so(e.rear);return t||r?{...t?{front:t}:{},...r?{rear:r}:{}}:void 0}function Pi(e){let t=bn(e),r=n=>n>=2?"independent":n===1?"diff":"none";return{front:r(t.front),rear:r(t.rear)}}function Li(e){if(!e.driveline)return;let t=Pi(e),r=e.r_dyn.value,n=s=>{if(t[s]!=="diff")return;let i=so(e.driveline?.[s]);if(!(!i||i.kind==="independent"))return{kind:i.kind,drive:li(i,"drive",r),coast:li(i,"coast",r),hubs:li(i,"hubs",r)}},o=n("front"),a=n("rear");return o||a?{...o?{front:o}:{},...a?{rear:a}:{}}:void 0}var mI={kind:{label:"Differential"},preloadNm:{label:"Preload",unit:"N\xB7m"},rampDriveDeg:{label:"Drive ramp",unit:"\xB0"},rampCoastDeg:{label:"Coast ramp",unit:"\xB0"},faces:{label:"Friction faces"},muClutch:{label:"Clutch friction \u03BC"},rFrictionMm:{label:"Friction radius",unit:"mm"},rRampMm:{label:"Ramp radius",unit:"mm"},tbrDrive:{label:"Drive bias ratio",unit:": 1"},tbrCoast:{label:"Coast bias ratio",unit:": 1"}},qk=e=>{let t=e==="front"?"Front":"Rear";return Object.fromEntries(Object.entries(mI).map(([r,n])=>[`${e}.${r}`,{section:t,...n}]))},ju={...qk("front"),...qk("rear")},Qk=e=>e.motorModel?.kind==="ice"?e.motorPlacement==="front"?"front":"rear":null;function Jk(e,t){let r=Qk(t);if(!(!r||Qk(e)===r||t.driveline?.[r]))return{...t.driveline,[r]:{...vt.clutch}}}function Ht(e,t,r,n){return e>0?!(r>0)||!Number.isFinite(r)?e:Math.max(1,e-t/r):n}function Uu(e,t,r){let n=Math.max(0,Math.min(1,r)),o=Ht(e.freeRadius,e.staticLoad,e.tyreRate,e.surveyed),a=Ht(t.freeRadius,t.staticLoad,t.tyreRate,t.surveyed);return n*o+(1-n)*a}function Pa(e,t,r){if(t===void 0||r===void 0||!Number.isFinite(t)||!Number.isFinite(r))return e;let n=r-t;return n===0?e:Math.max(1,e+n)}function Wr(e,t,r,n){if(!t||r===void 0||n===void 0||!Number.isFinite(r)||!Number.isFinite(n))return e;let o=n-r;return o===0?e:e+t*o}function Di(e,t){if(!e)return dI(t);let r=t-dn(e,0).camber;return r?{...e,camber:e.camber.map(n=>n+r)}:e}function pI(e){return{kinFront:Di(e.kinFront,Q(e,"camber_front_deg")),kinRear:Di(e.kinRear,Q(e,"camber_rear_deg"))}}function dI(e){let t=[-40,0,40];return{travel:t,motionRatio:t.map(()=>1),camber:t.map(()=>e),toe:t.map(()=>0),damperLen:t.map(()=>0)}}var eM=9.81,tM=e=>e>1?e/100:e;function La(e,t,r){let n=t??e.tireModel??Us(),o=r??e.tireModelRear??n,a={grip:Q(e,"grip_scale"),stiffness:Q(e,"stiffness_scale")},s=Zl(n,a);return{front:s,rear:o===n?s:Zl(o,a)}}function hr(e,t,r){let n=La(e,t,r),o=Pe(n.front);return pt(n.rear===n.front?o:Gl(o,Pe(n.rear)))}function Tb(e,t,r){let n=tM(e.front_mass_diss.value),o=La(e,t,r),a=Pe(o.front),s=o.rear===o.front?a:Pe(o.rear),i=t??e.tireModel,c=r??e.tireModelRear??i,l=e.m.value*eM*n/2,u=e.m.value*eM*(1-n)/2,m=(i?a.verticalStiffness():0)||Q(e,"tire_vertical_rate"),d=(c?s.verticalStiffness():0)||Q(e,"tire_vertical_rate"),p=lr(i)??0,f=lr(c)??0,h=e.surveyedRadiusFront&&e.surveyedRadiusRear?Uu({freeRadius:p,staticLoad:l,tyreRate:m,surveyed:e.surveyedRadiusFront},{freeRadius:f,staticLoad:u,tyreRate:d,surveyed:e.surveyedRadiusRear},n):void 0,b=e.surveyedRadiusFront?Ht(p,l,m,e.surveyedRadiusFront):void 0,g=e.surveyedRadiusRear?Ht(f,u,d,e.surveyedRadiusRear):void 0;return{ev:a,evR:s,Wf:l,Wr:u,tireRate:m,tireRateRear:d,tyreFreeRadius:p,tyreFreeRadiusRear:f,cgStandingRadius:h,standingFront:b,standingRear:g}}function Yu(e,t,r){let n=Tb(e,t,r);return{front:n.standingFront,rear:n.standingRear}}function rM(e,t,r){return Tb(e,t,r).cgStandingRadius}function ht(e,t,r){let n=tM(e.front_mass_diss.value),o=Q(e,"mr_front")||1,a=Q(e,"mr_rear")||1,{ev:s,evR:i,Wf:c,Wr:l,tireRate:u,tireRateRear:m,tyreFreeRadius:d,tyreFreeRadiusRear:p,cgStandingRadius:f,standingFront:h,standingRear:b}=Tb(e,t,r),g=ii(e),y=Li(e),R=ro(e.damperModel,e.damperSetup,o,a,e.damperModelRear??e.damperModel),k=e.readouts?.damper_front===ao,v=e.readouts?.damper_rear===ao,x={rho:e.rho.value,area:e.A.value,cl:e.c_l.value,cw:e.c_w.value,copLongFront:1-Math.max(0,Math.min(1,Q(e,"cop_long"))),copHeight:Q(e,"cop_height"),...e.aeroModel?{model:e.aeroModel}:{},rideHeightFront:Q(e,"ride_height_front"),rideHeightRear:Q(e,"ride_height_rear")};return{massTotal:e.m.value,frontMassFrac:n,steeringSystem:e.steeringSystem,tv:Cu(e),cgHeight:Pa(Q(e,"cg_height"),e.cgReference?.standingRadius,f),...f!==void 0?{cgStandingRadius:f}:{},wheelbase:Q(e,"wheelbase"),trackFront:Q(e,"track_front"),trackRear:Q(e,"track_rear"),wheelRateFront:Q(e,"spring_front")*o*o,wheelRateRear:Q(e,"spring_rear")*a*a,tireRate:u,...m!==u?{tireRateRear:m}:{},tireDamping:Q(e,"tire_vertical_damping"),arbFront:Q(e,"arb_front"),arbRear:Q(e,"arb_rear"),brakeBalanceFront:g.balanceFront,brakes:g,...y?{driveline:y}:{},heaveSpringFront:Q(e,"heave_spring_front"),heaveSpringRear:Q(e,"heave_spring_rear"),unsprungPerCorner:Q(e,"unsprung_mass"),unsprungCgHeight:fI(e,{Wf:c,Wr:l,tireRate:u,tireRateRear:m,tyreFreeRadius:d,tyreFreeRadiusRear:p,standingFront:h,standingRear:b}),tyreFreeRadius:d,...p!==d?{tyreFreeRadiusRear:p}:{},rcHeightFront:Wr(Q(e,"rc_front"),e.rcRoad?.gainFront,e.rcRoad?.radiusFront,h),rcHeightRear:Wr(Q(e,"rc_rear"),e.rcRoad?.gainRear,e.rcRoad?.radiusRear,b),corneringStiffnessFront:s.corneringStiffness(c),corneringStiffnessRear:i.corneringStiffness(l),damperFront:R?.front&&!k?R.front.rate:Q(e,"damper_front")*o*o,damperRear:R?.rear&&!v?R.rear.rate:Q(e,"damper_rear")*a*a,...R?.front&&!k?{damperCurveFront:R.front.curve}:{},...R?.rear&&!v?{damperCurveRear:R.rear.curve}:{},aero:x,ackermannPct:Q(e,"ackermann_pct"),toeFrontDeg:Q(e,"toe_front_deg"),toeRearDeg:Q(e,"toe_rear_deg"),yawInertia:Q(e,"I_yaw"),steerFront:e.steerFront,...pI(e)}}function fI(e,t){let r=(a,s,i,c)=>a??(s>0?Ht(s,i,c,s):void 0),n=r(t.standingFront,t.tyreFreeRadius,t.Wf,t.tireRate),o=r(t.standingRear,t.tyreFreeRadiusRear,t.Wr,t.tireRateRear);return n!==void 0&&o!==void 0?.5*(n+o):n??o??e.r_dyn.value*1e3}var Xu={capacity:"the battery model\u2019s pack charge \u2014 cells in parallel \xD7 cell capacity",ocv:"the battery model\u2019s pack voltage at full charge"};function nM(e,t=e.batteryModel){if(!t)return e;let r=Sr(t),n=(o,a)=>({...o,value:a});return{...e,capacity:n(e.capacity,r.capacityAh),ocv:n(e.ocv,r.voltageAtFull)}}var aM={damper_front:`the damper part sets it: its front curve at ${vn} mm/s`,damper_rear:`the damper part sets it (the rear's own, where the car names one): its rear curve at ${vn} mm/s`};function qu(e){let t=!!(e.damperModelId||e.damperModel),r=t||!!(e.damperModelIdRear||e.damperModelRear);return{...t?{damper_front:aM.damper_front}:{},...r?{damper_rear:aM.damper_rear}:{}}}function sM(e,t=e.damperModel,r=e.damperModelRear??t){if(!t&&!r)return e;let n=Q(e,"mr_front")||1,o=Q(e,"mr_rear")||1,a=ro(t,e.damperSetup,n,o,r);if(!a)return e;let s=(c,l,u)=>({...c??{label:l,unit:"N\xB7s/mm"},value:u}),i={...e};return a.front&&e.readouts?.damper_front!==ao&&(i.damper_front=s(e.damper_front,"damper front",a.front.rate/(n*n))),a.rear&&e.readouts?.damper_rear!==ao&&(i.damper_rear=s(e.damper_rear,"damper rear",a.rear.rate/(o*o))),i}var iM={how:"scripts/paramTiers.ts: each row \xB120 % (switches flipped, springs on the suspension), first car of every gallery template, largest change to any event time, % of it",templates:["fs-ev-comparison","fs-ev-single","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor","formula-1","touring-car","street-car","cup-car","stock-car","hill-climb","suspension","direct-coilover","pushrod","pullrod","third-spring","mcpherson-strut","tyre-study"],rows:{endurance_reserve:{group:"Powertrain",score:"infinite",byTemplate:{"fs-ev-comparison":"infinite","fs-ev-single":"infinite","fs-combustion":null,"fs-ev-awd":0,"fs-ev-rwd-hubs":"infinite","fs-ev-one-motor":"infinite","formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:0,"direct-coilover":null,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":null,"tyre-study":"infinite"}},gear_ratio:{group:"Powertrain",score:11.9893,byTemplate:{"fs-ev-comparison":11.9893,"fs-ev-single":11.9893,"fs-combustion":5.6255,"fs-ev-awd":5.8819,"fs-ev-rwd-hubs":11.5358,"fs-ev-one-motor":7.2758,"formula-1":.2473,"touring-car":.2195,"street-car":.0998,"cup-car":.2431,"stock-car":.0645,"hill-climb":3.1703,suspension:1.8984,"direct-coilover":.2195,pushrod:1.9001,pullrod:1.9126,"third-spring":1.9001,"mcpherson-strut":.111,"tyre-study":11.9893}},driven_wheels:{group:"Powertrain",score:11.9893,byTemplate:{"fs-ev-comparison":11.9893,"fs-ev-single":11.9893,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:1.9216,"direct-coilover":0,pushrod:1.9171,pullrod:1.919,"third-spring":1.9171,"mcpherson-strut":0,"tyre-study":11.9893}},power_scale:{group:"Powertrain",score:11.9893,byTemplate:{"fs-ev-comparison":11.9893,"fs-ev-single":11.9893,"fs-combustion":10.2883,"fs-ev-awd":4.2843,"fs-ev-rwd-hubs":11.6138,"fs-ev-one-motor":7.2758,"formula-1":2.6682,"touring-car":2.5337,"street-car":1.938,"cup-car":2.6155,"stock-car":1.2193,"hill-climb":1.869,suspension:1.9216,"direct-coilover":2.5337,pushrod:1.9171,pullrod:1.919,"third-spring":1.9171,"mcpherson-strut":1.9778,"tyre-study":11.9893}},grip_scale:{group:"Tyres",score:11.4886,byTemplate:{"fs-ev-comparison":10.9135,"fs-ev-single":10.9135,"fs-combustion":11.4886,"fs-ev-awd":11.3513,"fs-ev-rwd-hubs":11.3513,"fs-ev-one-motor":11.3905,"formula-1":10.9225,"touring-car":7.4484,"street-car":7.2578,"cup-car":7.1946,"stock-car":10.4642,"hill-climb":9.5384,suspension:8.3679,"direct-coilover":7.4484,pushrod:8.3929,pullrod:8.3807,"third-spring":8.3929,"mcpherson-strut":7.35,"tyre-study":10.9135}},front_mass_diss:{group:"Mass & chassis",score:10.3816,byTemplate:{"fs-ev-comparison":1.1854,"fs-ev-single":1.1854,"fs-combustion":1.5398,"fs-ev-awd":1.9682,"fs-ev-rwd-hubs":1.9682,"fs-ev-one-motor":4.5048,"formula-1":5.2182,"touring-car":1.241,"street-car":3.5067,"cup-car":.7277,"stock-car":2.2367,"hill-climb":10.3816,suspension:.5046,"direct-coilover":1.241,pushrod:.4796,pullrod:.4587,"third-spring":.4796,"mcpherson-strut":3.4131,"tyre-study":1.1854}},m:{group:"Mass & chassis",score:9.7815,byTemplate:{"fs-ev-comparison":9.7815,"fs-ev-single":9.7815,"fs-combustion":7.2245,"fs-ev-awd":5.6765,"fs-ev-rwd-hubs":9.2239,"fs-ev-one-motor":7.0296,"formula-1":5.3736,"touring-car":3.7044,"street-car":1.9146,"cup-car":2.6724,"stock-car":3.7623,"hill-climb":5.4157,suspension:3.8549,"direct-coilover":3.7044,pushrod:3.8507,pullrod:3.8527,"third-spring":3.8507,"mcpherson-strut":1.9399,"tyre-study":9.7815}},cop_long:{group:"Aerodynamics",score:6.6543,byTemplate:{"fs-ev-comparison":1.032,"fs-ev-single":1.032,"fs-combustion":1.0669,"fs-ev-awd":1.0452,"fs-ev-rwd-hubs":1.0452,"fs-ev-one-motor":1.0521,"formula-1":5.9878,"touring-car":.1327,"street-car":.0018,"cup-car":.2696,"stock-car":.6469,"hill-climb":6.6543,suspension:.3644,"direct-coilover":.1327,pushrod:.3575,pullrod:.355,"third-spring":.3575,"mcpherson-strut":.0072,"tyre-study":1.032}},front_aero_diss:{group:"Aerodynamics",score:5.2168,byTemplate:{"fs-ev-comparison":.9064,"fs-ev-single":.9064,"fs-combustion":.8657,"fs-ev-awd":.8967,"fs-ev-rwd-hubs":.8967,"fs-ev-one-motor":.8574,"formula-1":4.2912,"touring-car":.0708,"street-car":.0018,"cup-car":.2207,"stock-car":.5291,"hill-climb":5.2168,suspension:.2835,"direct-coilover":.0708,pushrod:.2831,pullrod:.2823,"third-spring":.2831,"mcpherson-strut":.0072,"tyre-study":.9064}},power_limit_kw:{group:"Powertrain",score:4.5916,byTemplate:{"fs-ev-comparison":.4828,"fs-ev-single":.4828,"fs-combustion":null,"fs-ev-awd":4.5916,"fs-ev-rwd-hubs":.5453,"fs-ev-one-motor":3.6198,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:.0626,"direct-coilover":null,pushrod:.0625,pullrod:.0626,"third-spring":.0625,"mcpherson-strut":null,"tyre-study":.4828}},soc:{group:"Powertrain",score:3.5618,byTemplate:{"fs-ev-comparison":3.2245,"fs-ev-single":3.2245,"fs-combustion":0,"fs-ev-awd":1.6179,"fs-ev-rwd-hubs":3.3095,"fs-ev-one-motor":3.5618,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":3.2245}},effi_pgb:{group:"Powertrain",score:3.5269,byTemplate:{"fs-ev-comparison":3.5269,"fs-ev-single":3.5269,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:.0626,"direct-coilover":0,pushrod:.0625,pullrod:.0626,"third-spring":.0625,"mcpherson-strut":0,"tyre-study":3.5269}},c_l:{group:"Aerodynamics",score:3.4342,byTemplate:{"fs-ev-comparison":.9751,"fs-ev-single":.9751,"fs-combustion":.9539,"fs-ev-awd":1.0777,"fs-ev-rwd-hubs":.9886,"fs-ev-one-motor":1.0797,"formula-1":3.4342,"touring-car":.8979,"street-car":.0715,"cup-car":.2158,"stock-car":.5467,"hill-climb":1.2705,suspension:.9751,"direct-coilover":.8979,pushrod:.9734,pullrod:.9708,"third-spring":.9734,"mcpherson-strut":.0704,"tyre-study":.9751}},ocv:{group:"Powertrain",score:3.3244,byTemplate:{"fs-ev-comparison":3.0446,"fs-ev-single":3.0446,"fs-combustion":0,"fs-ev-awd":1.4595,"fs-ev-rwd-hubs":3.1854,"fs-ev-one-motor":3.3244,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":3.0446}},capacity:{group:"Powertrain",score:3.3244,byTemplate:{"fs-ev-comparison":3.0446,"fs-ev-single":3.0446,"fs-combustion":0,"fs-ev-awd":1.4595,"fs-ev-rwd-hubs":3.1854,"fs-ev-one-motor":3.3244,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":3.0446}},A:{group:"Aerodynamics",score:2.3707,byTemplate:{"fs-ev-comparison":.802,"fs-ev-single":.802,"fs-combustion":.7928,"fs-ev-awd":.9333,"fs-ev-rwd-hubs":.7926,"fs-ev-one-motor":.961,"formula-1":2.3707,"touring-car":.6374,"street-car":.4904,"cup-car":.2428,"stock-car":.1932,"hill-climb":1.1486,suspension:.802,"direct-coilover":.6374,pushrod:.7991,pullrod:.7982,"third-spring":.7991,"mcpherson-strut":.4873,"tyre-study":.802}},rho:{group:"Aerodynamics",score:2.3707,byTemplate:{"fs-ev-comparison":.802,"fs-ev-single":.802,"fs-combustion":.7928,"fs-ev-awd":.9333,"fs-ev-rwd-hubs":.7926,"fs-ev-one-motor":.961,"formula-1":2.3707,"touring-car":.6374,"street-car":.4904,"cup-car":.2428,"stock-car":.1932,"hill-climb":0,suspension:.802,"direct-coilover":.6374,pushrod:.7991,pullrod:.7982,"third-spring":.7991,"mcpherson-strut":.4873,"tyre-study":.802}},cg_height:{group:"Mass & chassis",score:2.2005,byTemplate:{"fs-ev-comparison":1.8282,"fs-ev-single":1.8282,"fs-combustion":1.6978,"fs-ev-awd":2.2005,"fs-ev-rwd-hubs":1.8919,"fs-ev-one-motor":1.9269,"formula-1":.6248,"touring-car":1.2858,"street-car":1.4681,"cup-car":.992,"stock-car":1.2052,"hill-climb":.6037,suspension:1.8282,"direct-coilover":1.2858,pushrod:1.8142,pullrod:1.8229,"third-spring":1.8142,"mcpherson-strut":1.7176,"tyre-study":1.8282}},l_to_d_ratio:{group:"Aerodynamics",score:1.4351,byTemplate:{"fs-ev-comparison":.7905,"fs-ev-single":.7905,"fs-combustion":.6962,"fs-ev-awd":.5843,"fs-ev-rwd-hubs":.8444,"fs-ev-one-motor":.9611,"formula-1":1.4351,"touring-car":.3671,"street-car":.528,"cup-car":.5631,"stock-car":.4634,"hill-climb":.2349,suspension:.2456,"direct-coilover":.3671,pushrod:.2491,pullrod:.2456,"third-spring":.2491,"mcpherson-strut":.5265,"tyre-study":.7905}},tv_enabled:{group:"Torque vectoring",score:1.2381,byTemplate:{"fs-ev-comparison":1.2381,"fs-ev-single":1.2381,"fs-combustion":0,"fs-ev-awd":1.2293,"fs-ev-rwd-hubs":1.2293,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":.1209,"cup-car":.1617,"stock-car":0,"hill-climb":9e-4,suspension:.3086,"direct-coilover":0,pushrod:.2933,pullrod:.3089,"third-spring":.2933,"mcpherson-strut":.1326,"tyre-study":1.2381}},c_w:{group:"Aerodynamics",score:1.1499,byTemplate:{"fs-ev-comparison":.6319,"fs-ev-single":.6319,"fs-combustion":.5577,"fs-ev-awd":.462,"fs-ev-rwd-hubs":.6559,"fs-ev-one-motor":.7504,"formula-1":1.1499,"touring-car":.2914,"street-car":.4211,"cup-car":.4486,"stock-car":.3694,"hill-climb":.1625,suspension:.1945,"direct-coilover":.2914,pushrod:.1979,pullrod:.1948,"third-spring":.1979,"mcpherson-strut":.4196,"tyre-study":.6319}},brake_balance:{group:"Brakes",score:1.0132,byTemplate:{"fs-ev-comparison":.8303,"fs-ev-single":.8303,"fs-combustion":.6932,"fs-ev-awd":.9772,"fs-ev-rwd-hubs":.8148,"fs-ev-one-motor":1.0132,"formula-1":.97,"touring-car":.9585,"street-car":.7184,"cup-car":.1468,"stock-car":.0764,"hill-climb":.9096,suspension:.8303,"direct-coilover":.9585,pushrod:.8578,pullrod:.8454,"third-spring":.8578,"mcpherson-strut":.7099,"tyre-study":.8303}},stiffness_scale:{group:"Tyres",score:.871,byTemplate:{"fs-ev-comparison":.5088,"fs-ev-single":.5088,"fs-combustion":.4874,"fs-ev-awd":.3745,"fs-ev-rwd-hubs":.4753,"fs-ev-one-motor":.5706,"formula-1":.5776,"touring-car":.4346,"street-car":.1077,"cup-car":.4012,"stock-car":.1613,"hill-climb":.871,suspension:.5088,"direct-coilover":.4346,pushrod:.5253,pullrod:.5172,"third-spring":.5253,"mcpherson-strut":.1518,"tyre-study":.5088}},cop_height:{group:"Aerodynamics",score:.2837,byTemplate:{"fs-ev-comparison":.155,"fs-ev-single":.155,"fs-combustion":.1546,"fs-ev-awd":.1557,"fs-ev-rwd-hubs":.1557,"fs-ev-one-motor":.1542,"formula-1":.1173,"touring-car":.0072,"street-car":.0023,"cup-car":.0745,"stock-car":.1568,"hill-climb":.2837,suspension:.0421,"direct-coilover":.0072,pushrod:.0437,pullrod:.04,"third-spring":.0437,"mcpherson-strut":.0076,"tyre-study":.155}},spring_rear:{group:"Suspension",score:.2822,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":.0355,"touring-car":.1169,"street-car":.2242,"cup-car":.0902,"stock-car":.2822,"hill-climb":.1929,suspension:0,"direct-coilover":.1169,pushrod:.1142,pullrod:.2148,"third-spring":.1142,"mcpherson-strut":.1786,"tyre-study":0}},spring_front:{group:"Suspension",score:.2388,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":.0189,"touring-car":.0958,"street-car":.2388,"cup-car":.1462,"stock-car":.1719,"hill-climb":.1873,suspension:0,"direct-coilover":.0958,pushrod:.1257,pullrod:.0612,"third-spring":.1257,"mcpherson-strut":.1911,"tyre-study":0}},arb_front:{group:"Suspension",score:.1792,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":.0235,"touring-car":.0589,"street-car":.1792,"cup-car":.0215,"stock-car":.0926,"hill-climb":.1095,suspension:null,"direct-coilover":.0589,pushrod:.0455,pullrod:.049,"third-spring":.0455,"mcpherson-strut":.1435,"tyre-study":null}},fr_0:{group:"Tyres",score:.158,byTemplate:{"fs-ev-comparison":.158,"fs-ev-single":.158,"fs-combustion":.1097,"fs-ev-awd":.0708,"fs-ev-rwd-hubs":.1442,"fs-ev-one-motor":.1168,"formula-1":.07,"touring-car":.0492,"street-car":.1006,"cup-car":.065,"stock-car":.0262,"hill-climb":.0334,suspension:.0217,"direct-coilover":.0492,pushrod:.0229,pullrod:.0223,"third-spring":.0229,"mcpherson-strut":.0989,"tyre-study":.158}},arb_rear:{group:"Suspension",score:.1047,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":.0224,"touring-car":.0365,"street-car":.0832,"cup-car":.1047,"stock-car":.0436,"hill-climb":.0734,suspension:null,"direct-coilover":.0365,pushrod:.0411,pullrod:.0332,"third-spring":.0411,"mcpherson-strut":.0643,"tyre-study":null}},unsprung_mass:{group:"Mass & chassis",score:.102,byTemplate:{"fs-ev-comparison":.0477,"fs-ev-single":.0477,"fs-combustion":.0512,"fs-ev-awd":.0545,"fs-ev-rwd-hubs":.0514,"fs-ev-one-motor":.0799,"formula-1":.0313,"touring-car":.0471,"street-car":.102,"cup-car":.0315,"stock-car":.042,"hill-climb":.0278,suspension:.0477,"direct-coilover":.0471,pushrod:.0452,pullrod:.0468,"third-spring":.0452,"mcpherson-strut":.0876,"tyre-study":.0477}},camber_front_deg:{group:"Steering & alignment",score:.0576,byTemplate:{"fs-ev-comparison":.0065,"fs-ev-single":.0065,"fs-combustion":.008,"fs-ev-awd":.0075,"fs-ev-rwd-hubs":.0075,"fs-ev-one-motor":.0098,"formula-1":.0358,"touring-car":.0272,"street-car":.0025,"cup-car":.0191,"stock-car":.0576,"hill-climb":.0389,suspension:.0019,"direct-coilover":.0272,pushrod:.0017,pullrod:.0016,"third-spring":.0017,"mcpherson-strut":.002,"tyre-study":.0065}},camber_rear_deg:{group:"Steering & alignment",score:.0262,byTemplate:{"fs-ev-comparison":.0081,"fs-ev-single":.0081,"fs-combustion":.0085,"fs-ev-awd":.0054,"fs-ev-rwd-hubs":.0096,"fs-ev-one-motor":.0097,"formula-1":.0028,"touring-car":.0106,"street-car":8e-4,"cup-car":5e-4,"stock-car":.0035,"hill-climb":.0262,suspension:.0081,"direct-coilover":.0106,pushrod:.0082,pullrod:.0083,"third-spring":.0082,"mcpherson-strut":3e-4,"tyre-study":.0081}},I_yaw:{group:"Mass & chassis",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},I_roll:{group:"Mass & chassis",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},I_pitch:{group:"Mass & chassis",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},ride_height_front:{group:"Aerodynamics",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},ride_height_rear:{group:"Aerodynamics",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tire_vertical_rate:{group:"Tyres",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tire_vertical_damping:{group:"Tyres",score:0,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":0,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},r_dyn:{group:"Tyres",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},damper_front:{group:"Suspension",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},damper_rear:{group:"Suspension",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_kp:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_ff_low:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_ff_high:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_v_low:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_v_high:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},wheelbase:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},track_front:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},track_rear:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},rc_front:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},rc_rear:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},I_wheel:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},I_rotor:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},v_limit_endurance:{group:"Powertrain",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},mr_front:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},mr_rear:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},heave_spring_front:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},heave_spring_rear:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},toe_front_deg:{group:"Steering & alignment",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},toe_rear_deg:{group:"Steering & alignment",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},ackermann_pct:{group:"Steering & alignment",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}}}};function jr(e){return!!e&&typeof e=="object"&&"value"in e&&"label"in e}var yI={Batteriekapazit\u00E4t:"pack capacity",Rollwiderstandsbeiwert:"rolling-resistance coefficient"},lM=e=>yI[e]??e;function Qu(e){let t=[];for(let r of Object.keys(e)){if(r==="motor"||r==="name")continue;let n=e[r];jr(n)&&t.push({key:r,label:lM(n.label),value:n.value,unit:n.unit})}return t}var xI=[{title:"Mass & chassis",keys:["m","front_mass_diss","cg_height","unsprung_mass","wheelbase","track_front","track_rear","rc_front","rc_rear","I_yaw","I_roll","I_pitch","I_wheel","I_rotor"]},{title:"Aerodynamics",keys:["A","c_l","c_w","l_to_d_ratio","front_aero_diss","cop_long","cop_height","ride_height_front","ride_height_rear","rho"]},{title:"Tyres",keys:["grip_scale","stiffness_scale","tire_vertical_rate","tire_vertical_damping","fr_0","r_dyn"]},{title:"Powertrain",keys:["gear_ratio","driven_wheels","effi_pgb","power_scale","power_limit_kw","v_limit_endurance","endurance_reserve","capacity","ocv","soc"]},{title:"Suspension",keys:["spring_front","spring_rear","mr_front","mr_rear","arb_front","arb_rear","heave_spring_front","heave_spring_rear","damper_front","damper_rear"]},{title:"Steering & alignment",keys:["camber_front_deg","camber_rear_deg","toe_front_deg","toe_rear_deg","ackermann_pct"]},{title:"Brakes",keys:["brake_balance"]},{title:"Torque vectoring",keys:["tv_enabled","tv_kp","tv_ff_low","tv_ff_high","tv_v_low","tv_v_high"]}],RI=.5,cM=e=>e==="infinite"?1/0:typeof e=="number"?e:null,vI=e=>/front/.test(e)?e.replace("front","rear"):/rear/.test(e)?e.replace("rear","front"):null,G7=(()=>{let e=iM.rows,t=o=>{let a=vI(o),s=cM(e[o]?.score),i=a&&e[a]?cM(e[a].score):null;return s==null?i:i==null?s:Math.max(s,i)},r=new Set,n=new Map;for(let[o,a]of Object.entries(e)){let s=t(o);s!=null&&(s>=RI&&r.add(o),n.set(a.group,Math.max(n.get(a.group)??0,s)))}for(let[o,a]of Object.entries(e)){let s=t(o);s!=null&&s>0&&s===n.get(a.group)&&r.add(o)}return r})();var Pb={wheelbase:"set by the axle positions in Kinematics",track_front:"twice the front wheel-centre Y",track_rear:"twice the rear wheel-centre Y",rc_front:"solved from the front wishbones, on the fitted tyre",rc_rear:"solved from the rear wishbones, on the fitted tyre",mr_front:"damper travel per mm of front wheel travel, from the linkage",mr_rear:"damper travel per mm of rear wheel travel, from the linkage",spring_front:"the front corner spring rate, stored on the suspension the car runs",spring_rear:"the rear corner spring rate, stored on the suspension the car runs",ackermann_pct:"solved from the rack and tie rods, read near centre"};function uM(e){let t=new Map;for(let a of Qu(e))t.set(a.key,a);let r=new Set,n=[];for(let a of xI){let s=[];for(let i of a.keys){let c=t.get(i);c&&(s.push(c),r.add(i))}s.length&&n.push({title:a.title,rows:s})}let o=Qu(e).filter(a=>!r.has(a.key));return o.length&&n.push({title:"Other",rows:o}),n}var Lb={A:"the aero model's reference area",c_l:"read off the aero model at the ride heights",c_w:"read off the aero model at the ride heights",l_to_d_ratio:"read off the aero model at the ride heights",front_aero_diss:"the aero model's front and rear coefficients set the balance",cop_long:"the aero model's front and rear coefficients set the balance"},Db={ride_height_front:"reaches nothing until an aero model is attached at the head of the Aerodynamics group",ride_height_rear:"reaches nothing until an aero model is attached at the head of the Aerodynamics group"},mM=e=>!!(e.aeroModelId||e.aeroModel);function kI(e){let t=n=>n!=null&&n.design.kind!=="none",r={};return t(e.arbFrontDesign)&&(r.arb_front="the front anti-roll bar design sets it"),t(e.arbRearDesign)&&(r.arb_rear="the rear anti-roll bar design sets it"),t(e.heaveFrontDesign)&&(r.heave_spring_front="the front third-spring design sets it"),t(e.heaveRearDesign)&&(r.heave_spring_rear="the rear third-spring design sets it"),r}var MI=e=>!!(e.batteryModelId||e.batteryModel);function SI(e,t){let r={};return t.geometry&&Object.assign(r,Pb,kI(e)),mM(e)&&Object.assign(r,Lb),MI(e)&&Object.assign(r,Xu),Object.assign(r,qu(e)),e.readouts&&Object.assign(r,e.readouts),r}function pM(e,t){let r=SI(e,t);return mM(e)||Object.assign(r,Db),r}function Eb(e){let t=e.cop_long;return jr(t)?1-t.value:.5}function AI(e,t){let r=e.front_aero_diss,n=e.cop_long;!jr(r)||!jr(n)||(t===r.label?n.value=1-r.value:t===n.label&&(r.value=1-n.value))}function FI(e,t){AI(e,t);let r=e.c_l,n=e.c_w,o=e.l_to_d_ratio;!jr(r)||!jr(n)||(t===r.label||t===n.label?jr(o)&&n.value!==0&&(o.value=r.value/n.value):jr(o)&&t===o.label&&o.value!==0&&(n.value=r.value/o.value))}function Zu(e,t,r){let n=!1;for(let o of Object.keys(e)){if(o==="motor"||o==="name")continue;let a=e[o];if(jr(a)&&lM(a.label)===t){a.value=r,n=!0;break}}return n&&FI(e,t),n}function Ju(e,t,r=0,n,o){let a=()=>({cl:e.c_l.value,cw:e.c_w.value,frontShare:Eb(e),A:e.A.value,platform:null});if(!e.aeroModel)return a();let s=Fr(n??ht(e),t,r,o);if(!s)return a();let i=s.clFront+s.clRear;return{cl:i,cw:s.cd,frontShare:i!==0?s.clFront/i:Eb(e),A:s.area,platform:s}}var dM=e=>typeof e=="object"&&e!==null&&typeof e.value=="number"&&typeof e.label=="string";function fM(e,t=e.aeroModel){if(!t)return e;let r=on(t,{wheelbase:Q(e,"wheelbase")}).at(Q(e,"ride_height_front"),Q(e,"ride_height_rear")),{cl:n,balanceFront:o}=Fd(r),a=(i,c,l)=>({...i??c,value:l}),s={...e,A:a(e.A,e.A,t.area),c_l:a(e.c_l,e.c_l,n),c_w:a(e.c_w,e.c_w,r.cd),front_aero_diss:a(e.front_aero_diss,e.front_aero_diss,o),cop_long:a(dM(e.cop_long)?e.cop_long:void 0,pr.cop_long,1-o)};return dM(e.l_to_d_ratio)&&(s.l_to_d_ratio={...e.l_to_d_ratio,value:r.cd!==0?n/r.cd:0}),s}var Ei={dsTarget:.25,accelStep:.25,vTol:.002,scanSteps:24,seamIters:8,fitSpacing:1},wI=32;function hM(e,t,r){let n=Math.round(e/t);return Math.max(1,Math.min(Number.isFinite(n)?n:1,Math.floor(r/wI)||1))}function it(e){let t=Ei,r=(n,o,a)=>{let s=Number(n);return Number.isFinite(s)&&s>=a?s:o};return{dsTarget:r(e?.dsTarget,t.dsTarget,.001),accelStep:r(e?.accelStep,t.accelStep,.001),vTol:r(e?.vTol,t.vTol,1e-6),scanSteps:Math.max(4,Math.round(r(e?.scanSteps,t.scanSteps,4))),seamIters:Math.max(1,Math.round(r(e?.seamIters,t.seamIters,1))),fitSpacing:r(e?.fitSpacing,t.fitSpacing,0)}}var bM=Math.PI/180,em=.02,gM=new WeakMap;function Ii(e){let t=gM.get(e);if(t!==void 0)return t;let r=e.npts,n=new Array(r),o=new Array(r),a=!1;for(let i=0;i<r;i++){let c=(e.gradient?.[i]??0)*bM,l=(e.bank?.[i]??0)*bM,u=e.verticalCurvature?.[i]??0;n[i]=c===0&&l===0?1:Math.cos(c)*Math.cos(l),o[i]=(u-e.curvature[i]*Math.sin(l))/9.81,(n[i]!==1||o[i]!==0)&&(a=!0)}let s=a?{n0:n,k:o}:null;return gM.set(e,s),s}function tm(e,t,r){return e.n0[t]+e.k[t]*r*r}function yM(e,t){return e.k[t]<0?Math.sqrt(Math.max(0,e.n0[t])/-e.k[t]):1/0}function xM(e,t){if(!e)return null;let r=1/0,n=-1/0;for(let o=0;o<e.n0.length;o++){let a=tm(e,o,t[o]??0);a<r&&(r=a),a>n&&(n=a)}return r>=1-em&&n<=1+em?null:{lo:r,hi:n}}var Da=[.1,.25,.5,.75,1,1.25,1.5,2,2.5];function RM(e){let t=e.lo>=1-em?1:1-1.25*(1-e.lo)-.05,r=e.hi<=1+em?1:1+1.25*(e.hi-1)+.05,n=[...Da].reverse().find(a=>a<=t)??Da[0],o=Da.find(a=>a>=r)??Da[Da.length-1];return Da.filter(a=>a>=n&&a<=o)}function Ib(e,t,r){return r<1?Math.max(e,t):Math.min(e,t)}function vM(e,t,r,n){let o=e.n0.length;return a=>{let s=n?n(a):r,i=a%o;if(e.n0[i]===1&&e.k[i]===0)return s;let c=e.n0[i],l=e.k[i],u=m=>c+l*m*m;return n?{vMax:s.vMax,axAccel:(m,d,p=1,f=1)=>s.axAccel(m,d,p,f)+t.axAccel(u(m),m,d,p,f)-r.axAccel(m,d,p,f),axDecel:(m,d,p=1,f=1)=>{let h=b=>s.axDecel(m,d,p,b)+t.axDecel(u(m),m,d,p,b)-r.axDecel(m,d,p,b);return f===1?h(1):Ib(h(f),h(1),f)},ay:(m,d,p=1)=>Math.max(0,s.ay(m,d,p)+t.ay(u(m),m,d,p)-r.ay(m,d,p)),scrub:(m,d,p=1)=>(s.scrub?.(m,d,p)??0)+t.scrub(u(m),m,d,p)-(r.scrub?.(m,d,p)??0)}:{vMax:s.vMax,axAccel:(m,d,p=1,f=1)=>t.axAccel(u(m),m,d,p,f),axDecel:(m,d,p=1,f=1)=>t.axDecel(u(m),m,d,p,f),ay:(m,d,p=1)=>t.ay(u(m),m,d,p),scrub:(m,d,p=1)=>t.scrub(u(m),m,d,p)}}}function rm(e,t,r,n,o){let a=e.length,s=r?a:a-1,i=A=>r?(A+1)%a:A+1,{brakeAhead:c,apexAhead:l}=CI(e,t,r),u=new Array(a),m=new Array(a),d=new Array(a),p=new Array(a).fill(0),f=0,h=0,b=0,g=Math.max(0,Math.min(1,n.kept)),y=g>=1?0:n.up,R=g>=1?0:n.down,k=4*y*(1-g),v=A=>{let{v:w,gear:C,tau:T,target:F}=A;f=0,h=0,b=0;for(let S=0;S<s;S++){let P=i(S),L=e[P];for(let O=0;T<=0&&O<n.count;O++){let _=C;if(w<L-1e-9?n.best(w)>C&&(n.rpm(w,C)>=n.limitRpm||c[S]>=w*k)?_=C+1:C>0&&w<n.vIdle(C)&&(_=C-1):L<w-1e-9&&C>0&&n.best(l[S])<C&&n.rpm(w,C-1)<=n.limitRpm&&(_=C-1),_===C)break;F=_,_>C?f++:h++,T=_>C?y:R,T<=0&&(C=F)}u[S]=w,m[S]=C+1,d[S]=n.rpm(w,C);let D=T>0;p[S]=D?1:0;let I=L;if(!D)w<L&&(I=Math.min(L,Math.sqrt(Math.max(0,w*w+2*o(S,w,n.share(w,C))*t[S]))));else if(w<L){let O=o(S,w,g>0?g*n.share(w,C):0),_=Math.min(L,Math.sqrt(Math.max(0,w*w+2*O*t[S]))),z=w+_>0?2*t[S]/(w+_):1/0;if(z<=T)I=_,b+=z,T-=z;else{let E=Math.min(L,Math.max(0,w+O*T)),N=Math.max(0,t[S]-(w+E)*.5*T);b+=T,T=0,C=F,I=Math.min(L,Math.sqrt(Math.max(0,E*E+2*o(S,E,n.share(E,C))*N)))}}else{let O=w+I>0?2*t[S]/(w+I):0;b+=Math.min(O,T),T-=O,T<=0&&(C=F)}w=I}return{v:w,gear:C,tau:T,target:F}},x=n.best(e[0]),M={v:e[0],gear:x,tau:0,target:x};if(r)for(let A=0;A<6;A++){let w=v(M),C=Math.abs(w.v-M.v)<=1e-9&&w.gear===M.gear&&w.target===M.target&&Math.abs(w.tau-M.tau)<=1e-12;if(M=w,C)break}else{let A=v(M);u[a-1]=A.v,m[a-1]=A.gear+1,d[a-1]=n.rpm(A.v,A.gear),p[a-1]=A.tau>0?1:0}return{v:u,gear:m,rpm:d,shifting:p,upshifts:f,downshifts:h,gapTime:b}}function CI(e,t,r){let n=e.length,o=new Array(n).fill(1/0),a=e.slice(),s=1/0,i=e[n-1],c=r?2*n-1:n-2;for(let l=c;l>=0;l--){let u=l%n,m=r?(u+1)%n:u+1,d=e[m]<e[u]-1e-9;s=d?0:s+t[u],i=d?Math.min(i,e[m]):e[u],l<n&&(o[u]=s,a[u]=i)}return{brakeAhead:o,apexAhead:a}}var _b=.001,Nb=9.81,_i=(e,t)=>nm(e?.gradient?.[t]??0);function nm(e){return e===0?0:-Nb*Math.sin(e*Math.PI/180)}function Mn(e,t){let r=new Array(t);for(let n=0;n<t;n++)r[n]=nm(e?.[n]??0);return r}var kn=(e,t)=>{let r=e?.mu?.[t];return r!=null&&r>0?r:1},io=(e,t)=>e?.bank?.[t]??0;function TI(e,t,r,n,o,a){let s=e.ay(t,r,kn(o,a)),i=io(o,a);if(!i)return s;let c=i*Math.PI/180,l=n===0?0:-Math.sign(n)*Nb*Math.sin(c);return Math.max(0,(s+l)/Math.cos(c))}function He(e,t){if(!t)return e;let r=t*Math.PI/180;return e*Math.cos(r)+Nb*Math.sin(r)}function Ob(e,t,r,n,o){if(r<=t)return t;if(e(r)<=0)return r;let a=(r-t)/n,s=r,i=t,c=!1;for(let l=1;l<=n;l++){let u=r-l*a;if(e(u)<=0){i=u,s=u+a,c=!0;break}}if(!c)return t;for(;s-i>o;){let l=.5*(i+s);e(l)<=0?i=l:s=l}return i}var co=(e,t,r)=>t?t(r):e,PI=1e-4;function Ea(e,t,r,n,o,a,s){let i=it(r),c=[];for(let l=0;l<t.length;l++){let u=t[l],m=Math.abs(u),d=co(e,o,l),p=a!==void 0&&a>0?Math.min(d.vMax,a):d.vMax,f=s?Math.min(p,s(l)):p,h=m<=0?f:Ob(b=>b*b*m-TI(d,b,0,u,n,l),_b,f,i.scanSteps,Math.min(i.vTol,PI));c.push({v:h,ax:0,ay:h*h*u})}return c}function LI(e,t,r,n,o,a,s=1,i=0,c=0,l){if(r.v<=t.v)return 0;let u=p=>{let f=He(p*p*n,c),h=(l?e.axDecel(p,Math.abs(f),s,l(p)):e.axDecel(p,Math.abs(f),s))+i;return Math.sqrt(Math.max(0,p*p+2*h*o))},m=r.v;r.v=Ob(p=>u(p)-t.v,_b,r.v,a.scanSteps,a.vTol),r.ay=r.v*r.v*n;let d=Math.abs(He(r.ay,c));return r.ax=(l?e.axDecel(r.v,d,s,l(r.v)):e.axDecel(r.v,d,s))+i,m-r.v}function DI(e,t,r,n,o,a=1,s=0,i=0,c=1){if(r.v>=t.v)return 0;r.ay=r.v*r.v*n,r.ax=e.axAccel(r.v,Math.abs(He(r.ay,i)),a,c)+s;let l=t.v;return t.v=Math.min(t.v,Math.sqrt(Math.max(0,r.v*r.v+2*r.ax*o))),l-t.v}function kM(e,t,r,n,o,a){let s=it(n),i=r.npts,c=0;for(let l=0;l<s.seamIters;l++){let u=0;c++;for(let m=i-1;m>=0;m--){let d=(m+1)%i;u=Math.max(u,LI(co(e,o,m),t[d],t[m],r.curvature[m],r.ds[m],s,kn(r,m),_i(r,m),io(r,m),a?p=>a(m,p):void 0))}if(u<=s.vTol)break}return c}function MM(e,t,r,n,o,a){let s=it(n),i=r.npts,c=0;for(let l=0;l<s.seamIters;l++){let u=0;c++;for(let m=0;m<i;m++){let d=(m+1)%i;u=Math.max(u,DI(co(e,o,m),t[d],t[m],r.curvature[m],r.ds[m],kn(r,m),_i(r,m),io(r,m),a?a[m]:1))}if(u<=s.vTol)break}return c}function EI(e,t,r){let n=r.load?Ii(t):null;if(!n||!r.load)return{pick:r.envelope};let o=t.npts;return{pick:vM(n,r.load,e,r.envelope),cap:a=>yM(n,a%o),n:(a,s)=>tm(n,a,s)}}function SM(e,t,r,n,o,a,s){return rm(n,r.ds,o,a,(i,c,l)=>{let u=c*c*r.curvature[i];return co(e,t,i).axAccel(c,Math.abs(He(u,io(r,i))),kn(r,i),s?l*s[i]:l)+_i(r,i)})}function AM(e,t){return{gear:e.gear.slice(0,t),engineRpm:e.rpm.slice(0,t),shifting:e.shifting.slice(0,t)}}function FM(e,t,r,n){if(!e.scrub)return{};let o=!1,a=n.map((s,i)=>{let c=co(e,t,i),l=He(s*s*r.curvature[i],io(r,i)),u=c.scrub?c.scrub(s,Math.abs(l),kn(r,i)):0;return u!==0&&(o=!0),u});return o?{axScrub:a}:{}}function kt(e,t,r,n={}){let o=it(r),a=t.npts,s=t.closed&&!n.standingStart,{pick:i,cap:c,n:l}=EI(e,t,n),u=n.driveDerate,m=n.brakeFade;if(!s)return II(e,t,o,n.standingStart===!0,i,u,n.vCeiling,m,c,l,n.shifts);let d=Ea(e,t.curvature,o,t,i,n.vCeiling,c),p=kM(e,d,t,o,i,m),f=MM(e,d,t,o,i,u),h=n.shifts?SM(e,i,t,d.map(k=>k.v),!0,n.shifts,u):void 0;if(h)for(let k=0;k<a;k++)d[k].v=h.v[k];for(let k=0;k<a;k++){let v=d[k];v.ay=v.v*v.v*t.curvature[k];let x=d[(k+1)%a].v;v.ax=(x*x-v.v*v.v)/(2*t.ds[k])}let b=d.map(k=>k.v),g=d.map(k=>k.ax),y=d.map(k=>k.ay),R=0;for(let k=0;k<a;k++){let v=b[k]+b[(k+1)%a];v>0&&(R+=2*t.ds[k]/v)}return{states:d,v:b,ax:g,ay:y,laptime:R,sweeps:{backward:p,forward:f},...l?{loadFactor:b.map((k,v)=>l(v,k))}:{},...FM(e,i,t,b),...h?AM(h,a):{}}}function II(e,t,r,n,o,a,s,i,c,l,u){let m=t.npts,d=t.closed?m:m-1,p=d+1,f=new Array(p);for(let R=0;R<p;R++)f[R]=t.curvature[R%m];let h=Ea(e,f,r,t,o,s,c);n&&(h[0].v=0);for(let R=d-1;R>=0;R--){let k=h[R],v=h[R+1];if(k.v<=v.v)continue;let x=co(e,o,R),M=w=>{let C=He(w*w*t.curvature[R],io(t,R)),T=(i?x.axDecel(w,Math.abs(C),kn(t,R),i(R,w)):x.axDecel(w,Math.abs(C),kn(t,R)))+_i(t,R);return Math.sqrt(Math.max(0,w*w+2*T*t.ds[R]))},A=n&&R===0?k.v:_b;k.v=Ob(w=>M(w)-v.v,A,k.v,r.scanSteps,r.vTol)}for(let R=0;R<d;R++){let k=h[R],v=h[R+1];k.ay=k.v*k.v*t.curvature[R];let x=He(k.ay,io(t,R));k.ax=co(e,o,R).axAccel(k.v,Math.abs(x),kn(t,R),a?a[R]:1)+_i(t,R),v.v=Math.min(v.v,Math.sqrt(Math.max(0,k.v*k.v+2*k.ax*t.ds[R])))}let b=u?SM(e,o,t,h.map(R=>R.v),!1,u,a):void 0;if(b)for(let R=0;R<p;R++)h[R].v=b.v[R];let g=0;for(let R=0;R<d;R++){let k=h[R].v+h[R+1].v;k>0&&(g+=2*t.ds[R]/k)}let y=h.slice(0,m);for(let R=0;R<m;R++){let k=y[R];k.ay=k.v*k.v*t.curvature[R];let v=R<d?h[R+1].v:k.v;k.ax=t.ds[R]>0?(v*v-k.v*k.v)/(2*t.ds[R]):0}return{states:y,v:y.map(R=>R.v),ax:y.map(R=>R.ax),ay:y.map(R=>R.ay),laptime:g,sweeps:{backward:1,forward:1},...l?{loadFactor:y.map((R,k)=>l(k,R.v))}:{},...FM(e,o,t,y.map(R=>R.v)),...b?AM(b,m):{}}}var wM=(e,t)=>{let r=e[t]?.value;return Number.isFinite(r)&&r>0?r:0};function lo(e,t,r){let n=e.m.value,o=e.r_dyn?.value??0,a=wM(e,"I_wheel"),s=e.motorModel?.kind==="ice"?0:wM(e,"I_rotor"),i=e.gear_ratio?.value??1;if(!(o>0)||a===0&&s===0)return{mass:n,driven:0,undriven:0,effective:n,powerFactor:1,tractionFactor:1};let c=o*o,l=(t?2:0)+(r?2:0),u=4-l,m=(l*a+s*i*i)/c,d=u*a/c,p=n+m+d;return{mass:n,driven:m,undriven:d,effective:p,powerFactor:n/p,tractionFactor:n/(n+d)}}function uo(e){let t=e.fAxle;return{drivenFront:t?t.fFront.some(r=>r>0):!1,drivenRear:t?t.fRear.some(r=>r>0):!0}}var Ni=36e5,LM=Math.PI*2,Vb=e=>Math.max(0,Math.min(1,e));function Bb(e){let t=e.motorModel;if(!t){let s=e.effi_pgb?.value??.9;return()=>s}if(t.kind==="simple"){let s=t.efficiency>.01?t.efficiency:.9;return()=>s}if(t.kind==="ice"){let s=t.gearbox.efficiency>.01?t.gearbox.efficiency:.9;return()=>s}let r=rl(t),n=e.gear_ratio.value,o=e.r_dyn.value,a=Math.max(1,Math.round(e.motorCount??e.driven_wheels.value));return(s,i)=>{let c=s*n/o*(60/LM),l=Math.max(0,i*o/(n*a)),u=r.efficiency(c,l);return u>.01?u:.5}}var CM=new WeakMap;function Ia(e){if(e.batteryModel)return e.batteryModel;let t=e.capacity.value,r=e.ocv.value,n=CM.get(e);if(n&&n.capacityAh===t&&n.ocv===r)return n.model;let o=hd(t,r);return CM.set(e,{capacityAh:t,ocv:r,model:o}),o}function $b(e){let t=e.params,r=$h(t,du(e));if(bt(t.motorModel)||ft(t).mode!=="hydraulic")return r;let n;return(o,a,s,i=0)=>{if(!(o>0))return 0;n??=_I(e);let c=Ru(n.inp,n.ev,o,a,i);return c?Math.min(o,c.regenFront+c.regenRear):r(o,a,s)}}var TM=new WeakMap;function _I(e){let t=e.params,r=TM.get(t);if(!r){let n=Vr(t);r={inp:ht(n.regen?t:{...t,energy:{...n,regen:!0}}),ev:hr(t)},TM.set(t,r)}return r}var Oi=e=>e.airTempC??Tt;function om(e,t){return e.thermal?e.thermal.startC??t:Ho}function PM(e,t,r,n,o,a){let s=e.thermal;if(!s||!(o>0)||!(s.heatCapacityJPerK>0))return t;let i=s.coolingWPerK*(t-a)*o,c=s.entropicVPerK!==0?-r*(t+273.15)*s.entropicVPerK*o:0;return t+(n+c-i)/s.heatCapacityJPerK}var DM=()=>({windingC:[],derate:[],lossW:[],torqueNm:[],ampsRms:[]});function NI(e){let t=e.motorModel;if(!t?.thermal)return;let r=bd(t.thermal),n=rl(t),o=e.gear_ratio.value,a=e.r_dyn.value,s=Math.max(1,Math.round(e.motorCount??e.driven_wheels.value));return{th:r,rpm:i=>i*o/a*(60/LM),peak:i=>n.maxTorque(i),amps:i=>t.thermal.torqueConstant>0?Math.abs(i)/t.thermal.torqueConstant:0,torque:(i,c,l)=>Math.min(Math.abs(i)*a/(o*s),l*n.maxTorque(c))}}function OI(e,t,r,n,o){let a=e.ocv(n);if(!(r>0))return{dq:t/a,lossJ:0,energyJ:t,short:!1,cutoff:!1,seconds:r};let s=e.maxPower(n,o),i=s.watts,c=t/r,l=Math.min(c,i),u=c>s.voltageFloor;if(u&&!(l>0))return{dq:1/0,lossJ:0,energyJ:0,short:!0,cutoff:u,seconds:1/0};let m=e.currentFor(l,n,o),d=u?c/l:1,p=r*d;return{dq:m*p,lossJ:m*m*e.resistance(n,o)*p,energyJ:l*p,short:c>i,cutoff:u,seconds:p}}function VI(e,t,r,n,o){let a=e.ocv(n);if(!(r>0))return{dq:t/a,lossJ:0,energyJ:t,short:!1,cutoff:!1,seconds:r};let s=e.resistance(n,o),i=e.chargeCurrentFor(t/r,n,o),c=Math.min(i,e.chargeCurrentCeiling),l=c===i?t:c*(a+c*s)*r;return{dq:c*r,lossJ:c*c*s*r,energyJ:l,short:c<i,cutoff:!1,seconds:r}}function BI(e){let{drivenFront:t,drivenRear:r}=uo(e);return lo(e.params,t,r)}function _a(e,t,r,n,o=Or,a,s,i,c,l,u){let m=e.params,d=m.rho.value,p=m.fr_0.value,f=m.m.value,h=e.FG,b=m.aeroModel?ht(m):void 0,g=Bb(m),y=Sr(Ia(m)),R=y.chargeC,k=Vb(a??m.soc.value),v=Oi(m),x=s??om(y,v),M=x,A=0,w=0,C=0,T=0,F=-1,S=-1,P=-1,L=NI(m),D=L?L.th.startC:0,I=D,O=0,_=1,z=-1,E=0,N=0,B=$b(e),V=m.motorModel?.kind==="ice",G=u?.scrub,K=G?f/BI(e).tractionFactor:0,Y=Math.min(t.length,r.length);for(let j=0;j<Y;j++){let Z=r[j],ne=Z*Z,te=n[j]-(c?.[j]??0),{cl:fe,cw:W,A:J}=Ju(m,Z,te/9.81,b),re=.5*d*fe*J*ne,pe=.5*d*W*J*ne,de=(h+re)*-p,ie=G?-K*(G[j]??0):0,oe=de+pe+ie+f*te,ue=oe*t[j],$e=j+1<r.length?r[j+1]:Z,Ae=.5*(Z+$e),le=Ae>0?t[j]/Ae:0,Re=0,Te=k,ze=x,je=0,be=0,Fe=le;if(V){oe>0&&(be=ue/g(Z,oe),A+=be/Ni),l?.netKwh.push(A-w),l?.powerKw?.push(le>0?be/le/1e3:0);continue}if(oe>0){let xe=ue/g(Z,oe),me=OI(y,xe,le,k,x);me.short&&F<0&&(F=j),me.cutoff&&S<0&&(S=j);let Le=k*R,Se=Math.min(me.dq,Le),Ye=me.dq>0?Se/me.dq:1;Se>=Le&&P<0&&(P=j),A+=me.energyJ*Ye/Ni,be=me.energyJ*Ye,Fe=me.seconds,C+=me.lossJ*Ye,T+=Se,le>0&&(je=Se/me.seconds),k=Vb(k-Se/R),x=PM(y,x,me.dq>0&&le>0?Se/le:0,me.lossJ*Ye,le,v),x>M&&(M=x),Re=oe}else if(o.regen){let xe=u?He(u.ay[j],u.bank?.[j]??0)/9.81:0,me=B(-oe,Z,te/9.81,xe),Le=o.regenEfficiency*me*t[j],Se=VI(y,Le,le,k,x),Ye=(1-k)*R,Ue=Math.min(Se.dq,Ye),jt=Se.dq>0?Ue/Se.dq:1;w+=Se.energyJ*jt/Ni,be=-Se.energyJ*jt,C+=Se.lossJ*jt,T-=Ue,le>0&&(je=-Ue/le),k=Vb(k+Ue/R),x=PM(y,x,Ue>0&&le>0?-Ue/le:0,Se.lossJ*jt,le,v),x>M&&(M=x),Re=-me*jt}if(l?.netKwh.push(A-w),l?.powerKw?.push(le>0?be/Fe/1e3:0),l?.pack){let xe=l.pack;xe.soc.push(Te),xe.amps.push(je),xe.volts.push(y.ocv(Te)-je*y.resistance(Te,ze)),xe.cellC.push(ze)}if(L){let xe=L.rpm(Z),me=L.th.derate(xe,D,L.peak(xe));me<_&&(_=me),me<1&&z<0&&(z=j),N+=le,me<1&&(E+=le);let Le=L.torque(Re,xe,me),Se=L.th.lossW(xe,Le,D);O+=Se*le,i&&(i.windingC.push(D),i.derate.push(me),i.lossW.push(Se),i.torqueNm.push(Le),i.ampsRms.push(L.amps(Le))),D=L.th.step(D,Se,le),D>I&&(I=D)}}return{drive:A,regen:w,net:A-w,chargeAh:T/3600,loss:C/Ni,socEnd:k,shortAt:F,cutoffAt:S,emptyAt:P,tempEndC:x,tempMaxC:M,...L?{motorTempEndC:D,motorTempMaxC:I,motorLossKwh:O/Ni,motorDerateMin:_,motorDerateAt:z,motorDerateTimeFrac:N>0?E/N:0}:{}}}var $I=.5,GI=.02,KI=6;function EM(e,t,r,n,o,a,s,i){let c=n(),l=1,u=f=>{let h=DM(),b=_a(e,t,f.v,f.ax,r,o,a,h,s,void 0,{ay:f.ay,bank:i,...f.axScrub?{scrub:f.axScrub}:{}});return{trace:h,peak:b.motorTempMaxC??0,frac:b.motorDerateTimeFrac??0}},m=u(c);if(!m.trace.derate.length||m.frac===0)return{lap:c,solves:l,converged:!0,peakWindingC:m.peak,derateTimeFrac:m.frac};let d=m.trace.derate.slice(),p=!1;for(let f=0;f<KI;f++){let h=n(d);l++;let b=Math.abs(h.laptime-c.laptime);if(c=h,m=u(c),b<GI){p=!0;break}let g=m.trace.derate,y=new Array(d.length);for(let R=0;R<d.length;R++)y[R]=d[R]+$I*((g[R]??1)-d[R]);d=y}return{lap:c,derate:d,solves:l,converged:p,peakWindingC:m.peak,derateTimeFrac:m.frac}}var HI=.1;function IM(e){let t=e.power_limit_kw?.value??0;return t>0?t*1e3:0}function Gb(e,t,r){return e.motorModel?.kind==="ice"?1/0:Sr(Ia(e)).maxPower(t??e.soc.value,r,IM(e)).watts}function am(e,t,r,n){let o=Gb(e,r,n);if(!Number.isFinite(o))return 1/0;if(o<=0)return 0;let a=Math.max(HI,t),s=Bb(e),i=o*(e.effi_pgb?.value??.9)/a;return o*s(t,i)/a}var zI=180/Math.PI;function sm(e,t,r,n){let o=e*t,a=e*(1-t);return o/r-a/n}var im=e=>e*9.81*zI;var Fq=Math.PI/180;function cm(e,t,r,n=0){let o=Ce(e,t,0,n),a=typeof r=="function"?r:r.front,s=typeof r=="function"?r:r.rear,i=.5*(a(Math.max(0,o.FL))+a(Math.max(0,o.FR))),c=.5*(s(Math.max(0,o.RL))+s(Math.max(0,o.RR))),l=i>0&&c>0?sm(e.massTotal,e.frontMassFrac,2*i,2*c):0,u=im(l),m=u>.15?"understeer":u<-.15?"oversteer":"neutral";return{gradient:u,balance:m,cAlphaFront:i,cAlphaRear:c}}var Iq=Math.PI/180,_q=180/Math.PI;var _M=2220446049250313e-31;function jI(e){let t=e.length,r=2,n=r*r,o=!1;for(;!o;){o=!0;for(let a=0;a<t;a++){let s=0,i=0;for(let c=0;c<t;c++)c!==a&&(i+=Math.abs(e[c][a]),s+=Math.abs(e[a][c]));if(i!==0&&s!==0){let c=s/r,l=1,u=i+s;for(;i<c;)l*=r,i*=n;for(c=s*r;i>c;)l/=r,i/=n;if((i+s)/l<.95*u){o=!1;let m=1/l;for(let d=0;d<t;d++)e[a][d]*=m;for(let d=0;d<t;d++)e[d][a]*=l}}}}}function UI(e){let t=e.length;for(let r=1;r<t-1;r++){let n=0,o=r;for(let a=r;a<t;a++)Math.abs(e[a][r-1])>Math.abs(n)&&(n=e[a][r-1],o=a);if(o!==r){for(let a=r-1;a<t;a++){let s=e[o][a];e[o][a]=e[r][a],e[r][a]=s}for(let a=0;a<t;a++){let s=e[a][o];e[a][o]=e[a][r],e[a][r]=s}}if(n!==0)for(let a=r+1;a<t;a++){let s=e[a][r-1];if(s!==0){s/=n,e[a][r-1]=s;for(let i=r;i<t;i++)e[a][i]-=s*e[r][i];for(let i=0;i<t;i++)e[i][r]+=s*e[i][a]}}}for(let r=2;r<t;r++)for(let n=0;n<r-1;n++)e[r][n]=0}function XI(e){let t=e.length,r=new Array(t).fill(0),n=new Array(t).fill(0),o=0;for(let i=0;i<t;i++)for(let c=Math.max(i-1,0);c<t;c++)o+=Math.abs(e[i][c]);let a=t-1,s=0;for(;a>=0;){let i=0,c=0;do{for(c=a;c>=1;c--){let u=Math.abs(e[c-1][c-1])+Math.abs(e[c][c]);if(u===0&&(u=o),Math.abs(e[c][c-1])<=_M*u){e[c][c-1]=0;break}}let l=e[a][a];if(c===a)r[a]=l+s,n[a]=0,a--;else{let u=e[a-1][a-1],m=e[a][a-1]*e[a-1][a];if(c===a-1){let d=.5*(u-l),p=d*d+m,f=Math.sqrt(Math.abs(p));l+=s,p>=0?(f=d+(d>=0?Math.abs(f):-Math.abs(f)),r[a-1]=r[a]=l+f,f!==0&&(r[a]=l-m/f),n[a-1]=n[a]=0):(r[a-1]=r[a]=l+d,n[a]=f,n[a-1]=-f),a-=2}else{if(i===60)throw new Error("eigenvalues: QR iteration did not converge");if(i===10||i===20||i===30||i===40||i===50){s+=l;for(let g=0;g<=a;g++)e[g][g]-=l;let b=Math.abs(e[a][a-1])+Math.abs(e[a-1][a-2]);u=l=.75*b,m=-.4375*b*b}i++;let d=a-2,p=0,f=0,h=0;for(;d>=c;d--){let b=e[d][d],g=l-b,y=u-b;p=(g*y-m)/e[d+1][d]+e[d][d+1],f=e[d+1][d+1]-b-g-y,h=e[d+2][d+1];let R=Math.abs(p)+Math.abs(f)+Math.abs(h);if(p/=R,f/=R,h/=R,d===c)break;let k=Math.abs(e[d][d-1])*(Math.abs(f)+Math.abs(h)),v=Math.abs(p)*(Math.abs(e[d-1][d-1])+Math.abs(b)+Math.abs(e[d+1][d+1]));if(k<=_M*v)break}for(let b=d+2;b<=a;b++)e[b][b-2]=0,b!==d+2&&(e[b][b-3]=0);for(let b=d;b<=a-1;b++){b!==d&&(p=e[b][b-1],f=e[b+1][b-1],h=b!==a-1?e[b+2][b-1]:0,l=Math.abs(p)+Math.abs(f)+Math.abs(h),l!==0&&(p/=l,f/=l,h/=l));let g=Math.sqrt(p*p+f*f+h*h),y=p>=0?g:-g;if(y!==0){b===d?c!==d&&(e[b][b-1]=-e[b][b-1]):e[b][b-1]=-y*l,p+=y,l=p/y,u=f/y;let R=h/y;f/=p,h/=p;for(let v=b;v<=a;v++){let x=e[b][v]+f*e[b+1][v];b!==a-1&&(x+=h*e[b+2][v],e[b+2][v]-=x*R),e[b+1][v]-=x*u,e[b][v]-=x*l}let k=a<b+3?a:b+3;for(let v=c;v<=k;v++){let x=l*e[v][b]+u*e[v][b+1];b!==a-1&&(x+=R*e[v][b+2],e[v][b+2]-=x*h),e[v][b+1]-=x*f,e[v][b]-=x}}}}}}while(c<a-1&&a>=0)}return r.map((i,c)=>({re:i,im:n[c]}))}function NM(e){let t=e.length;if(t===0)return[];for(let n of e)if(n.length!==t)throw new Error("eigenvalues: matrix must be square");for(let n of e)for(let o of n)if(!Number.isFinite(o))throw new Error("eigenvalues: matrix has non-finite entries");if(t===1)return[{re:e[0][0],im:0}];let r=e.map(n=>n.slice());return jI(r),UI(r),XI(r)}function OM(e){let t=[],r=new Array(e.length).fill(!1),n=NM(e);for(let o=0;o<n.length;o++){if(r[o])continue;let{re:a,im:s}=n[o];if(s<0)continue;let i=Math.hypot(a,s);t.push({freq:i/(2*Math.PI),dampedFreq:Math.abs(s)/(2*Math.PI),dampingRatio:i>0?-a/i:0,eigenvalue:n[o]})}return t.sort((o,a)=>a.freq-o.freq)}function Kb(e,t){let r=e.length,n=Array.from({length:r},(c,l)=>l);for(let c=0;c<r-1;c++){let l=c,u=c,m=-1;for(let h=c;h<r;h++)for(let b=c;b<r;b++){let g=e[h][b]*e[h][b]+t[h][b]*t[h][b];g>m&&(m=g,l=h,u=b)}if(!(m>0))break;if([e[c],e[l]]=[e[l],e[c]],[t[c],t[l]]=[t[l],t[c]],u!==c){for(let h=0;h<r;h++)[e[h][c],e[h][u]]=[e[h][u],e[h][c]],[t[h][c],t[h][u]]=[t[h][u],t[h][c]];[n[c],n[u]]=[n[u],n[c]]}let d=e[c][c],p=t[c][c],f=d*d+p*p;for(let h=c+1;h<r;h++){let b=(e[h][c]*d+t[h][c]*p)/f,g=(t[h][c]*d-e[h][c]*p)/f;if(!(b===0&&g===0))for(let y=c;y<r;y++)e[h][y]-=b*e[c][y]-g*t[c][y],t[h][y]-=b*t[c][y]+g*e[c][y]}}let o=new Array(r).fill(0),a=new Array(r).fill(0);o[r-1]=1;for(let c=r-2;c>=0;c--){let l=e[c][c],u=t[c][c],m=l*l+u*u;if(!(m>0))continue;let d=0,p=0;for(let f=c+1;f<r;f++)d+=e[c][f]*o[f]-t[c][f]*a[f],p+=e[c][f]*a[f]+t[c][f]*o[f];o[c]=-(d*l+p*u)/m,a[c]=-(p*l-d*u)/m}let s=Math.sqrt(o.reduce((c,l,u)=>c+l*l+a[u]*a[u],0)),i=new Array(r);for(let c=0;c<r;c++)i[n[c]]={re:o[c]/s,im:a[c]/s};return i}function qI(e,t){let r=e.map((o,a)=>o.map((s,i)=>a===i?s-t.re:s)),n=e.map((o,a)=>o.map((s,i)=>a===i?-t.im:0));return Kb(r,n)}function lm(e,t=r=>qI(e,r)){return OM(e).map(r=>({...r,vector:t(r.eigenvalue)}))}function Na(e,t,r){let n,o=-1,a,s=-1;for(let i of e){let c=t(i.vector),l=c[r];i.eigenvalue.im===0?l>s&&(a=i,s=l):l>=Math.max(...c)&&l>o&&(n=i,o=l)}return n??a}function VM(e){let t=e.sprungMass;if(!(t>0))return;let r=Math.max(.1,e.unsprungMass),n=e.springRate*1e3,o=e.damperRate*1e3,a=e.tireRate*1e3,s=(e.tireDamping??0)*1e3,i=[[0,1,0,0],[-n/t,-o/t,n/t,o/t],[0,0,0,1],[n/r,o/r,-(n+a)/r,-(o+s)/r]];if(!i.every(l=>l.every(Number.isFinite)))return;let c=l=>{let u=t*(l[0].re**2+l[0].im**2),m=r*(l[2].re**2+l[2].im**2);return u+m>0?[u/(u+m),m/(u+m)]:[0,0]};return Na(lm(i),c,0)}function BM(e,t,r,n){let o=(r==="front"?t.sprungFront:t.sprungRear)/2;if(o<=0)return{dampingRatio:0,criticalDamping:0,naturalFreqDamped:0};let a=r==="front"?t.rideRateFront:t.rideRateRear,s=r==="front"?e.wheelRateFront+(e.heaveSpringFront??0):e.wheelRateRear+(e.heaveSpringRear??0),i=VM({sprungMass:o,unsprungMass:e.unsprungCornerMass??e.unsprungPerCorner,springRate:s,damperRate:n,tireRate:Xe(e,r),tireDamping:e.tireDamping}),c=2*Math.sqrt(a*1e3*o);return{dampingRatio:i?.dampingRatio??0,criticalDamping:c/1e3,naturalFreqDamped:i?.dampedFreq??0}}function um(e,t,r){let n=we(e);return{front:BM(e,n,"front",t??n.rideDampingFront),rear:BM(e,n,"rear",r??n.rideDampingRear)}}var Uq=180/Math.PI;var Hb=["FL","FR","RL","RR"],ce={zFL:0,vzFL:1,zFR:2,vzFR:3,zRL:4,vzRL:5,zRR:6,vzRR:7,zBody:8,vzBody:9,pitch:10,pitchRate:11,roll:12,rollRate:13,x:14,vx:15,y:16,vy:17,yaw:18,yawRate:19},Oa=20,$M=[ce.zFL,ce.zFR,ce.zRL,ce.zRR],GM=[ce.vzFL,ce.vzFR,ce.vzRL,ce.vzRR],Ur={fzFL:0,fzFR:1,fzRL:2,fzRR:3,fzBody:4,myBody:5,mxBody:6,fx:7,fy:8,mz:9},zb=10;function mm(e){let t=Array.from({length:Oa},()=>new Array(Oa).fill(0)),r=Array.from({length:Oa},()=>new Array(zb).fill(0));t[ce.zFL][ce.vzFL]=1,t[ce.zFR][ce.vzFR]=1,t[ce.zRL][ce.vzRL]=1,t[ce.zRR][ce.vzRR]=1,t[ce.zBody][ce.vzBody]=1,t[ce.pitch][ce.pitchRate]=1,t[ce.roll][ce.rollRate]=1,t[ce.x][ce.vx]=1,t[ce.y][ce.vy]=1,t[ce.yaw][ce.yawRate]=1;let{inertia:n}=e,o=[1,0,3,2],a=(s,i,c,l)=>{s[$M[i]]-=c,s[GM[i]]-=l,s[ce.zBody]+=c,s[ce.vzBody]+=l,s[ce.pitch]-=c*e.leverX[i],s[ce.pitchRate]-=l*e.leverX[i],s[ce.roll]+=c*e.leverY[i],s[ce.rollRate]+=l*e.leverY[i]};for(let s=0;s<4;s++){let i=s<2,c=M=>M?i?M.front:M.rear:0,l=e.springRate[s]+c(e.heaveSpring),u=e.springRate[s]+c(e.arb),m=e.damperRate[s]+c(e.heaveDamper),d=e.damperRate[s]+c(e.rollDamper),p=(l+u)/2,f=(l-u)/2,h=(m+d)/2,b=(m-d)/2,g=new Array(Oa).fill(0);a(g,s,p,h),(f!==0||b!==0)&&a(g,o[s],f,b);let y=e.wheelMass[s],R=e.leverX[s],k=e.leverY[s],v=$M[s],x=GM[s];for(let M=0;M<Oa;M++){let A=g[M];A!==0&&(t[x][M]+=A/y,t[ce.vzBody][M]-=A/e.bodyMass,t[ce.pitchRate][M]+=R*A/n.yy,t[ce.rollRate][M]-=k*A/n.xx)}t[x][v]-=e.tyreRate[s]/y,t[x][x]-=e.tyreDamping[s]/y,r[x][Ur.fzFL+s]=1/y}return r[ce.vzBody][Ur.fzBody]=1/e.bodyMass,r[ce.pitchRate][Ur.myBody]=1/n.yy,r[ce.rollRate][Ur.mxBody]=1/n.xx,r[ce.vx][Ur.fx]=1/e.totalMass,r[ce.vy][Ur.fy]=1/e.totalMass,r[ce.yawRate][Ur.mz]=1/n.zz,{A:t,B:r,params:e}}function Yb(e){let t=e.wheelbase/1e3,r=t*(1-e.frontMassFrac),n=t*e.frontMassFrac,o=e.trackFront/2e3,a=e.trackRear/2e3,s=e.unsprungCornerMass??e.unsprungPerCorner,i=Math.max(0,e.massTotal-4*s),c=e.wheelRateFront*1e3,l=e.wheelRateRear*1e3,u=(e.damperFront??2.5)*1e3,m=(e.damperRear??2.5)*1e3,d=Xe(e,"front")*1e3,p=Xe(e,"rear")*1e3,f=(e.tireDamping??0)*1e3;return{bodyMass:i,totalMass:e.massTotal,wheelMass:[s,s,s,s],inertia:{xx:e.rollInertia??i*.6*.6,yy:e.pitchInertia??i*1.2*1.2,zz:e.yawInertia??e.massTotal*1.2*1.2},leverX:[r,r,-n,-n],leverY:[o,-o,a,-a],springRate:[c,c,l,l],damperRate:[u,u,m,m],tyreRate:[d,d,p,p],tyreDamping:[f,f,f,f],arb:{front:e.arbFront*1e3,rear:e.arbRear*1e3},heaveSpring:{front:(e.heaveSpringFront??0)*1e3,rear:(e.heaveSpringRear??0)*1e3},rollDamper:{front:(e.rollDamperFront??0)*1e3,rear:(e.rollDamperRear??0)*1e3},heaveDamper:{front:(e.heaveDamperFront??0)*1e3,rear:(e.heaveDamperRear??0)*1e3}}}var KM=ce.rollRate+1;function HM(e){let t=e.params,r=[...t.wheelMass,t.bodyMass,t.inertia.yy,t.inertia.xx];if(!r.every(i=>i>0))return{};let n=e.A.slice(0,KM).map(i=>i.slice(0,KM));if(!n.every(i=>i.every(Number.isFinite)))return{};let a=lm(n,i=>{let c=i.re*i.re-i.im*i.im,l=2*i.re*i.im,u=r.map((d,p)=>r.map((f,h)=>(p===h?c:0)-i.re*n[2*p+1][2*h+1]-n[2*p+1][2*h])),m=r.map((d,p)=>r.map((f,h)=>(p===h?l:0)-i.im*n[2*p+1][2*h+1]));return Kb(u,m)}),s=i=>{let c=r.map((u,m)=>u*(i[m].re**2+i[m].im**2)),l=c.reduce((u,m)=>u+m,0)||1;return[c[0]+c[1]+c[2]+c[3],c[4],c[5],c[6]].map(u=>u/l)};return{heave:Na(a,s,1),pitch:Na(a,s,2),roll:Na(a,s,3)}}function zM(e,t,r){let n=e?2*Math.PI*e.freq:0,o=e&&n>0?e.dampingRatio:0,a=o>0&&o<1?Math.exp(-Math.PI*o/Math.sqrt(1-o*o))*100:0,s=o>0&&n>0?4/(o*n):1/0;return{freq:n/(2*Math.PI),dampedFreq:e&&n>0?e.dampedFreq:0,dampingRatio:o,stiffness:t,inertia:r,overshoot:a,settlingTime:s}}function pm(e){let t=we(e),r=e.wheelbase/1e3,n=r*(1-e.frontMassFrac),o=r*e.frontMassFrac,a=t.rollRateTotal*(180/Math.PI),s=e.rollInertia??t.sprungMass*.6*.6,i=2*t.rideRateFront*1e3,c=2*t.rideRateRear*1e3,l=i*n*n+c*o*o,u=e.pitchInertia??t.sprungMass*1.2*1.2,m=HM(mm(Yb(e)));return{roll:zM(m.roll,a,s),pitch:zM(m.pitch,l,u)}}var dm=9.81,Xr=Math.PI/180;function YM(e){let t=e.wheelbase/1e3,r=t*(1-e.frontMassFrac),n=t*e.frontMassFrac;return{wb:t,lf:r,lr:n,m:e.massTotal}}function Va(e,t,r,n,o){let{wb:a,lf:s,lr:i,m:c}=YM(e),l=0;for(let R=0;R<16;R++){let k=l/r,v=o-n-s*k/r,x=-n+i*k/r,M=Ce(e,l/dm,0,r),A=Math.max(0,M.FL+M.FR),w=Math.max(0,M.RL+M.RR),C=t(v,A),T=t(x,w),F=(C*Math.cos(o)+T)/c;if(l=.5*(l+F),Math.abs(F-l)<1e-4)break}let u=l/r,m=o-n-s*u/r,d=-n+i*u/r,p=Ce(e,l/dm,0,r),f=Math.max(0,p.FL+p.FR),h=Math.max(0,p.RL+p.RR),b=t(m,f),g=t(d,h),y=s*b*Math.cos(o)-i*g;return{ay:l/dm,cn:y/(c*dm*a)}}function Wb(e,t,r,n={}){let o=Math.max(8,r),a=(n.betaMaxDeg??10)*Xr,s=(n.deltaMaxDeg??10)*Xr,i=n.nLines??9,c=n.nPts??21,l=(g,y,R,k)=>R===1?g:g+(y-g)*k/(R-1),u=[],m={ay:[],cn:[]},d=0;for(let g=0;g<i;g++){let y=l(-s,s,i,g),R=[],k=[],v=[],x=[];for(let M=0;M<c;M++){let A=l(-a,a,c,M),w=Va(e,t,o,A,y);R.push(w.ay),k.push(w.cn),v.push(A/Xr),x.push(y/Xr),Math.abs(w.ay)>d&&(d=Math.abs(w.ay))}u.push({label:`\u03B4 ${(y/Xr).toFixed(0)}\xB0`,ay:R,cn:k,betaDeg:v,deltaDeg:x});for(let M=1;M<k.length;M++)if(k[M-1]===0||k[M-1]<0!=k[M]<0){let A=k[M-1]===k[M]?0:k[M-1]/(k[M-1]-k[M]);m.ay.push(R[M-1]+A*(R[M]-R[M-1])),m.cn.push(0);break}}let p=[];for(let g=0;g<i;g++){let y=l(-a,a,i,g),R=[],k=[],v=[],x=[];for(let M=0;M<c;M++){let A=l(-s,s,c,M),w=Va(e,t,o,y,A);R.push(w.ay),k.push(w.cn),v.push(y/Xr),x.push(A/Xr)}p.push({label:`\u03B2 ${(y/Xr).toFixed(0)}\xB0`,ay:R,cn:k,betaDeg:v,deltaDeg:x})}let f=.5*Xr,h=(Va(e,t,o,f,0).cn-Va(e,t,o,-f,0).cn)/(2*f),b=(Va(e,t,o,0,f).cn-Va(e,t,o,0,-f).cn)/(2*f);return{isoBeta:p,isoDelta:u,trim:m,maxAy:d,stability:h,control:b,speed:o}}function QI(e){return!e.corneringStiffnessFront||!e.corneringStiffnessRear?null:{Cf:2*e.corneringStiffnessFront,Cr:2*e.corneringStiffnessRear}}function Vi(e,t){let r=QI(e);if(!r)return null;let{Cf:n,Cr:o}=r,{wb:a,lf:s,lr:i,m:c}=YM(e),l=e.yawInertia??c*1*1,u=Math.max(3,t),m=-(n+o)/(c*u),d=(-s*n+i*o)/(c*u)-u,p=(-s*n+i*o)/(l*u),f=-(s*s*n+i*i*o)/(l*u),h=m+f,b=m*f-d*p,g=h*h-4*b,y,R,k;if(g<0)y=h/2,R=Math.sqrt(Math.max(0,b)),k=R>0?-h/(2*R):1;else{let P=Math.sqrt(g);y=Math.max((h+P)/2,(h-P)/2),R=Math.sqrt(Math.abs(b)),k=R>0?-h/(2*R):1}let v=h<0&&b>0,x=sm(c,e.frontMassFrac,n,o),M=im(x),A=M>.15?"understeer":M<-.15?"oversteer":"neutral",w=s*n-i*o,C=P=>P*3.6,T=null,F=null;w>1e-6?F=C(Math.sqrt(n*o*a*a/(c*w))):w<-1e-6&&(T=C(Math.sqrt(n*o*a*a/(c*-w))));let S=u/(a+x*u*u);return{stable:v,yawFreq:R/(2*Math.PI),dampingRatio:k,eigReal:y,understeerGradient:M,balance:A,characteristicSpeed:T,criticalSpeed:F,yawRateGain:S}}var WM=Math.PI/180;function XM(e,t){let r=Math.abs(e);return r<.15?"no measurable body slip \u2014 the car is travelling along its own centreline":Math.abs(t)<1e-6?`${r.toFixed(1)}\xB0 of body slip (not cornering, so there is no inside or outside yet)`:e*Math.sign(t)>0?`${r.toFixed(1)}\xB0 of body slip, nose pointing OUT of the corner \u2014 running wide of the path it is on`:`${r.toFixed(1)}\xB0 of body slip, nose pointing INTO the corner \u2014 rotated inside the path it is on`}function jM(e,t,r){return e.length<2?0:t<=0?(e[1]-e[0])/r:t>=e.length-1?(e[e.length-1]-e[e.length-2])/r:(e[t+1]-e[t-1])/(2*r)}function qM(e,t,r,n){let o=e.isoDelta.length,a=e.isoDelta[0]?.ay.length??0,s=Math.max(0,Math.min(o-1,Math.floor(t))),i=Math.max(0,Math.min(a-1,Math.floor(r))),c=Math.max(0,Math.min(1,t-s)),l=Math.max(0,Math.min(1,r-i)),u=0;for(let[m,d]of[[s,1-c],[Math.min(o-1,s+1),c]])if(!(d<=0))for(let[p,f]of[[i,1-l],[Math.min(a-1,i+1),l]])f<=0||(u+=d*f*n(e.isoDelta[m],p,m));return u}function QM(e,t,r){let n=e.isoDelta[0],o=(n.betaDeg[1]-n.betaDeg[0])*WM||1,a=e.isoDelta.length>1?(e.isoDelta[1].deltaDeg[0]-e.isoDelta[0].deltaDeg[0])*WM:1,s=x=>qM(e,t,r,x),i=s((x,M)=>x.ay[M]),c=s((x,M)=>x.cn[M]),l=s((x,M)=>x.betaDeg[M]),u=s((x,M)=>x.deltaDeg[M]),m=s((x,M)=>jM(x.cn,M,o)),d=s((x,M,A)=>jM(e.isoDelta.map(w=>w.cn[M]),A,a||1)),p=Math.max(1e-6,e.maxAy),f=Math.abs(i)/p,h=Math.max(1e-6,...e.isoDelta.flatMap(x=>x.cn.filter(Number.isFinite).map(Math.abs))),b=Math.abs(c)/h,g=i===0?c:c*Math.sign(i),y=[];y.push(`${XM(l,i)}.`),b<.03?y.push("On the trim line: yaw moments balance, so this is a steady corner the car can actually hold. Only points on this line are real cornering states \u2014 everywhere else the car is still rotating."):g>0?y.push(`Not a steady state: there is a surplus yaw moment turning the car further into the corner, so it would keep rotating from here. To hold ${Math.abs(i).toFixed(2)} g the driver would have to wind ${u>=0?"off":"on"} steer until the point reaches the trim line.`):y.push("Not a steady state: the yaw moment is straightening the car out, so it would run wide from here. The car needs more steer, or more front grip, to reach the trim line at this slip angle.");let R=Math.abs(e.stability)>1e-9?m/e.stability:1;R<.15?y.push("Yaw stiffness has collapsed here: the moment resisting a change in body slip is essentially gone, so the car will not gather itself up if it steps out. Both axles are close to saturation."):R<.85?y.push(`Yaw stiffness is down to about ${(100*R).toFixed(0)} % of its straight-ahead value \u2014 the car resists a change in body slip less firmly here than it does in the linear range.`):y.push(`Yaw stiffness is near its straight-ahead value (${(100*R).toFixed(0)} %), so the car still opposes a change in body slip about as firmly as it does in a straight line.`);let k=Math.abs(e.control),v=k>1e-9?Math.abs(d)/k:1;return v<.15?y.push("The steering has stopped working here: another degree of lock buys almost no yaw moment, which is what a saturated front axle looks like. This is understeer in its literal sense \u2014 the front tyres are already at their limit."):v<.5&&y.push(`Steering response is down to about ${(100*v).toFixed(0)} % of its straight-ahead value \u2014 the front is well into the non-linear part of its curve.`),f>.97?y.push(`At the edge of the diagram: ${Math.abs(i).toFixed(2)} g is essentially all this car has at this speed.`):f<.25&&y.push("Well inside the limit \u2014 this is the linear region the handling balance is measured in."),{ay:i,cn:c,betaDeg:l,deltaDeg:u,stability:m,control:d,gripUsed:f,notes:y}}var UM=1e-4;function jb(e){let t=null,r=d=>{if(!t)return!0;let p=Math.abs(d),f=Math.abs(t.ay);return p>f*(1+UM)?!0:p<f*(1-UM)?!1:d>0&&t.ay<0};for(let d=0;d<e.isoDelta.length;d++){let p=e.isoDelta[d];for(let f=1;f<p.cn.length;f++){if(!(p.cn[f-1]===0||p.cn[f-1]<0!=p.cn[f]<0))continue;let b=p.cn[f-1]===p.cn[f]?0:p.cn[f-1]/(p.cn[f-1]-p.cn[f]),g=p.ay[f-1]+b*(p.ay[f]-p.ay[f-1]);r(g)&&(t={ay:g,d,b:b<.5?f-1:f})}}if(!t)return null;let n=QM(e,t.d,t.b),o=Math.abs(e.control)>1e-9?Math.abs(n.control/e.control):1,a=Math.abs(e.stability)>1e-9?n.stability/e.stability:1,s=o<.35,i=a<.35,c=s&&i?"both":s?"front":i?"rear":o<a?"front":"rear",l=e.isoDelta[t.d].betaDeg.length,u=t.b===0||t.b===l-1||t.d===0||t.d===e.isoDelta.length-1,m=t.ay<0?-1:1;return{ay:Math.abs(t.ay),turn:m,betaDeg:e.isoDelta[t.d].betaDeg[t.b]*m,deltaDeg:e.isoDelta[t.d].deltaDeg[t.b]*m,d:t.d,b:t.b,limitedBy:c,controlFrac:o,stiffnessFrac:a,onGridEdge:u}}var ZI=["tv_kp"];function ZM(e=0){let t=e<0,r=e>0,n=t||r,o=[{key:"damper_front",why:"dampers act on velocity; every point here is at constant attitude"},{key:"damper_rear",why:"dampers act on velocity; every point here is at constant attitude"},{key:"tire_vertical_damping",why:"tyre damping acts on velocity; every point here is at constant attitude"},{key:"I_yaw",why:"inertia resists change; a steady corner has none"},{key:"I_roll",why:"inertia resists change; a steady corner has none"},{key:"I_pitch",why:"inertia resists change; a steady corner has none"},{key:"capacity",why:"energy does not enter a single steady-state point"},{key:"ocv",why:"energy does not enter a single steady-state point"},{key:"soc",why:"energy does not enter a single steady-state point"},...ZI.map(s=>({key:s,why:"the feedback gain multiplies a yaw error, and a trimmed point has none \u2014 the feedforward does move this diagram"}))];t||o.push({key:"brake_balance",why:r?"the diagram is drawn under acceleration, not braking":"no braking: the diagram is drawn at constant speed"});let a=n?"the longitudinal condition is set directly; what a motor could deliver is the lap solver\u2019s question":"no tractive force is applied at a constant speed";for(let s of["gear_ratio","power_scale","power_limit_kw","driven_wheels","effi_pgb"])o.push({key:s,why:a});for(let s of["I_wheel","I_rotor"])o.push({key:s,why:n?"rotating inertia is longitudinal, and `ax` is set here rather than solved \u2014 nothing in this picture spins a wheel up":"rotating inertia only acts where the car changes speed"});return o.push({key:"v_limit_endurance",why:"a limiter constrains a lap\u2019s speed profile; this diagram is drawn at one imposed speed"}),o.push({key:"endurance_reserve",why:"an energy budget sets the long event\u2019s speed ceiling; this diagram is drawn at one imposed speed"}),o.push({key:"fr_0",why:n?"rolling resistance is a drag term; `ax` is what the car does, not what the tyres are handed":"rolling resistance is longitudinal"}),o.push({key:"r_dyn",why:n?"the force each tyre carries is set here in newtons; a radius would only convert it to a torque":"the rolling radius only matters where a wheel is driven or braked"}),o}var JI=ZM(0);function JM(e=0){let t="Springs and bars act through the roll-stiffness split and the camber the wheels take in roll; a heave spring reaches it too, but only faintly, through how far aero pushes the car down onto its camber curve.";if(!e)return"Steady state, lateral only: every point is a car in equilibrium at constant speed. Dampers, inertias, brake balance and the whole powertrain therefore cannot appear here \u2014 not because they are ignored, but because nothing in this picture accelerates. "+t;let r=e<0?`braking at ${Math.abs(e).toFixed(2)} g`:`accelerating at ${e.toFixed(2)} g`,n=e<0?"the brake balance decides which axle pays for it":"the driven axle pays for it";return`Steady state, ${r}: the load has moved ${e<0?"forward":"rearward"} and every tyre is spending part of its grip longitudinally, so ${n}. Dampers and inertias still cannot appear \u2014 the attitude is constant, it is simply not level. `+t}var e2=JM(0);var t2=9.81;function r2(e){let t=e.wheelbase/1e3;return{lf:t*(1-e.frontMassFrac),lr:t*e.frontMassFrac}}function Bi(e,t,r,n){let o=t.tire;if(!o)return null;let s=(r==="limit"?hb(e,o,t.speed):Rn(e,o,t.speed,t.ayG)).wheels;return Pr(n??Jn(o,e.massTotal*t2*1.2),{FL:s.FL,FR:s.FR,RL:s.RL,RR:s.RR},r2(e))}function n2(e){if(!e.tire)return e.cornerStiffness;let t=ye(e.tire,"front"),r=ye(e.tire,"rear");return{front:n=>t.corneringStiffness(n),rear:n=>r.corneringStiffness(n)}}var eS=[{key:"understeer",label:"Understeer gradient",unit:"\xB0/g",compute:(e,t)=>cm(e,t.ayG,n2(t),t.speed).gradient},{key:"rollGradient",label:"Roll gradient",unit:"\xB0/g",compute:e=>we(e).rollGradient},{key:"pitchGradient",label:"Pitch gradient",unit:"\xB0/g",compute:e=>we(e).pitchGradient},{key:"tlltdFront",label:"TLLTD front",unit:"%",compute:e=>100*Cf(e)},{key:"rollStiffFront",label:"Front roll-stiffness",unit:"%",compute:e=>100*we(e).frontRollStiffFrac},{key:"rideFreqFront",label:"Ride freq front",unit:"Hz",compute:e=>we(e).rideFreqFront},{key:"rideFreqRear",label:"Ride freq rear",unit:"Hz",compute:e=>we(e).rideFreqRear},{key:"rollFreq",label:"Roll-mode freq",unit:"Hz",compute:e=>pm(e).roll.freq},{key:"pitchFreq",label:"Pitch-mode freq",unit:"Hz",compute:e=>pm(e).pitch.freq},{key:"zetaFront",label:"Damping \u03B6 front",unit:"-",compute:e=>um(e).front.dampingRatio},{key:"zetaRear",label:"Damping \u03B6 rear",unit:"-",compute:e=>um(e).rear.dampingRatio},{key:"yawFreq",label:"Yaw natural freq",unit:"Hz",compute:(e,t)=>Vi(e,t.speed)?.yawFreq??NaN},{key:"yawZeta",label:"Yaw damping \u03B6",unit:"-",compute:(e,t)=>Vi(e,t.speed)?.dampingRatio??NaN},{key:"stabilitySpeed",label:"Char./critical speed",unit:"km/h",compute:(e,t)=>{let r=Vi(e,t.speed);return r?r.criticalSpeed??r.characteristicSpeed??NaN:NaN}},{key:"maxAy",label:"Max lateral accel",unit:"g",compute:(e,t)=>t.fyAxle?Wb(e,t.fyAxle,t.speed,{betaMaxDeg:12,deltaMaxDeg:12}).maxAy:NaN},{key:"yawReserveRear",label:"Yaw stability reserve",unit:"N\xB7m",compute:(e,t)=>Bi(e,t,"operating")?.stabil??NaN},{key:"yawReserveFront",label:"Yaw agility reserve",unit:"N\xB7m",compute:(e,t)=>Bi(e,t,"operating")?.agil??NaN},{key:"limitBalance",label:"Limit balance (+US / \u2212OS)",unit:"-",compute:(e,t)=>Bi(e,t,"limit")?.rel??NaN},{key:"yawStiffness",label:"Yaw stiffness N_\u03B2",unit:"N\xB7m/rad",compute:(e,t)=>t.tire?fb(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorque",label:"Steering holding torque",unit:"N\xB7m",compute:(e,t)=>t.tire?pb(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorqueGradient",label:"Steering feedback gradient",unit:"N\xB7m/g",compute:(e,t)=>t.tire?db(e,t.tire,t.speed,t.ayG):NaN}],Ub=Object.fromEntries(eS.map(e=>[e.key,e]));var qr=9.81;function o2(e,t,r){let n=Math.abs(e);return n>0?t>0&&(n<=t||t>=r)?n/t:r>0?1+(n-t)/r:2:0}var a2={front:!1,rear:!0};function Ba(e,t,r){let n=e.muX(t)*t,o=e.muY(t)*t;if(!(n>0))return 0;let a=o>0?Math.min(1,r/o):1;return n*Math.sqrt(1-a*a)}function tS(e,t,r,n,o,a){let s=e[t]+e[r];if(!(s>0))return;let i=Ba(n,o[t],a[t]),c=Ba(n,o[r],a[r]);i+c>0||(i=n.muX(o[t])*o[t],c=n.muX(o[r])*o[r]),i+c>0&&(e[t]=s*i/(i+c),e[r]=s-e[t])}function rS(e,t,r,n,o,a={},s="open"){if(!e.rear)return 1;if(!e.front)return 0;let i=(d,p,f)=>f?ci(d,p,f):s==="own"?d+p:2*Math.min(d,p),c=i(Ba(n,t.FL,r.FL),Ba(n,t.FR,r.FR),a.front),l=i(Ba(o,t.RL,r.RL),Ba(o,t.RR,r.RR),a.rear);if(c+l>0)return c/(c+l);let u=n.muX(t.FL)*t.FL+n.muX(t.FR)*t.FR,m=o.muX(t.RL)*t.RL+o.muX(t.RR)*t.RR;return u+m>0?u/(u+m):.5}function Xb(e,t,r,n){return{car:t?aS(t,r.loadFactor[n]):e,ayTyre:He(r.ay[n],r.bank?.[n]??0),axCar:r.ax[n]-(r.axGrade?.[n]??0)}}function nS(e,t){if(!e.aero?.model)return 0;let r=Math.min(t.v.length,t.ax.length,t.ay.length),n=t.loadFactor?hm(e):void 0,o=0,a=0;for(let s=0;s<r;s++){let i=t.ds?.[s]??1,c=Xb(e,n,t,s);o+=i,wf(c.car,t.v[s],c.axCar/qr,c.ayTyre/qr)&&(a+=i)}return o>0?a/o:0}function oS(e,t,r){let n=Xt(ye(t,"front")),o=Xt(ye(t,"rear")),a=Math.min(r.v.length,r.ax.length,r.ay.length),s=r.loadFactor?hm(e):void 0,i=0,c=0;for(let l=0;l<a;l++){let u=r.ds?.[l]??1,m=Xb(e,s,r,l);i+=u;let d=Ce(m.car,m.ayTyre/qr,m.axCar/qr,r.v[l]);(d.FL>n||d.FR>n||d.RL>o||d.RR>o)&&(c+=u)}return i>0?c/i:0}function fm(e,t,r,n={}){let o=Math.min(r.v.length,r.ax.length,r.ay.length),a=e.wheelbase/1e3,s=a*(1-e.frontMassFrac),i=a*e.frontMassFrac,c=hi(t,e.massTotal*qr*1.2),l=da(c,"front"),u=da(c,"rear"),m=pt(ye(t,"front")),d=pt(ye(t,"rear")),p=n.perWheel?Df(m,l):null,f=n.perWheel?d===m?p:Df(d,u):null,h=n.driven??a2,b={front:Kt(e,"front",1),rear:Kt(e,"rear",1)},g={front:0,rear:0},y=new Array(o),R=new Array(o),k=new Array(o),v=1/0,x=0,M=0,A=Xt(m),w=Xt(d),C=0,T=0,F=0,S=0,P=0,L=0,D=["FL","FR","RL","RR"],I=n.perWheel?Object.fromEntries(D.map(_=>[_,{Fz:new Array(o),alpha:new Array(o),Fy:new Array(o),Fx:new Array(o),Mz:new Array(o),used:new Array(o),FxCap:new Array(o),FyCap:new Array(o)}])):void 0,O=r.loadFactor?hm(e):void 0;for(let _=0;_<o;_++){let z=Xb(e,O,r,_),{ayTyre:E,axCar:N}=z,B=E/qr,V=Ce(z.car,B,N/qr,r.v[_]),G=e.massTotal*E,K=G*i/a,Y=G*s/a,j=Ks(m,K,V.FL,V.FR,P),Z=Ks(d,Y,V.RL,V.RR,L);P=j,L=Z;let ne={FL:Math.abs(m.Fy(j,V.FL,0)),FR:Math.abs(m.Fy(j,V.FR,0)),RL:Math.abs(d.Fy(Z,V.RL,0)),RR:Math.abs(d.Fy(Z,V.RR,0))},te=(N-(r.axDrag?.[_]??0)-(r.axScrub?.[_]??0))/qr,fe=te>0&&h.front?rS(h,V,ne,l,u,b,"own"):0,W=r.v[_]*r.v[_],J=e.driveline?{Fz:V,alpha:{front:j,rear:Z},curvature:W>1?r.ay[_]/W:0,seed:g}:void 0,re={...cb(e,te,r.v[_],t,B,fe,J)};te>0&&(b.front||tS(re,"FL","FR",l,V,ne),b.rear||tS(re,"RL","RR",u,V,ne));let pe=!1,de=!1;for(let ue of["FL","FR","RL","RR"]){let $e=(ue==="FL"||ue==="FR"?l:u).muX(V[ue])*V[ue];Math.abs(re[ue])>$e&&(pe=!0),V[ue]>(ue==="FL"||ue==="FR"?A:w)&&(de=!0)}de&&(M+=r.ds?.[_]??1);let ie=Pr(c,{FL:{Fz:V.FL,Fy:ne.FL,Fx:re.FL},FR:{Fz:V.FR,Fy:ne.FR,Fx:re.FR},RL:{Fz:V.RL,Fy:ne.RL,Fx:re.RL},RR:{Fz:V.RR,Fy:ne.RR,Fx:re.RR}},{lf:s,lr:i});if(y[_]=ie.stabil,R[_]=ie.agil,k[_]=ie.rel,I){let ue=.5*(V.FL+V.FR),$e=.5*(V.RL+V.RR),Ae=l.muX(ue)*ue,le=u.muX($e)*$e;for(let Re of D){let Te=V[Re],ze=Re==="FL"||Re==="FR",je=ze?l:u,be=je.muY(Te)*Te,Fe=je.muX(Te)*Te,xe=I[Re],me=ze?j:Z;xe.Fz[_]=Te,xe.alpha[_]=me,xe.Fy[_]=ne[Re],xe.Fx[_]=re[Re],xe.Mz[_]=Te>0?(ze?m:d).Mz(me,Te,0):0,xe.FxCap[_]=Fe,xe.FyCap[_]=be;let Le=be>0?Math.min(1,Math.abs(ne[Re])/be):0,Se=o2(re[Re],Fe,ze?Ae:le),Ye=ze?p:f,Ue=Ye&&Te>0?Ye.reach(Te,Math.sign(re[Re])*Se,Le):1;xe.used[_]=Math.hypot(Le,Se)/Ue}}ie.stabil<v&&(v=ie.stabil,x=_);let oe=r.ds?.[_]??1;S+=oe,ie.diff>0&&(C+=oe),pe&&(T+=oe),wf(z.car,r.v[_],N/qr,B)&&(F+=oe)}return{stabil:y,agil:R,rel:k,minStabil:Number.isFinite(v)?v:0,minStabilAt:x,pastTurnoverFrac:S>0?M/S:0,understeerFrac:S>0?C/S:0,beyondFrac:S>0?T/S:0,aeroOutsideFrac:S>0?F/S:0,wheels:I}}function hm(e){return Object.create(e,{loadFactor:{value:1,writable:!0,enumerable:!0}})}function aS(e,t){return e.loadFactor=t,e}var qb=9.81;function Qb(e,t,r,n={}){let o=r.v.length,a=e.massTotal,s=$r(e),i=s.mode==="hydraulic",c={front:new Array(o).fill(0),rear:new Array(o).fill(0),...n.regen?{regen:new Array(o).fill(0)}:{},...i?{pFront:new Array(o).fill(0),pRear:new Array(o).fill(0),pedalN:new Array(o).fill(0)}:{}};for(let l=0;l<o;l++){let u=r.v[l],m=r.ax[l]-(r.axGrade?.[l]??0),d=m-(r.axDrag?.[l]??0)-(r.axScrub?.[l]??0),p=-a*d;if(!(p>0))continue;let f=He(r.ay[l],r.bank?.[l]??0)/qb,h=Math.min(.99,Math.max(.01,ka(e,d/qb,u,t,f)));c.front[l]=p*h,c.rear[l]=p*(1-h);let b=i?Ru(e,t,p,u,f):void 0;if(c.regen&&n.regen&&(c.regen[l]=b?Math.min(p,b.regenFront+b.regenRear):n.regen(p,u,m/qb)),c.regen&&b){let g=b.regenFront+b.regenRear,y=g>0?c.regen[l]/g:0;(c.regenFront??=new Array(o).fill(0))[l]=b.regenFront*y,(c.regenRear??=new Array(o).fill(0))[l]=b.regenRear*y}if(i){let g=b?b.demand:s.demand(s.controlFor(p,u),u);c.pFront[l]=g.pFront,c.pRear[l]=g.pRear,c.pedalN[l]=g.pedalN}}return c}var oZ=Math.PI/180;var aZ=Hb.map(bi);var sZ=[ce.zFL,ce.zFR,ce.zRL,ce.zRR];var iZ=Array.from({length:ce.rollRate+1},(e,t)=>t);var y2=9.81,x2=.001,R2=.6,v2=2,lS=4;function uS(e,t,r,n=lS){let o=Math.min(e.v.length,t.npts),{ds:a,closed:s}=t,i=r.massTotal*y2*r.wheelbase,c=k2(e.ay.slice(0,o).map((m,d)=>m/Math.max(x2,e.v[d])),a,s,n),l=new Array(o).fill(0),u=new Array(o).fill(0);if(!(i>0))return{demand:l,rdot:u};for(let m=0;m<o;m++){let d=m===0?s?o-1:-1:m-1,p=m===o-1?s?0:-1:m+1;if(d<0||p<0)continue;let f=a[d]+a[m];if(!(f>0))continue;u[m]=e.v[m]*(c[p]-c[d])/f;let h=Math.sign(c[m]);l[m]=h===0?0:h*r.yawInertia*u[m]/i}return{demand:l,rdot:u}}function k2(e,t,r,n){let o=e.length;if(!(n>0)||o<3)return e;let a=new Array(o);a[0]=0;for(let c=1;c<o;c++)a[c]=a[c-1]+t[c-1];let s=r?Math.floor((o-1)/2):o-1,i=new Array(o);for(let c=0;c<o;c++){let l=r?n:Math.min(n,a[c],a[o-1]-a[c]),u=e[c],m=1,d=0;for(let p=1;p<=s&&!(!r&&c+p>=o||(d+=t[(c+p-1)%o],!(d<l)));p++){let f=1-d/l;u+=f*e[(c+p)%o],m+=f}d=0;for(let p=1;p<=s&&!(!r&&c-p<0);p++){let f=(c-p+o)%o;if(d+=t[f],!(d<l))break;let h=1-d/l;u+=h*e[f],m+=h}i[c]=u/m}return i}function mS(e,t,r,n,o={}){let a=o.maxIter??20,s=o.tol??.001,i=Math.min(1,Math.max(.001,o.relax??R2)),c=o.smoothM??lS,l={standingStart:o.standingStart,...o.driveDerate?{driveDerate:o.driveDerate}:{},...o.brakeFade?{brakeFade:o.brakeFade}:{},...o.vCeiling?{vCeiling:o.vCeiling}:{},...o.load?{load:o.load}:{},...o.shifts?{shifts:o.shifts}:{}},u=kt(e.steady,t,n,l),m=[u.laptime],d=new Array(t.npts).fill(0),p=d.slice(),f=u,h=0,b=!1,g=0;for(let k=0;k<a;k++){h=k+1;let v=uS(f,t,r,c);d=v.demand.map((A,w)=>d[w]+i*(A-d[w])),p=v.rdot;let x=kt(e.steady,t,n,{...l,envelope:A=>e.at(d[A]??0)});m.push(x.laptime);let M=Math.abs(x.laptime-f.laptime);if(f=x,g=M<=s?g+1:0,g>=v2){b=!0;break}}let y=0,R=0;for(let k=0;k<t.npts;k++)R+=t.ds[k],e.clamps(d[k]??0)&&(y+=t.ds[k]);return{...f,steady:u,demand:d,rdot:p,history:m,iterations:h,converged:b,clampedFrac:R>0?y/R:0}}var bZ=Math.PI/180;var UZ=180/Math.PI;function $a(e,t,r){let n=e.length;if(n===1||r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0;for(;o<n-2&&e[o+1]<=r;)o++;let a=e[o],s=e[o+1],i=t[o],c=t[o+1];if(n===2)return i+(r-a)/(s-a)*(c-i);let l=d=>{let p=e[d];return i*(r-s)*(r-p)/((a-s)*(a-p))+c*(r-a)*(r-p)/((s-a)*(s-p))+t[d]*(r-a)*(r-s)/((p-a)*(p-s))},u=(r-a)/(s-a),m=o===0?l(2):o+1===n-1?l(o-1):(1-u)*l(o-1)+u*l(o+2);return Math.min(Math.max(i,c),Math.max(Math.min(i,c),m))}function dS(e,t){let r=e.filter(p=>p.atLock),n=e.filter(p=>!p.atLock),o=r.length>0&&n.length>0&&r[r.length-1].v<n[0].v,a=p=>({vs:p.map(h=>h.v),ayMax:p.map(h=>h.ayMax),radius:p.map(h=>Math.max(h.v,t)**2/h.ayMax),accel:p[0].axAccelN.map((h,b)=>p.map(g=>g.axAccelN[b])),decel:p[0].axDecelN.map((h,b)=>p.map(g=>g.axDecelN[b])),scrub:p[0].axScrubN.map((h,b)=>p.map(g=>g.axScrubN[b]))}),s=(p,f)=>({axAccelN:p.accel.map(h=>$a(p.vs,h,f)),axDecelN:p.decel.map(h=>$a(p.vs,h,f)),axScrubN:p.scrub.map(h=>$a(p.vs,h,f))});if(!o){let p=a(e);return f=>({ayMax:$a(p.vs,p.ayMax,f),...s(p,f)})}let i=a(r),c=a(n),l=i.vs[i.vs.length-1],u=c.vs[0],m=p=>Math.max(p,t)**2/$a(i.vs,i.radius,p),d=p=>p>=u||c.vs.length<2?$a(c.vs,c.ayMax,p):c.ayMax[0]+(c.ayMax[1]-c.ayMax[0])/(c.vs[1]-c.vs[0])*(p-u);return p=>{if(p<=l)return{ayMax:m(p),...s(i,p)};if(p>=u)return{ayMax:d(p),...s(c,p)};let f=m(p),h=d(p);return f<h?{ayMax:f,...s(i,p)}:{ayMax:h,...s(c,p)}}}function B2(e,t){let r=Math.abs(e.ayMax-t.ayMax)/Math.max(t.ayMax,1),n=Math.max(Math.abs(t.axAccelN[0]),1),o=Math.max(Math.abs(t.axDecelN[0]),1);for(let a=0;a<t.axAccelN.length;a++)r=Math.max(r,Math.abs(e.axAccelN[a]-t.axAccelN[a])/n,Math.abs(e.axDecelN[a]-t.axDecelN[a])/o,Math.abs(e.axScrubN[a]-t.axScrubN[a])/n);return r}function fS(e,t,r,n,o){let a=r>t?Math.max(2,Math.min(5,Math.floor(n))):1,s=[];for(let d=0;d<a;d++)s.push(e(a===1?t:t+(r-t)*d/(a-1)));let i=dS(s,t),c=[],l=a,u=(d,p)=>{let f=.5*(d+p),h=e(f);l++;let b=B2(i(f),h);s.splice(s.findIndex(g=>g.v>f),0,h),i=dS(s,t),b>o&&c.push({lo:d,hi:f,misfit:b},{lo:f,hi:p,misfit:b})},m=s.map(d=>d.v);for(let d=0;d+1<m.length&&l<n;d++)m[d+1]-m[d]>=1&&u(m[d],m[d+1]);if(m.length>1){let d=.5*(m[0]+m[1]);if(s.some(p=>p.v===d))for(let[p,f]of[[m[0],d],[d,m[1]]]){if(l>=n||f-p<1)break;let h=c.findIndex(b=>b.lo===p&&b.hi===f);h>=0&&c.splice(h,1),u(p,f)}}for(;l<n&&c.length>0;){let d=0;for(let b=1;b<c.length;b++)c[b].misfit>c[d].misfit&&(d=b);let{lo:p,hi:f,misfit:h}=c.splice(d,1)[0];if(h<=o)break;f-p<1||u(p,f)}return{anchors:s,at:i}}var $2=2,G2=.5,$i=Math.PI/180,hS=21,K2={nCoarse:11,nSteer:13,nNorm:41,nAngle:45},H2={nCoarse:11,nSteer:13,nNorm:41,nAngle:61},z2=.005,Y2=.05,Zb=e=>e<0?0:e>1?1:e;function W2(e,t,r,n){let o=e.massTotal,a=n.nSteer??7,s=(n.drivenFront?2:0)+(n.drivenRear?2:0),i=Ce(e,0,0,r),c=Math.max(1,(i.FL+i.FR+i.RL+i.RR)/4),l=8*$i,u=0,m=(b,g,y)=>{for(let R=b;R<=g;R+=y){let k=Math.abs(t.Fy(R*$i,c,0));k>u&&(u=k,l=R*$i)}};m(1,45,1),m(Math.max(.1,l/$i-1),l/$i+1,.1);let d=[],p=[],f=[],h=[];for(let b=0;b<a;b++){let g=b/(a-1),y=l*(g+Math.sin(Math.PI/2*g))/2,R=Math.abs(t.Fy(y,c,0));d.push(4*R/o),p.push(s*Ct(t,c,R,!1)/o),f.push(4*Ct(t,c,R,!0)/o),h.push(-4*R*Math.sin(y)/o)}return d[0]=0,{ayMax:4*u/o,ay:d,axAccel:p,axDecel:f,axScrub:h,rollover:!1}}function br(e,t=!1,r="twoTrack",n,o,a=0,s=1){if(a!==0&&r==="fast")throw new Error('the fast (point-mass) envelope has no yaw balance to shift; use mode "twoTrack" for a yaw-inertia demand');let i=n??(t?H2:K2),{nCoarse:c,nSteer:l,nAngle:u}=i,m=Br(0,1,i.nNorm).map(B=>Math.sin(Math.PI/2*B)),d=e.params,p=d.m.value,f=d.rho.value,h=d.fr_0.value,b=d.driven_wheels.value,g=d.power_scale.value,y=e.FG,R=ht(d);s!==1&&(R.loadFactor=s);let k=hr(d),v=F1(0,n?.vRes??(e.engine?G2:$2),e.vMax);v[v.length-1]<e.vMax&&v.push(e.vMax);let x=e.fRad.map(B=>B*b),M=e.fAxle,{drivenFront:A,drivenRear:w}=uo(e),C=lo(d,A,w),T=(B,V)=>{let G=M?dt(M.vVehicle,B,V):NaN;return Number.isFinite(G)?G:1/0},F=B=>{let V=B*B,{cl:G,cw:K,A:Y}=Ju(d,B,0,R),j=.5*f*-K*Y*V,Z=.5*f*-G*Y*V,ne=h*(-Z+y);return j+ne},S=B=>{let V=F(B)/p*C.powerFactor,G=F(B)/p*C.tractionFactor,K;if(e.engine){let j=F(B);K=xa(e.engine,B,C.effective,j,g).accel-V}else if(M){let j=0;A&&(j+=T(M.fFront,B)),w&&(j+=T(M.fRear,B)),K=g*j/p*C.powerFactor}else{let j=dt(e.vVehicle,x,B),Z=g*j/p*C.powerFactor;K=Number.isFinite(Z)?Z:1/0}let Y=am(d,B,o)/p*C.powerFactor;return{axDrag:V,axDragTyre:G,axDrive:K,axPackCap:Y,axPower:Math.min(K,Y)}},P=v.map(S),L=e.vMax;for(let B=1;B<v.length;B++){let V=P[B].axDrive+P[B].axDrag;if(V>0)continue;let G=P[B-1].axDrive+P[B-1].axDrag;L=G>0?v[B-1]+(v[B]-v[B-1])*G/(G-V):v[B-1];break}let D=Math.min(e.vMax,(1+Y2)*L),I=r==="fast"?W2:gb,O=B=>{let V=I(R,k,B,{drivenFront:A,drivenRear:w,nSteer:l,yawDemandCn:a,axDrag:F(B)/p,...d.diffYaw?{diffYaw:!0}:{}}),G=V.ay[0],K=V.ay[V.ay.length-1],Y=te=>Math.min(Math.max(te*V.ayMax,G),K),j=m.map(te=>mu(V.ay,V.axAccel,Y(te))*C.tractionFactor),Z=m.map(te=>mu(V.ay,V.axDecel,Y(te))),ne=m.map(te=>mu(V.ay,V.axScrub,Y(te))*C.tractionFactor);return{v:B,ayMax:V.ayMax,axAccelN:j,axDecelN:Z,axScrubN:ne,atLock:V.atLock===!0}},_=r==="fast"?0:Math.min(wu,D),z=fS(O,_,D,c,i.anchorTol??z2),E=[],N=[];for(let B=0;B<v.length;B++){let V=v[B],{axDrag:G,axDragTyre:K,axDrive:Y,axPackCap:j,axPower:Z}=P[B],{ayMax:ne,axAccelN:te,axDecelN:fe,axScrubN:W}=z.at(V);E.push({v:V,ayMax:ne,axTyreAcc:te[0],axTyreDec:fe[0],axDrive:Y,axPackCap:j,axPower:Z,axDrag:G,axDragTyre:K,axAccelN:te,axDecelN:fe,axScrubN:W});let J=[],re=[];for(let de=0;de<u;de++){let ie=Math.PI*de/(u-1),oe=ne*Math.cos(ie),ue=Zb(Math.abs(Math.cos(ie)));J.push({ax:Math.min(dt(m,te,ue)+K,Z+G)+dt(m,W,ue),ay:oe,v:V})}for(let de=u-1;de>=0;de--){let ie=Math.PI*de/(u-1),oe=ne*Math.cos(ie),ue=Zb(Math.abs(Math.cos(ie)));re.push({ax:dt(m,fe,ue)+G+dt(m,W,ue),ay:oe,v:V})}let pe=(de,ie,oe)=>Array.from({length:hS},(ue,$e)=>({ax:ie+(oe-ie)*($e+1)/(hS+1),ay:de,v:V}));N.push([...J,...pe(-ne,J[J.length-1].ax,re[0].ax),...re,...pe(ne,re[re.length-1].ax,J[0].ax)])}return{...gS(E,m),rows:E,norm:m,surf:N}}function Ga(e,t){return e?.length?t.map(r=>gm(e,r)):t.map(()=>0)}function gm(e,t){let r=e.length-1;if(!(t>e[0].v))return e[0].axDrag;if(t>=e[r].v)return e[r].axDrag;let n=0,o=r;for(;o-n>1;){let s=n+o>>1;e[s].v<=t?n=s:o=s}let a=(t-e[n].v)/(e[o].v-e[n].v);return e[n].axDrag+a*(e[o].axDrag-e[n].axDrag)}function gS(e,t){let r=e[e.length-1].v,n=f=>{if(f<=e[0].v)return{i0:0,i1:0,t:0};if(f>=r)return{i0:e.length-1,i1:e.length-1,t:0};let h=0,b=e.length-1;for(;b-h>1;){let g=h+b>>1;e[g].v<=f?h=g:b=g}return{i0:h,i1:b,t:(f-e[h].v)/(e[b].v-e[h].v)}},o=f=>{let{i0:h,i1:b,t:g}=n(f);return{a:e[h],b:e[b],t:h===b?0:g}},a=(f,h,b)=>f===0||h===b?h:h+f*(b-h),s=(f,h,b,g)=>f===0?dt(t,h,g):a(f,dt(t,h,g),dt(t,b,g)),i=(f,h)=>h>=1?f.axPower:Math.min(h*f.axDrive,f.axPackCap),c=({a:f,b:h,t:b},g,y)=>f.axScrubN?y*s(b,f.axScrubN,h.axScrubN,g):0,l=f=>f.axDragTyre??f.axDrag,u=({a:f,b:h,t:b},g,y)=>{let R=y*a(b,f.ayMax,h.ayMax);return R>0?Zb(g/R):1},m=(f,h,b=1,g=1)=>{let{a:y,b:R,t:k}=f,v=u(f,h,b),x=b*s(k,y.axAccelN,R.axAccelN,v)+a(k,l(y),l(R)),M=a(k,i(y,g),k===0?0:i(R,g))+a(k,y.axDrag,R.axDrag);return Math.min(x,M)+c(f,v,b)},d=(f,h,b=1,g=1)=>{let{a:y,b:R,t:k}=f,v=u(f,h,b),x=s(k,y.axDecelN,R.axDecelN,v);return(g===1||x>0?b*x:g*b*x)+a(k,y.axDrag,R.axDrag)+c(f,v,b)},p=({a:f,b:h,t:b},g,y=1)=>{let R=t.length-1,k=f.axAccelN,v=h.axAccelN,x=f.axDecelN,M=h.axDecelN,A=f.axScrubN,w=h.axScrubN,C=I=>k[I]+b*(v[I]-k[I]),T=I=>x[I]+b*(M[I]-x[I]),F=I=>A?y*(A[I]+b*(w[I]-A[I])):0,S=a(b,f.ayMax,h.ayMax),P=a(b,f.axDrag,h.axDrag),L=a(b,l(f),l(h)),D=a(b,f.axPower,h.axPower);for(let I=R;I>=0;I--){let O=Math.min(y*C(I)+L,D+P)+F(I),_=y*T(I)+P+F(I);if(!(g<=O+1e-6&&g>=_-1e-6))continue;if(I===R)return t[I]*y*S;let z=(V,G,K)=>{if(K(G))return 1;let Y=(V-g)/(V-G);return Y>0?Math.min(Y,1):0},E=V=>g<=V+1e-6,N=V=>g>=V-1e-6,B=Math.min(z(y*C(I)+L+F(I),y*C(I+1)+L+F(I+1),E),z(D+P+F(I),D+P+F(I+1),E),z(y*T(I)+P+F(I),y*T(I+1)+P+F(I+1),N));return(t[I]+B*(t[I+1]-t[I]))*y*S}return 0};return{vMax:r,axAccel:(f,h,b=1,g=1)=>m(o(f),h,b,g),axDecel:(f,h,b=1,g=1)=>d(o(f),h,b,g),ay:(f,h,b=1)=>p(o(f),h,b),scrub:(f,h,b=1)=>{let g=o(f);return c(g,u(g,h,b),b)}}}function j2(e,t,r){let n=e.params,o=n.m.value,{drivenFront:a,drivenRear:s}=uo(e),i=lo(n,a,s);return c=>am(n,c,t,r)/o*i.powerFactor}function Gi(e,t,r,n){let o=j2(t,r,n),a=e.rows.map(s=>{let i=o(s.v),c=Math.min(s.axDrive,i);return c===s.axPower&&i===s.axPackCap?s:{...s,axPackCap:i,axPower:c}});return{...gS(a,e.norm),rows:a,norm:e.norm}}var U2=[-.2,-.08,0,.06,.12,.2,.3];function yS(e,t=!1,r="twoTrack",n,o,a=U2){let s=[...new Set([...a,0])].sort((f,h)=>f-h),i=s.map(f=>br(e,t,r,n,o,f)),c=i[s.indexOf(0)],l=s[0],u=s[s.length-1],m=f=>{if(f<=l)return{i:0,t:0};if(f>=u)return{i:s.length-1,t:0};let h=0;for(;h<s.length-2&&s[h+1]<=f;)h++;return{i:h,t:(f-s[h])/(s[h+1]-s[h])}},d=f=>{let h=b=>{let{i:g,t:y}=m(b);return{a:f[g],b:f[Math.min(f.length-1,g+1)],t:y}};return b=>{let{a:g,b:y,t:R}=h(b);if(R===0)return g;let k=(v,x)=>v+R*(x-v);return{vMax:g.vMax,axAccel:(v,x,M=1,A=1)=>k(g.axAccel(v,x,M,A),y.axAccel(v,x,M,A)),axDecel:(v,x,M=1,A=1)=>k(g.axDecel(v,x,M,A),y.axDecel(v,x,M,A)),ay:(v,x,M=1)=>k(g.ay(v,x,M),y.ay(v,x,M)),scrub:(v,x,M=1)=>k(g.scrub?.(v,x,M)??0,y.scrub?.(v,x,M)??0)}}},p=f=>f<l||f>u;return{anchors:s,steady:c,clamps:p,at:d(i),atSoc(f,h,b){let g=i.map(y=>Gi(y,f,h,b));return{anchors:s,steady:g[s.indexOf(0)],clamps:p,at:d(g)}}}}function xS(e,t,r,n="twoTrack",o){let a=[...new Set([...t,1])].sort((i,c)=>i-c),s=a.map(i=>i===1?r:br(e,!1,n,o,void 0,0,i));return{...bS(a,s),atSoc:(i,c,l)=>bS(a,s.map(u=>Gi(u,i,c,l)))}}function bS(e,t){let r=e.length-1,n=1,o=0,a=0,s=0,i=1,c=0,l=0,u=p=>{if(n=1,!(p>e[0]))return void(o=0);if(p>=e[r])return void(o=r);let f=0;for(;f<r-1&&e[f+1]<=p;)f++;if(o=f,p===e[f])return;a=f+1;let h=e[f],b=e[f+1];if(r<2){n=2,c=(p-h)/(b-h),i=1-c;return}s=f===0?2:f+1===r||p-e[f-1]<e[f+2]-p?f-1:f+2;let g=e[s];n=3,i=(p-b)*(p-g)/((h-b)*(h-g)),c=(p-h)*(p-g)/((b-h)*(b-g)),l=(p-h)*(p-b)/((g-h)*(g-b))},m=p=>{let f=p(t[o]);if(n===1)return f;let h=p(t[a]);if(n===2)return i*f+c*h;let b=i*f+c*h+l*p(t[s]);return Math.min(Math.max(f,h),Math.max(Math.min(f,h),b))},d=(p,f,h,b,g)=>{if(u(p),n===1||h===0)return m(k=>g(k,h));let y=m(k=>k.ay(f,0,b));if(!(y>0))return m(k=>g(k,h));let R=h/y;return m(k=>g(k,R*k.ay(f,0,b)))};return{anchors:e,axAccel:(p,f,h,b=1,g=1)=>d(p,f,h,b,(y,R)=>y.axAccel(f,R,b,g)),axDecel:(p,f,h,b=1,g=1)=>{let y=R=>d(p,f,h,b,(k,v)=>k.axDecel(f,v,b,R));return g===1?y(1):Ib(y(g),y(1),g)},scrub:(p,f,h,b=1)=>d(p,f,h,b,(g,y)=>g.scrub?.(f,y,b)??0),ay:(p,f,h,b=1)=>{if(u(p),n===1||h===0)return m(k=>k.ay(f,h,b));let g=k=>h>0?k.axAccel(f,0,b):-k.axDecel(f,0,b),y=m(g);if(!(y>0))return m(k=>k.ay(f,h,b));let R=h/y;return m(k=>k.ay(f,R*g(k),b))}}}var RS=new WeakMap;function Jb(e,t){let r=RS.get(e);if(!r){let n=Vr(e).regen?$b(t??Pt(e)):void 0;r={inp:ht(e),ev:hr(e),...n?{regen:n}:{}},RS.set(e,r)}return r}function eg(e,t,r){let n=Jb(e,r);return Qb(n.inp,n.ev,t,n.regen?{regen:n.regen}:{})}function tg(e){let t=ft(e);if(t.mode!=="hydraulic")return null;let r=a=>a.heat?{heat:bh(a.heat,a.ratio),discs:a.discs}:void 0,n=r(t.hydraulic.front),o=r(t.hydraulic.rear);return n||o?{...n?{front:n}:{},...o?{rear:o}:{}}:null}function X2(e){let t=(r,n)=>n?r.map((o,a)=>Math.max(0,o-n[a])):r;return{front:t(e.front,e.regenFront),rear:t(e.rear,e.regenRear)}}function rg(e,t,r,n,o,a=Tt){if(!e)return null;let s=X2(t);return{...e.front?{front:su(e.front.heat,e.front.discs,s.front,r,n,o.front,a)}:{},...e.rear?{rear:su(e.rear.heat,e.rear.discs,s.rear,r,n,o.rear,a)}:{}}}var q2=.5,Q2=.02,Z2=6,ym=9,vS=1e-9,J2={FL:0,FR:0,RL:0,RR:0};function ng(e){return e?[...new Set([...e.padCurve.factor,1])].sort((t,r)=>t-r):[1]}function e_(e,t,r){let n=mr(e),o=n.hydraulic;return n.mode!=="hydraulic"||!o?e:{...e,brakes:{...n,hydraulic:{...o,front:{...o.front,padMu:o.front.padMu*t},rear:{...o.rear,padMu:o.rear.padMu*r}}}}}function kS(e,t){let r=e.length;if(r===1||t<=e[0])return{i:0,t:0};if(t>=e[r-1])return{i:r-2,t:1};let n=0;for(;n<r-2&&e[n+1]<=t;)n++;return{i:n,t:(t-e[n])/(e[n+1]-e[n])}}function MS(e,t,r,n,o=()=>0){let a=Array.from({length:ym},(m,d)=>r*d/(ym-1)),s=di(),{front:i,rear:c}=n,l=a.map(m=>{let d=o(m),p=h=>Gr(h,t,m,s).limitAt(0,0,J2,d).ax,f=p(e);return i.map(h=>c.map(b=>{if(h===1&&b===1)return 1;let g=f<0?p(e_(e,h,b))/f:1;return Math.abs(g-1)<vS?1:g}))}),u=a[1]-a[0];return{share(m,d,p){if(d===1&&p===1)return 1;let f=u>0?Math.min(ym-2,Math.max(0,Math.floor(m/u))):0,h=u>0?Math.min(1,Math.max(0,(m-a[f])/u)):0,b=kS(i,d),g=kS(c,p),y=k=>{let v=l[k],x=Math.min(i.length-1,b.i+1),M=Math.min(c.length-1,g.i+1),A=v[b.i][g.i]+g.t*(v[b.i][M]-v[b.i][g.i]),w=v[x][g.i]+g.t*(v[x][M]-v[x][g.i]);return A+b.t*(w-A)},R=y(f)+h*(y(Math.min(ym-1,f+1))-y(f));return Math.abs(R-1)<vS?1:R}}}function t_(e,t){let{front:r,rear:n}=t;return(o,a)=>e.share(a,r?.[o]??1,n?.[o]??1)}var r_=e=>(e.front??[]).every(t=>t===1)&&(e.rear??[]).every(t=>t===1);function SS(e,t,r){let n=e(),o=1,a=t(n);if(r_(a))return{lap:n,solves:o,converged:!0};let s={...a.front?{front:a.front.slice()}:{},...a.rear?{rear:a.rear.slice()}:{}},i=!1;for(let c=0;c<Z2;c++){let l=e(t_(r,s));o++;let u=Math.abs(l.laptime-n.laptime);if(n=l,u<Q2){i=!0;break}a=t(n);let m=(f,h)=>f&&h?f.map((b,g)=>b+q2*((h[g]??1)-b)):f,d=m(s.front,a.front),p=m(s.rear,a.rear);s={...d?{front:d}:{},...p?{rear:p}:{}}}return{lap:n,pads:s,solves:o,converged:i}}function Sn(e,t){let r=e.engine;if(!r||r.gears.length===0||t.length===0)return;let n=e.params,{drivenFront:o,drivenRear:a}=uo(e),s=lo(n,o,a).effective,i=n.power_scale.value,{up:c,down:l}=Lh(r.engine.gearbox),u=r.engine.idleRpm,m=(d,p,f)=>(i*r.force(d,p)+f)/(s+r.inertiaMass(d,p));return{count:r.gears.length,up:c,down:l,kept:Dh(r.engine.gearbox),limitRpm:r.engine.limitRpm,best:d=>xa(r,d,s,gm(t,d)*s,i).gear,share:(d,p)=>{let f=gm(t,d),h=f*s,b=xa(r,d,s,h,i);if(p===b.gear)return 1;let g=b.accel-f;return g>0?Math.min(1,Math.max(0,(m(d,p,h)-f)/g)):0},rpm:(d,p)=>r.slipping(d,p)?u:r.rpm(d,p),vIdle:d=>r.gears[d]?.vIdle??0}}var AS=new WeakMap;function ag(e){let t=AS.get(e.ggv);return t===void 0&&(t=Sn(e.vehicle,e.ggv.rows)??null,AS.set(e.ggv,t)),t??void 0}function n_(e){return e.gear&&e.engineRpm&&e.shifting?{gear:e.gear,rpm:e.engineRpm,shifting:e.shifting}:{}}var Rm=class extends Error{constructor(t){super(t),this.name="EventError"}};function o_(e,t){let{ggv:r}=t,n=it(t.numerics),o=n.accelStep,a=Math.max(1,Math.round(e.distance/o)),s=Ea(r,new Array(a+1).fill(0),n);s[0].v=e.vStart??0;for(let f=0;f<s.length-1;f++){let h=s[f],b=s[f+1];h.v>=b.v||(h.ax=r.axAccel(h.v,0),b.v=Math.min(r.vMax,Math.sqrt(Math.max(0,h.v*h.v+2*h.ax*o))))}let i=ag(t),c=i?rm(s.map(f=>f.v),new Array(a).fill(o),!1,i,(f,h,b)=>r.axAccel(h,0,1,b)):void 0;if(c){for(let f=0;f<=a;f++)s[f].v=c.v[f];for(let f=0;f<a;f++)s[f].ax=(s[f+1].v*s[f+1].v-s[f].v*s[f].v)/(2*o)}let l=0;for(let f=0;f<a;f++){let h=s[f].v+s[f+1].v;h>0&&(l+=2*o/h)}let u=s.slice(0,a).map(f=>f.v),m=s.slice(0,a).map(f=>f.ax),d=new Array(a).fill(o),p=d.map((f,h)=>h*o);return{id:e.id,label:e.label,kind:e.kind,time:l,distance:a*o,laps:1,lapTime:l,trace:{v:u,ax:m,ay:new Array(a).fill(0),s:p,x:p,y:new Array(a).fill(0),...c?{gear:c.gear.slice(0,a),rpm:c.rpm.slice(0,a),shifting:c.shifting.slice(0,a)}:{}},energy:IS(t,d,[...u,s[a].v],m,1)}}function a_(e,t){let r=Math.max(1,Math.round(e.laps??1)),[n]=Ea(t.ggv,[1/e.radius],t.numerics),o=2*Math.PI*e.radius,a=n.v>0?o/n.v:1/0,s=t.ggv.scrub?.(n.v,Math.abs(n.ay))??0,i=IS(t,[o],[n.v,n.v],[0],r,s!==0?{ay:[n.ay],scrub:[s]}:void 0);return{id:e.id,label:e.label,kind:e.kind,time:a*r,distance:o*r,laps:r,lapTime:a,energy:i}}function vm(e,t){return e.laps!=null?Math.max(1,Math.round(e.laps)):e.distance!=null?Math.max(1,Math.ceil(e.distance/t.length)):1}function s_(e,t){let r=e.distance!=null?t.v_limit_endurance?.value??0:0;return r>0?r/3.6:void 0}function i_(e,t){if(e.distance==null||bt(t.motorModel))return 0;let r=t.endurance_reserve?.value??0;return r>0?Math.min(r,95)/100:0}var FS=1;function LS(e,t,r,n){return{v:r.v,ax:r.ax,ay:r.ay,ds:t.ds,axDrag:Ga(e.ggv.rows,r.v),...r.axScrub?{axScrub:r.axScrub}:{},axGrade:n,...t.bank?{bank:t.bank}:{}}}var wS=new WeakMap;function DS(e){let t=e.vehicle.params;if(!t.brakeFade)return null;let r=wS.get(t);if(r===void 0){let n=tg(t),o=n?ft(t):null;if(!n||!o||o.mode!=="hydraulic")r=null;else{let a=Jb(t,e.vehicle),s=e.ggv.rows,i=MS(a.inp,a.ev,e.vehicle.vMax,{front:ng(o.hydraulic.front.heat),rear:ng(o.hydraulic.rear.heat)},c=>Ga(s,[c])[0]);r={discs:n,table:i}}wS.set(t,r)}return r}function c_(e,t,r){let n=e.vehicle.params,{soc:o,packTempC:a,launched:s,vCeiling:i}=r,c=e.load?.atSoc(e.vehicle,o,a),l=ag(e),u=(g,y)=>e.yaw?mS(e.yaw.family.atSoc(e.vehicle,o,a),t,e.yaw.car,e.numerics,{standingStart:s,...g?{driveDerate:g}:{},...y?{brakeFade:y}:{},...i?{vCeiling:i}:{},...c?{load:c}:{},...l?{shifts:l}:{}}):kt(Gi(e.ggv,e.vehicle,o,a),t,e.numerics,{standingStart:s,...g?{driveDerate:g}:{},...y?{brakeFade:y}:{},...i?{vCeiling:i}:{},...c?{load:c}:{},...l?{shifts:l}:{}}),m=Mn(t.gradient,t.npts),d=g=>n.motorThermal?EM(e.vehicle,t.ds,e.energyOpts??Or,y=>u(y,g),o,a,m,t.bank).lap:u(void 0,g),p=DS(e);if(!p)return d();let f=Oi(n),h=r.discC??{front:f,rear:f};return SS(d,g=>{let y=rg(p.discs,eg(n,LS(e,t,g,m),e.vehicle),g.v,t.ds,h,f);return{...y?.front?{front:y.front.padFactor}:{},...y?.rear?{rear:y.rear.padFactor}:{}}},p.table).lap}function l_(e,t){let r=s_(e,t.vehicle.params),n=i_(e,t.vehicle.params);return n>0?p_(e,t,n,r):Ki(e,t,r)}function xm(e,t){let r=e.energy?.remainingFraction??0;return e.incomplete?-t-(1-e.incomplete.lapsCompleted/Math.max(1,e.incomplete.lapsAsked)):r-t}var CS=5,u_=.1,m_=.005,TS=12;function p_(e,t,r,n){let o=Ki(e,t,n),a=1,s=(f,h,b)=>({...f,energyTarget:{reserve:r,capKmh:h===void 0?null:h*3.6,met:b,solves:a}}),i=xm(o,r);if(i>=0)return s(o,n,!0);let c=Math.min(n??1/0,t.ggv.vMax),l=c/2,u=Ki(e,t,l);a++;let m=xm(u,r);for(;m<0&&l>CS&&a<TS;)c=l,i=m,l=Math.max(CS,l/2),u=Ki(e,t,l),a++,m=xm(u,r);if(m<0)return s(u,l,!1);let d=l,p=0;for(;a<TS&&c-l>u_&&m>m_;){let f=c-l,h=Math.min(c-.05*f,Math.max(l+.05*f,l+m*f/(m-i))),b=Ki(e,t,h);a++;let g=xm(b,r);g>=0?(l=h,m=g,u=b,d=h,p===1&&(i/=2),p=1):(c=h,i=g,p===-1&&(m/=2),p=-1)}return s(u,d,!0)}function ES(e,t,r){return r===0?e:e&&!t}function Ki(e,t,r){let n=t.track;if(!n)throw new Rm(`Event "${e.id}" needs a track.`);let o=vm(e,n),a=e.standingStart??t.standingStart??!1,s=K=>ES(a,n.closed,K),i=t.vehicle.params,c=Sr(Ia(i)),l=c.capacityAh,u=i.soc.value,m=Oi(i),d=om(c,m),p=0,f=0,h=0,b=0,g=[],y=!1,R=-1/0,k=0,v=0,x=!1,M=-1/0,A=0,w=0,C=-1/0,T=(K,Y,j=1)=>{K.tempMaxC>C&&(C=K.tempMaxC),K.motorTempMaxC!==void 0&&(y=!0,x=!0,K.motorTempMaxC>R&&(R=K.motorTempMaxC),K.motorTempMaxC>M&&(M=K.motorTempMaxC),k+=(K.motorDerateTimeFrac??0)*Y,A+=(K.motorDerateTimeFrac??0)*Y,v+=(K.motorLossKwh??0)/j,w+=(K.motorLossKwh??0)/j)},F=null,S,P=tg(i),L={front:m,rear:m},D=null,I=DS(t)!==null,O=(K,Y)=>I&&(Math.abs(K.front-Y.front)>FS||Math.abs(K.rear-Y.rear)>FS),_=(K,Y,j)=>{let Z=Gb(i,K,Y);if(D&&D.launch===j&&!h_(Z,D.pw)&&!O(L,D.discC))return D.lap;let ne=c_(t,n,{soc:K,packTempC:Y,launched:j,...r?{vCeiling:r}:{},...I?{discC:L}:{}});return D={pw:Z,launch:j,discC:L,lap:ne},ne},z=Mn(n.gradient,n.npts),E=(K,Y,j)=>_a(t.vehicle,n.ds,K.v,K.ax,t.energyOpts,Y,j,void 0,z,void 0,{ay:K.ay,bank:n.bank,...K.axScrub?{scrub:K.axScrub}:{}}),N=new WeakMap,B=(K,Y)=>{let j=N.get(K);return j||(j=eg(i,LS(t,n,K,z),t.vehicle),N.set(K,j)),rg(P,j,K.v,n.ds,Y,m)},V=(K,Y,j)=>{let Z=`${(100*j/n.npts).toFixed(0)} % of the way through lap ${K+1}`,ne=Y.cutoffAt>=0&&Y.cutoffAt<=Y.emptyAt;return{lapsCompleted:K,lapsAsked:o,why:ne?`the pack reached its ${c.voltageFloor.toFixed(0)} V cut-off ${Z}`:`the pack ran out ${Z}`}};for(let K=0;K<o;K++){if(u<=0){S={lapsCompleted:K,lapsAsked:o,why:"the pack was empty"};break}let Y=s(K),j=u,Z=d;x=!1,M=-1/0,A=0,w=0,C=-1/0;let ne=_(u,d,Y),te=E(ne,u,d);if(te.emptyAt>=0){S=V(K,te,te.emptyAt);break}let W=_(te.socEnd,te.tempEndC,Y).laptime-ne.laptime,J,re,pe,de,ie=d,oe=-1,ue=null,$e=1;if(W<=og)J=ne.laptime,re=te.net,pe=te.loss,de=te.chargeAh,ie=te.tempEndC,T(te,J),$e=1;else{let le=Math.min(d_,Math.max(2,Math.ceil(W/(2*og))));$e=le;let Re=u,Te=d;J=0,re=0,pe=0,de=0;for(let ze=0;ze<le;ze++){let je=_(Re,Te,Y),be=E(je,Re,Te),Fe=be.emptyAt>=0?be.emptyAt/n.npts:1;if(Fe*le<1){oe=Math.round(n.npts*(ze/le+Fe)),ue=be;break}if(J+=je.laptime/le,T(be,je.laptime/le,le),re+=be.net/le/Fe,pe+=be.loss/le/Fe,de+=be.chargeAh/le/Fe,Re-=be.chargeAh/le/Fe/l,Te+=(be.tempEndC-Te)/le,Re<=0){oe=Math.round(n.npts*(ze+1)/le),ue=be;break}}if(ie=Te,oe>=0&&ue){S=V(K,ue,oe);break}u=Re}p+=J,f+=re,h+=pe,b+=de,W<=og&&(u=te.socEnd),d=ie;let Ae=P?B(ne,L):null;Ae&&(L={front:Ae.front?.endC??L.front,rear:Ae.rear?.endC??L.rear}),g.push({lap:K+1,time:J,elapsed:p,entryTime:ne.laptime,socStart:j,socEnd:u,packTempStartC:Z,packTempEndC:d,packTempMaxC:Number.isFinite(C)?C:Z,energyKwh:re,lossKwh:pe,chargeAh:de,launched:Y,substeps:$e,...r?{vCeiling:r}:{},...x?{motor:{peakWindingC:M,derateTimeFrac:J>0?A/J:0,lossKwh:w}}:{},...Ae?{brakes:{...Ae.front?{front:PS(Ae.front)}:{},...Ae.rear?{rear:PS(Ae.rear)}:{}}}:{}}),F=ne}if(!F){let K=ag(t);F=kt(Gi(t.ggv,t.vehicle,u),n,t.numerics,{standingStart:a,...t.load?{load:t.load.atSoc(t.vehicle,u)}:{},...K?{shifts:K}:{}}),S=S??{lapsCompleted:0,lapsAsked:o,why:"the pack was empty"}}let G=g.length;return{id:e.id,label:e.label,kind:e.kind,time:p,distance:n.length*G,laps:G,lapTime:F.laptime,trace:{v:F.v,ax:F.ax,ay:F.ay,s:n.s,x:n.x,y:n.y,...n.gradient.some(K=>K!==0)?{gradient:n.gradient}:{},...n.bank.some(K=>K!==0)?{bank:n.bank}:{},...n.z.some(K=>K!==0)?{z:n.z}:{},...n.mu.some(K=>K!==1)?{mu:n.mu}:{},...F.loadFactor?{loadFactor:F.loadFactor}:{},...F.axScrub?{axScrub:F.axScrub}:{},...n_(F)},energy:{consumed:f,loss:h,...bt(i.motorModel)?{}:{native:{value:b,unit:"Ah"}},remainingFraction:bt(i.motorModel)?1:u,...y?{motor:{peakWindingC:R,derateTimeFrac:p>0?k/p:0,lossKwh:v}}:{}},lapLog:g,...S?{incomplete:S}:{}}}var og=.05;function PS(e){let t=r=>e.workJ>0?r/e.workJ:0;return{startC:e.startC,endC:e.endC,maxC:e.maxC,workKj:e.workJ/1e3,coldShare:t(e.coldWorkJ),hotShare:t(e.hotWorkJ)}}var d_=4,f_=.001;function h_(e,t){return e===t?!1:!Number.isFinite(e)||!Number.isFinite(t)?!0:Math.abs(e-t)>f_*Math.max(1,Math.abs(t))}function IS(e,t,r,n,o,a){return b_(e,t,o,()=>({v:r,ax:n,...a?{lateral:a}:{}}))}function b_(e,t,r,n){let o=e.energyOpts,a=e.vehicle.params.soc.value,s=0,i=0,c=0;for(let l=0;l<r;l++){let u=n(l),m=_a(e.vehicle,t,u.v,u.ax,o,a,void 0,void 0,void 0,void 0,u.lateral);s+=m.net,i+=m.loss,c+=m.chargeAh,a=m.socEnd}return bt(e.vehicle.params.motorModel)?{consumed:s,loss:i,remainingFraction:1}:{consumed:s,loss:i,native:{value:c,unit:"Ah"},remainingFraction:a}}function _S(e,t){switch(e.kind){case"straightLineAccel":return o_(e,t);case"constantRadius":return a_(e,t);case"trackLap":return l_(e,t)}}function sg(e,t){let r={};for(let n of e)r[n.id]=_S(n,t);return r}function NS(e,t){if(e.kind!=="trackLap")return e;let{distance:r,...n}=e;return{...n,laps:Math.max(1,Math.round(t))}}function mo(e,t,r,n,o="twoTrack",a){let s=1/0,i=-1/0;for(let d of r){let p=Ii(d);if(!p)continue;let f=xM(p,kt(t,d,n).v);f&&(s=Math.min(s,f.lo),i=Math.max(i,f.hi))}if(!(i>=s))return;let c=RM({lo:s,hi:i}),l=c.join(","),u=a?.get(l);if(u)return u;let m=xS(e,c,t,o);return a?.set(l,m),m}var Hi=e=>e.distance/Math.max(1,e.laps);function zi(e){let t=e.s.length,r=new Array(t);for(let n=0;n<t;n++)r[n]=(n<t-1?e.s[n+1]:e.length)-e.s[n];return r}var g_=e=>e.v.map(t=>t*3.6),y_=e=>e.ax.map(t=>t/9.81),x_=e=>e.ay.map(t=>t/9.81),R_=e=>e.ay.map((t,r)=>e.v[r]>1e-6?t/(e.v[r]*e.v[r]):0),km=(e,t,r)=>e?.slice()??new Array(t.s.length).fill(r),v_=e=>km(e.z,e,0),k_=e=>e.gradient?e.gradient.map(t=>100*Math.tan(t*Math.PI/180)):km(void 0,e,0),M_=e=>km(e.bank,e,0),S_=e=>km(e.mu,e,1);function A_(e){let t=e.s.length,r=zi(e),n=new Array(t);n[0]=0;for(let o=1;o<t;o++)n[o]=n[o-1]+2*r[o-1]/(e.v[o-1]+e.v[o]);return n}var ig=[{name:"s",unit:"m",what:"distance along the lap"},{name:"ds",unit:"m",what:"length of the segment starting at this sample"},{name:"t",unit:"s",what:"elapsed time"},{name:"v",unit:"m/s",what:"speed"},{name:"speed",unit:"km/h",what:"speed"},{name:"ax",unit:"m/s\xB2",what:"longitudinal acceleration"},{name:"ay",unit:"m/s\xB2",what:"lateral acceleration"},{name:"axg",unit:"g",what:"longitudinal acceleration"},{name:"ayg",unit:"g",what:"lateral acceleration"},{name:"curv",unit:"1/m",what:"signed curvature, ay/v\xB2"},{name:"z",unit:"m",what:"elevation of the road"},{name:"grade",unit:"%",what:"grade of the road, uphill +"},{name:"bank",unit:"\xB0",what:"bank of the road, left side up +"},{name:"grip",unit:"-",what:"grip scale of the road, 1 = the tyre\u2019s own"}];function OS(e){let t=zi(e);return{ds:t,vars:{s:e.s,ds:t,t:A_(e),v:e.v,speed:g_(e),ax:e.ax,ay:e.ay,axg:y_(e),ayg:x_(e),curv:R_(e),z:v_(e),grade:k_(e),bank:M_(e),grip:S_(e)}}}function VS(e,t){return{v:e.v,ax:e.ax,ay:e.ay,ds:zi({s:e.s,length:t}),axGrade:Mn(e.gradient,e.v.length),...e.bank?{bank:e.bank}:{},...e.loadFactor?{loadFactor:e.loadFactor}:{}}}function BS(e,t){let r=ht(e);return{pastTurnover:oS(r,hr(e),t),...e.aeroModel?{aeroOutside:nS(r,t)}:{}}}var Mm="Flying lap";function cg(e,t){return e.kind!=="trackLap"||e.label!==Mm?e.label:e.standingStart??t?"Run":e.label}function F_(e){let t=ht(e);return{yawInertia:t.yawInertia??0,massTotal:t.massTotal,wheelbase:t.wheelbase/1e3}}function w_(e,t,r){let n=e.params,o=n.ggvMode??"twoTrack",a=n.quasiTransient?yS(e,!1,o):null,s=a?a.steady:br(e,!1,o),i=t?mo(e,s,[t],r,o):void 0;return{ggv:s,...a?{yaw:{family:a,car:F_(n)}}:{},...i?{load:i}:{}}}function C_(e,t){let r=t.lapCounts,n=t.standingStart??!1,o=!1,a=e.events.map(s=>{let i=r?.[s.id]!=null?NS(s,r[s.id]):s,c=cg(i,n),l=c===i.label?i:{...i,label:c};return l!==s&&(o=!0),l});return o?a:e.events}function T_(e,t,r){let n=r.lapCounts;if(!(!n||!r.track))for(let o of t.events){let a=n[o.id];if(o.kind!=="trackLap"||a==null)continue;let s=vm(o,r.track),i=Math.max(1,Math.round(a));i!==s&&e[o.id]&&(e[o.id]={...e[o.id],lapsOverridden:{asked:i,defined:s}})}}function P_(e,t){for(let[r,n]of Object.entries(e))n.trace&&(e[r]={...n,...BS(t,VS(n.trace,Hi(n)))})}function Yi(e,t,r={}){let n=Pt(e),o=w_(n,r.track,r.numerics),{ggv:a}=o,s=sg(C_(t,r),{vehicle:n,...o,track:r.track,energyOpts:Vr(e,r.energyOpts),numerics:r.numerics,standingStart:r.standingStart});return T_(s,t,r),P_(s,n.params),{name:e.name,rulesetId:t.id,events:s,ggv:a}}function lg(e){return{...e,ggv:{rows:e.ggv.rows,vMax:e.ggv.vMax,surf:e.ggv.surf}}}var ug=["<","<=",">",">=","==","!="],Oe=class extends Error{at;constructor(t,r){super(t),this.name="ExprError",this.at=r}},Wi=e=>e>="0"&&e<="9",$S=e=>/[A-Za-z_]/.test(e),L_=e=>/[A-Za-z0-9_]/.test(e);function D_(e){let t=[],r=0;for(;r<e.length;){let n=e[r];if(n===" "||n===" "||n===`
|
|
224
|
-
`||n==="\r"){r++;continue}if(Wi(n)||n==="."&&Wi(e[r+1]??"")){let o=r;for(;r<e.length&&(Wi(e[r])||e[r]===".");)r++;if(e[r]==="e"||e[r]==="E"){let i=r;if(r++,(e[r]==="+"||e[r]==="-")&&r++,Wi(e[r]??""))for(;r<e.length&&Wi(e[r]);)r++;else r=i}let a=e.slice(o,r),s=Number(a);if(!Number.isFinite(s))throw new Oe(`"${a}" is not a number`,o);t.push({t:"num",value:s,at:o});continue}if($S(n)){let o=r;for(;;){for(;r<e.length&&L_(e[r]);)r++;if(e[r]==="."&&$S(e[r+1]??""))r++;else break}t.push({t:"name",value:e.slice(o,r),at:o});continue}if("<>=!".includes(n)){let o=e.slice(r,r+2);if(ug.includes(o)){t.push({t:"op",value:o,at:r}),r+=2;continue}if(n==="<"||n===">"){t.push({t:"op",value:n,at:r}),r++;continue}throw new Oe(n==="="?'Compare with "==", not "="':'Write not(x) rather than "!x"',r)}if("+-*/^(),".includes(n)){t.push({t:"op",value:n,at:r}),r++;continue}throw new Oe(`"${n}" is not something this expression can contain`,r)}return t.push({t:"end",at:e.length}),t}function mg(e){let t=D_(e),r=0,n=()=>t[r],o=h=>{let b=n();return b.t==="op"&&b.value===h},a=h=>o(h)?(r++,!0):!1,s=(h,b)=>{if(!a(h))throw new Oe(`Expected ${b} here`,n().at)};function i(){let h=c(),b=n();if(b.t!=="op"||!ug.includes(b.value))return h;r++;let g={kind:"binary",op:b.value,left:h,right:c(),at:b.at},y=n();if(y.t==="op"&&ug.includes(y.value))throw new Oe("Comparisons do not chain \u2014 write and(a < b, b < c)",y.at);return g}function c(){let h=l();for(;;){let b=n().at;if(a("+"))h={kind:"binary",op:"+",left:h,right:l(),at:b};else if(a("-"))h={kind:"binary",op:"-",left:h,right:l(),at:b};else return h}}function l(){let h=u();for(;;){let b=n().at;if(a("*"))h={kind:"binary",op:"*",left:h,right:u(),at:b};else if(a("/"))h={kind:"binary",op:"/",left:h,right:u(),at:b};else return h}}function u(){return a("-")?{kind:"unary",op:"-",arg:u()}:a("+")?u():m()}function m(){let h=d(),b=n().at;return a("^")?{kind:"binary",op:"^",left:h,right:u(),at:b}:h}function d(){let h=n();if(h.t==="num")return r++,{kind:"num",value:h.value};if(h.t==="name"){if(r++,a("(")){let b=[];if(!o(")"))do b.push(i());while(a(","));return s(")","a closing bracket"),{kind:"call",name:h.value,args:b,at:h.at}}return{kind:"var",name:h.value,at:h.at}}if(a("(")){let b=i();return s(")","a closing bracket"),b}throw h.t==="end"?new Oe("The expression ends before it is finished",h.at):new Oe(`"${h.value}" cannot start a value`,h.at)}let p=i(),f=n();if(f.t!=="end")throw new Oe(`"${f.value}" is left over \u2014 check for a missing operator`,f.at);return p}function pg(e){let t=new Set,r=n=>{n.kind==="var"?t.add(n.name):n.kind==="call"?n.args.forEach(r):n.kind==="unary"?r(n.arg):n.kind==="binary"&&(r(n.left),r(n.right))};return r(e),t}var ji=(e,t)=>typeof e=="number"?new Array(t).fill(e):e;function E_(e){let t=1;for(let r of e)Array.isArray(r)&&(t=Math.max(t,r.length));return t}function Et(e,t){if(e.every(a=>typeof a=="number"))return t(...e);let r=E_(e),n=e.map(a=>ji(a,r)),o=new Array(r);for(let a=0;a<r;a++)o[a]=t(...n.map(s=>s[Math.min(a,s.length-1)]));return o}var Ve=(e,t)=>({arity:e,call:r=>Et(r,t)}),po=e=>e!==0&&!Number.isNaN(e),gr=e=>e?1:0;function GS(e,t,r){let n=KS(t,r,"integrate"),o=n.length,a=ji(e,o),s=new Array(o),i=0;for(let c=0;c<o;c++){s[c]=i;let l=a[Math.min(c,a.length-1)],u=a[Math.min(c+1,a.length-1)];i+=(l+u)/2*n[c]}return s}function KS(e,t,r){if(!e.ds||e.ds.length===0)throw new Oe(`${r}() needs to know the sample spacing, and this context has none`,t);return e.ds}var Sm={abs:Ve(1,Math.abs),sqrt:Ve(1,Math.sqrt),sign:Ve(1,Math.sign),floor:Ve(1,Math.floor),ceil:Ve(1,Math.ceil),round:Ve(1,Math.round),exp:Ve(1,Math.exp),log:Ve(1,Math.log),sin:Ve(1,Math.sin),cos:Ve(1,Math.cos),tan:Ve(1,Math.tan),atan:Ve(1,Math.atan),atan2:Ve(2,Math.atan2),hypot:Ve(2,Math.hypot),min:Ve(2,Math.min),max:Ve(2,Math.max),clamp:Ve(3,(e,t,r)=>Math.min(r,Math.max(t,e))),if:Ve(3,(e,t,r)=>po(e)?t:r),and:Ve(2,(e,t)=>gr(po(e)&&po(t))),or:Ve(2,(e,t)=>gr(po(e)||po(t))),not:Ve(1,e=>gr(!po(e))),finite:Ve(1,e=>gr(Number.isFinite(e))),peak:{arity:1,call:([e])=>{let t=Array.isArray(e)?e:[e],r=0;for(let n of t)r=Math.max(r,Math.abs(n));return r}},mean:{arity:1,call:([e])=>{let t=Array.isArray(e)?e:[e];return t.length?t.reduce((r,n)=>r+n,0)/t.length:0}},total:{arity:1,call:([e],t)=>{let r=GS(e,t,0),n=t.ds,o=ji(e,n.length),a=n.length-1;return r[a]+(o[a]+o[0])/2*n[a]}},integrate:{arity:1,call:([e],t)=>GS(e,t,0)},cum:{arity:1,call:([e],t)=>{let r=t.ds?.length??(Array.isArray(e)?e.length:1),n=ji(e,r),o=new Array(r),a=0;for(let s=0;s<r;s++)a+=n[Math.min(s,n.length-1)],o[s]=a;return o}},deriv:{arity:1,call:([e],t)=>{let r=KS(t,0,"deriv"),n=r.length,o=ji(e,n),a=new Array(n);for(let s=0;s<n;s++){let i=Math.max(0,s-1),c=Math.min(n-1,s+1),l=0;for(let u=i;u<c;u++)l+=r[u];a[s]=l>0?(o[c]-o[i])/l:0}return a}}},Ka={g:9.81,pi:Math.PI,e:Math.E,nan:NaN,inf:1/0},Ui={fleetmin:"min",fleetmax:"max"};function fo(e){switch(e.kind){case"call":return Object.hasOwn(Ui,e.name)||e.args.some(fo);case"unary":return fo(e.arg);case"binary":return fo(e.left)||fo(e.right);default:return!1}}var I_=e=>typeof e=="number"?`${e}`:`between ${e[0]} and ${e[1]}`;function __(e,t){let r=Array.from({length:t.length+1},(n,o)=>o);for(let n=1;n<=e.length;n++){let o=[n];for(let a=1;a<=t.length;a++)o[a]=Math.min(r[a]+1,o[a-1]+1,r[a-1]+(e[n-1]===t[a-1]?0:1));r=o}return r[t.length]}function N_(e,t){let r=t.map(c=>({k:c,d:__(c,e)})).filter(c=>c.d<=Math.max(1,Math.floor(e.length/4))),n=Math.min(...r.map(c=>c.d)),o=r.filter(c=>c.d===n).map(c=>c.k).slice(0,3);if(o.length)return`"${e}" is not a name here \u2014 did you mean ${o.join(" or ")}?`;let a=e.indexOf(".");if(a>0){let c=t.filter(l=>l.startsWith(e.slice(0,a+1)));if(c.length)return`"${e}" is not a name here. ${e.slice(0,a)} has ${c.join(", ")}`}let s=new Set,i=[];for(let c of t){let l=c.indexOf(".");l>0?s.add(`${c.slice(0,l)}.\u2026`):i.push(c)}return`"${e}" is not a name here. Available: ${[...s,...i].join(", ")}`}function yr(e,t){switch(e.kind){case"num":return e.value;case"var":{if(Object.hasOwn(t.vars,e.name))return t.vars[e.name];if(Object.hasOwn(Ka,e.name))return Ka[e.name];let r=[...Object.keys(t.vars),...Object.keys(Ka)].sort();throw new Oe(N_(e.name,r),e.at)}case"unary":return Et([yr(e.arg,t)],r=>-r);case"binary":{let r=yr(e.left,t),n=yr(e.right,t);switch(e.op){case"+":return Et([r,n],(o,a)=>o+a);case"-":return Et([r,n],(o,a)=>o-a);case"*":return Et([r,n],(o,a)=>o*a);case"/":return Et([r,n],(o,a)=>a===0?0:o/a);case"^":return Et([r,n],(o,a)=>o**a);case"<":return Et([r,n],(o,a)=>gr(o<a));case"<=":return Et([r,n],(o,a)=>gr(o<=a));case">":return Et([r,n],(o,a)=>gr(o>a));case">=":return Et([r,n],(o,a)=>gr(o>=a));case"==":return Et([r,n],(o,a)=>gr(o===a));case"!=":return Et([r,n],(o,a)=>gr(o!==a))}break}case"call":{let r=Object.hasOwn(Ui,e.name)?Ui[e.name]:void 0;if(r){if(!t.fleet)throw new Oe(`${e.name}() compares the cars in a field, so it belongs in a ruleset's KPIs, not in a channel`,e.at);if(e.args.length!==1)throw new Oe(`${e.name}() takes 1 argument, not ${e.args.length}`,e.at);return t.fleet(e.args[0],r,e.at)}let n=Object.hasOwn(Sm,e.name)?Sm[e.name]:void 0;if(!n){let s=[...Object.keys(Sm),...t.fleet?Object.keys(Ui):[]];throw new Oe(`There is no function called "${e.name}". Available: ${s.sort().join(", ")}`,e.at)}let o=typeof n.arity=="number"?n.arity:n.arity[0],a=typeof n.arity=="number"?n.arity:n.arity[1];if(e.args.length<o||e.args.length>a)throw new Oe(`${e.name}() takes ${I_(n.arity)} argument${o===1&&a===1?"":"s"}, not ${e.args.length}`,e.at);return n.call(e.args.map(s=>yr(s,t)),t)}}throw new Oe("Unreachable node",0)}var Ha=e=>Number.isFinite(e)?e:NaN,dg=[{name:"time",unit:"s",what:"the whole event, every lap",read:e=>Ha(e?.time)},{name:"lapTime",unit:"s",what:"one lap \u2014 the last one completed",read:e=>Ha(e?.lapTime)},{name:"distance",unit:"m",what:"distance covered",read:e=>Ha(e?.distance)},{name:"laps",unit:"-",what:"laps completed",read:e=>Ha(e?.laps)},{name:"energy",unit:"kWh",what:"energy drawn over the event",read:e=>Ha(e?.energy?.consumed)},{name:"remaining",unit:"-",what:"share of the pack or tank left afterwards",read:e=>Ha(e?.energy?.remainingFraction)},{name:"finished",unit:"-",what:"1 when the car ran the whole event, else 0",read:e=>e&&!e.incomplete?1:0}],HS=/^[A-Za-z_][A-Za-z0-9_]*$/,O_=new Set([...Object.keys(Ka),...ig.map(e=>e.name)]);function Am(e,t,r=[]){let n=[],o=new Set(r),a=t.map(b=>b.id),s=new Set;for(let b of a)HS.test(b)?s.has(b)&&n.push({key:null,message:`Two events are called "${b}"`}):n.push({key:null,message:`Event id "${b}" must be one word to be read as ${b}.time`}),s.add(b);let i=new Map,c=new Map;for(let b of e){if(!HS.test(b.key)){n.push({key:b.key,message:`"${b.key}" must be one word \u2014 letters, digits and _`});continue}if(O_.has(b.key)||o.has(b.key)){n.push({key:b.key,message:`"${b.key}" already means something in a formula \u2014 choose another key`});continue}if(i.has(b.key)){n.push({key:b.key,message:`Two KPIs are called "${b.key}"`});continue}i.set(b.key,b),b.over!=null&&!a.includes(b.over)&&n.push({key:b.key,message:`There is no event "${b.over}" to read the lap of. Events: ${a.join(", ")}`});try{c.set(b.key,mg(b.expr))}catch(g){let y=g;n.push({key:b.key,message:y.message,at:y.at})}}let l=new Map;for(let[b,g]of c)l.set(b,[...pg(g)].filter(y=>i.has(y)));let u=new Set,m=[];for(;;){let b=[...c.keys()].find(g=>!u.has(g)&&l.get(g).every(y=>u.has(y)||!c.has(y)));if(!b)break;u.add(b),m.push(b)}for(let b of c.keys()){if(u.has(b))continue;let g=V_(b,l);n.push({key:b,message:g?`"${b}" depends on itself, through ${g.join(" \u2192 ")}`:`"${b}" reads a KPI that depends on itself`})}let d=(b,g,y)=>{throw new Oe("fleetmin() and fleetmax() cannot sit inside one another",y)},p=new Set,f={};for(let b of a)for(let g of dg)f[`${b}.${g.name}`]=1;for(let b of o)f[b]=1;for(let b of i.keys())f[b]=1;let h={};for(let b of ig)h[b.name]=[1,1];for(let b of m){let g=i.get(b),y=c.get(b);(fo(y)||l.get(b).some(x=>p.has(x)))&&p.add(b);let R=g.over!=null?{...f,...h}:f,k=g.over!=null?[1,1]:void 0,v=(x,M,A)=>{let w=yr(x,{vars:R,ds:k,fleet:d});if(Array.isArray(w))throw new Oe("fleetmin() and fleetmax() compare one number per car \u2014 reduce the channel first, e.g. peak(v)",A);return w};try{let x=yr(y,{vars:R,ds:k,fleet:v});Array.isArray(x)&&n.push({key:b,message:"A KPI is one number per car \u2014 reduce the channel, e.g. peak(v) or mean(v)",at:0})}catch(x){let M=x;n.push({key:b,message:M.message,at:M.at})}}return n.length?{plan:null,problems:n}:{plan:{order:m.map(b=>({def:i.get(b),node:c.get(b)})),field:p,eventIds:a},problems:n}}function V_(e,t){let r=[e],n=o=>{for(let a of t.get(o)??[]){if(a===e)return!0;if(!r.includes(a)){if(r.push(a),n(a))return!0;r.pop()}}return!1};return n(e)?[...r,e]:null}function B_(e,t,r={}){let n={...r};for(let o of e.eventIds){let a=t.events[o];for(let s of dg)n[`${o}.${s.name}`]=s.read(a)}return{vars:n,laps:new Map,events:t.events}}function zS(e,t){if(t.over==null)return{vars:e.vars};let r=e.laps.get(t.over);if(r===void 0){let n=e.events[t.over];r=n?.trace?OS({...n.trace,length:Hi(n)}):null,e.laps.set(t.over,r)}return r?{vars:{...e.vars,...r.vars},ds:r.ds}:null}var YS=e=>Array.isArray(e)?NaN:e;function WS(e,t,r,n={}){let o=Object.keys(t),a=o.map(i=>B_(e,t[i],n[i]));for(let{def:i,node:c}of e.order){let l=e.field.has(i.key);if(l&&!r){for(let d of a)d.vars[i.key]=NaN;continue}let u=new Map,m=(d,p)=>{let f=u.get(d);if(f!==void 0)return f;let h=NaN;for(let b of a){let g=zS(b,i);if(!g)continue;let y=YS(yr(d,g));Number.isFinite(y)&&(Number.isNaN(h)||(p==="min"?y<h:y>h))&&(h=y)}return u.set(d,h),h};for(let d of a){let p=zS(d,i);d.vars[i.key]=p?YS(yr(c,l?{...p,fleet:m}:p)):NaN}}let s={};return o.forEach((i,c)=>{let l={};for(let{def:u}of e.order)l[u.key]=a[c].vars[u.key];s[i]=l}),s}function Xi(e,t,r){return WS(e,t,!0,r)}function fg(e,t,r){return WS(e,{car:t},!1,r?{car:r}:void 0).car}var Fm=class extends Error{problems;constructor(t,r){super(`Ruleset "${t}" does not compile:
|
|
223
|
+
`}function Er(e){let t=Zs(jv(e),e.name);return{...t,missing:[...t.missing??[],"a particular tyre \u2014 every coefficient is derived from class-level targets stated in generic.ts, on the road; run it with grip_scale = stiffness_scale = 1"]}}var Uv={name:"Formula Student 18x6-10",R0:.228,width:.1524,Fz0:950,Kz:110,pressure:83,muY:1.8,muX:1.7,muYLoad:-.2,muXLoad:-.15,corneringStiffness:26e3,slipStiffnessPerLoad:32,camberStiffness:45,Cy:1.5,Cx:1.6,RBY1:12,RBY2:12,RBX1:13,RBX2:10,trail:.08},Xv={name:"Formula 1 slick 18in",R0:.36,width:.305,Fz0:5e3,Kz:300,pressure:150,muY:1.8,muX:1.7,muYLoad:-.15,muXLoad:-.12,corneringStiffness:15e4,slipStiffnessPerLoad:28,camberStiffness:260,Cy:1.45,Cx:1.6,RBY1:12,RBY2:12,RBX1:13,RBX2:10,trail:.09},qv={name:"GT slick 18in",R0:.33,width:.3,Fz0:4e3,Kz:280,pressure:180,muY:1.45,muX:1.4,muYLoad:-.12,muXLoad:-.1,corneringStiffness:11e4,slipStiffnessPerLoad:24,camberStiffness:190,Cy:1.4,Cx:1.6,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.09},Qv={name:"Street tyre 245/40 R18",R0:.325,width:.245,Fz0:4e3,Kz:220,pressure:240,muY:1.05,muX:1,muYLoad:-.1,muXLoad:-.08,corneringStiffness:75e3,slipStiffnessPerLoad:20,camberStiffness:100,Cy:1.3,Cx:1.55,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.12},Zv={name:"Cup slick 18in",R0:.32,width:.25,Fz0:3500,Kz:280,pressure:180,muY:1.42,muX:1.38,muYLoad:-.12,muXLoad:-.1,corneringStiffness:9e4,slipStiffnessPerLoad:24,camberStiffness:160,Cy:1.4,Cx:1.6,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.09},Jv={name:"Stock car slick 18in",R0:.357,width:.32,Fz0:4500,Kz:320,pressure:200,muY:1.35,muX:1.3,muYLoad:-.12,muXLoad:-.1,corneringStiffness:125e3,slipStiffnessPerLoad:22,camberStiffness:170,Cy:1.4,Cx:1.6,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.09},e1={name:"Hill-climb slick 13in",R0:.3,width:.3,Fz0:2e3,Kz:200,pressure:150,muY:1.75,muX:1.65,muYLoad:-.18,muXLoad:-.14,corneringStiffness:6e4,slipStiffnessPerLoad:28,camberStiffness:90,Cy:1.45,Cx:1.6,RBY1:12,RBY2:12,RBX1:13,RBX2:10,trail:.085},t1={name:"Race truck tyre 315/70 R22.5",R0:.506,width:.315,Fz0:13e3,Kz:1e3,pressure:800,muY:1.1,muX:1.05,muYLoad:-.1,muXLoad:-.08,corneringStiffness:15e4,slipStiffnessPerLoad:14,camberStiffness:200,Cy:1.3,Cx:1.55,RBY1:10,RBY2:10,RBX1:11,RBX2:10,trail:.1},qf=()=>Er(Uv),Qf=()=>Er(Xv),Zf=()=>Er(qv),Jf=()=>Er(Qv),eh=()=>Er(Zv),th=()=>Er(Jv),rh=()=>Er(e1),nh=()=>Er(t1);var r1=e=>Number.isFinite(e)&&e>0;function tu(e,t){let r=r1(t.grip)?t.grip:1,n=r1(t.stiffness)?t.stiffness:1;if(r===1&&n===1)return e;if(e.kind==="simple"){let o=n/r;return{...e,muX0:e.muX0*r,muY0:e.muY0*r,loadSensX:e.loadSensX*r,loadSensY:e.loadSensY*r,Bx:e.Bx*o,By:e.By*o}}return{...e,coeffs:{...e.coeffs,LMUX:(e.coeffs.LMUX??1)*r,LMUY:(e.coeffs.LMUY??1)*r,LKX:(e.coeffs.LKX??1)*n,LKY:(e.coeffs.LKY??1)*n}}}var ei={ok:!0,violation:0},Xn=1e7;function Ir(e,t){let r;try{r=e.build(t)}catch(s){return{total:Xn*2,feasible:!1,terms:[],reason:`build failed: ${String(s)}`}}let n=e.feasible(r);if(!n.ok)return{total:Xn+Math.max(0,n.violation),feasible:!1,terms:[],reason:n.reason};let o;try{o=e.terms(r)}catch(s){return{total:Xn*2,feasible:!1,terms:[],reason:`objective threw: ${String(s)}`}}let a=0;for(let s of o)a+=s.contribution;return Number.isFinite(a)?{total:a,feasible:!0,terms:o}:{total:Xn*2,feasible:!1,terms:o,reason:"objective was not finite"}}var ti=(e,t)=>!t||(e.feasible!==t.feasible?e.feasible:e.total<t.total);function oh(e,t){return t.map((r,n)=>Math.min(e[n].hi,Math.max(e[n].lo,r)))}var _r=e=>e.map(t=>t.start);function ru(e){let t=e>>>0;return()=>{t=t+1831565813>>>0;let r=Math.imul(t^t>>>15,1|t);return r=r+Math.imul(r^r>>>7,61|r)^r,((r^r>>>14)>>>0)/4294967296}}function JL(e){let t=0;for(;t===0;)t=e();return Math.sqrt(-2*Math.log(t))*Math.cos(2*Math.PI*e())}function ah(e,t){let{budget:r}=t,n=Math.max(1,Math.floor(t.progressEvery??1)),o=e.variables,a=p=>oh(o,p.map((d,h)=>o[h].lo+d*(o[h].hi-o[h].lo))),s=p=>p.map((d,h)=>(d-o[h].lo)/(o[h].hi-o[h].lo)),i=0,c=0,l=null,u=null,m=[];return{vars:o,denorm:a,norm:s,evaluate:p=>{if(i>=r)return l?.total??Number.POSITIVE_INFINITY;i++;let d=p.map(g=>Math.min(1,Math.max(0,g))),h=Ir(e,a(d));h.feasible||c++;let b=ti(h,l)?h:l;return b===h&&(l=h,u=d),m.push(b.total),t.onProgress&&(i%n===0||i===r)&&t.onProgress({evaluations:i,budget:r,x:a(u),score:b,infeasible:c}),h.total},left:()=>r-i,result:p=>({method:p,x:u?a(u):_r(o),score:l??Ir(e,_r(o)),evaluations:i,history:m,infeasible:c})}}var sh=(e,t,r,n=0,o)=>{let a=t?r.norm(_r(e.variables)):e.variables.map(()=>.5);return!(n>0)||!o?a:a.map(s=>Math.min(1,Math.max(0,s+n*2*(o()-.5))))};function n1(e,t){let r=ah(e,t),n=ru(t.seed??1),o=e.variables.length;for(r.evaluate(sh(e,t.warmStart!==!1,r,t.startJitter,n));r.left()>0;){let a=[];for(let s=0;s<o;s++)a.push(n());r.evaluate(a)}return r.result("random")}function ga(e,t){let r=ah(e,t),n=e.variables.length,o=ru(t.seed??1),a=1,s=2,i=.5,c=.5,l=sh(e,t.warmStart!==!1,r,t.startJitter,o),u=.25;for(;r.left()>0;){let m=[{u:l,f:r.evaluate(l)}];for(let f=0;f<n&&r.left()>0;f++){let p=l.slice();p[f]+=p[f]+u>1?-u:u,m.push({u:p,f:r.evaluate(p)})}for(;r.left()>0;){m.sort((g,y)=>g.f-y.f);let f=m[n],p=new Array(n).fill(0);for(let g=0;g<n;g++)for(let y=0;y<n;y++)p[y]+=m[g].u[y]/n;let d=g=>p.map((y,R)=>y+g*(y-f.u[R])),h=d(a),b=r.evaluate(h);if(b<m[0].f){let g=d(s),y=r.evaluate(g);m[n]=y<b?{u:g,f:y}:{u:h,f:b}}else if(b<m[n-1].f)m[n]={u:h,f:b};else{let g=d(-i),y=r.evaluate(g);if(y<f.f)m[n]={u:g,f:y};else{let R=m[0],k=0;for(let v=1;v<=n;v++)for(let x=0;x<n;x++)k=Math.max(k,Math.abs(m[v].u[x]-R.u[x]));if(k<1e-4)break;for(let v=1;v<=n&&r.left()>0;v++){let x=m[v].u.map((M,F)=>R.u[F]+c*(M-R.u[F]));m[v]={u:x,f:r.evaluate(x)}}}}}m.sort((f,p)=>f.f-p.f),l=m[0].u.map(f=>Math.min(1,Math.max(0,f+.05*(o()-.5)))),u=Math.max(.02,u*.5)}return r.result("nelder-mead")}function o1(e,t){let r=ah(e,t),n=e.variables.length,o=ru(t.seed??1),a=4+Math.floor(3*Math.log(n)),s=Math.floor(a/2),i=[];for(let M=1;M<=s;M++)i.push(Math.log(s+.5)-Math.log(M));let c=i.reduce((M,F)=>M+F,0);for(let M=0;M<s;M++)i[M]/=c;let l=1/i.reduce((M,F)=>M+F*F,0),u=(l+2)/(n+l+5),m=1+2*Math.max(0,Math.sqrt((l-1)/(n+1))-1)+u,f=(4+l/n)/(n+4+2*l/n),p=(n+2)/3,d=Math.min(1,p*2/((n+1.3)**2+l)),h=Math.min(1-d,p*2*(l-2+1/l)/((n+2)**2+l)),b=Math.sqrt(n)*(1-1/(4*n)+1/(21*n*n)),g=sh(e,t.warmStart!==!1,r,t.startJitter,o),y=.25,R=new Array(n).fill(1),k=new Array(n).fill(0),v=new Array(n).fill(0),x=0;for(;r.left()>0;){x++;let M=[];for(let A=0;A<a&&r.left()>0;A++){let S=[];for(let L=0;L<n;L++)S.push(JL(o));let C=g.map((L,D)=>L+y*R[D]*S[D]);M.push({z:S,u:C,f:r.evaluate(C)})}if(M.length<s)break;M.sort((A,S)=>A.f-S.f);let F=g.slice(),w=new Array(n).fill(0);g=new Array(n).fill(0);for(let A=0;A<s;A++)for(let S=0;S<n;S++)g[S]+=i[A]*M[A].u[S],w[S]+=i[A]*M[A].z[S];g=g.map(A=>Math.min(1,Math.max(0,A)));for(let A=0;A<n;A++)k[A]=(1-u)*k[A]+Math.sqrt(u*(2-u)*l)*w[A];let T=Math.sqrt(k.reduce((A,S)=>A+S*S,0)),P=T/Math.sqrt(1-(1-u)**(2*x))/b<1.4+2/(n+1)?1:0;for(let A=0;A<n;A++){let S=(g[A]-F[A])/(y*R[A]);v[A]=(1-f)*v[A]+P*Math.sqrt(f*(2-f)*l)*S}for(let A=0;A<n;A++){let S=0;for(let D=0;D<s;D++)S+=i[D]*M[D].z[A]*M[D].z[A];let C=R[A]*R[A],L=(1-d-h)*C+d*(v[A]*v[A]+(1-P)*f*(2-f)*C)+h*S*C;R[A]=Math.sqrt(Math.max(1e-12,L))}if(y*=Math.exp(u/m*(T/b-1)),y<1e-6||y>10)break}return r.result("sep-cma-es")}var ya=[{name:"random",run:n1},{name:"nelder-mead",run:ga},{name:"sep-cma-es",run:o1}];var Kz=Math.PI/180;var nu=Math.PI/180;var Wz={Fz:100,alpha:.25*nu,kappa:.005,gamma:.5*nu,p:6900},a1={Fz:100,alpha:1*nu,kappa:.02,gamma:.5*nu,p:6900};var s1=Math.PI/180,Zz={t:{s:1,sec:1,ms:.001},v:{"m/s":1,"km/h":1/3.6,"km/hr":1/3.6,kph:1/3.6},alpha:{rad:1,deg:s1},gamma:{rad:1,deg:s1},p:{pa:1,kpa:1e3,bar:1e5,mpa:1e6},rl:{m:1,mm:.001,cm:.01},Fz:{n:1},Fx:{n:1},Fy:{n:1},Mz:{nm:1,"n-m":1}};var n6=Math.PI/180;var mD=Math.PI/180;var u6=3*mD;var h6=Math.PI/180;var w6=Math.PI/180;var xD={RCX1:1,RCY1:1,REX1:0,REY1:0,RBY3:0,RHX1:0,RHY1:0},l1={RBX1:15,RBX2:15,RBY1:18,RBY2:19,...xD};var V6=Math.PI/180;var SD=Math.PI/180,ou=[{id:"alpha",symbol:"\u03B1",name:"Slip angle",group:"inputs",unit:"rad"},{id:"kappa",symbol:"\u03BA",name:"Slip ratio",group:"inputs",unit:"-"},{id:"gamma",symbol:"\u03B3",name:"Inclination",group:"inputs",unit:"rad"},{id:"Fz",symbol:"Fz",name:"Vertical load",group:"inputs",unit:"N",quantity:"force"},{id:"p",symbol:"p",name:"Inflation pressure",group:"inputs",unit:"Pa",quantity:"pressure"},{id:"V",symbol:"V",name:"Speed",group:"inputs",unit:"m/s",quantity:"speed"},{id:"Fx",symbol:"Fx",name:"Longitudinal force",group:"forces",unit:"N",quantity:"force"},{id:"Fy",symbol:"Fy",name:"Lateral force",group:"forces",unit:"N",quantity:"force"},{id:"Mx",symbol:"Mx",name:"Overturning moment",group:"moments",unit:"N\xB7m"},{id:"My",symbol:"My",name:"Rolling-resistance moment",group:"moments",unit:"N\xB7m"},{id:"Mz",symbol:"Mz",name:"Aligning moment",group:"moments",unit:"N\xB7m"},{id:"t",symbol:"t",name:"Pneumatic trail",group:"aligning",unit:"m",quantity:"length"},{id:"Mzr",symbol:"Mzr",name:"Residual aligning moment",group:"aligning",unit:"N\xB7m"},{id:"s",symbol:"s",name:"Lever arm of Fx",group:"aligning",unit:"m",quantity:"length"},{id:"muX",symbol:"\u03BCx",name:"Longitudinal friction Fx/Fz",group:"friction",unit:"-"},{id:"muY",symbol:"\u03BCy",name:"Lateral friction Fy/Fz",group:"friction",unit:"-"},{id:"use",symbol:"use",name:"Friction ellipse used",group:"friction",unit:"-"},{id:"FyRel",symbol:"Fy/Fy,peak",name:"Lateral force over its peak at this load",group:"friction",unit:"-"},{id:"FxRel",symbol:"Fx/Fx,peak",name:"Driving force over its peak at this load",group:"friction",unit:"-"},{id:"dFyda",symbol:"\u2202Fy/\u2202\u03B1",name:"Cornering stiffness at the point",group:"stiffness",unit:"N/rad"},{id:"dFxdk",symbol:"\u2202Fx/\u2202\u03BA",name:"Slip stiffness at the point",group:"stiffness",unit:"N"},{id:"dFydg",symbol:"\u2202Fy/\u2202\u03B3",name:"Camber stiffness at the point",group:"stiffness",unit:"N/rad"},{id:"kz",symbol:"kz",name:"Vertical stiffness",group:"stiffness",unit:"N/mm",quantity:"springRate"},{id:"FxPeak",symbol:"Fx,peak",name:"Peak driving force",group:"characteristics",unit:"N",quantity:"force",characteristic:!0},{id:"FyPeak",symbol:"Fy,peak",name:"Peak lateral force",group:"characteristics",unit:"N",quantity:"force",characteristic:!0},{id:"muXPeak",symbol:"\u03BCx,peak",name:"Peak longitudinal friction",group:"characteristics",unit:"-",characteristic:!0},{id:"muYPeak",symbol:"\u03BCy,peak",name:"Peak lateral friction",group:"characteristics",unit:"-",characteristic:!0},{id:"kappaPeak",symbol:"\u03BA at peak",name:"Slip ratio at peak driving force",group:"characteristics",unit:"-",characteristic:!0},{id:"alphaPeak",symbol:"\u03B1 at peak",name:"Slip angle at peak lateral force",group:"characteristics",unit:"rad",characteristic:!0},{id:"Calpha",symbol:"C\u03B1",name:"Cornering stiffness at zero slip",group:"characteristics",unit:"N/rad",characteristic:!0},{id:"bestCamber",symbol:"\u03B3 best",name:"Camber for the most side force",group:"characteristics",unit:"rad",characteristic:!0},{id:"R0",symbol:"R0",name:"Free radius",group:"geometry",unit:"m",quantity:"length",characteristic:!0},{id:"Rl",symbol:"Rl",name:"Loaded radius",group:"geometry",unit:"m",quantity:"length",characteristic:!0},{id:"Re",symbol:"Re",name:"Effective rolling radius",group:"geometry",unit:"m",quantity:"length",characteristic:!0},{id:"width",symbol:"w",name:"Section width",group:"geometry",unit:"m",quantity:"length",characteristic:!0},{id:"sigmaA",symbol:"\u03C3\u03B1",name:"Lateral relaxation length",group:"transient",unit:"m",quantity:"length",characteristic:!0},{id:"Fr",symbol:"Fr",name:"Rolling-resistance force My/Re",group:"power",unit:"N",quantity:"force"},{id:"cr",symbol:"cr",name:"Rolling-resistance coefficient Fr/Fz",group:"power",unit:"-"},{id:"Pslip",symbol:"P slip",name:"Slip power |Fx\xB7Vsx| + |Fy\xB7Vsy|",group:"power",unit:"W"},{id:"Proll",symbol:"P roll",name:"Rolling power My\xB7\u03A9",group:"power",unit:"W"}],J6=new Map(ou.map(e=>[e.id,e]));var eY=.01*SD;var We=Math.PI/180;var p1=new Set(ou.filter(e=>e.group!=="inputs"&&(e.unit==="N"||e.unit==="N\xB7m"||e.unit==="N/rad")).map(e=>e.id)),d1={alpha:{from:-15*We,to:15*We,n:61},kappa:{from:-.25,to:.25,n:61},gamma:{from:-6*We,to:6*We,n:49},Fz:{from:200,to:3e3,n:40,follow:!0},p:{from:5e4,to:15e4,n:21},V:{from:0,to:40,n:41,follow:!0}},mh={alpha:{from:0,to:12*We,n:7},kappa:{from:-.2,to:.2,n:9},gamma:{from:-4*We,to:4*We,n:5},Fz:{from:400,to:1600,n:5},p:{from:6e4,to:12e4,n:4},V:{from:5,to:35,n:4}};var ph={alpha:{from:0,to:12*We,n:25},kappa:{from:-.2,to:.2,n:25},gamma:{from:-4*We,to:4*We,n:17},Fz:{from:300,to:1800,n:16},p:{from:6e4,to:12e4,n:13},V:{from:5,to:35,n:13}};var ke=(e,t,r,n={},o={})=>({id:e,form:"curves",sweep:[{input:t,...d1[t],...o}],x:t,y:r,...n}),au=(e,[t,r],n,o,a={})=>({id:e,form:"carpet",sweep:[{input:t,...mh[t]},{input:r,...mh[r]}],x:n,y:[o],...a}),Nr=(e,t)=>({id:e,fixed:t}),Ht={input:"Fz",values:"car"},uh={alpha:0,kappa:0},Mt={kappa:0},u1={alpha:0},FD={input:"Fz",values:[500,1e3,1500]},wD=[{id:"overview",name:"Overview",cards:[Nr("tyre","tyre"),ke("fy","alpha",["Fy"],{title:"Lateral force",hold:Mt}),ke("mz","alpha",["Mz"],{title:"Aligning moment",hold:Mt}),ke("fx","kappa",["Fx"],{title:"Longitudinal force",hold:u1}),au("combined-carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Nr("ellipse","ellipse")]},{id:"lateral",name:"Lateral",cards:[ke("fy-load","alpha",["Fy"],{title:"Lateral force per wheel load",series:Ht,hold:Mt}),ke("muy-load","alpha",["muY"],{title:"Lateral force per unit load",series:Ht,hold:Mt}),ke("fy-peak","alpha",["Fy"],{title:"Lateral force over its peak",series:Ht,hold:Mt,scale:{per:"peak"}},{from:0,to:15*We,n:61}),ke("muy-peak","Fz",["muYPeak"],{title:"Peak lateral \u03BC over load"}),ke("calpha","Fz",["Calpha"],{title:"Cornering stiffness over load"}),ke("alpha-peak","Fz",["alphaPeak"],{title:"Slip angle at the peak over load"})]},{id:"aligning",name:"Aligning",cards:[ke("mz-load","alpha",["Mz"],{title:"Aligning moment per wheel load",series:Ht,hold:Mt}),ke("trail","alpha",["t"],{title:"Pneumatic trail",series:Ht,hold:Mt},{from:0,to:12*We,n:49}),ke("mzr","alpha",["Mzr"],{title:"Residual aligning moment",series:Ht,hold:Mt},{from:0,to:12*We,n:49}),au("gough",["alpha","Fz"],"Fy","Mz",{title:"Gough plot",hold:Mt}),ke("steering-feel","alpha",["t"],{title:"Steering feel",x:"FyRel",series:Ht,hold:Mt},{from:0,to:12*We,n:49})]},{id:"longitudinal",name:"Longitudinal",cards:[ke("fx-load","kappa",["Fx"],{title:"Longitudinal force per wheel load",series:Ht,hold:u1}),ke("mux-peak","Fz",["muXPeak"],{title:"Peak longitudinal \u03BC over load"}),ke("kx","Fz",["dFxdk"],{title:"Slip stiffness at zero slip over load",hold:uh}),ke("kappa-peak","Fz",["kappaPeak"],{title:"Slip ratio at the peak over load"})]},{id:"combined",name:"Combined",cards:[au("carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),au("envelope-load",["kappa","alpha"],"Fy","Fx",{title:"Friction envelope per load",scale:{per:"Fz"},facet:FD}),ke("fy-kappa","kappa",["Fy"],{title:"Side force while driving or braking",series:{input:"alpha",values:[2*We,4*We,8*We]}}),ke("fx-kappa","kappa",["Fx"],{title:"Driving force while cornering",series:{input:"alpha",values:[0,4*We,8*We]}}),Nr("ellipse","ellipse")]},{id:"camber",name:"Camber",cards:[ke("fy-gamma","alpha",["Fy"],{title:"Lateral force per inclination",series:{input:"gamma",values:[-4,-2,0,2,4].map(e=>e*We)},hold:Mt}),ke("camber-sweep","gamma",["FyPeak","Fy"],{title:"Peak, and camber thrust at zero slip",hold:{alpha:0}}),{id:"camber-map",title:"Camber map",form:"map",sweep:[{input:"gamma",...ph.gamma},{input:"Fz",...ph.Fz,follow:!0}],x:"gamma",y:["Fz"],z:"muYPeak"},ke("camber-stiffness","alpha",["dFydg"],{title:"Camber stiffness at the point",series:Ht,hold:Mt}),ke("mx","alpha",["Mx"],{title:"Overturning moment",series:Ht,hold:Mt})]},{id:"rolling",name:"Rolling and radius",cards:[ke("my","V",["My"],{title:"Rolling-resistance moment",series:Ht,hold:uh}),ke("radius","Fz",["R0","Rl","Re"],{title:"Radius over load"},{from:0}),ke("p-roll","V",["Proll"],{title:"Rolling power",series:Ht,hold:uh})]},{id:"transient",name:"Transient",cards:[ke("sigma","Fz",["sigmaA"],{title:"Relaxation length over load"})]},{id:"tyres",name:"Side by side",cards:[{id:"trade-off",title:"Grip against cornering stiffness",form:"points",sweep:[],x:"Calpha",y:["muYPeak"]},{id:"pressure-family",title:"Peak \u03BCy over pressure, by family",form:"points",sweep:[],x:"p",y:["muYPeak"],family:!0},ke("delta-fy","alpha",["Fy"],{title:"Lateral force, minus the reference",hold:Mt,scale:{delta:!0}}),ke("delta-mu","Fz",["muYPeak"],{title:"Peak lateral \u03BC over load, minus the reference",scale:{delta:!0}}),ke("delta-calpha","Fz",["Calpha"],{title:"Cornering stiffness over load, minus the reference",scale:{delta:!0}})]},{id:"car",name:"Car",cards:[Nr("operating","operating"),Nr("wheels","wheels")]},{id:"fit",name:"Fit check",cards:[Nr("fitLateral","fitLateral"),Nr("fitLongitudinal","fitLongitudinal"),Nr("fitCoupling","fitCoupling"),Nr("fitEnvelope","fitEnvelope")]}];var ID=5670374e-14,dh=273.15,b1=.95,g1=60,su=10,_D=.55,Lt=25,fh=-20,hh=50,ni={tempC:[20,100,200,550,650,750],factor:[.8,.92,1,1,.85,.65]},oi={discMassKg:.5,discOuterMm:220,specificHeatJPerKgK:460,emissivity:.6,coolingWPerM2K:200,padCurve:{tempC:[...ni.tempC],factor:[...ni.factor]}},iu={...oi,discMassKg:.4,discOuterMm:200,padCurve:{tempC:[...ni.tempC],factor:[...ni.factor]}};function bh(e,t){let r=t==="front"?oi:iu,n=Math.round(2*e.effRadiusMm+40);return{...r,discOuterMm:n,discMassKg:Math.round(100*r.discMassKg*(n/r.discOuterMm)**2)/100,padCurve:{tempC:[...r.padCurve.tempC],factor:[...r.padCurve.factor]}}}var ND=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},ri=(e,t,r,n)=>Math.min(r,Math.max(t,ND(e,n)));function OD(e,t){let r=e,n=Array.isArray(r?.tempC)?r.tempC:[],o=Array.isArray(r?.factor)?r.factor:[],a=[];for(let i=0;i<Math.min(n.length,o.length);i++){let c=Number(n[i]),l=Number(o[i]);Number.isFinite(c)&&Number.isFinite(l)&&a.push([Math.min(1500,Math.max(-50,c)),Math.min(2,Math.max(.05,l))])}a.sort((i,c)=>i[0]-c[0]);let s=a.filter((i,c)=>c===0||i[0]>a[c-1][0]);return s.length?{tempC:s.map(i=>i[0]),factor:s.map(i=>i[1])}:{tempC:[...t.tempC],factor:[...t.factor]}}function gh(e,t){return{discMassKg:ri(e?.discMassKg,.05,20,t.discMassKg),discOuterMm:ri(e?.discOuterMm,50,600,t.discOuterMm),specificHeatJPerKgK:ri(e?.specificHeatJPerKgK,100,3e3,t.specificHeatJPerKgK),emissivity:ri(e?.emissivity,.02,1,t.emissivity),coolingWPerM2K:ri(e?.coolingWPerM2K,su,5e3,t.coolingWPerM2K),padCurve:OD(e?.padCurve,t.padCurve)}}function cu(e,t){let r=e.tempC,n=e.factor,o=Math.min(r.length,n.length);if(o===0)return 1;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=1;for(;a<o-1&&r[a]<t;)a++;return n[a-1]+(t-r[a-1])/(r[a]-r[a-1])*(n[a]-n[a-1])}function yh(e,t=1){let r=e.discMassKg*e.specificHeatJPerKgK,n=e.discOuterMm*.001/2,o=2*Math.PI*n*n,a=g1/3.6,s=e.emissivity*ID*o,i=m=>su+(e.coolingWPerM2K-su)*Math.pow(Math.max(0,m)*t/a,_D),c=(m,f,p)=>{let d=m+dh,h=p+dh;return i(f)*o*(m-p)+s*(d**4-h**4)},l=(m,f)=>i(f)*o+4*s*Math.max(0,m+dh)**3,u=(m,f)=>r/l(f,m);return{heatCapacityJPerK:r,areaM2:o,convectionAt:i,coolingW:c,timeConstantS:u,step(m,f,p,d,h){if(!(d>0))return m+f/r;let b=u(p,m+Math.max(0,f)/r),g=Math.max(1,Math.ceil(d/(.25*b))),y=d/g,R=f/g;for(let k=0;k<g;k++)m+=(R-c(m,p,h)*y)/r;return m},padFactor:m=>cu(e.padCurve,m),window:y1(e.padCurve)}}function lu(e,t,r,n,o,a,s=Lt){let i=n.length,c=new Array(i),l=new Array(i),u=new Array(i),m=b1/Math.max(1,t),f=a,p=f,d=0,h=0,b=0;for(let g=0;g<i;g++){let y=Math.max(0,r[g]??0);c[g]=f,l[g]=y*n[g],u[g]=e.padFactor(f);let R=y*(o[g]??0);d+=R,f<e.window.fromC?h+=R:f>e.window.toC&&(b+=R);let k=g+1<i?n[g+1]:n[g],v=.5*(n[g]+k),x=v>0?(o[g]??0)/v:0;f=e.step(f,m*R,v,x,s),f>p&&(p=f)}return{tempC:c,heatW:l,padFactor:u,startC:a,endC:f,maxC:p,workJ:d,coldWorkJ:h,hotWorkJ:b}}function y1(e){let t=e.tempC,r=Math.min(t.length,e.factor.length);if(r===0)return{fromC:-1/0,toC:1/0};let n=Math.max(...e.factor.slice(0,r)),o=null;for(let c=0;c<r;c++){if(e.factor[c]<n-1e-9)continue;let l=c;for(;l+1<r&&e.factor[l+1]>=n-1e-9;)l++;l>c&&(!o||t[l]-t[c]>o.toC-o.fromC)&&(o={fromC:t[c],toC:t[l]}),c=l}if(o)return o;let a=NaN,s=NaN,i=NaN;for(let c=Math.floor(t[0]);c<=Math.ceil(t[r-1])+1;c++){let l=c<=Math.ceil(t[r-1])&&cu(e,c)>=.98*n;l&&Number.isNaN(i)&&(i=c),!l&&!Number.isNaN(i)&&((Number.isNaN(a)||c-1-i>s-a)&&(a=i,s=c-1),i=NaN)}return{fromC:a,toC:s}}var xh=1e5,k1=.001,qn={pedalRatio:4,pedalForceMaxN:0,barFront:.5,masterFrontMm:15.875,masterRearMm:15.875,valve:"none",valveKneeBar:20,valveSlope:.3,front:{location:"outboard",discs:2,pistonsPerSide:2,pistonDiaMm:25.4,padMu:.45,effRadiusMm:90,ratio:1},rear:{location:"outboard",discs:2,pistonsPerSide:1,pistonDiaMm:25.4,padMu:.45,effRadiusMm:80,ratio:1},adjusterPitchMm:1,barLengthMm:0},vh={fullAtBar:10,maxPowerKw:0,fadeBelowKmh:0,distribution:"equal"};var kh=S1(mu(qn,"Formula Student brakes")),Mh=40,M1={ideal:!1,barFront:qn.barFront,pedalForceMaxN:0,testSpeedKmh:Mh,regen:vh};function x1(e){let{heat:t,...r}=e;return t?{...r,heat:{...t,padCurve:{tempC:[...t.padCurve.tempC],factor:[...t.padCurve.factor]}}}:r}function S1(e){let t=(r,n)=>r.heat?r:{...r,heat:bh(r,n)};return{...e,front:t(e.front,"front"),rear:t(e.rear,"rear")}}function mu(e,t){return{name:t,pedalRatio:e.pedalRatio,masterFrontMm:e.masterFrontMm,masterRearMm:e.masterRearMm,valve:e.valve,valveKneeBar:e.valveKneeBar,valveSlope:e.valveSlope,front:x1(e.front),rear:x1(e.rear),adjusterPitchMm:e.adjusterPitchMm,barLengthMm:e.barLengthMm}}function Sh(e,t){return A1({...e,barFront:t.barFront,pedalForceMaxN:t.pedalForceMaxN})}function Ah(e,t){let r=Vr(t),n=e?pr(e):void 0;return{mode:r.ideal?"tyre":n?"hydraulic":"balance",hydraulic:n?Sh(n,r):qn,regen:r.regen}}var VD=["none","proportioning","limiter"],uu=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},et=(e,t,r,n)=>Math.min(r,Math.max(t,uu(e,n))),BD=(e,t)=>{let r=uu(e,t);return r>0?r:t};function R1(e,t,r){let n=e?.location==="inboard"?"inboard":e?.location==="outboard"?"outboard":t.location;return{location:n,discs:Math.max(1,Math.min(4,Math.round(uu(e?.discs,n==="inboard"?1:t.discs)))),pistonsPerSide:Math.max(1,Math.min(6,Math.round(uu(e?.pistonsPerSide,t.pistonsPerSide)))),pistonDiaMm:et(e?.pistonDiaMm,5,80,t.pistonDiaMm),padMu:et(e?.padMu,.05,1.5,t.padMu),effRadiusMm:et(e?.effRadiusMm,20,300,t.effRadiusMm),ratio:n==="inboard"?et(e?.ratio,1,20,t.ratio):1,...e?.heat&&typeof e.heat=="object"?{heat:gh(e.heat,t.heat??r)}:{}}}function A1(e){let t=qn;return{pedalRatio:et(e?.pedalRatio,.5,15,t.pedalRatio),pedalForceMaxN:et(e?.pedalForceMaxN,0,5e3,t.pedalForceMaxN),barFront:et(e?.barFront,.05,.95,t.barFront),masterFrontMm:et(e?.masterFrontMm,8,40,t.masterFrontMm),masterRearMm:et(e?.masterRearMm,8,40,t.masterRearMm),valve:VD.includes(e?.valve)?e?.valve:t.valve,valveKneeBar:et(e?.valveKneeBar,0,200,t.valveKneeBar),valveSlope:et(e?.valveSlope,0,1,t.valveSlope),front:R1(e?.front,t.front,oi),rear:R1(e?.rear,t.rear,iu),adjusterPitchMm:BD(e?.adjusterPitchMm,t.adjusterPitchMm),barLengthMm:et(e?.barLengthMm,0,500,t.barLengthMm)}}function $D(e){let t=vh;return{fullAtBar:et(e?.fullAtBar,0,200,t.fullAtBar),maxPowerKw:et(e?.maxPowerKw,0,1e3,t.maxPowerKw),fadeBelowKmh:et(e?.fadeBelowKmh,0,100,t.fadeBelowKmh),distribution:e?.distribution==="wheel"?"wheel":"equal"}}function pr(e){let t=A1(e??void 0),r=typeof e?.name=="string"&&e.name.trim()?e.name:GD;return mu(t,r)}function Vr(e){return{ideal:e?.ideal===!0,barFront:et(e?.barFront,.05,.95,qn.barFront),pedalForceMaxN:et(e?.pedalForceMaxN,0,5e3,0),testSpeedKmh:et(e?.testSpeedKmh,5,150,Mh),regen:$D(e?.regen)}}var GD="Formula Student brakes";var Rh=e=>Math.PI/4*(e*k1)**2;function bn(e,t){let r=e.pistonsPerSide*Rh(e.pistonDiaMm)*xh;return e.discs*2*e.padMu*r*e.effRadiusMm*k1*e.ratio/Math.max(.05,t)}function F1(e,t){if(e.valve==="none"||t<=e.valveKneeBar)return t;let r=e.valve==="limiter"?0:e.valveSlope;return e.valveKneeBar+r*(t-e.valveKneeBar)}function ai(e,t){let r=Math.max(0,t)*e.pedalRatio,n=e.barFront*r/Rh(e.masterFrontMm)/xh,o=(1-e.barFront)*r/Rh(e.masterRearMm)/xh;return{front:n,rearIn:o,rear:F1(e,o)}}function KD(e,t){let r=ai(e,1);return{front:bn(e.front,t)*r.front,rear:bn(e.rear,t)*r.rearIn}}function si(e,t){let r=KD(e,t);return r.front/Math.max(1e-12,r.front+r.rear)}function ii(e,t){let r=[],n=[],o=[],a=e.vVehicle.length,s=Math.max(1,Math.floor(a/60));for(let c=0;c<a;c+=s)i(c);return(a-1)%s!==0&&i(a-1),{v:r,front:n,rear:o};function i(c){let l=e.vVehicle[c],u=w1(t,l),m=t.maxPowerKw>0&&l>0?t.maxPowerKw*1e3/l:1/0,f=Math.max(0,e.fFront[c]),p=Math.max(0,e.fRear[c]),d=f+p>0?Math.min(1,m/(f+p)):1;r.push(l),n.push(f*d*u),o.push(p*d*u)}}function w1(e,t){let r=e.fadeBelowKmh/3.6;return r>0?Math.max(0,Math.min(1,t/r)):1}function Or(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]||1);return t[o]+s*(t[a]-t[o])}var v1=new WeakMap;function Qn(e){let t=v1.get(e);return t||(t=e.mode==="hydraulic"&&e.hydraulic?zD(e,e.hydraulic):HD(e),v1.set(e,t)),t}function HD(e){let t=Math.min(.99,Math.max(.01,e.balanceFront));return{mode:e.mode,equalLeftRight:e.mode!=="tyre",uMax:1/0,shares:{front:t,rear:1-t},demand:r=>({front:t*r,rear:(1-t)*r,regenFront:0,regenRear:0,pFront:0,pRear:0,pedalN:0}),controlFor:r=>Math.max(0,r)}}function zD(e,t){let r=bn(t.front,e.tyreRadiusM),n=bn(t.rear,e.tyreRadiusM),o=e.regen,a=(c,l)=>{let u=ai(t,c),m=0,f=0;if(o&&u.front>0){let p=o.fullAtBar>0?Math.min(1,u.front/o.fullAtBar):1;m=p*Or(o.v,o.front,l),f=p*Or(o.v,o.rear,l)}return{front:r*u.front+m,rear:n*u.rear+f,regenFront:m,regenRear:f,pFront:u.front,pRear:u.rear,pedalN:c}},s=t.pedalForceMaxN>0?t.pedalForceMaxN:1/0,i=(c,l)=>{let u=a(c,l);return u.front+u.rear};return{mode:"hydraulic",equalLeftRight:!0,uMax:s,demand:a,controlFor:(c,l)=>{if(!(c>0))return 0;let u=100;for(;i(u,l)<c&&u<1e6;)u*=2;if(u=Math.min(u,s),i(u,l)<=c)return u;let m=0;for(let f=0;f<60;f++){let p=.5*(m+u);i(p,l)<c?m=p:u=p}return u}}}function Fh(e,t,r){let n=t>0?e.controlFor(t,r):0,o=e.demand(n>0?n:1,r),a=o.front+o.rear;return a>0?o.front/a:.5}var pu=Vs,YD=.1,Zn=(e,t)=>e.a*Math.sqrt(Math.max(0,1-(t/Math.max(1e-9,e.b))**2));function du(e,t,r){if(!(r>t))return t;let n=(Math.sqrt(5)-1)/2,o=t,a=r,s=a-n*(a-o),i=o+n*(a-o),c=e(s),l=e(i);for(let f=0;f<48;f++)c<l?(o=s,s=i,c=l,i=o+n*(a-o),l=e(i)):(a=i,i=s,l=c,s=a-n*(a-o),c=e(s));let u=.5*(o+a),m=e(u);for(let f of[t,r]){let p=e(f);p>m&&(u=f,m=p)}return u}function Th(e,t,r){let n=Math.max(0,r-pu*t.b),o=Math.min(r,pu*e.b);if(!(n<=o))return;let a=(c,l)=>c.a*c.a*Math.max(0,1-(l/Math.max(1e-9,c.b))**2),s=c=>a(e,c)-a(t,r-c),i;if(s(n)<=0)i=n;else if(s(o)>=0)i=o;else{let c=n,l=o;for(let u=0;u<40;u++){let m=.5*(c+l);s(m)>0?c=m:l=m}i=.5*(c+l)}return{lo:n,hi:o,y1:i,c1:e.cap(i),c2:t.cap(r-i)}}function Ph(e,t,r,n,o=0){let a=Math.max(0,r),s=Th(e,t,a),i=s?s.c1:0,c=s?s.c2:0,l=s?Math.min(i,c):0,[u,m]=e.a<=t.a?[e,t]:[t,e],f=u.Fz/Math.max(1e-9,u.Fz+m.Fz),p=Math.max(0,Math.min(1,1-f/YD)),d=p>0&&a<pu*m.b?m.cap(a):0,h=d>l?l+p*(d-l):0,b=Math.max(0,Math.min(u.slide,u.a)),g={xNoLock:l,xLock:h,slide:b,ceiling:Math.max(0,n)},y=Math.max(0,o);if(!(y>0)||!s)return{...g,regenWheel:s?y:0,mixedMax:2*l,regenRoom:P=>2*Math.max(0,l-P)};let{lo:R,hi:k}=s,v=du(P=>{let A=Zn(e,P),S=Zn(t,a-P);return Math.min(A+S,2*Math.min(A,S)+y)},R,k),x=e.cap(v),M=t.cap(a-v),F=Math.max(2*l,Math.min(x+M,2*Math.min(x,M)+y)),w=(P,A,S)=>Math.min(y,Math.max(0,P-S))+Math.min(y,Math.max(0,A-S));return{...g,regenWheel:y,mixedMax:F,regenRoom:P=>{let A=w(i,c,P);if(!(a>0))return A;let S=I=>pu*I.b*Math.sqrt(Math.max(0,1-(P/Math.max(1e-9,I.a))**2)),C=Math.max(R,a-S(t)),L=Math.min(k,S(e));if(!(C<=L))return A;let D=du(I=>Math.min(y,Zn(e,I)-P)+Math.min(y,Zn(t,a-I)-P),C,L);return Math.max(A,w(e.cap(D),t.cap(a-D),P))}}}var wh=e=>Math.max(e.xNoLock,e.xLock),Ch=e=>Math.max(e.mixedMax,2*e.xLock);function xa(e,t,r=0){let n=1e-9*Math.max(1,t),o=Math.max(0,r);if(t<=e.xNoLock+n)return Math.min(2*t+(o>0?Math.min(o,e.regenRoom(t)):0),e.ceiling);if(t<=e.xLock+n){let a=o>0?Math.min(e.regenWheel>0?Math.min(o,e.regenWheel):o/2,Math.max(0,e.xLock-t)):0;return Math.min(t+e.slide+a,e.ceiling)}return NaN}function Ra(e,t){let r=t/2,n=1e-9*Math.max(1,r);return r<=e.mixedMax/2+n?Math.min(t,e.ceiling):r<=e.xLock+n?Math.min(r+e.slide,e.ceiling):NaN}function ci(e,t,r,n){return e.shares?WD(e,e.shares,t,r,n):jD(e,t,r,n)}function C1(e,t){let r=e[0],n=t(r.u);for(let o of e.slice(1)){let a=t(o.u);a>n&&(r=o,n=a)}return{cand:r,force:n}}function WD(e,t,r,n,o){let a=Ch(r),s=Ch(n),i=Math.min(t.front>0?a/t.front:1/0,t.rear>0?s/t.rear:1/0,e.uMax),c=Number.isFinite(e.uMax)&&i>=e.uMax,l=b=>{let g=Ra(r,t.front*b),y=Ra(n,t.rear*b);return Number.isFinite(g)&&Number.isFinite(y)?g+y:-1/0},u=a>0?t.front*i/a:1/0,m=s>0?t.rear*i/s:1/0,f=[{u:i,by:c?"pedal":u>=m?"front":"rear"}];if(r.xLock>r.xNoLock){let b=t.front>0?r.mixedMax/t.front:1/0;b<i&&f.push({u:b,by:"front"})}if(n.xLock>n.xNoLock){let b=t.rear>0?n.mixedMax/t.rear:1/0;b<i&&f.push({u:b,by:"rear"})}let{cand:p,force:d}=C1(f,l),h=e.demand(p.u,o);return{force:Math.max(0,Number.isFinite(d)?d:0),control:p.u,demand:h,limitedBy:p.by,lockFront:h.front/2>r.mixedMax/2*(1+1e-9),lockRear:h.rear/2>n.mixedMax/2*(1+1e-9)}}function jD(e,t,r,n){let o=wh(t),a=wh(r),s=v=>(v.front-v.regenFront)/2,i=v=>(v.rear-v.regenRear)/2,c=v=>{let x=e.demand(v,n);return s(x)<=o*(1+1e-12)&&i(x)<=a*(1+1e-12)},l=(v,x)=>{if(v(e.demand(x,n)))return x;let M=0,F=x;for(let w=0;w<60;w++){let T=.5*(M+F);v(e.demand(T,n))?M=T:F=T}return M},u=Number.isFinite(e.uMax)?e.uMax:100;if(!Number.isFinite(e.uMax))for(;c(u)&&u<1e7;)u*=2;let m=c(u)?u:l(v=>s(v)<=o&&i(v)<=a,u),f=Number.isFinite(e.uMax)&&m>=e.uMax,p=v=>{let x=e.demand(v,n),M=xa(t,s(x),x.regenFront),F=xa(r,i(x),x.regenRear);return Number.isFinite(M)&&Number.isFinite(F)?M+F:-1/0},d=e.demand(m,n),h=o>0?s(d)/o:1/0,b=a>0?i(d)/a:1/0,g=[{u:m,by:f?"pedal":h>=b?"front":"rear"}];if(t.xLock>t.xNoLock){let v=l(x=>s(x)<=t.xNoLock,m);v<m&&g.push({u:v,by:"front"})}if(r.xLock>r.xNoLock){let v=l(x=>i(x)<=r.xNoLock,m);v<m&&g.push({u:v,by:"rear"})}let{cand:y,force:R}=C1(g,p),k=e.demand(y.u,n);return{force:Math.max(0,Number.isFinite(R)?R:0),control:y.u,demand:k,limitedBy:y.by,lockFront:s(k)>t.xNoLock*(1+1e-9),lockRear:i(k)>r.xNoLock*(1+1e-9)}}var Br={regen:!0,regenEfficiency:.6};function $r(e,t){let r=e.energy??t??Br;return{regen:r.regen===!0,regenEfficiency:Math.min(1,Math.max(0,Number.isFinite(r.regenEfficiency)?r.regenEfficiency:0))}}function Gr(e,t,r){let n=Math.max(0,Math.floor(r));if(n===0)return[];if(n===1)return[e];let o=new Array(n),a=(t-e)/(n-1);for(let s=0;s<n;s++)o[s]=e+a*s;return o[n-1]=t,o}function T1(e,t,r){let n=[],o=Math.floor((r-e)/t+1e-9);for(let a=0;a<=o;a++)n.push(e+t*a);return n}function ht(e,t,r){let n=e.length;if(r<e[0]||r>e[n-1])return NaN;if(r===e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function fu(e,t,r){let n=e.length;if(!(r>=e[0]&&r<=e[n-1]))return NaN;if(n<3)return n===1?t[0]:t[0]+(r-e[0])/(e[1]-e[0])*(t[1]-t[0]);let o=0,a=n-1;for(;a-o>1;){let d=o+a>>1;e[d]<=r?o=d:a=d}if(o===n-1)return t[n-1];let s=d=>e[d+1]-e[d],i=d=>(t[d+1]-t[d])/s(d),c=d=>{if(d===0||d===n-1){let[y,R]=d===0?[0,1]:[n-2,n-3],k=i(y)*(1+s(y)/(s(y)+s(R)))-i(R)*(s(y)/(s(y)+s(R)));return k*i(y)<=0?0:Math.abs(k)>2*Math.abs(i(y))?2*i(y):k}let h=i(d-1),b=i(d),g=(h*s(d)+b*s(d-1))/(s(d-1)+s(d));return(Math.sign(h)+Math.sign(b))*Math.min(Math.abs(h),Math.abs(b),.5*Math.abs(g))},l=s(o),u=i(o),m=c(o),f=c(o+1),p=r-e[o];return t[o]+p*(m+p*((3*u-2*m-f)/l+p*(m+f-2*u)/(l*l)))}function li(e,t,r){return r.map(n=>ht(e,t,n))}var ui=e=>e.reduce((t,r)=>r>t?r:t,-1/0),va=e=>e.reduce((t,r)=>r<t?r:t,1/0);var UD=[-.906179845938664,-.538469310105683,0,.538469310105683,.906179845938664],XD=[.236926885056189,.478628670499366,.568888888888889,.478628670499366,.236926885056189];function Lh(e,t,r){let n=.5*(r-t),o=.5*(t+r),a=0;for(let s=0;s<5;s++)a+=XD[s]*e(n*UD[s]+o);return n*a}var qD=Math.PI*2,QD=.5/3.6;function mi(e,t){let r=Math.max(0,Math.round(e));if(t==="front")return{front:r,rear:0};if(t==="rear")return{front:0,rear:r};let n=Math.floor(r/2);return{front:n,rear:r-n}}function Dh(e,t,r,n,o){let a=e.rpm,s=e.torque,i=a.length,c=new Array(i),l=new Array(i);for(let g=0;g<i;g++){let y=a[g]/60*qD;c[g]=y*o/n,l[g]=s[g]*n/o}let u=ui(c),m=Gr(va(c),u,u/QD),f=li(c,l,m),{front:p,rear:d}=mi(t,r),h=f.map(g=>g*p),b=f.map(g=>g*d);return{vVehicle:m,fFront:h,fRear:b,vMax:u}}var P1=60/(2*Math.PI),L1=.1,D1=.08,E1=0;function Eh(e){let t=(r,n)=>r===void 0||!Number.isFinite(r)?n:Math.max(0,r);return{up:t(e.upshiftTime,L1),down:t(e.downshiftTime,D1)}}function Ih(e){let t=e.driveKept;return t===void 0||!Number.isFinite(t)?E1:Math.max(0,Math.min(1,t))}function _h(e,t,r){let{primary:n,ratios:o,efficiency:a}=e.gearbox,s=t>0&&r>0&&n>0,i=(b,g)=>b/P1*r/g,c=s?o.filter(b=>b>0).map(b=>{let g=n*b*t;return{ratio:g,vIdle:i(e.idleRpm,g),vLimit:i(e.limitRpm,g)}}):[],l=Math.max(0,Math.min(1,a)),u=Math.max(0,e.inertia),m=b=>b>e.limitRpm?0:Math.max(0,Ge(e.rpm,e.torque,b)),f=(b,g)=>{let y=c[g];return y?b*y.ratio/r*P1:0},p=(b,g)=>g===0&&c.length>0&&b<c[0].vIdle,d=(b,g)=>{let y=c[g];return y?p(b,g)?m(e.idleRpm)*y.ratio*l/r:b<y.vIdle||b>y.vLimit?0:m(f(b,g))*y.ratio*l/r:0},h=(b,g)=>{let y=c[g];return!y||p(b,g)?0:u*y.ratio*y.ratio/(r*r)};return{engine:e,gears:c,efficiency:l,rDyn:r,vMax:c.length?c[c.length-1].vLimit:0,rpm:f,torque:m,force:d,inertiaMass:h,slipping:p}}function ka(e,t,r,n=0,o=1){let a=-1,s=-1/0;for(let i=0;i<e.gears.length;i++){let c=(o*e.force(t,i)+n)/(r+e.inertiaMass(t,i));c>=s&&(s=c,a=i)}return{gear:a,accel:s}}function Nh(e,t){let r=0;for(let n=0;n<e.gears.length;n++)r=Math.max(r,e.force(t,n));return r}var I1=9.81,_1=Math.PI*2;function Dt(e){let t=e.motor.rpm,r=e.motor.torque,n=t.length,o=new Array(n),a=new Array(n),s=new Array(n),i=new Array(n),c=new Array(n),l=e.gear_ratio.value,u=e.r_dyn.value;for(let v=0;v<n;v++)o[v]=r[v]*t[v]*(_1/60),a[v]=t[v]/60*_1,s[v]=a[v]*u/l,i[v]=r[v]*l,c[v]=i[v]/u;let m=ui(s),f=m,p=.5/3.6,d=Gr(va(s),m,m/p),h=li(s,c,d),b=Gr(va(t),ui(t),250),g=li(t,o,b).map(v=>v*e.power_scale.value),y,R=f,k;if(e.motorModel?.kind==="ice"){k=_h(e.motorModel,l,u);let v=Gr(0,k.vMax,Math.max(2,Math.ceil(k.vMax/p)+1)),x=v.map(w=>Nh(k,w)),M=v.map(()=>0),F=e.motorPlacement==="front";y={vVehicle:v,fFront:F?x:M,fRear:F?M:x,vMax:k.vMax},R=k.vMax}else e.motorModel&&(y=Dh(e.motorModel,Math.max(1,Math.round(e.motorCount??e.driven_wheels.value)),e.motorPlacement??"rear",l,u),R=y.vMax);return{params:e,g:I1,FG:e.m.value*I1,vMax:R,vVehicle:d,fRad:h,uMotor:b,pMotor:g,vRad:s,fAxle:y,...k?{engine:k}:{}}}var gn=e=>e.motorModel?.kind==="ice"?mi(1,e.motorPlacement==="front"?"front":"rear"):mi(Math.max(1,Math.round(e.motorCount??e.driven_wheels?.value??2)),e.motorPlacement??"rear");function N1(e){let t=gn(e);return t.front>=2||t.rear>=2}function O1(e){return N1(e)?e.motorMount??"hub":"chassis"}function Oh(e){if(!e.motorModel)return{front:!1,rear:!0};let t=gn(e);return{front:t.front>0,rear:t.rear>0}}function Vh(e){let t=gn(e),r=t.front>0,n=t.rear>0,o=e.front_mass_diss?.value??.5,a=Math.max(0,Math.min(1,o>1?o/100:o)),s=O1(e)==="chassis",i=c=>c===1||c>1&&s;return{front:r&&n?a:r?1:0,inboard:{front:i(t.front),rear:i(t.rear)}}}function bt(e){return Ah(e.brakeModel,e.brakeSetup)}function hu(e){return Vr(e.brakeSetup).ideal?"tyre":e.brakeModel||e.brakeModelId?"hydraulic":"balance"}function V1(e,t){if(!(xt(e.motorModel)||!$r(e).regen))return ii(bu(Dt(e)),t??bt(e).regen)}function bu(e){return e.fAxle??{vVehicle:e.vVehicle,fFront:e.vVehicle.map(()=>0),fRear:e.fRad.map(t=>t*e.params.driven_wheels.value)}}function Bh(e,t=bt(e)){if(t.mode==="hydraulic")return si(t.hydraulic,e.r_dyn.value);if(t.mode==="tyre"){let r=e.front_mass_diss.value>1?e.front_mass_diss.value/100:e.front_mass_diss.value;return Math.min(.95,Math.max(.05,r+Q(e,"cg_height")/Math.max(1,Q(e,"wheelbase"))))}return Q(e,"brake_balance")}function $h(e,t=bt(e)){return{front:t.hydraulic.front.location==="inboard",rear:t.hydraulic.rear.location==="inboard"}}function Gh(e){let t=bt(e);return{brakeBalanceFront:Bh(e,t),brakeInboard:$h(e,t)}}function B1(e,t=bt(e)){if(t.mode==="tyre"||t.regen.distribution!=="wheel"||xt(e.motorModel))return;let r=gn(e),n={front:r.front>=2,rear:r.rear>=2};return n.front||n.rear?n:void 0}function pi(e){let t=bt(e),r=e.r_dyn.value,n=$h(e,t),o=Bh(e,t),a=B1(e,t),s=t.mode==="hydraulic"||a?V1(e,t.regen):void 0;return{mode:t.mode,balanceFront:o,...t.mode==="hydraulic"?{hydraulic:t.hydraulic}:{},tyreRadiusM:r,inboard:n,...s?{regen:{...s,fullAtBar:t.regen.fullAtBar}}:{},...s&&a?{regenPerWheel:a}:{}}}var JD=9.81;function Kh(e,t){if(xt(e.motorModel))return()=>0;let r=bt(e),n=ii(t,r.regen);if(r.mode==="hydraulic"){let a=Qn({mode:"hydraulic",balanceFront:si(r.hydraulic,e.r_dyn.value),hydraulic:r.hydraulic,tyreRadiusM:e.r_dyn.value,regen:{...n,fullAtBar:r.regen.fullAtBar}});return(s,i)=>{if(!(s>0))return 0;let c=a.demand(a.controlFor(s,i),i);return Math.min(s,c.regenFront+c.regenRear)}}let o=r.mode==="tyre"?eE(e):()=>Math.min(.99,Math.max(.01,Q(e,"brake_balance")));return(a,s,i)=>{if(!(a>0))return 0;let c=o(s,i);return Math.min(c*a,Or(n.v,n.front,s))+Math.min((1-c)*a,Or(n.v,n.rear,s))}}function eE(e){let t=e.m.value*JD,r=e.front_mass_diss.value>1?e.front_mass_diss.value/100:e.front_mass_diss.value,n=Q(e,"cg_height")/Math.max(1,Q(e,"wheelbase")),o=1-Math.max(0,Math.min(1,Q(e,"cop_long"))),a=.5*e.rho.value*e.c_l.value*e.A.value;return(s,i)=>{let c=Math.max(0,a*s*s),l=t*(r+Math.abs(i)*n)+c*o;return Math.min(.99,Math.max(.01,l/(t+c)))}}function $1(e){let t=e==="front"?"Front axle":"Rear axle";return{[`${e}.location`]:{section:t,label:"Disc location",control:"Mounting"},[`${e}.discs`]:{section:t,label:"Discs",control:"Mounting"},[`${e}.ratio`]:{section:t,label:"Reduction to the wheel",unit:": 1"},[`${e}.pistonsPerSide`]:{section:t,label:"Pistons a side"},[`${e}.pistonDiaMm`]:{section:t,label:"Piston bore",unit:"mm"},[`${e}.padMu`]:{section:t,label:"Pad friction \u03BC"},[`${e}.effRadiusMm`]:{section:t,label:"Effective radius",unit:"mm"},[`${e}.heat.discMassKg`]:{section:t,label:"Disc mass",unit:"kg"},[`${e}.heat.discOuterMm`]:{section:t,label:"Disc diameter",unit:"mm"},[`${e}.heat.specificHeatJPerKgK`]:{section:t,label:"Specific heat",unit:"J/(kg\xB7K)"},[`${e}.heat.emissivity`]:{section:t,label:"Emissivity"},[`${e}.heat.coolingWPerM2K`]:{section:t,label:"Cooling at 60 km/h",unit:"W/(m\xB2\xB7K)"},[`${e}.heat.padCurve.tempC`]:{section:t,label:"Pad curve temperature",unit:"\xB0C"},[`${e}.heat.padCurve.factor`]:{section:t,label:"Pad curve friction"}}}var Hh={pedalRatio:{section:"Pedal box & bar",label:"Pedal ratio",unit:": 1"},barLengthMm:{section:"Pedal box & bar",label:"Bar length, clevis to clevis",unit:"mm"},adjusterPitchMm:{section:"Pedal box & bar",label:"Adjuster pitch",unit:"mm/turn"},masterFrontMm:{section:"Master cylinders",label:"Front bore",unit:"mm"},masterRearMm:{section:"Master cylinders",label:"Rear bore",unit:"mm"},valve:{section:"Rear valve",label:"Valve"},valveKneeBar:{section:"Rear valve",label:"Knee",unit:"bar"},valveSlope:{section:"Rear valve",label:"Gain above the knee"},...$1("front"),...$1("rear")},zh={ideal:{label:"Ideal brakes"},barFront:{label:"Balance bar"},pedalForceMaxN:{label:"Pedal force",unit:"N"},testSpeedKmh:{section:"Brake test",label:"Speed",unit:"km/h"},"regen.maxPowerKw":{section:"Regen",label:"Power ceiling",unit:"kW"},"regen.fadeBelowKmh":{section:"Regen",label:"Fades out below",unit:"km/h"},"regen.fullAtBar":{section:"Regen",label:"Full at",unit:"bar"},"regen.distribution":{section:"Regen",label:"Wheel by wheel"}};function Yh(e){let t=Hh[e];return`${t.label}, ${t.section}`.toLowerCase()}function Wh(e){let t=zh[e];return t.section?`${t.section} ${t.label.charAt(0).toLowerCase()}${t.label.slice(1)}`:t.label}var G1=new WeakMap;function dr(e){if(e.brakes)return e.brakes;let t=G1.get(e);if(!t){let r=Math.max(.05,(e.unsprungCgHeight||230)/1e3);t=e.brakeBalanceFront!=null?{mode:"balance",balanceFront:e.brakeBalanceFront,tyreRadiusM:r}:{mode:"tyre",balanceFront:e.frontMassFrac,tyreRadiusM:r},G1.set(e,t)}return t}var Kr=e=>Qn(dr(e));var oE=Math.PI/180,Ma=Object.freeze({tbr:1,preloadN:0}),gu=Object.freeze({tbr:1/0,preloadN:0}),Uh=e=>e.faces*e.muClutch*e.rFrictionMm/e.rRampMm;function Xh(e,t){if(!(e>0)||Number.isNaN(t))return 0;let r=Math.tan(Math.min(90,t)*oE);return r>0?Math.min(1,e/r):1}function H1(e){if(e>=1)return 1/0;let t=e>0?e:0;return(1+t)/(1-t)}function yu(e){return e===1/0?1:e>1?(e-1)/(e+1):0}function Sa(e,t){return e.tbr===1/0?1/0:(e.preloadN>0?e.preloadN:0)+yu(e.tbr)*Math.abs(t)}function fi(e,t,r){let n=o=>o!==void 0&&o>0&&r>0?o/r:0;switch(e.kind){case"open":return Ma;case"spool":return gu;case"independent":return t==="hubs"?Ma:gu;case"clutch":{let o=n(e.preloadNm);return t==="hubs"?{tbr:1,preloadN:o}:{tbr:H1(Xh(Uh(e),t==="drive"?e.rampDriveDeg:e.rampCoastDeg)),preloadN:o}}case"torsen":{let o=n(e.preloadNm);if(t==="hubs")return{tbr:1,preloadN:o};let a=t==="drive"?e.tbrDrive:e.tbrCoast;return{tbr:a>1?a:1,preloadN:o}}}}function di(e,t,r){let n=Math.max(0,Math.min(e,t)),o=Math.max(0,Math.max(e,t)),a=r.tbr>1?r.tbr:1,s=r.preloadN>0?r.preloadN:0;return a===1/0||s===1/0?n+o:n+Math.min(o,a*n+s*(1+a)/2)}var K1=4;function jh(e,t){let r=0;for(let a of e)r=Math.max(r,di(a.m1,a.m2,t));let n=t.tbr>1?t.tbr:1,o=(t.preloadN>0?t.preloadN:0)*(1+n)/2;if(n===1/0||o===1/0)return r;for(let a=0;a+1<e.length;a++){let s=e[a],i=e[a+1].m1-s.m1,c=e[a+1].m2-s.m2,l=f=>{f>0&&f<1&&(r=Math.max(r,di(s.m1+f*i,s.m2+f*c,t)))};i!==c&&l((s.m2-s.m1)/(i-c));let u=i+c-(1+n)*i,m=i+c-(1+n)*c;u!==0&&l(((1+n)*s.m1+o-s.m1-s.m2)/u),m!==0&&l(((1+n)*s.m2+o-s.m1-s.m2)/m)}return r}function hi(e,t,r,n,o){let a=Math.max(0,o),s=n.tbr>1?n.tbr:1,i=n.preloadN>0?n.preloadN:0;if(s===1/0||i===1/0)return a;let c=Math.max(0,r),l=Th(e,t,c),u=l?2*Math.min(l.c1,l.c2):0;if(!l||s===1&&i===0||!(a>u))return Math.min(u,a);let m=du(b=>Zn(e,b)+Zn(t,c-b),l.lo,l.hi),f=[{m1:l.c1,m2:l.c2}];for(let b=1;b<=K1&&m!==l.y1;b++){let g=l.y1+(m-l.y1)*b/K1;f.push({m1:e.cap(g),m2:t.cap(c-g)})}let p=jh(f,Ma),d=jh(f,gu);if(!(d>p))return u;let h=(jh(f,{tbr:s,preloadN:i})-p)/(d-p);return Math.min(a,u+(a-u)*Math.min(1,Math.max(0,h)))}function z1(e,t,r,n,o,a){return qh(e,o,hi(t,r,n,o,a))}function qh(e,t,r){let n=Math.max(e.xNoLock,r/2),o=t.tbr===1/0||!(e.xLock>n)?0:e.xLock;return e.regenWheel>0?{...e,xNoLock:n,xLock:o,mixedMax:Math.max(e.mixedMax,2*n)}:{...e,xNoLock:n,xLock:o,mixedMax:2*n,regenRoom:a=>2*Math.max(0,n-a)}}function Qh(e,t,r,n=30){let o=t,a=e(o),s=a-o;if(!(Math.abs(s)>r))return{x:o,fx:a,evals:1};let i=a,c=e(i),l=c-i,u=2;for(;Math.abs(l)>r&&u<n;){let m=s<0!=l<0,f=l-s,p=f!==0?i-l*(i-o)/f:NaN;m?p>Math.min(o,i)&&p<Math.max(o,i)||(p=.5*(o+i)):Number.isFinite(p)?Math.abs(p-i)>10*Math.abs(l)&&(p=i+Math.sign(p-i)*10*Math.abs(l)):p=c;let d=e(p),h=d-p;if(u++,m&&h<0==l<0?s*=.5:(o=i,s=l),i=p,c=d,l=h,s<0!=l<0&&Math.abs(i-o)<=r)break}return{x:i,fx:c,evals:u}}function Y1(e,t,r,n,o,a=60){let s=t,i=e(s),c=i-s,l=1;if(!(Math.abs(c)>n))return{x:s,fx:i,evals:l};let u=Math.sign(r-t),m=Math.abs(r-t),f=0;for(let p=o;l<a;p*=2){if(f=Math.min(f+p,m),f>m-n)return null;let d=t+u*f,h=e(d),b=h-d;if(l++,!(Math.abs(b)>n))return{x:d,fx:h,evals:l};if(c<0!=b<0)return j1(e,s,c,d,h,b,n,l,a);s=d,c=b}return null}function W1(e,t,r,n=60){let o=t,a=e(o),s=a-o;if(!(Math.abs(s)>r))return{x:o,fx:a,evals:1};let i=Math.sign(s),c=a;for(let l=2;;l++){let u=e(c),m=u-c;if(!(Math.abs(m)>r))return{x:c,fx:u,evals:l};if(s<0!=m<0)return j1(e,o,s,c,u,m,r,l,n);if(l>=n)return{x:c,fx:u,evals:l};let f=Math.abs(c-o),p=s!==m?m*(c-o)/(s-m):NaN,d=p*i>0?Math.min(Math.abs(p),10*Math.abs(m),2*f):2*f;o=c,s=m,c+=i*d}}function j1(e,t,r,n,o,a,s,i,c){let l=t,u=r,m=n,f=a,p=n,d=o,h=0;for(;i<c&&Math.abs(m-l)>s;){p=(l*f-m*u)/(f-u),d=e(p);let b=d-p;if(i++,!(Math.abs(b)>s))break;b<0==u<0?(l=p,u=b,h===-1&&(f*=.5),h=-1):(m=p,f=b,h===1&&(u*=.5),h=1)}return{x:p,fx:d,evals:i}}function xu(e,t){return Math.abs(e.fx-e.x)>t?e.x:e.fx}var aE=(e,t)=>{let r=e.brakes?.hydraulic?.[t];return!!r&&r.location==="inboard"&&r.discs===1};function zt(e,t,r){let n=e.driveline?.[t];if(n)return r>=0?n.drive:aE(e,t)?n.coast:n.hubs}var U1=e=>e.tbr>1||e.preloadN>0;var sE=9.81,X1=["FL","FR","RL","RR"],Zh=e=>e==="FL"||e==="FR",Ru=e=>Zh(e)?"front":"rear",q1={front:["FL","FR"],rear:["RL","RR"]},yi=()=>({peak:new Map,freeBrake:new Map}),gi=25;function bi(e,t){let r=Math.max(0,e)/gi,n=Math.floor(r),o=r-n,a=t(n);return o>0?a+o*(t(n+1)-a):a}var yn=1e-4,iE=.05;function Hr(e,t,r,n=yi(),o=!1){let a=r,s=e.massTotal,i=n.peak,c=(A,S)=>{let C=`${A}:${S}`,L=i.get(C);return L||(L=Dl(ye(t,A),Math.max(1,S*gi)),i.set(C,L)),L},l=(A,S)=>({aPeak:bi(S,C=>c(A,C).aPeak),fyPeak:bi(S,C=>c(A,C).fyPeak)}),u=n.freeBrake,m=(A,S)=>{let C=`${A}:${S}`,L=u.get(C);if(L===void 0){let D=Math.max(1,S*gi);L=Pt(ye(t,A),D,0,!0,c(A,S)),u.set(C,L)}return L},f=(A,S)=>S>0?bi(S,C=>m(A,C)):0,p=Kr(e),d=dr(e),h=A=>d.regen&&d.regenPerWheel?.[A]?Or(d.regen.v,d.regen[A],a)/2:0,b=h("front"),g=h("rear"),y=(A,S,C)=>{let L=Math.max(0,S[A]),D=l(Ru(A),L);return Pt(ye(t,Ru(A)),L,C[A]*D.fyPeak,!0,D)},R=(A,S,C,L,D=!0)=>{let I=te=>{let fe=Math.max(0,S[te]),W=ye(t,A),J=l(A,fe);return{Fz:fe,a:Math.abs(f(A,fe)),b:J.fyPeak,slide:fe>0?Math.abs(W.forces({Fz:fe,kappa:-1,alpha:0}).Fx):0,cap:re=>Math.abs(Pt(W,fe,re,!0,J))}},O=te=>Math.abs(C[te])*l(Ru(te),Math.max(0,S[te])).fyPeak,[N,z]=q1[A],E=I(N),_=I(z),B=O(N)+O(z),V=Ph(E,_,B,L,A==="front"?b:g),G=D?V:{...V,xLock:0},K=zt(e,A,-1),Y=K&&U1(K)?K:void 0;if(!Y)return{axle:A,eq:G,cap:G};let j=Number.isFinite(L)?L:E.cap(O(N))+_.cap(O(z)),Z=z1(G,E,_,B,Y,j);return{axle:A,eq:G,cap:Z,law:Y,strong:()=>E.cap(O(N))>=_.cap(O(z))?N:z}},k=(A,S,C,L)=>R(A,S,C,L).cap,v=(A,S,C)=>{let L=A.demand,D=p.shares?Ra(S,L.front):xa(S,(L.front-L.regenFront)/2,L.regenFront),I=p.shares?Ra(C,L.rear):xa(C,(L.rear-L.regenRear)/2,L.regenRear);return{front:Number.isFinite(D)?D:0,rear:Number.isFinite(I)?I:0}},x=A=>({muX:S=>S>0?Math.abs(f(A,S))/S:0,muY:S=>S>0?l(A,S).fyPeak/S:0}),M={front:x("front"),rear:x("rear")},F={lf:e.wheelbase/1e3*(1-e.frontMassFrac),lr:e.wheelbase/1e3*e.frontMassFrac},w={front:e.trackFront/2e3,rear:e.trackRear/2e3},T=(A,S,C,L,D)=>{let I=L.cap,O=D.cap,N=ci(p,I,O,a),z={arms:F,halfTrack:w,ayDir:Math.sign(A)};for(let E=0;E<2;E++){let _=v(N,I,O),B={};for(let G of X1){let K=Math.max(0,S[G]);B[G]={Fz:K,Fy:Math.abs(C[G])*l(Ru(G),K).fyPeak,Fx:-(Zh(G)?_.front:_.rear)/2}}let V=G=>{if(!G.law||!G.strong)return G.cap;let K={axle:G.axle,strong:G.strong(),full:2*G.cap.xNoLock,open:2*G.eq.xNoLock,sense:-1};return qh(G.eq,G.law,Jl(K,B,M,z))};I=V(L),O=V(D),N=ci(p,I,O,a)}return{limit:N,front:I,rear:O}};return{peakAt:l,axle:k,ceiling:(A,S,C)=>{let[L,D]=q1[A];return Math.abs(y(L,S,C)+y(D,S,C))},limitAt:(A,S,C,L=0)=>{let D={FL:0,FR:0,RL:0,RR:0},I=Ce(e,A,0,a,0,S),O,N=fe=>(O?.ax!==fe&&(O={ax:fe,loads:Ce(e,A,(fe+L)/sE,a,0,S)}),O.loads),z=El(fe=>ma(C,N(fe),I,l).short,-L,-1),E=C,_={front:0,rear:0},B,V,G=(fe,W=!0)=>{let J=z.at(fe);D=N(J),E=ma(C,D,I,l).util;let re=0,pe=0,de=0;for(let ie of X1){let oe=y(ie,D,E);re+=oe,Zh(ie)?pe+=oe:de+=oe}if(_={front:Math.abs(pe),rear:Math.abs(de)},p.mode!=="tyre"){let ie=R("front",D,E,Math.abs(pe),W),oe=R("rear",D,E,Math.abs(de),W);if(o&&(ie.law||oe.law)){let ue=T(A,D,E,ie,oe);B=ue.limit,V={front:ue.front,rear:ue.rear}}else B=ci(p,ie.cap,oe.cap,a),V={front:ie.cap,rear:oe.cap};re=-B.force}return re/s},K=Qh(G,0,yn),Y=xu(K,yn),j=Y;if(B?.lockFront||B?.lockRear){let fe=Qh(J=>G(J,!1),0,yn);j=xu(fe,yn);let W=Y1(G,fe.x,K.x,yn,iE);W||G(K.x),Y=xu(W??K,yn)}let Z=z.edge(),ne=Z!==void 0&&Y<Z;ne&&(Y=Math.min(0,Z),G(Y),j=Math.max(j,Y));let te={loads:D,ceiling:_,limit:B,axles:V};return{ax:Y,axUnlocked:j,...ne?{edge:Z}:{},...te,split:()=>te.limit&&te.axles?v(te.limit,te.axles.front,te.axles.rear):{...te.ceiling}}}}}var ku=9.81;function cE(e,t,r){let n=Ce(e,0,t,r),o=Math.max(0,n.FL)+Math.max(0,n.FR),a=Math.max(0,n.RL)+Math.max(0,n.RR);return o+a>0?o/(o+a):e.frontMassFrac}var J1=(e,t)=>t.mode==="hydraulic"&&!!dr(e).regen;function Aa(e,t,r=0,n,o=0){if(!e.brakes&&e.brakeBalanceFront==null)return e.frontMassFrac;let a=Kr(e);if(a.shares&&a.mode!=="tyre")return a.shares.front;let s=n&&J1(e,a)?ek(e,n):void 0,i=s?.shares??Q1.get(e);i||Q1.set(e,i=new Map);let c=Math.round(Math.abs(t)/.005),l=Math.round(Math.max(0,r)/.25),u=s?Math.round(o/.01):0,m=tk(c,l,u),f=i.get(m);if(f===void 0){let p=-c*.005,d=l*.25,h=e.massTotal*Math.abs(p)*ku;if(s){let b=nk(a,rk(e,s,c,l,u),h,d);f=b.front+b.rear>0?b.front/(b.front+b.rear):.5}else f=a.mode==="tyre"?cE(e,p,d):Fh(a,h,d);i.size>5e4&&i.clear(),i.set(m,f)}return f}var Q1=new WeakMap;function Mu(e,t,r,n,o=0){let a=Kr(e);if(!J1(e,a))return;let s=Math.round(Math.max(0,r)/(e.massTotal*ku)/.005),i=Math.round(Math.max(0,n)/.25);return nk(a,rk(e,ek(e,t),s,i,Math.round(o/.01)),Math.max(0,r),n)}var Z1=new WeakMap;function ek(e,t){let r=Z1.get(e);r||Z1.set(e,r=new WeakMap);let n=r.get(t);return n||r.set(t,n={ev:t,tyres:yi(),shares:new Map,rooms:new Map,speeds:new Map}),n}var tk=(e,t,r)=>(r*1001+e)*100003+t;function rk(e,t,r,n,o){let a=tk(r,n,o),s=t.rooms.get(a);if(!s){let i=n*.25,c=o*.01,l=t.speeds.get(n);l||(l={cap:Hr(e,t.ev,i,t.tyres),dragG:-Math.max(0,xs(e,i).drag)/(e.massTotal*ku)},t.speeds.set(n,l));let{cap:u}=l,m=Ce(e,c,-r*.005+l.dragG,i),f=Math.abs(c)*e.massTotal*ku,p=b=>{let[g,y]=b==="front"?["FL","FR"]:["RL","RR"],R=f*(b==="front"?e.frontMassFrac:1-e.frontMassFrac),k=u.peakAt(b,Math.max(0,m[g])).fyPeak+u.peakAt(b,Math.max(0,m[y])).fyPeak,v=R>0&&k>0?Math.min(1,R/k):0;return u.axle(b,m,{FL:v,FR:v,RL:v,RR:v},1/0)},d,h;s=(b,g)=>(b==="front"?d??=p("front"):h??=p("rear")).regenRoom(g),t.rooms.size>5e4&&t.rooms.clear(),t.rooms.set(a,s)}return s}function vu(e,t,r,n){let o=e.demand(r,n),a=o.front-o.regenFront,s=o.rear-o.regenRear,i=o.regenFront>0?Math.min(o.regenFront,t("front",a/2)):0,c=o.regenRear>0?Math.min(o.regenRear,t("rear",s/2)):0;return{front:i===o.regenFront?o.front:a+i,rear:c===o.regenRear?o.rear:s+c,regenFront:i,regenRear:c,demand:o}}function nk(e,t,r,n){if(!(r>0))return vu(e,t,1,n);let o=c=>c.front+c.rear,a=e.controlFor(r,n),s=vu(e,t,a,n);if(o(s)>=r||!(a<e.uMax))return s;let i=a;for(;o(s)<r&&i<e.uMax&&i<1e7;)a=i,i=Math.min(e.uMax,2*i),s=vu(e,t,i,n);if(o(s)<r)return s;for(let c=0;c<60&&i-a>1e-10*i;c++){let l=.5*(a+i),u=vu(e,t,l,n);o(u)<r?a=l:(i=l,s=u)}return s}var Fa={rel:.003,abs:2,kappa:1e-5,iters:12},Jh={rel:1e-6,abs:.001,kappa:1e-12,iters:40};function Jn(e,t,r,n=Fa){let o=t>=0?1:-1,a=Math.abs(t),s=Math.max(n.abs,n.rel*a),i=e(0);if(Math.abs(i.Fx)-a>=0)return{kappa:0,forces:i};let c=0,l=i,u=Math.abs(i.Fx)-a,m=Math.min(.3,Math.max(.004,Math.abs(r)||.02)),f=e(o*m),p=Math.abs(f.Fx)-a,d=null;for(;p<0&&m<.3;){let g=Math.min(.3,m*1.9),y=e(o*g),R=Math.abs(y.Fx);if(R<Math.abs(f.Fx)){d={kappa:g,forces:y};break}c=m,l=f,u=p,m=g,f=y,p=R-a}if(p<0){let g=mE(e,o,c,l,m,f,d),y=Math.abs(g.forces.Fx);if(y<a)return{kappa:o*g.kappa,forces:g.forces};m=g.kappa,f=g.forces,p=y-a}let h=f,b=o*m;for(let g=0;g<n.iters&&m-c>n.kappa;g++){let y=p-u,R=Math.abs(y)>1e-12?(c*p-m*u)/y:.5*(c+m);R>c&&R<m||(R=.5*(c+m));let k=e(o*R),v=Math.abs(k.Fx)-a;if(h=k,b=o*R,Math.abs(v)<s)break;v<0?(c=R,u=v,p*=.5):(m=R,p=v,u*=.5)}return{kappa:b,forces:h}}var ok=1e-6,lE=40,uE=(3-Math.sqrt(5))/2;function mE(e,t,r,n,o,a,s){let i=a,c,l,u,m=-Math.abs(a.Fx),f,p,d=-Math.abs(n.Fx);if(s){c=s.kappa;let g=-Math.abs(s.forces.Fx);[l,f,u,p]=g<=d?[c,g,r,d]:[r,d,c,g]}else{c=.3;let g=.3*(1-ok),y=e(t*g),R=-Math.abs(y.Fx);if(R>=m)return{kappa:o,forces:a};[l,f,u,p]=[o,m,r,d],o=g,m=R,i=y}d<m&&([l,f]=[o,m],o=r,m=d,i=n);let h=c-r,b=0;for(let g=0;g<lE;g++){let y=ok*Math.abs(o)+1e-10,R=.5*(r+c);if(Math.abs(o-R)<=2*y-.5*(c-r))break;let k=!0;if(Math.abs(h)>y){let F=(o-l)*(m-p),w=(o-u)*(m-f),T=(o-u)*w-(o-l)*F;w=2*(w-F),w>0&&(T=-T),w=Math.abs(w);let P=h;if(h=b,Math.abs(T)<Math.abs(.5*w*P)&&T>w*(r-o)&&T<w*(c-o)){b=T/w;let A=o+b;(A-r<2*y||c-A<2*y)&&(b=R>=o?y:-y),k=!1}}k&&(h=o>=R?r-o:c-o,b=uE*h);let v=Math.abs(b)>=y?o+b:o+(b>=0?y:-y),x=e(t*v),M=-Math.abs(x.Fx);M<=m?(v>=o?r=o:c=o,u=l,p=f,l=o,f=m,o=v,m=M,i=x):(v<o?r=v:c=v,M<=f||l===o?(u=l,p=f,l=v,f=M):(M<=p||u===o||u===l)&&(u=v,p=M))}return{kappa:o,forces:i}}var Su=e=>Math.max(2,.003*Math.abs(e)),pE=(e,t)=>Math.max(t.abs,t.rel*Math.abs(e)),eb=.5,dE=.03;function fE(e,t,r,n,o){let a=.5*(e.vx+t.vx),s=v=>{let x=(1+v)*a/e.vx-1,M=(1+v)*a/t.vx-1,F=e.at(x),w=t.at(M);return{kappaM:v,kl:x,kr:M,fl:F,fr:w,g:F.Fx+w.Fx-r}},i=pE(r,o),c=Math.max(-eb,Math.min(eb,n)),l=s(c);if(Math.abs(c)>dE){let v=s(.8*c);(l.g-v.g)/(c-v.kappaM)>0||(l=s(0))}if(Math.abs(l.g)<i)return l;let u=l.g<0?1:-1,m=l,f=l,p=.004,d=l;for(let v=0;v<12;v++){let x=m.kappaM+u*p;if(Math.abs(x)>eb)break;let M=s(x);if(Math.abs(M.g)<i)return M;if(Math.abs(M.g)<Math.abs(d.g)&&(d=M),Math.sign(M.g)!==Math.sign(m.g)){f=M;break}if(u*(M.g-m.g)<=0)return d;m=M,p*=1.9}if(f===l)return d;let h=m,b=f,g=h.g,y=b.g,R=Math.abs(g)<Math.abs(y)?h:b,k=Math.min(1e-7,o.kappa);for(let v=0;v<30&&Math.abs(b.kappaM-h.kappaM)>k;v++){let x=y-g,M=Math.abs(x)>1e-12?(h.kappaM*y-b.kappaM*g)/x:.5*(h.kappaM+b.kappaM),F=Math.min(h.kappaM,b.kappaM),w=Math.max(h.kappaM,b.kappaM);M>F&&M<w||(M=.5*(F+w));let T=s(M);if(R=T,Math.abs(T.g)<i)break;Math.sign(T.g)===Math.sign(g)?(h=T,g=T.g,y*=.5):(b=T,y=T.g,g*=.5)}return R}function ak(e,t,r,n){let o=(e*(1+t*n)+t*r)/(1-t*n);return e+o>=0?o:(e*(1-t*n)+t*r)/(1+t*n)}function tb(e,t,r,n,o,a=Fa){let s=fE(e,t,r,o,a),i=s.fr.Fx-s.fl.Fx,c=Sa(n,r);if(Math.abs(i)<=c){let R=r-(s.fl.Fx+s.fr.Fx),k=Math.max(0,Math.abs(R)-Su(r))/2;return{left:{kappa:s.kl,forces:s.fl,want:s.fl.Fx+R/2,short:k},right:{kappa:s.kr,forces:s.fr,want:s.fr.Fx+R/2,short:k},locked:!0,spoolKappa:s.kappaM}}let l=Math.sign(i),u=r/2-l*c/2,m=r/2+l*c/2,f=Jn(e.at,u,e.seed||s.kl,a),p=Jn(t.at,m,t.seed||s.kr,a),d=Math.abs(u-f.forces.Fx)>Su(u),h=Math.abs(m-p.forces.Fx)>Su(m),b=Math.max(0,n.preloadN),g=yu(n.tbr);d&&!h?p=Jn(t.at,ak(f.forces.Fx,l,b,g),p.kappa,a):h&&!d&&(f=Jn(e.at,ak(p.forces.Fx,-l,b,g),f.kappa,a));let y=(R,k)=>({kappa:R.kappa,forces:R.forces,want:k,short:Math.max(0,Math.abs(k-R.forces.Fx)-Su(k))});return{left:y(f,u),right:y(p,m),locked:!1,spoolKappa:s.kappaM}}var hE={front:["FL","FR"],rear:["RL","RR"]},bE=Object.freeze({Fx:0,Fy:0,Mz:0});function Au(e,t,r,n){let o=r;for(let a of["front","rear"]){let[s,i]=hE[a],c=r[s]+r[i],l=zt(e,a,c);if(!l||!(Sa(l,c)>0))continue;let u=ye(t,a),m=n.alpha[a],f=(a==="front"?e.trackFront:e.trackRear)/2e3,p=(h,b)=>{let g=Math.max(0,n.Fz[h]);return{at:g>0?y=>u.forces({Fz:g,kappa:y,alpha:m,gamma:0}):()=>bE,vx:Math.max(.05,1-b*n.curvature),seed:0}},d=tb(p(s,f),p(i,-f),c,l,n.seed?.[a]??0);n.seed&&(n.seed[a]=d.spoolKappa),o===r&&(o={...r}),o[s]=d.left.want,o[i]=d.right.want}return o}var Me=9.81,se=Math.PI/180,gE=8,yE=1e-6,Rn=["FL","FR","RL","RR"],Zt=e=>e==="FL"||e==="FR",xn=e=>Zt(e)?"front":"rear";function Ri(e,t){let r=ye(e,"front"),n=ye(e,"rear");return r===n?to(r,t):{front:to(r,t),rear:to(n,t)}}function to(e,t){return jf(e,Math.min(t,Qt(e)))}var wu=e=>e==="FL"||e==="RL";function Ca(e,t,r=0,n,o=0){let a=t?.axG??0,s=Number.isFinite(t?.tvRearDiffN)?t?.tvRearDiffN:0;if(!(!!a&&Number.isFinite(a))&&!s)return null;let c=e.massTotal*a*Me,l=a>=0?Math.min(1,Math.max(0,t?.driveFrontFrac??0)):Math.min(.99,Math.max(.01,Aa(e,a,r,n,o))),u=c*l/2,m=c*(1-l)/2;return{axG:a,fx:{FL:u,FR:u,RL:m-s/2,RR:m+s/2}}}function cb(e,t,r,n){return Math.abs(ro(e,t,r,n!==void 0?{steerMaxDeg:n}:{}).peak.steerDeg)}function lb(e,t,r,n){let o=e.tv;if(!o?.enabled)return 0;let a=Fk(o)(t,Math.abs(r),n);return r<0?-a:a}function ub(e,t,r=0,n,o=0,a=0,s){let i=Ca(e,{axG:t,driveFrontFrac:a},r,n,o),c=i?i.fx:{FL:0,FR:0,RL:0,RR:0};return i&&s&&n?Au(e,n,c,s):c}var vi=e=>wu(e)?-1:1,mb=(e,t,r,n,o)=>t*e.Fy(t*r,n,t*o);function sb(e){let t=e.wheelbase/1e3,r=t*(1-e.frontMassFrac),n=t*e.frontMassFrac;return{wb:t,lf:r,lr:n,m:e.massTotal}}function xE(e,t,r){let n=Math.abs(t),o=e.steerFront;if(o&&o.meanDeg.length>1){let u=t>=0,m=r&&o.travelSurface?ia(o,n/se,u?r.FL:r.FR,u?r.FR:r.FL):ca(o,n/se);return{innerMag:m.innerDeg*se,outerMag:m.outerDeg*se,innerCamber:m.innerCamber,outerCamber:m.outerCamber,atLock:m.atLock}}let a=e.trackFront/1e3,s=e.wheelbase/1e3,i=(e.ackermannPct??0)/100,c=n,l=n;if(n>1e-4){let u=s/Math.tan(n),m=Math.atan(s/Math.max(.05,u-a/2)),f=Math.atan(s/(u+a/2));c=n+i*(m-n),l=n+i*(f-n)}return{innerMag:c,outerMag:l,innerCamber:0,outerCamber:0,atLock:!1}}function no(e,t,r){let n=(e.toeFrontDeg??0)*se,o=(e.toeRearDeg??0)*se,a=xE(e,t,r),s=t>=0?1:-1,i=t>=0,c=s*(i?a.innerMag:a.outerMag),l=s*(i?a.outerMag:a.innerMag);return{steer:{FL:c-n,FR:l+n,RL:-o,RR:o},camber:{FL:i?a.innerCamber:a.outerCamber,FR:i?a.outerCamber:a.innerCamber,RL:0,RR:0},atLock:a.atLock}}function pb(e,t,r){if(r.Fz<=0)return 0;let n=ft(ye(e,xn(t))),o=vi(t),a=Math.abs(r.kappa)<1e-12?n.Mz(o*r.slipRad,r.Fz,o*r.camberRad):n.forces({Fz:r.Fz,kappa:r.kappa,alpha:o*r.slipRad,gamma:o*r.camberRad}).Mz;return o*a}function sk(e,t,r,n){if(!Un(e))return null;let o=ft(ye(t,"front")),a={};for(let s of["FL","FR"]){let i=n[s];a[s]={Fz:i.Fz,Fx:i.Fx,Fy:i.Fy,Mz:pb(o,s,i)}}return qs(e,r/se,a,dn(o.model),{FL:n.FL.travelMm,FR:n.FR.travelMm})}var ik=()=>({totalNm:[],aligningNm:[],lateralNm:[],longitudinalNm:[],jackingNm:[]});function ck(e,t){e.totalNm.push(t.totalNm),e.aligningNm.push(t.aligningNm),e.lateralNm.push(t.lateralNm),e.longitudinalNm.push(t.longitudinalNm),e.jackingNm.push(t.jackingNm)}var RE=Object.freeze({Fx:0,Fy:0,Mz:0});function lk(e,t,r){let n=t==="front"?(r?.FL??0)+(r?.FR??0):(r?.RL??0)+(r?.RR??0),o=zt(e,t,n);return o&&Sa(o,n)>0?{F:n,law:o}:null}function Et(e,t,r,n,o,a,s,i,c){let l=s?.fx,u=s?.axG??0,{wb:m,lf:f,lr:p,m:d}=sb(e),h=lk(e,"front",l),b=lk(e,"rear",l),g={front:0,rear:0},y=i!==void 0&&i>0&&Number.isFinite(i)?i:null,R=W=>y===null?r:Math.sqrt(Math.max(0,W)*y),k=ft(ye(t,"front")),v=ft(ye(t,"rear")),x=e.trackFront/2e3,M=e.trackRear/2e3,F=!!(e.kinFront&&e.kinRear),w=F&&y===null?hn(e,e.kinFront,e.kinRear,r):null,T=NaN,P=null,A=W=>{if(!F)return null;if(y===null)return w;let J=R(W);return J!==T&&(T=J,P=hn(e,e.kinFront,e.kinRear,J)),P},S={},C={FL:0,FR:0,RL:0,RR:0},L=e.kinFront?.compliance,D=e.kinRear?.compliance,I=!!(L||D),O=!!(L?.toePerMz||D?.toePerMz),N=W=>Zt(W)?L:D,z={FL:{fy:0,fx:0,mz:0},FR:{fy:0,fx:0,mz:0},RL:{fy:0,fx:0,mz:0},RR:{fy:0,fx:0,mz:0}},E=!1,_=W=>{let J=W/r,re=y===null?n+f*J/r:n+f/y,pe=y===null?n-p*J/r:n-p/y,de=A(W),ie=R(W),oe=de?de(W/Me,u,n/se,o/se):null,ue=oe?{FL:oe.FL.travel,FR:oe.FR.travel}:void 0,$e=Pl(e,W/Me,u,ie,n/se,o/se,ue,oe?.steeringJacking),Ae=$e.loads;E=$e.overturned;let le=no(e,o,ue),Re=le.steer,Te=0,ze=be=>{let Fe=Math.max(0,Ae[be]),xe=vi(be),me=Zt(be)?k:v,Le=N(be),Se=0,Ye=0;if(Le){let On=z[be];Se=Le.toePerFy*On.fy+Le.toePerFx*On.fx+Le.toePerMz*On.mz,Ye=Le.camberPerFy*On.fy+Le.camberPerFx*On.fx}let Xe=Re[be]+(oe?xe*oe[be].bumpToe*se:0)+xe*Se*se,Xt=Xe-(Zt(be)?re:pe),Nn=(oe?oe[be].camberRoad:0)*se+xe*(le.camber[be]+Ye)*se;return{Fz:Fe,mir:xe,t:me,gains:Le,complianceToe:Se,steerK:Xe,slip:Xt,camberRad:Nn}},Ue=(be,Fe)=>{let xe=y===null?J/r:1/y,me=Zt(be)?f:-p,Le=(wu(be)?1:-1)*(Zt(be)?x:M),Se=(Math.cos(n)-Le*xe)*Math.cos(Fe.steerK)+(Math.sin(n)+me*xe)*Math.sin(Fe.steerK);return{at:Fe.Fz>0?Ye=>Fe.t.forces({Fz:Fe.Fz,kappa:Ye,alpha:Fe.mir*Fe.slip,gamma:Fe.mir*Fe.camberRad}):()=>RE,vx:Math.max(.05,Se),seed:C[be]}};for(let be=0;be<(I?gE:1);be++){Te=0;let Fe=0,xe={};for(let me of Rn){let Le=Zt(me)?h:b;if(Le&&!xe[me]){let[zo,Vt]=Zt(me)?["FL","FR"]:["RL","RR"],tl=ze(zo),px=ze(Vt),dx=xn(me),cd=tb(Ue(zo,tl),Ue(Vt,px),Le.F,Le.law,g[dx],Jh);g[dx]=cd.spoolKappa,xe[zo]={w:tl,share:cd.left},xe[Vt]={w:px,share:cd.right}}let Se=xe[me]?.w??ze(me),{Fz:Ye,mir:Xe,t:Xt,gains:Nn,complianceToe:On,steerK:od,slip:ad,camberRad:sd}=Se,hs=l?.[me]??0,Go,Ko=0,id=0,el=0,Ho=xe[me]?.share;if(Ho)C[me]=Ho.kappa,id=Ho.kappa,Ko=Ho.forces.Fx,el=Ho.short,Go=Xe*Ho.forces.Fy;else if(hs===0||Ye<=0)Go=mb(Xt,Xe,ad,Ye,sd),el=Ye<=0?Math.abs(hs):0;else{let Vt=Jn(tl=>Xt.forces({Fz:Ye,kappa:tl,alpha:Xe*ad,gamma:Xe*sd}),hs,C[me],Jh);C[me]=Vt.kappa,id=Vt.kappa,Ko=Vt.forces.Fx,el=Math.max(0,Math.abs(hs-Ko)-Math.max(Fa.abs,Fa.rel*Math.abs(hs))),Go=Xe*Vt.forces.Fy}if(S[me]={Fz:Ye,travelMm:oe?.[me].travel??0,steerRad:od,slipRad:ad,camberRad:sd,Fy:Go,Fx:Ko,kappa:id,fxShort:el,lifted:$e.lifted[me]},Nn){let zo=O&&Nn.toePerMz?pb(Xt,me,S[me]):0;z[me]={fy:-Xe*Go,fx:Ko,mz:-Xe*zo*1e3};let Vt=z[me];Fe=Math.max(Fe,Math.abs(Nn.toePerFy*Vt.fy+Nn.toePerFx*Vt.fx+Nn.toePerMz*Vt.mz-On))}Te+=Go*Math.cos(od)+Ko*Math.sin(od)}if(Fe<yE)break}return Te/d},B=W=>{let J=Ce(e,0,u,W,0,o/se);return J.FL+J.FR+J.RL+J.RR},V=Math.max(20,3.5*B(r)/d);if(y!==null){V=4*Me;for(let W=0;W<8;W++){let J=Math.min(40*Me,3.5*B(R(V))/d);if(J<=V)break;V=J}V=Math.max(20,V)}let G=W=>_(W)-W,K=Math.max(.001,V*1e-4),Y=(W,J,re,pe)=>{let de=W,ie=re,oe=J,ue=pe,$e=de;for(let Ae=0;Ae<40;Ae++){let le=ue-oe,Re=Math.abs(le)>1e-12?(de*ue-ie*oe)/le:.5*(de+ie),Te=Math.min(de,ie),ze=Math.max(de,ie);Re>Te&&Re<ze||(Re=.5*(de+ie));let Ue=G(Re);if($e=Re,Math.abs(Ue)<1e-4||ze-Te<1e-6)break;Ue<0==oe<0?(de=Re,oe=Ue,ue*=.5):(ie=Re,ue=Ue,oe*=.5)}return $e},j=(W,J,re,pe=!1)=>{let de=(Ae,le)=>re>0?Ae>0&&le<0:le>0&&Ae<0,ie=W,oe=J,ue=W+re*Math.min(Math.abs(J),V);if(!pe&&Math.abs(ue-W)>K){let Ae=G(ue);if(de(oe,Ae))return{root:Y(ie,oe,ue,Ae),last:ie};ie=ue,oe=Ae}let $e=pe?V/24:Math.max(V/24,Math.abs(ue-W)/4);for(let Ae=1;Ae<=24;Ae++){let le=ie+re*$e;if(Math.abs(le)>V)break;let Re=G(le);if(de(oe,Re))return{root:Y(ie,oe,le,Re),last:ie};if(pe&&Re*re<0&&(Re-oe)*re<0)break;ie=le,oe=Re}return{root:null,last:ie}},Z=c??null;if(c===void 0&&a!==void 0&&Number.isFinite(a)&&Math.abs(a)<=V){let W=G(a);if(Math.abs(W)<=1e-4)G(a+K)<0&&G(a-K)>0&&(Z=a);else{let J=j(a,W,Math.sign(W)).root;Z=J!==null&&(J===0||Math.sign(J)===Math.sign(a))?J:null}}let ne=Z===null;if(Z===null){let W=G(0),J=G(K),re=Math.abs(W)<=1e-4,pe=re?y!==null?1:o!==0?Math.sign(o):J>0?1:-1:Math.sign(W),de=re?pe*K:0,ie=re?pe>0?J:G(-K):W,oe=j(de,ie,pe);Z=oe.root??(re?0:oe.last)}let te=_(Z);if(ne&&o!==0&&y===null){let W=Math.sign(o);if(Z*W<=0||(S.RL.Fy+S.RR.Fy)*W<0){let J={...S},re=E,pe=W*Math.max(Z*W+K,n*W*r*r/p),de=null;if(pe*W<V){let ie=G(pe);if(ie*W>0)de=j(pe,ie,W).root;else{let oe=pe+W*V/24,ue=G(oe);(ue-ie)*W>0&&(de=j(oe,ue,W,ue*W<=0).root)}}de!==null&&de*W>0?(Z=de,te=_(Z)):(Object.assign(S,J),E=re)}}let fe=f*(S.FL.Fy*Math.cos(S.FL.steerRad)+S.FR.Fy*Math.cos(S.FR.steerRad))-p*(S.RL.Fy+S.RR.Fy);if(s||h||b){let W=J=>(wu(J)?1:-1)*(Zt(J)?x:M);for(let J of Rn){let re=S[J],pe=Zt(J)?f:-p;fe+=pe*re.Fx*Math.sin(re.steerRad)-W(J)*re.Fx*Math.cos(re.steerRad)}}return y!==null&&Z<-1e-6?{ay:NaN,cn:NaN,wheels:S,overturned:E,res:NaN}:{ay:Z/Me,cn:fe/(d*Me*m),wheels:S,overturned:E,res:te-Z}}function vE(e,t,r,n,o,a,s,i=0){let c=20*se,l=.001,u=(h,b)=>{let g=Et(e,t,r,h,n,b,s);return{cn:g.cn-i,ay:g.ay*Me}},m=h=>n===0||i!==0||Math.abs(h)<.05||Math.sign(h)===Math.sign(n),f=(h,b,g,y)=>{let R=u(h,y);if(Math.abs(R.cn)<1e-5)return{beta:h,trimmed:!0};let k=y===void 0?void 0:R.ay,v={pos:{b:h,cn:R.cn,ay:k},neg:{b:h,cn:R.cn,ay:k}},x=null,M=h,F=Math.abs(R.cn);for(let w=0;w<b.length&&!x;w++)for(let T of[v.pos,v.neg]){let P=T===v.pos?1:-1,A=h+P*b[w];if(Math.abs(A)>c)continue;let S=u(A,T.ay);if(Math.abs(S.cn)<F&&m(S.ay)&&(F=Math.abs(S.cn),M=A),S.cn===0&&m(S.ay))return{beta:A,trimmed:!0};if(S.cn<0!=T.cn<0){let C={lo:T.b,hi:A,ayLo:T.ay},L=uk(u,C),D=u(L,T.ay);if(Math.abs(D.cn)<l&&m(D.ay))return x=C,{beta:L,trimmed:!0}}T.b=A,T.cn=S.cn,y!==void 0&&(T.ay=S.ay)}return x?{beta:uk(u,x),trimmed:!0}:g?{beta:M,trimmed:!1}:null},p=[.25,.75,2,5].map(h=>h*se);if(o!==void 0&&Number.isFinite(o)&&Math.abs(o)<=c){let h=f(o,p,!1,a);if(h)return h;if(!s&&i===0&&a!==void 0&&Number.isFinite(a)){let b=kE(e,t,r,n,o,a,c);if(b&&m(b.ay))return{beta:b.beta,trimmed:!0,ay:b.ay}}}let d=[1,3,7,15,20].map(h=>h*se).filter(h=>h<=c);return f(0,d,!0)??{beta:0,trimmed:!1}}function uk(e,t){let{lo:r,hi:n}=t,o=t.ayLo,a=e(r,o).cn,s=e(n,o).cn,i=r;for(let c=0;c<40;c++){let l=s-a,u=Math.abs(l)>1e-12?(r*s-n*a)/l:.5*(r+n);u>Math.min(r,n)&&u<Math.max(r,n)||(u=.5*(r+n));let m=e(u,o),f=m.cn;if(o!==void 0&&(o=m.ay),i=u,Math.abs(f)<1e-5||Math.abs(n-r)<1e-5)break;f<0==a<0?(r=u,a=f,s*=.5):(n=u,s=f,a*=.5)}return i}function kE(e,t,r,n,o,a,s){let i=(f,p)=>{let d=Et(e,t,r,f,n,void 0,null,void 0,p);return{r:d.res,c:d.cn}},c=o,l=a,u=i(c,l),m=0;for(let f=0;f<ME;f++){let p=i(c+rb,l),d=i(c,l+nb),h=(p.r-u.r)/rb,b=(d.r-u.r)/nb,g=(p.c-u.c)/rb,y=(d.c-u.c)/nb,R=h*y-b*g;if(!Number.isFinite(R)||R===0||Math.abs(R)<wE*(Math.abs(h*y)+Math.abs(b*g)))return null;if(f===0)m=Math.sign(R);else if(Math.sign(R)!==m)return null;if(Math.abs(u.r)<=1e-4&&Math.abs(u.c)<=1e-5)return{beta:c,ay:l};let k=(u.c*b-u.r*y)/R,v=(u.r*g-u.c*h)/R,x=Math.min(1,SE/Math.max(Math.abs(k),1e-300),AE/Math.max(Math.abs(v),1e-300));if(c+=x*k,l+=x*v,Math.abs(c-o)>FE||Math.abs(c)>s||l*a<0)return null;u=i(c,l)}return null}var ME=8,rb=1e-5,nb=.001,SE=1*se,AE=2,FE=5*se,wE=.5;function gk(e,t,r,n,o,a,s,i){let c=Et(e,t,r,n,o,a,s,void 0,i),l=c.ay*Me/r,u={},m=0;for(let d of Rn){let h=c.wheels[d],b=ye(t,xn(d)),g=Qt(b),y=b.muY(Math.min(h.Fz,g)),R=b.muX(Math.min(h.Fz,g));m+=h.fxShort,u[d]={Fz:h.Fz,steerDeg:h.steerRad/se,slipDeg:h.slipRad/se,camberDeg:h.camberRad/se,Fy:h.Fy,Fx:h.Fx,Mz:pb(b,d,h),gripUtil:y*h.Fz>0?Math.hypot(h.Fy/(y*h.Fz),R*h.Fz>0?h.Fx/(R*h.Fz):0):0,...h.Fz>g?{pastTurnover:!0}:{},lifted:h.lifted}}let f=qs(e,o/se,u,dn(ye(t,"front").model),{FL:c.wheels.FL.travelMm,FR:c.wheels.FR.travelMm}),p=no(e,o,e.kinFront&&e.kinRear?{FL:c.wheels.FL.travelMm,FR:c.wheels.FR.travelMm}:void 0);return{wheels:u,ay:c.ay,ax:s?.axG??0,beta:n/se,yawRate:l*180/Math.PI,steerDeg:o/se,...p.atLock?{lockDeg:(p.steer.FL+p.steer.FR)/2/se}:{},converged:!0,trimmed:!c.overturned,overturned:c.overturned,driving:!1,fxShortfall:m,...f?{steering:f}:{}}}function Yr(e,t,r,n,o,a,s=0){let i=Math.max(8,r),c=eo(e,t,i,n,o,a,s);return n!==0&&o?.driving===void 0&&(c.driving=KE(e,t,i,c,a,s)),c}function eo(e,t,r,n,o,a,s){let i=n*se,c=Ca(e,a,r,t),l=o&&Number.isFinite(o.ay)?o.ay*Me:void 0,u=o&&Number.isFinite(o.beta)?o.beta*se:void 0,{beta:m,trimmed:f,ay:p}=vE(e,t,r,i,u,l,c,s),d=gk(e,t,r,m,i,l,c,p),h={...d,trimmed:f&&!d.overturned};return h.driving=n===0?h.trimmed:o?.driving!==void 0&&o.driving&&h.trimmed&&Math.abs(h.beta-o.beta)<=CE,h}var CE=3;function ro(e,t,r,n={}){let o=Math.max(8,r),a=n.direction??1,s=n.yawDemandCn??0,i=n.steerMaxDeg??TE,c=typeof n.op=="function"?n.op:()=>n.op,l=typeof n.op=="function"?null:`${o}|${a}|${s}|${i}|${n.op?`${n.op.axG}|${n.op.driveFrontFrac??""}|${n.op.tvRearDiffN??""}`:""}`;if(l!==null){let x=ob.get(e)?.get(t)?.get(l);if(x)return x}let u=(x,M)=>M.trimmed&&Math.abs(M.beta-x.beta)<=Cu&&Math.abs(M.ay-x.ay)*Me<=Tu,m=!1,f=(x,M)=>{let F=eo(e,t,o,a*x,M,c(a*x),s);return u(M,F)?(F.driving=!0,F):(m=F.overturned,null)},p=[eo(e,t,o,0,void 0,c(0),s)],d=null,h=!1,b,g=x=>{let M=p.length-1;for(;M>1&&x.sb*(p[M].beta-p[M-1].beta)>=0;)M--;let F=a*(x.state.ay-p[M].ay)>0,w=T=>x.sb*(T.beta-x.state.beta)>0||a*T.steerDeg>=a*x.state.steerDeg||F&&a*T.ay>=a*x.state.ay;for(;p.length>Math.max(2,M)&&w(p[p.length-1]);)p.pop();b={state:x.state,stall:p[p.length-1]},p.push(x.state),d=Math.abs(x.state.steerDeg)},y=(x,M=!1)=>M||BE(p[p.length-1],x)?$E(e,t,o,a,p,x,c,s):null,R=p[0].trimmed?p[0]:null;if(!R){let x=0;for(let M=mk;M<=i&&!R;M+=mk){let F=eo(e,t,o,a*M,void 0,c(a*M),s);if(F.trimmed){let w=M;R=F;for(let T=0;T<6;T++){let P=.5*(x+w),A=eo(e,t,o,a*P,void 0,c(a*P),s);A.trimmed?(w=P,R=A):x=P}}else x=M}R&&(R.driving=!0,p.push(R))}if(R){let x=Math.abs(R.steerDeg),M=Math.min(ab,100/(o*o)),F=R;for(;x<i;){let w=Math.min(i,x+M),T=f(w,F);if(T){let L=y(T);if(L){g(L);break}if(p.push(T),w>=i||Ak(e,a*w))break;Math.abs(T.beta-F.beta)<.5*Cu&&Math.abs(T.ay-F.ay)*Me<.5*Tu&&(M=Math.min(ab,1.5*M)),x=w,F=T;continue}if(M>PE){M*=.5;continue}let P=m,A=!1,S=null;for(let L of LE){let D=Math.min(i,x+L);if(D<=x)continue;let I=f(D,F);if(I){if(S=y(I,!0),S)break;p.push(I),x=D,F=I,M=Math.min(ab,100/(o*o)),A=!0;break}}if(A)continue;if(S){g(S);break}d=x,h=P;let C=P?null:VE(e,t,o,a,p,c,s);C&&g(C);break}}else d=0;let k=p[0];for(let x of p)a*x.ay>a*k.ay&&(k=x);let v={states:p,foldDeg:d,rollover:h,peak:k,...b?{fold:b}:{}};if(l!==null){let x=ob.get(e);x||(x=new WeakMap,ob.set(e,x));let M=x.get(t);M||(M=new Map,x.set(t,M)),M.size>256&&M.clear(),M.set(l,v)}return v}var ob=new WeakMap,TE=90,Cu=1.5,Tu=2.5,ab=5,PE=.002,LE=[.5,1],mk=2.5,yk=.01,zr=.001,DE=.05,EE=.25,IE=5,_E=2,pk=1e-8,NE=1e-7,OE=1e-6;function xk(e,t,r,n,o,a,s){let i=n*se,c=o.ay*Me,l=b=>{let g=Et(e,t,r,i,b*se,c,Ca(e,a(b),r,t));return{g:g.cn-s,ay:g.ay}},u=o.steerDeg,m=l(u),f=u+(u<0?-.001:.001),p=l(f),d=()=>p.g===0||Math.abs(f-u)<pk;for(let b=0;b<40&&Math.sign(m.g)===Math.sign(p.g)&&!d();b++){let g=(p.g-m.g)/(f-u),y=g!==0?f-p.g/g:f+2*(f-u);if(!Number.isFinite(y))return null;let R=2*Math.abs(f-u)+.001;if(y=f+Math.max(-R,Math.min(R,y-f)),u=f,m=p,f=y,p=l(f),Math.abs(f-o.steerDeg)>_E)return null}let h={x:f,ay:p.ay};if(Math.sign(m.g)!==Math.sign(p.g)){let b=u,g=m.g,y=f,R=p.g;for(let k=0;k<60&&R!==0&&Math.abs(y-b)>pk;k++){let v=(b*R-y*g)/(R-g),x=l(v);if(h={x:v,ay:x.ay},x.g===0)break;Math.sign(x.g)===Math.sign(g)?(b=v,g=x.g,R*=.5):(y=v,R=x.g,g*=.5)}}else if(!d())return null;return Math.abs(h.ay-o.ay)*Me>Tu?null:{steerDeg:h.x,ay:h.ay}}function xi(e,t,r,n,o){let a=gk(e,t,r,n.beta*se,n.steerDeg*se,n.ay*Me,Ca(e,o(n.steerDeg),r,t));return{...a,trimmed:!a.overturned,driving:!a.overturned}}function VE(e,t,r,n,o,a,s){let i=o.length;if(i<3)return null;let c=o[i-1],l=i-2;for(;l>1&&o[l].beta===c.beta;)l--;let u=o[l],m=Math.sign(c.beta-u.beta);if(m===0||!u.driving)return null;let f=Rk(e,t,r,a,s),p=f(u.beta,u),d=f(c.beta,c);if(!p||!d)return null;let h=n*d.steerDeg>=n*p.steerDeg,b=h?p:d,g=h?d:p,y=h?m:-m,R=null;for(let x=yk;Math.abs(g.beta-c.beta)<=Cu;x*=1.5){let M=f(g.beta+y*x);if(!M)return null;if(n*M.steerDeg<=n*g.steerDeg){R=M;break}b=g,g=M}if(!R)return null;let k=vk(f,n,b,g,R);if(!k)return null;let v=xi(e,t,r,k,a);return!v.trimmed||Math.abs(v.beta-c.beta)>Cu||Math.abs(v.ay-c.ay)*Me>Tu?null:{state:v,sb:m}}function Rk(e,t,r,n,o){let a=[];return(s,i)=>{if(!i){i=a[0];for(let u of a)Math.abs(u.beta-s)<Math.abs(i.beta-s)&&(i=u)}let c=xk(e,t,r,s,i,n,o);if(!c)return null;let l={beta:s,...c};return a.push(l),l}}function BE(e,t){let r=Math.abs(t.beta-e.beta);return r>EE&&r>IE*Math.abs(t.steerDeg-e.steerDeg)}function $E(e,t,r,n,o,a,s,i){let c=o.length;if(c<2)return null;let l=o[c-1],u=c-2;for(;u>0&&o[u].beta===l.beta;)u--;let m=o[u],f=Math.sign(a.beta-l.beta);if(f===0||Math.sign(l.beta-m.beta)!==f||!m.driving)return null;let p=Rk(e,t,r,s,i),d=p(m.beta,m),h=p(l.beta,l);if(!d||!h||n*h.steerDeg<n*d.steerDeg)return null;let b=d,g=h,y=null;for(let R=yk;f*(a.beta-g.beta)>0;R=Math.min(DE,1.5*R)){let k=p(f*(a.beta-g.beta)>R?g.beta+f*R:a.beta);if(!k)return null;let v=n*k.steerDeg<=n*g.steerDeg;if(!y)v&&(y=[b,g,k]);else if(!v){let x=vk(p,n,...y);if(!x)return null;let M=xi(e,t,r,x,s);return M.trimmed?{state:M,sb:f}:null}b=g,g=k}return null}function vk(e,t,r,n,o){let a=p=>-t*p.steerDeg,s=Math.min(r.beta,o.beta),i=Math.max(r.beta,o.beta),c=n,l=a(r)<=a(o)?r:o,u=l===r?o:r,m=i-s,f=0;for(let p=0;p<100;p++){let d=.5*(s+i);if(Math.abs(c.beta-d)<=2*zr-.5*(i-s))break;let h=!0;if(Math.abs(m)>zr){let g=(c.beta-l.beta)*(a(c)-a(u)),y=(c.beta-u.beta)*(a(c)-a(l)),R=(c.beta-u.beta)*y-(c.beta-l.beta)*g;y=2*(y-g),y>0&&(R=-R),y=Math.abs(y);let k=m;if(m=f,Math.abs(R)<Math.abs(.5*y*k)&&R>y*(s-c.beta)&&R<y*(i-c.beta)){f=R/y;let v=c.beta+f;(v-s<2*zr||i-v<2*zr)&&(f=d>=c.beta?zr:-zr),h=!1}}h&&(m=c.beta>=d?s-c.beta:i-c.beta,f=Mk*m);let b=e(Math.abs(f)>=zr?c.beta+f:c.beta+(f>=0?zr:-zr));if(!b)return null;a(b)<=a(c)?(b.beta>=c.beta?s=c.beta:i=c.beta,u=l,l=c,c=b):(b.beta<c.beta?s=b.beta:i=b.beta,a(b)<=a(l)||l===c?(u=l,l=b):(a(b)<=a(u)||u===c||u===l)&&(u=b))}return c}function db(e,t,r,n,o,a,s=[n.stall]){let i=typeof o.op=="function"?o.op:()=>o.op,c=o.yawDemandCn??0,l="steerDeg"in a?b=>Math.abs(b.steerDeg)-Math.abs(a.steerDeg):b=>Math.abs(b.ay)-Math.abs(a.ayG),u=[...s,n.state].map(b=>({beta:b.beta,steerDeg:b.steerDeg,ay:b.ay})),m=u[0],f=u[u.length-1],p=l(m),d=l(f);if(p>0||d<0)return null;if(d===0)return xi(e,t,r,f,i);let h=m;for(let b=0;b<60&&Math.abs(f.beta-m.beta)>1e-9;b++){let g=(m.beta*d-f.beta*p)/(d-p),y=u[0];for(let x of u)Math.abs(x.beta-g)<Math.abs(y.beta-g)&&(y=x);let R=xk(e,t,r,g,y,i,c);if(!R)return null;let k={beta:g,...R};u.push(k),h=k;let v=l(k);if(Math.abs(v)<("steerDeg"in a?NE:OE))break;v<0?(m=k,p=v,d*=.5):(f=k,d=v,p*=.5)}return xi(e,t,r,h,i)}function GE(e,t,r,n,o,a){let s=Math.abs(o),{states:i}=n;if(s>Math.abs(i[i.length-1].steerDeg)+1e-9)return null;let c=0;for(;c<i.length-1&&Math.abs(i[c+1].steerDeg)<=s;)c++;let l=i[c];if(Math.abs(Math.abs(l.steerDeg)-s)<1e-9)return l;if(n.fold&&l===n.fold.stall)return db(e,t,r,n.fold,a,{steerDeg:o});let u=typeof a.op=="function"?a.op(o):a.op,m=eo(e,t,r,o,l,u,a.yawDemandCn??0);return m.driving?m:null}function KE(e,t,r,n,o,a){if(!n.trimmed)return!1;let s=n.steerDeg<0?-1:1,{states:i}=ro(e,t,r,{direction:s,op:o,yawDemandCn:a}),c=Math.abs(n.steerDeg);if(c>Math.abs(i[i.length-1].steerDeg)+1e-9)return!1;let l=0;for(;l<i.length-2&&Math.abs(i[l+1].steerDeg)<c;)l++;let u=i[l],m=i[Math.min(l+1,i.length-1)],f=Math.abs(m.steerDeg)-Math.abs(u.steerDeg),p=f>0?Math.min(1,Math.max(0,(c-Math.abs(u.steerDeg))/f)):0,d=u.beta+p*(m.beta-u.beta),h=u.ay+p*(m.ay-u.ay);return Math.abs(n.beta-d)<=1&&Math.abs(n.ay-h)<=.05}function vn(e,t,r,n,o){let a=Math.max(8,r),s=n>=0?1:-1,i=Math.abs(n),c=(b,g)=>Yr(e,t,a,s*b,g,o),l=ro(e,t,a,{direction:s,op:o}),{fold:u}=l;if(u&&Math.abs(u.state.steerDeg)<=wa){if(i>Math.abs(u.state.ay))return fk(e,t,a,s,i,o);if(i>Math.abs(u.stall.ay)){let b=db(e,t,a,u,{direction:s,op:o},{ayG:i});if(b)return b}}let m=l.states.filter(b=>Math.abs(b.steerDeg)<=wa),f=m[m.length-1],p=l.states.length>m.length;p&&Math.abs(f.steerDeg)<wa&&m.push(c(wa,f));let d=m.findIndex(b=>Math.abs(b.ay)>=i);if(d===0)return Yr(e,t,a,0,void 0,o);if(d>0)return dk(m[d-1],m[d],i,c);let h=kk(m,c,void 0,p||l.foldDeg===null);return h.ay>=i?dk(h.below,h.state,i,c):l.foldDeg!==null&&l.foldDeg<wa?fk(e,t,a,s,i,o):h.state}var wa=20;function dk(e,t,r,n){let o={steer:Math.abs(e.steerDeg),f:Math.abs(e.ay)-r},a={steer:Math.abs(t.steerDeg),f:Math.abs(t.ay)-r},s=a.f===o.f?.5:-o.f/(a.f-o.f),i={ay:e.ay+s*(t.ay-e.ay),beta:e.beta+s*(t.beta-e.beta),driving:e.driving},c=0,l=null,u=1/0;for(let m=0;m<60;m++){let f=a.f===o.f?.5*(o.steer+a.steer):o.steer-o.f*(a.steer-o.steer)/(a.f-o.f),p=n(f,i),d=Math.abs(p.ay)-r;if(Math.abs(d)<u&&(l=p,u=Math.abs(d)),Math.abs(d)<=HE||a.steer-o.steer<=zE)break;d<0?(o={steer:f,f:d},c===-1&&(a.f*=.5),c=-1):(a={steer:f,f:d},c===1&&(o.f*=.5),c=1)}return l}var HE=1e-9,zE=1e-7;function kk(e,t,r,n=!1){let o=r??0;if(r===void 0)for(let x=1;x<e.length;x++)Math.abs(e[x].ay)>Math.abs(e[o].ay)&&(o=x);let a=e[Math.max(0,o-1)],s=Math.abs(e[o].steerDeg),i=YE/4,c,l,u,m,f,p,d,h,b=null,g;if(o>0&&o<e.length-1){let x=e[o+1];g=w=>{if(w<s)return t(w,a);let T=t(w,e[o]);return T.ay===e[o].ay?t(w,a):T},c=Math.abs(a.steerDeg),l=Math.abs(x.steerDeg),u=s,m=-Math.abs(e[o].ay);let[M,F]=Math.abs(a.ay)>=Math.abs(x.ay)?[a,x]:[x,a];f=Math.abs(M.steerDeg),p=-Math.abs(M.ay),d=Math.abs(F.steerDeg),h=-Math.abs(F.ay)}else{let x=Math.abs(e[o].lockDeg??e[o].steerDeg),M=x-WE,F=o>0&&n&&M>Math.abs(a.steerDeg)?t(M,a):null;if(!F||Math.abs(F.ay)<=Math.abs(e[o].ay)){let w=t(s,a);return{state:w,below:a,ay:Math.abs(w.ay)}}g=w=>t(w,a),c=Math.abs(a.steerDeg),l=x,u=M,m=-Math.abs(F.ay),b=F,f=x,p=-Math.abs(e[o].ay),d=c,h=-Math.abs(a.ay)}let y=l-c,R=0;for(let x=0;x<100;x++){let M=.5*(c+l);if(Math.abs(u-M)<=2*i-.5*(l-c))break;let F=!0;if(Math.abs(y)>i){let A=(u-f)*(m-h),S=(u-d)*(m-p),C=(u-d)*S-(u-f)*A;S=2*(S-A),S>0&&(C=-C),S=Math.abs(S);let L=y;if(y=R,Math.abs(C)<Math.abs(.5*S*L)&&C>S*(c-u)&&C<S*(l-u)){R=C/S;let D=u+R;(D-c<2*i||l-D<2*i)&&(R=M>=u?i:-i),F=!1}}F&&(y=u>=M?c-u:l-u,R=Mk*y);let w=Math.abs(R)>=i?u+R:u+(R>=0?i:-i),T=g(w),P=-Math.abs(T.ay);P<=m?(w>=u?c=u:l=u,d=f,h=p,f=u,p=m,u=w,m=P,b=T):(w<u?c=w:l=w,P<=p||f===u?(d=f,h=p,f=w,p=P):(P<=h||d===u||d===f)&&(d=w,h=P))}let k=b??t(s,a),v=Math.abs(k.steerDeg)>s?e[o]:a;return{state:k,below:v,ay:Math.abs(k.ay)}}var YE=.001,WE=.01,Mk=(3-Math.sqrt(5))/2;function fk(e,t,r,n,o,a){let s=l=>Math.abs(Yr(e,t,r,n*l,void 0,a).ay),i=0,c=wa;if(s(c)<o)return Yr(e,t,r,n*c,void 0,a);for(let l=0;l<28;l++){let u=.5*(i+c);s(u)<o?i=u:c=u}return Yr(e,t,r,n*.5*(i+c),void 0,a)}function fb(e,t,r,n,o){let a=vn(e,t,r,n,o);return a.steering?Math.abs(a.steering.totalNm):NaN}function hb(e,t,r,n,o){if(!Un(e))return NaN;let a=n<0?-1:1,s=Math.abs(n),i=vn(e,t,r,a*s,o);if(!i.steering)return NaN;let c=Math.abs(i.steerDeg);for(let l of[.05,.1,.2,.4]){let u=Math.max(0,c-l),m=c+l,f=Yr(e,t,r,a*u,void 0,o),p=Yr(e,t,r,a*m,void 0,o),d=f.steering?Math.abs(f.steering.totalNm):NaN,h=p.steering?Math.abs(p.steering.totalNm):NaN,b=Math.abs(p.ay)-Math.abs(f.ay);if(Number.isFinite(d)&&Number.isFinite(h)&&b>=.01||l===.4&&Number.isFinite(d)&&Number.isFinite(h)&&b>.001)return(h-d)/b}return NaN}function ib(e,t,r,n,o,a){let s=Math.max(8,r),i=Et(e,t,s,n*se,o*se,void 0,Ca(e,a,s,t));return{ay:i.ay,cn:i.cn}}function bb(e,t,r,n,o){let a=Math.max(8,r),s=vn(e,t,a,n,o),i=.5,c=ib(e,t,a,s.beta+i,s.steerDeg,o).cn,l=ib(e,t,a,s.beta-i,s.steerDeg,o).cn;return(c-l)/(2*i*se)*e.massTotal*Me*(e.wheelbase/1e3)}function gb(e,t,r,n){let o=Math.max(8,r),{branch:a,opts:s}=jE(e,t,o,n);return Sk(e,t,o,a,s)}function jE(e,t,r,n){if(!e.tv?.enabled){let s=n?{op:n}:{};return{branch:ro(e,t,r,s),opts:s}}let o=cb(e,t,r),a={op:s=>{let i=lb(e,r,s,o);return i===0?n:{axG:n?.axG??0,driveFrontFrac:n?.driveFrontFrac,tvRearDiffN:i}}};return{branch:ro(e,t,r,a),opts:a}}function Sk(e,t,r,n,o){let a=typeof o.op=="function"?o.op:()=>o.op,s=o.yawDemandCn??0;if(n.fold&&n.peak===n.fold.state)return xi(e,t,r,n.peak,a);let i=(l,u)=>eo(e,t,r,l,u,a(l),s),c=n.states[0].driving||!n.peak.driving?n.states:n.states.slice(1);return kk(c,i,c.indexOf(n.peak),n.foldDeg===null).state}function yb(e,t,r,n={}){let o=n.radius!==void 0&&n.radius>0&&Number.isFinite(n.radius)?n.radius:void 0,a=o===void 0?Math.max(8,r):Math.max(8,Math.sqrt(Me*o)),s=(n.betaMaxDeg??10)*se,i=(n.deltaMaxDeg??10)*se,[c,l]=n.betaRangeDeg?[n.betaRangeDeg[0]*se,n.betaRangeDeg[1]*se]:[-s,s],[u,m]=n.deltaRangeDeg?[n.deltaRangeDeg[0]*se,n.deltaRangeDeg[1]*se]:[-i,i],{lf:f,lr:p}=sb(e),d=o===void 0?0:p/o,h=o===void 0?0:(f+p)/o,b=n.nLines??9,g=n.nPts??21,y=n.steering!==!1&&Un(e),R=y?dn(ye(t,"front").model):void 0,k=(E,_,B,V)=>B===1?E:E+(_-E)*V/(B-1),v=e.tv?.enabled?cb(e,t,a):0,x=E=>{let _=lb(e,a,E/se,v);return!n.axG&&_===0?null:Ca(e,{axG:n.axG??0,driveFrontFrac:n.driveFrontFrac,tvRearDiffN:_},a,t)},{lf:M,lr:F}=sb(e),w=n.reserves?Ri(t,e.massTotal*Me*1.2):null,T=E=>w?Dr(w,{FL:E.FL,FR:E.FR,RL:E.RL,RR:E.RR},{lf:M,lr:F}):null,P=[],A={ay:[],cn:[]},S=0;for(let E=0;E<b;E++){let _=k(u,m,b,E),B=x(_),V=[],G=[],K=[],Y=[],j=w?{stabil:[],agil:[]}:void 0,Z=y?ik():void 0,ne;for(let W=0;W<g;W++){let J=k(c,l,g,W),re=Et(e,t,a,J,_,ne,B,o);if(ne=Number.isFinite(re.ay)?re.ay*Me:void 0,V.push(re.ay),G.push(re.cn),K.push(J/se),Y.push(_/se),j){let pe=T(re.wheels);j.stabil.push(pe.stabil),j.agil.push(pe.agil)}Z&&ck(Z,sk(e,t,_,re.wheels)),Math.abs(re.ay)>S&&(S=Math.abs(re.ay))}P.push({label:`\u03B4 ${(_/se).toFixed(0)}\xB0`,ay:V,cn:G,betaDeg:K,deltaDeg:Y,reserve:j,steering:Z});let te=null,fe=1/0;for(let W=1;W<G.length;W++){if(!Number.isFinite(G[W-1])||!Number.isFinite(G[W])||G[W-1]!==0&&G[W-1]<0==G[W]<0)continue;let J=G[W-1]===G[W]?0:G[W-1]/(G[W-1]-G[W]),re=V[W-1]+J*(V[W]-V[W-1]);if(o===void 0&&_!==0&&Math.abs(re)>=.05&&Math.sign(re)!==Math.sign(_))continue;let pe=Math.abs(K[W-1]+J*(K[W]-K[W-1])-d/se);pe<fe&&(fe=pe,te=re)}te!==null&&(A.ay.push(te),A.cn.push(0))}let C=[];for(let E=0;E<b;E++){let _=k(c,l,b,E),B=[],V=[],G=[],K=[],Y=w?{stabil:[],agil:[]}:void 0,j=y?ik():void 0,Z;for(let ne=0;ne<g;ne++){let te=k(u,m,g,ne),fe=Et(e,t,a,_,te,Z,x(te),o);if(Z=Number.isFinite(fe.ay)?fe.ay*Me:void 0,B.push(fe.ay),V.push(fe.cn),G.push(_/se),K.push(te/se),Y){let W=T(fe.wheels);Y.stabil.push(W.stabil),Y.agil.push(W.agil)}j&&ck(j,sk(e,t,te,fe.wheels))}C.push({label:`\u03B2 ${(_/se).toFixed(0)}\xB0`,ay:B,cn:V,betaDeg:G,deltaDeg:K,reserve:Y,steering:j})}let L=.5*se,D=x(h),I,O;if(o===void 0)I=(Et(e,t,a,d+L,h,void 0,D,o).cn-Et(e,t,a,d-L,h,void 0,D,o).cn)/(2*L),O=(Et(e,t,a,d,h+L,void 0,x(h+L),o).cn-Et(e,t,a,d,h-L,void 0,x(h-L),o).cn)/(2*L);else{let E=(V,G)=>Et(e,t,a,V,G,void 0,x(G),o).cn,_=(V,G,K)=>Number.isFinite(V)?(-3*V+4*G-K)/(2*L):(K-G)/L,B=E(d,h);I=-_(B,E(d-L,h),E(d-2*L,h)),O=_(B,E(d,h+L),E(d,h+2*L))}let N=0;if(D&&D.axG){let E=Et(e,t,a,d,h,void 0,D,o),_=0;for(let B of Rn)_+=E.wheels[B].fxShort;N=_/Math.abs(e.massTotal*D.axG*Me)}let z=A.ay.reduce((E,_)=>Math.max(E,Math.abs(_)),0);return{isoBeta:C,isoDelta:P,trim:A,maxAy:S,stability:I,control:O,speed:o===void 0?a:Math.sqrt(z*Me*o),...o!==void 0?{radius:o}:{},axG:D?.axG??0,axShortfall:N,...R?{steeringAligningSource:R}:{}}}function Ak(e,t){return no(e,t*se).atLock}function UE(e,t,r,n,o=Hr(e,t,r)){let a=r,s=e.massTotal,i=Rn.filter(g=>Zt(g)?n.drivenFront:n.drivenRear),c=o.peakAt,l={front:n.drivenFront?zt(e,"front",1):void 0,rear:n.drivenRear?zt(e,"rear",1):void 0},u=new Map,m=(g,y)=>{let R=`${g}:${y}`,k=u.get(R);if(k===void 0){let v=Math.max(1,y*gi);k=Pt(ye(t,g),v,0,!1,c(g,v)),u.set(R,k)}return k},f=(g,y)=>y>0?bi(y,R=>m(g,R)):0,p=(g,y,R,k)=>{let v=ye(t,g),x=D=>{let I=Math.max(0,R[D]),O=c(g,I);return{Fz:I,a:f(g,I),b:O.fyPeak,slide:0,cap:N=>I>0?Pt(v,I,N,!1,O):0}},[M,F]=g==="front"?["FL","FR"]:["RL","RR"],w=x(M),T=x(F),P=k[M]*w.b,A=k[F]*T.b,S=w.cap(P)+T.cap(A),C=hi(w,T,P+A,y,S);return{l:M,r:F,full:C,asHeld:()=>({axle:g,strong:w.cap(P)>=T.cap(A)?M:F,full:C,open:hi(w,T,P+A,Ma,S),sense:1})}},d=g=>({muX:y=>y>0?f(g,y)/y:0,muY:y=>y>0?c(g,y).fyPeak/y:0}),h={front:d("front"),rear:d("rear")},b=g=>({arms:{lf:e.wheelbase/1e3*(1-e.frontMassFrac),lr:e.wheelbase/1e3*e.frontMassFrac},halfTrack:{front:e.trackFront/2e3,rear:e.trackRear/2e3},ayDir:Math.sign(g)});return{limitAt:(g,y,R,k=0)=>{let v={FL:0,FR:0,RL:0,RR:0},x=Ce(e,g,0,a,0,y),M,F=C=>(M?.ax!==C&&(M={ax:C,loads:Ce(e,g,(C+k)/Me,a,0,y)}),M.loads),w=El(C=>ma(R,F(C),x,c).short,-k,1),T=R,P=C=>{let L=w.at(C);v=F(L),T=ma(R,v,x,c).util;let D=0,I=n.diffYaw?{fx:{FL:0,FR:0,RL:0,RR:0},axles:[]}:null;for(let O of i){let N=l[xn(O)];if(N){if(wu(O)){let B=p(xn(O),N,v,T);D+=B.full,I&&(I.fx[B.l]=I.fx[B.r]=B.full/2,I.axles.push(B.asHeld()))}continue}let z=Math.max(0,v[O]),E=c(xn(O),z),_=Pt(ye(t,xn(O)),z,T[O]*E.fyPeak,!1,E);D+=_,I&&(I.fx[O]=_)}if(I){let O={};for(let N of Rn){let z=Math.max(0,v[N]);O[N]={Fz:z,Fy:T[N]*c(xn(N),z).fyPeak,Fx:I.fx[N]}}for(let N of I.axles)D+=Jl(N,O,h,b(g))-N.full}return D/s},A=W1(P,-k,yn).fx,S=w.edge();return S!==void 0&&A>S&&(A=S,P(A)),{ax:A,loads:v}}}}var Fu=.05,hk=.001,bk=16,Pu=8;function xb(e,t,r,n){let o=Math.max(Pu,r),a=n.nSteer??7,s=e.tv?.enabled?cb(e,t,o,n.steerMaxDeg):0,i=E=>{let _=lb(e,o,E,s);return _===0?void 0:{axG:0,tvRearDiffN:_}},c=n.yawDemandCn??0,l={op:i,yawDemandCn:c,...n.steerMaxDeg!==void 0?{steerMaxDeg:n.steerMaxDeg}:{}},u=ro(e,t,o,l),m=E=>{let _={},B={};for(let V of Rn)_[V]=E.wheels[V].slipDeg*se,B[V]=Math.min(1,E.wheels[V].gripUtil);return{steerDeg:E.steerDeg,ayMs:Math.max(0,E.ay*Me),ayG:E.ay,slip:_,util:B,scrub:E.ay>0?XE(E,e.massTotal):0}},f=null,p=E=>{if(f&&E===f.steerDeg)return m(f);let _=GE(e,t,o,u,E,l);if(_)return m(_);let B=u.states[0];for(let V of u.states)V.steerDeg<=E&&(B=V);return m(B)},d=u.peak.driving&&u.peak.ay>0?Sk(e,t,o,u,l):null,h=d?Math.max(0,d.ay*Me):0,b=d?[...u.states.filter(E=>E.steerDeg<d.steerDeg),d]:u.states,g=d?b.findIndex(E=>E.ay*Me>=.995*h):0,y=b[g].steerDeg,{fold:R}=u;if(d&&R&&u.peak===R.state){let E=.995*h/Me,_=u.states.indexOf(R.stall),B=_-1;for(;B>0&&u.states[B].beta===R.stall.beta;)B--;let V=Math.sign(R.stall.beta-u.states[B].beta),G=_;for(;G>0&&u.states[G].ay>=E&&Math.sign(u.states[G].beta-u.states[G-1].beta)!==-V;)G--;u.states[G].ay<E&&(f=db(e,t,o,R,l,{ayG:E},u.states.slice(G,_+1)))}if(f)y=f.steerDeg;else if(g>0){let E=b[g-1].steerDeg,_=y;for(let B=0;B<8&&_-E>.001;B++){let V=.5*(E+_);p(V).ayMs>=.995*h?_=V:E=V}y=_}let k=[];for(let E=0;E<(h>0?a:1);E++){let _=E/(a-1);k.push(p(y*(_+Math.sin(Math.PI/2*_))/2))}k[0].ayMs=0;let v=[],x=[],M=[],F=[],w=Hr(e,t,o,void 0,n.diffYaw===!0),T=UE(e,t,o,n,w),P=n.axDrag??0,A=E=>{let _=w.limitAt(E.ayMs/Me,E.steerDeg,E.util,P+E.scrub);return{axD:_.edge!==void 0&&_.edge>0?_.edge:_.ax,locked:_.axUnlocked-_.ax>Fu}},S=E=>T.limitAt(E.ayMs/Me,E.steerDeg,E.util,P+E.scrub).ax,C=k.map(E=>({p:E,axA:S(E),...A(E)})),L=[];for(let E=0;E+1<C.length;E++){let _=C[E],B=C[E+1],V=[];_.locked!==B.locked?V.push({read:A,past:G=>G.locked===B.locked,braking:!0}):(B.axA>_.axA+Fu&&V.push({read:G=>({axA:S(G)}),past:G=>(G.axA??-1/0)>_.axA}),-B.axD>-_.axD+Fu&&V.push({read:A,past:G=>-(G.axD??0)>-_.axD}));for(let{read:G,past:K,braking:Y}of V){let j=_.p.steerDeg,Z=B.p.steerDeg,ne=null,te=_.axD,fe=B.axD;for(let W=0;W<bk&&Z-j>hk&&!(Y&&Math.abs(fe-te)<=Fu);W++){let J=.5*(j+Z),re=p(J),pe=G(re);K(pe)?(Z=J,ne={p:re,r:pe},fe=pe.axD??fe):(j=J,te=pe.axD??te)}if(ne){let{p:W,r:J}=ne,re=J.axD!==void 0&&J.locked!==void 0?{axD:J.axD,locked:J.locked}:A(W);L.push({p:W,axA:J.axA??S(W),...re})}}}C.push(...L),C.sort((E,_)=>E.p.steerDeg-_.p.steerDeg);let D=E=>E.axA+P+E.p.scrub,I=.001*Math.max(1,k[k.length-1].ayMs),O=[];for(let E=0;E+1<C.length;E++){let _=C[E],B=C[E+1];if(!(D(_)>=0&&D(B)<0))continue;let V=_.p.steerDeg,G=B.p.steerDeg,K=null,Y=null;for(let Z=0;Z<bk&&G-V>hk;Z++){let ne=.5*(V+G),te=p(ne);D({p:te,axA:S(te)})>=0?(V=ne,K=te):(G=ne,Y=te)}let j=K??Y;j&&j.ayMs>_.p.ayMs&&j.ayMs<B.p.ayMs&&O.push({p:j,axA:-(P+j.scrub),steady:!0,...A(j)})}C.push(...O),C.sort((E,_)=>E.p.steerDeg-_.p.steerDeg);let N=!1;for(let{p:E,axA:_,axD:B,steady:V}of C){let G=v.length-1,K=G>=0&&(V||N?!(E.ayMs>v[G]):E.ayMs-v[G]<I);N=V===!0&&!K,K?(x[G]=Math.max(x[G],_),M[G]=Math.min(M[G],B)):(v.push(E.ayMs),x.push(_),M.push(B),F.push(E.scrub))}for(let E=v.length-2;E>=0;E--)x[E]=Math.max(x[E],x[E+1]),M[E]=Math.min(M[E],M[E+1]);return{ayMax:v[v.length-1],ay:v,axAccel:x,axDecel:M,axScrub:F,rollover:u.rollover,atLock:d!==null&&Ak(e,d.steerDeg)}}function XE(e,t){let r=e.beta*se,n=0;for(let o of Rn){let a=e.wheels[o],s=a.steerDeg*se-r;n+=a.Fx*(Math.cos(s)-1)-a.Fy*Math.sin(s)}return n/t}var g9=Math.PI/180,y9={speeds:Array.from({length:23},(e,t)=>8+t),steerMaxDeg:14,steerSteps:29};function wk(e=150,t=300,r=18,n=25){return(o,a,s)=>{let i=Math.min(1,Math.max(0,(o-r)/(n-r))),c=s>0?Math.min(1,a/s):0;return(e+i*(t-e))*c}}var Ta={enabled:!1,kp:3e3,ffLow:150,ffHigh:300,vLow:18,vHigh:25},Fk=e=>wk(e.ffLow,e.ffHigh,e.vLow,e.vHigh);var fr={power_limit_kw:{value:0,label:"battery power limit (0 = none)",unit:"kW"},v_limit_endurance:{value:0,label:"endurance speed limit (0 = none)",unit:"km/h"},endurance_reserve:{value:0,label:"endurance energy reserve (0 = flat out)",unit:"%"},grip_scale:{value:1,label:"grip scale (rig \u2192 road)",unit:"-"},stiffness_scale:{value:1,label:"stiffness scale (rig \u2192 road)",unit:"-"},camber_front_deg:{value:0,label:"static camber front (\u2212 top in)",unit:"\xB0"},camber_rear_deg:{value:0,label:"static camber rear (\u2212 top in)",unit:"\xB0"},cg_height:{value:300,label:"CG height",unit:"mm"},tire_vertical_rate:{value:100,label:"tyre vertical rate",unit:"N/mm"},tire_vertical_damping:{value:0,label:"tyre vertical damping",unit:"N\xB7s/mm"},arb_front:{value:20,label:"ARB front (@wheel)",unit:"N/mm"},arb_rear:{value:15,label:"ARB rear (@wheel)",unit:"N/mm"},heave_spring_front:{value:0,label:"Heave spring front (@wheel)",unit:"N/mm"},heave_spring_rear:{value:0,label:"Heave spring rear (@wheel)",unit:"N/mm"},unsprung_mass:{value:8,label:"unsprung mass/corner",unit:"kg"},brake_balance:{value:.6,label:"brake balance (front)",unit:"-"},damper_front:{value:2.5,label:"damper front",unit:"N\xB7s/mm"},damper_rear:{value:2.5,label:"damper rear",unit:"N\xB7s/mm"},cop_long:{value:.5,label:"CoP aft of front",unit:"\xB7wb"},cop_height:{value:300,label:"CoP height",unit:"mm"},ride_height_front:{value:30,label:"static ride height front (laden)",unit:"mm"},ride_height_rear:{value:35,label:"static ride height rear (laden)",unit:"mm"},I_yaw:{value:295,label:"yaw inertia Izz",unit:"kg\xB7m\xB2"},I_roll:{value:95,label:"roll inertia Ixx",unit:"kg\xB7m\xB2"},I_pitch:{value:380,label:"pitch inertia Iyy",unit:"kg\xB7m\xB2"},I_wheel:{value:0,label:"rotating inertia per wheel",unit:"kg\xB7m\xB2"},I_rotor:{value:0,label:"driveline inertia at the motor",unit:"kg\xB7m\xB2"},ackermann_pct:{value:50,label:"Ackermann",unit:"%"},toe_front_deg:{value:0,label:"static toe front (+ in)",unit:"\xB0"},toe_rear_deg:{value:0,label:"static toe rear (+ in)",unit:"\xB0"},spring_front:{value:35,label:"spring front (@spring)",unit:"N/mm"},spring_rear:{value:40,label:"spring rear (@spring)",unit:"N/mm"},mr_front:{value:1,label:"motion ratio front",unit:"-"},mr_rear:{value:1,label:"motion ratio rear",unit:"-"},track_front:{value:1200,label:"track front",unit:"mm"},track_rear:{value:1200,label:"track rear",unit:"mm"},wheelbase:{value:1535,label:"wheelbase",unit:"mm"},rc_front:{value:30,label:"roll centre front",unit:"mm"},rc_rear:{value:40,label:"roll centre rear",unit:"mm"},tv_enabled:{value:0,label:"torque vectoring",unit:"0/1"},tv_kp:{value:3e3,label:"TV yaw-rate gain",unit:"N per rad/s"},tv_ff_low:{value:150,label:"TV feedforward, low speed",unit:"N"},tv_ff_high:{value:300,label:"TV feedforward, high speed",unit:"N"},tv_v_low:{value:18,label:"TV feedforward ramp start",unit:"m/s"},tv_v_high:{value:25,label:"TV feedforward ramp end",unit:"m/s"}},qE=["k_yaw","k_roll","k_pitch"];function ki(e){for(let t of qE)delete e[t];for(let t of Object.keys(fr)){let r=e[t];if(!r){e[t]={...fr[t]};continue}e[t]={...r,label:fr[t].label,unit:fr[t].unit}}return e}function Q(e,t){return e[t]?.value??fr[t].value}function Lu(e){let t=(r,n)=>e[r]?.value??n;return{enabled:t("tv_enabled",0)>=.5,kp:t("tv_kp",Ta.kp),ffLow:t("tv_ff_low",Ta.ffLow),ffHigh:t("tv_ff_high",Ta.ffHigh),vLow:t("tv_v_low",Ta.vLow),vHigh:t("tv_v_high",Ta.vHigh)}}var Ck=[10,25,50,100,200,300];function Rb(e,t,r,n,o){let s=Ck.map(i=>Math.round(i<=25?r*i:r*25+n*(i-25)));return{id:e,label:t,speedMmS:[...Ck],reboundN:s,bumpN:s.map(i=>Math.round(i*o))}}var Du={name:"Generic FS damper",curves:[Rb("c1","Soft",1.6,1,.65),Rb("c2","Medium",3,1.6,.65),Rb("c3","Firm",8,2.4,.65)]};function Eu(e){let t=e.curves.length;return t>0?e.curves[Math.floor((t-1)/2)].id:""}var kn=25;function Pa(e,t){let r=e.speedMmS,n=e.forceN,o=Math.min(r.length,n.length);if(o===0||!(t>0))return 0;let a=0,s=0;for(let i=0;i<o;i++){let c=r[i],l=n[i];if(t<=c)return s+(l-s)*(t-a)/(c-a);if(i===o-1)return l+Math.max(0,(l-s)/(c-a))*(t-c);a=c,s=l}return 0}function Tk(e,t){return t>=0?Pa(e.rebound,t):-Pa(e.bump,-t)}function Pk(e,t,r){return t*Tk(e,t*r)}var vb=(e,t)=>e.curves.find(r=>r.id===t);function Mi(e,t){let r=vb(e,Eu(e)),n=(t&&vb(e,t.bump))??r,o=(t&&vb(e,t.rebound))??r;return{bump:{speedMmS:n?.speedMmS??[],forceN:n?.bumpN??[]},rebound:{speedMmS:o?.speedMmS??[],forceN:o?.reboundN??[]}}}var Iu=5e3;function Si(e,t){let r=t>0?t:1,n=[],o=[],a=e.bump.speedMmS.map(c=>c/r).filter(c=>c<Iu),s=e.rebound.speedMmS.map(c=>c/r).filter(c=>c<Iu),i=c=>{n.push(c),o.push(Pk(e,r,c))};i(-Iu);for(let c=a.length-1;c>=0;c--)i(-a[c]);i(0);for(let c of s)i(c);return i(Iu),{kind:"map",input:"velocity",x:n,y:o}}var kb=64;function Ai(e,t,r){let n=t>0?t:1,o=Math.max(r,1e-6),a=0;for(let s=0;s<kb;s++){let i=Math.sin((s+.5)*Math.PI/kb),c=n*o*i;a+=n*(Pa(e.rebound,c)+Pa(e.bump,c))*i}return a*(Math.PI/kb)/(Math.PI*o)}function oo(e,t,r,n,o=e){let a=(c,l,u)=>{if(!c||c.curves.length===0)return;let m=Mi(c,l);return{law:m,curve:Si(m,u),rate:Ai(m,u,kn)}},s=a(e,t?.front,r),i=a(o??e,t?.rear,n);return!s&&!i?null:{...s?{front:s}:{},...i?{rear:i}:{}}}var Lk=(e,t)=>({...e,y:e.y.map(r=>r*t)}),QE=e=>({...e,x:e.x.map(t=>-t).reverse(),y:e.y.map(t=>-t).reverse()});function Mb(e,t,r){let n=Math.abs(r)>0?Math.abs(r):1,o=Mi(e,t);return{law:o,curve:Lk(Si(o,n),.5),rate:Ai(o,n,kn)/2,mr:n,ratio:n,share:.5}}function Sb(e,t,r,n,o){let a=n*(Math.abs(r)>0?Math.abs(r):1),s=Mi(e,t),i=Lk(Si(s,a),1/n);return{law:s,curve:o?QE(i):i,rate:Ai(s,a,kn)/n,mr:a/n,ratio:a,share:1/n}}function Fi(e,t){let r=e.damperModelIdRear?t(e.damperModelIdRear):void 0,n=e.heaveDamperModelId?t(e.heaveDamperModelId):void 0,o=e.rollDamperModelId?t(e.rollDamperModelId):void 0;return{...r?{damperModelRear:r}:{},...n?{heaveDamperModel:n}:{},...o?{rollDamperModel:o}:{}}}var _u=["front","rear","heaveFront","heaveRear","rollFront","rollRear"];function wi(e,t){if(t?.body){let{extended:n,stroke:o,...a}=e??{},{extended:s,stroke:i}=t.body;return{coilover:{...a,extended:s,...i!==void 0?{stroke:i}:{}},source:"part",part:t}}let r=e?.extended!==void 0&&e.extended>0;return{...e?{coilover:e}:{},source:r?"suspension":"none"}}function Wr(e,t){if(typeof e=="number")return e;let{x:r,y:n}=e,o=r.length;if(o===0)return 0;if(o===1||t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}function Ti(e){return e.kind==="coil"?2:1}function Ci(e){let t=Math.max(0,e.od),r=Math.max(0,Math.min(e.id,t));return Math.PI*(t**4-r**4)/32}function Ek(e){return Ci(e)/2}function Ik(e){let t=Math.max(0,e.width),r=Math.max(0,e.thickness),n=t*r**3/12,o=r*t**3/12,a=e.angleDeg*Math.PI/180;return n*Math.cos(a)**2+o*Math.sin(a)**2}function Dk(e){let t=0;for(let r of e)if(Number.isFinite(r)){if(r<=0)return 0;t+=1/r}return t>0?1/t:1/0}function ZE(e,t,r){let n=Math.min(e.length,t.length);if(n<2)return 0;let o=Math.abs(r);if(o<=e[0])return(t[1]-t[0])/(e[1]-e[0]);for(let a=1;a<n;a++)if(o<=e[a])return(t[a]-t[a-1])/(e[a]-e[a-1]);return(t[n-1]-t[n-2])/(e[n-1]-e[n-2])}function Pi(e,t=0){let r={rateAtLink:0,contributions:{},torsional:0};switch(e.kind){case"none":return r;case"ubar":{let n=e.armLength;if(n<=0||e.barLength<=0)return r;let o=e.G*Ci(e.section)/e.barLength,a=2*o/(n*n),s=Ek(e.armSection??e.section),i=3*e.E*s/n**3,c=e.dropLinkRate??1/0;return{rateAtLink:Dk([a,i,c]),contributions:{barTwist:a,armBending:i,dropLink:c},torsional:o}}case"blade":{let n=e.armLength;if(n<=0||e.barLength<=0)return r;let o=e.G*Ci(e.section)/e.barLength,a=2*o/(n*n),s=3*e.E*Ik(e.blade)/n**3,i=e.dropLinkRate??1/0;return{rateAtLink:Dk([a,s,i]),contributions:{barTwist:a,armBending:s,dropLink:i},torsional:o}}case"torsionTube":{let n=e.leverArm;if(n<=0||e.length<=0)return r;let o=e.G*Ci(e.section)/e.length,a=2*o/(n*n);return{rateAtLink:a,contributions:{barTwist:a},torsional:o}}case"coil":{let n=Wr(e.rate,2*Math.abs(t)),o=2*Math.max(0,n);return{rateAtLink:o,contributions:{spring:o},torsional:0}}case"direct":return{rateAtLink:e.wheelRate,contributions:{},torsional:0};case"tabulated":{let n=ZE(e.linkTravel,e.force,t);return{rateAtLink:Math.max(0,n),contributions:{},torsional:0}}}}function Nu(e,t,r=0){if(e.kind==="none")return{wheelRate:0,motionRatio:0,rateAtLink:0};if(e.kind==="direct")return{wheelRate:Math.max(0,e.wheelRate),motionRatio:1,rateAtLink:0};let n=t?sf(t,r):1,o=t?cf(t,r):0,a=Pi(e,o).rateAtLink;return{wheelRate:Math.max(0,a*n*n),motionRatio:n,rateAtLink:a}}function Li(e,t){let r=e.damper??0;return!r||e.design.kind==="none"?0:Ti(e.design)*r*t*t}var JE=150;function eI(e){return X(e,[0,-.5,1])<-1e-9?U(e,-1):e}function _k(e){let t=e.hardpoints,r=H(t.rockerPivotB,t.rockerPivotA),n=ee(t.rockerPivotA,U(H(t.rockerToDamper,t.rockerPivotA),.6)),o=eI(q(ae(r,H(t.rockerToDamper,t.rockerPivotA))));return{outer:n,inner:ee(n,U(o,JE)),attach:"rocker"}}function It(e,t){let r={};for(let o of ir)r[o]=rt(_e(e,o));let n={vehicle:e,ctx:r};return t&&(n.kc=wl(n,t)),n}function tI(e,t,r,n){let o=e.corner.hardpoints,a=Zo(e.rocker,t.points.rockerAngle),s=i=>Tt(i,r);return{ucaFront:s(o.ucaFront),ucaRear:s(o.ucaRear),lcaFront:s(o.lcaFront),lcaRear:s(o.lcaRear),tieInner:s($n(e.inv,t.steer)),rockerPivotA:s(o.rockerPivotA),rockerPivotB:s(o.rockerPivotB),damperChassis:s(e.inv.strut?t.points.uprightUpper:o.damperChassis),uprightUpper:s(t.points.uprightUpper),uprightLower:s(t.points.uprightLower),tieOuter:s(t.points.tieOuter),wheelCenter:s(t.points.wheelCenter),pushrodOuter:s(t.points.pushrodOuter),contactPatch:s(t.points.contactPatch),kingpinGround:s(t.points.kingpinGround),kingpinAtHub:s(t.points.kingpinAtHub),rockerToPushrod:s(a.pushrod),rockerToDamper:s(a.damper),spinAxis:Tr(t.points.spinAxis,r),direct:e.corner.config.actuation==="direct",decoupled:e.corner.config.actuation==="decoupled",mcpherson:e.inv.strut!==void 0,loadedRadius:n.loadedRadius,tyreDeflection:n.tyreDeflection,load:n.load,lifted:n.lifted,clearance:n.clearance??0,contactLength:n.contactLength}}function Ou(e,t,r,n){let o=Ze(t,e.vehicle.config),a=o.isFront?o.sideSign*n:0,s;try{s=dt(ge(e.ctx[t],r,a))}catch{return null}if(!s)return null;let i=_e(e.vehicle,t).config.loadedRadius,c=tI(e.ctx[t],s,o,{loadedRadius:i,tyreDeflection:0,load:NaN,lifted:!1,contactLength:0});return c.wheelCenter.every(Number.isFinite)?{id:t,placement:o,solved:!0,state:s,geometry:c}:null}var Vu=.5;function rI(e,t){let r=([i,c,l])=>{let u=q(H(c,i)),m=H(l,i),f=q(H(m,U(u,X(m,u))));return[u,f,ae(u,f)]},n=r(e),o=r(t),a=[0,1,2].map(i=>[0,1,2].map(c=>o[0][i]*n[0][c]+o[1][i]*n[1][c]+o[2][i]*n[2][c]));return{rot:a,move:i=>{let c=H(i,e[0]);return ee(t[0],[0,1,2].map(l=>a[l][0]*c[0]+a[l][1]*c[1]+a[l][2]*c[2]))}}}var Nk=e=>[(e[2][1]-e[1][2])/2,(e[0][2]-e[2][0])/2,(e[1][0]-e[0][1])/2];function Bu(e,t,r){let n=Ze(t,e.vehicle.config),o=e.ctx[t],a=r.rigid?void 0:{loadedRadius:r.loadedRadius},s=r.state?null:ge(o,r.travel,r.steer,void 0,a),i=r.state??it(s),c=ge(o,r.travel+Vu,r.steer,void 0,a),l=ge(o,r.travel-Vu,r.steer,void 0,a),u=(s?s.ok:r.converged)&&c.ok&&l.ok,m=it(c),f=it(l),p=(T,P)=>Tt(T.points[P],n),d=o.inv.strut?"pushrodOuter":"uprightUpper",h=p(i,d),b=p(i,"uprightLower"),g=T=>{let P=H(b,h);return Math.hypot(...ae(P,H(p(i,T),h)))/Math.hypot(...P)},y=g("tieOuter")>=g("wheelCenter")?"tieOuter":"wheelCenter",R=[h,b,p(i,y)],k=T=>rI(R,[p(T,d),p(T,"uprightLower"),p(T,y)]),v=k(m),x=k(f),M=Nk(v.rot),F=Nk(x.rot),w=[NaN,NaN,NaN];return{solved:u,state:i,at:T=>p(i,T),velocity:T=>u?U(H(v.move(T),x.move(T)),1/(2*Vu)):w,omega:u?U(H(M,F),1/(2*Vu)):w}}function Ab(e,t,r,n){let o=t[0]*-n[1]-t[1]*-n[0];if(Math.abs(o)<1e-9)return null;let a=r[0]-e[0],s=r[1]-e[1],i=(a*-n[1]-s*-n[0])/o;return[e[0]+i*t[0],e[1]+i*t[1]]}function Ok(e,t,r){let n=Bu(e,t,vt(e,r)[t]),o=n.at("contactPatch"),a=n.velocity(o);return{solved:n.solved,cp:[o[1],o[2]],vCp:[a[1],a[2]],wx:n.omega[0]}}function Vk(e){let t=Math.hypot(e.vCp[0],e.vCp[1]);return Math.abs(e.wx)*1e9>t?[e.cp[0]-e.vCp[1]/e.wx,e.cp[1]+e.vCp[0]/e.wx]:null}function Bk(e,t){let r=Math.hypot(e.vCp[0],e.vCp[1]);if(!(r>1e-9))return null;let n=[-e.vCp[1]/r,e.vCp[0]/r],o=t?[t[0]-e.cp[0],t[1]-e.cp[1]]:[e.cp[0]>0?-1:1,0];return n[0]*o[0]+n[1]*o[1]<0?[-n[0],-n[1]]:n}function nI(e,t,r){return Math.abs(t[0]*(r[1]-e[1])-t[1]*(r[0]-e[0]))<=1e-6*Math.max(1,Math.hypot(r[0]-e[0],r[1]-e[1]))?[(e[0]+r[0])/2,(e[1]+r[1])/2]:null}var oI=.1*Math.PI/180;function $k(e,t,r,n,o){return Math.max(Math.hypot(e[0]-t[0],e[1]-t[1]),Math.hypot(e[0]-r[0],e[1]-r[1]))*oI<=o*n}function $u(e,t){return!e.valid||!e.cpLeft||!e.cpRight?!1:$k([e.lateral,e.height],e.cpLeft,e.cpRight,e.sinAngle,t)}function Di(e){let t=(o,a,s)=>{let i=o&&a?[a[0]-o[0],a[1]-o[1]]:s;return!o||!i||!(Math.abs(i[0])>1e-9)?Number.NaN:o[1]-o[0]*i[1]/i[0]},r=t(e.cpLeft,e.icLeft,e.lineLeft),n=t(e.cpRight,e.icRight,e.lineRight);return Number.isFinite(r)&&Number.isFinite(n)?{left:r,right:n}:null}var aI=1;function Gk(e){let t=Di(e);if(!t||!e.cpLeft||!e.cpRight||Math.abs(t.left-t.right)>aI)return null;let r=(t.left+t.right)/2,n=e.cpRight[0]-e.cpLeft[0],o=e.cpRight[1]-e.cpLeft[1],a=Math.hypot(n,o)||1;return{height:r,heightAboveGround:(0-e.cpLeft[0])*(-o/a)+(r-e.cpLeft[1])*(n/a)}}function La(e){let t=(n,o,a)=>{if(!n)return Number.NaN;if(!o)return a?0:Number.NaN;let s=n[0]-o[0];return Math.abs(s)>1e-9?n[0]/s:Number.NaN},r=(t(e.cpLeft,e.icLeft,e.lineLeft)+t(e.cpRight,e.icRight,e.lineRight))/2;return e.valid&&Number.isFinite(r)?r:0}function hr(e,t,r){let n=r==="front"?"FL":"RL",o=r==="front"?"FR":"RR",a=Ok(e,n,t),s=Ok(e,o,t);if(!a.solved||!s.solved)return{height:0,lateral:0,heightAboveGround:0,lateralAlongGround:0,valid:!1,unsolved:!0,icLeft:null,icRight:null,lineLeft:null,lineRight:null,sinAngle:0,cpLeft:a.cp,cpRight:s.cp};let i=Vk(a),c=Vk(s),l=Bk(a,i),u=Bk(s,c),m={height:0,lateral:0,heightAboveGround:0,lateralAlongGround:0,valid:!1,icLeft:i,icRight:c,lineLeft:l,lineRight:u,sinAngle:0,cpLeft:a.cp,cpRight:s.cp};if(!l||!u)return m;let f=i?[i[0]-a.cp[0],i[1]-a.cp[1]]:l,p=c?[c[0]-s.cp[0],c[1]-s.cp[1]]:u,d=Math.hypot(f[0],f[1]),h=Math.hypot(p[0],p[1]),b=d>0&&h>0?Math.abs(f[0]*p[1]-f[1]*p[0])/(d*h):0,g=Ab(a.cp,f,s.cp,p)??nI(a.cp,l,s.cp);if(!g)return{...m,sinAngle:b};let y=s.cp[0]-a.cp[0],R=s.cp[1]-a.cp[1],k=Math.hypot(y,R)||1,v=y/k,x=R/k,M=(a.cp[0]+s.cp[0])/2,F=(a.cp[1]+s.cp[1])/2,w=(g[0]-a.cp[0])*-x+(g[1]-a.cp[1])*v,T=(g[0]-M)*v+(g[1]-F)*x;return{lateral:g[0],height:g[1],heightAboveGround:w,lateralAlongGround:T,valid:!0,icLeft:i,icRight:c,lineLeft:l,lineRight:u,sinAngle:b,cpLeft:a.cp,cpRight:s.cp}}function jr(e,t){return{front:hr(e,t,"front"),rear:hr(e,t,"rear")}}function Gu(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function sI(e,t){return{camber:Gu(e.travel,e.camber,t),toe:Gu(e.travel,e.toe,t),motionRatio:Gu(e.travel,e.motionRatio,t),damperLen:e.damperLen?Gu(e.travel,e.damperLen,t):0}}var Kk=e=>sI(e,0).motionRatio;function Fb(e,t){if(e.kind!=="coil")return null;let r=t??e.motionRatio,n=Wr(e.rate,0)*r*r/2;return n>0&&Number.isFinite(n)?{rate:n,gap:Math.max(0,e.gap??0),bothWays:!!e.bothWays}:null}function Ku(e,t){if(e.kind==="none")return 0;if(e.kind==="tabulated"){let n=a=>iI(e,a);return(n(.5)-n(-.5))/(2*.5)/2}if((e.gap??0)>0)return 0;let r=t??e.motionRatio;return Wr(e.rate,0)*r*r/2}function Ei(e,t){let r=e.damper??0;if(!r||e.design.kind==="none"||e.design.kind==="coil"&&(e.design.gap??0)>0)return 0;let n=t??(e.design.kind==="coil"?e.design.motionRatio:1);return r*n*n/2}function iI(e,t){let{travel:r,force:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}var wb={kind:"coil",rate:120,motionRatio:.7,gap:5,bothWays:!1};var Hk=new WeakMap;function zu(e,t){let r=Hk.get(e);r||(r=new Map,Hk.set(e,r));let n=`${t.attach}|${t.outer.join(",")}|${JSON.stringify(t.mount??null)}`,o=r.get(n);if(o)return o;let a=Gn(e,t);return r.set(n,a),a}var cI=32,Ii=new Map,zk=new WeakMap,lI=1;function uI(e){let t=zk.get(e);return t===void 0&&(t=lI++,zk.set(e,t)),t}function Cb(e,t){if(!t.linkage)return null;let r=pn(e,t.linkage,t.design.kind),n=`${uI(e)}|${r?"unit":"bar"}|${JSON.stringify(t.linkage)}`,o=Ii.get(n);if(o)return o;let a=oa(e,t.linkage,{kind:t.design.kind});return Ii.size>=cI&&Ii.delete(Ii.keys().next().value),Ii.set(n,a),a}function so(e,t,r=0){let n=(o,a)=>{if(!(!o||o.design.kind==="none"))return Nu(o.design,Cb(a,o),r).wheelRate};return{front:n(t.arbFrontDesign,e.front),rear:n(t.arbRearDesign,e.rear)}}function Da(e,t){let r=(n,o)=>{if(!n||n.design.kind==="none")return;let a=n.linkage?zu(o,n.linkage).atDesign:void 0;return Ku(n.design,a)};return{front:r(t.heaveFrontDesign,e.front),rear:r(t.heaveRearDesign,e.rear)}}function Xk(e,t){let r=(a,s)=>{if(!a||a.design.kind!=="coil")return;let i=a.linkage?zu(s,a.linkage).atDesign:void 0;return Fb(a.design,i)??void 0},n=r(t.heaveFrontDesign,e.front),o=r(t.heaveRearDesign,e.rear);return{...n?{front:n}:{},...o?{rear:o}:{}}}function Yu(e,t){let r=(o,a)=>o?Ei(o,Tb(o,a)):0,n=(o,a)=>o?Li(o,Pb(o,a)):0;return{heaveFront:r(t.heaveFrontDesign,e.front),heaveRear:r(t.heaveRearDesign,e.rear),rollFront:n(t.arbFrontDesign,e.front),rollRear:n(t.arbRearDesign,e.rear)}}var Tb=(e,t)=>e.linkage?zu(t,e.linkage).atDesign:void 0,Pb=(e,t)=>Nu(e.design,Cb(t,e),0).motionRatio;function qk(e,t){let r=t.damperSetup,n=t.heaveDamperModel??t.damperModel,o=t.rollDamperModel??t.damperModel,a=(f,p,d)=>{if(!f||!n?.curves.length)return;let h=Tb(f,p);if(Ei(f,h)>0)return Mb(n,r?.[d],h??(f.design.kind==="coil"?f.design.motionRatio:1))},s=(f,p,d)=>{if(!f||!o?.curves.length)return;let h=Pb(f,p);if(!(Li(f,h)>0))return;let b=Cb(p,f)!==null;return Sb(o,r?.[d],h,Ti(f.design),b&&h>0)},i={},c=a(t.heaveFrontDesign,e.front,"heaveFront"),l=a(t.heaveRearDesign,e.rear,"heaveRear"),u=s(t.arbFrontDesign,e.front,"rollFront"),m=s(t.arbRearDesign,e.rear,"rollRear");return c&&(i.heaveFront=c),l&&(i.heaveRear=l),u&&(i.rollFront=u),m&&(i.rollRear=m),i}function Wu(e,t){let r=t.heaveDamperModel??t.damperModel,n=t.rollDamperModel??t.damperModel,o=(i,c)=>ao(i)?{source:"none"}:wi(i.config.coilover,c),a=(i,c)=>{if(!i)return{source:"none"};let l=Ei(i,Tb(i,c))>0;return wi(i.coilover,l?r:void 0)},s=(i,c)=>{if(!i||i.design.kind!=="coil")return{source:"none"};let l=Li(i,Pb(i,c))>0;return wi(i.coilover,l?n:void 0)};return{front:o(e.front,t.damperModel),rear:o(e.rear,t.damperModelRear??t.damperModel),heaveFront:a(t.heaveFrontDesign,e.front),heaveRear:a(t.heaveRearDesign,e.rear),rollFront:s(t.arbFrontDesign,e.front),rollRear:s(t.arbRearDesign,e.rear)}}function Qk(e){let t=(r,n)=>{let o={};return r?.linkage&&r.design.kind==="coil"&&(o.heave=r.linkage),n?.linkage&&n.design.kind!=="none"&&n.design.kind!=="direct"&&(o.roll=n.linkage,o.rollKind=n.design.kind),o.heave||o.roll?o:void 0};return{front:t(e.heaveFrontDesign,e.arbFrontDesign),rear:t(e.heaveRearDesign,e.arbRearDesign)}}var ao=e=>e.config.actuation==="decoupled",io="a decoupled axle damps in its heave and roll elements, set below";function Zk(e,t,r={}){let n={...t},o=(m,f)=>{let p=n[m];p&&typeof p=="object"&&"value"in p&&(n[m]={...p,value:f})},{front:a,rear:s}=so(e,t);a!==void 0&&o("arb_front",a),s!==void 0&&o("arb_rear",s);for(let[m,f,p]of[[t.heaveFrontDesign,e.front,"heave_spring_front"],[t.heaveRearDesign,e.rear,"heave_spring_rear"]]){if(!m||m.design.kind==="none")continue;let d=m.linkage?zu(f,m.linkage).atDesign:void 0;o(p,Ku(m.design,d))}let i=pI(e,t,r),c=mI(e,i);n.kinFront=c.kinFront,n.kinRear=c.kinRear;let l=hI(e,i);n.steerFront=c.steerFront,Number.isFinite(l.ackermannPct)&&o("ackermann_pct",l.ackermannPct);let u=m=>ao(m)?0:m.measured?.springRate??m.config.springRate;o("spring_front",u(e.front)),o("spring_rear",u(e.rear));for(let[m,f]of[[e.front,"spring_front"],[e.rear,"spring_rear"]])ao(m)&&(n.readouts={...n.readouts,[f]:"a decoupled axle has no corner spring; its heave and roll elements carry the car"});for(let[m,f]of[[e.front,"damper_front"],[e.rear,"damper_rear"]])ao(m)&&(o(f,0),n.readouts={...n.readouts,[f]:io});return o("mr_front",l.mrFront),o("mr_rear",l.mrRear),o("wheelbase",l.wheelbase),o("track_front",l.trackFront),o("track_rear",l.trackRear),o("rc_front",l.rcFront),o("rc_rear",l.rcRear),n.surveyedRadiusFront=e.front.config.loadedRadius,n.surveyedRadiusRear=e.rear.config.loadedRadius,n.rcRoad={radiusFront:e.front.config.loadedRadius,radiusRear:e.rear.config.loadedRadius,gainFront:l.rcGainFront,gainRear:l.rcGainRear},n}function mI(e,t){return{kinFront:Wk(e.front),kinRear:Wk(e.rear),steerFront:e.front.measured?void 0:ju(e.front,t)}}var Yk=new WeakMap;function Wk(e){let t=Yk.get(e);return t||Yk.set(e,t=ha(e)),t}function pI(e,t,r={}){return dI(e,t,r.front,r.rear)}function dI(e,t,r,n){let o=e.front.config.loadedRadius;if(!((mr(r??t.tireModel)??0)>0))return o;let a={...t,surveyedRadiusFront:o,surveyedRadiusRear:e.rear.config.loadedRadius};return Uu(a,r,n).front??o}var jk=new WeakMap;function ju(e,t=e.config.loadedRadius){let r=jk.get(e);r||(r=new Map,jk.set(e,r));let n=r.get(t);if(n)return n;let o=t===e.config.loadedRadius?void 0:{loadedRadius:t},a=wf(e,kt(e.config),void 0,void 0,void 0,void 0,o);return r.size>=4&&r.clear(),r.set(t,a),a}var Uk=new WeakMap;function fI(e){return Ke(e,{travelMin:-1,travelMax:1,steps:3}).samples[1].metrics.motionRatio??1}var Hu=e=>e.measured?Kk(e.measured):fI(e);function hI(e,t=e.front.config.loadedRadius){let r=()=>e.front.measured?void 0:ju(e.front,t);return{...bI(e),get steerFront(){return r()},get ackermannPct(){let n=r();return n?Cf(n,Rt(e.front),e.config.wheelbase):Number.NaN}}}function bI(e){let t=Uk.get(e);if(t)return t;let r=e.front.measured,n=e.rear.measured,a=!r||!n?jr(It(e),{heave:0,pitch:0,roll:0,steer:0}):null,s={wheelbase:e.config.wheelbase,trackFront:r?r.track:Rt(e.front),trackRear:n?n.track:Rt(e.rear),mrFront:Hu(e.front),mrRear:Hu(e.rear),rcFront:r?r.rollCentreHeight:a&&a.front.valid?a.front.heightAboveGround:0,rcRear:n?n.rollCentreHeight:a&&a.rear.valid?a.rear.heightAboveGround:0,rcGainFront:r||!a?0:La(a.front),rcGainRear:n||!a?0:La(a.rear),rcFrontValid:r?!0:!!a?.front.valid,rcRearValid:n?!0:!!a?.rear.valid};return Uk.set(e,s),s}var St={open:{kind:"open"},spool:{kind:"spool"},clutch:{kind:"clutch",preloadNm:30,rampDriveDeg:40,rampCoastDeg:50,faces:6,muClutch:.1,rFrictionMm:30.4,rRampMm:36},torsen:{kind:"torsen",tbrDrive:3,tbrCoast:3}},tM=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),br=(e,t,r,n=1/0)=>typeof e=="number"&&Number.isFinite(e)?Math.min(n,Math.max(r,e)):t;function co(e){if(tM(e))switch(e.kind){case"open":case"spool":return{kind:e.kind};case"clutch":{let t=St.clutch;return{kind:"clutch",preloadNm:br(e.preloadNm,t.preloadNm,0),rampDriveDeg:br(e.rampDriveDeg,t.rampDriveDeg,1,90),rampCoastDeg:br(e.rampCoastDeg,t.rampCoastDeg,1,90),faces:Math.round(br(e.faces,t.faces,0)),muClutch:br(e.muClutch,t.muClutch,0,1),rFrictionMm:br(e.rFrictionMm,t.rFrictionMm,1),rRampMm:br(e.rRampMm,t.rRampMm,1)}}case"torsen":{let t=St.torsen,r=br(e.preloadNm,0,0);return{kind:"torsen",tbrDrive:br(e.tbrDrive,t.tbrDrive,1),tbrCoast:br(e.tbrCoast,t.tbrCoast,1),...r>0?{preloadNm:r}:{}}}default:return}}function Xu(e){if(!tM(e))return;let t=co(e.front),r=co(e.rear);return t||r?{...t?{front:t}:{},...r?{rear:r}:{}}:void 0}function _i(e){let t=gn(e),r=n=>n>=2?"independent":n===1?"diff":"none";return{front:r(t.front),rear:r(t.rear)}}function Ni(e){if(!e.driveline)return;let t=_i(e),r=e.r_dyn.value,n=s=>{if(t[s]!=="diff")return;let i=co(e.driveline?.[s]);if(!(!i||i.kind==="independent"))return{kind:i.kind,drive:fi(i,"drive",r),coast:fi(i,"coast",r),hubs:fi(i,"hubs",r)}},o=n("front"),a=n("rear");return o||a?{...o?{front:o}:{},...a?{rear:a}:{}}:void 0}var gI={kind:{label:"Differential"},preloadNm:{label:"Preload",unit:"N\xB7m"},rampDriveDeg:{label:"Drive ramp",unit:"\xB0"},rampCoastDeg:{label:"Coast ramp",unit:"\xB0"},faces:{label:"Friction faces"},muClutch:{label:"Clutch friction \u03BC"},rFrictionMm:{label:"Friction radius",unit:"mm"},rRampMm:{label:"Ramp radius",unit:"mm"},tbrDrive:{label:"Drive bias ratio",unit:": 1"},tbrCoast:{label:"Coast bias ratio",unit:": 1"}},Jk=e=>{let t=e==="front"?"Front":"Rear";return Object.fromEntries(Object.entries(gI).map(([r,n])=>[`${e}.${r}`,{section:t,...n}]))},qu={...Jk("front"),...Jk("rear")},eM=e=>e.motorModel?.kind==="ice"?e.motorPlacement==="front"?"front":"rear":null;function rM(e,t){let r=eM(t);if(!(!r||eM(e)===r||t.driveline?.[r]))return{...t.driveline,[r]:{...St.clutch}}}function Yt(e,t,r,n){return e>0?!(r>0)||!Number.isFinite(r)?e:Math.max(1,e-t/r):n}function Qu(e,t,r){let n=Math.max(0,Math.min(1,r)),o=Yt(e.freeRadius,e.staticLoad,e.tyreRate,e.surveyed),a=Yt(t.freeRadius,t.staticLoad,t.tyreRate,t.surveyed);return n*o+(1-n)*a}function Ea(e,t,r){if(t===void 0||r===void 0||!Number.isFinite(t)||!Number.isFinite(r))return e;let n=r-t;return n===0?e:Math.max(1,e+n)}function Ur(e,t,r,n){if(!t||r===void 0||n===void 0||!Number.isFinite(r)||!Number.isFinite(n))return e;let o=n-r;return o===0?e:e+t*o}function Oi(e,t){if(!e)return xI(t);let r=t-fn(e,0).camber;return r?{...e,camber:e.camber.map(n=>n+r)}:e}function yI(e){return{kinFront:Oi(e.kinFront,Q(e,"camber_front_deg")),kinRear:Oi(e.kinRear,Q(e,"camber_rear_deg"))}}function xI(e){let t=[-40,0,40];return{travel:t,motionRatio:t.map(()=>1),camber:t.map(()=>e),toe:t.map(()=>0),damperLen:t.map(()=>0)}}var nM=9.81,oM=e=>e>1?e/100:e;function Ia(e,t,r){let n=t??e.tireModel??Js(),o=r??e.tireModelRear??n,a={grip:Q(e,"grip_scale"),stiffness:Q(e,"stiffness_scale")},s=tu(n,a);return{front:s,rear:o===n?s:tu(o,a)}}function gr(e,t,r){let n=Ia(e,t,r),o=Pe(n.front);return ft(n.rear===n.front?o:zl(o,Pe(n.rear)))}function Lb(e,t,r){let n=oM(e.front_mass_diss.value),o=Ia(e,t,r),a=Pe(o.front),s=o.rear===o.front?a:Pe(o.rear),i=t??e.tireModel,c=r??e.tireModelRear??i,l=e.m.value*nM*n/2,u=e.m.value*nM*(1-n)/2,m=(i?a.verticalStiffness():0)||Q(e,"tire_vertical_rate"),f=(c?s.verticalStiffness():0)||Q(e,"tire_vertical_rate"),p=mr(i)??0,d=mr(c)??0,h=e.surveyedRadiusFront&&e.surveyedRadiusRear?Qu({freeRadius:p,staticLoad:l,tyreRate:m,surveyed:e.surveyedRadiusFront},{freeRadius:d,staticLoad:u,tyreRate:f,surveyed:e.surveyedRadiusRear},n):void 0,b=e.surveyedRadiusFront?Yt(p,l,m,e.surveyedRadiusFront):void 0,g=e.surveyedRadiusRear?Yt(d,u,f,e.surveyedRadiusRear):void 0;return{ev:a,evR:s,Wf:l,Wr:u,tireRate:m,tireRateRear:f,tyreFreeRadius:p,tyreFreeRadiusRear:d,cgStandingRadius:h,standingFront:b,standingRear:g}}function Uu(e,t,r){let n=Lb(e,t,r);return{front:n.standingFront,rear:n.standingRear}}function aM(e,t,r){return Lb(e,t,r).cgStandingRadius}function gt(e,t,r){let n=oM(e.front_mass_diss.value),o=Q(e,"mr_front")||1,a=Q(e,"mr_rear")||1,{ev:s,evR:i,Wf:c,Wr:l,tireRate:u,tireRateRear:m,tyreFreeRadius:f,tyreFreeRadiusRear:p,cgStandingRadius:d,standingFront:h,standingRear:b}=Lb(e,t,r),g=pi(e),y=Ni(e),R=oo(e.damperModel,e.damperSetup,o,a,e.damperModelRear??e.damperModel),k=e.readouts?.damper_front===io,v=e.readouts?.damper_rear===io,x={rho:e.rho.value,area:e.A.value,cl:e.c_l.value,cw:e.c_w.value,copLongFront:1-Math.max(0,Math.min(1,Q(e,"cop_long"))),copHeight:Q(e,"cop_height"),...e.aeroModel?{model:e.aeroModel}:{},rideHeightFront:Q(e,"ride_height_front"),rideHeightRear:Q(e,"ride_height_rear")};return{massTotal:e.m.value,frontMassFrac:n,steeringSystem:e.steeringSystem,tv:Lu(e),cgHeight:Ea(Q(e,"cg_height"),e.cgReference?.standingRadius,d),...d!==void 0?{cgStandingRadius:d}:{},wheelbase:Q(e,"wheelbase"),trackFront:Q(e,"track_front"),trackRear:Q(e,"track_rear"),wheelRateFront:Q(e,"spring_front")*o*o,wheelRateRear:Q(e,"spring_rear")*a*a,tireRate:u,...m!==u?{tireRateRear:m}:{},tireDamping:Q(e,"tire_vertical_damping"),arbFront:Q(e,"arb_front"),arbRear:Q(e,"arb_rear"),brakeBalanceFront:g.balanceFront,brakes:g,...y?{driveline:y}:{},heaveSpringFront:Q(e,"heave_spring_front"),heaveSpringRear:Q(e,"heave_spring_rear"),unsprungPerCorner:Q(e,"unsprung_mass"),unsprungCgHeight:RI(e,{Wf:c,Wr:l,tireRate:u,tireRateRear:m,tyreFreeRadius:f,tyreFreeRadiusRear:p,standingFront:h,standingRear:b}),tyreFreeRadius:f,...p!==f?{tyreFreeRadiusRear:p}:{},rcHeightFront:Ur(Q(e,"rc_front"),e.rcRoad?.gainFront,e.rcRoad?.radiusFront,h),rcHeightRear:Ur(Q(e,"rc_rear"),e.rcRoad?.gainRear,e.rcRoad?.radiusRear,b),corneringStiffnessFront:s.corneringStiffness(c),corneringStiffnessRear:i.corneringStiffness(l),damperFront:R?.front&&!k?R.front.rate:Q(e,"damper_front")*o*o,damperRear:R?.rear&&!v?R.rear.rate:Q(e,"damper_rear")*a*a,...R?.front&&!k?{damperCurveFront:R.front.curve}:{},...R?.rear&&!v?{damperCurveRear:R.rear.curve}:{},aero:x,ackermannPct:Q(e,"ackermann_pct"),toeFrontDeg:Q(e,"toe_front_deg"),toeRearDeg:Q(e,"toe_rear_deg"),yawInertia:Q(e,"I_yaw"),steerFront:e.steerFront,...yI(e)}}function RI(e,t){let r=(a,s,i,c)=>a??(s>0?Yt(s,i,c,s):void 0),n=r(t.standingFront,t.tyreFreeRadius,t.Wf,t.tireRate),o=r(t.standingRear,t.tyreFreeRadiusRear,t.Wr,t.tireRateRear);return n!==void 0&&o!==void 0?.5*(n+o):n??o??e.r_dyn.value*1e3}var Zu={capacity:"the battery model\u2019s pack charge \u2014 cells in parallel \xD7 cell capacity",ocv:"the battery model\u2019s pack voltage at full charge"};function sM(e,t=e.batteryModel){if(!t)return e;let r=Fr(t),n=(o,a)=>({...o,value:a});return{...e,capacity:n(e.capacity,r.capacityAh),ocv:n(e.ocv,r.voltageAtFull)}}var cM={damper_front:`the damper part sets it: its front curve at ${kn} mm/s`,damper_rear:`the damper part sets it (the rear's own, where the car names one): its rear curve at ${kn} mm/s`};function Ju(e){let t=!!(e.damperModelId||e.damperModel),r=t||!!(e.damperModelIdRear||e.damperModelRear);return{...t?{damper_front:cM.damper_front}:{},...r?{damper_rear:cM.damper_rear}:{}}}function lM(e,t=e.damperModel,r=e.damperModelRear??t){if(!t&&!r)return e;let n=Q(e,"mr_front")||1,o=Q(e,"mr_rear")||1,a=oo(t,e.damperSetup,n,o,r);if(!a)return e;let s=(c,l,u)=>({...c??{label:l,unit:"N\xB7s/mm"},value:u}),i={...e};return a.front&&e.readouts?.damper_front!==io&&(i.damper_front=s(e.damper_front,"damper front",a.front.rate/(n*n))),a.rear&&e.readouts?.damper_rear!==io&&(i.damper_rear=s(e.damper_rear,"damper rear",a.rear.rate/(o*o))),i}var uM={how:"scripts/paramTiers.ts: each row \xB120 % (switches flipped, springs on the suspension), first car of every gallery template, largest change to any event time, % of it",templates:["fs-ev-comparison","fs-ev-single","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor","formula-1","touring-car","street-car","cup-car","stock-car","hill-climb","suspension","direct-coilover","pushrod","pullrod","third-spring","mcpherson-strut","tyre-study"],rows:{endurance_reserve:{group:"Powertrain",score:"infinite",byTemplate:{"fs-ev-comparison":"infinite","fs-ev-single":"infinite","fs-combustion":null,"fs-ev-awd":0,"fs-ev-rwd-hubs":"infinite","fs-ev-one-motor":"infinite","formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:0,"direct-coilover":null,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":null,"tyre-study":"infinite"}},gear_ratio:{group:"Powertrain",score:11.9893,byTemplate:{"fs-ev-comparison":11.9893,"fs-ev-single":11.9893,"fs-combustion":5.6255,"fs-ev-awd":5.8819,"fs-ev-rwd-hubs":11.5358,"fs-ev-one-motor":7.2758,"formula-1":.2473,"touring-car":.2195,"street-car":.0998,"cup-car":.2431,"stock-car":.0645,"hill-climb":3.1703,suspension:1.8984,"direct-coilover":.2195,pushrod:1.9001,pullrod:1.9126,"third-spring":1.9001,"mcpherson-strut":.111,"tyre-study":11.9893}},driven_wheels:{group:"Powertrain",score:11.9893,byTemplate:{"fs-ev-comparison":11.9893,"fs-ev-single":11.9893,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:1.9216,"direct-coilover":0,pushrod:1.9171,pullrod:1.919,"third-spring":1.9171,"mcpherson-strut":0,"tyre-study":11.9893}},power_scale:{group:"Powertrain",score:11.9893,byTemplate:{"fs-ev-comparison":11.9893,"fs-ev-single":11.9893,"fs-combustion":10.2883,"fs-ev-awd":4.2843,"fs-ev-rwd-hubs":11.6138,"fs-ev-one-motor":7.2758,"formula-1":2.6682,"touring-car":2.5337,"street-car":1.938,"cup-car":2.6155,"stock-car":1.2193,"hill-climb":1.869,suspension:1.9216,"direct-coilover":2.5337,pushrod:1.9171,pullrod:1.919,"third-spring":1.9171,"mcpherson-strut":1.9778,"tyre-study":11.9893}},grip_scale:{group:"Tyres",score:11.4886,byTemplate:{"fs-ev-comparison":10.9135,"fs-ev-single":10.9135,"fs-combustion":11.4886,"fs-ev-awd":11.3513,"fs-ev-rwd-hubs":11.3513,"fs-ev-one-motor":11.3905,"formula-1":10.9225,"touring-car":7.4484,"street-car":7.2578,"cup-car":7.1946,"stock-car":10.4642,"hill-climb":9.5384,suspension:8.3679,"direct-coilover":7.4484,pushrod:8.3929,pullrod:8.3807,"third-spring":8.3929,"mcpherson-strut":7.35,"tyre-study":10.9135}},front_mass_diss:{group:"Mass & chassis",score:10.3816,byTemplate:{"fs-ev-comparison":1.1854,"fs-ev-single":1.1854,"fs-combustion":1.5398,"fs-ev-awd":1.9682,"fs-ev-rwd-hubs":1.9682,"fs-ev-one-motor":4.5048,"formula-1":5.2182,"touring-car":1.241,"street-car":3.5067,"cup-car":.7277,"stock-car":2.2367,"hill-climb":10.3816,suspension:.5046,"direct-coilover":1.241,pushrod:.4796,pullrod:.4587,"third-spring":.4796,"mcpherson-strut":3.4131,"tyre-study":1.1854}},m:{group:"Mass & chassis",score:9.7815,byTemplate:{"fs-ev-comparison":9.7815,"fs-ev-single":9.7815,"fs-combustion":7.2245,"fs-ev-awd":5.6765,"fs-ev-rwd-hubs":9.2239,"fs-ev-one-motor":7.0296,"formula-1":5.3736,"touring-car":3.7044,"street-car":1.9146,"cup-car":2.6724,"stock-car":3.7623,"hill-climb":5.4157,suspension:3.8549,"direct-coilover":3.7044,pushrod:3.8507,pullrod:3.8527,"third-spring":3.8507,"mcpherson-strut":1.9399,"tyre-study":9.7815}},cop_long:{group:"Aerodynamics",score:6.6543,byTemplate:{"fs-ev-comparison":1.032,"fs-ev-single":1.032,"fs-combustion":1.0669,"fs-ev-awd":1.0452,"fs-ev-rwd-hubs":1.0452,"fs-ev-one-motor":1.0521,"formula-1":5.9878,"touring-car":.1327,"street-car":.0018,"cup-car":.2696,"stock-car":.6469,"hill-climb":6.6543,suspension:.3644,"direct-coilover":.1327,pushrod:.3575,pullrod:.355,"third-spring":.3575,"mcpherson-strut":.0072,"tyre-study":1.032}},front_aero_diss:{group:"Aerodynamics",score:5.2168,byTemplate:{"fs-ev-comparison":.9064,"fs-ev-single":.9064,"fs-combustion":.8657,"fs-ev-awd":.8967,"fs-ev-rwd-hubs":.8967,"fs-ev-one-motor":.8574,"formula-1":4.2912,"touring-car":.0708,"street-car":.0018,"cup-car":.2207,"stock-car":.5291,"hill-climb":5.2168,suspension:.2835,"direct-coilover":.0708,pushrod:.2831,pullrod:.2823,"third-spring":.2831,"mcpherson-strut":.0072,"tyre-study":.9064}},power_limit_kw:{group:"Powertrain",score:4.5916,byTemplate:{"fs-ev-comparison":.4828,"fs-ev-single":.4828,"fs-combustion":null,"fs-ev-awd":4.5916,"fs-ev-rwd-hubs":.5453,"fs-ev-one-motor":3.6198,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:.0626,"direct-coilover":null,pushrod:.0625,pullrod:.0626,"third-spring":.0625,"mcpherson-strut":null,"tyre-study":.4828}},soc:{group:"Powertrain",score:3.5618,byTemplate:{"fs-ev-comparison":3.2245,"fs-ev-single":3.2245,"fs-combustion":0,"fs-ev-awd":1.6179,"fs-ev-rwd-hubs":3.3095,"fs-ev-one-motor":3.5618,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":3.2245}},effi_pgb:{group:"Powertrain",score:3.5269,byTemplate:{"fs-ev-comparison":3.5269,"fs-ev-single":3.5269,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:.0626,"direct-coilover":0,pushrod:.0625,pullrod:.0626,"third-spring":.0625,"mcpherson-strut":0,"tyre-study":3.5269}},c_l:{group:"Aerodynamics",score:3.4342,byTemplate:{"fs-ev-comparison":.9751,"fs-ev-single":.9751,"fs-combustion":.9539,"fs-ev-awd":1.0777,"fs-ev-rwd-hubs":.9886,"fs-ev-one-motor":1.0797,"formula-1":3.4342,"touring-car":.8979,"street-car":.0715,"cup-car":.2158,"stock-car":.5467,"hill-climb":1.2705,suspension:.9751,"direct-coilover":.8979,pushrod:.9734,pullrod:.9708,"third-spring":.9734,"mcpherson-strut":.0704,"tyre-study":.9751}},ocv:{group:"Powertrain",score:3.3244,byTemplate:{"fs-ev-comparison":3.0446,"fs-ev-single":3.0446,"fs-combustion":0,"fs-ev-awd":1.4595,"fs-ev-rwd-hubs":3.1854,"fs-ev-one-motor":3.3244,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":3.0446}},capacity:{group:"Powertrain",score:3.3244,byTemplate:{"fs-ev-comparison":3.0446,"fs-ev-single":3.0446,"fs-combustion":0,"fs-ev-awd":1.4595,"fs-ev-rwd-hubs":3.1854,"fs-ev-one-motor":3.3244,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":3.0446}},A:{group:"Aerodynamics",score:2.3707,byTemplate:{"fs-ev-comparison":.802,"fs-ev-single":.802,"fs-combustion":.7928,"fs-ev-awd":.9333,"fs-ev-rwd-hubs":.7926,"fs-ev-one-motor":.961,"formula-1":2.3707,"touring-car":.6374,"street-car":.4904,"cup-car":.2428,"stock-car":.1932,"hill-climb":1.1486,suspension:.802,"direct-coilover":.6374,pushrod:.7991,pullrod:.7982,"third-spring":.7991,"mcpherson-strut":.4873,"tyre-study":.802}},rho:{group:"Aerodynamics",score:2.3707,byTemplate:{"fs-ev-comparison":.802,"fs-ev-single":.802,"fs-combustion":.7928,"fs-ev-awd":.9333,"fs-ev-rwd-hubs":.7926,"fs-ev-one-motor":.961,"formula-1":2.3707,"touring-car":.6374,"street-car":.4904,"cup-car":.2428,"stock-car":.1932,"hill-climb":0,suspension:.802,"direct-coilover":.6374,pushrod:.7991,pullrod:.7982,"third-spring":.7991,"mcpherson-strut":.4873,"tyre-study":.802}},cg_height:{group:"Mass & chassis",score:2.2005,byTemplate:{"fs-ev-comparison":1.8282,"fs-ev-single":1.8282,"fs-combustion":1.6978,"fs-ev-awd":2.2005,"fs-ev-rwd-hubs":1.8919,"fs-ev-one-motor":1.9269,"formula-1":.6248,"touring-car":1.2858,"street-car":1.4681,"cup-car":.992,"stock-car":1.2052,"hill-climb":.6037,suspension:1.8282,"direct-coilover":1.2858,pushrod:1.8142,pullrod:1.8229,"third-spring":1.8142,"mcpherson-strut":1.7176,"tyre-study":1.8282}},l_to_d_ratio:{group:"Aerodynamics",score:1.4351,byTemplate:{"fs-ev-comparison":.7905,"fs-ev-single":.7905,"fs-combustion":.6962,"fs-ev-awd":.5843,"fs-ev-rwd-hubs":.8444,"fs-ev-one-motor":.9611,"formula-1":1.4351,"touring-car":.3671,"street-car":.528,"cup-car":.5631,"stock-car":.4634,"hill-climb":.2349,suspension:.2456,"direct-coilover":.3671,pushrod:.2491,pullrod:.2456,"third-spring":.2491,"mcpherson-strut":.5265,"tyre-study":.7905}},tv_enabled:{group:"Torque vectoring",score:1.2381,byTemplate:{"fs-ev-comparison":1.2381,"fs-ev-single":1.2381,"fs-combustion":0,"fs-ev-awd":1.2293,"fs-ev-rwd-hubs":1.2293,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":.1209,"cup-car":.1617,"stock-car":0,"hill-climb":9e-4,suspension:.3086,"direct-coilover":0,pushrod:.2933,pullrod:.3089,"third-spring":.2933,"mcpherson-strut":.1326,"tyre-study":1.2381}},c_w:{group:"Aerodynamics",score:1.1499,byTemplate:{"fs-ev-comparison":.6319,"fs-ev-single":.6319,"fs-combustion":.5577,"fs-ev-awd":.462,"fs-ev-rwd-hubs":.6559,"fs-ev-one-motor":.7504,"formula-1":1.1499,"touring-car":.2914,"street-car":.4211,"cup-car":.4486,"stock-car":.3694,"hill-climb":.1625,suspension:.1945,"direct-coilover":.2914,pushrod:.1979,pullrod:.1948,"third-spring":.1979,"mcpherson-strut":.4196,"tyre-study":.6319}},brake_balance:{group:"Brakes",score:1.0132,byTemplate:{"fs-ev-comparison":.8303,"fs-ev-single":.8303,"fs-combustion":.6932,"fs-ev-awd":.9772,"fs-ev-rwd-hubs":.8148,"fs-ev-one-motor":1.0132,"formula-1":.97,"touring-car":.9585,"street-car":.7184,"cup-car":.1468,"stock-car":.0764,"hill-climb":.9096,suspension:.8303,"direct-coilover":.9585,pushrod:.8578,pullrod:.8454,"third-spring":.8578,"mcpherson-strut":.7099,"tyre-study":.8303}},stiffness_scale:{group:"Tyres",score:.871,byTemplate:{"fs-ev-comparison":.5088,"fs-ev-single":.5088,"fs-combustion":.4874,"fs-ev-awd":.3745,"fs-ev-rwd-hubs":.4753,"fs-ev-one-motor":.5706,"formula-1":.5776,"touring-car":.4346,"street-car":.1077,"cup-car":.4012,"stock-car":.1613,"hill-climb":.871,suspension:.5088,"direct-coilover":.4346,pushrod:.5253,pullrod:.5172,"third-spring":.5253,"mcpherson-strut":.1518,"tyre-study":.5088}},cop_height:{group:"Aerodynamics",score:.2837,byTemplate:{"fs-ev-comparison":.155,"fs-ev-single":.155,"fs-combustion":.1546,"fs-ev-awd":.1557,"fs-ev-rwd-hubs":.1557,"fs-ev-one-motor":.1542,"formula-1":.1173,"touring-car":.0072,"street-car":.0023,"cup-car":.0745,"stock-car":.1568,"hill-climb":.2837,suspension:.0421,"direct-coilover":.0072,pushrod:.0437,pullrod:.04,"third-spring":.0437,"mcpherson-strut":.0076,"tyre-study":.155}},spring_rear:{group:"Suspension",score:.2822,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":.0355,"touring-car":.1169,"street-car":.2242,"cup-car":.0902,"stock-car":.2822,"hill-climb":.1929,suspension:0,"direct-coilover":.1169,pushrod:.1142,pullrod:.2148,"third-spring":.1142,"mcpherson-strut":.1786,"tyre-study":0}},spring_front:{group:"Suspension",score:.2388,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":.0189,"touring-car":.0958,"street-car":.2388,"cup-car":.1462,"stock-car":.1719,"hill-climb":.1873,suspension:0,"direct-coilover":.0958,pushrod:.1257,pullrod:.0612,"third-spring":.1257,"mcpherson-strut":.1911,"tyre-study":0}},arb_front:{group:"Suspension",score:.1792,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":.0235,"touring-car":.0589,"street-car":.1792,"cup-car":.0215,"stock-car":.0926,"hill-climb":.1095,suspension:null,"direct-coilover":.0589,pushrod:.0455,pullrod:.049,"third-spring":.0455,"mcpherson-strut":.1435,"tyre-study":null}},fr_0:{group:"Tyres",score:.158,byTemplate:{"fs-ev-comparison":.158,"fs-ev-single":.158,"fs-combustion":.1097,"fs-ev-awd":.0708,"fs-ev-rwd-hubs":.1442,"fs-ev-one-motor":.1168,"formula-1":.07,"touring-car":.0492,"street-car":.1006,"cup-car":.065,"stock-car":.0262,"hill-climb":.0334,suspension:.0217,"direct-coilover":.0492,pushrod:.0229,pullrod:.0223,"third-spring":.0229,"mcpherson-strut":.0989,"tyre-study":.158}},arb_rear:{group:"Suspension",score:.1047,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":.0224,"touring-car":.0365,"street-car":.0832,"cup-car":.1047,"stock-car":.0436,"hill-climb":.0734,suspension:null,"direct-coilover":.0365,pushrod:.0411,pullrod:.0332,"third-spring":.0411,"mcpherson-strut":.0643,"tyre-study":null}},unsprung_mass:{group:"Mass & chassis",score:.102,byTemplate:{"fs-ev-comparison":.0477,"fs-ev-single":.0477,"fs-combustion":.0512,"fs-ev-awd":.0545,"fs-ev-rwd-hubs":.0514,"fs-ev-one-motor":.0799,"formula-1":.0313,"touring-car":.0471,"street-car":.102,"cup-car":.0315,"stock-car":.042,"hill-climb":.0278,suspension:.0477,"direct-coilover":.0471,pushrod:.0452,pullrod:.0468,"third-spring":.0452,"mcpherson-strut":.0876,"tyre-study":.0477}},camber_front_deg:{group:"Steering & alignment",score:.0576,byTemplate:{"fs-ev-comparison":.0065,"fs-ev-single":.0065,"fs-combustion":.008,"fs-ev-awd":.0075,"fs-ev-rwd-hubs":.0075,"fs-ev-one-motor":.0098,"formula-1":.0358,"touring-car":.0272,"street-car":.0025,"cup-car":.0191,"stock-car":.0576,"hill-climb":.0389,suspension:.0019,"direct-coilover":.0272,pushrod:.0017,pullrod:.0016,"third-spring":.0017,"mcpherson-strut":.002,"tyre-study":.0065}},camber_rear_deg:{group:"Steering & alignment",score:.0262,byTemplate:{"fs-ev-comparison":.0081,"fs-ev-single":.0081,"fs-combustion":.0085,"fs-ev-awd":.0054,"fs-ev-rwd-hubs":.0096,"fs-ev-one-motor":.0097,"formula-1":.0028,"touring-car":.0106,"street-car":8e-4,"cup-car":5e-4,"stock-car":.0035,"hill-climb":.0262,suspension:.0081,"direct-coilover":.0106,pushrod:.0082,pullrod:.0083,"third-spring":.0082,"mcpherson-strut":3e-4,"tyre-study":.0081}},I_yaw:{group:"Mass & chassis",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},I_roll:{group:"Mass & chassis",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},I_pitch:{group:"Mass & chassis",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},ride_height_front:{group:"Aerodynamics",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},ride_height_rear:{group:"Aerodynamics",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tire_vertical_rate:{group:"Tyres",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tire_vertical_damping:{group:"Tyres",score:0,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":0,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},r_dyn:{group:"Tyres",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},damper_front:{group:"Suspension",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},damper_rear:{group:"Suspension",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_kp:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_ff_low:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_ff_high:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_v_low:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_v_high:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},wheelbase:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},track_front:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},track_rear:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},rc_front:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},rc_rear:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},I_wheel:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},I_rotor:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},v_limit_endurance:{group:"Powertrain",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},mr_front:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},mr_rear:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},heave_spring_front:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},heave_spring_rear:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},toe_front_deg:{group:"Steering & alignment",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},toe_rear_deg:{group:"Steering & alignment",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},ackermann_pct:{group:"Steering & alignment",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}}}};function Xr(e){return!!e&&typeof e=="object"&&"value"in e&&"label"in e}var SI={Batteriekapazit\u00E4t:"pack capacity",Rollwiderstandsbeiwert:"rolling-resistance coefficient"},pM=e=>SI[e]??e;function em(e){let t=[];for(let r of Object.keys(e)){if(r==="motor"||r==="name")continue;let n=e[r];Xr(n)&&t.push({key:r,label:pM(n.label),value:n.value,unit:n.unit})}return t}var AI=[{title:"Mass & chassis",keys:["m","front_mass_diss","cg_height","unsprung_mass","wheelbase","track_front","track_rear","rc_front","rc_rear","I_yaw","I_roll","I_pitch","I_wheel","I_rotor"]},{title:"Aerodynamics",keys:["A","c_l","c_w","l_to_d_ratio","front_aero_diss","cop_long","cop_height","ride_height_front","ride_height_rear","rho"]},{title:"Tyres",keys:["grip_scale","stiffness_scale","tire_vertical_rate","tire_vertical_damping","fr_0","r_dyn"]},{title:"Powertrain",keys:["gear_ratio","driven_wheels","effi_pgb","power_scale","power_limit_kw","v_limit_endurance","endurance_reserve","capacity","ocv","soc"]},{title:"Suspension",keys:["spring_front","spring_rear","mr_front","mr_rear","arb_front","arb_rear","heave_spring_front","heave_spring_rear","damper_front","damper_rear"]},{title:"Steering & alignment",keys:["camber_front_deg","camber_rear_deg","toe_front_deg","toe_rear_deg","ackermann_pct"]},{title:"Brakes",keys:["brake_balance"]},{title:"Torque vectoring",keys:["tv_enabled","tv_kp","tv_ff_low","tv_ff_high","tv_v_low","tv_v_high"]}],FI=.5,mM=e=>e==="infinite"?1/0:typeof e=="number"?e:null,wI=e=>/front/.test(e)?e.replace("front","rear"):/rear/.test(e)?e.replace("rear","front"):null,X7=(()=>{let e=uM.rows,t=o=>{let a=wI(o),s=mM(e[o]?.score),i=a&&e[a]?mM(e[a].score):null;return s==null?i:i==null?s:Math.max(s,i)},r=new Set,n=new Map;for(let[o,a]of Object.entries(e)){let s=t(o);s!=null&&(s>=FI&&r.add(o),n.set(a.group,Math.max(n.get(a.group)??0,s)))}for(let[o,a]of Object.entries(e)){let s=t(o);s!=null&&s>0&&s===n.get(a.group)&&r.add(o)}return r})();var Db={wheelbase:"set by the axle positions in Kinematics",track_front:"twice the front wheel-centre Y",track_rear:"twice the rear wheel-centre Y",rc_front:"solved from the front wishbones, on the fitted tyre",rc_rear:"solved from the rear wishbones, on the fitted tyre",mr_front:"damper travel per mm of front wheel travel, from the linkage",mr_rear:"damper travel per mm of rear wheel travel, from the linkage",spring_front:"the front corner spring rate, stored on the suspension the car runs",spring_rear:"the rear corner spring rate, stored on the suspension the car runs",ackermann_pct:"solved from the rack and tie rods, read near centre"};function dM(e){let t=new Map;for(let a of em(e))t.set(a.key,a);let r=new Set,n=[];for(let a of AI){let s=[];for(let i of a.keys){let c=t.get(i);c&&(s.push(c),r.add(i))}s.length&&n.push({title:a.title,rows:s})}let o=em(e).filter(a=>!r.has(a.key));return o.length&&n.push({title:"Other",rows:o}),n}var Eb={A:"the aero model's reference area",c_l:"read off the aero model at the ride heights",c_w:"read off the aero model at the ride heights",l_to_d_ratio:"read off the aero model at the ride heights",front_aero_diss:"the aero model's front and rear coefficients set the balance",cop_long:"the aero model's front and rear coefficients set the balance"},Ib={ride_height_front:"reaches nothing until an aero model is attached at the head of the Aerodynamics group",ride_height_rear:"reaches nothing until an aero model is attached at the head of the Aerodynamics group"},fM=e=>!!(e.aeroModelId||e.aeroModel);function CI(e){let t=n=>n!=null&&n.design.kind!=="none",r={};return t(e.arbFrontDesign)&&(r.arb_front="the front anti-roll bar design sets it"),t(e.arbRearDesign)&&(r.arb_rear="the rear anti-roll bar design sets it"),t(e.heaveFrontDesign)&&(r.heave_spring_front="the front third-spring design sets it"),t(e.heaveRearDesign)&&(r.heave_spring_rear="the rear third-spring design sets it"),r}var TI=e=>!!(e.batteryModelId||e.batteryModel);function PI(e,t){let r={};return t.geometry&&Object.assign(r,Db,CI(e)),fM(e)&&Object.assign(r,Eb),TI(e)&&Object.assign(r,Zu),Object.assign(r,Ju(e)),e.readouts&&Object.assign(r,e.readouts),r}function hM(e,t){let r=PI(e,t);return fM(e)||Object.assign(r,Ib),r}function _b(e){let t=e.cop_long;return Xr(t)?1-t.value:.5}function LI(e,t){let r=e.front_aero_diss,n=e.cop_long;!Xr(r)||!Xr(n)||(t===r.label?n.value=1-r.value:t===n.label&&(r.value=1-n.value))}function DI(e,t){LI(e,t);let r=e.c_l,n=e.c_w,o=e.l_to_d_ratio;!Xr(r)||!Xr(n)||(t===r.label||t===n.label?Xr(o)&&n.value!==0&&(o.value=r.value/n.value):Xr(o)&&t===o.label&&o.value!==0&&(n.value=r.value/o.value))}function tm(e,t,r){let n=!1;for(let o of Object.keys(e)){if(o==="motor"||o==="name")continue;let a=e[o];if(Xr(a)&&pM(a.label)===t){a.value=r,n=!0;break}}return n&&DI(e,t),n}function rm(e,t,r=0,n,o){let a=()=>({cl:e.c_l.value,cw:e.c_w.value,frontShare:_b(e),A:e.A.value,platform:null});if(!e.aeroModel)return a();let s=Cr(n??gt(e),t,r,o);if(!s)return a();let i=s.clFront+s.clRear;return{cl:i,cw:s.cd,frontShare:i!==0?s.clFront/i:_b(e),A:s.area,platform:s}}var bM=e=>typeof e=="object"&&e!==null&&typeof e.value=="number"&&typeof e.label=="string";function gM(e,t=e.aeroModel){if(!t)return e;let r=an(t,{wheelbase:Q(e,"wheelbase")}).at(Q(e,"ride_height_front"),Q(e,"ride_height_rear")),{cl:n,balanceFront:o}=Cd(r),a=(i,c,l)=>({...i??c,value:l}),s={...e,A:a(e.A,e.A,t.area),c_l:a(e.c_l,e.c_l,n),c_w:a(e.c_w,e.c_w,r.cd),front_aero_diss:a(e.front_aero_diss,e.front_aero_diss,o),cop_long:a(bM(e.cop_long)?e.cop_long:void 0,fr.cop_long,1-o)};return bM(e.l_to_d_ratio)&&(s.l_to_d_ratio={...e.l_to_d_ratio,value:r.cd!==0?n/r.cd:0}),s}var Vi={dsTarget:.25,accelStep:.25,vTol:.002,scanSteps:24,seamIters:8,fitSpacing:1},EI=32;function yM(e,t,r){let n=Math.round(e/t);return Math.max(1,Math.min(Number.isFinite(n)?n:1,Math.floor(r/EI)||1))}function ct(e){let t=Vi,r=(n,o,a)=>{let s=Number(n);return Number.isFinite(s)&&s>=a?s:o};return{dsTarget:r(e?.dsTarget,t.dsTarget,.001),accelStep:r(e?.accelStep,t.accelStep,.001),vTol:r(e?.vTol,t.vTol,1e-6),scanSteps:Math.max(4,Math.round(r(e?.scanSteps,t.scanSteps,4))),seamIters:Math.max(1,Math.round(r(e?.seamIters,t.seamIters,1))),fitSpacing:r(e?.fitSpacing,t.fitSpacing,0)}}var xM=Math.PI/180,nm=.02,RM=new WeakMap;function Bi(e){let t=RM.get(e);if(t!==void 0)return t;let r=e.npts,n=new Array(r),o=new Array(r),a=!1;for(let i=0;i<r;i++){let c=(e.gradient?.[i]??0)*xM,l=(e.bank?.[i]??0)*xM,u=e.verticalCurvature?.[i]??0;n[i]=c===0&&l===0?1:Math.cos(c)*Math.cos(l),o[i]=(u-e.curvature[i]*Math.sin(l))/9.81,(n[i]!==1||o[i]!==0)&&(a=!0)}let s=a?{n0:n,k:o}:null;return RM.set(e,s),s}function om(e,t,r){return e.n0[t]+e.k[t]*r*r}function vM(e,t){return e.k[t]<0?Math.sqrt(Math.max(0,e.n0[t])/-e.k[t]):1/0}function kM(e,t){if(!e)return null;let r=1/0,n=-1/0;for(let o=0;o<e.n0.length;o++){let a=om(e,o,t[o]??0);a<r&&(r=a),a>n&&(n=a)}return r>=1-nm&&n<=1+nm?null:{lo:r,hi:n}}var _a=[.1,.25,.5,.75,1,1.25,1.5,2,2.5];function MM(e){let t=e.lo>=1-nm?1:1-1.25*(1-e.lo)-.05,r=e.hi<=1+nm?1:1+1.25*(e.hi-1)+.05,n=[..._a].reverse().find(a=>a<=t)??_a[0],o=_a.find(a=>a>=r)??_a[_a.length-1];return _a.filter(a=>a>=n&&a<=o)}function Nb(e,t,r){return r<1?Math.max(e,t):Math.min(e,t)}function SM(e,t,r,n){let o=e.n0.length;return a=>{let s=n?n(a):r,i=a%o;if(e.n0[i]===1&&e.k[i]===0)return s;let c=e.n0[i],l=e.k[i],u=m=>c+l*m*m;return n?{vMax:s.vMax,axAccel:(m,f,p=1,d=1)=>s.axAccel(m,f,p,d)+t.axAccel(u(m),m,f,p,d)-r.axAccel(m,f,p,d),axDecel:(m,f,p=1,d=1)=>{let h=b=>s.axDecel(m,f,p,b)+t.axDecel(u(m),m,f,p,b)-r.axDecel(m,f,p,b);return d===1?h(1):Nb(h(d),h(1),d)},ay:(m,f,p=1)=>Math.max(0,s.ay(m,f,p)+t.ay(u(m),m,f,p)-r.ay(m,f,p)),scrub:(m,f,p=1)=>(s.scrub?.(m,f,p)??0)+t.scrub(u(m),m,f,p)-(r.scrub?.(m,f,p)??0)}:{vMax:s.vMax,axAccel:(m,f,p=1,d=1)=>t.axAccel(u(m),m,f,p,d),axDecel:(m,f,p=1,d=1)=>t.axDecel(u(m),m,f,p,d),ay:(m,f,p=1)=>t.ay(u(m),m,f,p),scrub:(m,f,p=1)=>t.scrub(u(m),m,f,p)}}}function am(e,t,r,n,o){let a=e.length,s=r?a:a-1,i=F=>r?(F+1)%a:F+1,{brakeAhead:c,apexAhead:l}=II(e,t,r),u=new Array(a),m=new Array(a),f=new Array(a),p=new Array(a).fill(0),d=0,h=0,b=0,g=Math.max(0,Math.min(1,n.kept)),y=g>=1?0:n.up,R=g>=1?0:n.down,k=4*y*(1-g),v=F=>{let{v:w,gear:T,tau:P,target:A}=F;d=0,h=0,b=0;for(let S=0;S<s;S++){let C=i(S),L=e[C];for(let O=0;P<=0&&O<n.count;O++){let N=T;if(w<L-1e-9?n.best(w)>T&&(n.rpm(w,T)>=n.limitRpm||c[S]>=w*k)?N=T+1:T>0&&w<n.vIdle(T)&&(N=T-1):L<w-1e-9&&T>0&&n.best(l[S])<T&&n.rpm(w,T-1)<=n.limitRpm&&(N=T-1),N===T)break;A=N,N>T?d++:h++,P=N>T?y:R,P<=0&&(T=A)}u[S]=w,m[S]=T+1,f[S]=n.rpm(w,T);let D=P>0;p[S]=D?1:0;let I=L;if(!D)w<L&&(I=Math.min(L,Math.sqrt(Math.max(0,w*w+2*o(S,w,n.share(w,T))*t[S]))));else if(w<L){let O=o(S,w,g>0?g*n.share(w,T):0),N=Math.min(L,Math.sqrt(Math.max(0,w*w+2*O*t[S]))),z=w+N>0?2*t[S]/(w+N):1/0;if(z<=P)I=N,b+=z,P-=z;else{let E=Math.min(L,Math.max(0,w+O*P)),_=Math.max(0,t[S]-(w+E)*.5*P);b+=P,P=0,T=A,I=Math.min(L,Math.sqrt(Math.max(0,E*E+2*o(S,E,n.share(E,T))*_)))}}else{let O=w+I>0?2*t[S]/(w+I):0;b+=Math.min(O,P),P-=O,P<=0&&(T=A)}w=I}return{v:w,gear:T,tau:P,target:A}},x=n.best(e[0]),M={v:e[0],gear:x,tau:0,target:x};if(r)for(let F=0;F<6;F++){let w=v(M),T=Math.abs(w.v-M.v)<=1e-9&&w.gear===M.gear&&w.target===M.target&&Math.abs(w.tau-M.tau)<=1e-12;if(M=w,T)break}else{let F=v(M);u[a-1]=F.v,m[a-1]=F.gear+1,f[a-1]=n.rpm(F.v,F.gear),p[a-1]=F.tau>0?1:0}return{v:u,gear:m,rpm:f,shifting:p,upshifts:d,downshifts:h,gapTime:b}}function II(e,t,r){let n=e.length,o=new Array(n).fill(1/0),a=e.slice(),s=1/0,i=e[n-1],c=r?2*n-1:n-2;for(let l=c;l>=0;l--){let u=l%n,m=r?(u+1)%n:u+1,f=e[m]<e[u]-1e-9;s=f?0:s+t[u],i=f?Math.min(i,e[m]):e[u],l<n&&(o[u]=s,a[u]=i)}return{brakeAhead:o,apexAhead:a}}var Ob=.001,Vb=9.81,$i=(e,t)=>sm(e?.gradient?.[t]??0);function sm(e){return e===0?0:-Vb*Math.sin(e*Math.PI/180)}function Sn(e,t){let r=new Array(t);for(let n=0;n<t;n++)r[n]=sm(e?.[n]??0);return r}var Mn=(e,t)=>{let r=e?.mu?.[t];return r!=null&&r>0?r:1},lo=(e,t)=>e?.bank?.[t]??0;function _I(e,t,r,n,o,a){let s=e.ay(t,r,Mn(o,a)),i=lo(o,a);if(!i)return s;let c=i*Math.PI/180,l=n===0?0:-Math.sign(n)*Vb*Math.sin(c);return Math.max(0,(s+l)/Math.cos(c))}function He(e,t){if(!t)return e;let r=t*Math.PI/180;return e*Math.cos(r)+Vb*Math.sin(r)}function Bb(e,t,r,n,o){if(r<=t)return t;if(e(r)<=0)return r;let a=(r-t)/n,s=r,i=t,c=!1;for(let l=1;l<=n;l++){let u=r-l*a;if(e(u)<=0){i=u,s=u+a,c=!0;break}}if(!c)return t;for(;s-i>o;){let l=.5*(i+s);e(l)<=0?i=l:s=l}return i}var uo=(e,t,r)=>t?t(r):e,NI=1e-4;function Na(e,t,r,n,o,a,s){let i=ct(r),c=[];for(let l=0;l<t.length;l++){let u=t[l],m=Math.abs(u),f=uo(e,o,l),p=a!==void 0&&a>0?Math.min(f.vMax,a):f.vMax,d=s?Math.min(p,s(l)):p,h=m<=0?d:Bb(b=>b*b*m-_I(f,b,0,u,n,l),Ob,d,i.scanSteps,Math.min(i.vTol,NI));c.push({v:h,ax:0,ay:h*h*u})}return c}function OI(e,t,r,n,o,a,s=1,i=0,c=0,l){if(r.v<=t.v)return 0;let u=p=>{let d=He(p*p*n,c),h=(l?e.axDecel(p,Math.abs(d),s,l(p)):e.axDecel(p,Math.abs(d),s))+i;return Math.sqrt(Math.max(0,p*p+2*h*o))},m=r.v;r.v=Bb(p=>u(p)-t.v,Ob,r.v,a.scanSteps,a.vTol),r.ay=r.v*r.v*n;let f=Math.abs(He(r.ay,c));return r.ax=(l?e.axDecel(r.v,f,s,l(r.v)):e.axDecel(r.v,f,s))+i,m-r.v}function VI(e,t,r,n,o,a=1,s=0,i=0,c=1){if(r.v>=t.v)return 0;r.ay=r.v*r.v*n,r.ax=e.axAccel(r.v,Math.abs(He(r.ay,i)),a,c)+s;let l=t.v;return t.v=Math.min(t.v,Math.sqrt(Math.max(0,r.v*r.v+2*r.ax*o))),l-t.v}function AM(e,t,r,n,o,a){let s=ct(n),i=r.npts,c=0;for(let l=0;l<s.seamIters;l++){let u=0;c++;for(let m=i-1;m>=0;m--){let f=(m+1)%i;u=Math.max(u,OI(uo(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],s,Mn(r,m),$i(r,m),lo(r,m),a?p=>a(m,p):void 0))}if(u<=s.vTol)break}return c}function FM(e,t,r,n,o,a){let s=ct(n),i=r.npts,c=0;for(let l=0;l<s.seamIters;l++){let u=0;c++;for(let m=0;m<i;m++){let f=(m+1)%i;u=Math.max(u,VI(uo(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],Mn(r,m),$i(r,m),lo(r,m),a?a[m]:1))}if(u<=s.vTol)break}return c}function BI(e,t,r){let n=r.load?Bi(t):null;if(!n||!r.load)return{pick:r.envelope};let o=t.npts;return{pick:SM(n,r.load,e,r.envelope),cap:a=>vM(n,a%o),n:(a,s)=>om(n,a,s)}}function wM(e,t,r,n,o,a,s){return am(n,r.ds,o,a,(i,c,l)=>{let u=c*c*r.curvature[i];return uo(e,t,i).axAccel(c,Math.abs(He(u,lo(r,i))),Mn(r,i),s?l*s[i]:l)+$i(r,i)})}function CM(e,t){return{gear:e.gear.slice(0,t),engineRpm:e.rpm.slice(0,t),shifting:e.shifting.slice(0,t)}}function TM(e,t,r,n){if(!e.scrub)return{};let o=!1,a=n.map((s,i)=>{let c=uo(e,t,i),l=He(s*s*r.curvature[i],lo(r,i)),u=c.scrub?c.scrub(s,Math.abs(l),Mn(r,i)):0;return u!==0&&(o=!0),u});return o?{axScrub:a}:{}}function At(e,t,r,n={}){let o=ct(r),a=t.npts,s=t.closed&&!n.standingStart,{pick:i,cap:c,n:l}=BI(e,t,n),u=n.driveDerate,m=n.brakeFade;if(!s)return $I(e,t,o,n.standingStart===!0,i,u,n.vCeiling,m,c,l,n.shifts);let f=Na(e,t.curvature,o,t,i,n.vCeiling,c),p=AM(e,f,t,o,i,m),d=FM(e,f,t,o,i,u),h=n.shifts?wM(e,i,t,f.map(k=>k.v),!0,n.shifts,u):void 0;if(h)for(let k=0;k<a;k++)f[k].v=h.v[k];for(let k=0;k<a;k++){let v=f[k];v.ay=v.v*v.v*t.curvature[k];let x=f[(k+1)%a].v;v.ax=(x*x-v.v*v.v)/(2*t.ds[k])}let b=f.map(k=>k.v),g=f.map(k=>k.ax),y=f.map(k=>k.ay),R=0;for(let k=0;k<a;k++){let v=b[k]+b[(k+1)%a];v>0&&(R+=2*t.ds[k]/v)}return{states:f,v:b,ax:g,ay:y,laptime:R,sweeps:{backward:p,forward:d},...l?{loadFactor:b.map((k,v)=>l(v,k))}:{},...TM(e,i,t,b),...h?CM(h,a):{}}}function $I(e,t,r,n,o,a,s,i,c,l,u){let m=t.npts,f=t.closed?m:m-1,p=f+1,d=new Array(p);for(let R=0;R<p;R++)d[R]=t.curvature[R%m];let h=Na(e,d,r,t,o,s,c);n&&(h[0].v=0);for(let R=f-1;R>=0;R--){let k=h[R],v=h[R+1];if(k.v<=v.v)continue;let x=uo(e,o,R),M=w=>{let T=He(w*w*t.curvature[R],lo(t,R)),P=(i?x.axDecel(w,Math.abs(T),Mn(t,R),i(R,w)):x.axDecel(w,Math.abs(T),Mn(t,R)))+$i(t,R);return Math.sqrt(Math.max(0,w*w+2*P*t.ds[R]))},F=n&&R===0?k.v:Ob;k.v=Bb(w=>M(w)-v.v,F,k.v,r.scanSteps,r.vTol)}for(let R=0;R<f;R++){let k=h[R],v=h[R+1];k.ay=k.v*k.v*t.curvature[R];let x=He(k.ay,lo(t,R));k.ax=uo(e,o,R).axAccel(k.v,Math.abs(x),Mn(t,R),a?a[R]:1)+$i(t,R),v.v=Math.min(v.v,Math.sqrt(Math.max(0,k.v*k.v+2*k.ax*t.ds[R])))}let b=u?wM(e,o,t,h.map(R=>R.v),!1,u,a):void 0;if(b)for(let R=0;R<p;R++)h[R].v=b.v[R];let g=0;for(let R=0;R<f;R++){let k=h[R].v+h[R+1].v;k>0&&(g+=2*t.ds[R]/k)}let y=h.slice(0,m);for(let R=0;R<m;R++){let k=y[R];k.ay=k.v*k.v*t.curvature[R];let v=R<f?h[R+1].v:k.v;k.ax=t.ds[R]>0?(v*v-k.v*k.v)/(2*t.ds[R]):0}return{states:y,v:y.map(R=>R.v),ax:y.map(R=>R.ax),ay:y.map(R=>R.ay),laptime:g,sweeps:{backward:1,forward:1},...l?{loadFactor:y.map((R,k)=>l(k,R.v))}:{},...TM(e,o,t,y.map(R=>R.v)),...b?CM(b,m):{}}}var PM=(e,t)=>{let r=e[t]?.value;return Number.isFinite(r)&&r>0?r:0};function mo(e,t,r){let n=e.m.value,o=e.r_dyn?.value??0,a=PM(e,"I_wheel"),s=e.motorModel?.kind==="ice"?0:PM(e,"I_rotor"),i=e.gear_ratio?.value??1;if(!(o>0)||a===0&&s===0)return{mass:n,driven:0,undriven:0,effective:n,powerFactor:1,tractionFactor:1};let c=o*o,l=(t?2:0)+(r?2:0),u=4-l,m=(l*a+s*i*i)/c,f=u*a/c,p=n+m+f;return{mass:n,driven:m,undriven:f,effective:p,powerFactor:n/p,tractionFactor:n/(n+f)}}function po(e){let t=e.fAxle;return{drivenFront:t?t.fFront.some(r=>r>0):!1,drivenRear:t?t.fRear.some(r=>r>0):!0}}var Gi=36e5,IM=Math.PI*2,$b=e=>Math.max(0,Math.min(1,e));function Gb(e){let t=e.motorModel;if(!t){let s=e.effi_pgb?.value??.9;return()=>s}if(t.kind==="simple"){let s=t.efficiency>.01?t.efficiency:.9;return()=>s}if(t.kind==="ice"){let s=t.gearbox.efficiency>.01?t.gearbox.efficiency:.9;return()=>s}let r=al(t),n=e.gear_ratio.value,o=e.r_dyn.value,a=Math.max(1,Math.round(e.motorCount??e.driven_wheels.value));return(s,i)=>{let c=s*n/o*(60/IM),l=Math.max(0,i*o/(n*a)),u=r.efficiency(c,l);return u>.01?u:.5}}var LM=new WeakMap;function Oa(e){if(e.batteryModel)return e.batteryModel;let t=e.capacity.value,r=e.ocv.value,n=LM.get(e);if(n&&n.capacityAh===t&&n.ocv===r)return n.model;let o=gd(t,r);return LM.set(e,{capacityAh:t,ocv:r,model:o}),o}function Kb(e){let t=e.params,r=Kh(t,bu(e));if(xt(t.motorModel)||bt(t).mode!=="hydraulic")return r;let n;return(o,a,s,i=0)=>{if(!(o>0))return 0;n??=GI(e);let c=Mu(n.inp,n.ev,o,a,i);return c?Math.min(o,c.regenFront+c.regenRear):r(o,a,s)}}var DM=new WeakMap;function GI(e){let t=e.params,r=DM.get(t);if(!r){let n=$r(t);r={inp:gt(n.regen?t:{...t,energy:{...n,regen:!0}}),ev:gr(t)},DM.set(t,r)}return r}var Ki=e=>e.airTempC??Lt;function im(e,t){return e.thermal?e.thermal.startC??t:Wo}function EM(e,t,r,n,o,a){let s=e.thermal;if(!s||!(o>0)||!(s.heatCapacityJPerK>0))return t;let i=s.coolingWPerK*(t-a)*o,c=s.entropicVPerK!==0?-r*(t+273.15)*s.entropicVPerK*o:0;return t+(n+c-i)/s.heatCapacityJPerK}var _M=()=>({windingC:[],derate:[],lossW:[],torqueNm:[],ampsRms:[]});function KI(e){let t=e.motorModel;if(!t?.thermal)return;let r=yd(t.thermal),n=al(t),o=e.gear_ratio.value,a=e.r_dyn.value,s=Math.max(1,Math.round(e.motorCount??e.driven_wheels.value));return{th:r,rpm:i=>i*o/a*(60/IM),peak:i=>n.maxTorque(i),amps:i=>t.thermal.torqueConstant>0?Math.abs(i)/t.thermal.torqueConstant:0,torque:(i,c,l)=>Math.min(Math.abs(i)*a/(o*s),l*n.maxTorque(c))}}function HI(e,t,r,n,o){let a=e.ocv(n);if(!(r>0))return{dq:t/a,lossJ:0,energyJ:t,short:!1,cutoff:!1,seconds:r};let s=e.maxPower(n,o),i=s.watts,c=t/r,l=Math.min(c,i),u=c>s.voltageFloor;if(u&&!(l>0))return{dq:1/0,lossJ:0,energyJ:0,short:!0,cutoff:u,seconds:1/0};let m=e.currentFor(l,n,o),f=u?c/l:1,p=r*f;return{dq:m*p,lossJ:m*m*e.resistance(n,o)*p,energyJ:l*p,short:c>i,cutoff:u,seconds:p}}function zI(e,t,r,n,o){let a=e.ocv(n);if(!(r>0))return{dq:t/a,lossJ:0,energyJ:t,short:!1,cutoff:!1,seconds:r};let s=e.resistance(n,o),i=e.chargeCurrentFor(t/r,n,o),c=Math.min(i,e.chargeCurrentCeiling),l=c===i?t:c*(a+c*s)*r;return{dq:c*r,lossJ:c*c*s*r,energyJ:l,short:c<i,cutoff:!1,seconds:r}}function YI(e){let{drivenFront:t,drivenRear:r}=po(e);return mo(e.params,t,r)}function Va(e,t,r,n,o=Br,a,s,i,c,l,u){let m=e.params,f=m.rho.value,p=m.fr_0.value,d=m.m.value,h=e.FG,b=m.aeroModel?gt(m):void 0,g=Gb(m),y=Fr(Oa(m)),R=y.chargeC,k=$b(a??m.soc.value),v=Ki(m),x=s??im(y,v),M=x,F=0,w=0,T=0,P=0,A=-1,S=-1,C=-1,L=KI(m),D=L?L.th.startC:0,I=D,O=0,N=1,z=-1,E=0,_=0,B=Kb(e),V=m.motorModel?.kind==="ice",G=u?.scrub,K=G?d/YI(e).tractionFactor:0,Y=Math.min(t.length,r.length);for(let j=0;j<Y;j++){let Z=r[j],ne=Z*Z,te=n[j]-(c?.[j]??0),{cl:fe,cw:W,A:J}=rm(m,Z,te/9.81,b),re=.5*f*fe*J*ne,pe=.5*f*W*J*ne,de=(h+re)*-p,ie=G?-K*(G[j]??0):0,oe=de+pe+ie+d*te,ue=oe*t[j],$e=j+1<r.length?r[j+1]:Z,Ae=.5*(Z+$e),le=Ae>0?t[j]/Ae:0,Re=0,Te=k,ze=x,Ue=0,be=0,Fe=le;if(V){oe>0&&(be=ue/g(Z,oe),F+=be/Gi),l?.netKwh.push(F-w),l?.powerKw?.push(le>0?be/le/1e3:0);continue}if(oe>0){let xe=ue/g(Z,oe),me=HI(y,xe,le,k,x);me.short&&A<0&&(A=j),me.cutoff&&S<0&&(S=j);let Le=k*R,Se=Math.min(me.dq,Le),Ye=me.dq>0?Se/me.dq:1;Se>=Le&&C<0&&(C=j),F+=me.energyJ*Ye/Gi,be=me.energyJ*Ye,Fe=me.seconds,T+=me.lossJ*Ye,P+=Se,le>0&&(Ue=Se/me.seconds),k=$b(k-Se/R),x=EM(y,x,me.dq>0&&le>0?Se/le:0,me.lossJ*Ye,le,v),x>M&&(M=x),Re=oe}else if(o.regen){let xe=u?He(u.ay[j],u.bank?.[j]??0)/9.81:0,me=B(-oe,Z,te/9.81,xe),Le=o.regenEfficiency*me*t[j],Se=zI(y,Le,le,k,x),Ye=(1-k)*R,Xe=Math.min(Se.dq,Ye),Xt=Se.dq>0?Xe/Se.dq:1;w+=Se.energyJ*Xt/Gi,be=-Se.energyJ*Xt,T+=Se.lossJ*Xt,P-=Xe,le>0&&(Ue=-Xe/le),k=$b(k+Xe/R),x=EM(y,x,Xe>0&&le>0?-Xe/le:0,Se.lossJ*Xt,le,v),x>M&&(M=x),Re=-me*Xt}if(l?.netKwh.push(F-w),l?.powerKw?.push(le>0?be/Fe/1e3:0),l?.pack){let xe=l.pack;xe.soc.push(Te),xe.amps.push(Ue),xe.volts.push(y.ocv(Te)-Ue*y.resistance(Te,ze)),xe.cellC.push(ze)}if(L){let xe=L.rpm(Z),me=L.th.derate(xe,D,L.peak(xe));me<N&&(N=me),me<1&&z<0&&(z=j),_+=le,me<1&&(E+=le);let Le=L.torque(Re,xe,me),Se=L.th.lossW(xe,Le,D);O+=Se*le,i&&(i.windingC.push(D),i.derate.push(me),i.lossW.push(Se),i.torqueNm.push(Le),i.ampsRms.push(L.amps(Le))),D=L.th.step(D,Se,le),D>I&&(I=D)}}return{drive:F,regen:w,net:F-w,chargeAh:P/3600,loss:T/Gi,socEnd:k,shortAt:A,cutoffAt:S,emptyAt:C,tempEndC:x,tempMaxC:M,...L?{motorTempEndC:D,motorTempMaxC:I,motorLossKwh:O/Gi,motorDerateMin:N,motorDerateAt:z,motorDerateTimeFrac:_>0?E/_:0}:{}}}var WI=.5,jI=.02,UI=6;function NM(e,t,r,n,o,a,s,i){let c=n(),l=1,u=d=>{let h=_M(),b=Va(e,t,d.v,d.ax,r,o,a,h,s,void 0,{ay:d.ay,bank:i,...d.axScrub?{scrub:d.axScrub}:{}});return{trace:h,peak:b.motorTempMaxC??0,frac:b.motorDerateTimeFrac??0}},m=u(c);if(!m.trace.derate.length||m.frac===0)return{lap:c,solves:l,converged:!0,peakWindingC:m.peak,derateTimeFrac:m.frac};let f=m.trace.derate.slice(),p=!1;for(let d=0;d<UI;d++){let h=n(f);l++;let b=Math.abs(h.laptime-c.laptime);if(c=h,m=u(c),b<jI){p=!0;break}let g=m.trace.derate,y=new Array(f.length);for(let R=0;R<f.length;R++)y[R]=f[R]+WI*((g[R]??1)-f[R]);f=y}return{lap:c,derate:f,solves:l,converged:p,peakWindingC:m.peak,derateTimeFrac:m.frac}}var XI=.1;function OM(e){let t=e.power_limit_kw?.value??0;return t>0?t*1e3:0}function Hb(e,t,r){return e.motorModel?.kind==="ice"?1/0:Fr(Oa(e)).maxPower(t??e.soc.value,r,OM(e)).watts}function cm(e,t,r,n){let o=Hb(e,r,n);if(!Number.isFinite(o))return 1/0;if(o<=0)return 0;let a=Math.max(XI,t),s=Gb(e),i=o*(e.effi_pgb?.value??.9)/a;return o*s(t,i)/a}var qI=180/Math.PI;function lm(e,t,r,n){let o=e*t,a=e*(1-t);return o/r-a/n}var um=e=>e*9.81*qI;var Iq=Math.PI/180;function mm(e,t,r,n=0){let o=Ce(e,t,0,n),a=typeof r=="function"?r:r.front,s=typeof r=="function"?r:r.rear,i=.5*(a(Math.max(0,o.FL))+a(Math.max(0,o.FR))),c=.5*(s(Math.max(0,o.RL))+s(Math.max(0,o.RR))),l=i>0&&c>0?lm(e.massTotal,e.frontMassFrac,2*i,2*c):0,u=um(l),m=u>.15?"understeer":u<-.15?"oversteer":"neutral";return{gradient:u,balance:m,cAlphaFront:i,cAlphaRear:c}}var Kq=Math.PI/180,Hq=180/Math.PI;var VM=2220446049250313e-31;function JI(e){let t=e.length,r=2,n=r*r,o=!1;for(;!o;){o=!0;for(let a=0;a<t;a++){let s=0,i=0;for(let c=0;c<t;c++)c!==a&&(i+=Math.abs(e[c][a]),s+=Math.abs(e[a][c]));if(i!==0&&s!==0){let c=s/r,l=1,u=i+s;for(;i<c;)l*=r,i*=n;for(c=s*r;i>c;)l/=r,i/=n;if((i+s)/l<.95*u){o=!1;let m=1/l;for(let f=0;f<t;f++)e[a][f]*=m;for(let f=0;f<t;f++)e[f][a]*=l}}}}}function e2(e){let t=e.length;for(let r=1;r<t-1;r++){let n=0,o=r;for(let a=r;a<t;a++)Math.abs(e[a][r-1])>Math.abs(n)&&(n=e[a][r-1],o=a);if(o!==r){for(let a=r-1;a<t;a++){let s=e[o][a];e[o][a]=e[r][a],e[r][a]=s}for(let a=0;a<t;a++){let s=e[a][o];e[a][o]=e[a][r],e[a][r]=s}}if(n!==0)for(let a=r+1;a<t;a++){let s=e[a][r-1];if(s!==0){s/=n,e[a][r-1]=s;for(let i=r;i<t;i++)e[a][i]-=s*e[r][i];for(let i=0;i<t;i++)e[i][r]+=s*e[i][a]}}}for(let r=2;r<t;r++)for(let n=0;n<r-1;n++)e[r][n]=0}function t2(e){let t=e.length,r=new Array(t).fill(0),n=new Array(t).fill(0),o=0;for(let i=0;i<t;i++)for(let c=Math.max(i-1,0);c<t;c++)o+=Math.abs(e[i][c]);let a=t-1,s=0;for(;a>=0;){let i=0,c=0;do{for(c=a;c>=1;c--){let u=Math.abs(e[c-1][c-1])+Math.abs(e[c][c]);if(u===0&&(u=o),Math.abs(e[c][c-1])<=VM*u){e[c][c-1]=0;break}}let l=e[a][a];if(c===a)r[a]=l+s,n[a]=0,a--;else{let u=e[a-1][a-1],m=e[a][a-1]*e[a-1][a];if(c===a-1){let f=.5*(u-l),p=f*f+m,d=Math.sqrt(Math.abs(p));l+=s,p>=0?(d=f+(f>=0?Math.abs(d):-Math.abs(d)),r[a-1]=r[a]=l+d,d!==0&&(r[a]=l-m/d),n[a-1]=n[a]=0):(r[a-1]=r[a]=l+f,n[a]=d,n[a-1]=-d),a-=2}else{if(i===60)throw new Error("eigenvalues: QR iteration did not converge");if(i===10||i===20||i===30||i===40||i===50){s+=l;for(let g=0;g<=a;g++)e[g][g]-=l;let b=Math.abs(e[a][a-1])+Math.abs(e[a-1][a-2]);u=l=.75*b,m=-.4375*b*b}i++;let f=a-2,p=0,d=0,h=0;for(;f>=c;f--){let b=e[f][f],g=l-b,y=u-b;p=(g*y-m)/e[f+1][f]+e[f][f+1],d=e[f+1][f+1]-b-g-y,h=e[f+2][f+1];let R=Math.abs(p)+Math.abs(d)+Math.abs(h);if(p/=R,d/=R,h/=R,f===c)break;let k=Math.abs(e[f][f-1])*(Math.abs(d)+Math.abs(h)),v=Math.abs(p)*(Math.abs(e[f-1][f-1])+Math.abs(b)+Math.abs(e[f+1][f+1]));if(k<=VM*v)break}for(let b=f+2;b<=a;b++)e[b][b-2]=0,b!==f+2&&(e[b][b-3]=0);for(let b=f;b<=a-1;b++){b!==f&&(p=e[b][b-1],d=e[b+1][b-1],h=b!==a-1?e[b+2][b-1]:0,l=Math.abs(p)+Math.abs(d)+Math.abs(h),l!==0&&(p/=l,d/=l,h/=l));let g=Math.sqrt(p*p+d*d+h*h),y=p>=0?g:-g;if(y!==0){b===f?c!==f&&(e[b][b-1]=-e[b][b-1]):e[b][b-1]=-y*l,p+=y,l=p/y,u=d/y;let R=h/y;d/=p,h/=p;for(let v=b;v<=a;v++){let x=e[b][v]+d*e[b+1][v];b!==a-1&&(x+=h*e[b+2][v],e[b+2][v]-=x*R),e[b+1][v]-=x*u,e[b][v]-=x*l}let k=a<b+3?a:b+3;for(let v=c;v<=k;v++){let x=l*e[v][b]+u*e[v][b+1];b!==a-1&&(x+=R*e[v][b+2],e[v][b+2]-=x*h),e[v][b+1]-=x*d,e[v][b]-=x}}}}}}while(c<a-1&&a>=0)}return r.map((i,c)=>({re:i,im:n[c]}))}function BM(e){let t=e.length;if(t===0)return[];for(let n of e)if(n.length!==t)throw new Error("eigenvalues: matrix must be square");for(let n of e)for(let o of n)if(!Number.isFinite(o))throw new Error("eigenvalues: matrix has non-finite entries");if(t===1)return[{re:e[0][0],im:0}];let r=e.map(n=>n.slice());return JI(r),e2(r),t2(r)}function $M(e){let t=[],r=new Array(e.length).fill(!1),n=BM(e);for(let o=0;o<n.length;o++){if(r[o])continue;let{re:a,im:s}=n[o];if(s<0)continue;let i=Math.hypot(a,s);t.push({freq:i/(2*Math.PI),dampedFreq:Math.abs(s)/(2*Math.PI),dampingRatio:i>0?-a/i:0,eigenvalue:n[o]})}return t.sort((o,a)=>a.freq-o.freq)}function zb(e,t){let r=e.length,n=Array.from({length:r},(c,l)=>l);for(let c=0;c<r-1;c++){let l=c,u=c,m=-1;for(let h=c;h<r;h++)for(let b=c;b<r;b++){let g=e[h][b]*e[h][b]+t[h][b]*t[h][b];g>m&&(m=g,l=h,u=b)}if(!(m>0))break;if([e[c],e[l]]=[e[l],e[c]],[t[c],t[l]]=[t[l],t[c]],u!==c){for(let h=0;h<r;h++)[e[h][c],e[h][u]]=[e[h][u],e[h][c]],[t[h][c],t[h][u]]=[t[h][u],t[h][c]];[n[c],n[u]]=[n[u],n[c]]}let f=e[c][c],p=t[c][c],d=f*f+p*p;for(let h=c+1;h<r;h++){let b=(e[h][c]*f+t[h][c]*p)/d,g=(t[h][c]*f-e[h][c]*p)/d;if(!(b===0&&g===0))for(let y=c;y<r;y++)e[h][y]-=b*e[c][y]-g*t[c][y],t[h][y]-=b*t[c][y]+g*e[c][y]}}let o=new Array(r).fill(0),a=new Array(r).fill(0);o[r-1]=1;for(let c=r-2;c>=0;c--){let l=e[c][c],u=t[c][c],m=l*l+u*u;if(!(m>0))continue;let f=0,p=0;for(let d=c+1;d<r;d++)f+=e[c][d]*o[d]-t[c][d]*a[d],p+=e[c][d]*a[d]+t[c][d]*o[d];o[c]=-(f*l+p*u)/m,a[c]=-(p*l-f*u)/m}let s=Math.sqrt(o.reduce((c,l,u)=>c+l*l+a[u]*a[u],0)),i=new Array(r);for(let c=0;c<r;c++)i[n[c]]={re:o[c]/s,im:a[c]/s};return i}function r2(e,t){let r=e.map((o,a)=>o.map((s,i)=>a===i?s-t.re:s)),n=e.map((o,a)=>o.map((s,i)=>a===i?-t.im:0));return zb(r,n)}function pm(e,t=r=>r2(e,r)){return $M(e).map(r=>({...r,vector:t(r.eigenvalue)}))}function Ba(e,t,r){let n,o=-1,a,s=-1;for(let i of e){let c=t(i.vector),l=c[r];i.eigenvalue.im===0?l>s&&(a=i,s=l):l>=Math.max(...c)&&l>o&&(n=i,o=l)}return n??a}function GM(e){let t=e.sprungMass;if(!(t>0))return;let r=Math.max(.1,e.unsprungMass),n=e.springRate*1e3,o=e.damperRate*1e3,a=e.tireRate*1e3,s=(e.tireDamping??0)*1e3,i=[[0,1,0,0],[-n/t,-o/t,n/t,o/t],[0,0,0,1],[n/r,o/r,-(n+a)/r,-(o+s)/r]];if(!i.every(l=>l.every(Number.isFinite)))return;let c=l=>{let u=t*(l[0].re**2+l[0].im**2),m=r*(l[2].re**2+l[2].im**2);return u+m>0?[u/(u+m),m/(u+m)]:[0,0]};return Ba(pm(i),c,0)}function KM(e,t,r,n){let o=(r==="front"?t.sprungFront:t.sprungRear)/2;if(o<=0)return{dampingRatio:0,criticalDamping:0,naturalFreqDamped:0};let a=r==="front"?t.rideRateFront:t.rideRateRear,s=r==="front"?e.wheelRateFront+(e.heaveSpringFront??0):e.wheelRateRear+(e.heaveSpringRear??0),i=GM({sprungMass:o,unsprungMass:e.unsprungCornerMass??e.unsprungPerCorner,springRate:s,damperRate:n,tireRate:qe(e,r),tireDamping:e.tireDamping}),c=2*Math.sqrt(a*1e3*o);return{dampingRatio:i?.dampingRatio??0,criticalDamping:c/1e3,naturalFreqDamped:i?.dampedFreq??0}}function dm(e,t,r){let n=we(e);return{front:KM(e,n,"front",t??n.rideDampingFront),rear:KM(e,n,"rear",r??n.rideDampingRear)}}var rQ=180/Math.PI;var Yb=["FL","FR","RL","RR"],ce={zFL:0,vzFL:1,zFR:2,vzFR:3,zRL:4,vzRL:5,zRR:6,vzRR:7,zBody:8,vzBody:9,pitch:10,pitchRate:11,roll:12,rollRate:13,x:14,vx:15,y:16,vy:17,yaw:18,yawRate:19},$a=20,HM=[ce.zFL,ce.zFR,ce.zRL,ce.zRR],zM=[ce.vzFL,ce.vzFR,ce.vzRL,ce.vzRR],qr={fzFL:0,fzFR:1,fzRL:2,fzRR:3,fzBody:4,myBody:5,mxBody:6,fx:7,fy:8,mz:9},Wb=10;function fm(e){let t=Array.from({length:$a},()=>new Array($a).fill(0)),r=Array.from({length:$a},()=>new Array(Wb).fill(0));t[ce.zFL][ce.vzFL]=1,t[ce.zFR][ce.vzFR]=1,t[ce.zRL][ce.vzRL]=1,t[ce.zRR][ce.vzRR]=1,t[ce.zBody][ce.vzBody]=1,t[ce.pitch][ce.pitchRate]=1,t[ce.roll][ce.rollRate]=1,t[ce.x][ce.vx]=1,t[ce.y][ce.vy]=1,t[ce.yaw][ce.yawRate]=1;let{inertia:n}=e,o=[1,0,3,2],a=(s,i,c,l)=>{s[HM[i]]-=c,s[zM[i]]-=l,s[ce.zBody]+=c,s[ce.vzBody]+=l,s[ce.pitch]-=c*e.leverX[i],s[ce.pitchRate]-=l*e.leverX[i],s[ce.roll]+=c*e.leverY[i],s[ce.rollRate]+=l*e.leverY[i]};for(let s=0;s<4;s++){let i=s<2,c=M=>M?i?M.front:M.rear:0,l=e.springRate[s]+c(e.heaveSpring),u=e.springRate[s]+c(e.arb),m=e.damperRate[s]+c(e.heaveDamper),f=e.damperRate[s]+c(e.rollDamper),p=(l+u)/2,d=(l-u)/2,h=(m+f)/2,b=(m-f)/2,g=new Array($a).fill(0);a(g,s,p,h),(d!==0||b!==0)&&a(g,o[s],d,b);let y=e.wheelMass[s],R=e.leverX[s],k=e.leverY[s],v=HM[s],x=zM[s];for(let M=0;M<$a;M++){let F=g[M];F!==0&&(t[x][M]+=F/y,t[ce.vzBody][M]-=F/e.bodyMass,t[ce.pitchRate][M]+=R*F/n.yy,t[ce.rollRate][M]-=k*F/n.xx)}t[x][v]-=e.tyreRate[s]/y,t[x][x]-=e.tyreDamping[s]/y,r[x][qr.fzFL+s]=1/y}return r[ce.vzBody][qr.fzBody]=1/e.bodyMass,r[ce.pitchRate][qr.myBody]=1/n.yy,r[ce.rollRate][qr.mxBody]=1/n.xx,r[ce.vx][qr.fx]=1/e.totalMass,r[ce.vy][qr.fy]=1/e.totalMass,r[ce.yawRate][qr.mz]=1/n.zz,{A:t,B:r,params:e}}function jb(e){let t=e.wheelbase/1e3,r=t*(1-e.frontMassFrac),n=t*e.frontMassFrac,o=e.trackFront/2e3,a=e.trackRear/2e3,s=e.unsprungCornerMass??e.unsprungPerCorner,i=Math.max(0,e.massTotal-4*s),c=e.wheelRateFront*1e3,l=e.wheelRateRear*1e3,u=(e.damperFront??2.5)*1e3,m=(e.damperRear??2.5)*1e3,f=qe(e,"front")*1e3,p=qe(e,"rear")*1e3,d=(e.tireDamping??0)*1e3;return{bodyMass:i,totalMass:e.massTotal,wheelMass:[s,s,s,s],inertia:{xx:e.rollInertia??i*.6*.6,yy:e.pitchInertia??i*1.2*1.2,zz:e.yawInertia??e.massTotal*1.2*1.2},leverX:[r,r,-n,-n],leverY:[o,-o,a,-a],springRate:[c,c,l,l],damperRate:[u,u,m,m],tyreRate:[f,f,p,p],tyreDamping:[d,d,d,d],arb:{front:e.arbFront*1e3,rear:e.arbRear*1e3},heaveSpring:{front:(e.heaveSpringFront??0)*1e3,rear:(e.heaveSpringRear??0)*1e3},rollDamper:{front:(e.rollDamperFront??0)*1e3,rear:(e.rollDamperRear??0)*1e3},heaveDamper:{front:(e.heaveDamperFront??0)*1e3,rear:(e.heaveDamperRear??0)*1e3}}}var YM=ce.rollRate+1;function WM(e){let t=e.params,r=[...t.wheelMass,t.bodyMass,t.inertia.yy,t.inertia.xx];if(!r.every(i=>i>0))return{};let n=e.A.slice(0,YM).map(i=>i.slice(0,YM));if(!n.every(i=>i.every(Number.isFinite)))return{};let a=pm(n,i=>{let c=i.re*i.re-i.im*i.im,l=2*i.re*i.im,u=r.map((f,p)=>r.map((d,h)=>(p===h?c:0)-i.re*n[2*p+1][2*h+1]-n[2*p+1][2*h])),m=r.map((f,p)=>r.map((d,h)=>(p===h?l:0)-i.im*n[2*p+1][2*h+1]));return zb(u,m)}),s=i=>{let c=r.map((u,m)=>u*(i[m].re**2+i[m].im**2)),l=c.reduce((u,m)=>u+m,0)||1;return[c[0]+c[1]+c[2]+c[3],c[4],c[5],c[6]].map(u=>u/l)};return{heave:Ba(a,s,1),pitch:Ba(a,s,2),roll:Ba(a,s,3)}}function jM(e,t,r){let n=e?2*Math.PI*e.freq:0,o=e&&n>0?e.dampingRatio:0,a=o>0&&o<1?Math.exp(-Math.PI*o/Math.sqrt(1-o*o))*100:0,s=o>0&&n>0?4/(o*n):1/0;return{freq:n/(2*Math.PI),dampedFreq:e&&n>0?e.dampedFreq:0,dampingRatio:o,stiffness:t,inertia:r,overshoot:a,settlingTime:s}}function hm(e){let t=we(e),r=e.wheelbase/1e3,n=r*(1-e.frontMassFrac),o=r*e.frontMassFrac,a=t.rollRateTotal*(180/Math.PI),s=e.rollInertia??t.sprungMass*.6*.6,i=2*t.rideRateFront*1e3,c=2*t.rideRateRear*1e3,l=i*n*n+c*o*o,u=e.pitchInertia??t.sprungMass*1.2*1.2,m=WM(fm(jb(e)));return{roll:jM(m.roll,a,s),pitch:jM(m.pitch,l,u)}}var bm=9.81,Qr=Math.PI/180;function UM(e){let t=e.wheelbase/1e3,r=t*(1-e.frontMassFrac),n=t*e.frontMassFrac;return{wb:t,lf:r,lr:n,m:e.massTotal}}function Ga(e,t,r,n,o){let{wb:a,lf:s,lr:i,m:c}=UM(e),l=0;for(let R=0;R<16;R++){let k=l/r,v=o-n-s*k/r,x=-n+i*k/r,M=Ce(e,l/bm,0,r),F=Math.max(0,M.FL+M.FR),w=Math.max(0,M.RL+M.RR),T=t(v,F),P=t(x,w),A=(T*Math.cos(o)+P)/c;if(l=.5*(l+A),Math.abs(A-l)<1e-4)break}let u=l/r,m=o-n-s*u/r,f=-n+i*u/r,p=Ce(e,l/bm,0,r),d=Math.max(0,p.FL+p.FR),h=Math.max(0,p.RL+p.RR),b=t(m,d),g=t(f,h),y=s*b*Math.cos(o)-i*g;return{ay:l/bm,cn:y/(c*bm*a)}}function Ub(e,t,r,n={}){let o=Math.max(8,r),a=(n.betaMaxDeg??10)*Qr,s=(n.deltaMaxDeg??10)*Qr,i=n.nLines??9,c=n.nPts??21,l=(g,y,R,k)=>R===1?g:g+(y-g)*k/(R-1),u=[],m={ay:[],cn:[]},f=0;for(let g=0;g<i;g++){let y=l(-s,s,i,g),R=[],k=[],v=[],x=[];for(let M=0;M<c;M++){let F=l(-a,a,c,M),w=Ga(e,t,o,F,y);R.push(w.ay),k.push(w.cn),v.push(F/Qr),x.push(y/Qr),Math.abs(w.ay)>f&&(f=Math.abs(w.ay))}u.push({label:`\u03B4 ${(y/Qr).toFixed(0)}\xB0`,ay:R,cn:k,betaDeg:v,deltaDeg:x});for(let M=1;M<k.length;M++)if(k[M-1]===0||k[M-1]<0!=k[M]<0){let F=k[M-1]===k[M]?0:k[M-1]/(k[M-1]-k[M]);m.ay.push(R[M-1]+F*(R[M]-R[M-1])),m.cn.push(0);break}}let p=[];for(let g=0;g<i;g++){let y=l(-a,a,i,g),R=[],k=[],v=[],x=[];for(let M=0;M<c;M++){let F=l(-s,s,c,M),w=Ga(e,t,o,y,F);R.push(w.ay),k.push(w.cn),v.push(y/Qr),x.push(F/Qr)}p.push({label:`\u03B2 ${(y/Qr).toFixed(0)}\xB0`,ay:R,cn:k,betaDeg:v,deltaDeg:x})}let d=.5*Qr,h=(Ga(e,t,o,d,0).cn-Ga(e,t,o,-d,0).cn)/(2*d),b=(Ga(e,t,o,0,d).cn-Ga(e,t,o,0,-d).cn)/(2*d);return{isoBeta:p,isoDelta:u,trim:m,maxAy:f,stability:h,control:b,speed:o}}function n2(e){return!e.corneringStiffnessFront||!e.corneringStiffnessRear?null:{Cf:2*e.corneringStiffnessFront,Cr:2*e.corneringStiffnessRear}}function Hi(e,t){let r=n2(e);if(!r)return null;let{Cf:n,Cr:o}=r,{wb:a,lf:s,lr:i,m:c}=UM(e),l=e.yawInertia??c*1*1,u=Math.max(3,t),m=-(n+o)/(c*u),f=(-s*n+i*o)/(c*u)-u,p=(-s*n+i*o)/(l*u),d=-(s*s*n+i*i*o)/(l*u),h=m+d,b=m*d-f*p,g=h*h-4*b,y,R,k;if(g<0)y=h/2,R=Math.sqrt(Math.max(0,b)),k=R>0?-h/(2*R):1;else{let C=Math.sqrt(g);y=Math.max((h+C)/2,(h-C)/2),R=Math.sqrt(Math.abs(b)),k=R>0?-h/(2*R):1}let v=h<0&&b>0,x=lm(c,e.frontMassFrac,n,o),M=um(x),F=M>.15?"understeer":M<-.15?"oversteer":"neutral",w=s*n-i*o,T=C=>C*3.6,P=null,A=null;w>1e-6?A=T(Math.sqrt(n*o*a*a/(c*w))):w<-1e-6&&(P=T(Math.sqrt(n*o*a*a/(c*-w))));let S=u/(a+x*u*u);return{stable:v,yawFreq:R/(2*Math.PI),dampingRatio:k,eigReal:y,understeerGradient:M,balance:F,characteristicSpeed:P,criticalSpeed:A,yawRateGain:S}}var XM=Math.PI/180;function ZM(e,t){let r=Math.abs(e);return r<.15?"no measurable body slip \u2014 the car is travelling along its own centreline":Math.abs(t)<1e-6?`${r.toFixed(1)}\xB0 of body slip (not cornering, so there is no inside or outside yet)`:e*Math.sign(t)>0?`${r.toFixed(1)}\xB0 of body slip, nose pointing OUT of the corner \u2014 running wide of the path it is on`:`${r.toFixed(1)}\xB0 of body slip, nose pointing INTO the corner \u2014 rotated inside the path it is on`}function qM(e,t,r){return e.length<2?0:t<=0?(e[1]-e[0])/r:t>=e.length-1?(e[e.length-1]-e[e.length-2])/r:(e[t+1]-e[t-1])/(2*r)}function JM(e,t,r,n){let o=e.isoDelta.length,a=e.isoDelta[0]?.ay.length??0,s=Math.max(0,Math.min(o-1,Math.floor(t))),i=Math.max(0,Math.min(a-1,Math.floor(r))),c=Math.max(0,Math.min(1,t-s)),l=Math.max(0,Math.min(1,r-i)),u=0;for(let[m,f]of[[s,1-c],[Math.min(o-1,s+1),c]])if(!(f<=0))for(let[p,d]of[[i,1-l],[Math.min(a-1,i+1),l]])d<=0||(u+=f*d*n(e.isoDelta[m],p,m));return u}function eS(e,t,r){let n=e.isoDelta[0],o=(n.betaDeg[1]-n.betaDeg[0])*XM||1,a=e.isoDelta.length>1?(e.isoDelta[1].deltaDeg[0]-e.isoDelta[0].deltaDeg[0])*XM:1,s=x=>JM(e,t,r,x),i=s((x,M)=>x.ay[M]),c=s((x,M)=>x.cn[M]),l=s((x,M)=>x.betaDeg[M]),u=s((x,M)=>x.deltaDeg[M]),m=s((x,M)=>qM(x.cn,M,o)),f=s((x,M,F)=>qM(e.isoDelta.map(w=>w.cn[M]),F,a||1)),p=Math.max(1e-6,e.maxAy),d=Math.abs(i)/p,h=Math.max(1e-6,...e.isoDelta.flatMap(x=>x.cn.filter(Number.isFinite).map(Math.abs))),b=Math.abs(c)/h,g=i===0?c:c*Math.sign(i),y=[];y.push(`${ZM(l,i)}.`),b<.03?y.push("On the trim line: yaw moments balance, so this is a steady corner the car can actually hold. Only points on this line are real cornering states \u2014 everywhere else the car is still rotating."):g>0?y.push(`Not a steady state: there is a surplus yaw moment turning the car further into the corner, so it would keep rotating from here. To hold ${Math.abs(i).toFixed(2)} g the driver would have to wind ${u>=0?"off":"on"} steer until the point reaches the trim line.`):y.push("Not a steady state: the yaw moment is straightening the car out, so it would run wide from here. The car needs more steer, or more front grip, to reach the trim line at this slip angle.");let R=Math.abs(e.stability)>1e-9?m/e.stability:1;R<.15?y.push("Yaw stiffness has collapsed here: the moment resisting a change in body slip is essentially gone, so the car will not gather itself up if it steps out. Both axles are close to saturation."):R<.85?y.push(`Yaw stiffness is down to about ${(100*R).toFixed(0)} % of its straight-ahead value \u2014 the car resists a change in body slip less firmly here than it does in the linear range.`):y.push(`Yaw stiffness is near its straight-ahead value (${(100*R).toFixed(0)} %), so the car still opposes a change in body slip about as firmly as it does in a straight line.`);let k=Math.abs(e.control),v=k>1e-9?Math.abs(f)/k:1;return v<.15?y.push("The steering has stopped working here: another degree of lock buys almost no yaw moment, which is what a saturated front axle looks like. This is understeer in its literal sense \u2014 the front tyres are already at their limit."):v<.5&&y.push(`Steering response is down to about ${(100*v).toFixed(0)} % of its straight-ahead value \u2014 the front is well into the non-linear part of its curve.`),d>.97?y.push(`At the edge of the diagram: ${Math.abs(i).toFixed(2)} g is essentially all this car has at this speed.`):d<.25&&y.push("Well inside the limit \u2014 this is the linear region the handling balance is measured in."),{ay:i,cn:c,betaDeg:l,deltaDeg:u,stability:m,control:f,gripUsed:d,notes:y}}var QM=1e-4;function Xb(e){let t=null,r=f=>{if(!t)return!0;let p=Math.abs(f),d=Math.abs(t.ay);return p>d*(1+QM)?!0:p<d*(1-QM)?!1:f>0&&t.ay<0};for(let f=0;f<e.isoDelta.length;f++){let p=e.isoDelta[f];for(let d=1;d<p.cn.length;d++){if(!(p.cn[d-1]===0||p.cn[d-1]<0!=p.cn[d]<0))continue;let b=p.cn[d-1]===p.cn[d]?0:p.cn[d-1]/(p.cn[d-1]-p.cn[d]),g=p.ay[d-1]+b*(p.ay[d]-p.ay[d-1]);r(g)&&(t={ay:g,d:f,b:b<.5?d-1:d})}}if(!t)return null;let n=eS(e,t.d,t.b),o=Math.abs(e.control)>1e-9?Math.abs(n.control/e.control):1,a=Math.abs(e.stability)>1e-9?n.stability/e.stability:1,s=o<.35,i=a<.35,c=s&&i?"both":s?"front":i?"rear":o<a?"front":"rear",l=e.isoDelta[t.d].betaDeg.length,u=t.b===0||t.b===l-1||t.d===0||t.d===e.isoDelta.length-1,m=t.ay<0?-1:1;return{ay:Math.abs(t.ay),turn:m,betaDeg:e.isoDelta[t.d].betaDeg[t.b]*m,deltaDeg:e.isoDelta[t.d].deltaDeg[t.b]*m,d:t.d,b:t.b,limitedBy:c,controlFrac:o,stiffnessFrac:a,onGridEdge:u}}var o2=["tv_kp"];function tS(e=0){let t=e<0,r=e>0,n=t||r,o=[{key:"damper_front",why:"dampers act on velocity; every point here is at constant attitude"},{key:"damper_rear",why:"dampers act on velocity; every point here is at constant attitude"},{key:"tire_vertical_damping",why:"tyre damping acts on velocity; every point here is at constant attitude"},{key:"I_yaw",why:"inertia resists change; a steady corner has none"},{key:"I_roll",why:"inertia resists change; a steady corner has none"},{key:"I_pitch",why:"inertia resists change; a steady corner has none"},{key:"capacity",why:"energy does not enter a single steady-state point"},{key:"ocv",why:"energy does not enter a single steady-state point"},{key:"soc",why:"energy does not enter a single steady-state point"},...o2.map(s=>({key:s,why:"the feedback gain multiplies a yaw error, and a trimmed point has none \u2014 the feedforward does move this diagram"}))];t||o.push({key:"brake_balance",why:r?"the diagram is drawn under acceleration, not braking":"no braking: the diagram is drawn at constant speed"});let a=n?"the longitudinal condition is set directly; what a motor could deliver is the lap solver\u2019s question":"no tractive force is applied at a constant speed";for(let s of["gear_ratio","power_scale","power_limit_kw","driven_wheels","effi_pgb"])o.push({key:s,why:a});for(let s of["I_wheel","I_rotor"])o.push({key:s,why:n?"rotating inertia is longitudinal, and `ax` is set here rather than solved \u2014 nothing in this picture spins a wheel up":"rotating inertia only acts where the car changes speed"});return o.push({key:"v_limit_endurance",why:"a limiter constrains a lap\u2019s speed profile; this diagram is drawn at one imposed speed"}),o.push({key:"endurance_reserve",why:"an energy budget sets the long event\u2019s speed ceiling; this diagram is drawn at one imposed speed"}),o.push({key:"fr_0",why:n?"rolling resistance is a drag term; `ax` is what the car does, not what the tyres are handed":"rolling resistance is longitudinal"}),o.push({key:"r_dyn",why:n?"the force each tyre carries is set here in newtons; a radius would only convert it to a torque":"the rolling radius only matters where a wheel is driven or braked"}),o}var a2=tS(0);function rS(e=0){let t="Springs and bars act through the roll-stiffness split and the camber the wheels take in roll; a heave spring reaches it too, but only faintly, through how far aero pushes the car down onto its camber curve.";if(!e)return"Steady state, lateral only: every point is a car in equilibrium at constant speed. Dampers, inertias, brake balance and the whole powertrain therefore cannot appear here \u2014 not because they are ignored, but because nothing in this picture accelerates. "+t;let r=e<0?`braking at ${Math.abs(e).toFixed(2)} g`:`accelerating at ${e.toFixed(2)} g`,n=e<0?"the brake balance decides which axle pays for it":"the driven axle pays for it";return`Steady state, ${r}: the load has moved ${e<0?"forward":"rearward"} and every tyre is spending part of its grip longitudinally, so ${n}. Dampers and inertias still cannot appear \u2014 the attitude is constant, it is simply not level. `+t}var s2=rS(0);var i2=9.81;function c2(e){let t=e.wheelbase/1e3;return{lf:t*(1-e.frontMassFrac),lr:t*e.frontMassFrac}}function zi(e,t,r,n){let o=t.tire;if(!o)return null;let s=(r==="limit"?gb(e,o,t.speed):vn(e,o,t.speed,t.ayG)).wheels;return Dr(n??to(o,e.massTotal*i2*1.2),{FL:s.FL,FR:s.FR,RL:s.RL,RR:s.RR},c2(e))}function l2(e){if(!e.tire)return e.cornerStiffness;let t=ye(e.tire,"front"),r=ye(e.tire,"rear");return{front:n=>t.corneringStiffness(n),rear:n=>r.corneringStiffness(n)}}var nS=[{key:"understeer",label:"Understeer gradient",unit:"\xB0/g",compute:(e,t)=>mm(e,t.ayG,l2(t),t.speed).gradient},{key:"rollGradient",label:"Roll gradient",unit:"\xB0/g",compute:e=>we(e).rollGradient},{key:"pitchGradient",label:"Pitch gradient",unit:"\xB0/g",compute:e=>we(e).pitchGradient},{key:"tlltdFront",label:"TLLTD front",unit:"%",compute:e=>100*Pf(e)},{key:"rollStiffFront",label:"Front roll-stiffness",unit:"%",compute:e=>100*we(e).frontRollStiffFrac},{key:"rideFreqFront",label:"Ride freq front",unit:"Hz",compute:e=>we(e).rideFreqFront},{key:"rideFreqRear",label:"Ride freq rear",unit:"Hz",compute:e=>we(e).rideFreqRear},{key:"rollFreq",label:"Roll-mode freq",unit:"Hz",compute:e=>hm(e).roll.freq},{key:"pitchFreq",label:"Pitch-mode freq",unit:"Hz",compute:e=>hm(e).pitch.freq},{key:"zetaFront",label:"Damping \u03B6 front",unit:"-",compute:e=>dm(e).front.dampingRatio},{key:"zetaRear",label:"Damping \u03B6 rear",unit:"-",compute:e=>dm(e).rear.dampingRatio},{key:"yawFreq",label:"Yaw natural freq",unit:"Hz",compute:(e,t)=>Hi(e,t.speed)?.yawFreq??NaN},{key:"yawZeta",label:"Yaw damping \u03B6",unit:"-",compute:(e,t)=>Hi(e,t.speed)?.dampingRatio??NaN},{key:"stabilitySpeed",label:"Char./critical speed",unit:"km/h",compute:(e,t)=>{let r=Hi(e,t.speed);return r?r.criticalSpeed??r.characteristicSpeed??NaN:NaN}},{key:"maxAy",label:"Max lateral accel",unit:"g",compute:(e,t)=>t.fyAxle?Ub(e,t.fyAxle,t.speed,{betaMaxDeg:12,deltaMaxDeg:12}).maxAy:NaN},{key:"yawReserveRear",label:"Yaw stability reserve",unit:"N\xB7m",compute:(e,t)=>zi(e,t,"operating")?.stabil??NaN},{key:"yawReserveFront",label:"Yaw agility reserve",unit:"N\xB7m",compute:(e,t)=>zi(e,t,"operating")?.agil??NaN},{key:"limitBalance",label:"Limit balance (+US / \u2212OS)",unit:"-",compute:(e,t)=>zi(e,t,"limit")?.rel??NaN},{key:"yawStiffness",label:"Yaw stiffness N_\u03B2",unit:"N\xB7m/rad",compute:(e,t)=>t.tire?bb(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorque",label:"Steering holding torque",unit:"N\xB7m",compute:(e,t)=>t.tire?fb(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorqueGradient",label:"Steering feedback gradient",unit:"N\xB7m/g",compute:(e,t)=>t.tire?hb(e,t.tire,t.speed,t.ayG):NaN}],qb=Object.fromEntries(nS.map(e=>[e.key,e]));var Zr=9.81;function u2(e,t,r){let n=Math.abs(e);return n>0?t>0&&(n<=t||t>=r)?n/t:r>0?1+(n-t)/r:2:0}var m2={front:!1,rear:!0};function Ka(e,t,r){let n=e.muX(t)*t,o=e.muY(t)*t;if(!(n>0))return 0;let a=o>0?Math.min(1,r/o):1;return n*Math.sqrt(1-a*a)}function oS(e,t,r,n,o,a){let s=e[t]+e[r];if(!(s>0))return;let i=Ka(n,o[t],a[t]),c=Ka(n,o[r],a[r]);i+c>0||(i=n.muX(o[t])*o[t],c=n.muX(o[r])*o[r]),i+c>0&&(e[t]=s*i/(i+c),e[r]=s-e[t])}function aS(e,t,r,n,o,a={},s="open"){if(!e.rear)return 1;if(!e.front)return 0;let i=(f,p,d)=>d?di(f,p,d):s==="own"?f+p:2*Math.min(f,p),c=i(Ka(n,t.FL,r.FL),Ka(n,t.FR,r.FR),a.front),l=i(Ka(o,t.RL,r.RL),Ka(o,t.RR,r.RR),a.rear);if(c+l>0)return c/(c+l);let u=n.muX(t.FL)*t.FL+n.muX(t.FR)*t.FR,m=o.muX(t.RL)*t.RL+o.muX(t.RR)*t.RR;return u+m>0?u/(u+m):.5}function Qb(e,t,r,n){return{car:t?cS(t,r.loadFactor[n]):e,ayTyre:He(r.ay[n],r.bank?.[n]??0),axCar:r.ax[n]-(r.axGrade?.[n]??0)}}function sS(e,t){if(!e.aero?.model)return 0;let r=Math.min(t.v.length,t.ax.length,t.ay.length),n=t.loadFactor?ym(e):void 0,o=0,a=0;for(let s=0;s<r;s++){let i=t.ds?.[s]??1,c=Qb(e,n,t,s);o+=i,Tf(c.car,t.v[s],c.axCar/Zr,c.ayTyre/Zr)&&(a+=i)}return o>0?a/o:0}function iS(e,t,r){let n=Qt(ye(t,"front")),o=Qt(ye(t,"rear")),a=Math.min(r.v.length,r.ax.length,r.ay.length),s=r.loadFactor?ym(e):void 0,i=0,c=0;for(let l=0;l<a;l++){let u=r.ds?.[l]??1,m=Qb(e,s,r,l);i+=u;let f=Ce(m.car,m.ayTyre/Zr,m.axCar/Zr,r.v[l]);(f.FL>n||f.FR>n||f.RL>o||f.RR>o)&&(c+=u)}return i>0?c/i:0}function gm(e,t,r,n={}){let o=Math.min(r.v.length,r.ax.length,r.ay.length),a=e.wheelbase/1e3,s=a*(1-e.frontMassFrac),i=a*e.frontMassFrac,c=Ri(t,e.massTotal*Zr*1.2),l=ba(c,"front"),u=ba(c,"rear"),m=ft(ye(t,"front")),f=ft(ye(t,"rear")),p=n.perWheel?If(m,l):null,d=n.perWheel?f===m?p:If(f,u):null,h=n.driven??m2,b={front:zt(e,"front",1),rear:zt(e,"rear",1)},g={front:0,rear:0},y=new Array(o),R=new Array(o),k=new Array(o),v=1/0,x=0,M=0,F=Qt(m),w=Qt(f),T=0,P=0,A=0,S=0,C=0,L=0,D=["FL","FR","RL","RR"],I=n.perWheel?Object.fromEntries(D.map(N=>[N,{Fz:new Array(o),alpha:new Array(o),Fy:new Array(o),Fx:new Array(o),Mz:new Array(o),used:new Array(o),FxCap:new Array(o),FyCap:new Array(o)}])):void 0,O=r.loadFactor?ym(e):void 0;for(let N=0;N<o;N++){let z=Qb(e,O,r,N),{ayTyre:E,axCar:_}=z,B=E/Zr,V=Ce(z.car,B,_/Zr,r.v[N]),G=e.massTotal*E,K=G*i/a,Y=G*s/a,j=js(m,K,V.FL,V.FR,C),Z=js(f,Y,V.RL,V.RR,L);C=j,L=Z;let ne={FL:Math.abs(m.Fy(j,V.FL,0)),FR:Math.abs(m.Fy(j,V.FR,0)),RL:Math.abs(f.Fy(Z,V.RL,0)),RR:Math.abs(f.Fy(Z,V.RR,0))},te=(_-(r.axDrag?.[N]??0)-(r.axScrub?.[N]??0))/Zr,fe=te>0&&h.front?aS(h,V,ne,l,u,b,"own"):0,W=r.v[N]*r.v[N],J=e.driveline?{Fz:V,alpha:{front:j,rear:Z},curvature:W>1?r.ay[N]/W:0,seed:g}:void 0,re={...ub(e,te,r.v[N],t,B,fe,J)};te>0&&(b.front||oS(re,"FL","FR",l,V,ne),b.rear||oS(re,"RL","RR",u,V,ne));let pe=!1,de=!1;for(let ue of["FL","FR","RL","RR"]){let $e=(ue==="FL"||ue==="FR"?l:u).muX(V[ue])*V[ue];Math.abs(re[ue])>$e&&(pe=!0),V[ue]>(ue==="FL"||ue==="FR"?F:w)&&(de=!0)}de&&(M+=r.ds?.[N]??1);let ie=Dr(c,{FL:{Fz:V.FL,Fy:ne.FL,Fx:re.FL},FR:{Fz:V.FR,Fy:ne.FR,Fx:re.FR},RL:{Fz:V.RL,Fy:ne.RL,Fx:re.RL},RR:{Fz:V.RR,Fy:ne.RR,Fx:re.RR}},{lf:s,lr:i});if(y[N]=ie.stabil,R[N]=ie.agil,k[N]=ie.rel,I){let ue=.5*(V.FL+V.FR),$e=.5*(V.RL+V.RR),Ae=l.muX(ue)*ue,le=u.muX($e)*$e;for(let Re of D){let Te=V[Re],ze=Re==="FL"||Re==="FR",Ue=ze?l:u,be=Ue.muY(Te)*Te,Fe=Ue.muX(Te)*Te,xe=I[Re],me=ze?j:Z;xe.Fz[N]=Te,xe.alpha[N]=me,xe.Fy[N]=ne[Re],xe.Fx[N]=re[Re],xe.Mz[N]=Te>0?(ze?m:f).Mz(me,Te,0):0,xe.FxCap[N]=Fe,xe.FyCap[N]=be;let Le=be>0?Math.min(1,Math.abs(ne[Re])/be):0,Se=u2(re[Re],Fe,ze?Ae:le),Ye=ze?p:d,Xe=Ye&&Te>0?Ye.reach(Te,Math.sign(re[Re])*Se,Le):1;xe.used[N]=Math.hypot(Le,Se)/Xe}}ie.stabil<v&&(v=ie.stabil,x=N);let oe=r.ds?.[N]??1;S+=oe,ie.diff>0&&(T+=oe),pe&&(P+=oe),Tf(z.car,r.v[N],_/Zr,B)&&(A+=oe)}return{stabil:y,agil:R,rel:k,minStabil:Number.isFinite(v)?v:0,minStabilAt:x,pastTurnoverFrac:S>0?M/S:0,understeerFrac:S>0?T/S:0,beyondFrac:S>0?P/S:0,aeroOutsideFrac:S>0?A/S:0,wheels:I}}function ym(e){return Object.create(e,{loadFactor:{value:1,writable:!0,enumerable:!0}})}function cS(e,t){return e.loadFactor=t,e}var Zb=9.81;function Jb(e,t,r,n={}){let o=r.v.length,a=e.massTotal,s=Kr(e),i=s.mode==="hydraulic",c={front:new Array(o).fill(0),rear:new Array(o).fill(0),...n.regen?{regen:new Array(o).fill(0)}:{},...i?{pFront:new Array(o).fill(0),pRear:new Array(o).fill(0),pedalN:new Array(o).fill(0)}:{}};for(let l=0;l<o;l++){let u=r.v[l],m=r.ax[l]-(r.axGrade?.[l]??0),f=m-(r.axDrag?.[l]??0)-(r.axScrub?.[l]??0),p=-a*f;if(!(p>0))continue;let d=He(r.ay[l],r.bank?.[l]??0)/Zb,h=Math.min(.99,Math.max(.01,Aa(e,f/Zb,u,t,d)));c.front[l]=p*h,c.rear[l]=p*(1-h);let b=i?Mu(e,t,p,u,d):void 0;if(c.regen&&n.regen&&(c.regen[l]=b?Math.min(p,b.regenFront+b.regenRear):n.regen(p,u,m/Zb)),c.regen&&b){let g=b.regenFront+b.regenRear,y=g>0?c.regen[l]/g:0;(c.regenFront??=new Array(o).fill(0))[l]=b.regenFront*y,(c.regenRear??=new Array(o).fill(0))[l]=b.regenRear*y}if(i){let g=b?b.demand:s.demand(s.controlFor(p,u),u);c.pFront[l]=g.pFront,c.pRear[l]=g.pRear,c.pedalN[l]=g.pedalN}}return c}var pZ=Math.PI/180;var dZ=Yb.map(vi);var fZ=[ce.zFL,ce.zFR,ce.zRL,ce.zRR];var hZ=Array.from({length:ce.rollRate+1},(e,t)=>t);var S2=9.81,A2=.001,F2=.6,w2=2,pS=4;function dS(e,t,r,n=pS){let o=Math.min(e.v.length,t.npts),{ds:a,closed:s}=t,i=r.massTotal*S2*r.wheelbase,c=C2(e.ay.slice(0,o).map((m,f)=>m/Math.max(A2,e.v[f])),a,s,n),l=new Array(o).fill(0),u=new Array(o).fill(0);if(!(i>0))return{demand:l,rdot:u};for(let m=0;m<o;m++){let f=m===0?s?o-1:-1:m-1,p=m===o-1?s?0:-1:m+1;if(f<0||p<0)continue;let d=a[f]+a[m];if(!(d>0))continue;u[m]=e.v[m]*(c[p]-c[f])/d;let h=Math.sign(c[m]);l[m]=h===0?0:h*r.yawInertia*u[m]/i}return{demand:l,rdot:u}}function C2(e,t,r,n){let o=e.length;if(!(n>0)||o<3)return e;let a=new Array(o);a[0]=0;for(let c=1;c<o;c++)a[c]=a[c-1]+t[c-1];let s=r?Math.floor((o-1)/2):o-1,i=new Array(o);for(let c=0;c<o;c++){let l=r?n:Math.min(n,a[c],a[o-1]-a[c]),u=e[c],m=1,f=0;for(let p=1;p<=s&&!(!r&&c+p>=o||(f+=t[(c+p-1)%o],!(f<l)));p++){let d=1-f/l;u+=d*e[(c+p)%o],m+=d}f=0;for(let p=1;p<=s&&!(!r&&c-p<0);p++){let d=(c-p+o)%o;if(f+=t[d],!(f<l))break;let h=1-f/l;u+=h*e[d],m+=h}i[c]=u/m}return i}function fS(e,t,r,n,o={}){let a=o.maxIter??20,s=o.tol??.001,i=Math.min(1,Math.max(.001,o.relax??F2)),c=o.smoothM??pS,l={standingStart:o.standingStart,...o.driveDerate?{driveDerate:o.driveDerate}:{},...o.brakeFade?{brakeFade:o.brakeFade}:{},...o.vCeiling?{vCeiling:o.vCeiling}:{},...o.load?{load:o.load}:{},...o.shifts?{shifts:o.shifts}:{}},u=At(e.steady,t,n,l),m=[u.laptime],f=new Array(t.npts).fill(0),p=f.slice(),d=u,h=0,b=!1,g=0;for(let k=0;k<a;k++){h=k+1;let v=dS(d,t,r,c);f=v.demand.map((F,w)=>f[w]+i*(F-f[w])),p=v.rdot;let x=At(e.steady,t,n,{...l,envelope:F=>e.at(f[F]??0)});m.push(x.laptime);let M=Math.abs(x.laptime-d.laptime);if(d=x,g=M<=s?g+1:0,g>=w2){b=!0;break}}let y=0,R=0;for(let k=0;k<t.npts;k++)R+=t.ds[k],e.clamps(f[k]??0)&&(y+=t.ds[k]);return{...d,steady:u,demand:f,rdot:p,history:m,iterations:h,converged:b,clampedFrac:R>0?y/R:0}}var SZ=Math.PI/180;var rJ=180/Math.PI;function Ha(e,t,r){let n=e.length;if(n===1||r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0;for(;o<n-2&&e[o+1]<=r;)o++;let a=e[o],s=e[o+1],i=t[o],c=t[o+1];if(n===2)return i+(r-a)/(s-a)*(c-i);let l=f=>{let p=e[f];return i*(r-s)*(r-p)/((a-s)*(a-p))+c*(r-a)*(r-p)/((s-a)*(s-p))+t[f]*(r-a)*(r-s)/((p-a)*(p-s))},u=(r-a)/(s-a),m=o===0?l(2):o+1===n-1?l(o-1):(1-u)*l(o-1)+u*l(o+2);return Math.min(Math.max(i,c),Math.max(Math.min(i,c),m))}function bS(e,t){let r=e.filter(p=>p.atLock),n=e.filter(p=>!p.atLock),o=r.length>0&&n.length>0&&r[r.length-1].v<n[0].v,a=p=>({vs:p.map(h=>h.v),ayMax:p.map(h=>h.ayMax),radius:p.map(h=>Math.max(h.v,t)**2/h.ayMax),accel:p[0].axAccelN.map((h,b)=>p.map(g=>g.axAccelN[b])),decel:p[0].axDecelN.map((h,b)=>p.map(g=>g.axDecelN[b])),scrub:p[0].axScrubN.map((h,b)=>p.map(g=>g.axScrubN[b]))}),s=(p,d)=>({axAccelN:p.accel.map(h=>Ha(p.vs,h,d)),axDecelN:p.decel.map(h=>Ha(p.vs,h,d)),axScrubN:p.scrub.map(h=>Ha(p.vs,h,d))});if(!o){let p=a(e);return d=>({ayMax:Ha(p.vs,p.ayMax,d),...s(p,d)})}let i=a(r),c=a(n),l=i.vs[i.vs.length-1],u=c.vs[0],m=p=>Math.max(p,t)**2/Ha(i.vs,i.radius,p),f=p=>p>=u||c.vs.length<2?Ha(c.vs,c.ayMax,p):c.ayMax[0]+(c.ayMax[1]-c.ayMax[0])/(c.vs[1]-c.vs[0])*(p-u);return p=>{if(p<=l)return{ayMax:m(p),...s(i,p)};if(p>=u)return{ayMax:f(p),...s(c,p)};let d=m(p),h=f(p);return d<h?{ayMax:d,...s(i,p)}:{ayMax:h,...s(c,p)}}}function Y2(e,t){let r=Math.abs(e.ayMax-t.ayMax)/Math.max(t.ayMax,1),n=Math.max(Math.abs(t.axAccelN[0]),1),o=Math.max(Math.abs(t.axDecelN[0]),1);for(let a=0;a<t.axAccelN.length;a++)r=Math.max(r,Math.abs(e.axAccelN[a]-t.axAccelN[a])/n,Math.abs(e.axDecelN[a]-t.axDecelN[a])/o,Math.abs(e.axScrubN[a]-t.axScrubN[a])/n);return r}function gS(e,t,r,n,o){let a=r>t?Math.max(2,Math.min(5,Math.floor(n))):1,s=[];for(let f=0;f<a;f++)s.push(e(a===1?t:t+(r-t)*f/(a-1)));let i=bS(s,t),c=[],l=a,u=(f,p)=>{let d=.5*(f+p),h=e(d);l++;let b=Y2(i(d),h);s.splice(s.findIndex(g=>g.v>d),0,h),i=bS(s,t),b>o&&c.push({lo:f,hi:d,misfit:b},{lo:d,hi:p,misfit:b})},m=s.map(f=>f.v);for(let f=0;f+1<m.length&&l<n;f++)m[f+1]-m[f]>=1&&u(m[f],m[f+1]);if(m.length>1){let f=.5*(m[0]+m[1]);if(s.some(p=>p.v===f))for(let[p,d]of[[m[0],f],[f,m[1]]]){if(l>=n||d-p<1)break;let h=c.findIndex(b=>b.lo===p&&b.hi===d);h>=0&&c.splice(h,1),u(p,d)}}for(;l<n&&c.length>0;){let f=0;for(let b=1;b<c.length;b++)c[b].misfit>c[f].misfit&&(f=b);let{lo:p,hi:d,misfit:h}=c.splice(f,1)[0];if(h<=o)break;d-p<1||u(p,d)}return{anchors:s,at:i}}var W2=2,j2=.5,Yi=Math.PI/180,yS=21,U2={nCoarse:11,nSteer:13,nNorm:41,nAngle:45},X2={nCoarse:11,nSteer:13,nNorm:41,nAngle:61},q2=.005,Q2=.05,eg=e=>e<0?0:e>1?1:e;function Z2(e,t,r,n){let o=e.massTotal,a=n.nSteer??7,s=(n.drivenFront?2:0)+(n.drivenRear?2:0),i=Ce(e,0,0,r),c=Math.max(1,(i.FL+i.FR+i.RL+i.RR)/4),l=8*Yi,u=0,m=(b,g,y)=>{for(let R=b;R<=g;R+=y){let k=Math.abs(t.Fy(R*Yi,c,0));k>u&&(u=k,l=R*Yi)}};m(1,45,1),m(Math.max(.1,l/Yi-1),l/Yi+1,.1);let f=[],p=[],d=[],h=[];for(let b=0;b<a;b++){let g=b/(a-1),y=l*(g+Math.sin(Math.PI/2*g))/2,R=Math.abs(t.Fy(y,c,0));f.push(4*R/o),p.push(s*Pt(t,c,R,!1)/o),d.push(4*Pt(t,c,R,!0)/o),h.push(-4*R*Math.sin(y)/o)}return f[0]=0,{ayMax:4*u/o,ay:f,axAccel:p,axDecel:d,axScrub:h,rollover:!1}}function yr(e,t=!1,r="twoTrack",n,o,a=0,s=1){if(a!==0&&r==="fast")throw new Error('the fast (point-mass) envelope has no yaw balance to shift; use mode "twoTrack" for a yaw-inertia demand');let i=n??(t?X2:U2),{nCoarse:c,nSteer:l,nAngle:u}=i,m=Gr(0,1,i.nNorm).map(B=>Math.sin(Math.PI/2*B)),f=e.params,p=f.m.value,d=f.rho.value,h=f.fr_0.value,b=f.driven_wheels.value,g=f.power_scale.value,y=e.FG,R=gt(f);s!==1&&(R.loadFactor=s);let k=gr(f),v=T1(0,n?.vRes??(e.engine?j2:W2),e.vMax);v[v.length-1]<e.vMax&&v.push(e.vMax);let x=e.fRad.map(B=>B*b),M=e.fAxle,{drivenFront:F,drivenRear:w}=po(e),T=mo(f,F,w),P=(B,V)=>{let G=M?ht(M.vVehicle,B,V):NaN;return Number.isFinite(G)?G:1/0},A=B=>{let V=B*B,{cl:G,cw:K,A:Y}=rm(f,B,0,R),j=.5*d*-K*Y*V,Z=.5*d*-G*Y*V,ne=h*(-Z+y);return j+ne},S=B=>{let V=A(B)/p*T.powerFactor,G=A(B)/p*T.tractionFactor,K;if(e.engine){let j=A(B);K=ka(e.engine,B,T.effective,j,g).accel-V}else if(M){let j=0;F&&(j+=P(M.fFront,B)),w&&(j+=P(M.fRear,B)),K=g*j/p*T.powerFactor}else{let j=ht(e.vVehicle,x,B),Z=g*j/p*T.powerFactor;K=Number.isFinite(Z)?Z:1/0}let Y=cm(f,B,o)/p*T.powerFactor;return{axDrag:V,axDragTyre:G,axDrive:K,axPackCap:Y,axPower:Math.min(K,Y)}},C=v.map(S),L=e.vMax;for(let B=1;B<v.length;B++){let V=C[B].axDrive+C[B].axDrag;if(V>0)continue;let G=C[B-1].axDrive+C[B-1].axDrag;L=G>0?v[B-1]+(v[B]-v[B-1])*G/(G-V):v[B-1];break}let D=Math.min(e.vMax,(1+Q2)*L),I=r==="fast"?Z2:xb,O=B=>{let V=I(R,k,B,{drivenFront:F,drivenRear:w,nSteer:l,yawDemandCn:a,axDrag:A(B)/p,...f.diffYaw?{diffYaw:!0}:{}}),G=V.ay[0],K=V.ay[V.ay.length-1],Y=te=>Math.min(Math.max(te*V.ayMax,G),K),j=m.map(te=>fu(V.ay,V.axAccel,Y(te))*T.tractionFactor),Z=m.map(te=>fu(V.ay,V.axDecel,Y(te))),ne=m.map(te=>fu(V.ay,V.axScrub,Y(te))*T.tractionFactor);return{v:B,ayMax:V.ayMax,axAccelN:j,axDecelN:Z,axScrubN:ne,atLock:V.atLock===!0}},N=r==="fast"?0:Math.min(Pu,D),z=gS(O,N,D,c,i.anchorTol??q2),E=[],_=[];for(let B=0;B<v.length;B++){let V=v[B],{axDrag:G,axDragTyre:K,axDrive:Y,axPackCap:j,axPower:Z}=C[B],{ayMax:ne,axAccelN:te,axDecelN:fe,axScrubN:W}=z.at(V);E.push({v:V,ayMax:ne,axTyreAcc:te[0],axTyreDec:fe[0],axDrive:Y,axPackCap:j,axPower:Z,axDrag:G,axDragTyre:K,axAccelN:te,axDecelN:fe,axScrubN:W});let J=[],re=[];for(let de=0;de<u;de++){let ie=Math.PI*de/(u-1),oe=ne*Math.cos(ie),ue=eg(Math.abs(Math.cos(ie)));J.push({ax:Math.min(ht(m,te,ue)+K,Z+G)+ht(m,W,ue),ay:oe,v:V})}for(let de=u-1;de>=0;de--){let ie=Math.PI*de/(u-1),oe=ne*Math.cos(ie),ue=eg(Math.abs(Math.cos(ie)));re.push({ax:ht(m,fe,ue)+G+ht(m,W,ue),ay:oe,v:V})}let pe=(de,ie,oe)=>Array.from({length:yS},(ue,$e)=>({ax:ie+(oe-ie)*($e+1)/(yS+1),ay:de,v:V}));_.push([...J,...pe(-ne,J[J.length-1].ax,re[0].ax),...re,...pe(ne,re[re.length-1].ax,J[0].ax)])}return{...RS(E,m),rows:E,norm:m,surf:_}}function za(e,t){return e?.length?t.map(r=>Rm(e,r)):t.map(()=>0)}function Rm(e,t){let r=e.length-1;if(!(t>e[0].v))return e[0].axDrag;if(t>=e[r].v)return e[r].axDrag;let n=0,o=r;for(;o-n>1;){let s=n+o>>1;e[s].v<=t?n=s:o=s}let a=(t-e[n].v)/(e[o].v-e[n].v);return e[n].axDrag+a*(e[o].axDrag-e[n].axDrag)}function RS(e,t){let r=e[e.length-1].v,n=d=>{if(d<=e[0].v)return{i0:0,i1:0,t:0};if(d>=r)return{i0:e.length-1,i1:e.length-1,t:0};let h=0,b=e.length-1;for(;b-h>1;){let g=h+b>>1;e[g].v<=d?h=g:b=g}return{i0:h,i1:b,t:(d-e[h].v)/(e[b].v-e[h].v)}},o=d=>{let{i0:h,i1:b,t:g}=n(d);return{a:e[h],b:e[b],t:h===b?0:g}},a=(d,h,b)=>d===0||h===b?h:h+d*(b-h),s=(d,h,b,g)=>d===0?ht(t,h,g):a(d,ht(t,h,g),ht(t,b,g)),i=(d,h)=>h>=1?d.axPower:Math.min(h*d.axDrive,d.axPackCap),c=({a:d,b:h,t:b},g,y)=>d.axScrubN?y*s(b,d.axScrubN,h.axScrubN,g):0,l=d=>d.axDragTyre??d.axDrag,u=({a:d,b:h,t:b},g,y)=>{let R=y*a(b,d.ayMax,h.ayMax);return R>0?eg(g/R):1},m=(d,h,b=1,g=1)=>{let{a:y,b:R,t:k}=d,v=u(d,h,b),x=b*s(k,y.axAccelN,R.axAccelN,v)+a(k,l(y),l(R)),M=a(k,i(y,g),k===0?0:i(R,g))+a(k,y.axDrag,R.axDrag);return Math.min(x,M)+c(d,v,b)},f=(d,h,b=1,g=1)=>{let{a:y,b:R,t:k}=d,v=u(d,h,b),x=s(k,y.axDecelN,R.axDecelN,v);return(g===1||x>0?b*x:g*b*x)+a(k,y.axDrag,R.axDrag)+c(d,v,b)},p=({a:d,b:h,t:b},g,y=1)=>{let R=t.length-1,k=d.axAccelN,v=h.axAccelN,x=d.axDecelN,M=h.axDecelN,F=d.axScrubN,w=h.axScrubN,T=I=>k[I]+b*(v[I]-k[I]),P=I=>x[I]+b*(M[I]-x[I]),A=I=>F?y*(F[I]+b*(w[I]-F[I])):0,S=a(b,d.ayMax,h.ayMax),C=a(b,d.axDrag,h.axDrag),L=a(b,l(d),l(h)),D=a(b,d.axPower,h.axPower);for(let I=R;I>=0;I--){let O=Math.min(y*T(I)+L,D+C)+A(I),N=y*P(I)+C+A(I);if(!(g<=O+1e-6&&g>=N-1e-6))continue;if(I===R)return t[I]*y*S;let z=(V,G,K)=>{if(K(G))return 1;let Y=(V-g)/(V-G);return Y>0?Math.min(Y,1):0},E=V=>g<=V+1e-6,_=V=>g>=V-1e-6,B=Math.min(z(y*T(I)+L+A(I),y*T(I+1)+L+A(I+1),E),z(D+C+A(I),D+C+A(I+1),E),z(y*P(I)+C+A(I),y*P(I+1)+C+A(I+1),_));return(t[I]+B*(t[I+1]-t[I]))*y*S}return 0};return{vMax:r,axAccel:(d,h,b=1,g=1)=>m(o(d),h,b,g),axDecel:(d,h,b=1,g=1)=>f(o(d),h,b,g),ay:(d,h,b=1)=>p(o(d),h,b),scrub:(d,h,b=1)=>{let g=o(d);return c(g,u(g,h,b),b)}}}function J2(e,t,r){let n=e.params,o=n.m.value,{drivenFront:a,drivenRear:s}=po(e),i=mo(n,a,s);return c=>cm(n,c,t,r)/o*i.powerFactor}function Wi(e,t,r,n){let o=J2(t,r,n),a=e.rows.map(s=>{let i=o(s.v),c=Math.min(s.axDrive,i);return c===s.axPower&&i===s.axPackCap?s:{...s,axPackCap:i,axPower:c}});return{...RS(a,e.norm),rows:a,norm:e.norm}}var e_=[-.2,-.08,0,.06,.12,.2,.3];function vS(e,t=!1,r="twoTrack",n,o,a=e_){let s=[...new Set([...a,0])].sort((d,h)=>d-h),i=s.map(d=>yr(e,t,r,n,o,d)),c=i[s.indexOf(0)],l=s[0],u=s[s.length-1],m=d=>{if(d<=l)return{i:0,t:0};if(d>=u)return{i:s.length-1,t:0};let h=0;for(;h<s.length-2&&s[h+1]<=d;)h++;return{i:h,t:(d-s[h])/(s[h+1]-s[h])}},f=d=>{let h=b=>{let{i:g,t:y}=m(b);return{a:d[g],b:d[Math.min(d.length-1,g+1)],t:y}};return b=>{let{a:g,b:y,t:R}=h(b);if(R===0)return g;let k=(v,x)=>v+R*(x-v);return{vMax:g.vMax,axAccel:(v,x,M=1,F=1)=>k(g.axAccel(v,x,M,F),y.axAccel(v,x,M,F)),axDecel:(v,x,M=1,F=1)=>k(g.axDecel(v,x,M,F),y.axDecel(v,x,M,F)),ay:(v,x,M=1)=>k(g.ay(v,x,M),y.ay(v,x,M)),scrub:(v,x,M=1)=>k(g.scrub?.(v,x,M)??0,y.scrub?.(v,x,M)??0)}}},p=d=>d<l||d>u;return{anchors:s,steady:c,clamps:p,at:f(i),atSoc(d,h,b){let g=i.map(y=>Wi(y,d,h,b));return{anchors:s,steady:g[s.indexOf(0)],clamps:p,at:f(g)}}}}function kS(e,t,r,n="twoTrack",o){let a=[...new Set([...t,1])].sort((i,c)=>i-c),s=a.map(i=>i===1?r:yr(e,!1,n,o,void 0,0,i));return{...xS(a,s),atSoc:(i,c,l)=>xS(a,s.map(u=>Wi(u,i,c,l)))}}function xS(e,t){let r=e.length-1,n=1,o=0,a=0,s=0,i=1,c=0,l=0,u=p=>{if(n=1,!(p>e[0]))return void(o=0);if(p>=e[r])return void(o=r);let d=0;for(;d<r-1&&e[d+1]<=p;)d++;if(o=d,p===e[d])return;a=d+1;let h=e[d],b=e[d+1];if(r<2){n=2,c=(p-h)/(b-h),i=1-c;return}s=d===0?2:d+1===r||p-e[d-1]<e[d+2]-p?d-1:d+2;let g=e[s];n=3,i=(p-b)*(p-g)/((h-b)*(h-g)),c=(p-h)*(p-g)/((b-h)*(b-g)),l=(p-h)*(p-b)/((g-h)*(g-b))},m=p=>{let d=p(t[o]);if(n===1)return d;let h=p(t[a]);if(n===2)return i*d+c*h;let b=i*d+c*h+l*p(t[s]);return Math.min(Math.max(d,h),Math.max(Math.min(d,h),b))},f=(p,d,h,b,g)=>{if(u(p),n===1||h===0)return m(k=>g(k,h));let y=m(k=>k.ay(d,0,b));if(!(y>0))return m(k=>g(k,h));let R=h/y;return m(k=>g(k,R*k.ay(d,0,b)))};return{anchors:e,axAccel:(p,d,h,b=1,g=1)=>f(p,d,h,b,(y,R)=>y.axAccel(d,R,b,g)),axDecel:(p,d,h,b=1,g=1)=>{let y=R=>f(p,d,h,b,(k,v)=>k.axDecel(d,v,b,R));return g===1?y(1):Nb(y(g),y(1),g)},scrub:(p,d,h,b=1)=>f(p,d,h,b,(g,y)=>g.scrub?.(d,y,b)??0),ay:(p,d,h,b=1)=>{if(u(p),n===1||h===0)return m(k=>k.ay(d,h,b));let g=k=>h>0?k.axAccel(d,0,b):-k.axDecel(d,0,b),y=m(g);if(!(y>0))return m(k=>k.ay(d,h,b));let R=h/y;return m(k=>k.ay(d,R*g(k),b))}}}var MS=new WeakMap;function tg(e,t){let r=MS.get(e);if(!r){let n=$r(e).regen?Kb(t??Dt(e)):void 0;r={inp:gt(e),ev:gr(e),...n?{regen:n}:{}},MS.set(e,r)}return r}function rg(e,t,r){let n=tg(e,r);return Jb(n.inp,n.ev,t,n.regen?{regen:n.regen}:{})}function ng(e){let t=bt(e);if(t.mode!=="hydraulic")return null;let r=a=>a.heat?{heat:yh(a.heat,a.ratio),discs:a.discs}:void 0,n=r(t.hydraulic.front),o=r(t.hydraulic.rear);return n||o?{...n?{front:n}:{},...o?{rear:o}:{}}:null}function t_(e){let t=(r,n)=>n?r.map((o,a)=>Math.max(0,o-n[a])):r;return{front:t(e.front,e.regenFront),rear:t(e.rear,e.regenRear)}}function og(e,t,r,n,o,a=Lt){if(!e)return null;let s=t_(t);return{...e.front?{front:lu(e.front.heat,e.front.discs,s.front,r,n,o.front,a)}:{},...e.rear?{rear:lu(e.rear.heat,e.rear.discs,s.rear,r,n,o.rear,a)}:{}}}var r_=.5,n_=.02,o_=6,vm=9,SS=1e-9,a_={FL:0,FR:0,RL:0,RR:0};function ag(e){return e?[...new Set([...e.padCurve.factor,1])].sort((t,r)=>t-r):[1]}function s_(e,t,r){let n=dr(e),o=n.hydraulic;return n.mode!=="hydraulic"||!o?e:{...e,brakes:{...n,hydraulic:{...o,front:{...o.front,padMu:o.front.padMu*t},rear:{...o.rear,padMu:o.rear.padMu*r}}}}}function AS(e,t){let r=e.length;if(r===1||t<=e[0])return{i:0,t:0};if(t>=e[r-1])return{i:r-2,t:1};let n=0;for(;n<r-2&&e[n+1]<=t;)n++;return{i:n,t:(t-e[n])/(e[n+1]-e[n])}}function FS(e,t,r,n,o=()=>0){let a=Array.from({length:vm},(m,f)=>r*f/(vm-1)),s=yi(),{front:i,rear:c}=n,l=a.map(m=>{let f=o(m),p=h=>Hr(h,t,m,s).limitAt(0,0,a_,f).ax,d=p(e);return i.map(h=>c.map(b=>{if(h===1&&b===1)return 1;let g=d<0?p(s_(e,h,b))/d:1;return Math.abs(g-1)<SS?1:g}))}),u=a[1]-a[0];return{share(m,f,p){if(f===1&&p===1)return 1;let d=u>0?Math.min(vm-2,Math.max(0,Math.floor(m/u))):0,h=u>0?Math.min(1,Math.max(0,(m-a[d])/u)):0,b=AS(i,f),g=AS(c,p),y=k=>{let v=l[k],x=Math.min(i.length-1,b.i+1),M=Math.min(c.length-1,g.i+1),F=v[b.i][g.i]+g.t*(v[b.i][M]-v[b.i][g.i]),w=v[x][g.i]+g.t*(v[x][M]-v[x][g.i]);return F+b.t*(w-F)},R=y(d)+h*(y(Math.min(vm-1,d+1))-y(d));return Math.abs(R-1)<SS?1:R}}}function i_(e,t){let{front:r,rear:n}=t;return(o,a)=>e.share(a,r?.[o]??1,n?.[o]??1)}var c_=e=>(e.front??[]).every(t=>t===1)&&(e.rear??[]).every(t=>t===1);function wS(e,t,r){let n=e(),o=1,a=t(n);if(c_(a))return{lap:n,solves:o,converged:!0};let s={...a.front?{front:a.front.slice()}:{},...a.rear?{rear:a.rear.slice()}:{}},i=!1;for(let c=0;c<o_;c++){let l=e(i_(r,s));o++;let u=Math.abs(l.laptime-n.laptime);if(n=l,u<n_){i=!0;break}a=t(n);let m=(d,h)=>d&&h?d.map((b,g)=>b+r_*((h[g]??1)-b)):d,f=m(s.front,a.front),p=m(s.rear,a.rear);s={...f?{front:f}:{},...p?{rear:p}:{}}}return{lap:n,pads:s,solves:o,converged:i}}function An(e,t){let r=e.engine;if(!r||r.gears.length===0||t.length===0)return;let n=e.params,{drivenFront:o,drivenRear:a}=po(e),s=mo(n,o,a).effective,i=n.power_scale.value,{up:c,down:l}=Eh(r.engine.gearbox),u=r.engine.idleRpm,m=(f,p,d)=>(i*r.force(f,p)+d)/(s+r.inertiaMass(f,p));return{count:r.gears.length,up:c,down:l,kept:Ih(r.engine.gearbox),limitRpm:r.engine.limitRpm,best:f=>ka(r,f,s,Rm(t,f)*s,i).gear,share:(f,p)=>{let d=Rm(t,f),h=d*s,b=ka(r,f,s,h,i);if(p===b.gear)return 1;let g=b.accel-d;return g>0?Math.min(1,Math.max(0,(m(f,p,h)-d)/g)):0},rpm:(f,p)=>r.slipping(f,p)?u:r.rpm(f,p),vIdle:f=>r.gears[f]?.vIdle??0}}var CS=new WeakMap;function ig(e){let t=CS.get(e.ggv);return t===void 0&&(t=An(e.vehicle,e.ggv.rows)??null,CS.set(e.ggv,t)),t??void 0}function l_(e){return e.gear&&e.engineRpm&&e.shifting?{gear:e.gear,rpm:e.engineRpm,shifting:e.shifting}:{}}var Mm=class extends Error{constructor(t){super(t),this.name="EventError"}};function u_(e,t){let{ggv:r}=t,n=ct(t.numerics),o=n.accelStep,a=Math.max(1,Math.round(e.distance/o)),s=Na(r,new Array(a+1).fill(0),n);s[0].v=e.vStart??0;for(let d=0;d<s.length-1;d++){let h=s[d],b=s[d+1];h.v>=b.v||(h.ax=r.axAccel(h.v,0),b.v=Math.min(r.vMax,Math.sqrt(Math.max(0,h.v*h.v+2*h.ax*o))))}let i=ig(t),c=i?am(s.map(d=>d.v),new Array(a).fill(o),!1,i,(d,h,b)=>r.axAccel(h,0,1,b)):void 0;if(c){for(let d=0;d<=a;d++)s[d].v=c.v[d];for(let d=0;d<a;d++)s[d].ax=(s[d+1].v*s[d+1].v-s[d].v*s[d].v)/(2*o)}let l=0;for(let d=0;d<a;d++){let h=s[d].v+s[d+1].v;h>0&&(l+=2*o/h)}let u=s.slice(0,a).map(d=>d.v),m=s.slice(0,a).map(d=>d.ax),f=new Array(a).fill(o),p=f.map((d,h)=>h*o);return{id:e.id,label:e.label,kind:e.kind,time:l,distance:a*o,laps:1,lapTime:l,trace:{v:u,ax:m,ay:new Array(a).fill(0),s:p,x:p,y:new Array(a).fill(0),...c?{gear:c.gear.slice(0,a),rpm:c.rpm.slice(0,a),shifting:c.shifting.slice(0,a)}:{}},energy:OS(t,f,[...u,s[a].v],m,1)}}function m_(e,t){let r=Math.max(1,Math.round(e.laps??1)),[n]=Na(t.ggv,[1/e.radius],t.numerics),o=2*Math.PI*e.radius,a=n.v>0?o/n.v:1/0,s=t.ggv.scrub?.(n.v,Math.abs(n.ay))??0,i=OS(t,[o],[n.v,n.v],[0],r,s!==0?{ay:[n.ay],scrub:[s]}:void 0);return{id:e.id,label:e.label,kind:e.kind,time:a*r,distance:o*r,laps:r,lapTime:a,energy:i}}function Sm(e,t){return e.laps!=null?Math.max(1,Math.round(e.laps)):e.distance!=null?Math.max(1,Math.ceil(e.distance/t.length)):1}function p_(e,t){let r=e.distance!=null?t.v_limit_endurance?.value??0:0;return r>0?r/3.6:void 0}function d_(e,t){if(e.distance==null||xt(t.motorModel))return 0;let r=t.endurance_reserve?.value??0;return r>0?Math.min(r,95)/100:0}var TS=1;function IS(e,t,r,n){return{v:r.v,ax:r.ax,ay:r.ay,ds:t.ds,axDrag:za(e.ggv.rows,r.v),...r.axScrub?{axScrub:r.axScrub}:{},axGrade:n,...t.bank?{bank:t.bank}:{}}}var PS=new WeakMap;function _S(e){let t=e.vehicle.params;if(!t.brakeFade)return null;let r=PS.get(t);if(r===void 0){let n=ng(t),o=n?bt(t):null;if(!n||!o||o.mode!=="hydraulic")r=null;else{let a=tg(t,e.vehicle),s=e.ggv.rows,i=FS(a.inp,a.ev,e.vehicle.vMax,{front:ag(o.hydraulic.front.heat),rear:ag(o.hydraulic.rear.heat)},c=>za(s,[c])[0]);r={discs:n,table:i}}PS.set(t,r)}return r}function f_(e,t,r){let n=e.vehicle.params,{soc:o,packTempC:a,launched:s,vCeiling:i}=r,c=e.load?.atSoc(e.vehicle,o,a),l=ig(e),u=(g,y)=>e.yaw?fS(e.yaw.family.atSoc(e.vehicle,o,a),t,e.yaw.car,e.numerics,{standingStart:s,...g?{driveDerate:g}:{},...y?{brakeFade:y}:{},...i?{vCeiling:i}:{},...c?{load:c}:{},...l?{shifts:l}:{}}):At(Wi(e.ggv,e.vehicle,o,a),t,e.numerics,{standingStart:s,...g?{driveDerate:g}:{},...y?{brakeFade:y}:{},...i?{vCeiling:i}:{},...c?{load:c}:{},...l?{shifts:l}:{}}),m=Sn(t.gradient,t.npts),f=g=>n.motorThermal?NM(e.vehicle,t.ds,e.energyOpts??Br,y=>u(y,g),o,a,m,t.bank).lap:u(void 0,g),p=_S(e);if(!p)return f();let d=Ki(n),h=r.discC??{front:d,rear:d};return wS(f,g=>{let y=og(p.discs,rg(n,IS(e,t,g,m),e.vehicle),g.v,t.ds,h,d);return{...y?.front?{front:y.front.padFactor}:{},...y?.rear?{rear:y.rear.padFactor}:{}}},p.table).lap}function h_(e,t){let r=p_(e,t.vehicle.params),n=d_(e,t.vehicle.params);return n>0?y_(e,t,n,r):ji(e,t,r)}function km(e,t){let r=e.energy?.remainingFraction??0;return e.incomplete?-t-(1-e.incomplete.lapsCompleted/Math.max(1,e.incomplete.lapsAsked)):r-t}var LS=5,b_=.1,g_=.005,DS=12;function y_(e,t,r,n){let o=ji(e,t,n),a=1,s=(d,h,b)=>({...d,energyTarget:{reserve:r,capKmh:h===void 0?null:h*3.6,met:b,solves:a}}),i=km(o,r);if(i>=0)return s(o,n,!0);let c=Math.min(n??1/0,t.ggv.vMax),l=c/2,u=ji(e,t,l);a++;let m=km(u,r);for(;m<0&&l>LS&&a<DS;)c=l,i=m,l=Math.max(LS,l/2),u=ji(e,t,l),a++,m=km(u,r);if(m<0)return s(u,l,!1);let f=l,p=0;for(;a<DS&&c-l>b_&&m>g_;){let d=c-l,h=Math.min(c-.05*d,Math.max(l+.05*d,l+m*d/(m-i))),b=ji(e,t,h);a++;let g=km(b,r);g>=0?(l=h,m=g,u=b,f=h,p===1&&(i/=2),p=1):(c=h,i=g,p===-1&&(m/=2),p=-1)}return s(u,f,!0)}function NS(e,t,r){return r===0?e:e&&!t}function ji(e,t,r){let n=t.track;if(!n)throw new Mm(`Event "${e.id}" needs a track.`);let o=Sm(e,n),a=e.standingStart??t.standingStart??!1,s=K=>NS(a,n.closed,K),i=t.vehicle.params,c=Fr(Oa(i)),l=c.capacityAh,u=i.soc.value,m=Ki(i),f=im(c,m),p=0,d=0,h=0,b=0,g=[],y=!1,R=-1/0,k=0,v=0,x=!1,M=-1/0,F=0,w=0,T=-1/0,P=(K,Y,j=1)=>{K.tempMaxC>T&&(T=K.tempMaxC),K.motorTempMaxC!==void 0&&(y=!0,x=!0,K.motorTempMaxC>R&&(R=K.motorTempMaxC),K.motorTempMaxC>M&&(M=K.motorTempMaxC),k+=(K.motorDerateTimeFrac??0)*Y,F+=(K.motorDerateTimeFrac??0)*Y,v+=(K.motorLossKwh??0)/j,w+=(K.motorLossKwh??0)/j)},A=null,S,C=ng(i),L={front:m,rear:m},D=null,I=_S(t)!==null,O=(K,Y)=>I&&(Math.abs(K.front-Y.front)>TS||Math.abs(K.rear-Y.rear)>TS),N=(K,Y,j)=>{let Z=Hb(i,K,Y);if(D&&D.launch===j&&!v_(Z,D.pw)&&!O(L,D.discC))return D.lap;let ne=f_(t,n,{soc:K,packTempC:Y,launched:j,...r?{vCeiling:r}:{},...I?{discC:L}:{}});return D={pw:Z,launch:j,discC:L,lap:ne},ne},z=Sn(n.gradient,n.npts),E=(K,Y,j)=>Va(t.vehicle,n.ds,K.v,K.ax,t.energyOpts,Y,j,void 0,z,void 0,{ay:K.ay,bank:n.bank,...K.axScrub?{scrub:K.axScrub}:{}}),_=new WeakMap,B=(K,Y)=>{let j=_.get(K);return j||(j=rg(i,IS(t,n,K,z),t.vehicle),_.set(K,j)),og(C,j,K.v,n.ds,Y,m)},V=(K,Y,j)=>{let Z=`${(100*j/n.npts).toFixed(0)} % of the way through lap ${K+1}`,ne=Y.cutoffAt>=0&&Y.cutoffAt<=Y.emptyAt;return{lapsCompleted:K,lapsAsked:o,why:ne?`the pack reached its ${c.voltageFloor.toFixed(0)} V cut-off ${Z}`:`the pack ran out ${Z}`}};for(let K=0;K<o;K++){if(u<=0){S={lapsCompleted:K,lapsAsked:o,why:"the pack was empty"};break}let Y=s(K),j=u,Z=f;x=!1,M=-1/0,F=0,w=0,T=-1/0;let ne=N(u,f,Y),te=E(ne,u,f);if(te.emptyAt>=0){S=V(K,te,te.emptyAt);break}let W=N(te.socEnd,te.tempEndC,Y).laptime-ne.laptime,J,re,pe,de,ie=f,oe=-1,ue=null,$e=1;if(W<=sg)J=ne.laptime,re=te.net,pe=te.loss,de=te.chargeAh,ie=te.tempEndC,P(te,J),$e=1;else{let le=Math.min(x_,Math.max(2,Math.ceil(W/(2*sg))));$e=le;let Re=u,Te=f;J=0,re=0,pe=0,de=0;for(let ze=0;ze<le;ze++){let Ue=N(Re,Te,Y),be=E(Ue,Re,Te),Fe=be.emptyAt>=0?be.emptyAt/n.npts:1;if(Fe*le<1){oe=Math.round(n.npts*(ze/le+Fe)),ue=be;break}if(J+=Ue.laptime/le,P(be,Ue.laptime/le,le),re+=be.net/le/Fe,pe+=be.loss/le/Fe,de+=be.chargeAh/le/Fe,Re-=be.chargeAh/le/Fe/l,Te+=(be.tempEndC-Te)/le,Re<=0){oe=Math.round(n.npts*(ze+1)/le),ue=be;break}}if(ie=Te,oe>=0&&ue){S=V(K,ue,oe);break}u=Re}p+=J,d+=re,h+=pe,b+=de,W<=sg&&(u=te.socEnd),f=ie;let Ae=C?B(ne,L):null;Ae&&(L={front:Ae.front?.endC??L.front,rear:Ae.rear?.endC??L.rear}),g.push({lap:K+1,time:J,elapsed:p,entryTime:ne.laptime,socStart:j,socEnd:u,packTempStartC:Z,packTempEndC:f,packTempMaxC:Number.isFinite(T)?T:Z,energyKwh:re,lossKwh:pe,chargeAh:de,launched:Y,substeps:$e,...r?{vCeiling:r}:{},...x?{motor:{peakWindingC:M,derateTimeFrac:J>0?F/J:0,lossKwh:w}}:{},...Ae?{brakes:{...Ae.front?{front:ES(Ae.front)}:{},...Ae.rear?{rear:ES(Ae.rear)}:{}}}:{}}),A=ne}if(!A){let K=ig(t);A=At(Wi(t.ggv,t.vehicle,u),n,t.numerics,{standingStart:a,...t.load?{load:t.load.atSoc(t.vehicle,u)}:{},...K?{shifts:K}:{}}),S=S??{lapsCompleted:0,lapsAsked:o,why:"the pack was empty"}}let G=g.length;return{id:e.id,label:e.label,kind:e.kind,time:p,distance:n.length*G,laps:G,lapTime:A.laptime,trace:{v:A.v,ax:A.ax,ay:A.ay,s:n.s,x:n.x,y:n.y,...n.gradient.some(K=>K!==0)?{gradient:n.gradient}:{},...n.bank.some(K=>K!==0)?{bank:n.bank}:{},...n.z.some(K=>K!==0)?{z:n.z}:{},...n.mu.some(K=>K!==1)?{mu:n.mu}:{},...A.loadFactor?{loadFactor:A.loadFactor}:{},...A.axScrub?{axScrub:A.axScrub}:{},...l_(A)},energy:{consumed:d,loss:h,...xt(i.motorModel)?{}:{native:{value:b,unit:"Ah"}},remainingFraction:xt(i.motorModel)?1:u,...y?{motor:{peakWindingC:R,derateTimeFrac:p>0?k/p:0,lossKwh:v}}:{}},lapLog:g,...S?{incomplete:S}:{}}}var sg=.05;function ES(e){let t=r=>e.workJ>0?r/e.workJ:0;return{startC:e.startC,endC:e.endC,maxC:e.maxC,workKj:e.workJ/1e3,coldShare:t(e.coldWorkJ),hotShare:t(e.hotWorkJ)}}var x_=4,R_=.001;function v_(e,t){return e===t?!1:!Number.isFinite(e)||!Number.isFinite(t)?!0:Math.abs(e-t)>R_*Math.max(1,Math.abs(t))}function OS(e,t,r,n,o,a){return k_(e,t,o,()=>({v:r,ax:n,...a?{lateral:a}:{}}))}function k_(e,t,r,n){let o=e.energyOpts,a=e.vehicle.params.soc.value,s=0,i=0,c=0;for(let l=0;l<r;l++){let u=n(l),m=Va(e.vehicle,t,u.v,u.ax,o,a,void 0,void 0,void 0,void 0,u.lateral);s+=m.net,i+=m.loss,c+=m.chargeAh,a=m.socEnd}return xt(e.vehicle.params.motorModel)?{consumed:s,loss:i,remainingFraction:1}:{consumed:s,loss:i,native:{value:c,unit:"Ah"},remainingFraction:a}}function VS(e,t){switch(e.kind){case"straightLineAccel":return u_(e,t);case"constantRadius":return m_(e,t);case"trackLap":return h_(e,t)}}function cg(e,t){let r={};for(let n of e)r[n.id]=VS(n,t);return r}function BS(e,t){if(e.kind!=="trackLap")return e;let{distance:r,...n}=e;return{...n,laps:Math.max(1,Math.round(t))}}function fo(e,t,r,n,o="twoTrack",a){let s=1/0,i=-1/0;for(let f of r){let p=Bi(f);if(!p)continue;let d=kM(p,At(t,f,n).v);d&&(s=Math.min(s,d.lo),i=Math.max(i,d.hi))}if(!(i>=s))return;let c=MM({lo:s,hi:i}),l=c.join(","),u=a?.get(l);if(u)return u;let m=kS(e,c,t,o);return a?.set(l,m),m}var Ui=e=>e.distance/Math.max(1,e.laps);function Xi(e){let t=e.s.length,r=new Array(t);for(let n=0;n<t;n++)r[n]=(n<t-1?e.s[n+1]:e.length)-e.s[n];return r}var M_=e=>e.v.map(t=>t*3.6),S_=e=>e.ax.map(t=>t/9.81),A_=e=>e.ay.map(t=>t/9.81),F_=e=>e.ay.map((t,r)=>e.v[r]>1e-6?t/(e.v[r]*e.v[r]):0),Am=(e,t,r)=>e?.slice()??new Array(t.s.length).fill(r),w_=e=>Am(e.z,e,0),C_=e=>e.gradient?e.gradient.map(t=>100*Math.tan(t*Math.PI/180)):Am(void 0,e,0),T_=e=>Am(e.bank,e,0),P_=e=>Am(e.mu,e,1);function L_(e){let t=e.s.length,r=Xi(e),n=new Array(t);n[0]=0;for(let o=1;o<t;o++)n[o]=n[o-1]+2*r[o-1]/(e.v[o-1]+e.v[o]);return n}var lg=[{name:"s",unit:"m",what:"distance along the lap"},{name:"ds",unit:"m",what:"length of the segment starting at this sample"},{name:"t",unit:"s",what:"elapsed time"},{name:"v",unit:"m/s",what:"speed"},{name:"speed",unit:"km/h",what:"speed"},{name:"ax",unit:"m/s\xB2",what:"longitudinal acceleration"},{name:"ay",unit:"m/s\xB2",what:"lateral acceleration"},{name:"axg",unit:"g",what:"longitudinal acceleration"},{name:"ayg",unit:"g",what:"lateral acceleration"},{name:"curv",unit:"1/m",what:"signed curvature, ay/v\xB2"},{name:"z",unit:"m",what:"elevation of the road"},{name:"grade",unit:"%",what:"grade of the road, uphill +"},{name:"bank",unit:"\xB0",what:"bank of the road, left side up +"},{name:"grip",unit:"-",what:"grip scale of the road, 1 = the tyre\u2019s own"}];function $S(e){let t=Xi(e);return{ds:t,vars:{s:e.s,ds:t,t:L_(e),v:e.v,speed:M_(e),ax:e.ax,ay:e.ay,axg:S_(e),ayg:A_(e),curv:F_(e),z:w_(e),grade:C_(e),bank:T_(e),grip:P_(e)}}}function GS(e,t){return{v:e.v,ax:e.ax,ay:e.ay,ds:Xi({s:e.s,length:t}),axGrade:Sn(e.gradient,e.v.length),...e.bank?{bank:e.bank}:{},...e.loadFactor?{loadFactor:e.loadFactor}:{}}}function KS(e,t){let r=gt(e);return{pastTurnover:iS(r,gr(e),t),...e.aeroModel?{aeroOutside:sS(r,t)}:{}}}var Fm="Flying lap";function ug(e,t){return e.kind!=="trackLap"||e.label!==Fm?e.label:e.standingStart??t?"Run":e.label}function D_(e){let t=gt(e);return{yawInertia:t.yawInertia??0,massTotal:t.massTotal,wheelbase:t.wheelbase/1e3}}function E_(e,t,r){let n=e.params,o=n.ggvMode??"twoTrack",a=n.quasiTransient?vS(e,!1,o):null,s=a?a.steady:yr(e,!1,o),i=t?fo(e,s,[t],r,o):void 0;return{ggv:s,...a?{yaw:{family:a,car:D_(n)}}:{},...i?{load:i}:{}}}function I_(e,t){let r=t.lapCounts,n=t.standingStart??!1,o=!1,a=e.events.map(s=>{let i=r?.[s.id]!=null?BS(s,r[s.id]):s,c=ug(i,n),l=c===i.label?i:{...i,label:c};return l!==s&&(o=!0),l});return o?a:e.events}function __(e,t,r){let n=r.lapCounts;if(!(!n||!r.track))for(let o of t.events){let a=n[o.id];if(o.kind!=="trackLap"||a==null)continue;let s=Sm(o,r.track),i=Math.max(1,Math.round(a));i!==s&&e[o.id]&&(e[o.id]={...e[o.id],lapsOverridden:{asked:i,defined:s}})}}function N_(e,t){for(let[r,n]of Object.entries(e))n.trace&&(e[r]={...n,...KS(t,GS(n.trace,Ui(n)))})}function qi(e,t,r={}){let n=Dt(e),o=E_(n,r.track,r.numerics),{ggv:a}=o,s=cg(I_(t,r),{vehicle:n,...o,track:r.track,energyOpts:$r(e,r.energyOpts),numerics:r.numerics,standingStart:r.standingStart});return __(s,t,r),N_(s,n.params),{name:e.name,rulesetId:t.id,events:s,ggv:a}}function mg(e){return{...e,ggv:{rows:e.ggv.rows,vMax:e.ggv.vMax,surf:e.ggv.surf}}}var pg=["<","<=",">",">=","==","!="],Oe=class extends Error{at;constructor(t,r){super(t),this.name="ExprError",this.at=r}},Qi=e=>e>="0"&&e<="9",HS=e=>/[A-Za-z_]/.test(e),O_=e=>/[A-Za-z0-9_]/.test(e);function V_(e){let t=[],r=0;for(;r<e.length;){let n=e[r];if(n===" "||n===" "||n===`
|
|
224
|
+
`||n==="\r"){r++;continue}if(Qi(n)||n==="."&&Qi(e[r+1]??"")){let o=r;for(;r<e.length&&(Qi(e[r])||e[r]===".");)r++;if(e[r]==="e"||e[r]==="E"){let i=r;if(r++,(e[r]==="+"||e[r]==="-")&&r++,Qi(e[r]??""))for(;r<e.length&&Qi(e[r]);)r++;else r=i}let a=e.slice(o,r),s=Number(a);if(!Number.isFinite(s))throw new Oe(`"${a}" is not a number`,o);t.push({t:"num",value:s,at:o});continue}if(HS(n)){let o=r;for(;;){for(;r<e.length&&O_(e[r]);)r++;if(e[r]==="."&&HS(e[r+1]??""))r++;else break}t.push({t:"name",value:e.slice(o,r),at:o});continue}if("<>=!".includes(n)){let o=e.slice(r,r+2);if(pg.includes(o)){t.push({t:"op",value:o,at:r}),r+=2;continue}if(n==="<"||n===">"){t.push({t:"op",value:n,at:r}),r++;continue}throw new Oe(n==="="?'Compare with "==", not "="':'Write not(x) rather than "!x"',r)}if("+-*/^(),".includes(n)){t.push({t:"op",value:n,at:r}),r++;continue}throw new Oe(`"${n}" is not something this expression can contain`,r)}return t.push({t:"end",at:e.length}),t}function dg(e){let t=V_(e),r=0,n=()=>t[r],o=h=>{let b=n();return b.t==="op"&&b.value===h},a=h=>o(h)?(r++,!0):!1,s=(h,b)=>{if(!a(h))throw new Oe(`Expected ${b} here`,n().at)};function i(){let h=c(),b=n();if(b.t!=="op"||!pg.includes(b.value))return h;r++;let g={kind:"binary",op:b.value,left:h,right:c(),at:b.at},y=n();if(y.t==="op"&&pg.includes(y.value))throw new Oe("Comparisons do not chain \u2014 write and(a < b, b < c)",y.at);return g}function c(){let h=l();for(;;){let b=n().at;if(a("+"))h={kind:"binary",op:"+",left:h,right:l(),at:b};else if(a("-"))h={kind:"binary",op:"-",left:h,right:l(),at:b};else return h}}function l(){let h=u();for(;;){let b=n().at;if(a("*"))h={kind:"binary",op:"*",left:h,right:u(),at:b};else if(a("/"))h={kind:"binary",op:"/",left:h,right:u(),at:b};else return h}}function u(){return a("-")?{kind:"unary",op:"-",arg:u()}:a("+")?u():m()}function m(){let h=f(),b=n().at;return a("^")?{kind:"binary",op:"^",left:h,right:u(),at:b}:h}function f(){let h=n();if(h.t==="num")return r++,{kind:"num",value:h.value};if(h.t==="name"){if(r++,a("(")){let b=[];if(!o(")"))do b.push(i());while(a(","));return s(")","a closing bracket"),{kind:"call",name:h.value,args:b,at:h.at}}return{kind:"var",name:h.value,at:h.at}}if(a("(")){let b=i();return s(")","a closing bracket"),b}throw h.t==="end"?new Oe("The expression ends before it is finished",h.at):new Oe(`"${h.value}" cannot start a value`,h.at)}let p=i(),d=n();if(d.t!=="end")throw new Oe(`"${d.value}" is left over \u2014 check for a missing operator`,d.at);return p}function fg(e){let t=new Set,r=n=>{n.kind==="var"?t.add(n.name):n.kind==="call"?n.args.forEach(r):n.kind==="unary"?r(n.arg):n.kind==="binary"&&(r(n.left),r(n.right))};return r(e),t}var Zi=(e,t)=>typeof e=="number"?new Array(t).fill(e):e;function B_(e){let t=1;for(let r of e)Array.isArray(r)&&(t=Math.max(t,r.length));return t}function _t(e,t){if(e.every(a=>typeof a=="number"))return t(...e);let r=B_(e),n=e.map(a=>Zi(a,r)),o=new Array(r);for(let a=0;a<r;a++)o[a]=t(...n.map(s=>s[Math.min(a,s.length-1)]));return o}var Ve=(e,t)=>({arity:e,call:r=>_t(r,t)}),ho=e=>e!==0&&!Number.isNaN(e),xr=e=>e?1:0;function zS(e,t,r){let n=YS(t,r,"integrate"),o=n.length,a=Zi(e,o),s=new Array(o),i=0;for(let c=0;c<o;c++){s[c]=i;let l=a[Math.min(c,a.length-1)],u=a[Math.min(c+1,a.length-1)];i+=(l+u)/2*n[c]}return s}function YS(e,t,r){if(!e.ds||e.ds.length===0)throw new Oe(`${r}() needs to know the sample spacing, and this context has none`,t);return e.ds}var wm={abs:Ve(1,Math.abs),sqrt:Ve(1,Math.sqrt),sign:Ve(1,Math.sign),floor:Ve(1,Math.floor),ceil:Ve(1,Math.ceil),round:Ve(1,Math.round),exp:Ve(1,Math.exp),log:Ve(1,Math.log),sin:Ve(1,Math.sin),cos:Ve(1,Math.cos),tan:Ve(1,Math.tan),atan:Ve(1,Math.atan),atan2:Ve(2,Math.atan2),hypot:Ve(2,Math.hypot),min:Ve(2,Math.min),max:Ve(2,Math.max),clamp:Ve(3,(e,t,r)=>Math.min(r,Math.max(t,e))),if:Ve(3,(e,t,r)=>ho(e)?t:r),and:Ve(2,(e,t)=>xr(ho(e)&&ho(t))),or:Ve(2,(e,t)=>xr(ho(e)||ho(t))),not:Ve(1,e=>xr(!ho(e))),finite:Ve(1,e=>xr(Number.isFinite(e))),peak:{arity:1,call:([e])=>{let t=Array.isArray(e)?e:[e],r=0;for(let n of t)r=Math.max(r,Math.abs(n));return r}},mean:{arity:1,call:([e])=>{let t=Array.isArray(e)?e:[e];return t.length?t.reduce((r,n)=>r+n,0)/t.length:0}},total:{arity:1,call:([e],t)=>{let r=zS(e,t,0),n=t.ds,o=Zi(e,n.length),a=n.length-1;return r[a]+(o[a]+o[0])/2*n[a]}},integrate:{arity:1,call:([e],t)=>zS(e,t,0)},cum:{arity:1,call:([e],t)=>{let r=t.ds?.length??(Array.isArray(e)?e.length:1),n=Zi(e,r),o=new Array(r),a=0;for(let s=0;s<r;s++)a+=n[Math.min(s,n.length-1)],o[s]=a;return o}},deriv:{arity:1,call:([e],t)=>{let r=YS(t,0,"deriv"),n=r.length,o=Zi(e,n),a=new Array(n);for(let s=0;s<n;s++){let i=Math.max(0,s-1),c=Math.min(n-1,s+1),l=0;for(let u=i;u<c;u++)l+=r[u];a[s]=l>0?(o[c]-o[i])/l:0}return a}}},Ya={g:9.81,pi:Math.PI,e:Math.E,nan:NaN,inf:1/0},Ji={fleetmin:"min",fleetmax:"max"};function bo(e){switch(e.kind){case"call":return Object.hasOwn(Ji,e.name)||e.args.some(bo);case"unary":return bo(e.arg);case"binary":return bo(e.left)||bo(e.right);default:return!1}}var $_=e=>typeof e=="number"?`${e}`:`between ${e[0]} and ${e[1]}`;function G_(e,t){let r=Array.from({length:t.length+1},(n,o)=>o);for(let n=1;n<=e.length;n++){let o=[n];for(let a=1;a<=t.length;a++)o[a]=Math.min(r[a]+1,o[a-1]+1,r[a-1]+(e[n-1]===t[a-1]?0:1));r=o}return r[t.length]}function K_(e,t){let r=t.map(c=>({k:c,d:G_(c,e)})).filter(c=>c.d<=Math.max(1,Math.floor(e.length/4))),n=Math.min(...r.map(c=>c.d)),o=r.filter(c=>c.d===n).map(c=>c.k).slice(0,3);if(o.length)return`"${e}" is not a name here \u2014 did you mean ${o.join(" or ")}?`;let a=e.indexOf(".");if(a>0){let c=t.filter(l=>l.startsWith(e.slice(0,a+1)));if(c.length)return`"${e}" is not a name here. ${e.slice(0,a)} has ${c.join(", ")}`}let s=new Set,i=[];for(let c of t){let l=c.indexOf(".");l>0?s.add(`${c.slice(0,l)}.\u2026`):i.push(c)}return`"${e}" is not a name here. Available: ${[...s,...i].join(", ")}`}function Rr(e,t){switch(e.kind){case"num":return e.value;case"var":{if(Object.hasOwn(t.vars,e.name))return t.vars[e.name];if(Object.hasOwn(Ya,e.name))return Ya[e.name];let r=[...Object.keys(t.vars),...Object.keys(Ya)].sort();throw new Oe(K_(e.name,r),e.at)}case"unary":return _t([Rr(e.arg,t)],r=>-r);case"binary":{let r=Rr(e.left,t),n=Rr(e.right,t);switch(e.op){case"+":return _t([r,n],(o,a)=>o+a);case"-":return _t([r,n],(o,a)=>o-a);case"*":return _t([r,n],(o,a)=>o*a);case"/":return _t([r,n],(o,a)=>a===0?0:o/a);case"^":return _t([r,n],(o,a)=>o**a);case"<":return _t([r,n],(o,a)=>xr(o<a));case"<=":return _t([r,n],(o,a)=>xr(o<=a));case">":return _t([r,n],(o,a)=>xr(o>a));case">=":return _t([r,n],(o,a)=>xr(o>=a));case"==":return _t([r,n],(o,a)=>xr(o===a));case"!=":return _t([r,n],(o,a)=>xr(o!==a))}break}case"call":{let r=Object.hasOwn(Ji,e.name)?Ji[e.name]:void 0;if(r){if(!t.fleet)throw new Oe(`${e.name}() compares the cars in a field, so it belongs in a ruleset's KPIs, not in a channel`,e.at);if(e.args.length!==1)throw new Oe(`${e.name}() takes 1 argument, not ${e.args.length}`,e.at);return t.fleet(e.args[0],r,e.at)}let n=Object.hasOwn(wm,e.name)?wm[e.name]:void 0;if(!n){let s=[...Object.keys(wm),...t.fleet?Object.keys(Ji):[]];throw new Oe(`There is no function called "${e.name}". Available: ${s.sort().join(", ")}`,e.at)}let o=typeof n.arity=="number"?n.arity:n.arity[0],a=typeof n.arity=="number"?n.arity:n.arity[1];if(e.args.length<o||e.args.length>a)throw new Oe(`${e.name}() takes ${$_(n.arity)} argument${o===1&&a===1?"":"s"}, not ${e.args.length}`,e.at);return n.call(e.args.map(s=>Rr(s,t)),t)}}throw new Oe("Unreachable node",0)}var Wa=e=>Number.isFinite(e)?e:NaN,hg=[{name:"time",unit:"s",what:"the whole event, every lap",read:e=>Wa(e?.time)},{name:"lapTime",unit:"s",what:"one lap \u2014 the last one completed",read:e=>Wa(e?.lapTime)},{name:"distance",unit:"m",what:"distance covered",read:e=>Wa(e?.distance)},{name:"laps",unit:"-",what:"laps completed",read:e=>Wa(e?.laps)},{name:"energy",unit:"kWh",what:"energy drawn over the event",read:e=>Wa(e?.energy?.consumed)},{name:"remaining",unit:"-",what:"share of the pack or tank left afterwards",read:e=>Wa(e?.energy?.remainingFraction)},{name:"finished",unit:"-",what:"1 when the car ran the whole event, else 0",read:e=>e&&!e.incomplete?1:0}],WS=/^[A-Za-z_][A-Za-z0-9_]*$/,H_=new Set([...Object.keys(Ya),...lg.map(e=>e.name)]);function Cm(e,t,r=[]){let n=[],o=new Set(r),a=t.map(b=>b.id),s=new Set;for(let b of a)WS.test(b)?s.has(b)&&n.push({key:null,message:`Two events are called "${b}"`}):n.push({key:null,message:`Event id "${b}" must be one word to be read as ${b}.time`}),s.add(b);let i=new Map,c=new Map;for(let b of e){if(!WS.test(b.key)){n.push({key:b.key,message:`"${b.key}" must be one word \u2014 letters, digits and _`});continue}if(H_.has(b.key)||o.has(b.key)){n.push({key:b.key,message:`"${b.key}" already means something in a formula \u2014 choose another key`});continue}if(i.has(b.key)){n.push({key:b.key,message:`Two KPIs are called "${b.key}"`});continue}i.set(b.key,b),b.over!=null&&!a.includes(b.over)&&n.push({key:b.key,message:`There is no event "${b.over}" to read the lap of. Events: ${a.join(", ")}`});try{c.set(b.key,dg(b.expr))}catch(g){let y=g;n.push({key:b.key,message:y.message,at:y.at})}}let l=new Map;for(let[b,g]of c)l.set(b,[...fg(g)].filter(y=>i.has(y)));let u=new Set,m=[];for(;;){let b=[...c.keys()].find(g=>!u.has(g)&&l.get(g).every(y=>u.has(y)||!c.has(y)));if(!b)break;u.add(b),m.push(b)}for(let b of c.keys()){if(u.has(b))continue;let g=z_(b,l);n.push({key:b,message:g?`"${b}" depends on itself, through ${g.join(" \u2192 ")}`:`"${b}" reads a KPI that depends on itself`})}let f=(b,g,y)=>{throw new Oe("fleetmin() and fleetmax() cannot sit inside one another",y)},p=new Set,d={};for(let b of a)for(let g of hg)d[`${b}.${g.name}`]=1;for(let b of o)d[b]=1;for(let b of i.keys())d[b]=1;let h={};for(let b of lg)h[b.name]=[1,1];for(let b of m){let g=i.get(b),y=c.get(b);(bo(y)||l.get(b).some(x=>p.has(x)))&&p.add(b);let R=g.over!=null?{...d,...h}:d,k=g.over!=null?[1,1]:void 0,v=(x,M,F)=>{let w=Rr(x,{vars:R,ds:k,fleet:f});if(Array.isArray(w))throw new Oe("fleetmin() and fleetmax() compare one number per car \u2014 reduce the channel first, e.g. peak(v)",F);return w};try{let x=Rr(y,{vars:R,ds:k,fleet:v});Array.isArray(x)&&n.push({key:b,message:"A KPI is one number per car \u2014 reduce the channel, e.g. peak(v) or mean(v)",at:0})}catch(x){let M=x;n.push({key:b,message:M.message,at:M.at})}}return n.length?{plan:null,problems:n}:{plan:{order:m.map(b=>({def:i.get(b),node:c.get(b)})),field:p,eventIds:a},problems:n}}function z_(e,t){let r=[e],n=o=>{for(let a of t.get(o)??[]){if(a===e)return!0;if(!r.includes(a)){if(r.push(a),n(a))return!0;r.pop()}}return!1};return n(e)?[...r,e]:null}function Y_(e,t,r={}){let n={...r};for(let o of e.eventIds){let a=t.events[o];for(let s of hg)n[`${o}.${s.name}`]=s.read(a)}return{vars:n,laps:new Map,events:t.events}}function jS(e,t){if(t.over==null)return{vars:e.vars};let r=e.laps.get(t.over);if(r===void 0){let n=e.events[t.over];r=n?.trace?$S({...n.trace,length:Ui(n)}):null,e.laps.set(t.over,r)}return r?{vars:{...e.vars,...r.vars},ds:r.ds}:null}var US=e=>Array.isArray(e)?NaN:e;function XS(e,t,r,n={}){let o=Object.keys(t),a=o.map(i=>Y_(e,t[i],n[i]));for(let{def:i,node:c}of e.order){let l=e.field.has(i.key);if(l&&!r){for(let f of a)f.vars[i.key]=NaN;continue}let u=new Map,m=(f,p)=>{let d=u.get(f);if(d!==void 0)return d;let h=NaN;for(let b of a){let g=jS(b,i);if(!g)continue;let y=US(Rr(f,g));Number.isFinite(y)&&(Number.isNaN(h)||(p==="min"?y<h:y>h))&&(h=y)}return u.set(f,h),h};for(let f of a){let p=jS(f,i);f.vars[i.key]=p?US(Rr(c,l?{...p,fleet:m}:p)):NaN}}let s={};return o.forEach((i,c)=>{let l={};for(let{def:u}of e.order)l[u.key]=a[c].vars[u.key];s[i]=l}),s}function ec(e,t,r){return XS(e,t,!0,r)}function bg(e,t,r){return XS(e,{car:t},!1,r?{car:r}:void 0).car}var Tm=class extends Error{problems;constructor(t,r){super(`Ruleset "${t}" does not compile:
|
|
225
225
|
`+r.map(n=>` ${n.key?`${n.key}: `:""}${n.message}`).join(`
|
|
226
|
-
`)),this.name="RulesetDefError",this.problems=r}},Qi=e=>typeof e=="number"&&Number.isFinite(e),qi=e=>Qi(e)&&e>0,It=(e,t)=>e===void 0||t(e);function $_(e){let t=[],r=(o,a=null)=>t.push({key:a,message:o});if(typeof e.id!="string"||e.id===""?r("A ruleset needs an id"):/^[A-Za-z0-9_-]+$/.test(e.id)||r(`The id "${e.id}" is letters, digits, "-" and "_" only`),typeof e.label!="string"&&r("A ruleset needs a label"),typeof e.description!="string"&&r("A ruleset needs a description, even an empty one"),Array.isArray(e.events)||r("A ruleset\u2019s events are a list"),Array.isArray(e.kpis)||r("A ruleset\u2019s KPIs are a list"),t.length)return t;for(let o of e.events){let a=o,s=typeof a?.id=="string"?`Event "${a.id}"`:"An event";if(typeof a!="object"||a===null||typeof a.id!="string"||typeof a.label!="string"){r(`${s} needs an id and a label`);continue}switch(a.kind){case"straightLineAccel":qi(a.distance)||r(`${s} needs a distance above zero, in metres`),It(a.vStart,i=>Qi(i)&&i>=0)||r(`${s}'s entry speed must be zero or more`);break;case"constantRadius":qi(a.radius)||r(`${s} needs a radius above zero, in metres`),It(a.laps,i=>Qi(i)&&i>=1)||r(`${s} runs at least one lap`);break;case"trackLap":It(a.laps,i=>Qi(i)&&i>=1)||r(`${s} runs at least one lap`),It(a.distance,qi)||r(`${s}'s distance must be above zero, in metres`),It(a.standingStart,i=>typeof i=="boolean")||r(`${s}'s standing start is yes or no`);break;default:r(`${s} is of a kind this build does not run: ${String(a.kind)}`)}}for(let o of e.kpis){let a=o;if(typeof a!="object"||a===null||typeof a.key!="string"){r("A KPI needs a key");continue}let s=a.key;typeof a.expr!="string"&&r("Needs a formula",s),typeof a.label!="string"&&r("Needs a label",s),It(a.unit,i=>typeof i=="string")||r("Its unit is text",s),It(a.over,i=>typeof i=="string")||r("Names its event by id",s),It(a.format,i=>i==="time"||i==="points")||r("Is shown as a time, as points, or as a number",s),It(a.max,Qi)||r("Its maximum is a number",s),It(a.lowerBetter,i=>typeof i=="boolean")||r("Lower is better, or it is not",s),It(a.hidden,i=>typeof i=="boolean")||r("Is hidden, or it is not",s)}It(e.track?.minTurnRadius,qi)||r("The tightest turn the rules allow is a radius above zero");let n=e.battery;for(let o of["packVoltageMax","segmentVoltageMax","powerLimitKw"])It(n?.[o],qi)||r(`The pack's ${o} must be above zero`);if(e.score!==void 0){let o=e.score?.parts;typeof e.score?.total!="string"||typeof o!="object"||o===null||Array.isArray(o)?r("The score names its total and its parts"):Object.values(o).every(a=>typeof a=="string")||r("Each part of the score names a KPI")}return t}function jS(e){let t=$_(e);if(t.length)return{plan:null,problems:t};let r=[];e.events.length===0&&r.push({key:null,message:"A ruleset runs at least one event"});let n=e.events.map(i=>i.id);e.traceEventId!=null&&!n.includes(e.traceEventId)&&r.push({key:null,message:`The plotted event "${e.traceEventId}" is not one of this ruleset's events`});let{plan:o,problems:a}=Am(e.kpis,e.events);r.push(...a);let s=new Set(e.kpis.map(i=>i.key));if(e.score){s.has(e.score.total)||r.push({key:null,message:`The total "${e.score.total}" is not one of this ruleset's KPIs`});let i=Object.entries(e.score.parts);i.length===0&&r.push({key:null,message:"A ruleset that awards points names at least one part"});for(let[c,l]of i)s.has(l)||r.push({key:null,message:`The part "${c}" reads "${l}", which is not one of this ruleset's KPIs`})}return{plan:r.length?null:o,problems:r}}function wm(e){return jS(e).problems}var hg=e=>Number.isFinite(e)?e:NaN;function G_(e){return e.unit&&e.format!=="time"?`${e.label} (${e.unit})`:e.label}function An(e){let t=structuredClone(e),{plan:r,problems:n}=jS(t);if(!r)throw new Fm(t.id,n);let o=new WeakMap,a=p=>{let f=o.get(p);return f||(f=fg(r,p),o.set(p,f)),f},s=new Map(t.kpis.map(p=>[p.key,p])),i=new Map;for(let[p,f]of Object.entries(t.score?.parts??{}))i.has(f)||i.set(f,p);let c=p=>(f,h)=>{if(!h)return NaN;let b=h.kpis?.[p];if(b!==void 0)return hg(b);let g=h,y=i.get(p);return y!==void 0?hg(g.parts?.[y]):p===t.score?.total?hg(g.total):NaN},l=t.kpis.filter(p=>!p.hidden).map(p=>{let f=r.field.has(p.key);return{key:p.key,label:G_(p),lowerBetter:p.lowerBetter??!1,...p.format?{format:p.format}:{},...f?{field:!0}:{},value:f?c(p.key):h=>a(h)[p.key]}}),u=t.score,m=u?p=>{let f=Xi(r,p),h={};for(let[b,g]of Object.entries(f)){let y={},R={};for(let[k,v]of Object.entries(u.parts)){y[k]=g[v];let x=s.get(v)?.max;x!=null&&(R[k]=x)}h[b]={total:g[u.total],parts:y,...Object.keys(R).length?{maxima:R}:{},kpis:Object.fromEntries(t.kpis.map(k=>[k.key,g[k.key]]))}}return h}:void 0,d=m||(r.field.size>0?p=>{let f=Xi(r,p),h={};for(let[b,g]of Object.entries(f))h[b]={kpis:Object.fromEntries(t.kpis.map(y=>[y.key,g[y.key]]))};return h}:void 0);return{id:t.id,label:t.label,description:t.description,events:t.events,metrics:l,...t.track?{track:t.track}:{},...t.battery?{battery:t.battery}:{},...t.traceEventId?{traceEventId:t.traceEventId}:{},...m?{score:m}:{},...d?{field:d}:{},definition:t}}var Qt={accel:"accel",skidpad:"skidpad",autocross:"autocross",endurance:"endurance"},US=[{kind:"straightLineAccel",id:Qt.accel,label:"Acceleration (75 m)",distance:75},{kind:"constantRadius",id:Qt.skidpad,label:"Skidpad",radius:8.375},{kind:"trackLap",id:Qt.autocross,label:"Autocross (1 lap)",laps:1},{kind:"trackLap",id:Qt.endurance,label:"Endurance (22 km)",distance:22e3}],XS=[{key:"autocross",label:"Autocross lap",format:"time",lowerBetter:!0,expr:"autocross.time"},{key:"accel",label:"Acceleration",format:"time",lowerBetter:!0,expr:"accel.time"},{key:"skidpad",label:"Skidpad lap",format:"time",lowerBetter:!0,expr:"skidpad.lapTime"},{key:"endurance",label:"Endurance",format:"time",lowerBetter:!0,expr:"endurance.time"},{key:"energy",label:"Energy",unit:"kWh",lowerBetter:!0,expr:"endurance.energy"},{key:"overall",label:"Overall",unit:"pts",format:"points",expr:"accelPts + skidpadPts + autocrossPts + endurancePts + efficiencyPts"},{key:"endurancePts",label:"Endurance",unit:"pts",format:"points",max:250,expr:"if(finite(finishedEndurance), 0.9 * 250 * ((1.333 * fleetmin(finishedEndurance) / min(finishedEndurance, 1.333 * fleetmin(finishedEndurance)) - 1) / 0.333) + 0.1 * 250, 0)"},{key:"efficiencyPts",label:"Efficiency",unit:"pts",format:"points",max:100,expr:"if(and(finite(finishedEndurance), finishedEndurance <= 1.333 * fleetmin(finishedEndurance)), 100 * ((1.5 * fleetmin(efficiencyFactor) - min(1.5 * fleetmin(efficiencyFactor), efficiencyFactor)) / (1.5 * fleetmin(efficiencyFactor) - fleetmin(efficiencyFactor))), 0)"},{key:"finishedEndurance",label:"Endurance, if finished",unit:"s",hidden:!0,expr:"if(endurance.finished, endurance.time, nan)"},{key:"efficiencyFactor",label:"Efficiency factor",unit:"s\xB2\xB7kWh",hidden:!0,expr:"finishedEndurance ^ 2 * endurance.energy"},{key:"accelPts",label:"Acceleration",unit:"pts",format:"points",max:75,hidden:!0,expr:"0.95 * 75 * ((1.5 * fleetmin(accel) / min(accel, 1.5 * fleetmin(accel)) - 1) / 0.5) + 0.05 * 75"},{key:"skidpadPts",label:"Skidpad",unit:"pts",format:"points",max:75,hidden:!0,expr:"0.95 * 75 * (((1.25 * fleetmin(skidpad) / min(skidpad, 1.25 * fleetmin(skidpad))) ^ 2 - 1) / 0.5625) + 0.05 * 75"},{key:"autocrossPts",label:"Autocross",unit:"pts",format:"points",max:100,hidden:!0,expr:"0.95 * 100 * ((1.25 * fleetmin(autocross) / min(autocross, 1.25 * fleetmin(autocross)) - 1) / 0.25) + 0.05 * 100"}],qS={total:"overall",parts:{[Qt.accel]:"accelPts",[Qt.skidpad]:"skidpadPts",[Qt.autocross]:"autocrossPts",[Qt.endurance]:"endurancePts",efficiency:"efficiencyPts"}},QS={id:"fs-ev",label:"Formula Student \u2014 Electric",description:"The four dynamic events (acceleration, skidpad, autocross, endurance) scored on the Formula Student point table, with efficiency from battery energy.",events:US,kpis:XS,score:qS,track:{minTurnRadius:4.5},battery:mx,traceEventId:Qt.autocross},ZS={id:"fs-cv",label:"Formula Student \u2014 Combustion",description:"Same events and point table as the electric class. An engine car\u2019s efficiency is scored on the work at its crankshaft until its fuel is modelled; an electric car\u2019s on its pack.",events:US,kpis:XS,score:qS,track:{minTurnRadius:4.5},traceEventId:Qt.autocross},Zi=An(QS),bg=An(ZS);var gg="lap",K_=[{kind:"trackLap",id:gg,label:Mm,laps:1}],JS={id:"trackday",label:"Track day",description:"One flying lap of the selected track. Times and traces only \u2014 no scoring.",events:K_,kpis:[{key:"lap",label:"Lap time",format:"time",lowerBetter:!0,expr:"lap.time"},{key:"topSpeed",label:"Top speed",unit:"km/h",over:gg,expr:"peak(speed)"},{key:"energy",label:"Energy / lap",unit:"kWh",lowerBetter:!0,expr:"lap.energy"}],traceEventId:gg},yg=An(JS);function Fn(e){if(e===null||typeof e!="object")return JSON.stringify(e)??"null";if(Array.isArray(e))return`[${e.map(Fn).join(",")}]`;let t=e,r=Object.keys(t).sort(),n=[];for(let o of r)t[o]!==void 0&&n.push(`${JSON.stringify(o)}:${Fn(t[o])}`);return`{${n.join(",")}}`}function ho(e){let t=Fn(e),r=2166136261;for(let n=0;n<t.length;n++)r^=t.charCodeAt(n),r=r+((r<<1)+(r<<4)+(r<<7)+(r<<8)+(r<<24))>>>0;return r.toString(16).padStart(8,"0").slice(-6)}var za=[Zi,bg,yg],bo=Zi.id,Ya=e=>za.some(t=>t.id===e),eA=new WeakMap,Ji=new Map,H_=64;function Cm(e){let t=eA.get(e);if(t!==void 0)return t;let r=Fn(e),n=Ji.get(r);return n===void 0&&(n=wm(e).length?null:An(e),Ji.size>=H_&&Ji.delete(Ji.keys().next().value),Ji.set(r,n)),eA.set(e,n),n}function Tm(e,t=[]){if(e==null)return;if(typeof e!="string")return Cm(e)??void 0;let r=za.find(o=>o.id===e);if(r)return r;let n=t.find(o=>o.id===e);return n?Cm(n)??void 0:void 0}function go(e,t=[]){return Tm(e,t)??Zi}function xg(e=[]){let t=e.filter(r=>!Ya(r.id)).map(r=>Cm(r)).filter(r=>r!==null);return[...za,...t]}var ec=e=>e.definition??e.id;function Pm(e,t,r){let n=e.length,o=new Array(n);for(let f=0;f<n;f++){let h=f+1<n?e[f+1]:r;o[f]=h-e[f]}let a=new Array(n).fill(0),s=new Array(n).fill(0),i=new Array(n).fill(0),c=new Array(n).fill(0);for(let f=0;f<n;f++){let h=o[(f-1+n)%n],b=o[f];a[f]=h,s[f]=2*(h+b),i[f]=b;let g=t[(f+1)%n],y=t[(f-1+n)%n];c[f]=6*((g-t[f])/b-(t[f]-y)/h)}let l=z_(a,s,i,c),u=new Array(n),m=new Array(n),d=new Array(n),p=new Array(n);for(let f=0;f<n;f++){let h=o[f],b=l[f],g=l[(f+1)%n],y=t[f],R=t[(f+1)%n];u[f]=y,d[f]=b/2,p[f]=(g-b)/(6*h),m[f]=(R-y)/h-h*(2*b+g)/6}return{n,eval:(f,h)=>u[f]+h*(m[f]+h*(d[f]+h*p[f])),d1:(f,h)=>m[f]+h*(2*d[f]+h*3*p[f]),d2:(f,h)=>2*d[f]+h*6*p[f]}}function vg(e,t){let r=e.length,n=r-1,o=new Array(n);for(let u=0;u<n;u++)o[u]=e[u+1]-e[u];let a=new Array(r).fill(0);if(r>2){let u=r-2,m=new Array(u).fill(0),d=new Array(u).fill(0),p=new Array(u).fill(0),f=new Array(u).fill(0);for(let g=0;g<u;g++){let y=g+1;m[g]=o[y-1],d[g]=2*(o[y-1]+o[y]),p[g]=o[y],f[g]=6*((t[y+1]-t[y])/o[y]-(t[y]-t[y-1])/o[y-1])}let h=n>=3;if(h){let g=o[0]/o[1];d[0]+=o[0]*(1+g),p[0]-=o[0]*g;let y=o[n-1]/o[n-2];d[u-1]+=o[n-1]*(1+y),m[u-1]-=o[n-1]*y}let b=Rg(m,d,p,f);for(let g=0;g<u;g++)a[g+1]=b[g];h&&(a[0]=(1+o[0]/o[1])*a[1]-o[0]/o[1]*a[2],a[r-1]=(1+o[n-1]/o[n-2])*a[r-2]-o[n-1]/o[n-2]*a[r-3])}let s=new Array(n),i=new Array(n),c=new Array(n),l=new Array(n);for(let u=0;u<n;u++)s[u]=t[u],c[u]=a[u]/2,l[u]=(a[u+1]-a[u])/(6*o[u]),i[u]=(t[u+1]-t[u])/o[u]-o[u]*(2*a[u]+a[u+1])/6;return{n,eval:(u,m)=>s[u]+m*(i[u]+m*(c[u]+m*l[u])),d1:(u,m)=>i[u]+m*(2*c[u]+m*3*l[u]),d2:(u,m)=>2*c[u]+m*6*l[u]}}function z_(e,t,r,n){let o=t.length;if(o===1)return[n[0]/(t[0]+e[0]+r[0])];if(o===2){let f=t[0],h=r[0]+e[0],b=e[1]+r[1],g=t[1],y=f*g-h*b;return[(n[0]*g-h*n[1])/y,(f*n[1]-n[0]*b)/y]}let a=e[0],s=r[o-1],i=-t[0]||1e-30,c=t.slice();c[0]=t[0]-i,c[o-1]=t[o-1]-a*s/i;let l=Rg(e,c,r,n),u=new Array(o).fill(0);u[0]=i,u[o-1]=s;let m=Rg(e,c,r,u),d=(l[0]+a*l[o-1]/i)/(1+m[0]+a*m[o-1]/i),p=new Array(o);for(let f=0;f<o;f++)p[f]=l[f]-d*m[f];return p}function Rg(e,t,r,n){let o=t.length,a=new Array(o),s=new Array(o);a[0]=r[0]/t[0],s[0]=n[0]/t[0];for(let c=1;c<o;c++){let l=t[c]-e[c]*a[c-1];a[c]=r[c]/l,s[c]=(n[c]-e[c]*s[c-1])/l}let i=new Array(o);i[o-1]=s[o-1];for(let c=o-2;c>=0;c--)i[c]=s[c]-a[c]*i[c+1];return i}function tc(e){let t=e.z;if(!Array.isArray(t)||t.length<2)return null;let r=e.closed!==!1,n=e.x.length,o=r?n:n-1,a=[0];for(let l=0;l<o;l++){let u=(l+1)%n;a.push(a[l]+Math.hypot(e.x[u]-e.x[l],e.y[u]-e.y[l]))}let s=a[o],i=t.length,c=i===n?a.slice(0,n):Array.from({length:i},(l,u)=>r?u/i*s:u/(i-1)*s);return{z:t,pos:c,length:s,closed:r}}function tA(e,t,r){let n=e.pos[r]-e.pos[t];return e.closed?n>e.length/2?n-e.length:n<-e.length/2?n+e.length:n:n}function rA(e,t){let[r,n,o,a,s,i]=e,c=a*i-s*s,l=o*s-n*i,u=n*s-o*a,m=r*c+n*l+o*u;if(!(Math.abs(m)>1e-12*Math.max(1,Math.abs(r*a*i))))return null;let d=r*i-o*o,p=n*o-r*s,f=r*a-n*n;return[(c*t[0]+l*t[1]+u*t[2])/m,(l*t[0]+d*t[1]+p*t[2])/m,(u*t[0]+p*t[1]+f*t[2])/m]}function nA(e){let t=e.z.length;if(t<5)return 0;let r=[];for(let a=0;a<t;a++){let s=[a-2,a-1,a+1,a+2].map(h=>e.closed?(h+t)%t:h);if(s.some(h=>h<0||h>=t))continue;let i=s.map(h=>tA(e,a,h)),c=Math.max(...i.map(Math.abs));if(!(c>0))continue;let l=i.map(h=>h/c),u=[0,0,0,0,0];for(let h of l)for(let b=0;b<5;b++)u[b]+=h**b;let m=rA([u[0],u[1],u[2],u[2],u[3],u[4]],[1,0,0]);if(!m)continue;let d=l.map(h=>m[0]+m[1]*h+m[2]*h*h),p=0,f=1;d.forEach((h,b)=>{p+=h*e.z[s[b]],f+=h*h}),r.push(Math.abs(e.z[a]-p)/Math.sqrt(f))}if(!r.length)return 0;r.sort((a,s)=>a-s);let n=r.length>>1;return 1.4826*(r.length%2?r[n]:(r[n-1]+r[n])/2)}function Y_(e,t,r){let n=e.z.length,o=[t],a=[0];for(let s of[-1,1])for(let i=1;i<n;i++){let c=e.closed?((t+s*i)%n+n)%n:t+s*i;if(c<0||c>=n)break;let l=tA(e,t,c);if(Math.abs(l)>=r||Math.sign(l)!==s)break;o.push(c),a.push(l)}return{j:o,t:a}}function W_(e,t,r){let{j:n,t:o}=Y_(e,t,r);if(n.length<4)return null;let a=o.map(l=>(1-Math.abs(l/r)**3)**3),s=o.map(l=>l/r),i=[0,0,0,0,0];s.forEach((l,u)=>{let m=a[u];for(let d=0;d<5;d++)i[d]+=m,m*=l});let c=rA([i[0],i[1],i[2],i[2],i[3],i[4]],[1,0,0]);return c?{j:n,value:s.map((l,u)=>a[u]*(c[0]+c[1]*l+c[2]*l*l))}:null}function kg(e,t){return t>0?e.z.map((r,n)=>{let o=W_(e,n,t/2);return o?o.value.reduce((a,s,i)=>a+s*e.z[o.j[i]],0):r}):[...e.z]}function j_(e,t){if(!(e>0)||!(t>0))return 0;let r=(22.5*t*e*e/1e-4**2)**.2;return Math.min(100/2,r)}function Lm(e){let t=tc(e);if(!t)return 0;let r=nA(t);return r>1e-6?Math.max(10,j_(r,U_(t))):0}function U_(e){let t=[];for(let r=1;r<e.pos.length;r++)t.push(e.pos[r]-e.pos[r-1]);return e.closed&&e.pos.length&&t.push(e.length-e.pos[e.pos.length-1]+e.pos[0]),t.sort((r,n)=>r-n),t.length?t[t.length>>1]:0}function xr(e,t,r){let n=e.n;if(e.closed===!1){let a=r-t;return a===0?e.diag[t]:a===1?e.off1[t]:a===2?e.off2[t]:a===-1?e.off1[r]:a===-2?e.off2[r]:0}let o=((r-t)%n+n)%n;return o===0?e.diag[t]:o===1?e.off1[t]:o===2?e.off2[t]:o===n-1?e.off1[r]:o===n-2?e.off2[r]:0}function Em(e,t){let r=e.n,n=new Array(r).fill(0);for(let o=0;o<r;o++){let a=e.diag[o]*t[o];for(let[s,i]of[[1,e.off1],[2,e.off2]]){(o+s<r||e.closed!==!1)&&(a+=i[o]*t[(o+s)%r]);let c=(o-s+r)%r;(o-s>=0||e.closed!==!1)&&(a+=i[c]*t[c])}n[o]=a}return n}function oA(e,t){let r=new Array(e).fill(0),n=new Array(e).fill(0),o=new Array(e).fill(0);for(let a=0;a<e;a++){a>=2&&(o[a]=r[a-2]!==0?t(a,a-2)/r[a-2]:0),a>=1&&(n[a]=r[a-1]!==0?(t(a,a-1)-o[a]*n[a-1])/r[a-1]:0);let s=t(a,a)-n[a]*n[a]-o[a]*o[a];if(!(s>0)||!Number.isFinite(s))return null;r[a]=Math.sqrt(s)}return{d:r,l1:n,l2:o}}function Dm(e,t){let r=t.length,n=new Array(r).fill(0);for(let a=0;a<r;a++){let s=t[a];a>=1&&(s-=e.l1[a]*n[a-1]),a>=2&&(s-=e.l2[a]*n[a-2]),n[a]=s/e.d[a]}let o=new Array(r).fill(0);for(let a=r-1;a>=0;a--){let s=n[a];a+1<r&&(s-=e.l1[a+1]*o[a+1]),a+2<r&&(s-=e.l2[a+2]*o[a+2]),o[a]=s/e.d[a]}return o}function X_(e,t){let r=e[0][0]*e[1][1]-e[0][1]*e[1][0],n=Math.max(Math.abs(e[0][0]*e[1][1]),Math.abs(e[0][1]*e[1][0]),Number.MIN_VALUE);return!Number.isFinite(r)||Math.abs(r)<1e-12*n?null:[(t[0]*e[1][1]-e[0][1]*t[1])/r,(e[0][0]*t[1]-t[0]*e[1][0])/r]}function Mg(e,t){let r=e.n;if(r<7)throw new Error(`periodic band solver needs n >= 7, got ${r}`);if(e.closed===!1){let b=oA(r,(y,R)=>xr(e,y,R));if(!b)return null;let g=Dm(b,t);return g.every(Number.isFinite)?g:null}let n=r-2,a=oA(n,(b,g)=>xr(e,b,g));if(!a)return null;let s=new Array(n).fill(0),i=new Array(n).fill(0);for(let b=0;b<n;b++)s[b]=xr(e,b,r-2),i[b]=xr(e,b,r-1);let c=Dm(a,t.slice(0,n)),l=Dm(a,s),u=Dm(a,i),m=(b,g)=>{let y=0;for(let R=0;R<b.length;R++)y+=b[R]*g[R];return y},d=[[xr(e,r-2,r-2)-m(s,l),xr(e,r-2,r-1)-m(s,u)],[xr(e,r-1,r-2)-m(i,l),xr(e,r-1,r-1)-m(i,u)]],p=[t[r-2]-m(s,c),t[r-1]-m(i,c)],f=X_(d,p);if(!f)return null;let h=new Array(r).fill(0);for(let b=0;b<n;b++)h[b]=c[b]-l[b]*f[0]-u[b]*f[1];return h[r-2]=f[0],h[r-1]=f[1],h.every(Number.isFinite)?h:null}function aA(e,t,r=0){let n=Math.max(...e.diag.map(Math.abs),1e-30),o=r>0?r:n*1e-12,a=Math.sqrt(t.reduce((s,i)=>s+i*i,0));for(let s=0;s<40;s++){let i={...e,diag:e.diag.map(l=>l+o)},c=Mg(i,t);if(c){let l=Em(i,c).map((m,d)=>m-t[d]);if(Math.sqrt(l.reduce((m,d)=>m+d*d,0))<=1e-6*Math.max(a,1e-12))return c}o=o===0?n*1e-12:o*10}return null}var sA=4,q_=8,Sg=.001;function Q_(e,t,r){let n=[];for(let c=1;c<e.length;c++){let l=e[c]-e[c-1];l>=Sg&&n.push(l)}let o=Float64Array.from(n).sort(),a=o.length>>1,s=o.length?o.length%2?o[a]:.5*(o[a-1]+o[a]):0,i=t?n.length:n.length+1;return Math.max(3,Math.round(i/hM(r,s,i)))}function Z_(e,t){let r=e.closed!==!1,n=[],o=[],a=(A,w)=>{let C=n.length-1;C>=0&&Math.hypot(A-n[C],w-o[C])<Sg||(n.push(A),o.push(w))},s=e.x.length,i=r?s:s-1,c=new Array(i+1);c[0]=0;for(let A=0;A<i;A++){let w=(A+1)%s;c[A+1]=c[A]+Math.hypot(e.x[w]-e.x[A],e.y[w]-e.y[A])}let l=c[i],u=e.fit==="interpolate",m=u?s:Q_(c,r,t),d=r?m:m-1,p=0;for(let A=0;A<=d&&!(r&&A===d);A++){if(u){a(e.x[A],e.y[A]);continue}let w=A*l/d;for(;p<i-1&&c[p+1]<w;)p++;let C=c[p+1]-c[p],T=C>0?(w-c[p])/C:0,F=(p+1)%s;a(e.x[p]+T*(e.x[F]-e.x[p]),e.y[p]+T*(e.y[F]-e.y[p]))}if(r)for(;n.length>2&&Math.hypot(n[n.length-1]-n[0],o[o.length-1]-o[0])<Sg;)n.pop(),o.pop();let f=n.length,h=r?f:f-1,b=new Array(h+1);b[0]=0;for(let A=1;A<=h;A++){let w=A%f,C=n[w]-n[A-1],T=o[w]-o[A-1],F=Math.sqrt(Math.hypot(C,T))||1e-9;b[A]=b[A-1]+F}let g=r?Pm(b.slice(0,f),n,b[f]):vg(b,n),y=r?Pm(b.slice(0,f),o,b[f]):vg(b,o),R=new Array(h);for(let A=0;A<h;A++)R[A]=b[A+1]-b[A];let k=[0],v=[0],x=[0],M=0;for(let A=0;A<h;A++){let w=R[A]/sA;for(let C=0;C<sA;C++){let T=C*w;M+=Th(F=>Math.hypot(g.d1(A,F),y.d1(A,F)),T,T+w),k.push(M),v.push(A),x.push(T+w)}}return{closed:r,sx:g,sy:y,h:R,sTable:k,segTable:v,uTable:x,length:M,rawCum:c,rawLength:l}}function rc(e,t,r,n){if(e===void 0)return r.map(()=>t);if(typeof e=="number")return r.map(()=>e);let o=e.length;if(o===0)return r.map(()=>t);if(o===1)return r.map(()=>e[0]);let a=n.rawCum.length-1,s=o===(n.closed?a:a+1);return r.map(i=>{let c;if(s){let d=i*n.rawLength,p=0,f=a;for(;p<f;){let b=p+f+1>>1;n.rawCum[b]<=d?p=b:f=b-1}let h=p<a?n.rawCum[p+1]-n.rawCum[p]:0;c=p+(h>0?(d-n.rawCum[p])/h:0)}else c=n.closed?i*o:i*(o-1);let l=Math.min(Math.floor(c),o-1)%o,u=c-Math.floor(c),m=n.closed?(l+1)%o:Math.min(l+1,o-1);return e[l]+u*(e[m]-e[l])})}var J_=.01,eN=3,iA=10;function tN(e,t,r,n=iA){let o={step:0,uncertainty:1/0},a=e.length;if(a<8||!(r>0))return o;let s=Math.max(iA,n,6*r/a),i=(r-t[a-1])/2,c=0;for(;c<a/2&&t[c]+i<=s;)c++;let l=0;for(;l<a/2&&r-t[a-1-l]-i<=s;)l++;let u=Math.min(c,l);if(u<3)return o;let m=[],d=[],p=(R,k,v)=>{let x=R/s;m.push([1,x,x*x,x*x*x,k]),d.push(v)};for(let R=0;R<u;R++)p(t[R]+i,1,e[R]);for(let R=0;R<u;R++)p(t[a-1-R]-r+i,0,e[a-1-R]);let f=Array.from({length:5},()=>new Array(5).fill(0)),h=new Array(5).fill(0);m.forEach((R,k)=>{for(let v=0;v<5;v++){h[v]+=R[v]*d[k];for(let x=0;x<5;x++)f[v][x]+=R[v]*R[x]}});let b=or(f,h),g=or(f,[0,0,0,0,1]);if(b.singular||g.singular)return o;let y=0;return m.forEach((R,k)=>{let v=0;for(let x=0;x<5;x++)v+=R[x]*b.x[x];y+=(d[k]-v)**2}),{step:b.x[4],uncertainty:Math.sqrt(y/(m.length-5)*g.x[4])}}function rN(e,t){let r=t[t.length-1];return{pos:e===t.length-1?t.slice(0,e):Array.from({length:e},(o,a)=>a/e*r),loop:r}}function nN(e,t,r){let{pos:n,loop:o}=rN(e.length,t),{step:a,uncertainty:s}=tN(e,n,o,r);return Math.abs(a)>Math.max(J_,eN*s)?{z:e.map((i,c)=>i+a*n[c]/o),drift:-a}:{z:e,drift:0}}function oN(e,t){let{sTable:r,segTable:n,uTable:o,h:a,sx:s,sy:i}=e,c=0,l=r.length-1;for(;c<l;){let y=c+l+1>>1;r[y]<=t?c=y:l=y-1}let u=Math.min(c,r.length-2),m=r[u],d=r[u+1],p=n[u+1],f=o[u+1],h=n[u]===p?o[u]:0,b=d-m,g=b>0?h+(t-m)/b*(f-h):h;for(let y=0;y<2;y++){let R=m+Th(v=>Math.hypot(s.d1(p,v),i.d1(p,v)),h,g),k=Math.hypot(s.d1(p,g),i.d1(p,g));if(k<1e-12)break;g-=(R-t)/k}return{seg:p,du:Math.min(Math.max(g,0),a[p])}}var aN=3,Ag=5;function sN(e,t,r,n=Ag){return _m(e,t,r,n)}function _m(e,t,r,n,o=!1){let a=e.length;if(!(t>0)||!(n>0)||a<7)return[...e];let s=(n/(2*Math.PI*t))**4,i=new Array(a).fill(1+6*s),c=new Array(a).fill(-4*s),l=new Array(a).fill(s),u=[...e];if(!r&&(i[0]=i[a-1]=1+s,i[1]=i[a-2]=1+5*s,c[0]=c[a-2]=-2*s,o)){let m=1e9*(1+s);for(let d of[0,a-1])i[d]+=m,u[d]*=1+m}return Mg({n:a,diag:i,off1:c,off2:l,closed:r},u)??[...e]}function ct(e,t){let r=it(t),n=Z_(e,r.fitSpacing),o=n.length,a=Math.max(q_,Math.round(o/r.dsTarget)),s=n.closed?a:a+1,i=o/a,c=new Array(s),l=new Array(s),u=new Array(s),m=new Array(s).fill(i);n.closed||(m[s-1]=0);let d=new Array(s),p=new Array(s),f=new Array(s);for(let C=0;C<s;C++){let T=C*i,{seg:F,du:S}=oN(n,T);c[C]=n.sx.eval(F,S),l[C]=n.sy.eval(F,S),u[C]=T;let P=n.sx.d1(F,S),L=n.sy.d1(F,S),D=n.sx.d2(F,S),I=n.sy.d2(F,S),O=Math.hypot(P,L),_=Math.pow(P*P+L*L,1.5);d[C]=_>0?(P*I-L*D)/_:0,p[C]=O>0?-L/O:0,f[C]=O>0?P/O:0}let h=u.map(C=>o>0?Math.min(1,C/o):0),b=Array.isArray(e.z)&&e.z.length>1,g=b&&(e.zSmoothing??0)>0?e.zSmoothing:0,y=b&&n.closed?nN(e.z,n.rawCum,g):null,R=y?y.z:e.z,k=g>0?tc(e):null,v=k?kg({...k,z:R},g):R,x=rc(v,0,h,n),M=new Array(s).fill(0);if(b){for(let T=0;T<s;T++){let F=n.closed?(T+1)%s:Math.min(T+1,s-1),S=n.closed?(T-1+s)%s:Math.max(T-1,0),P=n.closed?2:F-S,L=x[F]-x[S];M[T]=P>0?Math.atan2(L,P*i)*180/Math.PI:0}for(let T=0;T<s;T++){if(m[T]===0)continue;let F=n.closed?(T+1)%s:T+1,S=x[F]-x[T];m[T]=Math.hypot(i,S)}let C=0;for(let T=0;T<s;T++)u[T]=C,C+=m[T]}let A=b?m.reduce((C,T)=>C+T,0):o,w;if(b){w=new Array(s).fill(0);let C=Math.max(aN,e.zReach??Lm(e)),T=Math.max(2,Math.round(C/i));if(n.closed?s>2*T:s>2*T+1){let F=0,S=0;for(let D=-T;D<=T;D++)F+=D*D,S+=D*D*D*D;let P=2*T+1,L=S-F*F/P;for(let D=0;D<s;D++){let I=n.closed?D:Math.min(Math.max(D,T),s-1-T),O=0,_=0;for(let N=-T;N<=T;N++){let B=x[n.closed?(I+N+s)%s:I+N];O+=(N*N-F/P)*B,_+=N*B}let z=2*O/L/(i*i),E=_/F/i;w[D]=z/Math.pow(1+E*E,1.5)}}}return{name:e.name,closed:n.closed,x:c,y:l,s:u,ds:m,curvature:e.turnReach?sN(d,i,n.closed,e.turnReach):d,npts:s,length:A,nx:p,ny:f,z:x,gradient:M,...w?{verticalCurvature:w}:{},widthLeft:rc(e.widthLeft,1.5,h,n),widthRight:rc(e.widthRight,1.5,h,n),bank:rc(e.bank,0,h,n),mu:rc(e.mu,1,h,n),...y?.drift?{elevationDrift:y.drift}:{}}}function cA(e,t,r){let n=Em(e,r),o=0;for(let a=0;a<r.length;a++)o+=.5*r[a]*n[a]-t[a]*r[a];return o}function iN(e,t,r,n){let o=e.n,a=e.closed!==!1,s=(l,u)=>{let m=l+u;return a?(m%o+o)%o:m>=0&&m<o?m:null},i=[...t];for(let l=0;l<o;l++){if(r[l]==="free")continue;let u=n(l);if(u!==0)for(let m of[-2,-1,1,2]){let d=s(l,m);d!=null&&(i[d]-=xr(e,d,l)*u)}}let c={n:o,closed:e.closed,diag:[...e.diag],off1:[...e.off1],off2:[...e.off2]};for(let l=0;l<o;l++){if(r[l]==="free")continue;c.diag[l]=1,c.off1[l]=0,c.off2[l]=0;let u=s(l,-1),m=s(l,-2);u!=null&&(c.off1[u]=0),m!=null&&(c.off2[m]=0),i[l]=n(l)}return aA(c,i)}var cN=1e-4;function lA(e,t,r,n,o={}){let a=e.n,s=o.maxIter??60,i=o.tol??1e-9,c=o.bounds,l=(f,h)=>Math.min(n[h],Math.max(r[h],f)),u=r.map((f,h)=>c?.[h]==="hi"?n[h]:c?.[h]==="lo"?r[h]:l(0,h)),m=cA(e,t,u),d=new Array(a).fill("free"),p=!1;for(let f=0;f<s;f++){let h=Em(e,u).map((R,k)=>R-t[k]),b=!1;for(let R=0;R<a;R++){let k=u[R]<=r[R]+i&&h[R]>=-i?"lo":u[R]>=n[R]-i&&h[R]<=i?"hi":"free";k!==d[R]&&(d[R]=k,b=!0)}if(p&&!b)return{x:u,iterations:f+1,converged:!0,bounds:d};let g=iN(e,t,d,R=>u[R]);if(!g)return{x:u,iterations:f+1,converged:!1,bounds:d};let y=!1;for(let R=1;R>1e-12;R*=.5){let k=!1,v=u.map((A,w)=>{if(d[w]!=="free")return A;let C=A+R*(g[w]-A),T=l(C,w);return T!==C&&(k=!0),T}),x=cA(e,t,v),M=0;for(let A=0;A<a;A++)M+=h[A]*(v[A]-u[A]);if(R===1&&!k||x<m&&x<=m+cN*M){u=v,m=x,p=R===1&&!k,y=!0;break}}if(!y)return{x:u,iterations:f+1,converged:!1,bounds:d}}return{x:u,iterations:s,converged:!1,bounds:d}}var Fg={lineStep:2,carHalfWidth:.75,margin:.1,foldMargin:.25,referenceReach:5,passes:40,iterations:400},lN=[1,.5,.25,.125,.0625,.03125,.015625,.0078125,.00390625,.001953125,.0009765625],uN=e=>Math.sqrt(e.reduce((t,r)=>t+r*r,0)/(e.length||1));function nc(e,t,r=!0){let n=e.length,o=new Array(n).fill(0);for(let a=0;a<n;a++){if(!r&&(a===0||a===n-1))continue;let s=(a-1+n)%n,i=(a+1)%n,c=e[a]-e[s],l=t[a]-t[s],u=e[i]-e[a],m=t[i]-t[a],d=e[i]-e[s],p=t[i]-t[s],f=Math.hypot(c,l),h=Math.hypot(u,m),b=Math.hypot(d,p),g=f*h*b;o[a]=g>1e-12?2*(c*m-l*u)/g:0}return o}var mN=Math.PI/180,uA=20;function pN(e,t){let r=e.npts,n=e.closed,o=e.x.map((p,f)=>p+t[f]*e.nx[f]),a=e.y.map((p,f)=>p+t[f]*e.ny[f]),s=[0];for(let p=1;p<r;p++)s.push(s[p-1]+Math.hypot(o[p]-o[p-1],a[p]-a[p-1]));let i=n?s[r-1]+Math.hypot(o[0]-o[r-1],a[0]-a[r-1]):s[r-1],c=n?[-1,0,1]:[0],l=[],u=[];for(let p of c)for(let f=0;f<r;f++)l.push(s[f]+p*i),u.push(f+p*r);n&&(l.push(2*i),u.push(2*r));let m=[0];for(let p=1;p<l.length;p++)m.push(m[p-1]+.5*(u[p]+u[p-1])*(l[p]-l[p-1]));let d=p=>{let f=0,h=l.length-1;for(;h-f>1;){let g=f+h>>1;l[g]<=p?f=g:h=g}let b=l[h]>l[f]?(p-l[f])/(l[h]-l[f]):0;return m[f]+(l[h]-l[f])*b*(u[f]+.5*b*(u[h]-u[f]))};return s.map((p,f)=>{let h=n?uA:Math.min(uA,p,i-p);if(!(h>0))return e.z[f];let b=(d(p+h)-d(p-h))/(2*h),g=n?(b%r+r)%r:Math.min(Math.max(b,0),r-1),y=Math.min(Math.floor(g),r-1),R=n?(y+1)%r:Math.min(y+1,r-1);return e.z[y]+(g-y)*(e.z[R]-e.z[y])})}function dN(e,t,r){let n=Array.isArray(e.z)&&e.z.length>1,o=t.bank.some(i=>i!==0),a=t.mu.some(i=>i!==1),s=n?pN(t,r):t.z;return{...n||o?{z:s.map((i,c)=>i+r[c]*Math.tan(t.bank[c]*mN))}:{},...n?{zReach:e.zReach??Lm(e)}:{},...o?{bank:[...t.bank]}:{},...a?{mu:[...t.mu]}:{}}}function mA(e,t,r=!0){let n=e.length,o=new Array(n).fill(0);for(let a=0;a<n;a++){if(!r&&(a===0||a===n-1))continue;let s=(a-1+n)%n,i=(a+1)%n;o[a]=.5*(Math.hypot(e[a]-e[s],t[a]-t[s])+Math.hypot(e[i]-e[a],t[i]-t[a]))}return o}function fN(e,t,r,n,o){let a=e.length,s=new Array(a).fill(0),i={l:new Array(a).fill(0),d:new Array(a).fill(0),r:new Array(a).fill(0)},c=(l,u,m,d)=>l*d-u*m;for(let l=0;l<a;l++){if(!o&&(l===0||l===a-1))continue;let u=(l-1+a)%a,m=(l+1)%a,d=e[l]-e[u],p=t[l]-t[u],f=e[m]-e[l],h=t[m]-t[l],b=e[m]-e[u],g=t[m]-t[u],y=Math.hypot(d,p),R=Math.hypot(f,h),k=Math.hypot(b,g),v=y*R*k;if(!(v>1e-12))continue;let x=2*c(d,p,f,h)/v,M=Math.sqrt(.5*(y+R)),A=x/(2*M),w=(d*r[u]+p*n[u])/y,C=(b*r[u]+g*n[u])/k,T=(d*r[l]+p*n[l])/y,F=(f*r[l]+h*n[l])/R,S=(f*r[m]+h*n[m])/R,P=(b*r[m]+g*n[m])/k,L=-2*c(r[u],n[u],f,h)/v+x*(w/y+C/k),D=2*c(r[l],n[l],b,g)/v-x*(T/y-F/R),I=2*c(d,p,r[m],n[m])/v-x*(S/R+P/k);s[l]=x*M,i.l[l]=M*L-A*.5*w,i.d[l]=M*D+A*.5*(T-F),i.r[l]=M*I+A*.5*S}return{res:s,jac:i}}function hN(e,t,r,n,o){let a=n-r+1,s=e.l.slice(r,n+1),i=e.d.slice(r,n+1),c=e.r.slice(r,n+1),l=t.slice(r,n+1);o||(i[0]+=s[0],s[0]=0,i[a-1]+=c[a-1],c[a-1]=0);let u=(h,b)=>o?h[(b+a)%a]:b>=0&&b<a?h[b]:0,m=new Array(a),d=new Array(a),p=new Array(a),f=new Array(a);for(let h=0;h<a;h++){let b=u(c,h-1),g=u(s,h+1);m[h]=b*b+i[h]*i[h]+g*g,d[h]=i[h]*c[h]+g*u(i,h+1),p[h]=g*u(c,h+1),f[h]=-(b*u(l,h-1)+i[h]*l[h]+g*u(l,h+1))}return{M:{n:a,closed:o,diag:m,off1:d,off2:p},b:f}}function bN(e,t){let r=e.npts,n=e.closed;if(!(t>0)||r<7)return e;let o=n?r:r-1,a=0;for(let d=0;d<o;d++){let p=(d+1)%r;a+=Math.hypot(e.x[p]-e.x[d],e.y[p]-e.y[d])}let s=a/o,i=_m(e.x,s,n,t,!0),c=_m(e.y,s,n,t,!0),l=new Array(r),u=new Array(r);for(let d=0;d<r;d++){let p=n?(d-1+r)%r:Math.max(d-1,0),f=n?(d+1)%r:Math.min(d+1,r-1),h=i[f]-i[p],b=c[f]-c[p],g=Math.hypot(h,b)||1;l[d]=-b/g,u[d]=h/g}let m=nc(i,c,n);return n||(m[0]=m[1],m[r-1]=m[r-2]),{...e,x:i,y:c,nx:l,ny:u,curvature:m}}var gN=6;function yN(e,t,r,n){let o=e.npts,a=e.closed?o:o-1,s=new Array(a);for(let l=0;l<a;l++){let u=(l+1)%o,m=Math.atan2(e.nx[l]*e.ny[u]-e.ny[l]*e.nx[u],e.nx[l]*e.nx[u]+e.ny[l]*e.ny[u]),d=Math.hypot(e.x[u]-e.x[l],e.y[u]-e.y[l]);s[l]=d>1e-9?m/d:0}let i=Math.max(0,Math.round(gN/(e.ds[0]||1))),c=1-n;for(let l=0;l<o;l++){let u=0,m=0;for(let d=-i-1;d<=i;d++){let p=e.closed?((l+d)%o+o)%o:l+d;p<0||p>=a||(u=Math.max(u,s[p]),m=Math.max(m,-s[p]))}u>0&&(t[l]=Math.max(r[l],Math.min(t[l],c/u))),m>0&&(r[l]=Math.min(t[l],Math.max(r[l],-c/m)))}}function wg(e,t={}){let r={...Fg,...t},n=ct(e,{dsTarget:r.lineStep}),o=bN(n,r.referenceReach),a=o.npts,s=T=>({x:o.x.map((F,S)=>F+o.nx[S]*T[S]),y:o.y.map((F,S)=>F+o.ny[S]*T[S])}),i=T=>{let F=nc(T.x,T.y,o.closed),S=mA(T.x,T.y,o.closed),P=0;for(let L=0;L<F.length;L++)P+=F[L]*F[L]*S[L];return P},c=uN(n.curvature),l=mA(n.x,n.y,n.closed).reduce((T,F)=>T+F,0),u=new Array(a).fill(0),m=r.carHalfWidth+r.margin,d=new Array(a),p=new Array(a),f=0;for(let T=0;T<a;T++){let F=o.widthLeft[T]-m,S=-(o.widthRight[T]-m);if(F<S){f++;let P=(o.widthLeft[T]-o.widthRight[T])/2;d[T]=P,p[T]=P}else d[T]=F,p[T]=S}let h=[...d],b=[...p];yN(o,d,p,r.foldMargin);let g=T=>{let F=s(T),S=dN(e,o,T),P={name:`${e.name} \u2014 racing line`,x:F.x,y:F.y,closed:o.closed,widthLeft:h.map((E,N)=>Math.max(0,E-T[N])),widthRight:b.map((E,N)=>Math.max(0,T[N]-E)),...S,fit:"interpolate",turnReach:Ag},L=1e-6,D=T.filter((E,N)=>E>=d[N]-L||E<=p[N]+L).length,I=nc(F.x,F.y,o.closed),O=E=>1/Math.max(...E.map(Math.abs),1e-9),_=0,z=o.closed?F.x.length:F.x.length-1;for(let E=0;E<z;E++){let N=(E+1)%F.x.length,B=F.x[N]-F.x[E],V=F.y[N]-F.y[E];_+=S.z?Math.hypot(B,V,S.z[N]-S.z[E]):Math.hypot(B,V)}return{offset:T,s:[...o.s],asset:P,curvatureRms:{centreLine:c,racingLine:Math.sqrt(i(F)/(l||1))},infeasibleSamples:f,atBoundary:a?D/a:0,length:{centreLine:n.length,racingLine:_},worstRadius:{centreLine:O(n.curvature),racingLine:O(I)}}},y=o.closed?0:1,R=o.closed?a-1:a-2,k=R-y+1,v=new Array(k),x=new Array(k);for(let T=0;T<k;T++)v[T]=p[y+T],x[T]=d[y+T];if(!o.closed&&k>0){let T=(F,S)=>{if(v[F]=Math.max(v[F],p[S]),x[F]=Math.min(x[F],d[S]),v[F]>x[F]){let P=.5*(v[F]+x[F]);v[F]=P,x[F]=P}};T(0,0),T(k-1,a-1),v[0]=x[0]=Math.min(x[0],Math.max(v[0],0))}if(k<7)return g(u);let M=T=>{let F=s(T),P=[...nc(F.x,F.y,o.closed).map(Math.abs)].sort((L,D)=>L-D);return{integral:i(F),tail:P[Math.floor(.99*(P.length-1))]}},A=[...u],w=M(u),C;for(let T=0;T<r.passes;T++){let F=s(A),{res:S,jac:P}=fN(F.x,F.y,o.nx,o.ny,o.closed),{M:L,b:D}=hN(P,S,y,R,o.closed),I=lA(L,D,v.map((z,E)=>z-A[y+E]),x.map((z,E)=>z-A[y+E]),{maxIter:r.iterations,bounds:C});C=I.bounds;let O=new Array(a).fill(0);for(let z=0;z<k;z++)O[y+z]=I.x[z];o.closed||(O[0]=O[1],O[a-1]=O[a-2]);let _=!1;for(let z of lN){let E=A.map((B,V)=>B+z*O[V]),N=M(E);if(N.integral<w.integral*(1-1e-6)){A=E,w=N,_=!0;break}}if(!_)break}return g(A)}function Cg(e){let t=Math.max(Q(e,"track_front"),Q(e,"track_rear"));return(t>0?t/2e3:.6)+.1}function Nm(e,t,r={}){if(!r.racingLine)return{asset:e,numerics:t,line:null};let n=r.params?Cg(r.params):void 0,o=wg(e,{...r.line,...n?{carHalfWidth:n}:{}});return{asset:o.asset,numerics:{...t,fitSpacing:0},line:o}}function oc(e,t,r={}){let n=Nm(e,t,r);return{track:ct(n.asset,n.numerics),line:n.line}}function Tg(e=4,t=oc){let r=new WeakMap;return(n,o,a={})=>{let s=a.racingLine===!0,i=s?[a.params?Cg(a.params):null,a.line??null]:null,c=JSON.stringify([o,s,i]),l=r.get(n);l||(l=new Map,r.set(n,l));let u=l.get(c);if(u)return l.delete(c),l.set(c,u),u;let m=t(n,o,a);return l.set(c,m),l.size>e&&l.delete(l.keys().next().value),m}}var pA={racingLine:!1,standingStart:!1},Om=256;function ac(e,t,r,n,o=pA,a=oc){let s=go(n),{racingLine:i,standingStart:c,lapCounts:l}=o;return e.map(u=>{let{track:m}=a(t,r,{racingLine:i,params:u});return lg(Yi(u,s,{track:m,numerics:r,standingStart:c,lapCounts:l}))})}function Pg(e,t){let r=go(e),n=r.score?r.score(t):null,o=r.field===r.score?n:r.field?r.field(t):null;return{scores:n,field:o}}function Lg(e,t,r){let n={};for(let o of go(e).metrics)n[o.key]=o.value(t,r);return n}var Vm=36;var Ig=287.05287,RN=461.495,Bm=9.80665/(Ig*.0065),vN=101325/(Ig*288.15),kN=273.15,MN=-500,SN=6e3,AN=400,FN=1100,$m={source:"car",altitudeM:0,pressure:{kind:"standard"},humidityPct:0};function wN(e){return 101325*Math.pow(1-.0065*e/288.15,Bm)}function CN(e){return 288.15/.0065*(1-Math.pow(e/vN,1/(Bm-1)))}function TN(e){return 288.15/.0065*(1-Math.pow(e/101325,1/Bm))}function PN(e,t){return e*Math.pow(1-.0065*t/288.15,Bm)}function LN(e){return 611.21*Math.exp((18.678-e/234.5)*(e/(257.14+e)))}function DN(e,t){switch(e.kind){case"standard":return wN(t);case"qnh":return PN(e.hPa*100,t);case"station":return e.hPa*100}}function sc(e,t,r=0,n=TN(e)){let o=t+kN,a=Math.min(.5*e,Math.max(0,Math.min(100,r))/100*LN(t)),s=e-a,i=s/(Ig*o)+a/(RN*o);return{altitudeM:n,p:e,pDry:s,T:o,rho:i,densityAltitudeM:CN(i)}}function dA(e,t){return sc(DN(e.pressure,e.altitudeM),t,e.humidityPct,e.altitudeM)}var Dg=(e,t,r)=>Math.min(r,Math.max(t,e)),Eg=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function Gm(e){if(!e||typeof e!="object")return structuredClone($m);let t=e,r=t.pressure??{},n=Dg(Eg(r.hPa,1013.25),AN,FN),o=r.kind==="qnh"?{kind:"qnh",hPa:n}:r.kind==="station"?{kind:"station",hPa:n}:{kind:"standard"};return{source:t.source==="venue"?"venue":"car",altitudeM:Dg(Eg(t.altitudeM,0),MN,SN),pressure:o,humidityPct:Dg(Eg(t.humidityPct,0),0,100)}}var ic=e=>e?.source==="venue";var EN=Math.PI/180;function IN(){return{ucaFront:[110,245,330],ucaRear:[-110,258,335],lcaFront:[130,185,112],lcaRear:[-130,205,116],tieInner:[-92,210,132],uprightUpper:[-6,542,352],uprightLower:[4,560,120],tieOuter:[-78,556,146],wheelCenter:[0,600,230],pushrodOuter:[8,520,128],rockerPivotA:[70,380,440],rockerPivotB:[-50,383,442],rockerToPushrod:[10,480,420],rockerToDamper:[10,280,440],damperChassis:[10,275,245]}}function _N(){return{ucaFront:[120,250,340],ucaRear:[-120,262,345],lcaFront:[140,190,118],lcaRear:[-140,210,122],tieInner:[120,215,150],uprightUpper:[-4,548,360],uprightLower:[6,566,126],tieOuter:[108,560,158],wheelCenter:[0,610,232],pushrodOuter:[10,526,132],rockerPivotA:[70,385,450],rockerPivotB:[-50,388,452],rockerToPushrod:[12,486,430],rockerToDamper:[12,286,450],damperChassis:[12,281,255]}}function _g(e){let t=-e*EN;return q([0,Math.cos(t),Math.sin(t)])}function Km(){let e={rodType:"push",pushrodAttach:"lowerArm",steerMode:"rack",spinAxis:_g(-1),loadedRadius:230,springRate:35,rackAxis:[0,1,0]};return{hardpoints:IN(),config:e}}function cc(){let e={rodType:"pull",pushrodAttach:"lowerArm",steerMode:"fixed",spinAxis:_g(-1.5),loadedRadius:232,springRate:40,rackAxis:[0,1,0]};return{hardpoints:_N(),config:e}}function Hm(){let e=[-25,635,460],t=[-40,600,710],r={layout:"mcpherson",actuation:"direct",rodType:"push",pushrodAttach:"upright",steerMode:"rack",spinAxis:_g(-.5),loadedRadius:320,springRate:38,rackAxis:[0,1,0],rackTravel:70};return{hardpoints:{ucaFront:[49,426,430],ucaRear:[-99,425,431],lcaFront:[60,395,180],lcaRear:[-280,415,185],tieInner:[-150,375,256],uprightUpper:[...e],uprightLower:[0,720,145],tieOuter:[-140,705,230],wheelCenter:[0,775,320],pushrodOuter:[...e],damperChassis:[...t],rockerPivotA:[...t],rockerPivotB:[...t],rockerToPushrod:[...e],rockerToDamper:[...t]},config:r}}function Ng(){return{front:Km(),rear:cc(),config:{wheelbase:1600,trackFront:1200,trackRear:1220,frontAxleX:800}}}var NN=Math.PI/180;function fA(e){let t=-e*NN;return q([0,Math.cos(t),Math.sin(t)])}function Og(e,t){let r=([l,u,m])=>[l*t.kx,u*t.ky,m*t.kz],n=e.hardpoints,o=Object.fromEntries(Object.entries(n).map(([l,u])=>[l,r(u)])),a=(l,u)=>{o[l]=[o[l][0],o[l][1],o[l][2]+u]},s=t.lowerInnerDz??0,i=t.upperInnerDz??0;a("lcaFront",s),a("lcaRear",s),a("tieInner",s),a("ucaFront",i),a("ucaRear",i);let c={...e.config,spinAxis:fA(t.camberDeg),loadedRadius:t.loadedRadius,springRate:t.springRate};if(t.actuation==="direct"){let l=o.pushrodOuter,u=[l[0],l[1]*.7,l[2]+1.3*t.loadedRadius];o.damperChassis=u,o.rockerPivotA=u,o.rockerPivotB=u,o.rockerToPushrod=l,o.rockerToDamper=u,c={...c,actuation:"direct",rodType:"push",pushrodAttach:"lowerArm"}}else c={...c,actuation:"rocker"};for(let l of Object.keys(o))o[l]=ON(o[l]);return{hardpoints:o,config:c}}function ON(e){return e.map(t=>Math.round(t*10)/10+0)}function xo(e){return{name:e.name,front:Og(Km(),e.front),rear:Og(cc(),e.rear),config:{wheelbase:e.wheelbase,trackFront:e.trackFront,trackRear:e.trackRear,frontAxleX:e.wheelbase/2}}}function Wa(e,t,r){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:t}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:r}}}}var ja=600,Ro=610,Ua=230,vo=232;function ko(){let e=Ng();return{...e,name:"Formula Student",front:{...e.front,config:{...e.front.config,actuation:"rocker"}},rear:{...e.rear,config:{...e.rear.config,actuation:"rocker"}}}}function Vg(){return xo({name:"Formula 1",wheelbase:3600,trackFront:1600,trackRear:1600,front:{kx:1.3,ky:800/ja,kz:355/Ua,lowerInnerDz:-5,upperInnerDz:0,camberDeg:-3,loadedRadius:355,springRate:200},rear:{kx:1.3,ky:800/Ro,kz:355/vo,lowerInnerDz:35,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:220}})}function lc(){return Wa(xo({name:"GT car",wheelbase:2700,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/ja,kz:325/Ua,lowerInnerDz:18,upperInnerDz:5,camberDeg:-3.5,loadedRadius:325,springRate:110,actuation:"direct"},rear:{kx:1.2,ky:825/Ro,kz:325/vo,lowerInnerDz:36,upperInnerDz:15,camberDeg:-2,loadedRadius:325,springRate:120,actuation:"direct"}}),318.6,318.6)}function uc(){return Wa(xo({name:"Sports car",wheelbase:2750,trackFront:1550,trackRear:1550,front:{kx:1.15,ky:775/ja,kz:320/Ua,lowerInnerDz:36,upperInnerDz:15,camberDeg:-.5,loadedRadius:320,springRate:55,actuation:"direct"},rear:{kx:1.15,ky:775/Ro,kz:320/vo,lowerInnerDz:57,upperInnerDz:25,camberDeg:-1,loadedRadius:320,springRate:60,actuation:"direct"}}),305.4,309)}function VN(e,t,r,n,o,a){let s=Hm(),i=Object.fromEntries(Object.entries(s.hardpoints).map(([l,[u,m,d]])=>[l,[u,m+e,d]])),c=(l,u)=>{i[l]=[i[l][0],i[l][1],i[l][2]+u]};return c("lcaFront",t),c("lcaRear",t),c("tieInner",r),{hardpoints:i,config:{...s.config,spinAxis:fA(n),springRate:o,rackTravel:a}}}function hA(){return Wa({name:"Cup car",front:VN(55,-25,-23,-3.5,150,55),rear:Og(cc(),{kx:1.15,ky:820/Ro,kz:320/vo,lowerInnerDz:37,upperInnerDz:12,camberDeg:-2,loadedRadius:320,springRate:130,actuation:"direct"}),config:{wheelbase:2650,trackFront:1660,trackRear:1640,frontAxleX:2650/2},chassis:{boxes:[],body:"cup"}},306.3,311.6)}function bA(){return{...Wa(xo({name:"Stock car",wheelbase:2794,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/ja,kz:355/Ua,lowerInnerDz:20,upperInnerDz:5,camberDeg:-2.5,loadedRadius:355,springRate:175,actuation:"direct"},rear:{kx:1.2,ky:825/Ro,kz:355/vo,lowerInnerDz:40,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:150,actuation:"direct"}}),343.8,345.3),chassis:{boxes:[],body:"nascar"}}}function gA(){let e=Wa(xo({name:"Hill-climb prototype",wheelbase:2550,trackFront:1580,trackRear:1540,front:{kx:1.1,ky:790/ja,kz:300/Ua,lowerInnerDz:10,upperInnerDz:5,camberDeg:-2.5,loadedRadius:300,springRate:90},rear:{kx:1.1,ky:770/Ro,kz:300/vo,lowerInnerDz:30,upperInnerDz:15,camberDeg:-1.5,loadedRadius:300,springRate:120}}),293.3,290.8);return{...e,front:{...e.front,config:{...e.front.config,rackTravel:45}},chassis:{boxes:[],body:"hillclimb"}}}function yA(){let e=Wa(xo({name:"Race truck",wheelbase:3700,trackFront:2050,trackRear:1950,front:{kx:1.5,ky:1025/ja,kz:506/Ua,lowerInnerDz:40,upperInnerDz:10,camberDeg:-.5,loadedRadius:506,springRate:200,actuation:"direct"},rear:{kx:1.5,ky:975/Ro,kz:506/vo,lowerInnerDz:60,upperInnerDz:20,camberDeg:-.25,loadedRadius:506,springRate:160,actuation:"direct"}}),490.4,495.6);return{...e,front:{...e.front,config:{...e.front.config,rackTravel:60}},chassis:{boxes:[],body:"truck"}}}var rt=(e,t,r)=>({value:e,label:t,unit:r}),xA=(e,t)=>({...pr[e],value:t});function RA(e,t,r){let n=[],o=[];for(let a=0;a<=r;a+=500)n.push(a),o.push(a<=t?e:e*t/a);return{rpm:n,torque:o}}function Mo(e,t,r,n,o){let a=[],s=[];for(let i=0;i<=r;i+=500){a.push(i);let c=i<=t?n:Math.min(n,9549*e/i);s.push(c/o)}return{rpm:a,torque:s}}function Qr(e){let t={name:e.name,m:rt(e.m,"vehicle mass (with driver)","kg"),A:rt(e.A,"frontal area","m^2"),c_l:rt(e.cl,"downforce coefficient","-"),c_w:rt(e.cw,"drag coefficient","-"),l_to_d_ratio:rt(e.cw>0?e.cl/e.cw:0,"lift-to-drag ratio","-"),driven_wheels:rt(e.drivenWheels,"driven wheels","-"),fr_0:rt(-.012,"rolling-resistance coefficient","-"),front_aero_diss:rt(e.frontAero,"front aero distribution","-"),front_mass_diss:rt(e.frontMass,"front mass distribution","-"),r_dyn:rt(e.rDyn,"dynamic tyre radius","m"),rho:rt(1.2,"air density","kg/m^3"),gear_ratio:rt(e.gearRatio,"gear ratio","-"),effi_pgb:rt(e.drivetrainEfficiency,"drivetrain efficiency","-"),capacity:rt(e.capacityAh,"pack capacity","Ah"),soc:rt(1,"state of charge","-"),ocv:rt(e.ocv,"pack open-circuit voltage","V"),power_scale:rt(1,"power scaling factor","-"),power_limit_kw:xA("power_limit_kw",e.powerLimitKw),motor:e.motor,tireModelId:e.tireModelId};e.motorCount!==void 0&&(t.motorCount=e.motorCount),e.driveline&&(t.driveline=structuredClone(e.driveline)),e.motorPlacement&&(t.motorPlacement=e.motorPlacement);for(let[r,n]of Object.entries(e.dynamics))t[r]=xA(r,n);return t}var Xa={name:"Formula Student",m:300,A:1,cl:3,cw:1.3,frontMass:.47,frontAero:.45,rDyn:.222,drivenWheels:2,gearRatio:11.5,motor:RA(25,15e3,2e4),capacityAh:12,ocv:550,drivetrainEfficiency:.95,powerLimitKw:80,tireModelId:"t3",dynamics:{grip_scale:1,stiffness_scale:1,endurance_reserve:5,cg_height:300,tire_vertical_rate:110,unsprung_mass:8,brake_balance:.62,arb_front:20,arb_rear:15,damper_front:2.5,damper_rear:2.5,spring_front:35,spring_rear:40,mr_front:.94,mr_rear:.92,cop_long:.55,cop_height:300,ride_height_front:30,ride_height_rear:35,I_yaw:140,I_roll:45,I_pitch:130,camber_front_deg:-1,camber_rear_deg:-1.5,track_front:1200,track_rear:1220,wheelbase:1600,rc_front:5,rc_rear:4}},$g={name:"Formula 1",m:798,A:1.5,cl:3,cw:.9,frontMass:.46,frontAero:.44,rDyn:.35,drivenWheels:2,gearRatio:4.9,motor:Mo(735,2e3,12500,2500,2),motorCount:1,driveline:{rear:vt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t4",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:290,tire_vertical_rate:300,unsprung_mass:30,brake_balance:.58,arb_front:250,arb_rear:150,damper_front:6,damper_rear:6,spring_front:200,spring_rear:220,mr_front:.95,mr_rear:.91,heave_spring_front:800,heave_spring_rear:800,tire_vertical_damping:.5,cop_long:.56,cop_height:400,ride_height_front:35,ride_height_rear:70,I_yaw:800,I_roll:150,I_pitch:800,camber_front_deg:-3,camber_rear_deg:-1.5,track_front:1600,track_rear:1600,wheelbase:3600,rc_front:-4,rc_rear:78}},zm={name:"GT car",m:1300,A:2,cl:1.4,cw:.42,frontMass:.5,frontAero:.42,rDyn:.33,drivenWheels:2,gearRatio:3.43,motor:Mo(410,2e3,8e3,2e3,2),motorCount:1,driveline:{rear:vt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t5",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:450,tire_vertical_rate:280,unsprung_mass:45,brake_balance:.6,arb_front:40,arb_rear:25,damper_front:4.5,damper_rear:4.5,spring_front:110,spring_rear:120,mr_front:.79,mr_rear:.77,cop_long:.58,cop_height:500,ride_height_front:55,ride_height_rear:75,I_yaw:1800,I_roll:450,I_pitch:1800,camber_front_deg:-3.5,camber_rear_deg:-2,track_front:1650,track_rear:1650,wheelbase:2700,rc_front:48,rc_rear:80}},Ym={name:"Sports car",m:1600,A:2.2,cl:-.1,cw:.3,frontMass:.55,frontAero:.5,rDyn:.32,drivenWheels:2,gearRatio:3.14,motor:Mo(220,1500,6500,1400,2),motorCount:1,driveline:{rear:vt.open},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t6",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:520,tire_vertical_rate:220,unsprung_mass:50,brake_balance:.65,arb_front:25,arb_rear:12,damper_front:2.4,damper_rear:2.4,spring_front:55,spring_rear:60,mr_front:.78,mr_rear:.75,cop_long:.5,cop_height:500,ride_height_front:130,ride_height_rear:140,I_yaw:2600,I_roll:550,I_pitch:2500,camber_front_deg:-.5,camber_rear_deg:-1,track_front:1550,track_rear:1550,wheelbase:2750,rc_front:80,rc_rear:122}},Gg={name:"Cup car",m:1265,A:2.1,cl:.45,cw:.4,frontMass:.62,frontAero:.45,rDyn:.31,drivenWheels:2,gearRatio:3.5,motor:Mo(250,2e3,7e3,1190,2),motorCount:1,motorPlacement:"front",driveline:{front:vt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t7",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:480,tire_vertical_rate:280,unsprung_mass:40,brake_balance:.68,arb_front:20,arb_rear:90,damper_front:4,damper_rear:3.5,spring_front:150,spring_rear:130,mr_front:.95,mr_rear:.76,cop_long:.55,cop_height:450,ride_height_front:64,ride_height_rear:78,I_yaw:1700,I_roll:400,I_pitch:1700,camber_front_deg:-3.5,camber_rear_deg:-2,track_front:1660,track_rear:1640,wheelbase:2650,rc_front:60,rc_rear:84}},Kg={name:"Stock car",m:1620,A:2.2,cl:.6,cw:.45,frontMass:.53,frontAero:.45,rDyn:.35,drivenWheels:2,gearRatio:4.1,motor:Mo(500,2500,9e3,1680,2),motorCount:1,driveline:{rear:vt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t8",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:430,tire_vertical_rate:320,unsprung_mass:55,brake_balance:.6,arb_front:60,arb_rear:15,damper_front:7.5,damper_rear:6.75,spring_front:175,spring_rear:150,mr_front:.8,mr_rear:.78,cop_long:.55,cop_height:500,ride_height_front:75,ride_height_rear:90,I_yaw:2500,I_roll:550,I_pitch:2500,camber_front_deg:-2.5,camber_rear_deg:-1.5,track_front:1650,track_rear:1650,wheelbase:2794,rc_front:53,rc_rear:91}},Hg={name:"Hill-climb prototype",m:650,A:1.2,cl:2.5,cw:.9,frontMass:.42,frontAero:.42,rDyn:.29,drivenWheels:2,gearRatio:4,motor:Mo(330,3e3,8500,1240,2),motorCount:1,driveline:{rear:vt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t9",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:280,tire_vertical_rate:200,unsprung_mass:25,brake_balance:.58,arb_front:40,arb_rear:30,damper_front:3,damper_rear:3.5,spring_front:90,spring_rear:120,mr_front:.94,mr_rear:.91,cop_long:.58,cop_height:350,ride_height_front:45,ride_height_rear:55,I_yaw:550,I_roll:120,I_pitch:550,camber_front_deg:-2.5,camber_rear_deg:-1.5,track_front:1580,track_rear:1540,wheelbase:2550,rc_front:27,rc_rear:65}},zg={name:"Race truck",m:5300,A:6.2,cl:-.1,cw:.65,frontMass:.6,frontAero:.6,rDyn:.502,drivenWheels:2,gearRatio:3.55,motor:Mo(880,100,3e3,88e3,2),motorCount:1,driveline:{rear:vt.spool},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t10",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:950,tire_vertical_rate:1e3,unsprung_mass:350,brake_balance:.75,arb_front:350,arb_rear:150,damper_front:12,damper_rear:8.5,spring_front:200,spring_rear:160,mr_front:.81,mr_rear:.8,cop_long:.4,cop_height:1500,ride_height_front:110,ride_height_rear:240,I_yaw:16e3,I_roll:3500,I_pitch:16e3,camber_front_deg:-.5,camber_rear_deg:-.25,track_front:2050,track_rear:1950,wheelbase:3700,rc_front:95,rc_rear:134}};function Bg(e,t,r){return Qr(r({...structuredClone(e),name:t}))}var Wm={[Xa.name]:Qr(Xa),"Formula Student +15% downforce":Bg(Xa,"Formula Student +15% downforce",e=>({...e,cl:e.cl*1.15,cw:e.cw*1.08})),"Formula Student -15 kg":Bg(Xa,"Formula Student -15 kg",e=>({...e,m:e.m-15})),"Formula Student +15% power":Bg(Xa,"Formula Student +15% power",e=>({...e,motor:RA(25*1.15,15e3,2e4),powerLimitKw:80*1.15})),[$g.name]:Qr($g),[zm.name]:Qr(zm),[Ym.name]:Qr(Ym),[Gg.name]:Qr(Gg),[Kg.name]:Qr(Kg),[Hg.name]:Qr(Hg),[zg.name]:Qr(zg)},vA=Object.keys(Wm),Yg=vA.slice(0,4),Wg=[Xa.name,$g.name,zm.name,Ym.name,Gg.name,Kg.name,Hg.name,zg.name];var Kne={"Touring car":zm.name,"Street car":Ym.name};var BN={bg:"#0e1116",panel:"#161b22",panel2:"#1c232d",border:"#2a323d",borderBright:"#39424e",sunken:"#11161c",ink:"#06090d"},$N={normal:"#d6dde6",dim:"#8b96a3",bright:"#e7ecf3",white:"#ffffff"},GN={label:"#c8d2dc",grid:"#39424e",gridFaint:"#232b35",empty:"#1a2028"},KN={accent:"#4aa3ff",accentInk:"#04121f",warn:"#ffb454",good:"#4ec9a0",bad:"#ff6b6b",badSoft:"#ff8f8f"},HN=["#f0e442","#7b68ee","#f7a8b8","#d55e00","#d8b4fe","#b5e48c"],jm={front:"#a6e22e",rear:"#00b4d8"},kA=["#5b4bd6","#4aa3ff","#4ec9a0","#f0e442"],jg={power:"#ffb454",traction:"#f0845c",front:jm.front,rear:jm.rear,grip:"#73c9b3",braking:"#b48aff",crest:"#e88fd0",below:"rgba(214, 221, 230, 0.32)"},zN={chassis:"#4aa3ff",ballJoint:"#ffb454",arm:"#b8c3cf",tie:"#73c9b3",pushrod:"#e5c65f",rocker:"#9f91d4",kingpin:"#d8c968",arbBar:"#cf7898",arbArm:"#b96b86",arbLink:"#ffb454",heaveSpring:"#7ad7f0",wheelCentre:"#e7ecf3",contactPatch:"#ff6b6b",ground:"#15222e",groundFaint:"#0b151f"},YN={x:"#ff6b6b",y:"#57c75a",z:"#4aa3ff"},WN={line:"#b4bfcb"},jN={compression:"#b48aff",tension:"#ff6b6b"},UN={fz:"#e7ecf3",fx:"#7ad7f0",fy:"#ff54c8"},XN={drivenLine:"#4d7cff",axis:"#eef3fa",slip:"#ffe81a",drive:jg.power,brake:jg.braking},qN={ground:"#101920",grid:"#1a2630",gridMajor:"#26343f",horizon:"#1d2833",bridge:"#6f7a86",coneLeft:"#2f63c9",coneRight:"#d9b51f",coneStart:"#ee7a2c"},QN={chassis:"#435160",volume:"#303b47",tyre:"#435160",tyreLine:"#39424e",tyreFace:"#1c232d"},ZN={centreLine:"#4aa3ff",corridorFill:"rgba(74,163,255,0.10)",boundary:"#3d4956",racingLine:"#ffb454",start:"#e7ecf3",finish:"#ff6b6b",direction:"#8b96a3"},JN={SURFACE:BN,TEXT:$N,CHART:GN,ROLE:KN,SERIES:HN,AXLE:jm,LAP_SPEED:kA,LIMITER:jg,RIG:zN,AXIS:YN,CONSTRUCTION:WN,FORCE:jN,TYRE_FORCE:UN,REPLAY:XN,SCENERY:qN,BODY:QN,TRACK:ZN},MA=e=>Object.fromEntries(Object.entries(e).map(([t,r])=>[t,Array.isArray(r)?Object.freeze([...r]):Object.freeze({...r})])),Um=MA(JN),Mt=Um.SERIES,SA=(()=>{let e="#b06400",t="#d1343a",r={front:"#70bf03",rear:"#3392d0"},n={power:e,traction:"#d05a2a",front:r.front,rear:r.rear,grip:"#2a9a83",braking:"#7b55d0",crest:"#c2479f",below:"rgba(34, 39, 45, 0.28)"};return MA({SURFACE:{bg:"#f4f5f3",panel:"#fbfbfa",panel2:"#ffffff",border:"#d6dadd",borderBright:"#b7bec4",sunken:"#eceeeb",ink:"#ffffff"},TEXT:{normal:"#22272d",dim:"#5c6570",bright:"#0f1215",white:"#000000"},CHART:{label:"#3a424b",grid:"#c2c8cd",gridFaint:"#e2e5e7",empty:"#e8eae7"},ROLE:{accent:"#1a64c2",accentInk:"#ffffff",warn:e,good:"#0f8a66",bad:t,badSoft:"#e2696d"},SERIES:["#b5a11a","#2844e3","#f47ec1","#9b3a1b","#764299","#58b977"],AXLE:r,LAP_SPEED:["#4b3bc4","#1a64c2","#0f8a66","#a87e00"],LIMITER:n,RIG:{chassis:"#1a64c2",ballJoint:"#c27200",arm:"#56616d",tie:"#24907b",pushrod:"#a3820f",rocker:"#6656b8",kingpin:"#8f7f10",arbBar:"#b04d77",arbArm:"#9a4767",arbLink:"#c27200",heaveSpring:"#1688ad",wheelCentre:"#15181c",contactPatch:t,ground:"#e2e6e8",groundFaint:"#edf0f1"},AXIS:{x:"#d93a3a",y:"#2f9d34",z:"#1a64c2"},CONSTRUCTION:{line:"#5a6570"},FORCE:{compression:"#7b55d0",tension:t},TYRE_FORCE:{fz:"#15181c",fx:"#0f8fb0",fy:"#c8198f"},REPLAY:{drivenLine:"#2f5be0",axis:"#15181c",slip:"#c79a00",drive:n.power,brake:n.braking},SCENERY:{ground:"#dde3e1",grid:"#ccd3d1",gridMajor:"#b5bfbc",horizon:"#e8edf0",bridge:"#9aa3ab",coneLeft:"#2f63c9",coneRight:"#d9b51f",coneStart:"#ee7a2c"},BODY:{chassis:"#a9b3bd",volume:"#c7ced5",tyre:"#24282c",tyreLine:"#2c333a",tyreFace:"#c3cad0"},TRACK:{centreLine:"#1a64c2",corridorFill:"rgba(26,100,194,0.10)",boundary:"#a3acb4",racingLine:e,start:"#15181c",finish:t,direction:"#5c6570"}})})();var AA=e=>{let t=/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(e.trim());return t?`#${(t[1].length===3?t[1].replace(/./g,n=>n+n):t[1]).toLowerCase()}`:null},zne=(()=>{let e=new Map,t=["SERIES","AXLE","LAP_SPEED","LIMITER","ROLE","RIG","FORCE","TYRE_FORCE","REPLAY","AXIS","TRACK","CONSTRUCTION","TEXT","CHART","SCENERY","BODY","SURFACE"];for(let r of t){let n=Um[r],o=SA[r];for(let a of Object.keys(n)){let s=AA(n[a]);s&&!e.has(s)&&e.set(s,o[a])}}return e})();var FA=(e,t)=>new Set(t.flatMap(r=>{let n=e[r];return Array.isArray(n)?[...n]:Object.values(n)}).map(AA).filter(r=>r!==null)),Yne=FA(SA,["SERIES","AXLE","LAP_SPEED","LIMITER","ROLE","RIG","FORCE","TYRE_FORCE","REPLAY","AXIS","TRACK","CONSTRUCTION"]),Wne=FA(Um,Object.keys(Um).filter(e=>e!=="SURFACE"));function Ug(){return{kind:"simple",name:"Simple motor",rpm:[0,16e3,2e4],torque:[21,21,14],efficiency:.95}}function Xg(){return{kind:"map",name:"Mapped motor",rpm:[0,8e3,16e3,2e4],torque:[24,24,21,16],effRpm:[1e3,5e3,9e3,13e3,17e3,2e4],effTorque:[4,8,12,16,21],effGrid:[[.78,.84,.86,.85,.82,.79],[.83,.9,.93,.92,.89,.86],[.85,.93,.96,.95,.92,.89],[.84,.92,.95,.94,.91,.88],[.82,.89,.92,.9,.87,.84]]}}function qg(){return{kind:"simple",name:"Inboard motor, axial flux (example)",rpm:[0,4e3,4500,5e3,5500,6e3],torque:[230,230,204,184,167,153],efficiency:.95}}function Qg(){return{kind:"ice",name:"600 cc four, restricted (example)",rpm:[3e3,4e3,5e3,6e3,7e3,8e3,9e3,1e4,11e3,12e3,12500],torque:[40,46,52,56,59,61,62,60,56,49,45],idleRpm:3e3,limitRpm:12500,inertia:.012,gearbox:{primary:76/36,ratios:[33/12,32/16,30/18,26/18,30/23,29/24],efficiency:.9,upshiftTime:.1,downshiftTime:.08},breathing:{induction:{kind:"natural"}}}}function Zg(){return{kind:"ice",name:"Formula 1 power unit (example)",rpm:[4e3,5e3,6e3,7e3,8e3,9e3,1e4,10500,11e3,11500,12e3,12500],torque:[896,822,773,738,712,692,675,668,638,610,585,545],idleRpm:4e3,limitRpm:12500,inertia:.02,gearbox:{primary:1,ratios:[4,3.15,2.575,2.175,1.85,1.6,1.375,1.18],efficiency:.94,upshiftTime:0,downshiftTime:0,driveKept:1},breathing:{induction:{kind:"boosted",boostKPa:350,maxPressureRatio:5}}}}function wA(){return{kind:"ice",name:"GT race engine, 4.0 l (example)",rpm:[2500,3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3,7500,8e3],torque:[380,410,440,465,485,500,515,525,530,540,522,480],idleRpm:2500,limitRpm:8e3,inertia:.15,gearbox:{primary:1,ratios:[3,2.15,1.7,1.4,1.17,.98],efficiency:.93,upshiftTime:.05,downshiftTime:.08},breathing:{induction:{kind:"natural"}}}}function CA(){return{kind:"ice",name:"Turbocharged 3.0 l six (example)",rpm:[1e3,1500,1800,2500,3500,4500,5e3,5500,6e3,6500,7e3],torque:[230,340,400,400,400,400,400,382,350,315,280],idleRpm:1e3,limitRpm:7e3,inertia:.2,gearbox:{primary:1,ratios:[3.6,2.19,1.54,1.21,1,.83],efficiency:.92,upshiftTime:.2,downshiftTime:.2,driveKept:.8},breathing:{induction:{kind:"boosted",boostKPa:220,maxPressureRatio:3}}}}function TA(){return{kind:"ice",name:"Turbocharged 2.0 l four (example)",rpm:[2e3,2500,3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3],torque:[330,400,420,420,420,420,415,410,398,365,330],idleRpm:2e3,limitRpm:7e3,inertia:.15,gearbox:{primary:1,ratios:[2.92,2.05,1.61,1.32,1.12,.97],efficiency:.93,upshiftTime:.07,downshiftTime:.08},breathing:{induction:{kind:"boosted",boostKPa:250,maxPressureRatio:3.2}}}}function PA(){return{kind:"ice",name:"Stock car V8, 5.9 l (example)",rpm:[2500,3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3,7500,8e3,8500,9e3],torque:[450,480,510,535,555,570,585,595,600,598,590,578,562,525],idleRpm:2500,limitRpm:9e3,inertia:.18,gearbox:{primary:1,ratios:[2.8,2,1.55,1.24,1],efficiency:.93,upshiftTime:.1,downshiftTime:.1},breathing:{induction:{kind:"natural"}}}}function LA(){return{kind:"ice",name:"Turbocharged 2.0 l four, hill climb (example)",rpm:[3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3,7500,8e3,8500],torque:[314,380,446,462,462,462,458,450,437,420,388,347],idleRpm:3e3,limitRpm:8500,inertia:.1,gearbox:{primary:1,ratios:[2.69,2,1.6,1.33,1.14,1],efficiency:.93,upshiftTime:.05,downshiftTime:.08},breathing:{induction:{kind:"boosted",boostKPa:250,maxPressureRatio:4.5}}}}function DA(){return{kind:"ice",name:"Race truck diesel six, 13 l (example)",rpm:[800,1e3,1200,1400,1600,1800,2e3,2200,2400,2600,2800,3e3],torque:[3e3,4e3,4900,5500,5250,4670,4200,3820,3500,3230,3e3,2700],idleRpm:800,limitRpm:3e3,inertia:1.5,gearbox:{primary:1,ratios:[16,12.44,9.67,7.51,5.84,4.54,3.53,2.74,2.13,1.66,1.29,1],efficiency:.92,upshiftTime:.35,downshiftTime:.35},breathing:{induction:{kind:"boosted",boostKPa:350,maxPressureRatio:4.3}}}}function EA(e){return ho(eO(e))}function eO(e){if(e===null||typeof e!="object"||Array.isArray(e))return e;let t={...e};return delete t.name,Array.isArray(t.vehicles)&&(t.vehicles=t.vehicles.map(r=>{if(r===null||typeof r!="object"||Array.isArray(r))return r;let n={...r};return delete n.name,n})),t}function mc(e,t){return{...t,fingerprint:EA(e)}}var IA="CC-BY-4.0",tO={title:"PaceDynamics built-in library",url:"https://pacedyn.dev/",licence:IA},_A={fidelity:"generic",licence:IA,sources:[tO]};var Xm=e=>mc(e,_A);var NA=["raw.githubusercontent.com"],OA=["tum-csv"],nO=/^[0-9a-f]{64}$/;function dc(e){if(typeof e!="object"||e===null||Array.isArray(e))return!1;let{url:t,sha256:r,format:n}=e;if(typeof t!="string"||t.length>500||typeof r!="string"||!nO.test(r)||!OA.includes(n))return!1;try{let o=new URL(t);return o.protocol==="https:"&&NA.includes(o.hostname)&&!o.username&&!o.password&&!o.port}catch{return!1}}var qm=e=>new URL(e.url).hostname;async function VA(e){let t=await globalThis.crypto.subtle.digest("SHA-256",e);return[...new Uint8Array(t)].map(r=>r.toString(16).padStart(2,"0")).join("")}function oO(e){let t=new URL(e).pathname.split("/").pop()??"";return decodeURIComponent(t).replace(/\.[^.]*$/,"")||"Linked track"}function aO(e,t){let r=[],n=[],o=[],a=[];for(let[s,i]of e.split(/\r?\n/).entries()){let c=i.trim();if(!c||c.startsWith("#"))continue;let l=c.split(",").map(u=>Number(u.trim()));if(l.length!==4||!l.every(Number.isFinite))throw new Error(`Line ${s+1} of ${t} is not four numbers.`);r.push(l[0]),n.push(l[1]),o.push(l[2]),a.push(l[3])}if(r.length<3)throw new Error(`${t} has ${r.length} points; a track needs at least 3.`);return{name:t,x:r,y:n,widthLeft:a,widthRight:o,closed:!0,fit:"interpolate"}}var sO={"tum-csv":aO};function BA(e,t){return sO[t.format](e,oO(t.url))}async function Jg(e,t,r){let n=await VA(e);if(n!==t.sha256)throw new Error(`${qm(t)} did not return the file that was reviewed (its SHA-256 is ${n.slice(0,12)}\u2026, not ${t.sha256.slice(0,12)}\u2026).`);let o=BA(new TextDecoder().decode(e),t),a=await Qm(o);if(a!==r)throw new Error(`Linked track ${r} does not convert to its name (it is ${a}).`);return o}var e0=20,cO=new RegExp(`^[0-9a-f]{${e0}}$`),fc=e=>typeof e=="string"&&cO.test(e);async function Qm(e){let t=new TextEncoder().encode(Fn(e)),r=await globalThis.crypto.subtle.digest("SHA-256",t);return[...new Uint8Array(r)].map(n=>n.toString(16).padStart(2,"0")).join("").slice(0,e0)}var t0=e=>`tracks/${e}.json`;var lO=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function r0(e){return{model:{name:e.name,source:e.source},...e.provenance?{provenance:e.provenance}:{}}}async function n0(e,t){if(!lO(e)||typeof e.name!="string"||!Array.isArray(e.x)||!Array.isArray(e.y)||e.x.length!==e.y.length||e.x.length<2)throw new Error(`Catalogue track ${t} is not a track.`);let r=await Qm(e);if(r!==t)throw new Error(`Catalogue track ${t} does not match its name (it is ${r}).`);return e}var So=(e,t,r,n=[])=>({doc:e,ref:t,refs:[t,...n.map(o=>o.ref)],slots:[{key:e,ref:t,label:r},...n],label:r}),wn=[So("suspensions","suspensionId","suspension"),So("tires","tireModelId","tyre",[{key:"tiresRear",ref:"tireModelIdRear",label:"rear tyre"}]),So("motors","motorModelId","motor"),So("aeros","aeroModelId","aero map"),So("batteries","batteryModelId","battery"),So("brakes","brakeModelId","brakes"),So("dampers","damperModelId","dampers",[{key:"dampersRear",ref:"damperModelIdRear",label:"rear dampers"},{key:"dampersHeave",ref:"heaveDamperModelId",label:"heave dampers"},{key:"dampersRoll",ref:"rollDamperModelId",label:"roll dampers"}])];function Zm(e){let t={...e};for(let r of wn)for(let n of r.refs)delete t[n];return t}var Jm=Mt,hc=Jm,o0=Jm,Cn=[...Mt.slice(3),...Mt.slice(0,3)],i0=[...Mt.slice(1),Mt[0]],a0=[...Mt.slice(2),...Mt.slice(0,2)],s0=[...Mt.slice(4),...Mt.slice(0,4)],c0=[...Mt.slice(5),...Mt.slice(0,5)],bc=[...Mt.slice(2),...Mt.slice(0,2)];function l0(){let e=globalThis.crypto;return e&&typeof e.randomUUID=="function"?e.randomUUID():`p-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}function u0(e,t,r){let n=Wm[e];if(!n)throw new Error(`no preset vehicle named "${e}"`);return{id:t,params:{...gi(structuredClone(n)),energy:{...Or},suspensionId:"sus1"},visible:!0,color:hc[r%hc.length]}}function pO(){return Yg.map((e,t)=>u0(e,`v${t+1}`,t))}function dO(){return[Us(),jf(),Uf(),Xf(),qf(),Qf(),Zf(),Jf(),eh(),th()].map((t,r)=>({id:`t${r+1}`,color:o0[r%o0.length],model:t}))}function fO(){return[wd(),Cd(),Td(),Pd(),Ld(),Dd(),Ed(),Id()].map((t,r)=>({id:`a${r+1}`,color:a0[r%a0.length],model:t}))}function hO(){return[pd(),dd(),fd()].map((t,r)=>({id:`b${r+1}`,color:s0[r%s0.length],model:t}))}function bO(){return[{id:"brk1",color:c0[0],model:structuredClone(Rh)}]}function gO(){return[{id:"dmp1",color:bc[0],model:structuredClone(Tu)}]}function yO(){return[Ug(),Xg()].map((t,r)=>({id:`m${r+1}`,color:Cn[r%Cn.length],model:t}))}function m0(e){let t=r=>({...r,provenance:Xm(r.model)});return{...e,suspensions:e.suspensions.map(t),vehicles:e.vehicles.map(r=>({...r,provenance:Xm(Zm(r.params))})),tires:e.tires.map(t),motors:e.motors.map(t),aeros:e.aeros.map(t),batteries:e.batteries.map(t),brakes:e.brakes.map(t),dampers:e.dampers.map(t)}}function gc(e="Untitled project"){let t=new Date().toISOString(),r=pO();return m0({schemaVersion:Vm,meta:{id:l0(),name:e,domain:"racecar",rulesetId:bo,createdAt:t,updatedAt:t},suspensions:[{id:"sus1",color:i0[0],model:ko()}],activeSuspensionId:"sus1",vehicles:r,activeVehicleId:r[0]?.id??null,tires:dO(),motors:yO(),aeros:fO(),batteries:hO(),brakes:bO(),dampers:gO(),tracks:[],activeTrackId:null,mathChannels:[],rulesets:[],studies:[],activeStudyId:null,loadCases:[],reportLayouts:[],tyreSheets:[],kinSheets:[],plans:[],results:[],settings:{numerics:{...Ei},ggvMode:"twoTrack",quasiTransient:!1,motorThermal:!1,brakeFade:!1,airTempC:Tt,air:structuredClone($m),diffYaw:!1,lapCounts:{},pathPlanId:null,useRacingLine:!0,standingStart:!1}})}var xO=["front","rear"],p0=9.81,RO=Math.PI/180;var Rr="*",d0=40,$A=.8;function f0(e){let{s:t,curvature:r}=e;if(!t?.length||t.length!==r?.length)return null;let n=0,o=0,a=0,s=0;for(let i=0;i<t.length;i++){for(;a<t.length&&t[a]<=t[i]+2.5;)s+=Math.abs(r[a++]);for(;t[o]<t[i]-2.5;)s-=Math.abs(r[o++]);let c=s/Math.max(1,a-o);c>n&&(n=c)}return n>1e-6?1/n:null}function GA(e,t,r){let n=t.rows.map(c=>c.v),o=c=>dt(n,t.rows.map(l=>l.ayMax),Math.min(n[n.length-1],Math.max(n[0],c))),a=(c,l,u)=>({speedKmh:Math.round(c*36)/10,ayG:Math.round(l/p0*100)/100+0,axG:Math.round(u/p0*100)/100+0}),s=t.vMax,i=Array.from({length:41},(c,l)=>20/3.6+l*Math.max(0,s-20/3.6)/40);switch(e){case"slowCorner":{if(r===null)return a(d0/3.6,o(d0/3.6),0);let c=10;for(let l=0;l<30;l++)c=Math.min(s,Math.sqrt(r*o(c)));return a(c,o(c),0)}case"fastCorner":return a($A*s,o($A*s),0);case"braking":{let c=i.reduce((l,u)=>t.axDecel(u,0)<t.axDecel(l,0)?u:l);return a(c,0,t.axDecel(c,0))}case"traction":{let c=i.reduce((l,u)=>t.axAccel(u,0)>t.axAccel(l,0)?u:l);return a(c,0,t.axAccel(c,0))}case"topSpeed":return a(s,0,0)}}function h0(e,t,r){let n=!1,o=e.map(a=>{if(!a.follows)return a;let s=GA(a.follows,t,r);return![s.speedKmh,s.ayG,s.axG].every(Number.isFinite)||!t.rows.some(i=>i.ayMax>0)||s.speedKmh===a.speedKmh&&s.ayG===a.ayG&&s.axG===a.axG?a:(n=!0,{...a,...s})});return n?o:e}function b0(e,t){let r=e.speedKmh/3.6,n=e.ayG*p0;if(!(Math.abs(n)>1e-6)||!(r>.1))return 0;let o=r*r/Math.abs(n);return Math.sign(n)*Math.atan(t/1e3/o)/RO}var KA=e=>e.ayG<0?"L":"R";function g0(e,t=xO){if(!e.length||!t.length)return null;let r=t.flatMap(i=>i==="front"?["FL","FR"]:["RL","RR"]),n=0,o=0,a=0;for(let i of e){for(let c of r){let l=i.corners[c].travel;if(!Number.isFinite(l))return null;n=Math.min(n,l),o=Math.max(o,l)}a=Math.max(a,Math.abs(i.rollDeg))}let s=5;return{travelMin:Math.min(-1,Math.floor(n-s)),travelMax:Math.max(1,Math.ceil(o+s)),rollMaxDeg:Math.max(.5,Math.ceil((a+.5)*10)/10),rollAtLimitDeg:Math.ceil(a*10)/10}}var y0=(e,t)=>e.travelMin===t.travelMin&&e.travelMax===t.travelMax&&e.rollMaxDeg===t.rollMaxDeg&&e.rollAtLimitDeg===t.rollAtLimitDeg;var Zr=Math.PI/180,vO=9.81,yc=.1,x0=20,HA=6,jA=50;function zA(e,t,r){let n=e(0),o=0;for(let d=t;d<=r+1e-9;d+=t){let p=e(d);if(p>n)n=p,o=d;else if(d>o+3*t)break}let a=Math.max(0,o-t),s=Math.min(r,o+t),i=.6180339887498949,c=s-i*(s-a),l=a+i*(s-a),u=e(c),m=e(l);for(let d=0;d<14;d++)u>m?(s=l,l=c,m=u,c=s-i*(s-a),u=e(c)):(a=c,c=l,u=m,l=a+i*(s-a),m=e(l));return u>n?u>=m?{force:u,at:c}:{force:m,at:l}:m>n?{force:m,at:l}:{force:n,at:o}}function R0(e,t,r,n,o){let a=o*Zr;if(t==="side")return zA(i=>r*e.Fy(r*i*Zr,n,a),1,45);let s=t==="drive"?1:-1;return zA(i=>s*e.Fx(s*i,n,a),.02,.6)}function tp(e){let t=e?Ul(e)?.gamma:void 0,r=[t?.min,t?.max].filter(o=>o!==void 0&&Number.isFinite(o));if(!r.length)return{lo:-HA,hi:HA,stated:!1};let n=Math.max(...r.map(Math.abs))/Zr;return{lo:-n,hi:n,stated:!0}}function kO(e,t,r){if(!(r>t))return t;let n=Math.max(2,Math.ceil(r-t)+1),o=(r-t)/(n-1),a=t,s=-1/0;for(let h=0;h<n;h++){let b=t+h*o,g=e(b);g>s&&(s=g,a=b)}let i=Math.max(t,a-o),c=Math.min(r,a+o),l=.6180339887498949,u=c-l*(c-i),m=i+l*(c-i),d=e(u),p=e(m);for(let h=0;h<12;h++)d>p?(c=m,m=u,p=d,u=c-l*(c-i),d=e(u)):(i=u,u=m,d=p,m=i+l*(c-i),p=e(m));let f=d>=p?{g:u,v:d}:{g:m,v:p};return f.v>s?f.g:a}var YA=250,WA=new WeakMap;function MO(e,t,r,n,o,a,s){let i=WA.get(e);i||WA.set(e,i=new Map);let c=`${t}|${n}|${o}|${s.lo}|${s.hi}`,l=i.get(c);l||i.set(c,l=new Map);let u=f=>{let h=l.get(f);if(h===void 0){let b=Math.max(50,f*YA);h=kO(g=>R0(r,n,o,b,g).force,s.lo,s.hi),l.set(f,h)}return h},m=Math.max(0,a)/YA,d=Math.floor(m),p=m-d;return p<1e-9?u(d):u(d)*(1-p)+u(d+1)*p}function qa(e,t){return t==="front"?e.tireModel:e.tireModelRear??e.tireModel}var SO=new WeakMap,AO=new WeakMap,FO=new WeakMap,v0=(e,t,r)=>{let n=e.get(t);return n===void 0&&e.set(t,n=r()),n};function rp(e,t){let r=qa(e,t);return r?v0(SO,r,()=>Gs(r))?null:"This tyre\u2019s side force does not change with camber, so it wants no camber.":"The car runs the built-in simple tyre, which has no camber term."}function k0(e,t){let r=qa(e,t);return r?v0(FO,r,()=>Xl(r).none)?"This tyre file has no drive or brake grip.":v0(AO,r,()=>{let n=Pe(r),o=r.kind==="magic"?r.fnomin:r.nominalLoad,a=n.Fx(.1,o,0),s=n.Fx(.1,o,3*Zr);return Number.isFinite(a)&&Number.isFinite(s)&&Math.abs(s-a)>1})?null:"This tyre\u2019s drive and brake grip does not change with camber.":"The car runs the built-in simple tyre, which has no camber term."}function Ao(e,t){return e==="side"||e==="ackermann"?Math.abs(t.ayG)>=yc?e==="ackermann"&&!(UA(t)<=x0)?`is a corner wider than ${x0} m`:null:"does not corner":(e==="drive"?t.axG:-t.axG)>=yc?null:e==="drive"?"does not drive":"does not brake"}var wO=e=>e.axG>=yc?"drive":e.axG<=-yc?"brake":null;function UA(e){let t=e.speedKmh/3.6,r=Math.abs(e.ayG)*vO;return r>1e-9?t*t/r:1/0}var ep=(e,t)=>`${e==="front"?"F":"R"}${t}`,CO=e=>e==="L"?"R":"L",TO=(e,t,r)=>Math.min(r,Math.max(t,e));function M0({ev:e,params:t,input:r,state:n,pose:o}){let a=`${Q(t,"grip_scale")}|${Q(t,"stiffness_scale")}`,s=UA(n),i=r.wheelbase*(1-r.frontMassFrac)/1e3,c=r.wheelbase*r.frontMassFrac/1e3,l=r.wheelbase/1e3,u=k=>(k==="front"?r.trackFront:r.trackRear)/2e3,m=(k,v,x,M,A)=>{let w=ye(e,k),C=qa(t,k),T=Math.max(0,o.loads[v]),F=o.camber[v],S=TO(F,A.lo,A.hi),P=R0(w,x,M,T,S),L=T<jA,D=C&&!L?MO(C,a,w,x,M,T,A):S,I=L?P.force:R0(w,x,M,T,D).force,O=.05;return{corner:v,Fz:T,lifted:L,camber:F,read:S,outside:S!==F,wants:D,atEdge:!L&&(D-A.lo<O||A.hi-D<O),peak:P.force,slip:P.at,best:I}},d=(k,v,x)=>{let M=v[0].best+v[1].best,A=v[0].peak+v[1].peak;return{kind:k,wheels:v,lossCamber:M>0?Math.max(0,1-A/M):NaN,range:x}},p=new Map,f=k=>{if(p.has(k))return p.get(k)??null;let v=null;if(!Ao("side",n)){let x=tp(qa(t,k));v=[m(k,ep(k,o.outer),"side",1,x),m(k,ep(k,CO(o.outer)),"side",-1,x)]}return p.set(k,v),v},h=new Map,b=new Map,g=new Map,y=(k,v,x)=>{let M=k==="front"?i:-c,A=(v?1:-1)*u(k),w=x*Zr;return Math.atan2(M+s*Math.sin(w),s*Math.cos(w)-A)/Zr},R=k=>(n.ayG<0?-1:1)*o.steer[k];return{side(k){if(h.has(k))return h.get(k)??null;let v=rp(t,k)?null:f(k),x=v?d("side",v,tp(qa(t,k))):null;return h.set(k,x),x},long(k){if(b.has(k))return b.get(k)??null;let v=wO(n),x=null;if(v&&!k0(t,k)){let M=tp(qa(t,k));x=d(v,[m(k,ep(k,"L"),v,1,M),m(k,ep(k,"R"),v,1,M)],M)}return b.set(k,x),x},toeLoss(k){let v=g.get(k);if(v!==void 0)return v;let x=f(k),M=NaN;if(x&&x[0].peak+x[1].peak>0){let A=ye(e,k),[w,C]=x,T=[{g:w,dt:1,inner:!1,steer:R(w.corner)},{g:C,dt:-1,inner:!0,steer:R(C.corner)}],F=I=>T.reduce((O,_)=>{let z=_.steer-y(k,_.inner,I);return O+_.dt*A.Fy(_.dt*z*Zr,_.g.Fz,_.g.read*Zr)},0),S=T.map(I=>I.steer-I.g.slip-y(k,I.inner,0)),P=Math.min(...S)-2,L=Math.max(...S)+2,D=PO(F,P,L,.25);M=Math.max(0,1-D/(w.peak+C.peak))}return g.set(k,M),M},ackermann(){if(Ao("ackermann",n))return NaN;let k=f("front");if(!k||k[0].lifted||k[1].lifted)return NaN;let[v,x]=k,M=Math.sqrt(Math.max(s*s-c*c,1e-6)),A=u("front"),w=(Math.atan(l/(M-A))-Math.atan(l/(M+A)))/Zr;if(!(w>.001))return NaN;let C=R(x.corner)-R(v.corner),T=w+(x.slip-v.slip);return 100*(C-T)/w}}}function PO(e,t,r,n){let o=-1/0,a=t;for(let p=t;p<=r+1e-9;p+=n){let f=e(p);f>o&&(o=f,a=p)}let s=a-n,i=a+n,c=.6180339887498949,l=i-c*(i-s),u=s+c*(i-s),m=e(l),d=e(u);for(let p=0;p<14;p++)m>d?(i=u,u=l,d=m,l=i-c*(i-s),m=e(l)):(s=l,l=u,m=d,u=s+c*(i-s),d=e(u));return Math.max(o,m,d)}var LO=9.81,XA=Math.PI/180,xc={speed:20,ayG:1.2};function S0(e,t={}){let r=t.operating??xc,n=t.assemble,o,a,s,i=new Map,c=new Map,l=new Map,u=new Map,m=new Map,d=v=>({speed:v?.speed!==void 0&&Number.isFinite(v.speed)&&v.speed>0?v.speed:r.speed,ayG:v?.ayG!==void 0&&Number.isFinite(v.ayG)?v.ayG:r.ayG}),p=()=>{if(o!==void 0)return o;if(!n)return o=null;try{o=n(e)}catch{o=null}return o},f=()=>{if(a!==void 0)return a;try{a=hr(e.params)}catch{a=null}return a},h=v=>{let x=d(v),M=`${x.speed}|${x.ayG}`,A=i.get(M);if(A!==void 0)return A;let w=f();if(!w)return i.set(M,null),null;let C={cornerStiffness:T=>w.corneringStiffness(T),ayG:x.ayG,speed:x.speed,fyAxle:(T,F)=>2*w.Fy(T,F/2),tire:w};return i.set(M,C),C},b=()=>{if(s!==void 0)return s;let v=p(),x=f();if(!v||!x)return s=null;try{s=Jn(x,v.massTotal*LO*1.2)}catch{s=null}return s},g=v=>{let x=d(v).speed,M=`${x}`,A=c.get(M);if(A!==void 0)return A;let w=p(),C=f(),T=null;if(w&&C)try{T=bb(w,C,x,{steering:!1})}catch{T=null}return c.set(M,T),T},y=v=>{let x=`${v.speedKmh}|${v.ayG}|${v.axG}`,M=m.get(x);if(M!==void 0)return M;let A=null,w=p();try{let C=w?.kinFront,T=w?.kinRear;if(w&&C&&T){let F=b0(v,w.wheelbase),S=v.speedKmh/3.6,P=fn(w,C,T,S)(v.ayG,v.axG,0,F),L={FL:P.FL.travel,FR:P.FR.travel},D=to(w,F*XA,L),I=F?D.camber:null,O={},_={};for(let E of["FL","FR","RL","RR"]){let N=E[1]==="R"?P[E].camberRoad:0-P[E].camberRoad;O[E]=N+(I?.[E]??0),_[E]=D.steer[E]/XA+(E[1]==="R"?1:-1)*P[E].bumpToe}let z=Ce(w,v.ayG,v.axG,S,0,F,L,P.steeringJacking);A={corners:P,rollDeg:P.FL.camberRoad-P.FL.camber,steerDeg:F,camber:O,outer:KA(v),loads:z,steer:_}}}catch{A=null}return m.set(x,A),A},R=new Map;return{operating:r,dynAvailable:!!n,poseAt:y,tyreAt:v=>{let x=`${v.speedKmh}|${v.ayG}|${v.axG}`,M=R.get(x);if(M!==void 0)return M;let A=y(v),w=p(),C=f(),T=A&&w&&C?M0({ev:C,params:e.params,input:w,state:v,pose:A}):null;return R.set(x,T),T},operatingAt:d,dynInput:p,tyre:f,dynCtx:h,grip:b,ymd:g,ymdLimit:v=>{let x=`${d(v).speed}`,M=l.get(x);if(M!==void 0)return M;let A=g(v),w=A?jb(A):null;return l.set(x,w),w},reserves:(v,x)=>{let M=d(x),A=`${v}|${M.speed}|${M.ayG}`,w=u.get(A);if(w!==void 0)return w;let C=p(),T=h(x),F=null;if(C&&T)try{F=Bi(C,T,v,b()??void 0)}catch{F=null}return u.set(A,F),F}}}var qA=["widthLeft","widthRight","bank","mu"];function Rc(e){let t=e.x.length,r=new Array(t).fill(0);for(let n=1;n<t;n++)r[n]=r[n-1]+Math.hypot(e.x[n]-e.x[n-1],e.y[n]-e.y[n-1]);return r}function A0(e){let t=Rc(e),r=e.x.length;return r===0?0:e.closed===!1||r<2?t[r-1]:t[r-1]+Math.hypot(e.x[0]-e.x[r-1],e.y[0]-e.y[r-1])}function op(e,t,r,n={}){let o=t.length,a=l=>{let u=n[l];return u&&u.length===o?u.slice():new Array(o).fill(r[l])},s={widthLeft:a("widthLeft"),widthRight:a("widthRight"),bank:a("bank"),mu:a("mu")};if(!e.length)return s;let i=[...e].sort((l,u)=>l.from-u.from),c=o?t[o-1]:0;for(let l of i){if(!(l.to>l.from))continue;let u=Math.max(0,l.ramp??0),m=l.to>=c-1e-9;for(let d of qA){let p=l[d];if(p===void 0)continue;let f=s[d],h=r[d];for(let b=0;b<o&&t[b]<l.from;b++)h=f[b];for(let b=0;b<o;b++){let g=t[b];if(g<l.from||g>=l.to&&!(m&&g>=c-1e-9))continue;let y=g-l.from;f[b]=u>0&&y<u?h+(p-h)*(y/u):p}}}return s}function ap(e,t,r){if(!t.length)return e;let n=Rc(e),o=n.length,a={widthLeft:np(e.widthLeft,r.widthLeft),widthRight:np(e.widthRight,r.widthRight),bank:np(e.bank,r.bank),mu:np(e.mu,r.mu)},s={};for(let c of qA){let l=e[c];Array.isArray(l)&&l.length===o&&(s[c]=l)}let i=op(t,n,a,s);return{...e,...i}}function np(e,t){return typeof e=="number"?e:t}var JA=1,QA=4,ip=Math.PI/180,F0=e=>e===null||!Number.isFinite(e)||e===0?0:1/e;function w0(e){return e.kind==="arc"?Math.abs(e.radius)*Math.abs(e.angle)*ip:e.length}function sp(e,t){return e.kind==="straight"?0:e.kind==="arc"?F0(e.radius):t}function ZA(e){return e.kind==="straight"?0:e.kind==="arc"?F0(e.radius):F0(e.endRadius)}var vc=(e,t,r,n,o)=>e+t*o+(n>0?(r-t)*o*o/(2*n):0);function kc(e,t={}){let r=Math.max(.05,t.spacing??JA),n=t.closed!==!1,o=t.start??{x:0,y:0,heading:0},a=t.base??{widthLeft:1.5,widthRight:1.5,bank:0,mu:1},s=[],i=[],c=[],l=[],u=e.reduce((F,S)=>F+w0(S),0),m=Math.max(n?3:2,Math.round(u/r)),d=u>0?u/m:r,p=o.x,f=o.y,h=o.heading*ip,b=e.length?sp(e[0],0):0,g=0,y=d,R=(F,S,P)=>{s.push(F),i.push(S),c.push(P)};R(p,f,0);let k=(F,S,P,L,D)=>{let I=D-L;if(I<=0)return;if(Math.abs(S-F)<1e-12){let _=vc(h,F,F,P,L);if(Math.abs(F)<1e-12)p+=I*Math.cos(_),f+=I*Math.sin(_);else{let z=_+F*I;p+=(Math.sin(z)-Math.sin(_))/F,f+=-(Math.cos(z)-Math.cos(_))/F}return}let O=I/QA;for(let _=0;_<QA;_++){let z=L+_*O,E=vc(h,F,S,P,z),N=vc(h,F,S,P,z+O/2),B=vc(h,F,S,P,z+O);p+=O/6*(Math.cos(E)+4*Math.cos(N)+Math.cos(B)),f+=O/6*(Math.sin(E)+4*Math.sin(N)+Math.sin(B))}};for(let F of e){let S=w0(F),P=sp(F,b),L=ZA(F);if(l.push({from:g,to:g+S,...F.widthLeft!==void 0?{widthLeft:F.widthLeft}:{},...F.widthRight!==void 0?{widthRight:F.widthRight}:{},...F.bank!==void 0?{bank:F.bank}:{},...F.mu!==void 0?{mu:F.mu}:{},...F.ramp!==void 0?{ramp:F.ramp}:{}}),S<=0){b=L;continue}let D=0;for(;y<=g+S+1e-9;){let I=Math.min(S,y-g);k(P,L,S,D,I),D=I,R(p,f,g+I),y+=d}k(P,L,S,D,S),h=vc(h,P,L,S,S),b=L,g+=S}let v=s.length>1?Math.hypot(s[0]-s[s.length-1],i[0]-i[i.length-1]):0,x=g;n&&s.length>1&&(s.pop(),i.pop(),c.pop());let M=e.length?sp(e[0],b):0,A={gap:v,headingError:DO((h-o.heading*ip)/ip),curvatureError:b-M},w=[];for(let F=0;F<e.length;F++){let S=ZA(e[F]),P=F+1<e.length?e[F+1]:n?e[0]:null;if(!P)continue;let L=sp(P,S);w.push({index:F,before:S,after:L,jump:Math.abs(L-S)})}let C=op(l,c,a);return{asset:{name:t.name??"Track",x:s,y:i,fit:"interpolate",...n?{}:{closed:!1},...C},sections:l,joints:w,closure:A,length:x}}function DO(e){let t=e%360;return t>180&&(t-=360),t<-180&&(t+=360),t}var EO={halfWidthM:1.5,spacingM:.5};function Mc(e){switch(e.kind){case"skidpad":return`${e.radiusM.toFixed(2)} m constant-radius circle`;case"acceleration":return`${e.distanceM.toFixed(0)} m straight from rest`;case"slalom":return`${e.gates} gates at ${e.pitchM.toFixed(1)} m, \xB1${e.offsetM.toFixed(2)} m`;case"curves":{let t=e.segments.filter(r=>r.kind==="arc").length;return`${t} ${t===1?"curve":"curves"} over ${tF(e).toFixed(0)} m`}}}function tF(e){switch(e.kind){case"skidpad":return 2*Math.PI*e.radiusM;case"acceleration":return e.distanceM;case"slalom":return e.leadInM+Math.max(1,e.gates)*e.pitchM;case"curves":return e.segments.reduce((t,r)=>t+(r.kind==="arc"?Math.abs(r.angle)*Math.PI*Math.abs(r.radius)/180:r.length),0)}}var rF=e=>e.kind==="skidpad"||e.kind==="curves"&&e.closed===!0,nF=e=>e.kind==="acceleration",oF=1.5,aF=3;function IO(e,t){let r=e.offsetM,n=e.pitchM,o=Math.max(1,e.gates)*n,a=Math.max(0,e.leadInM),s=oF*n,i=h=>{let b=Math.min(1,Math.max(0,h));return b*b*b*(b*(b*6-15)+10)},c=h=>Math.min(i(h/s),i((o-h)/s)),l=r*(Math.PI/n)**2,u=l>0?Math.max(.05,Math.min(t.spacingM,1/l*(aF*Math.PI/180))):t.spacingM,m=[],d=[],p=Math.max(1,Math.round(a/u));for(let h=0;h<p;h++)m.push(-a+a*h/p),d.push(0);let f=Math.max(8,Math.round(o/u));for(let h=0;h<=f;h++){let b=o*h/f;m.push(b),d.push(r*c(b)*Math.sin(Math.PI*b/n))}return{name:Mc(e),x:m,y:d,closed:!1,widthLeft:t.halfWidthM,widthRight:t.halfWidthM,fit:"interpolate"}}function _O(e){switch(e.kind){case"skidpad":return[{kind:"arc",radius:e.radiusM,angle:360}];case"acceleration":return[{kind:"straight",length:e.distanceM}];case"curves":return e.segments;case"slalom":return null}}function C0(e,t={}){let r={...EO,...t},n=nF(e),o=_O(e);if(!o){let u=IO(e,r);return{asset:u,peakCurvature:eF(u),worstJoint:0,standingStart:n}}let a=rF(e),s=o.reduce((u,m)=>m.kind==="arc"?Math.min(u,Math.abs(m.radius)):u,1/0),i=Number.isFinite(s)?Math.max(.05,Math.min(r.spacingM,s*(aF*Math.PI/180))):r.spacingM,c=kc(o,{name:Mc(e),spacing:i,closed:a,base:{widthLeft:r.halfWidthM,widthRight:r.halfWidthM,bank:0,mu:1}}),l=a?c.joints:c.joints.filter(u=>u.index<o.length-1);return{asset:c.asset,peakCurvature:eF(c.asset),worstJoint:l.reduce((u,m)=>Math.max(u,m.jump),0),standingStart:n}}function eF(e){try{return Math.max(...ct(e).curvature.map(Math.abs))}catch{return NaN}}var lp={courses:[{id:"c1",course:{kind:"manoeuvre",spec:{kind:"skidpad",radiusM:8.375}}}],ggvMode:"twoTrack"};function T0(e){return e.course.kind==="project"?"the project\u2019s track":e.course.kind==="track"?e.course.name:Mc(e.course.spec)}var sF=new WeakMap,cp=new Map;function iF(e,t,r){if(e.kind==="project"||e.kind==="track"){let i=(e.kind==="project"?t.projectTrack?.():t.libraryTrack?.(e.trackId))??null;return i?{asset:i.asset,standingStart:i.standingStart,numerics:i.numerics}:null}let n=JSON.stringify(e.spec),o=cp.get(n);if(o)return{...o,numerics:r};let a=C0(e.spec),s={asset:a.asset,standingStart:a.standingStart};return cp.size>64&&cp.clear(),cp.set(n,s),{...s,numerics:r}}function P0(e,t,r={}){let n=r.lap??lp,o=r.simParams,a=r.numerics??{},s=n.courses.length?n.courses:lp.courses,i,c,l,u=new Map,m=new Map,d=new Map,p=new Map,f=k=>(k?.courseId?s.find(v=>v.id===k.courseId):void 0)??s[0],h=()=>{if(i!==void 0)return i;if(!o)return i=null;try{i={...o(e),ggvMode:n.ggvMode}}catch{i=null}return i},b=k=>{let v=f(k);if(!v)return null;let x=m.get(v.id);if(x!==void 0)return x;let M=iF(v.course,r,a),A=null;if(M)try{let w=JSON.stringify(M.numerics),C=sF.get(M.asset);C||(C=new Map,sF.set(M.asset,C));let T=C.get(w);T||(T=ct(M.asset,M.numerics),C.set(w,T)),A={id:v.id,track:T,standingStart:M.standingStart,numerics:M.numerics,name:M.asset.name}}catch{A=null}return m.set(v.id,A),A},g=()=>{if(c!==void 0)return c;let k=h();if(!k)return c=null;try{l=Pt(k),c=br(l,!1,n.ggvMode)}catch{c=null}return c},y=k=>{let v=b(k);if(!v)return null;let x=d.get(v.id);if(x!==void 0)return x;let M=g(),A=null;if(M)try{let w=l?mo(l,M,[v.track],v.numerics,n.ggvMode,u):void 0,C=l?Sn(l,M.rows):void 0;A=kt(M,v.track,v.numerics,{standingStart:v.standingStart,...w?{load:w}:{},...C?{shifts:C}:{}})}catch{A=null}return d.set(v.id,A),A};return{lapSettings:n,get lapAvailable(){return!!o&&s.some(k=>!!iF(k.course,r,a))},lapParams:h,courses:()=>s,course:b,ggv:g,lap:y,lapReserve:k=>{let v=b(k);if(!v)return null;let x=p.get(v.id);if(x!==void 0)return x;let M=y(k),A=t.dynInput(),w=t.tyre(),C=null;if(M&&A&&w)try{let T=h();C=fm(A,w,{v:M.v,ax:M.ax,ay:M.ay,ds:v.track.ds,axDrag:Ga(g()?.rows,M.v),...M.axScrub?{axScrub:M.axScrub}:{},axGrade:Mn(v.track.gradient,M.v.length),bank:v.track.bank,...M.loadFactor?{loadFactor:M.loadFactor}:{}},T?{driven:_h(T)}:{})}catch{C=null}return p.set(v.id,C),C}}}var cF=180/Math.PI,L0={rise:0,sinPitch:0,sinRoll:0};function lF(e){let t=e.kc;return t?uF(e.vehicle,r=>t.ground0[r]):L0}function uF(e,t){let r=e.config,n=ln(r),o=0,a=0,s=0,i=0,c=0,l=0,u=0,m=0,d=0;for(let g of ar){let y=Qe(g,r),R=y.axleX-n,k=y.sideSign*Bt(e,y.isFront)/2,v=t(g);if(!Number.isFinite(v))return L0;o++,a+=R,s+=k,i+=v,c+=R*R,l+=k*k,u+=R*k,m+=R*v,d+=k*v}let p=o*(c*l-u*u)-a*(a*l-u*s)+s*(a*u-c*s);if(!(Math.abs(p)>1e-9))return{rise:i/o,sinPitch:0,sinRoll:0};let f=(i*(c*l-u*u)-a*(m*l-u*d)+s*(m*u-c*d))/p,h=(o*(m*l-u*d)-i*(a*l-u*s)+s*(a*d-m*s))/p,b=(o*(c*d-m*u)-a*(a*d-m*s)+i*(a*u-c*s))/p;return{rise:f,sinPitch:h,sinRoll:-b}}function Sc(e,t){let r=e.kc,n=uF(e.vehicle,o=>(r?r.ground0[o]:0)+t[o]);return q([-n.sinPitch,n.sinRoll,1])}function D0(e,t,r,n){let o=q(wr(e,Qe(t,r)));return-Math.asin(Math.max(-1,Math.min(1,X(o,n))))*cF}function up(e,t,r,n,o){let a=q(wr(n,Qe(t,r))),s=q([1-a[0]*a[0],-a[0]*a[1],-a[0]*a[2]]),i=ae(a,s),c=p=>[X(p,s),X(p,i),X(p,a)],l=p=>ee(ee(U(s,p[0]),U(i,p[1])),U(a,p[2])),u=e.points,m=c(u.spinAxis),d=ys({uprightUpper:c(u.uprightUpper),uprightLower:c(u.uprightLower),wheelCenter:c(u.wheelCenter),spinAxis:m,tieOuter:c(u.tieOuter),loadedRadius:o.loadedRadius,patchShift:o.patchShift&&NO(o.patchShift,e.metrics.toe/cF,Math.atan2(m[0],m[1]))});return{caster:d.caster,kpi:d.kpi,scrubRadius:d.scrubRadius,mechanicalTrail:d.mechanicalTrail,scrubAtWheel:d.scrubAtWheel,trailAtWheel:d.trailAtWheel,kingpinOffset:d.kingpinOffset,casterOffset:d.casterOffset,kingpinGround:l(d.kingpinGround),contactPatch:l(d.contactPatch),elbow:l([d.contactPatch[0],d.kingpinGround[1],d.kingpinGround[2]]),kingpinAtHub:l(d.kingpinAtHub)}}function NO(e,t,r){if(r===t)return e;let n=e.x*Math.cos(t)-e.y*Math.sin(t),o=e.x*Math.sin(t)+e.y*Math.cos(t);return{x:n*Math.cos(r)+o*Math.sin(r),y:o*Math.cos(r)-n*Math.sin(r)}}function mp(e,t){let r=lF(t);if(r===L0)return e;let n=o=>Math.max(-1,Math.min(1,o));return{...e,heave:e.heave-r.rise,pitch:Math.asin(n(Math.sin(e.pitch)-r.sinPitch)),roll:Math.asin(n(Math.sin(e.roll)-r.sinRoll))}}function Qa(e,t,r){let n=mp({heave:0,pitch:0,roll:0,steer:0},r);return e-Ud(n,[t,0,0],ln(r.vehicle.config))}var OO=180/Math.PI;function E0(e,t){return!e.valid||!e.ic?!1:Math.hypot(e.ic[0]-e.cp[0],e.ic[1]-e.cp[1])<=t}function pp(e,t,r){let n=Qe(t,e.vehicle.config),o=yt(e,r),a=Nu(e,t,o[t]),s=a.at("uprightUpper"),i=a.at("uprightLower"),c=a.at("contactPatch"),l=a.at("wheelCenter"),u=S=>{let P=a.velocity(S);return[P[0],P[2]]},m=u(c),d=u(l),p=[c[0],c[2]],f=[l[0],l[2]];if(!a.solved)return{ic:null,line:null,cp:p,wc:f,road:[1,0],swingArmAngleDeg:NaN,tanTheta:NaN,tanThetaHub:NaN,valid:!1,unsolved:!0,sinAngle:0};let h=Sc(e,{FL:o.FL.ground,FR:o.FR.ground,RL:o.RL.ground,RR:o.RR.ground}),b=Math.hypot(h[0],h[2]),g=[h[0]/b,h[2]/b],y=[g[1],-g[0]],R=S=>{let P=S[0]*g[0]+S[1]*g[1];return Math.abs(P)>1e-9?-(S[0]*y[0]+S[1]*y[1])/P:0},k=a.omega[1],v=Math.hypot(m[0],m[1]),x=Math.abs(k)*1e9>v?[p[0]+m[1]/k,p[1]-m[0]/k]:null,A=x?(S=>{let P=[s[0]-S[0],s[2]-S[1]],L=[i[0]-S[0],i[2]-S[1]];return Math.abs(P[0]*L[1]-P[1]*L[0])/(Math.hypot(...P)*Math.hypot(...L))})(x):0;if(!(Math.abs(m[0]*g[0]+m[1]*g[1])>1e-9))return{ic:x,line:null,cp:p,wc:f,road:y,swingArmAngleDeg:0,tanTheta:0,tanThetaHub:0,valid:!1,sinAngle:A};let w=[m[1]/v,-m[0]/v],C=x?[x[0]-p[0],x[1]-p[1]]:[n.isFront?-1:1,0],T=w[0]*C[0]+w[1]*C[1]<0?[-w[0],-w[1]]:w,F=R(m);return{ic:x,line:T,cp:p,wc:f,road:y,swingArmAngleDeg:Math.atan(F)*OO,tanTheta:F,tanThetaHub:R(d),valid:!0,sinAngle:A}}function mF(e,t,r,n){let o=r/Math.max(1e-6,n.cgHeight),a=t==="front",s=a?n.drive.front:1-n.drive.front,i=a?n.brakeBalanceFront:1-n.brakeBalanceFront,c=(a?n.drive.inboard.front:n.drive.inboard.rear)?e.tanThetaHub:e.tanTheta,l=(a?n.brakeInboard?.front:n.brakeInboard?.rear)?e.tanThetaHub:e.tanTheta,u=a?-1:1;return{brake:u*100*l*o*i,drive:u*100*c*o*s}}var BO=180/Math.PI,$O=Math.PI/180,I0=.5,dp=2,_0=.25,GO={heave:0,pitch:0,roll:0,steer:0},KO={FL:"FR",FR:"FL",RL:"RR",RR:"RL"},fp=e=>e.ok?e.state:{...e.nearest,converged:!1};function N0(e,t,r){return t.state?t.solved===!1?{...t.state,converged:!1}:t.state:fp(ge(e,t.travel,t.steer,void 0,r))}var pF=new WeakMap;function dF(e,t){let r=e.ctx[t],n=_e(e.vehicle,t).config.loadedRadius,o=$t(n,e.kc,t),a=pF.get(r);a||(a=new Map,pF.set(r,a));let s=a.get(o);if(!s){let i=un(t,e.vehicle.config,GO,e.vehicle);s=fp(ge(r,i.travel,i.steer,void 0,o===n?void 0:{loadedRadius:o})),a.set(o,s)}return s}var vr=(e,t)=>!e||!e.lo.converged||!e.hi.converged?NaN:(t(e.hi)-t(e.lo))/(2*e.step),fF=(e,t,r)=>{if(!e||!e.lo.converged||!e.hi.converged)return NaN;let n=r(e.hi)-r(e.lo);return Math.abs(n)<1e-9?NaN:(t(e.hi)-t(e.lo))/n};function bF(e,t,r,n,o){let a=e.vehicle.config,s=qo(r),i=_e(e.vehicle,r),c=Qe(r,a),l=e.ctx[r],u=yt(e,t),m=u[r],d={travel:m.travel,steer:m.steer},p=m.rigid?void 0:{loadedRadius:m.loadedRadius},f=N0(l,m,p),h=dF(e,r),b={lo:fp(ge(l,d.travel-I0,d.steer,void 0,p)),hi:fp(ge(l,d.travel+I0,d.steer,void 0,p)),step:I0},g=c.isFront?{lo:Ie(l,f.beta,d.steer-dp,void 0,p),hi:Ie(l,f.beta,d.steer+dp,void 0,p),step:dp}:null,y=Y=>{let j=yt(e,{...t,roll:t.roll+Y*$O})[r];return N0(l,j,j.rigid?void 0:{loadedRadius:j.loadedRadius})},R={lo:y(-_0),hi:y(_0),step:_0},k=zO(e,t,r,c.isFront,u,g),v=wt(f.points.contactPatch,c),x=wt(h.points.contactPatch,c),M=Math.abs(v[1])-Math.abs(x[1]),A=KO[r],w=u[A],C=N0(e.ctx[A],w,w.rigid?void 0:{loadedRadius:w.loadedRadius}),T=C.converged?M+Math.abs(C.points.contactPatch[1])-Math.abs(dF(e,A).points.contactPatch[1]):NaN,F=o??dr(e,t,s),S=Ou(F,gt(i)),P=S?null:Vk(F),L=c.sideSign>0?F.icRight:F.icLeft,D=L?Math.hypot(L[0]-v[1],L[1]-v[2]):1/0,I=pp(e,r,t),O=I.ic?Math.hypot(I.ic[0]-I.cp[0],I.ic[1]-I.cp[1]):1/0,_=mF(I,s,a.wheelbase,n),z=-vr(b,Y=>Y.points.damperLength),E=i.config.springRate,N=vr(R,Y=>Y.metrics.camber),B=Sc(e,{FL:u.FL.ground,FR:u.FR.ground,RL:u.RL.ground,RR:u.RR.ground}),V=e.kc?.loadCase,G=Y=>V?up(Y,r,a,B,{loadedRadius:m.loadedRadius,patchShift:V.patchShift[r]}):Y.metrics,K=G(f);return{id:r,converged:f.converged,travel:f.travel,camber:f.metrics.camber,camberRoad:D0(f.points.spinAxis,r,a,B),toe:f.metrics.toe,caster:K.caster,kpi:K.kpi,scrubRadius:K.scrubRadius,mechanicalTrail:K.mechanicalTrail,scrubAtWheel:K.scrubAtWheel,trailAtWheel:K.trailAtWheel,kingpinOffset:K.kingpinOffset,casterOffset:K.casterOffset,steeringArm:f.metrics.steeringArm,camberGain:vr(b,Y=>Y.metrics.camber),bumpSteer:vr(b,Y=>Y.metrics.toe),trackScrubRate:vr(b,Y=>Math.abs(wt(Y.points.contactPatch,c)[1])),casterGain:vr(b,Y=>G(Y).caster),kpiGain:vr(b,Y=>G(Y).kpi),scrubGain:vr(b,Y=>G(Y).scrubRadius),trailGain:vr(b,Y=>G(Y).mechanicalTrail),...c.isFront?{camberPerSteer:fF(g,Y=>Y.metrics.camber,Y=>Y.metrics.toe),steerJacking:-fF(g,Y=>Y.points.contactPatch[2],Y=>Y.metrics.toe),...k!==void 0?{steerLoad:k}:{}}:{},rollCamber:N,camberRecovery:-100*c.sideSign*N,rollSteer:c.sideSign*vr(R,Y=>Y.metrics.toe),halfTrackChange:M,trackChange:T,longitudinal:v[0]-x[0],rollCentreHeight:P?P.heightAboveGround:F.heightAboveGround,rollCentreHeightChassis:(P?P.height:F.height)-Qa(0,c.axleX,e),rollCentreLateral:F.lateralAlongGround,rollCentreValid:F.valid,rollCentreUsable:S,rollCentreHeightUsable:S||P!==null,rollCentreSinAngle:F.sinAngle,fvsaLength:D,svsaLength:O,swingArmAngle:I.swingArmAngleDeg,svsaUsable:E0(I,a.wheelbase),svsaSinAngle:I.sinAngle,...s==="front"?{antiDive:_.brake,antiLift:_.drive}:{antiSquat:_.drive,antiLift:_.brake},decoupled:i.config.actuation==="decoupled",mcpherson:i.config.layout==="mcpherson",springRate:E,motionRatio:z,wheelRate:E*z*z,damperLength:f.points.damperLength,damperTravel:h.points.damperLength-f.points.damperLength,...HO(i,h.points.damperLength,f.points.damperLength,e.kc?.curve[r].spring?.law),rockerAngle:i.config.actuation==="direct"?0:(f.points.rockerAngle-h.points.rockerAngle)*BO,groundDisplacement:m.rigid?f.travel:m.ground,tyreDeflection:m.tyreDeflection,wheelLoad:m.load,loadedRadiusAt:m.loadedRadius,rideRate:m.rideRate,wheelRateAtLoad:m.wheelRateAtLoad,lifted:m.lifted,clearance:m.clearance??0,tyreRigid:m.rigid}}function HO(e,t,r,n){if(e.config.actuation==="decoupled")return{};let o=n?{droop:n.droopStated?n.droop:null,bump:n.bump}:Zo(t,e.config.coilover),a=t-r;return{...o.droop!==null?{damperToExtended:a-o.droop}:{},...o.bump!==null?{damperToClosed:o.bump-a}:{}}}function zO(e,t,r,n,o,a){if(!a||!n)return;let s=Al(e,t,"front"),i=e.kc;if(!s||!i)return;let c=["FL","FR"],l=[0,0],u=[0,0],m={lo:[],hi:[]},d=0;for(let h=0;h<2;h++){let b=c[h],g=o[b],y=e.ctx[b],R=g.rigid?void 0:{loadedRadius:g.loadedRadius},x=(b==="FR"?1:-1)*(r==="FR"?1:-1)*dp,M=g.state?{q:[...g.state.pose.t,...g.state.pose.omega],phi:g.state.points.rockerAngle}:void 0,A=mt(ge(y,g.travel,g.steer-x,M,R)),w=mt(ge(y,g.travel,g.steer+x,M,R));if(!A||!w)return NaN;l[h]=w.points.contactPatch[2]-A.points.contactPatch[2],u[h]=Cr(i.curve[b],g.travel,w.points.damperLength)-Cr(i.curve[b],g.travel,A.points.damperLength),m.lo.push(A),m.hi.push(w),b===r&&(d=w.metrics.toe-A.metrics.toe)}let p=i.elements?.front;if(p){let h=[o.FL.travel,o.FR.travel],b=Ts(p,h,[m.hi[0],m.hi[1]]),g=Ts(p,h,[m.lo[0],m.lo[1]]);u[0]+=b[0]-g[0],u[1]+=b[1]-g[1]}return Math.abs(d)>1e-9?s([0,0],l,u)[r==="FL"?0:1]/d:NaN}function Ac(e,t,r,n,o){return bF(e,t,r==="front"?"FL":"RL",n,o)}function O0(e,t,r,n){let o=Ac(e,t,"front",r,n?.front),a=Ac(e,t,"rear",r,n?.rear);return{front:o,rear:a,wheelbaseChange:o.longitudinal-a.longitudinal}}function hp(e,t){let r=t.vehicle.config;return e.map(n=>{let o=n.axle==="front"?r.frontAxleX:r.frontAxleX-r.wheelbase,a=o+Math.min(n.xMin,n.xMax),s=o+Math.max(n.xMin,n.xMax),i=(a+s)/2;return{...n,min:[a,Math.min(n.yMin,n.yMax),Qa(Math.min(n.zMin,n.zMax),i,t)],max:[s,Math.max(n.yMin,n.yMax),Qa(Math.max(n.zMin,n.zMax),i,t)]}})}var Fo=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],zt=(e,t)=>[e[0]+t[0],e[1]+t[1],e[2]+t[2]],nt=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],Zt=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],Fc=e=>Math.sqrt(Zt(e,e));function YO(e,t){return{min:e,max:t,support:r=>[r[0]>=0?t[0]:e[0],r[1]>=0?t[1]:e[1],r[2]>=0?t[2]:e[2]]}}function WO(e,t){return{min:[Math.min(e[0],t[0]),Math.min(e[1],t[1]),Math.min(e[2],t[2])],max:[Math.max(e[0],t[0]),Math.max(e[1],t[1]),Math.max(e[2],t[2])],support:r=>Zt(r,e)>=Zt(r,t)?e:t,samples:()=>Array.from({length:41},(r,n)=>zt(e,nt(Fo(t,e),n/40)))}}function jO(e,t,r,n){let o=nt(t,1/(Fc(t)||1)),a=n/2,s=o.map(i=>r*Math.sqrt(Math.max(0,1-i*i))+a*Math.abs(i));return{min:Fo(e,s),max:zt(e,s),support:i=>{let c=Zt(i,o),l=Fo(i,nt(o,c)),u=Fc(l),m=u>1e-12?nt(l,r/u):[0,0,0];return zt(zt(e,nt(o,c>=0?a:-a)),m)},samples:()=>{let i=Math.abs(o[0])<.9?[1,0,0]:[0,1,0],c=Fo(i,nt(o,Zt(i,o))),l=nt(c,1/Fc(c)),u=[o[1]*l[2]-o[2]*l[1],o[2]*l[0]-o[0]*l[2],o[0]*l[1]-o[1]*l[0]],m=[];for(let d of[-1,-.5,0,.5,1]){let p=zt(e,nt(o,d*a));m.push(p);let f=Math.abs(d)===1?[.5,1]:[1];for(let h of f)for(let b=0;b<72;b++){let g=b/72*2*Math.PI;m.push(zt(p,zt(nt(l,h*r*Math.cos(g)),nt(u,h*r*Math.sin(g)))))}}return m}}}function UO(e){let t=e[0],r=e.slice(1).map(c=>Fo(c,t)),n=r.length;if(n===0)return{v:t,w:[1]};let o=r.map(c=>r.map(l=>Zt(c,l))),a=r.map(c=>-Zt(c,t));for(let c=0;c<n;c++){let l=c;for(let u=c+1;u<n;u++)Math.abs(o[u][c])>Math.abs(o[l][c])&&(l=u);if(Math.abs(o[l][c])<1e-12)return null;[o[c],o[l]]=[o[l],o[c]],[a[c],a[l]]=[a[l],a[c]];for(let u=0;u<n;u++){if(u===c)continue;let m=o[u][c]/o[c][c];for(let d=c;d<n;d++)o[u][d]-=m*o[c][d];a[u]-=m*a[c]}}let s=a.map((c,l)=>c/o[l][l]),i=t;for(let c=0;c<n;c++)i=zt(i,nt(r[c],s[c]));return{v:i,w:[1-s.reduce((c,l)=>c+l,0),...s]}}function XO(e){let t=null,r=1/0,n=e.length;for(let o=1;o<1<<n;o++){let a=e.filter((c,l)=>o&1<<l),s=UO(a.map(c=>c.w));if(!s||s.w.some(c=>c<-1e-9))continue;let i=Zt(s.v,s.v);(i<r-1e-12||Math.abs(i-r)<=1e-12&&t&&a.length<t.keep.length)&&(r=i,t={v:s.v,keep:a,weights:s.w})}return t??{v:e[0].w,keep:[e[0]],weights:[1]}}function qO(e,t){let r=s=>{let i=e.support(s),c=t.support(nt(s,-1));return{w:Fo(i,c),a:i,b:c}},n=(s,i)=>{let c=[0,0,0],l=[0,0,0];return s.keep.forEach((u,m)=>{c=zt(c,nt(u.a,s.weights[m])),l=zt(l,nt(u.b,s.weights[m]))}),{distance:i,onA:c,onB:l}},o=r([1,0,0]),a={v:o.w,keep:[o],weights:[1]};for(let s=0;s<64;s++){let i=a.v,c=Zt(i,i);if(c<1e-12)return n(a,0);let l=r(nt(i,-1));if(c-Zt(i,l.w)<=1e-9*Math.max(1,c))return n(a,Math.sqrt(c));let u=XO([...a.keep,l]);if(u.keep.length===4)return n(u,0);if(Zt(u.v,u.v)>=c-1e-12)return n(a,Math.sqrt(c));a=u}return n(a,Fc(a.v))}function QO(e,t){let r=null;for(let o of t.samples?.()??[]){let a=1/0,s=0,i=0;for(let c=0;c<3;c++)o[c]-e.min[c]<a&&(a=o[c]-e.min[c],s=c,i=e.min[c]),e.max[c]-o[c]<a&&(a=e.max[c]-o[c],s=c,i=e.max[c]);a>0&&(!r||a>r.depth)&&(r={depth:a,point:o,axis:s,to:i})}if(!r)return null;let n=[...r.point];return n[r.axis]=r.to,{depth:r.depth,point:r.point,face:n}}function ZO(e,t){let r=0;for(let n=0;n<3;n++){let o=Math.max(0,e.min[n]-t.max[n],t.min[n]-e.max[n]);r+=o*o}return Math.sqrt(r)}var xF={linkRadius:8,mountAllowance:15},JO=(e,t,r)=>e.z0+e.dzdx*t+e.dzdy*r;function eV(e,t){let r=Math.sin(e.pitch);return{z0:-e.heave+t*r,dzdx:-r,dzdy:Math.sin(e.roll)}}function RF(e){return eV(mp({heave:0,pitch:0,roll:0,steer:0},e),ln(e.vehicle.config))}var tV=[{name:"upper wishbone, front leg",inboard:"ucaFront",outboard:"uprightUpper"},{name:"upper wishbone, rear leg",inboard:"ucaRear",outboard:"uprightUpper"},{name:"lower wishbone, front leg",inboard:"lcaFront",outboard:"uprightLower"},{name:"lower wishbone, rear leg",inboard:"lcaRear",outboard:"uprightLower"},{name:"tie rod",inboard:"tieInner",outboard:"tieOuter"},{name:"pushrod",inboard:"rockerToPushrod",outboard:"pushrodOuter"},{name:"strut",inboard:"damperChassis",outboard:"pushrodOuter"}];function rV(e){return tV.filter(t=>t.name==="strut"?e.mcpherson:t.name==="pushrod"?!e.direct:!(e.mcpherson&&t.name.startsWith("upper")))}var nV=(e,t,r)=>e.every((n,o)=>n>=t.min[o]-r&&n<=t.max[o]+r);function gF(e,t,r){let n=Fo(t,e),o=Fc(n);return o>1e-9?zt(e,nt(n,r/o)):e}function yF(e,t){let r=null;for(let{shape:n,pad:o,part:a,pose:s}of t){if(r&&ZO(e,n)-o>=r.distance)continue;let i=qO(e,n),c=i.distance>0?null:QO(e,n),l=i.distance>0?i.distance-o:-((c?.depth??0)+o);if(Number.isFinite(l)&&(!r||l<r.distance)){let u=i.distance>0?{part:gF(i.onB,i.onA,o),box:i.onA}:c?{part:gF(c.point,c.face,-o),box:c.face}:{part:i.onB,box:i.onA};r={distance:l,part:a,corner:s.corner,travel:s.travel,rack:s.rack,gap:u}}}return r}function oV(e,t){let r=[];for(let c of[e.min[0],e.max[0]])for(let l of[e.min[1],e.max[1]])r.push([c,l,e.min[2]]);let n=r.map(t),o=Math.min(...n),a=r.filter((c,l)=>n[l]<=o+.5),s=new Set(a.map(c=>c[0])),i=new Set(a.map(c=>c[1]));return{height:o,lowest:{x:s.size>1||e.min[0]===e.max[0]?null:a[0][0]===e.max[0]?"front":"rear",y:i.size>1||e.min[1]===e.max[1]?null:a[0][1]===e.max[1]?"right":"left"},at:nt(a.reduce((c,l)=>zt(c,l),[0,0,0]),1/a.length)}}function vF(e,t){return{...oV(e,r=>r[2]-JO(t,r[0],r[1])),road:t}}function kF(e,t){let r=(a,s,i)=>a[0]*(s[1]*i[2]-s[2]*i[1])-a[1]*(s[0]*i[2]-s[2]*i[0])+a[2]*(s[0]*i[1]-s[1]*i[0]),n=r(e[0],e[1],e[2]);if(Math.abs(n)<1e-12)return null;let o=a=>e.map((s,i)=>s.map((c,l)=>l===a?t[i]:c));return[r(...o(0))/n,r(...o(1))/n,r(...o(2))/n]}function aV(e,t){let r=e.map(o=>({pose:o,part:`${o.corner} tyre`,pad:0,shape:jO(o.g.wheelCenter,o.g.spinAxis,o.corner[0]==="F"?t.tyreRadius.front:t.tyreRadius.rear,t.tyreWidth)})),n=e.flatMap(o=>rV(o.g).map(a=>{let s=o.g[a.inboard],i=o.g[a.outboard];return{pose:o,part:`${o.corner} ${a.name}`,pad:t.linkRadius,inboard:s,shape:WO(s,i)}})).filter(o=>o.inboard.every(Number.isFinite)&&[o.shape.min,o.shape.max].every(a=>a.every(Number.isFinite)));return{tyres:r,links:n}}function sV(e,t,r){let n=YO(e.min,e.max),o=t.links.filter(a=>!nV(a.inboard,e,r.mountAllowance+r.linkRadius));return{tyre:yF(n,t.tyres),link:yF(n,o)}}function MF(e,t,r){let n=aV(t,r);return e.map(o=>({boxId:o.id,...sV(o,n,r)}))}var TF=152,PF={travelSteps:9,rackSteps:5},wo=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],Jr=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],wc=(e,t)=>[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]],Jt=e=>{let t=Math.hypot(e[0],e[1],e[2]);return t>0?[e[0]/t,e[1]/t,e[2]/t]:[NaN,NaN,NaN]},LF=180/Math.PI,iV=[[1,0,0],[0,1,0],[0,0,1]],SF=(e,t)=>[e[0][0]*t[0]+e[1][0]*t[1]+e[2][0]*t[2],e[0][1]*t[0]+e[1][1]*t[1]+e[2][1]*t[2],e[0][2]*t[0]+e[1][2]*t[1]+e[2][2]*t[2]],cV=(e,t)=>[Jr(e[0],t),Jr(e[1],t),Jr(e[2],t)];function AF(e,t,r){let n=Jt(wo(t,e)),o=Jt(wc(n,wo(r,e)));return[n,wc(o,n),o]}function lV(e,t){let r=n=>[t[0][0]*e[0][n]+t[1][0]*e[1][n]+t[2][0]*e[2][n],t[0][1]*e[0][n]+t[1][1]*e[1][n]+t[2][1]*e[2][n],t[0][2]*e[0][n]+t[1][2]*e[1][n]+t[2][2]*e[2][n]];return[r(0),r(1),r(2)]}function V0(e,t,r,n){let o=Jt(wo(t,e)),a=b=>{let g=wo(b,e),y=Jr(g,o);return[g[0]-y*o[0],g[1]-y*o[1],g[2]-y*o[2]]},s=Jt(a(r)),i=Jt(a(n)),c=Jr(wc(s,i),o),u=Jr(s,i),m=c,d=1-u,[p,f,h]=o;return[[d*p*p+u,d*p*f+m*h,d*p*h-m*f],[d*p*f-m*h,d*f*f+u,d*f*h+m*p],[d*p*h+m*f,d*f*h-m*p,d*h*h+u]]}var uV=(e,t)=>Math.acos(Math.max(-1,Math.min(1,Jr(Jt(e),Jt(t)))))*LF;function mV(e,t){return{upright:lV(AF(e.uprightLower,e.tieOuter,e.wheelCenter),AF(t.uprightLower,t.tieOuter,t.wheelCenter)),uca:t.mcpherson?null:V0(t.ucaFront,t.ucaRear,e.uprightUpper,t.uprightUpper),lca:V0(t.lcaFront,t.lcaRear,e.uprightLower,t.uprightLower),rocker:t.direct?null:V0(t.rockerPivotA,t.rockerPivotB,e.rockerToPushrod,t.rockerToPushrod)}}function DF(e){let t=Jt(e[0]),r=Math.abs(t[0])<.9?[1,0,0]:[0,1,0],n=Jt(wc(t,r)),o=wc(t,n),a=e.map(f=>{let h=Jt(f);return[Jr(h,n),Jr(h,o)]}),s=f=>{let h=Math.cos(f),b=Math.sin(f),g=0;for(let[y,R]of a)g=Math.max(g,Math.abs(y*h+R*b));return g},i=Math.PI/180,c=0,l=1/0;for(let f=0;f<180;f++){let h=s(f*i);h<l&&([c,l]=[f*i,h])}let u=c-i,m=c+i,d=(Math.sqrt(5)-1)/2;for(let f=0;f<30;f++){let h=m-d*(m-u),b=u+d*(m-u);s(h)<s(b)?m=b:u=h}let p=Math.min(l,s((u+m)/2));return Math.asin(Math.min(1,p))*LF}function FF(e){let t=null;for(let r of e)Number.isFinite(r.angle)&&(!t||r.angle>t.angle)&&(t=r);return t}var pV={upright:"upright",lowerArm:"lca",upperArm:"uca"};function EF(e,t,r,n){let o=t.map(m=>mV(e,m)),a=Jt(wo(e.uprightUpper,e.uprightLower)),s=m=>Math.max(0,...o.map(d=>d[m]?uV(SF(d.upright,a),SF(d[m],a)):0)),i=[{angle:s("lca"),joint:"lower ball joint"}];e.mcpherson||i.push({angle:s("uca"),joint:"upper ball joint"});let c=(m,d,p)=>{let f=[wo(e[d],e[m])];for(let h=0;h<t.length;h++){let b=p(o[h]);if(!b)return null;f.push(cV(b,wo(t[h][d],t[h][m])))}return f},l=[["tie rod, inner end",c("tieInner","tieOuter",()=>iV)],["tie rod, outer end",c("tieInner","tieOuter",m=>m.upright)]];e.direct||l.push([`${n}, rocker end`,c("rockerToPushrod","pushrodOuter",m=>m.rocker)],[`${n}, outer end`,c("rockerToPushrod","pushrodOuter",m=>m[pV[r]])]);let u=l.filter(m=>m[1]!==null).map(([m,d])=>({joint:m,angle:DF(d)}));return{ballJoint:FF(i),rodEnd:FF(u)}}function dV(e){let t=(r,n)=>{let o=$t(n,e.kc,r),a=e.kc?.input.corners[r];return a&&a.tyreRate>0&&Number.isFinite(a.tyreRate)?o+Math.max(0,a.staticLoad)/a.tyreRate:o};return{front:t("FL",e.vehicle.front.config.loadedRadius),rear:t("RL",e.vehicle.rear.config.loadedRadius)}}function IF(e,t){let r=Ql(t);return{...xF,tyreRadius:dV(e),tyreWidth:r!==null?r*1e3:TF}}var wF={front:["FL","FR"],rear:["RL","RR"]},CF=(e,t,r)=>r<=1||t===e?[e]:Array.from({length:r},(n,o)=>e+(t-e)*o/(r-1));function B0(e,t,r,n,o=PF){let a=e.vehicle,[s]=wF[t],i=Iu(e,s,0,0)?.geometry;if(!i)return null;let c=hp(a.chassis?.boxes??[],{vehicle:a,kc:e.kc}),l=t==="front"?xt(a.front.config):0,u=l>0?CF(-l,l,Math.max(3,o.rackSteps|1)):[0],m=CF(Math.min(0,r.min),Math.max(0,r.max),Math.max(2,o.travelSteps)),d=[];for(let b of c.length?wF[t]:[s])for(let g of m)for(let y of u){let R=Iu(e,b,g,y)?.geometry;R&&d.push({corner:b,travel:g,rack:y,g:R})}let p=null;if(c.length){for(let b of MF(c,d,IF(e,n)))for(let g of[b.tyre,b.link])g&&(!p||g.distance<p.distance)&&(p={distance:g.distance,part:g.part,boxId:b.boxId});p??={distance:NaN,part:"",boxId:""}}let f=a[t].config,h=EF(i,d.filter(b=>b.corner===s).map(b=>b.g),f.pushrodAttach,f.rodType==="pull"?"pullrod":"pushrod");return{chassis:p,...h}}var bp=Math.PI/180,Cc={travelSteps:9,heaveSteps:5,rollSteps:4,rackSteps:6},gp={travelMin:-25,travelMax:25,rollMaxDeg:3,rollAtLimitDeg:2.5};function fV(e){let t=e.params;return{cgHeight:t.cg_height?ht({...t,surveyedRadiusFront:e.vehicle.front.config.loadedRadius,surveyedRadiusRear:e.vehicle.rear.config.loadedRadius}).cgHeight:300,...Bh(t),drive:Nh(t)}}function _F(e,t){for(let r=1;r<e.length;r++){let n=3*t(r)+10;for(let o of["cpLeft","cpRight"]){let a=e[r-1][o],s=e[r][o];if(a&&s&&Math.hypot(s[0]-a[0],s[1]-a[1])>n)return r}}return-1}function $0(e,t=Cc,r=gp,n){let o=null,a=(S,P)=>(o||(o={violation:S,reason:P}),null),s=e.vehicle,i=S=>S==="front"?s.front:s.rear,c=null,l=null,u=()=>{if(c)return c;if(n)try{let S=n();if(S)return c=Dt(s,S.kc),l=S.cgHeight,c}catch{a(500,"the car could not be stood on its tyre: its rates did not assemble")}return c=Dt(s)},m=S=>S==="front"?"FL":"RL",d=S=>{let P=u();if(!P.kc)return;let L=i(S).config.loadedRadius,D=$t(L,P.kc,m(S));return D===L?void 0:{loadedRadius:D}},p=(S,P)=>-Ps(u(),m(S),P),f=new Map,h=new Map,b=new Map,g=new Map,y=new Map,R=new Map,k=new Map,v=new Map,x=null,M=()=>{if(x)return x;u();let S=fV(e);return x=l!==null&&Number.isFinite(l)?{...S,cgHeight:l}:S},A,w,C=()=>{if(w!==void 0)return w;let S=Ll(u().ctx.FL,xt(s.front.config));return w=S?Dl(S):null,w},T=(S,P,L)=>{if(S.has(P))return S.get(P)??null;let D=L();return S.set(P,D),D};return{car:e,density:t,envelope:r,get failure(){return o},axisLength:(S,P)=>{let L=i(S),D=L.hardpoints;return P==="uca"&&L.config.layout==="mcpherson"?NaN:P==="uca"?ve(D.ucaFront,D.ucaRear):ve(D.lcaFront,D.lcaRear)},linkLength:S=>{let P=i(S).hardpoints;return ve(P.tieInner,P.tieOuter)},compliance:S=>T(h,S,()=>Gf(i(S))??null),sweep:S=>T(f,S,()=>{let P;try{P=Ke(i(S),{travelMin:r.travelMin,travelMax:r.travelMax,steps:t.travelSteps})}catch{return a(500,`the ${S} travel sweep threw`)}if(!P.covered){let D=P.samples.map(_=>_.travel),I=Math.max(...D)-Math.min(...D),O=r.travelMax-r.travelMin;return a(Math.max(0,O-I),`the ${S} linkage reaches only ${I.toFixed(0)} mm of the ${O.toFixed(0)} mm travel range`)}if(P.fold)return a(200,`the ${S} travel(beta) folds \u2014 the suspension goes over centre in range`);let L=P.samples.filter(D=>!D.converged).length;if(L>0)return a(100+10*L,`${L} of ${P.samples.length} ${S} travel solves did not converge`);if(S==="front"&&i("front").config.steerMode==="rack"){let D=C();if(D)return a(D.violation,D.reason)}return P}),rcHeave:S=>T(b,S,()=>{let P=[],L=[],D=Math.max(2,t.heaveSteps);try{for(let O=0;O<D;O++){let _=r.travelMin+(r.travelMax-r.travelMin)*O/(D-1);P.push(_),L.push(dr(u(),{heave:p(S,_),pitch:0,roll:0,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in heave`)}let I=_F(L,O=>Math.abs(P[O]-P[O-1]));return I>0?a(300,`the ${S} roll-centre construction lands on another branch at ${P[I].toFixed(0)} mm of travel`):{at:P,rc:L}}),rcRoll:S=>T(g,S,()=>{let P=[],L=[],D=Math.max(2,t.rollSteps);try{for(let O=0;O<D;O++){let _=r.rollMaxDeg*O/(D-1);P.push(_),L.push(dr(u(),{heave:0,pitch:0,roll:_*bp,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in roll`)}let I=_F(L,O=>Math.abs(L[O].cpLeft?.[0]??0)*Math.abs(P[O]-P[O-1])*bp);return I>0?a(300,`the ${S} roll-centre construction lands on another branch at ${P[I].toFixed(1)}\xB0 of roll`):{at:P,rc:L}}),steer:()=>{if(A!==void 0)return A;try{A=kf(u(),{steerMax:xt(s.front.config),steps:t.rackSteps})}catch{A=a(500,"the steering sweep threw")}let S=A?.filter(P=>!P.converged).length??0;if(A&&S>0){let P=C();A=P?a(P.violation,P.reason):a(100+10*S,`${S} of ${A.length} steering solves did not converge`)}return A??null},solveAt:(S,P,L=0)=>T(y,`${S}:${P}:${L}`,()=>{try{let D=ge(u().ctx[m(S)],P,L,void 0,d(S));return D.ok?D.state:D.why==="unconverged"?a(100,`the ${S} corner did not solve at ${P.toFixed(0)} mm of travel`):a(100+Math.abs(D.travelMiss),`the ${S} corner reaches only ${(P+D.travelMiss).toFixed(0)} of ${P.toFixed(0)} mm of travel`)}catch{return a(150,`the ${S} corner solve threw at ${P.toFixed(0)} mm of travel`)}}),readout:S=>T(k,`${S.heave}:${S.pitch}:${S.roll}:${S.steer}`,()=>{try{return O0(u(),S,M())}catch{return a(500,"the derived readout threw")}}),readoutAtTravel:(S,P)=>T(v,`${S}:${P}`,()=>{try{return Ac(u(),{heave:p(S,P),pitch:0,roll:0,steer:0},S,M())}catch{return a(500,`the ${S} readout threw at ${P.toFixed(0)} mm of travel`)}}),travelAtRoll:(S,P)=>{let L=i(S).hardpoints.wheelCenter[1]*Math.sin(P*bp),D=u();if(!D.kc)return L;try{let I=yt(D,{heave:0,pitch:0,roll:P*bp,steer:0}),O=S==="front"?Math.max(I.FL.travel,I.FR.travel):Math.max(I.RL.travel,I.RR.travel);return Number.isFinite(O)?O:L}catch{return a(500,`the ${S} axle could not be rolled on its tyre`),L}},onTyre:()=>!!u().kc,contexts:u,keepOuts:S=>T(R,S,()=>{try{let P=e.params,L=S==="front"?P.tireModel:P.tireModelRear??P.tireModel,D={min:r.travelMin,max:r.travelMax};return B0(u(),S,D,L)??a(100,`the ${S} corner did not solve at its design ride`)}catch{return a(500,`the ${S} keep-outs threw`)}})}}var hV=Tg();function G0(e,t={}){let r=new Map;return{session(n){if(r.has(n))return r.get(n);let o=null,a=t.session?.();if(t.sessionParams&&a)try{let s=Tm(n,a.rulesets),i=s?.events.some(c=>c.kind==="trackLap");if(s&&(a.track||!i)){let c=t.sessionParams(e),{standingStart:l,lapCounts:u}=a.settings,m=a.track?ac([c],a.track,a.numerics,ec(s),a.settings,hV)[0]:Yi(c,s,{numerics:a.numerics,standingStart:l,lapCounts:u});o={};for(let d of s.metrics)Jc(d)&&(o[d.key]=d.value(m,void 0))}}catch{o=null}return r.set(n,o),o}}}var yp=.01;function bV(e,t){return t.bump!==null&&e>t.bump-yp?{at:"closed",past:Math.max(0,e-t.bump)}:t.droopStated&&e<t.droop+yp?{at:"toppedOut",past:Math.max(0,t.droop-e)}:t.seat!==null&&e<t.seat+yp?{at:"unseated",past:Math.max(0,t.seat-e)}:{at:"free",past:0}}var NF=e=>({droop:e.droop,droopStated:e.droopStated,bump:e.bump,seat:e.holdsLoad&&Number.isFinite(e.free)?e.free:null}),gV=[["front","FL","FR"],["rear","RL","RR"]];function H0(e,t){let r=[];for(let[n,o,a]of gV){let s=[t[o],t[a]];for(let m of[o,a]){let d=e.curve[m],p=d.spring?.law;if(!d.spring||!p)continue;let f=tf(d,t[m]);f===null||!Number.isFinite(f)||r.push(K0(m,n,n,f,d.spring.length0-f,NF(p),!0))}let i=e.elements?.[n];if(!i)continue;let c=i.heave?.law;if(c){let m=DR(i,s),d=i.read.heave?.span0,p=n==="front"?"heaveFront":"heaveRear";r.push(K0(p,p,n,m,d!==void 0?d-m:null,NF(c),i.carriesLoad))}let l=i.rollStop,u=l?ER(i,s):null;if(l&&u!==null){let m=l.length0-u,d=n==="front"?"rollFront":"rollRear",p={droop:l.droop??-1/0,droopStated:l.droop!==null,bump:l.bump,seat:null};r.push(K0(d,d,n,m,u,p,i.carriesLoad))}}return r}function K0(e,t,r,n,o,a,s){return{damper:e,place:t,axle:r,length:o,compression:n,toToppedOut:a.droopStated?n-a.droop:null,toClosed:a.bump!==null?a.bump-n:null,...bV(n,a),bumpStated:a.bump!==null,bounds:s}}var BF=Math.PI/180;function z0(e,t,r,n){let o=t.speedKmh/3.6,a=Od(e,o,t.axG,an(e,t.ayG,0));if(!a||!e.aero)return null;let s=e.wheelbase,i=Uo(e.aero,s),c=(h,b)=>Math.atan((b-h)/s)/BF,l={},u={};for(let h of ar)l[h]=r.corners[h].travel,u[h]=r.corners[h].ground;let m=n.kc?H0(n.kc,l):[],d=e.aero.model,p=a.downFront+a.downRear,f=d?{balance:Math.abs(p)>1e-9?100*a.downFront/p:NaN,clA:(a.clFront+a.clRear)*a.area,cdA:a.cd*a.area,loopMargin:1-a.gain,dataMargin:$F(d,s,a.hFront,a.hRear)}:null;return{front:{height:a.hFront,...OF(m,"front")},rear:{height:a.hRear,...OF(m,"rear")},rakeDeg:c(a.hFront,a.hRear),pitchDeg:c(a.hFront,a.hRear)-c(i.hFront,i.hRear),rollDeg:Math.abs(r.rollDeg),aero:f,clearance:yV(n,u)}}function OF(e,t){let r=e.filter(o=>o.axle===t&&o.bounds),n=o=>{let a=o.filter(s=>s!==null&&Number.isFinite(s));return a.length?Math.min(...a):null};return{toBump:n(r.map(o=>o.toClosed)),toDroop:n(r.map(o=>o.toToppedOut))}}function $F(e,t,r,n){let o=(a,[s,i])=>Math.min(a-s,i-a);if(Ax(e)){let{x:a,y:s}=zo(e),i=[a[0],a[a.length-1]],c=[s[0],s[s.length-1]];return nn(e)?VF(e.frame,t,i,c,r,n):Math.min(o(r,i),o(n,c))}return al(e)?VF(e.frame,t,e.range.h,e.range.pitch,r,n):Math.min(o(r,e.range.hFront),o(n,e.range.hRear))}function VF(e,t,r,n,o,a){let s=Yo(e,t,o,a),i=l=>t*Math.tan(l*BF),c=a-o;return Math.min(s.h-r[0],r[1]-s.h,c-i(n[0]),i(n[1])-c)}function yV(e,t){let r=e.vehicle.chassis?.boxes;if(!r?.length)return null;let n={vehicle:e.vehicle,kc:e.kc},o=e.vehicle.config,a=o.frontAxleX,s=o.frontAxleX-o.wheelbase,i=Bt(e.vehicle,!0)/2,c=Bt(e.vehicle,!1)/2,l={FL:[a,-i],FR:[a,i],RL:[s,-c],RR:[s,c]},u=[[0,0,0],[0,0,0],[0,0,0]],m=[0,0,0];for(let b of ar){let g=[1,l[b][0],l[b][1]];for(let y=0;y<3;y++){m[y]+=g[y]*t[b];for(let R=0;R<3;R++)u[y][R]+=g[y]*g[R]}}let d=kF(u,m);if(!d)return null;let p=RF(n),f={z0:p.z0+d[0],dzdx:p.dzdx+d[1],dzdy:p.dzdy+d[2]},h=null;for(let b of hp(r,n)){let g=vF(b,f);(!h||g.height<h.height)&&(h={height:g.height,volume:b.name})}return h}function xp(e){return e.aeroModel?null:"The car runs on aero constants, which do not move with the platform; attach an aero model in Aerodynamics"}var xV={front:"front",rear:"rear",heaveFront:"front",heaveRear:"rear",rollFront:"front",rollRear:"rear"};function Tc(e,t,r,n){let o=Hu(e,t);return Du.some(s=>{if(xV[s]!==r)return!1;let i=o[s].coilover,c=i?.extended!==void 0&&i.extended>0;return n==="droop"?c:c&&i?.stroke!==void 0&&i.stroke>0})?null:n==="droop"?`No ${r} damper states its extended length; state it on its part in Dampers, or under Elements \u203A Stops`:`No ${r} damper states its stroke; state its extended length and stroke on its part in Dampers, or under Elements \u203A Stops`}function Y0(e){return e.chassis?.boxes.length?null:"This suspension has no mockup volumes to measure the ground from; draw one under Kinematics \u203A Chassis"}var Rp=Math.PI/180,vp=1e-6;function KF(e,t){let r=e.length;if(r===0)return 0;if(0<=e[0])return t[0];if(0>=e[r-1])return t[r-1];let n=0;for(;e[n+1]<0;)n++;let o=(0-e[n])/(e[n+1]-e[n]);return t[n]+o*(t[n+1]-t[n])}function Pc(e){let t=e.measured;if(t)return KF(t.travel,t.camber);let r=q(e.config.spinAxis);return-Math.asin(Math.max(-1,Math.min(1,r[2])))/Rp}function Lc(e){let t=e.measured;if(t)return KF(t.travel,t.toe);let[r,n]=e.config.spinAxis;return Math.atan2(r,n)/Rp}function W0(e,t){let r=Math.abs(t.camber)>=vp,n=Math.abs(t.toe)>=vp;if(!r&&!n)return e;let o=e.measured;if(o)return{...e,measured:{...o,...r?{camber:o.camber.map(p=>p+t.camber)}:{},...n?{toe:o.toe.map(p=>p+t.toe)}:{}}};let[a,s]=e.config.spinAxis,i=Math.hypot(a,s);if(!(i>0))return e;let c=(Pc(e)+t.camber)*Rp,l=(Lc(e)+t.toe)*Rp,[u,m]=n?[Math.sin(l),Math.cos(l)]:[a/i,s/i],d=[u*Math.cos(c),m*Math.cos(c),-Math.sin(c)];return{...e,config:{...e.config,spinAxis:d}}}function kp(e){let t=e&&typeof e=="object"?e.value:void 0;return typeof t=="number"&&Number.isFinite(t)?t:void 0}function RV(e,t){let r=t;return{front:kp(r.camber_front_deg)??Pc(e.front),rear:kp(r.camber_rear_deg)??Pc(e.rear)}}function vV(e,t){let r=t;return{front:kp(r.toe_front_deg)??Lc(e.front),rear:kp(r.toe_rear_deg)??Lc(e.rear)}}function kV(e){return{camber:{front:Pc(e.front),rear:Pc(e.rear)},toe:{front:Lc(e.front),rear:Lc(e.rear)}}}var GF=new WeakMap;function MV(e,t){let r=kV(e),n={front:{camber:t.camber.front-r.camber.front,toe:t.toe.front-r.toe.front},rear:{camber:t.camber.rear-r.camber.rear,toe:t.toe.rear-r.toe.rear}},o=u=>Math.abs(u.camber)<vp&&Math.abs(u.toe)<vp;if(o(n.front)&&o(n.rear))return e;let a=`${t.camber.front}|${t.camber.rear}|${t.toe.front}|${t.toe.rear}`,s=GF.get(e),i=s?.get(a);if(i)return i;let c=e.corners?Object.fromEntries(Object.entries(e.corners).map(([u,m])=>[u,m&&W0(m,n[qo(u)])])):void 0,l={...e,front:W0(e.front,n.front),rear:W0(e.rear,n.rear),...c?{corners:c}:{}};return s||GF.set(e,s=new Map),s.size>=16&&s.clear(),s.set(a,l),l}function Za(e,t){return t?MV(e,{camber:RV(e,t),toe:vV(e,t)}):e}var SV=9.81;function Ja(e){let t=Kn(e),r=Math.max(0,e.unsprungPerCorner)*SV,n=a=>{let s=a==="FL"||a==="FR",i=s?"front":"rear",c=Xe(e,i),l=c>0?c:1/0,u=gd(e,i);return{staticLoad:t[a],springLoad:Math.max(0,t[a]-r),tyreRate:l,arbRate:s?e.arbFront:e.arbRear,heaveRate:(s?e.heaveSpringFront:e.heaveSpringRear)??0,...u>0?{staticLoadedRadius:Ht(u,t[a],l,u)}:{}}},o={};for(let[a,s,i,c,l,u]of[["front",e.elementLinkagesFront,!!e.decoupledFront,e.heaveCoiloverFront,e.heaveSeatFront,e.rollCoiloverFront],["rear",e.elementLinkagesRear,!!e.decoupledRear,e.heaveCoiloverRear,e.heaveSeatRear,e.rollCoiloverRear]]){let m=!i&&!!l&&(l.gap>0||!l.bothWays);(s?.heave||s?.roll||i||m)&&(o[a]={...s,carriesLoad:i,...c?{coilover:c}:{},...l&&!i?{heaveSeat:l}:{},...u?{rollCoilover:u}:{}})}return{corners:{FL:n("FL"),FR:n("FR"),RL:n("RL"),RR:n("RR")},...o.front||o.rear?{elements:o}:{},...e.cornerCoiloverFront||e.cornerCoiloverRear?{cornerCoilover:{...e.cornerCoiloverFront?{front:e.cornerCoiloverFront}:{},...e.cornerCoiloverRear?{rear:e.cornerCoiloverRear}:{}}}:{}}}var HF=new WeakMap;function AV(e){let t=Za(e.vehicle,e.params);if(t===e.vehicle)return e;let r=HF.get(e);return(!r||r.vehicle!==t)&&HF.set(e,r={...e,vehicle:t}),r}function Tn(e,t={}){let r=AV(e),n=S0(r,t),o=t.assemble?()=>{let m=n.dynInput();if(!m)throw new Error("the car did not assemble");return{kc:Ja(m),cgHeight:m.cgHeight}}:void 0,a=$0(r,t.density,t.envelope,o),s=P0(r,n,t),i=G0(r,t),c=t.states??[],l=new Map;return{...a,...n,...s,...i,get failure(){return a.failure},values:new Map,states:c,stateOf:m=>m===void 0?c[0]??null:c.find(d=>d.id===m)??null,platformAt:m=>{let d=`${m.speedKmh}|${m.ayG}|${m.axG}`,p=l.get(d);if(p!==void 0)return p;let f=n.poseAt(m),h=n.dynInput(),b=null;if(f&&h)try{b=z0(h,m,f,a.contexts())}catch{b=null}return l.set(d,b),b}}}var FV=["x","y","z"],wV=/^(line|plane)\((-?\d+),(-?\d+)\)([uv]?)$/,zF=Math.PI/18e3,YF=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],WF=(e,t)=>[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]],CV=e=>Math.hypot(e[0],e[1],e[2]),j0=(e,t)=>[e[0]*t,e[1]*t,e[2]*t];function U0(e){let t=CV(e);return t>1e-9?j0(e,1/t):null}function TV(e,t){let r=e*zF,n=t*zF;return[Math.cos(n)*Math.cos(r),Math.cos(n)*Math.sin(r),Math.sin(n)]}function kr(e){let t=e.lastIndexOf(".");if(t<0)return null;let r=wV.exec(e.slice(t+1));if(!r)return null;let n=r[1];return n==="line"!=(r[4]==="")?null:{point:e.slice(0,t),shape:{kind:n,dir:TV(Number(r[2]),Number(r[3]))},coord:n==="line"?"along":r[4]}}function jF(e){let t=U0(WF([0,0,1],e))??[1,0,0];(t[0]<-1e-9||Math.abs(t[0])<=1e-9&&t[1]<0)&&(t=j0(t,-1));let r=U0(WF(e,t))??[0,1,0];return(r[2]<-1e-9||Math.abs(r[2])<=1e-9&&r[1]<0)&&(r=j0(r,-1)),[t,r]}function X0(e){if(e.coord==="along")return e.shape.dir;let[t,r]=jF(e.shape.dir);return e.coord==="u"?t:r}function UF(e,t){let r=kr(t);if(!r)return;let n=FV.map(u=>e[`${r.point}.${u}`]);if(n.some(u=>!u))return;let o=X0(r),a=[0,1,2].filter(u=>Math.abs(o[u])>1e-12),s=u=>n.map(m=>m.read(u)),i=n[0],c=a.map(u=>n[u].supersededBy).find(Boolean),l=i.label.replace(/ x$/,"");return{id:t,group:i.group,label:r.coord==="along"?`${l} along its line`:`${l} in its plane, ${r.coord}`,...i.scope?{scope:i.scope}:{},unit:i.unit,defaultSpan:i.defaultSpan,read:u=>YF(s(u),o),write:(u,m)=>{let d=s(u),p=m-YF(d,o),f=u;for(let h of a)f=n[h].write(f,d[h]+p*o[h]);return f},...c?{supersededBy:c}:{}}}var Mp=["x","y","z"];var PV=/^(?:hp\.(?:front|rear)\.\w+|(?:heave|roll)\.(?:front|rear)\.(?:outer|inner|anchor))$/;function Dc(e){let t=e.lastIndexOf("."),r=e.slice(0,t);if(t<0||!PV.test(r))return null;let n=e.slice(t+1);if(n==="x"||n==="y"||n==="z")return{point:r,axis:n};let o=kr(e);return o?{point:r,axis:o.coord}:null}var Ec="*";function q0(e){let t={sum:"summed",min:"lowest",max:"highest",distance:"by length",harmonic:"overall"};return e?.across?`all courses, ${t[e.across]}`:"all courses"}var Q0=e=>e?.reads==="speed"||e?.reads==="operating",Z0=e=>e?.reads==="lateral"||e?.reads==="operating";function Co(e){if(!e)return"";let t=[];return e.speed!==void 0&&Number.isFinite(e.speed)&&t.push(`v${e.speed}`),e.ayG!==void 0&&Number.isFinite(e.ayG)&&t.push(`a${e.ayG}`),e.courseId&&t.push(`c${e.courseId}`),e.stateId&&t.push(`s${e.stateId}`),t.join(",")}function Sp(e,t){return e?.appliesAt?t.find(r=>!e.appliesAt(r)):t[0]}function es(e,t,r){let n=r?.stateId?e.stateOf(r.stateId):Sp(t,e.states)??null;return n&&!t.appliesAt?.(n)?n:null}function St(e,t,r){let n=`${t.id}@${Co(r)}`,o=e.values.get(n);if(o!==void 0)return o;let a;try{a=r?.courseId===Ec&&t.reads==="course"?LV(e,t,r):r?.stateId===Rr&&t.reads==="state"?DV(e,t,r):t.read(e,r)}catch{a=NaN}return e.values.set(n,a),a}function LV(e,t,r){if(!t.across)return NaN;let n=e.courses();if(!n.length)return NaN;let o=n.map(s=>{let i={...r,courseId:s.id};return{v:St(e,t,i),length:e.course(i)?.track.length??NaN}});if(o.some(s=>!Number.isFinite(s.v)))return NaN;if(t.across==="sum")return o.reduce((s,i)=>s+i.v,0);if(t.across==="min")return Math.min(...o.map(s=>s.v));if(t.across==="max")return Math.max(...o.map(s=>s.v));let a=o.reduce((s,i)=>s+i.length,0);return a>0?t.across==="harmonic"?a/o.reduce((s,i)=>s+i.length/i.v,0):o.reduce((s,i)=>s+i.v*i.length,0)/a:NaN}function DV(e,t,r){let n=t.appliesAt?e.states.filter(i=>!t.appliesAt(i)):e.states;if(!t.acrossStates||!n.length)return NaN;let o=n.map(i=>({v:St(e,t,{...r,stateId:i.id}),w:i.weight,s:i})),a=t.appliesAt?o.filter(i=>Number.isFinite(i.v)||!e.poseAt(i.s)):o;if(!a.length||a.some(i=>!Number.isFinite(i.v)))return NaN;if(t.acrossStates==="max")return Math.max(...a.map(i=>i.v));if(t.acrossStates==="min")return Math.min(...a.map(i=>i.v));if(t.acrossStates==="span")return Math.max(...a.map(i=>i.v))-Math.min(...a.map(i=>i.v));let s=a.reduce((i,c)=>i+c.w,0);return s>0?a.reduce((i,c)=>i+c.v*c.w,0)/s:NaN}function J0(e){let t={mean:"weighted mean",max:"highest",min:"lowest",span:"span"};return e?.acrossStates?`every state, ${t[e.acrossStates]}`:"every state"}function et(e){return`${e.quantity??e.groupShort??e.group} \xB7 ${e.label}`}var EV={front:"Front",rear:"Rear"},Ic={heave:0,pitch:0,roll:0,steer:0};function XF(e,t){let r=0,n=0;for(let o=1;o<e.length;o++){let a=e[o]-e[o-1];if(Math.abs(a)<1e-9)continue;let s=(t[o]-t[o-1])/a;r+=s*s,n++}return n?Math.sqrt(r/n):NaN}function IV(e,t){let r=0;for(let n=1;n<e.length;n++){let o=e[n]-e[n-1];Math.abs(o)<1e-9||(r=Math.max(r,Math.abs((t[n]-t[n-1])/o)))}return r}var _c=e=>e.length?Math.max(...e)-Math.min(...e):NaN;function qF(e){let t=(e??[]).filter(Number.isFinite);if(!t.length)return NaN;let r=t.reduce((n,o)=>n+o,0)/t.length;return Math.abs(r)>0?(Math.max(...t)-Math.min(...t))/Math.abs(r):NaN}function QF(e,t){if(!e.length)return;let r=0;for(let n=1;n<e.length;n++)Math.abs(e[n])<Math.abs(e[r])&&(r=n);return t[r]}function ts(e,t,r){let n=e.stateOf(t?.stateId),o=n?e.poseAt(n):null;return o?r(o):NaN}var Nc=(e,t)=>`${e==="front"?"F":"R"}${t}`,ZF=e=>e==="L"?"R":"L";function JF(e){let t=EV[e],r=x=>`kin.${e}.${x}`,n=(x,M)=>{let A=x.sweep(e);return A?{x:A.samples.map(w=>w.travel),y:A.samples.map(M)}:{x:[],y:[]}},o=x=>e==="front"?x.vehicle.front:x.vehicle.rear,a=x=>x.params[e==="front"?"heaveFrontDesign":"heaveRearDesign"],s=x=>x.params[e==="front"?"arbFrontDesign":"arbRearDesign"],i=e==="front"?"the front axle":"the rear axle";function c(x){return o(x).config.actuation==="decoupled"?`${i} is decoupled, with no corner damper \u2014 read its heave and roll elements`:null}function l(x){let M=a(x);return M&&M.design.kind!=="none"?null:`${i} has no heave element`}function u(x){let M=a(x);return M?.design.kind==="coil"&&M.linkage?null:`${i} has no heave element on a linkage`}function m(x){let M=s(x);return M&&M.design.kind!=="none"?null:`${i} has no roll element`}function d(x){let M=s(x);return M?.linkage&&M.design.kind!=="none"&&M.design.kind!=="direct"?null:`${i} has no roll element on a linkage`}let p=x=>{if(u(x.car))return null;let M=x.sweep(e);return M?sf(o(x.car),a(x.car).linkage,M.samples):null},f=x=>{if(d(x.car))return null;let M=x.sweep(e);if(!M)return null;let A=s(x.car),w=nf(o(x.car),A.linkage,A.design.kind,M.samples),C=w.atDesign<0?-1:1;return{travel:w.travel,ratio:w.ratio.map(T=>T*C),atDesign:w.atDesign*C}},h=x=>x.readout(Ic)?.[e],b=x=>x.readoutAtTravel(e,x.envelope.travelMax),g=x=>{let M=n(x,A=>A.metrics.camber);return M.x.length?{key:r("camberGain"),title:`${t} camber vs travel`,xLabel:"travel [mm]",yLabel:"camber [\xB0]",...M}:null},y=x=>{let M=n(x,A=>A.metrics.toe);return M.x.length?{key:r("bumpSteer"),title:`${t} toe vs travel`,xLabel:"travel [mm]",yLabel:"toe [\xB0]",...M}:null},R=[{id:r("rcStatic"),group:`${t} roll centre`,label:"static height",unit:"mm",scale:30,scope:e,cost:"cheap",read:x=>x.rcRoll(e)?.rc[0]?.heightAboveGround??NaN},{id:r("rcHeaveWorst"),group:`${t} roll centre`,label:"worst migration vs travel",unit:"mm/mm",scale:.5,scope:e,cost:"cheap",read:x=>{let M=x.rcHeave(e);return M?IV(M.at,M.rc.map(A=>A.height)):NaN},curve:x=>{let M=x.rcHeave(e);return M?{key:r("rcHeaveWorst"),title:`${t} roll-centre height vs wheel travel`,xLabel:"travel [mm]",yLabel:"RC height [mm]",x:M.at,y:M.rc.map(A=>A.height)}:null}},{id:r("rcRollSpan"),group:`${t} roll centre`,label:"height span over the roll envelope",unit:"mm",scale:15,scope:e,cost:"cheap",read:x=>{let M=x.rcRoll(e);return M?_c(M.rc.map(A=>A.height)):NaN},curve:x=>{let M=x.rcRoll(e);return M?{key:r("rcRollSpan"),title:`${t} roll-centre height vs body roll`,xLabel:"roll [\xB0]",yLabel:"RC height [mm]",x:M.at,y:M.rc.map(A=>A.height)}:null}},{id:r("rcLateralSpan"),group:`${t} roll centre`,label:"lateral migration over roll",unit:"mm",scale:50,scope:e,cost:"cheap",read:x=>{let M=x.rcRoll(e);return M?_c(M.rc.map(A=>A.lateral)):NaN},curve:x=>{let M=x.rcRoll(e);return M?{key:r("rcLateralSpan"),title:`${t} roll-centre lateral position vs body roll`,xLabel:"roll [\xB0]",yLabel:"RC lateral [mm]",x:M.at,y:M.rc.map(A=>A.lateral)}:null}},{id:r("minSinAngle"),group:`${t} roll centre`,label:"construction conditioning (min sinAngle)",unit:"-",scale:.04,scope:e,cost:"cheap",read:x=>{let M=x.rcHeave(e),A=x.rcRoll(e);return!M||!A?NaN:Math.min(...M.rc.map(w=>w.sinAngle),...A.rc.map(w=>w.sinAngle))},curve:x=>{let M=x.rcHeave(e);return M?{key:r("minSinAngle"),title:`${t} construction conditioning vs travel`,xLabel:"travel [mm]",yLabel:"sinAngle",x:M.at,y:M.rc.map(A=>A.sinAngle)}:null}},{id:r("fvsaLength"),group:`${t} roll centre`,label:"front-view swing-arm length",unit:"mm",scale:500,scope:e,cost:"readout",read:x=>h(x)?.fvsaLength??NaN},{id:r("complianceSteer"),group:`${t} compliance`,label:"compliance steer",unit:"\xB0/kN lateral",scale:.05,scope:e,cost:"readout",read:x=>(x.compliance(e)?.toePerFy??0)*1e3},{id:r("complianceCamber"),group:`${t} compliance`,label:"compliance camber",unit:"\xB0/kN lateral",scale:.05,scope:e,cost:"readout",read:x=>(x.compliance(e)?.camberPerFy??0)*1e3},{id:r("complianceSteerLong"),group:`${t} compliance`,label:"compliance steer under braking",unit:"\xB0/kN longitudinal",scale:.05,scope:e,cost:"readout",read:x=>(x.compliance(e)?.toePerFx??0)*1e3},{id:r("steeringCompliance"),group:`${t} compliance`,label:"steer given back under aligning torque",unit:"\xB0/100 N\xB7m",scale:.2,scope:e,cost:"readout",read:x=>(x.compliance(e)?.toePerMz??0)*1e5},{id:r("staticCamber"),group:`${t} camber & toe`,label:"static camber",unit:"\xB0",scale:1,scope:e,cost:"cheap",read:x=>{let M=x.solveAt(e,0);return M?M.metrics.camber:NaN}},{id:r("staticToe"),group:`${t} camber & toe`,label:"static toe",unit:"\xB0",scale:.5,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.toe??NaN},{id:r("camberGainDesign"),group:`${t} camber & toe`,label:"camber gain in bump",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.camberGain??NaN,curve:x=>g(x)},{id:r("rollCamber"),group:`${t} camber & toe`,label:"camber gain in roll",unit:"\xB0/\xB0",scale:.2,scope:e,cost:"readout",read:x=>h(x)?.rollCamber??NaN},{id:r("rollCamberRecovery"),group:`${t} camber & toe`,label:"camber recovery in roll",unit:"%",scale:20,scope:e,cost:"readout",read:x=>h(x)?.camberRecovery??NaN},{id:r("bumpSteerDesign"),group:`${t} camber & toe`,label:"bump steer at design",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.bumpSteer??NaN,curve:x=>y(x)},{id:r("rollSteer"),group:`${t} camber & toe`,label:"roll steer",unit:"\xB0/\xB0",scale:.1,scope:e,cost:"readout",read:x=>h(x)?.rollSteer??NaN},{id:r("bumpSteer"),group:`${t} camber & toe`,label:"bump steer, RMS over the travel",unit:"\xB0/mm",scale:.02,scope:e,cost:"cheap",read:x=>{let M=n(x,A=>A.metrics.toe);return M.x.length?XF(M.x,M.y):NaN},curve:x=>y(x)},{id:r("camberGain"),group:`${t} camber & toe`,label:"camber gain, RMS over the travel",unit:"\xB0/mm",scale:.02,scope:e,cost:"cheap",read:x=>{let M=n(x,A=>A.metrics.camber);return M.x.length?XF(M.x,M.y):NaN},curve:x=>g(x)},{id:r("camberSpan"),group:`${t} camber & toe`,label:"camber range over travel",unit:"\xB0",scale:1,scope:e,cost:"cheap",read:x=>_c(n(x,M=>M.metrics.camber).y)},{id:r("toeSpan"),group:`${t} camber & toe`,label:"toe range over travel",unit:"\xB0",scale:.5,scope:e,cost:"cheap",read:x=>_c(n(x,M=>M.metrics.toe).y)},{id:r("camberRecovery"),group:`${t} camber & toe`,label:"outer camber at limit roll",unit:"\xB0",scale:2,scope:e,cost:"cheap",read:x=>{let M=x.solveAt(e,x.travelAtRoll(e,x.envelope.rollAtLimitDeg)),A=x.solveAt(e,0);return!M||!A?NaN:Math.abs(M.metrics.camber-A.metrics.camber+x.envelope.rollAtLimitDeg)}},{id:r("stateCamberOuter"),group:`${t} camber & toe`,label:"outer camber to the road at a state",unit:"\xB0",scale:1,scope:e,cost:"cheap",reads:"state",acrossStates:"mean",read:(x,M)=>ts(x,M,A=>A.camber[Nc(e,A.outer)])},{id:r("stateCamberInner"),group:`${t} camber & toe`,label:"inner camber to the road at a state",unit:"\xB0",scale:1,scope:e,cost:"cheap",reads:"state",acrossStates:"mean",read:(x,M)=>ts(x,M,A=>A.camber[Nc(e,ZF(A.outer))])},{id:r("stateToeOuter"),group:`${t} camber & toe`,label:"outer toe change at a state",unit:"\xB0",scale:.2,scope:e,cost:"cheap",reads:"state",acrossStates:"mean",read:(x,M)=>ts(x,M,A=>A.corners[Nc(e,A.outer)].bumpToe)},{id:r("caster"),group:`${t} upright`,label:"caster",unit:"\xB0",scale:5,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.caster??NaN},{id:r("kpi"),group:`${t} upright`,label:"kingpin inclination",unit:"\xB0",scale:5,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.kpi??NaN},{id:r("scrubRadius"),group:`${t} upright`,label:"scrub radius",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.scrubRadius??NaN},{id:r("mechanicalTrail"),group:`${t} upright`,label:"mechanical trail",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.mechanicalTrail??NaN},{id:r("kingpinOffset"),group:`${t} upright`,label:"kingpin offset at hub height",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.kingpinOffset??NaN},{id:r("casterOffset"),group:`${t} upright`,label:"caster offset at hub height",unit:"mm",scale:10,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.casterOffset??NaN},{id:r("steeringArm"),group:`${t} upright`,label:"steering arm",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.steeringArm??NaN},{id:r("casterGain"),group:`${t} upright`,label:"caster gain in bump",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.casterGain??NaN},{id:r("kpiGain"),group:`${t} upright`,label:"kingpin inclination gain in bump",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.kpiGain??NaN},{id:r("scrubGain"),group:`${t} upright`,label:"scrub radius gain in bump",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:x=>h(x)?.scrubGain??NaN},{id:r("trailGain"),group:`${t} upright`,label:"mechanical trail gain in bump",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:x=>h(x)?.trailGain??NaN},{id:r("motionRatio"),group:`${t} rates`,label:"motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let M=x.sweep(e);return M?QF(M.samples.map(A=>A.travel),M.samples.map(A=>A.metrics.motionRatio??NaN))??NaN:NaN},curve:x=>{if(c(x.car))return null;let M=n(x,A=>A.metrics.motionRatio??NaN);return M.x.length?{key:r("motionRatio"),title:`${t} motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",...M}:null}},{id:r("mrSpread"),group:`${t} rates`,label:"motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let M=x.sweep(e);if(!M)return NaN;let A=M.samples.map(C=>C.metrics.motionRatio??NaN).filter(Number.isFinite);if(!A.length)return NaN;let w=A.reduce((C,T)=>C+T,0)/A.length;return w>0?(Math.max(...A)-Math.min(...A))/w:NaN}},{id:r("wheelRate"),group:`${t} rates`,label:"wheel rate at design",unit:"N/mm",scale:10,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let M=x.sweep(e);return M?QF(M.samples.map(A=>A.travel),M.samples.map(A=>A.metrics.wheelRate??NaN))??NaN:NaN}},{id:r("heaveMotionRatio"),group:`${t} rates`,label:"heave element motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:u,read:x=>p(x)?.atDesign??NaN,curve:x=>{let M=p(x);return M?{key:r("heaveMotionRatio"),title:`${t} heave element motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",x:M.travel,y:M.ratio}:null}},{id:r("heaveMrSpread"),group:`${t} rates`,label:"heave element motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:u,read:x=>qF(p(x)?.ratio)},{id:r("heaveWheelRate"),group:`${t} rates`,label:"heave element wheel rate at design",unit:"N/mm",scale:10,scope:e,cost:"cheap",unavailable:l,read:x=>l(x.car)||!x.sweep(e)?NaN:Ta(x.car.vehicle,x.car.params)[e]??NaN},{id:r("rollMotionRatio"),group:`${t} rates`,label:"roll element motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:d,read:x=>f(x)?.atDesign??NaN,curve:x=>{let M=f(x);return M?{key:r("rollMotionRatio"),title:`${t} roll element motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",x:M.travel,y:M.ratio}:null}},{id:r("rollMrSpread"),group:`${t} rates`,label:"roll element motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:d,read:x=>qF(f(x)?.ratio)},{id:r("rollWheelRate"),group:`${t} rates`,label:"roll element wheel rate at design",unit:"N/mm",scale:10,scope:e,cost:"cheap",unavailable:m,read:x=>m(x.car)||!x.sweep(e)?NaN:oo(x.car.vehicle,x.car.params)[e]??NaN},{id:r("ucaAxisLength"),group:`${t} package`,label:"upper arm pivot-axis length",unit:"mm",scale:80,scope:e,cost:"geometry",read:x=>x.axisLength(e,"uca")},{id:r("lcaAxisLength"),group:`${t} package`,label:"lower arm pivot-axis length",unit:"mm",scale:80,scope:e,cost:"geometry",read:x=>x.axisLength(e,"lca")},{id:r("linkLength"),group:`${t} package`,label:"tie/toe link length",unit:"mm",scale:100,scope:e,cost:"geometry",read:x=>x.linkLength(e)},{id:r("trackScrubRate"),group:`${t} package`,label:"track scrub rate",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:x=>x.readout(Ic)?.[e].trackScrubRate??NaN},{id:r("trackChange"),group:`${t} package`,label:"track change at full bump",unit:"mm",scale:2,scope:e,cost:"readout",read:x=>b(x)?.trackChange??NaN},{id:r("stateTravelOuter"),group:`${t} package`,label:"outer wheel travel at a state",unit:"mm",scale:10,scope:e,cost:"cheap",reads:"state",acrossStates:"max",read:(x,M)=>ts(x,M,A=>A.corners[Nc(e,A.outer)].travel)},{id:r("stateTravelInner"),group:`${t} package`,label:"inner wheel travel at a state",unit:"mm",scale:10,scope:e,cost:"cheap",reads:"state",acrossStates:"min",read:(x,M)=>ts(x,M,A=>A.corners[Nc(e,ZF(A.outer))].travel)},{id:r("damperStroke"),group:`${t} package`,label:"damper stroke over the travel",unit:"mm",scale:20,scope:e,cost:"cheap",unavailable:c,read:x=>c(x.car)?NaN:_c(n(x,M=>M.metrics.damperLength).y),curve:x=>{if(c(x.car))return null;let M=n(x,A=>A.metrics.damperLength);return M.x.length?{key:r("damperStroke"),title:`${t} damper length vs travel`,xLabel:"travel [mm]",yLabel:"length [mm]",...M}:null}}];e==="front"&&R.push({id:r("camberPerSteer"),group:`${t} camber & toe`,label:"camber change with steer",unit:"\xB0/\xB0",scale:.05,scope:"front",cost:"readout",read:x=>h(x)?.camberPerSteer??NaN},{id:r("steerJacking"),group:`${t} upright`,label:"corner rise per degree of steer",unit:"mm/\xB0",scale:.05,scope:"front",cost:"readout",read:x=>h(x)?.steerJacking??NaN}),e==="front"?R.push({id:r("antiDive"),group:`${t} anti geometry`,label:"anti-dive",unit:"%",scale:20,scope:"front",cost:"readout",read:x=>x.readout(Ic)?.front.antiDive??NaN}):R.push({id:r("antiSquat"),group:`${t} anti geometry`,label:"anti-squat (driving)",unit:"%",scale:20,scope:"rear",cost:"readout",read:x=>x.readout(Ic)?.rear.antiSquat??NaN},{id:r("antiLift"),group:`${t} anti geometry`,label:"anti-lift (braking)",unit:"%",scale:20,scope:"rear",cost:"readout",read:x=>x.readout(Ic)?.rear.antiLift??NaN});let k=x=>{let M=x.slice(t.length+1);return M.charAt(0).toUpperCase()+M.slice(1)};return[...new Set(R.map(x=>x.group))].flatMap(x=>R.filter(M=>M.group===x)).map(x=>({...x,quantity:`${t} \xB7 ${k(x.group)}`}))}function ew(e,t){let r=e.steer();if(!r)return NaN;let n=r.filter(a=>Number.isFinite(a.ackermannPct)&&a.inner>.3&&a.outer>.3);return n.length?n.reduce((a,s)=>t==="centre"?s.inner<a.inner?s:a:s.inner>a.inner?s:a).ackermannPct:NaN}var _V=[{id:"kin.front.ackermannCentre",group:"Steering",label:"Ackermann near centre",unit:"%",scale:25,scope:"front",cost:"cheap",read:e=>ew(e,"centre"),curve:e=>{let t=e.steer();if(!t)return null;let r=t.filter(n=>Number.isFinite(n.ackermannPct)&&n.inner>.3&&n.outer>.3);return r.length?{key:"kin.front.ackermann",title:"Ackermann vs steer",xLabel:"inner wheel steer [\xB0]",yLabel:"Ackermann [%]",x:r.map(n=>n.inner),y:r.map(n=>n.ackermannPct)}:null}},{id:"kin.front.ackermannLock",group:"Steering",label:"Ackermann at lock",unit:"%",scale:25,scope:"front",cost:"cheap",read:e=>ew(e,"lock")},{id:"kin.front.lockInner",group:"Steering",label:"inner wheel angle at full rack",unit:"\xB0",scale:5,scope:"front",cost:"cheap",read:e=>{let t=e.steer();return t?.length?Math.max(...t.map(r=>r.inner)):NaN}}],NV=[{id:"kin.car.trackFront",group:"Whole car",label:"front track",unit:"mm",scale:50,scope:"front",cost:"geometry",read:e=>2*e.car.vehicle.front.hardpoints.wheelCenter[1]},{id:"kin.car.trackRear",group:"Whole car",label:"rear track",unit:"mm",scale:50,scope:"rear",cost:"geometry",read:e=>2*e.car.vehicle.rear.hardpoints.wheelCenter[1]},{id:"kin.car.stateRoll",group:"Whole car",label:"body roll at a state",unit:"\xB0",scale:1,scope:"car",cost:"cheap",reads:"state",acrossStates:"max",read:(e,t)=>ts(e,t,r=>Math.abs(r.rollDeg))},{id:"kin.car.wheelbaseChange",group:"Whole car",label:"wheelbase change at full bump",unit:"mm",scale:2,scope:"car",cost:"readout",read:e=>{let t=e.readoutAtTravel("front",e.envelope.travelMax),r=e.readoutAtTravel("rear",e.envelope.travelMax);return t&&r?t.longitudinal-r.longitudinal:NaN}}],ey=[...JF("front"),...JF("rear"),..._V,...NV];var OV={front:"Front",rear:"Rear"};function rw(e){return e.chassis?.boxes.length?null:"This suspension has no mockup volumes to keep its parts out of; draw one under Kinematics \u203A Chassis"}function tw(e){let t=OV[e],r=s=>`kin.${e}.${s}`,n=e==="front"?"over the travel and the rack":"over the travel",o=(s,i)=>{let c=s.keepOuts(e);return c?i(c)??NaN:NaN},a={group:`${t} keep-outs`,quantity:`${t} \xB7 Keep-outs`,scope:e,cost:"readout"};return[{...a,id:r("chassisClearance"),label:`least clearance to the chassis volumes ${n}`,unit:"mm",scale:5,unavailable:s=>rw(s.vehicle),read:s=>o(s,i=>i.chassis?.distance)},{...a,id:r("ballJointAngle"),label:`largest ball-joint angle ${n}`,unit:"\xB0",scale:1,read:s=>o(s,i=>i.ballJoint?.angle)},{...a,id:r("rodEndAngle"),label:`largest rod-end angle ${n}`,unit:"\xB0",scale:1,read:s=>o(s,i=>i.rodEnd?.angle)}]}var ty=[...tw("front"),...tw("rear")];var iw={front:"Front",rear:"Rear"},nw=e=>Ao("side",e),VV=e=>Ao("drive",e)&&Ao("brake",e)?"neither brakes nor drives":null;function BV(e,t,r,n){let o=es(e,t,r),a=o?e.tyreAt(o):null;return a?n(a):NaN}function rs(e,t){let r={...e,read:(n,o)=>BV(n,r,o,t)};return r}var ow=e=>e?100*e.lossCamber:NaN,aw=e=>e&&!e.lifted?e.camber-e.wants:NaN;function sw(e){let t=iw[e],r=s=>`tyre.${e}.${s}`,n={group:`${t} tyre`,quantity:`${t} \xB7 Tyre`,scope:e,cost:"cheap",reads:"state",acrossStates:"mean"},o={...n,appliesAt:nw,unavailable:s=>rp(s.params,e)},a=[rs({...o,id:r("camberErrorOuter"),label:"camber error at the outer wheel",unit:"\xB0",scale:.5},s=>aw(s.side(e)?.wheels[0])),rs({...o,id:r("camberErrorInner"),label:"camber error at the inner wheel",unit:"\xB0",scale:.5},s=>aw(s.side(e)?.wheels[1])),rs({...o,id:r("sideLossCamber"),label:"side grip lost to camber",unit:"%",scale:1},s=>ow(s.side(e))),rs({...n,appliesAt:nw,id:r("sideLossToe"),label:"side grip lost to the toe split",unit:"%",scale:1},s=>100*s.toeLoss(e)),rs({...n,appliesAt:VV,unavailable:s=>k0(s.params,e),id:r("longLossCamber"),label:"drive and brake grip lost to camber",unit:"%",scale:1},s=>ow(s.long(e)))];return e==="front"&&a.push(rs({...n,appliesAt:s=>Ao("ackermann",s),id:r("ackermannError"),label:"Ackermann against the tyre",unit:"%",scale:25},s=>s.ackermann())),a}var ry=[...sw("front"),...sw("rear")],$V=/^tyre\.(front|rear)\.(camberErrorOuter|camberErrorInner|sideLossCamber|longLossCamber)$/;function ny(e,t){let r=new Map,n=a=>a.name.charAt(0).toLowerCase()+a.name.slice(1),o=a=>`${a>0?"+":a<0?"\u2212":""}${Math.abs(a).toFixed(1)}\xB0`;for(let{m:a,at:s}of t){let i=$V.exec(a.id);if(!i)continue;let c=i[1],l=i[2]==="longLossCamber",u=s?.stateId==="*"?e.states.filter(m=>!a.appliesAt?.(m)):[es(e,a,s)].filter(m=>!!m);for(let m of u){let d=`${c}|${m.id}|${l}`;if(r.has(d))continue;let p=e.tyreAt(m),f=p?l?p.long(c):p.side(c):null;if(!f)continue;let{lo:h,hi:b,stated:g}=f.range,y=g?`the ${o(h)} \u2026 ${o(b)} its data covers`:`the \xB1${b.toFixed(0)}\xB0 read without a stated range`,R=M=>l?M===0?"left":"right":M===0?"outer":"inner",k=f.wheels.findIndex(M=>M.atEdge),v=f.wheels.findIndex(M=>M.outside&&!M.lifted),x=[];k>=0&&x.push(`the ${iw[c].toLowerCase()} ${R(k)} tyre wants ${o(f.wheels[k].wants)}, the edge of ${y}, and may want more`),v>=0&&x.push(`the ${R(v)} wheel has ${o(f.wheels[v].camber)}, past it, and is read at ${o(f.wheels[v].read)}`),x.length&&r.set(d,`In the ${n(m)} ${x.join("; ")}.`)}}return[...r.values()]}function oy(e,t){let r=e.appliesAt?.(t);return r?`is read at ${t.name}, which ${r}`:null}var GV={front:"Front",rear:"Rear"};function KV(e,t,r,n){let o=es(e,t,r),a=o?e.platformAt(o):null;return(a?n(a):null)??NaN}function Yt(e,t){let r={...e,read:(n,o)=>KV(n,r,o,t)};return r}var ay={cost:"cheap",reads:"state"},HV={unavailable:e=>xp(e.params)};function cw(e){let t=GV[e],r=o=>`platform.${e}.${o}`,n={...ay,group:`${t} platform`,quantity:`${t} \xB7 Platform`,scope:e};return[Yt({...n,id:r("rideHeight"),label:"ride height at a state",unit:"mm",scale:5,acrossStates:"min"},o=>o[e].height),Yt({...n,id:r("toBumpStop"),label:"travel left to the bump stop",unit:"mm",scale:5,acrossStates:"min",unavailable:o=>Tc(o.vehicle,o.params,e,"bump")},o=>o[e].toBump),Yt({...n,id:r("toDroopStop"),label:"travel left to the droop stop",unit:"mm",scale:5,acrossStates:"min",unavailable:o=>Tc(o.vehicle,o.params,e,"droop")},o=>o[e].toDroop)]}var Ap={...ay,group:"Platform",scope:"car"},Oc={...ay,...HV,group:"Aero platform",groupShort:"Aero",scope:"car"},sy=[...cw("front"),...cw("rear"),Yt({...Ap,id:"platform.rake",label:"rake at a state",unit:"\xB0",scale:.2,acrossStates:"span"},e=>e.rakeDeg),Yt({...Ap,id:"platform.pitch",label:"pitch at a state",unit:"\xB0",scale:.2,acrossStates:"max"},e=>e.pitchDeg),Yt({...Ap,id:"platform.roll",label:"body roll at a state",unit:"\xB0",scale:.2,acrossStates:"max"},e=>e.rollDeg),Yt({...Ap,id:"platform.groundClearance",label:"ground clearance at a state",unit:"mm",scale:5,acrossStates:"min",unavailable:e=>Y0(e.vehicle)},e=>e.clearance?.height),Yt({...Oc,id:"platform.balance",label:"balance at a state",unit:"%",scale:1,acrossStates:"span"},e=>e.aero?.balance),Yt({...Oc,id:"platform.clA",label:"downforce Cl\xB7A at a state",unit:"m\xB2",scale:.1,acrossStates:"mean"},e=>e.aero?.clA),Yt({...Oc,id:"platform.cdA",label:"drag Cd\xB7A at a state",unit:"m\xB2",scale:.05,acrossStates:"mean"},e=>e.aero?.cdA),Yt({...Oc,id:"platform.dataMargin",label:"margin to the model\u2019s data",unit:"mm",scale:5,acrossStates:"min"},e=>e.aero?.dataMargin),Yt({...Oc,id:"platform.loopMargin",label:"aero-elastic margin, 1 \u2212 loop gain",unit:"-",scale:.1,acrossStates:"min"},e=>e.aero?.loopMargin)];var lw={understeer:"operating",yawFreq:"speed",yawZeta:"speed",yawStiffness:"operating",steeringTorque:"operating",steeringTorqueGradient:"operating"};function ot(e,t,r,n="cheap"){let o=Ub[e];if(!o)throw new Error(`no DYN_METRIC "${e}"`);return{id:`dyn.${e}`,group:t,label:o.label,unit:o.unit,scale:r,scope:"car",cost:n,...lw[e]?{reads:lw[e]}:{},read:(a,s)=>{let i=a.dynInput(),c=a.dynCtx(s);return i&&c?o.compute(i,c):NaN}}}var zV=[ot("understeer","Handling \u2014 balance",.1),ot("tlltdFront","Handling \u2014 balance",5),ot("rollStiffFront","Handling \u2014 balance",5)],YV=[ot("yawFreq","Handling \u2014 response",.5),ot("yawZeta","Handling \u2014 response",.2),ot("stabilitySpeed","Handling \u2014 response",50),ot("yawStiffness","Handling \u2014 response",2e4,"trim")],WV=[ot("steeringTorque","Steering feel",1,"trim"),ot("steeringTorqueGradient","Steering feel",2,"trim")],jV=[ot("rollGradient","Ride & body",.5),ot("pitchGradient","Ride & body",.5),ot("rideFreqFront","Ride & body",.5),ot("rideFreqRear","Ride & body",.5),ot("rollFreq","Ride & body",.5),ot("pitchFreq","Ride & body",.5),ot("zetaFront","Ride & body",.2),ot("zetaRear","Ride & body",.2)],UV=[{id:"dyn.reserveStabil",group:"What the car has left",label:"Yaw stability reserve",unit:"N\xB7m",scale:200,scope:"car",cost:"trim",reads:"operating",read:(e,t)=>e.reserves("operating",t)?.stabil??NaN},{id:"dyn.reserveAgil",group:"What the car has left",label:"Yaw agility reserve",unit:"N\xB7m",scale:200,scope:"car",cost:"trim",reads:"operating",read:(e,t)=>e.reserves("operating",t)?.agil??NaN},{id:"dyn.limitBalance",group:"What the car has left",label:"Limit balance (+US / \u2212OS)",unit:"-",scale:.5,scope:"car",cost:"trim",reads:"speed",read:(e,t)=>e.reserves("limit",t)?.rel??NaN}],XV=[{id:"dyn.ymdMaxAy",group:"Yaw-moment diagram",label:"Max lateral acceleration",unit:"g",scale:.2,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymd(t)?.maxAy??NaN},{id:"dyn.ymdStability",group:"Yaw-moment diagram",label:"Stability \u2202CN/\u2202\u03B2 at the origin",unit:"1/rad",scale:5,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymd(t)?.stability??NaN},{id:"dyn.ymdControl",group:"Yaw-moment diagram",label:"Control \u2202CN/\u2202\u03B4 at the origin",unit:"1/rad",scale:.5,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymd(t)?.control??NaN},{id:"dyn.trimAy",group:"Yaw-moment diagram",label:"Trim limit \u2014 the fastest corner it can hold",unit:"g",scale:.2,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.ay??NaN},{id:"dyn.trimBeta",group:"Yaw-moment diagram",label:"Body slip at the trim limit",unit:"\xB0",scale:2,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.betaDeg??NaN},{id:"dyn.trimDelta",group:"Yaw-moment diagram",label:"Steer at the trim limit",unit:"\xB0",scale:2,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.deltaDeg??NaN},{id:"dyn.trimControlFrac",group:"Yaw-moment diagram",label:"Control left at the trim limit",unit:"-",scale:.25,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.controlFrac??NaN},{id:"dyn.trimStiffnessFrac",group:"Yaw-moment diagram",label:"Yaw stiffness left at the trim limit",unit:"-",scale:.25,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.stiffnessFrac??NaN}],iy=[...zV,...YV,...WV,...jV,...UV,...XV];function qV(e,t){let r=e.lap(t),n=e.course(t);if(!r||!n)return NaN;let o=n.track.ds,a=0,s=0;for(let i=0;i<r.v.length-1;i++){let c=o[i]??0,l=.5*(r.v[i]+r.v[i+1]);c>0&&l>0&&(a+=c,s+=c/l)}return s>0?a/s:NaN}var cy=[{id:"lap.time",group:"Lap & manoeuvre",label:"Time",unit:"s",scale:.1,scope:"car",cost:"lap",reads:"course",across:"sum",read:(e,t)=>e.lap(t)?.laptime??NaN},{id:"lap.vMean",group:"Lap & manoeuvre",label:"Mean speed",unit:"km/h",scale:2,scope:"car",cost:"lap",reads:"course",across:"harmonic",read:(e,t)=>qV(e,t)*3.6},{id:"lap.vMin",group:"Lap & manoeuvre",label:"Minimum speed",unit:"km/h",scale:2,scope:"car",cost:"lap",reads:"course",across:"min",read:(e,t)=>{let r=e.lap(t);return r?Math.min(...r.v)*3.6:NaN}},{id:"lap.vMax",group:"Lap & manoeuvre",label:"Maximum speed",unit:"km/h",scale:5,scope:"car",cost:"lap",reads:"course",across:"max",read:(e,t)=>{let r=e.lap(t);return r?Math.max(...r.v)*3.6:NaN}},{id:"lap.ayPeak",group:"Lap & manoeuvre",label:"Peak lateral acceleration",unit:"g",scale:.1,scope:"car",cost:"lap",reads:"course",across:"max",read:(e,t)=>{let r=e.lap(t);return r?Math.max(...r.ay.map(Math.abs))/9.81:NaN}},{id:"lap.minStabil",group:"What the car had left",label:"Worst stability reserve",unit:"N\xB7m",scale:50,scope:"car",cost:"lap",reads:"course",across:"min",read:(e,t)=>e.lapReserve(t)?.minStabil??NaN},{id:"lap.understeerFrac",group:"What the car had left",label:"Lap fraction front-limited",unit:"-",scale:.1,scope:"car",cost:"lap",reads:"course",across:"distance",read:(e,t)=>e.lapReserve(t)?.understeerFrac??NaN},{id:"lap.beyondFrac",group:"What the car had left",label:"Beyond the tyre ellipse \u2014 a health warning, not a target",unit:"-",scale:.05,scope:"car",cost:"lap",reads:"course",across:"distance",read:(e,t)=>e.lapReserve(t)?.beyondFrac??NaN}];function QV(e,t){let r=/^(.*?)\s*\(([^)]+)\)\s*$/.exec(e);return r?{label:r[1],unit:r[2]}:{label:e,unit:t?"s":""}}function ZV(e){return e==="s"||e==="kWh"?.1:e==="km/h"?2:1}var uw=new WeakMap;function Fp(e){let t=uw.get(e);return t||(t=e.metrics.filter(Jc).map(r=>{let{label:n,unit:o}=QV(r.label,r.format==="time");return{id:`event.${e.id}.${r.key}`,group:`Events \xB7 ${e.label}`,groupShort:"Events",label:n,unit:o,scale:ZV(o),scope:"car",cost:"session",read:a=>a.session(e.id)?.[r.key]??NaN}}),uw.set(e,t),t)}var ly=za.flatMap(Fp);var wp=[...ey,...ty,...ry,...sy,...iy,...cy,...ly],ns=Object.fromEntries(wp.map(e=>[e.id,e]));var mw={all:wp,byId:ns},pw=new WeakMap;function en(e=[]){if(e.length===0)return mw;let t=pw.get(e);if(t)return t;let r=xg(e).filter(n=>!Ya(n.id)).flatMap(Fp);return t=r.length?{all:[...wp,...r],byId:{...ns,...Object.fromEntries(r.map(n=>[n.id,n]))}}:mw,pw.set(e,t),t}var Vc=180/Math.PI,os=Math.PI/180,e3=.2;function Cp(e,t){let r=H(t,e);return q(r[0]<0?Bd(r):r)}var Tp=e=>({side:Math.atan2(e[2],e[0])*Vc,plan:Math.atan2(e[1],e[0])*Vc}),Pp=(e,t)=>q([1,Math.tan(t*os),Math.tan(e*os)]),Bc=e=>Math.abs(e[0])>=e3,Lp=(e,t)=>Math.atan(t/Math.max(e,1))*Vc,Dp=(e,t)=>Math.tan(t*os)*Math.max(e,1);var Pn=["side","plan","clock","len"],er={uca:{fore:"ucaFront",aft:"ucaRear",ball:"uprightUpper"},lca:{fore:"lcaFront",aft:"lcaRear",ball:"uprightLower"}},$c={uca:"upper arm",lca:"lower arm"},t3=1,dw=(e,t)=>Cp(e[er[t].fore],e[er[t].aft]);function fw(e){let t=q(H(Vd,U(e,X(Vd,e))));return{e1:t,e2:ae(e,t)}}function uy(e,t){let r=dw(e,t);if(!Bc(r))return`the ${$c[t]}'s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it`;let n=er[t],o=cn(e[n.ball],e[n.fore],r);return Math.hypot(...H(o,e[n.ball]))>=t3?null:`the ${$c[t]}'s ball joint sits on its own pivot axis, so the arm has no length to swing on`}function tn(e,t){let r=er[t],n=e[r.ball],o=dw(e,t),a=cn(n,e[r.fore],o),s=H(a,n),i=Math.hypot(s[0],s[1],s[2]),{e1:c,e2:l}=fw(o),u=i>0?U(s,1/i):c;return{...Tp(o),clock:Math.atan2(X(u,l),X(u,c))*Vc,len:i,sFront:X(H(e[r.fore],a),o),sRear:X(H(e[r.aft],a),o)}}function my(e,t){let r=Pp(e.side,e.plan),{e1:n,e2:o}=fw(r),a=ee(U(n,Math.cos(e.clock*os)),U(o,Math.sin(e.clock*os))),s=ee(t,U(a,e.len));return{fore:ee(s,U(r,e.sFront)),aft:ee(s,U(r,e.sRear))}}function hw(e,t,r,n){let o=er[t],a={...tn(e,t),[r]:n},{fore:s,aft:i}=my(a,e[o.ball]);return{...e,[o.fore]:s,[o.aft]:i}}function bw(e,t){return t==="clock"?e.len:Math.abs(e.sFront-e.sRear)/2}function Ep(e,t,r){return t==="len"?r:Lp(bw(e,t),r)}function py(e,t,r){return t==="len"?r:Dp(bw(e,t),r)}var To=["side","plan","atY","atZ"],Po={fore:"rockerPivotA",aft:"rockerPivotB"},r3=5,gw=e=>Cp(e.rockerPivotA,e.rockerPivotB);function as(e){return Math.hypot(...H(e.rockerPivotB,e.rockerPivotA))<r3?"the rocker\u2019s two pivots are the same point, so there is no axis to describe":Bc(gw(e))?null:"the rocker\u2019s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it"}function Ln(e){let t=gw(e),r=Bc(t)?t:[1,0,0],n=e.rockerPivotA,o=ee(n,U(r,-n[0]/r[0]));return{...Tp(r),atY:o[1],atZ:o[2],sA:X(H(n,o),r),sB:X(H(e.rockerPivotB,o),r)}}function dy(e){let t=Pp(e.side,e.plan),r=[0,e.atY,e.atZ];return{a:ee(r,U(t,e.sA)),b:ee(r,U(t,e.sB))}}function yw(e,t,r){if(as(e))return e;let{a:n,b:o}=dy({...Ln(e),[t]:r});return{...e,rockerPivotA:n,rockerPivotB:o}}var xw=e=>Math.abs(e.sA-e.sB)/2;function fy(e,t,r){return t==="side"||t==="plan"?Lp(xw(e),r):r}function hy(e,t,r){return t==="side"||t==="plan"?Dp(xw(e),r):r}var rr={front:"Front",rear:"Rear"},tr=["x","y","z"],Be=(e,t)=>t==="front"?e.front:e.rear,Gc=(e,t,r)=>t==="front"?{...e,front:r}:{...e,rear:r},Rw=[{kind:"inboard",keys:[{key:"ucaFront",label:"UCA front pivot"},{key:"ucaRear",label:"UCA rear pivot"},{key:"lcaFront",label:"LCA front pivot"},{key:"lcaRear",label:"LCA rear pivot"},{key:"tieInner",label:"tie/toe link inner"}]},{kind:"outboard",keys:[{key:"uprightUpper",label:"upper ball joint"},{key:"uprightLower",label:"lower ball joint"},{key:"tieOuter",label:"tie/toe link outer"},{key:"wheelCenter",label:"wheel centre"}]},{kind:"actuation",keys:[{key:"pushrodOuter",label:"push/pull rod outer"},{key:"rockerPivotA",label:"rocker pivot A"},{key:"rockerPivotB",label:"rocker pivot B"},{key:"rockerToPushrod",label:"rocker \u2014 rod end"},{key:"rockerToDamper",label:"rocker \u2014 damper end"},{key:"damperChassis",label:"damper chassis mount"}]}],vw={damperChassis:"strut top mount",pushrodOuter:"strut lower mount"},Lo=30;function n3(e){let t=[];for(let r of["front","rear"]){let n=Be(e.vehicle,r).config.layout==="mcpherson";for(let o of Rw)for(let{key:a,label:s}of o.keys){let i=n&&vw[a]||s;for(let c=0;c<3;c++)t.push({id:`hp.${r}.${a}.${tr[c]}`,group:`${rr[r]} hardpoints \u2014 ${o.kind}`,label:`${i} ${tr[c]}`,scope:rr[r],unit:"mm",defaultSpan:Lo,read:l=>Be(l.vehicle,r).hardpoints[a][c],write:(l,u)=>{let m=Be(l.vehicle,r),d=[...m.hardpoints[a]];d[c]=u;let p={...m.hardpoints,[a]:d};return{...l,vehicle:Gc(l.vehicle,r,{...m,hardpoints:p})}}})}}return t}var o3={side:"axis side-view angle",plan:"axis plan-view angle",clock:"arm clock angle",len:"effective arm length"},a3={side:"\xB0",plan:"\xB0",clock:"\xB0",len:"mm"};function s3(e){let t=[];for(let r of["front","rear"]){let n=Be(e.vehicle,r).config.layout==="mcpherson";for(let o of["uca","lca"]){let a=Be(e.vehicle,r).hardpoints,s=uy(a,o)?null:tn(a,o);for(let i of Pn)t.push({id:`arm.${r}.${o}.${i}`,group:`${rr[r]} ${n?"arm axes":"wishbone axes"}`,label:`${$c[o]} \u2014 ${o3[i]}`,scope:rr[r],unit:a3[i],defaultSpan:s?Ep(s,i,Lo):Lo,read:c=>tn(Be(c.vehicle,r).hardpoints,o)[i],write:(c,l)=>{let u=Be(c.vehicle,r),m=hw(u.hardpoints,o,i,l);return{...c,vehicle:Gc(c.vehicle,r,{...u,hardpoints:m})}}})}}return t}var i3={side:"pivot axis side-view angle",plan:"pivot axis plan-view angle",atY:"pivot axis outboard, at the wheel-centre plane",atZ:"pivot axis height, at the wheel-centre plane"},c3={side:"\xB0",plan:"\xB0",atY:"mm",atZ:"mm"};function l3(e){let t=[];for(let r of["front","rear"]){let n=Be(e.vehicle,r).hardpoints,o=as(n)?null:Ln(n);for(let a of To)t.push({id:`rocker.${r}.${a}`,group:`${rr[r]} rocker axis`,label:`rocker \u2014 ${i3[a]}`,scope:rr[r],unit:c3[a],defaultSpan:o?fy(o,a,Lo):Lo,read:s=>Ln(Be(s.vehicle,r).hardpoints)[a],write:(s,i)=>{let c=Be(s.vehicle,r),l=yw(c.hardpoints,a,i);return{...s,vehicle:Gc(s.vehicle,r,{...c,hardpoints:l})}}})}return t}var Ip={front:"heaveFrontDesign",rear:"heaveRearDesign"},by={front:"arbFrontDesign",rear:"arbRearDesign"};function u3(e,t){return{heave:e.config.actuation==="decoupled"?"heave element":"third spring",roll:t?.design.kind==="coil"?"roll shock":"anti-roll bar"}}var _p=e=>/^(heave|roll)\.(front|rear)\.(outer|inner|anchor)\.[xyz]$/.test(e);function m3(e){let t=[];for(let r of["front","rear"]){let n=Be(e.vehicle,r),o=e.params[Ip[r]],a=e.params[by[r]],s=u3(n,a),i=f=>f.params[Ip[r]],c=f=>f.params[by[r]],l=(f,h)=>({...f,params:{...f.params,[Ip[r]]:h}}),u=(f,h)=>({...f,params:{...f.params,[by[r]]:h}}),m={group:`${rr[r]} heave & roll elements`,scope:rr[r]},d=(f,h,b,g,y)=>{for(let R of b)t.push({...m,id:`${f}.${tr[R]}`,label:`${h} ${tr[R]}`,unit:"mm",defaultSpan:Lo,read:k=>g(k)[R],write:(k,v)=>{let x=[...g(k)];return x[R]=v,y(k,x)}})},p=(f,h,b,g,y)=>{t.push({...m,id:f,label:h,unit:"N/mm",defaultSpan:Math.max(5,b*.4),read:g,write:y})};if(o?.design.kind==="coil"){if(o.linkage){let f=b=>i(b).linkage;d(`heave.${r}.outer`,`${s.heave} eye`,[0,1,2],b=>f(b).outer,(b,g)=>l(b,{...i(b),linkage:{...f(b),outer:g}})),o.linkage.mount?.kind==="chassis"&&d(`heave.${r}.anchor`,`${s.heave} chassis anchor`,[0,2],b=>f(b).mount.anchor,(b,g)=>l(b,{...i(b),linkage:{...f(b),mount:{kind:"chassis",anchor:g}}}))}if(typeof o.design.rate=="number"){let f=h=>i(h).design;p(`heave.${r}.rate`,`${s.heave} spring rate (@element)`,o.design.rate,h=>f(h).rate,(h,b)=>l(h,{...i(h),design:{...f(h),rate:b}}))}}if(a&&a.design.kind!=="none"){if(a.linkage&&a.design.kind!=="direct"){let h=R=>c(R).linkage,b=mn(n,a.linkage,a.design.kind),[g,y]=b?["left arm eye","right arm eye"]:["drop-link pickup","arm tip"];d(`roll.${r}.outer`,`${s.roll} ${g}`,[0,1,2],R=>h(R).outer,(R,k)=>u(R,{...c(R),linkage:{...h(R),outer:k}})),d(`roll.${r}.inner`,`${s.roll} ${y}`,[0,1,2],R=>h(R).inner,(R,k)=>u(R,{...c(R),linkage:{...h(R),inner:k}}))}let f=a.design;if(f.kind==="coil"&&typeof f.rate=="number"){let h=b=>c(b).design;p(`roll.${r}.rate`,`${s.roll} spring rate (@element)`,f.rate,b=>h(b).rate,(b,g)=>u(b,{...c(b),design:{kind:"coil",rate:g}}))}else f.kind==="direct"&&p(`roll.${r}.wheelRate`,`${s.roll} rate (@wheel)`,f.wheelRate,h=>c(h).design.wheelRate,(h,b)=>u(h,{...c(h),design:{kind:"direct",wheelRate:b}}))}}return t}var p3=[{axle:"front",field:"springRate",group:"Springs & bars",label:"spring rate (@spring)",unit:"N/mm",fallback:35,span:e=>Math.max(5,e*.4)},{axle:"rear",field:"springRate",group:"Springs & bars",label:"spring rate (@spring)",unit:"N/mm",fallback:40,span:e=>Math.max(5,e*.4)},{axle:"front",field:"rackTravel",group:"Steering",label:"rack travel from centre",unit:"mm",fallback:35,span:()=>15,frontOnly:!0},{axle:"front",field:"rackRatio",group:"Steering",label:"rack per steering-wheel turn",unit:"mm/rev",fallback:55,span:()=>15,frontOnly:!0},{axle:"front",field:"loadedRadius",group:"Wheel & tyre",label:"loaded radius",unit:"mm",fallback:228,span:()=>15},{axle:"rear",field:"loadedRadius",group:"Wheel & tyre",label:"loaded radius",unit:"mm",fallback:228,span:()=>15}];function d3(e){let t=[];for(let r of["front","rear"]){let n=Be(e.vehicle,r).compliance;if(!n)continue;let o=(a,s,i,c)=>{let l=i(n);l===void 0||!(l>0)||!Number.isFinite(l)||t.push({id:`kc.${r}.${a}`,group:"Compliance",label:s,scope:rr[r],unit:"N/mm",defaultSpan:Math.max(500,l*.4),read:u=>i(Be(u.vehicle,r).compliance??{})??l,write:(u,m)=>{let d=Be(u.vehicle,r),p={...d,compliance:c(d.compliance??{},Math.max(1,m))};return{...u,vehicle:Gc(u.vehicle,r,p)}}})};for(let a of["ucaFront","ucaRear","lcaFront","lcaRear","tieRod","pushRod"])o(`link.${a}`,`${f3[a]} (link)`,s=>s.links?.[a],(s,i)=>({...s,links:{...s.links,[a]:i}}));for(let a of["ucaFront","ucaRear","lcaFront","lcaRear","tieInner","topMount"])o(`bush.${a}`,`${h3[a]} (bushing)`,s=>s.bushings?.[a],(s,i)=>({...s,bushings:{...s.bushings,[a]:i}}));r==="front"&&o("rack","rack to housing",a=>a.rack,(a,s)=>({...a,rack:s}))}return t}var f3={ucaFront:"UCA front leg",ucaRear:"UCA rear leg",lcaFront:"LCA front leg",lcaRear:"LCA rear leg",tieRod:"tie rod",pushRod:"push/pull rod"},h3={ucaFront:"UCA front pickup",ucaRear:"UCA rear pickup",lcaFront:"LCA front pickup",lcaRear:"LCA rear pickup",tieInner:"tie-rod inner",topMount:"strut top mount"};function b3(){return p3.map(e=>({id:`cfg.${e.axle}.${e.field}`,group:e.group,label:e.label,scope:rr[e.axle],unit:e.unit,defaultSpan:e.span(e.fallback),read:t=>Be(t.vehicle,e.axle).config[e.field]??e.fallback,write:(t,r)=>{let n=Be(t.vehicle,e.axle),o={...n,config:{...n.config,[e.field]:r}};return{...t,vehicle:Gc(t.vehicle,e.axle,o)}}}))}function g3(e){let t=Yn(e.params.steeringSystem);if(!t.enabled)return[];let r=(n,o,a,s,i)=>({id:`steeringSystem.${n}`,group:"Steering",label:o,unit:a,defaultSpan:s,read:c=>Yn(c.params.steeringSystem)[n],write:(c,l)=>({...c,params:{...c.params,steeringSystem:Yn({...c.params.steeringSystem,enabled:!0,[n]:i(l)})}})});return[r("roadFeedbackGain","road feedback gain","\xD7",Math.max(.1,.25*t.roadFeedbackGain),n=>Math.min(2,Math.max(0,n))),r("turnInFrictionNm","turn-in friction","N\xB7m",Math.max(.1,.5*t.turnInFrictionNm),n=>Math.max(0,n))]}function y3(e){let t=Pi(e.params),r=[];for(let n of["front","rear"]){if(t[n]!=="diff")continue;let o=so(e.params.driveline?.[n]);if(o?.kind!=="clutch"&&o?.kind!=="torsen")continue;let a=(s,i)=>{let c=ju[`${n}.${s}`];return{id:`driveline.${n}.${s}`,group:"Differential",label:c.label.charAt(0).toLowerCase()+c.label.slice(1),scope:rr[n],unit:c.unit===": 1"?"":c.unit??"",defaultSpan:i,read:l=>so(l.params.driveline?.[n])?.[s],write:(l,u)=>({...l,params:{...l.params,driveline:Wu({...l.params.driveline,[n]:{...l.params.driveline?.[n],[s]:u}})}})}};o.kind==="clutch"?r.push(a("preloadNm",Math.max(5,.2*o.preloadNm)),a("rampDriveDeg",5),a("rampCoastDeg",5)):r.push(a("tbrDrive",Math.max(.25,.2*o.tbrDrive)),a("tbrCoast",Math.max(.25,.2*o.tbrCoast)))}return r}function x3(e){if(pu(e.params)!=="hydraulic")return[];let t=[{id:"brakeSetup.barFront",group:"Brakes",label:`${zh("barFront").toLowerCase()}, front share`,unit:"-",defaultSpan:.05,read:a=>Nr(a.params.brakeSetup).barFront,write:(a,s)=>({...a,params:{...a.params,brakeSetup:Nr({...Nr(a.params.brakeSetup),barFront:s})}})}];if(!e.params.brakeModel)return t;let r=ur(e.params.brakeModel),n=(a,s)=>s.circuit?a[s.circuit][s.key]:a[s.key],o=(a,s,i)=>({id:`brakeModel.${a.circuit?`${a.circuit}.`:""}${String(a.key)}`,group:"Brakes",label:Hh(a.circuit?`${a.circuit}.${String(a.key)}`:a.key),unit:s,defaultSpan:i,read:c=>n(ur(c.params.brakeModel),a),write:(c,l)=>{let u=ur(c.params.brakeModel),m=a.circuit?{...u,[a.circuit]:{...u[a.circuit],[a.key]:l}}:{...u,[a.key]:l};return{...c,params:{...c.params,brakeModel:ur(m)}}}});return t.push(o({key:"masterFrontMm"},"mm",1.5),o({key:"masterRearMm"},"mm",1.5),o({key:"pedalRatio"},"-",.5),o({key:"pistonDiaMm",circuit:"front"},"mm",2),o({key:"pistonDiaMm",circuit:"rear"},"mm",2),o({key:"effRadiusMm",circuit:"front"},"mm",10),o({key:"effRadiusMm",circuit:"rear"},"mm",10)),r.valve!=="none"&&t.push(o({key:"valveKneeBar"},"bar",5)),r.valve==="proportioning"&&t.push(o({key:"valveSlope"},"-",.1)),t}var kw=e=>!!e&&typeof e=="object"&&"value"in e&&"label"in e;function Mw(e){let t={...e};for(let r of Object.keys(t)){let n=t[r];kw(n)&&(t[r]={...n})}return t}function R3(e){let t=[];for(let r of uM(e))for(let n of r.rows){let o=Math.abs(n.value);t.push({id:`param.${n.key}`,group:r.title,label:n.label,unit:n.unit,defaultSpan:o>0?o*.2:1,read:a=>{let s=a.params[n.key];return kw(s)?s.value:NaN},write:(a,s)=>{let i=Mw(a.params);return Zu(i,n.label,s),{...a,params:i}}})}return t}function Sw(e){let t={};for(let s of["front","rear"]){if(!Be(e.vehicle,s).measured)continue;let c="this axle is described by measured curves, so its linkage is not solved";for(let l of Rw)for(let{key:u}of l.keys)for(let m of tr)t[`hp.${s}.${u}.${m}`]={why:c};for(let l of["uca","lca"])for(let u of Pn)t[`arm.${s}.${l}.${u}`]={why:c};for(let l of To)t[`rocker.${s}.${l}`]={why:c};for(let l of["heave.outer","heave.anchor","roll.outer","roll.inner"]){let[u,m]=l.split(".");for(let d of tr)t[`${u}.${s}.${m}.${d}`]={why:c}}t[`cfg.${s}.springRate`]={why:"the measured curve set carries its own spring rate"}}let r=["rockerPivotA","rockerPivotB","rockerToPushrod","rockerToDamper"];for(let s of["front","rear"]){if(Be(e.vehicle,s).config.actuation!=="direct")continue;let i="this axle is direct-acting \u2014 there is no bell-crank";for(let c of r)for(let l of tr)t[`hp.${s}.${c}.${l}`]={why:i};for(let c of To)t[`rocker.${s}.${c}`]={why:i}}for(let s of["front","rear"]){let i=Be(e.vehicle,s);if(i.measured||i.config.actuation!=="decoupled")continue;let c="this axle is decoupled \u2014 the corner damper is out of circuit";for(let l of["rockerToDamper","damperChassis"])for(let u of tr)t[`hp.${s}.${l}.${u}`]={why:c,useInstead:`heave.${s}.outer.${u}`};t[`cfg.${s}.springRate`]={why:"a decoupled axle has no corner spring \u2014 its elements hold it up",useInstead:`heave.${s}.rate`}}for(let s of["front","rear"]){let i=Be(e.vehicle,s),c=e.params[Ip[s]]?.linkage;if(i.measured||!c||c.attach!=="rocker"||c.mount?.kind==="chassis")continue;let l=i.hardpoints,u=[0,1,2].map(d=>l.rockerPivotB[d]-l.rockerPivotA[d]),m=Math.hypot(u[0],u[1],u[2]);if(m>0)for(let d=0;d<3;d++)Math.abs(u[d]/m)<1-1e-12||(t[`heave.${s}.outer.${tr[d]}`]={why:`the rocker shaft runs along ${tr[d]} \u2014 this only slides the eye along it`})}for(let s of["front","rear"]){let i=Be(e.vehicle,s);if(i.measured||i.config.layout!=="mcpherson")continue;let c="this axle is a McPherson strut \u2014 there is no upper arm";for(let l of["ucaFront","ucaRear","uprightUpper"])for(let u of tr)t[`hp.${s}.${l}.${u}`]={why:c,useInstead:`hp.${s}.damperChassis.${u}`};for(let l of Pn)t[`arm.${s}.uca.${l}`]={why:c};for(let l of["link.ucaFront","link.ucaRear","bush.ucaFront","bush.ucaRear"])t[`kc.${s}.${l}`]={why:c}}for(let s of["front","rear"]){let i=Be(e.vehicle,s);if(i.measured)continue;for(let l of["uca","lca"]){if(l==="uca"&&i.config.layout==="mcpherson")continue;let u=uy(i.hardpoints,l);if(u)for(let m of Pn)t[`arm.${s}.${l}.${m}`]={why:u,useInstead:`hp.${s}.${er[l].fore}.z`}}let c=as(i.hardpoints);if(c&&i.config.actuation!=="direct")for(let l of To)t[`rocker.${s}.${l}`]={why:c,useInstead:`hp.${s}.${Po.fore}.z`}}let n=[["arbFrontDesign","param.arb_front","the front anti-roll bar design in Vehicle Dynamics","front","roll"],["arbRearDesign","param.arb_rear","the rear anti-roll bar design in Vehicle Dynamics","rear","roll"],["heaveFrontDesign","param.heave_spring_front","the front third-spring design","front","heave"],["heaveRearDesign","param.heave_spring_rear","the rear third-spring design","rear","heave"]];for(let[s,i,c,l,u]of n){let m=e.params[s];if(!m?.design||m.design.kind==="none")continue;let d=m.design.kind==="direct"?`${u}.${l}.wheelRate`:`${u}.${l}.rate`;t[i]={why:`computed from ${c}`,useInstead:d}}let o=e.params.aeroModelId||e.params.aeroModel?Lb:Db;for(let[s,i]of Object.entries(o))t[`param.${s}`]={why:i};if(e.params.batteryModelId||e.params.batteryModel)for(let[s,i]of Object.entries(Xu))t[`param.${s}`]={why:i};for(let[s,i]of Object.entries(qu(e.params)))t[`param.${s}`]={why:i};let a=pu(e.params);return a==="hydraulic"?t["param.brake_balance"]={why:"set by the balance bar and the brake hardware",useInstead:"brakeSetup.barFront"}:a==="tyre"&&(t["param.brake_balance"]={why:"tyre-limited brakes split as the grip does"}),t}function Aw(e){let t={...k3,...Sw(e)};for(let[n,o]of Object.entries(t))o.useInstead&&t[o.useInstead]&&(t[n]={why:o.why});let r=n=>{let o=t[n.id];return o?{...n,supersededBy:o}:n};return[...n3(e),...s3(e),...l3(e),...m3(e),...b3(),...g3(e),...x3(e),...y3(e),...d3(e),...R3(e.params)].map(r)}var v3={spring_front:"cfg.front.springRate",spring_rear:"cfg.rear.springRate"},k3=Object.fromEntries(Object.entries(Pb).map(([e,t])=>[`param.${e}`,{why:t,useInstead:v3[e]}])),lt=e=>e.scope?`${e.scope} \xB7 ${e.label}`:e.label;function Wt(e){let t={};for(let n of Aw(e))t[n.id]=n;let r=(n,o)=>{if(typeof o!="string")return;let a=UF(n,o);return a&&(n[o]=a),a};return new Proxy(t,{get:(n,o,a)=>typeof o=="string"&&!Object.hasOwn(n,o)?r(n,o)??Reflect.get(n,o,a):Reflect.get(n,o,a),has:(n,o)=>Reflect.has(n,o)||!!r(n,o)})}var gy=e=>e.step!==void 0&&Number.isFinite(e.step)&&e.step>0?e.step:0,yy=e=>gy(e)>0||(e.values?.length??0)>0,xy=e=>e.some(yy),Fw=e=>1e-9*Math.max(1,Math.abs(e.lo),Math.abs(e.hi));function ww(e,t){if(!Number.isFinite(t))return t;if(e.values?.length){let s=e.values[0];for(let i of e.values)Math.abs(i-t)<Math.abs(s-t)&&(s=i);return s}let r=gy(e);if(!r||!Number.isFinite(e.start))return t;let n=Fw(e),o=Math.round((t-e.start)/r),a=s=>e.start+s*r;return a(o)>e.hi+n&&a(o-1)>=e.lo-n?a(o-1):a(o)<e.lo-n&&a(o+1)<=e.hi+n?a(o+1):a(o)}var Cw=(e,t)=>t.map((r,n)=>e[n]&&yy(e[n])?ww(e[n],r):r);function Ry(e,t=1e3){if(e.values?.length)return e.values.length;let r=gy(e);if(!r||!Number.isFinite(e.start))return 1/0;let n=Fw(e),o=Math.ceil((e.lo-n-e.start)/r),a=Math.floor((e.hi+n-e.start)/r);return Math.max(0,Math.min(t,a-o+1))}function vy(e,t,r){let n=Cw(e.variables,t),o=n.every((a,s)=>a===t[s]);return{x:n,score:o?r:Dr(e,n)}}function Sy(e,t){if(!e.variables.some(Pw))return e;let r=e.variables.filter(o=>o.follows&&!o.fixed).map(o=>({id:o.id,follows:o.follows})),n=e.variables.filter(o=>!o.fixed&&!o.follows).map(o=>{if(Lw(o))return{...o,lo:Math.min(...o.values),hi:Math.max(...o.values)};if(!o.around)return o;let{around:a,fixed:s,...i}=o,c=t(o.id);return Number.isFinite(c)?{...i,lo:c-a.minus,hi:c+a.plus}:i});return r.length?{...e,variables:n,followers:r}:{...e,variables:n}}var Pw=e=>!!(e.fixed||e.around||e.follows)||Lw(e),Lw=e=>!!e.values?.length&&(e.lo!==Math.min(...e.values)||e.hi!==Math.max(...e.values));function _t(e,t){if(!t.variables.some(Pw))return t;let r=Wt(e);return Sy(t,n=>{let o=r[n];if(!o)return NaN;try{return o.read(e)}catch{return NaN}})}function nr(e){return[...e.objectives,...e.constraints,...e.watches??[]]}var Op=e=>(e.metrics??en()).byId;function Ay(e,t){t=_t(e,t);let r=Wt(e),n=[];for(let o of t.variables){let a=r[o.id];a&&n.push({id:a.id,name:lt(a),unit:a.unit,lo:o.lo,hi:o.hi,start:a.read(e),...o.step!==void 0?{step:o.step}:{},...o.values?{values:o.values}:{}})}return n}function Vp(e,t,r){t=_t(e,t);let n=Wt(e),o=e;return t.variables.forEach((a,s)=>{let i=n[a.id];i&&Number.isFinite(r[s])&&(o=i.write(o,r[s]))}),Cy(e,o,t.followers,n)}function Fy(e,t,r={}){let n=t.states??[],o=n.some(c=>c.follows);if(!o&&!t.envelopeFollows)return t;let a=Tn(e,{density:t.density,envelope:t.envelope,states:n,operating:t.operating,lap:t.lap,assemble:r.assemble,simParams:r.simParams,projectTrack:r.projectTrack,libraryTrack:r.libraryTrack,numerics:r.numerics}),s=n;if(o&&r.simParams)try{let c=a.ggv();c&&(s=h0(n,c,A3(r)))}catch{s=n}let i=t.envelope;if(t.envelopeFollows&&s.length){let c=s.map(h=>a.poseAt(h)).filter(h=>h!==null),l=Op(r),u=wy(t,l),m=nr(t).map(h=>({r:h,m:l[h.metricId]})).filter(({m:h})=>h&&h.id.startsWith("kin.")&&h.reads!=="state"&&(h.scope==="car"||u.includes(h.scope))),d=h=>{let b=Tn(e,{density:t.density,envelope:h,assemble:r.assemble,numerics:r.numerics});return m.every(({r:g,m:y})=>Number.isFinite(St(b,y,g.at)))},p=c.length===s.length?S3(e,g0(c,u),u):null,f=p&&m.length?M3(p,d):p;f&&!y0(f,t.envelope)&&(i=f)}return s===n&&i===t.envelope?t:{...t,states:s,envelope:i}}var Np=3;function M3(e,t){let r=(c,l)=>t({...e,travelMin:c,travelMax:l}),n=e.travelMin-Np,o=e.travelMax+Np;if(r(n,o))return e;let a=(c,l,u)=>{for(;Math.abs(l-c)>1;){let m=Math.round((c+l)/2);u(m)?c=m:l=m}return c};if(r(n,1))o=a(1,o,c=>r(n,c));else if(r(-1,1))n=a(-1,n,c=>r(c,1)),o=a(1,o,c=>r(n,c));else return e;let s=Math.min(-1,Math.max(e.travelMin,n+Np)),i=Math.max(1,Math.min(e.travelMax,o-Np));return s===e.travelMin&&i===e.travelMax?e:{...e,travelMin:s,travelMax:i}}function wy(e,t){let r=new Set;for(let n of nr(e)){let o=t[n.metricId];if(!(!o||!o.id.startsWith("kin.")||o.reads==="state")){if(o.scope==="car")return["front","rear"];r.add(o.scope)}}return r.size?["front","rear"].filter(n=>r.has(n)):["front","rear"]}function S3(e,t,r){if(!t)return null;let n=Za(e.vehicle,e.params),{travelMin:o,travelMax:a}=t;for(let s of r.map(i=>n[i]))try{let i=Ke(s,{travelMin:o,travelMax:a,steps:Cc.travelSteps});if(i.covered)continue;let c=i.samples.filter(l=>l.converged).map(l=>l.travel);if(!c.length)continue;o=Math.max(o,Math.min(-1,Math.ceil(Math.min(...c))+1)),a=Math.min(a,Math.max(1,Math.floor(Math.max(...c))-1))}catch{continue}return o===t.travelMin&&a===t.travelMax?t:{...t,travelMin:o,travelMax:a}}function A3(e){let t=e.projectTrack?.();if(!t)return null;try{return f0(ct(t.asset,t.numerics))}catch{return null}}function Cy(e,t,r,n){if(!r?.length)return t;let o=t;for(let a of r){let s=n[a.id],i=n[a.follows];if(!s||!i)continue;let c=i.read(t)-i.read(e);Number.isFinite(c)&&c!==0&&(o=s.write(o,s.read(e)+c))}return o}function Kc(e,t){if(!Number.isFinite(t))return NaN;if(e.op==="max")return t-e.limit;if(e.op==="min")return e.limit-t;let r=e.limit2??e.limit;return Math.max(e.limit-t,t-r)}var Dw=(e,t="")=>t&&t!=="-"?`${e} ${t}`:`${e}`;function Ew(e,t,r){let n=t??ns[e.metricId],o=(n?et(n):e.metricId)+Hc(e.at,n,r),a=s=>Dw(s,n?.unit);return e.op==="max"?`${o} \u2264 ${a(e.limit)}`:e.op==="min"?`${o} \u2265 ${a(e.limit)}`:`${o} between ${e.limit} and ${a(e.limit2??e.limit)}`}function Hc(e,t,r){if(!e&&t?.reads!=="state")return"";e??={};let n=[];if(t?.reads==="state")if(e.stateId===Rr)n.push(J0(t));else{let o=e.stateId===void 0?r?.states?.[0]:r?.states?.find(a=>a.id===e.stateId);o&&n.push(o.name)}if(e.speed!==void 0&&Q0(t)&&n.push(`${(e.speed*3.6).toFixed(0)} km/h`),e.ayG!==void 0&&Z0(t)&&n.push(`${e.ayG.toFixed(2)} g`),e.courseId===Ec&&t?.reads==="course")n.push(q0(t));else if(e.courseId&&t?.reads==="course"){let o=r?.lap.courses.find(a=>a.id===e.courseId);o&&n.push(T0(o))}return n.length?` @ ${n.join(", ")}`:""}function Iw(e,t,r){let n=r/t.scale;return e.goal==="min"?e.weight*n:e.goal==="max"?-e.weight*n:e.weight*Math.max(0,Math.abs(r-(e.target??0))-Math.max(0,e.tolerance??0))/t.scale}var _w=5e-4;function Nw(e,t){return e.cost!=="lap"&&e.cost!=="session"?0:Number.isFinite(t)?_w*Math.abs(t):0}function Bp(e,t,r={}){t=_t(e,t);let n=Ay(e,t),o=Wt(e),a=Op(r),s=t.constraints.map(m=>({spec:m,metric:a[m.metricId]})).filter(m=>!!m.metric),i=s.filter(m=>m.metric.cost==="geometry"),c=s.filter(m=>m.metric.cost!=="geometry"),l=t.objectives.map(m=>({spec:m,metric:a[m.metricId]})).filter(m=>!!m.metric),u=(m,d)=>{let p=0,f=[];for(let{spec:h,metric:b}of m){let g=St(d,b,h.at);if(!Number.isFinite(g))return{ok:!1,violation:d.failure?.violation??400,reason:d.failure?.reason??`${et(b)} could not be computed`};let y=Kc(h,g);y>0&&(p+=y/b.scale,f.push(`${Ew(h,b,t)} (${Dw(g.toFixed(3),b.unit)})`))}return f.length===0?Xs:{ok:!1,violation:p,reason:f.join("; ")}};return{name:"study",variables:n,build:m=>{let d=e;return t.variables.forEach((p,f)=>{let h=o[p.id];h&&(d=h.write(d,m[f]))}),d=Cy(e,d,t.followers,o),{car:d,ev:Tn(d,{density:t.density,envelope:t.envelope,states:t.states,operating:t.operating,lap:t.lap,assemble:r.assemble,simParams:r.simParams,projectTrack:r.projectTrack,libraryTrack:r.libraryTrack,sessionParams:r.sessionParams,session:r.session,numerics:r.numerics})}},feasible:({ev:m})=>{let d=u(i,m);if(!d.ok)return d;for(let{spec:p,metric:f}of c)St(m,f,p.at);for(let{spec:p,metric:f}of l)St(m,f,p.at);return m.failure?{ok:!1,violation:m.failure.violation,reason:m.failure.reason}:u(c,m)},terms:({ev:m})=>l.map(({spec:d,metric:p})=>{let f=St(m,p,d.at);return{name:et(p)+Hc(d.at,p,t),raw:f,unit:p.unit,weight:d.weight,contribution:Iw(d,p,f),resolution:Math.abs(d.weight)*Nw(p,f)/p.scale}})}}function ky(e){let t=/^arm\.(front|rear)\.(uca|lca)\./.exec(e);if(t)return`${t[1]}.${t[2]}`;let r=/^rocker\.(front|rear)\./.exec(e);if(r)return`${r[1]}.rocker`;let n=/^hp\.(front|rear)\.(ucaFront|ucaRear|lcaFront|lcaRear|rockerPivotA|rockerPivotB)\./.exec(e);return n?n[2].startsWith("rocker")?`${n[1]}.rocker`:`${n[1]}.${n[2].startsWith("uca")?"uca":"lca"}`:null}function Ow(e,t){if(e.variables.some(o=>o.id===t))return!0;let r=Dc(t);if(!r||!Mp.includes(r.axis))return!1;if(e.variables.some(o=>kr(o.id)?.point===r.point))return!0;let n=ky(t);return!!n&&e.variables.some(o=>/^(arm|rocker)\./.test(o.id)&&ky(o.id)===n)}function F3(e,t){let r=e.followers??[],n=new Map(r.map(i=>[i.id,i.follows])),o=i=>{let c=t[i],l=Dc(i);return c&&l&&Mp.includes(l.axis)?{name:lt({...c,label:c.label.replace(/ [xyz]$/,"")}),axis:l.axis}:{name:c?lt(c):`\u201C${i}\u201D`}},a=new Map,s=(i,c,l)=>{let u=a.get(i);u||a.set(i,u={text:l,axes:[]}),c&&u.axes.push(c)};for(let i of r){let c=t[i.id],l=t[i.follows],u=o(i.id),m=o(i.follows),d=p=>p&&p!=="x, y, z"?` in ${p}`:"";if(!c){s(`missing:${i.id}`,void 0,()=>`\u201C${i.id}\u201D is not a variable this car has.`);continue}if(c.supersededBy&&s(`superseded:${u.name}`,u.axis,p=>`${u.name}${d(p)} cannot be moved: ${c.supersededBy.why}.`),!l)s(`no-lead:${u.name}:${i.follows}`,u.axis,p=>`${u.name}${d(p)} moves with \u201C${i.follows}\u201D, which is not a variable this car has.`);else if(i.follows===i.id)s(`self:${u.name}`,u.axis,p=>`${u.name}${d(p)} cannot move with itself.`);else if(l.unit!==c.unit)s(`unit:${u.name}:${m.name}`,u.axis,p=>`${u.name}${d(p)} moves with ${m.name}, which is in ${l.unit} where it is in ${c.unit}. Link it to one in the same unit.`);else if(n.has(i.follows)){let p=o(n.get(i.follows));s(`chain:${u.name}:${m.name}`,u.axis,f=>`${u.name}${d(f)} moves with ${m.name}, which itself moves with ${p.name}. Link it to ${p.name}.`)}else Ow(e,i.follows)||s(`still:${u.name}:${m.name}`,u.axis,p=>`${u.name}${d(p)} moves with ${m.name}, which the study does not move${d(p)}. Free that one, or give this its own bound.`)}return[...a.values()].map(i=>i.text(i.axes.join(", ")))}function Ty(e,t,r={}){let n=t.variables.length>0&&t.variables.every(y=>y.fixed||y.follows),o=t.variables.some(y=>y.follows&&!y.fixed);t=_t(e,t);let a=Wt(e),s=[],i=Op(r),c=nr(t).map(y=>y.metricId),l=c.some(y=>y.startsWith("dyn.")),u=c.some(y=>y.startsWith("lap."));if(c.some(y=>y.startsWith("kin."))){let y=t.envelope;y.travelMin<0&&y.travelMax>0||s.push("The travel the linkage is read over must reach both ways from the design ride: droop below zero, bump above."),(!(y.rollMaxDeg>0)||!(y.rollAtLimitDeg>=0))&&s.push("The roll the linkage is read over must be above zero.")}let m=nr(t).filter(y=>i[y.metricId]?.reads==="state");if(m.length){let y=t.states??[];if(!y.length)s.push("This study reads targets at a state and has none. Take the car\u2019s five under Conditions.");else{let R=new Set([...y.map(k=>k.id),Rr]);for(let k of m){let v=i[k.metricId];if(k.at?.stateId&&!R.has(k.at.stateId))s.push(`${et(v)} names a state this study no longer has. Point it at one of the states under Conditions.`);else if(k.at?.stateId===Rr&&!v.acrossStates)s.push(`${et(v)} is read at one state at a time, not over every state.`);else if(v.appliesAt){let x=k.at?.stateId&&k.at.stateId!==Rr?y.find(A=>A.id===k.at.stateId):void 0,M=x?oy(v,x):null;M?s.push(`${et(v)} ${M}. Point it at a state that does.`):!x&&!Sp(v,y)&&s.push(`${et(v)} has no state to be read at: ${v.appliesAt(y[0])} in every state of this study.`)}}}r.assemble||s.push("This study reads targets at a state, and nothing here can assemble the car to find its pose.")}for(let y of t.states??[])(!(y.speedKmh>=0)||!Number.isFinite(y.ayG)||!Number.isFinite(y.axG))&&s.push(`The state \u201C${y.name}\u201D needs a speed of zero or more and finite accelerations.`),y.weight>0||s.push(`The state \u201C${y.name}\u201D needs a weight above zero.`);if(l&&!r.assemble&&s.push("This study reads whole-car metrics, and nothing here can assemble the car to read them from."),u&&!r.simParams&&s.push("This study reads lap metrics, and nothing here can prepare the car for a lap."),u&&!t.lap.courses.length&&s.push("This study reads lap metrics and has no course to drive. Add one under \u201CWhat the car drives\u201D."),u&&t.lap.courses.some(y=>y.course.kind==="project")&&!r.projectTrack?.()&&s.push("This study laps the project\u2019s track, and the project has none. Pick a manoeuvre, or load a track."),u)for(let y of t.lap.courses)y.course.kind==="track"&&!r.libraryTrack?.(y.course.trackId)&&s.push(`This study drives ${y.course.name}, which is not in the project\u2019s tracks, or has not loaded yet.`);let d=new Set([...t.lap.courses.map(y=>y.id),Ec]);for(let y of nr(t))if(y.at?.courseId&&!d.has(y.at.courseId)){let R=i[y.metricId];s.push(`${R?et(R):y.metricId} names a course this study no longer has. Point it at one of the courses below.`)}u&&t.lap.ggvMode==="fast"&&t.variables.some(R=>/arb_|spring|heave_|front_mass_diss|cg_height|^hp\./.test(R.id.replace("param.","")))&&s.push("The fast grip envelope is a point mass: no load transfer, no trim. It cannot see bars, springs, roll centres or where the mass sits, and this study moves at least one of those."),n?s.push(o?"Every variable is fixed or moves with another \u2014 there is nothing to search.":"Every variable is fixed \u2014 there is nothing to search."):t.variables.length===0&&s.push("No variables selected \u2014 there is nothing to search."),t.objectives.length===0&&s.push("No objective selected. Constraints alone say which designs are legal, not which is better.");for(let y of t.variables){let R=a[y.id];if(!R){s.push(`\u201C${y.id}\u201D is not a variable this car has.`);continue}if(y.values&&y.values.length<2?s.push(`${lt(R)}: list two values or more, or fix it where it is.`):y.hi>y.lo?y.step!==void 0&&Ry({...y,start:R.read(e)})<2&&s.push(`${lt(R)}: a step of ${y.step} ${R.unit} leaves no other place to land in its box. Make the step finer or the box wider, or fix it.`):s.push(`${lt(R)}: the upper bound must be above the lower one (${y.lo} to ${y.hi}).`),R.supersededBy){let v=R.supersededBy.useInstead?a[R.supersededBy.useInstead]:void 0,x=v?lt(v):void 0;s.push(`${lt(R)} cannot be searched: ${R.supersededBy.why}.`+(x?` Use ${x} instead.`:""))}let k=R.read(e);Number.isFinite(k)&&(k<y.lo||k>y.hi)&&s.push(`${lt(R)} starts at ${k.toFixed(1)} ${R.unit}, outside its own bounds.`)}let p=t.followers??[],f=new Map;for(let y of[...t.variables.map(R=>R.id),...p.map(R=>R.id)]){let R=ky(y);if(!R)continue;let k=f.get(R);k||f.set(R,k={arms:[],coords:[]}),(/^(arm|rocker)\./.test(y)?k.arms:k.coords).push(y)}for(let[y,R]of f){if(R.arms.length===0||R.coords.length===0)continue;let k=x=>a[x]?lt(a[x]):x,v=y.endsWith("rocker")?"rocker":`${y.endsWith("uca")?"upper":"lower"} arm`;s.push(`${y.startsWith("front")?"The front":"The rear"} ${v} is being moved two ways at once \u2014 as an axis (${R.arms.map(k).join(", ")}) and as pivot coordinates (${R.coords.map(k).join(", ")}). They describe the same ${v}, so whichever is applied second overwrites the other. Keep one.`)}let h=new Map,b=new Set(p.map(y=>y.id));for(let y of[...t.variables.map(R=>R.id),...b]){let R=Dc(y);if(!R)continue;let k=kr(y),v=b.has(y)?"with":k?`${k.shape.kind}:${y.slice(y.lastIndexOf(".")+1).replace(/[uv]$/,"")}`:"axes",x=h.get(R.point);x||h.set(R.point,x=new Set),x.add(v)}for(let[y,R]of h){if(R.size<2||R.size===2&&R.has("axes")&&R.has("with"))continue;let k=[...R].map(w=>w.split(":")[0]),v=w=>k.filter(C=>C===w).length,x=[v("axes")?"in its axes":"",v("line")===1?"along a line":v("line")>1?"along two lines":"",v("plane")===1?"in a plane":v("plane")>1?"in two planes":"",v("with")?"with another point":""].filter(Boolean),M=a[`${y}.x`],A=M?lt({...M,label:M.label.replace(/ x$/,"")}):y;s.push(`${A} is moved more than one way at once \u2014 ${x.join(" and ")}. Each write moves it off the other's, so keep one.`)}s.push(...F3(t,a));for(let y of t.constraints){let R=i[y.metricId];if(!R){s.push(`\u201C${y.metricId}\u201D is not a metric.`);continue}y.op==="band"&&!((y.limit2??y.limit)>y.limit)&&s.push(`${et(R)}: the band's upper limit must be above its lower one.`)}l&&!(t.operating.speed>0)&&s.push("Whole-car metrics need a speed to be read at; a yaw-moment diagram at rest is degenerate.");for(let y of nr(t))if(y.at?.speed!==void 0&&!(y.at.speed>0)){let R=i[y.metricId];s.push(`${R?et(R):y.metricId} is asked for at rest, where a yaw-moment diagram is degenerate.`)}for(let y of t.watches??[])i[y.metricId]||s.push(`\u201C${y.metricId}\u201D is not a metric.`);let g=new Set;for(let y of nr(t)){let R=i[y.metricId],k=R?.unavailable?.(e);!R||!k||g.has(R.id)||(g.add(R.id),s.push(`${et(R)} cannot be read on this car: ${k}.`))}for(let y of t.objectives)i[y.metricId]?y.weight>0?y.goal==="target"&&!Number.isFinite(y.target)?s.push(`${et(i[y.metricId])}: \u201Chit a value\u201D needs a value.`):y.goal==="target"&&y.tolerance!==void 0&&!(y.tolerance>=0)&&s.push(`${et(i[y.metricId])}: the tolerance must be zero or more.`):s.push(`${et(i[y.metricId])}: weight must be positive.`):s.push(`\u201C${y.metricId}\u201D is not a metric.`);return s}var Vw=.1,Bw=2e3,My=3;function Py(e,t,r={},n=Bw){t=_t(e,t);let o=Bp(e,t,r),a=Op(r),s=Wt(e),i=o.variables.map(F=>F.start),c=F=>{let S=o.build(F);return o.feasible(S).ok&&o.terms(S),S},l=c(i),u=o.feasible(l),m=[...t.objectives,...t.constraints],d=(F,S=m)=>{let P={};for(let L of S){let D=a[L.metricId];D&&(P[`${L.metricId}@${Co(L.at)}`]=St(F.ev,D,L.at))}return P},p=F=>m.map(S=>F[`${S.metricId}@${Co(S.at)}`]).map(S=>Number.isFinite(S)?S.toFixed(9):"x").join("|"),f=d(l,nr(t)),h=p(f),b=[],g=[],y={},R=[],k=0;t.variables.forEach((F,S)=>{let P=s[F.id];if(!P)return;if(R.length>=My&&k>n){g.push(P);return}let L=[...i];L[S]=i[S]+(F.hi-i[S])*.25||F.hi;let D=performance.now(),I=c(L),O=performance.now()-D;k+=O,R.push(O);let _=d(I);y[P.id]=_,p(_)===h&&b.push(P)});let v=t.variables[0],x=v?t.variables.indexOf(v):-1;for(let F=0;v&&R.length>0&&R.length<My;F++){let S=[...i];S[x]=i[x]+(v.hi-i[x])*(.4+.15*F)||v.hi;let P=performance.now();c(S),R.push(performance.now()-P)}let M=[...R].sort((F,S)=>F-S),A=M.length?M[M.length>>1]:0,w=[],C=nr(t).map(F=>F.metricId);if(C.some(F=>F.startsWith("dyn.trim")||F==="dyn.ymdMaxAy")){let F=l.ev.ymdLimit();F?.onGridEdge&&w.push("The yaw-moment diagram peaks on the edge of its swept grid, so the trim readings are where the sweep stopped rather than where the car does. Widen the \u03B2/\u03B4 envelope before trusting them."),!F&&l.ev.dynAvailable&&w.push("The yaw-moment diagram found no trim point, so anything read off the limit is unavailable.")}if(C.some(F=>F==="dyn.steeringTorque"||F==="dyn.steeringTorqueGradient")){let F=l.ev.tyre()?.model,S=F?pn(F):null;S==="assumed"?w.push("This tyre carries no explicit Mz coefficient block. Its steering-aligning contribution uses Magic Formula defaults, so optimise the curve only as a qualitative placeholder until Mz is imported or fitted."):S==="none"&&w.push("This tyre model has no aligning-moment curve. Steering metrics contain contact-patch force and jacking, but not the pneumatic-trail signal that normally warns the driver at the tyre limit.")}let T=["lap.minStabil","lap.understeerFrac"];if(C.some(F=>T.includes(F))){let S=l.ev.lapReserve()?.beyondFrac;if(S!==void 0&&Number.isFinite(S)){let P=(S*100).toFixed(0);S>=Vw?w.push(`Over ${P} % of this course, some wheel is asked for more longitudinal force than its own tyre ellipse allows \u2014 the speed profile and the per-wheel reconstruction disagree that far. A reserve read there is the two models disagreeing rather than the car having nothing left, and a search pointed at one will optimise the disagreement. It concentrates in high-speed braking, so a shorter straight into the first corner is the usual cure.`):S>0&&w.push(`${P} % of this course is beyond the per-wheel tyre ellipse, which is the usual level of disagreement between the speed profile and the reconstruction. Reserves are readable; treat small differences between designs as smaller than they look.`)}}return w.push(...ny(l.ev,nr(t).map(F=>({m:a[F.metricId],at:F.at})).filter(F=>!!F.m))),{msPerEval:A,values:f,samples:R.length,times:R,dead:b,moves:y,unprobed:g,warnings:w,beyondFrac:C.some(F=>T.includes(F))?l.ev.lapReserve()?.beyondFrac:void 0,startFeasible:u.ok,startReason:u.reason}}var C3=[{kind:"title",label:"Title",what:"The name, what it changes against the Reference, the version and the date",on:"both",make:()=>({kind:"title"})},{kind:"picture",label:"Picture",what:"The car in plan, to scale",on:"each",make:()=>({kind:"picture",half:!0})},{kind:"keyFigures",label:"Key figures",what:"Large numbers picked from the sheet, or formulas",on:"each",make:()=>({kind:"keyFigures",rows:T3.slice(0,4),half:!0})},{kind:"spec",label:"Setup",what:"The Setup by group, or rows picked one by one",on:"each",make:()=>({kind:"spec",rows:"essential"})},{kind:"parts",label:"Parts",what:"Each part by name",on:"each",make:()=>({kind:"parts"})},{kind:"characteristics",label:"Characteristics",what:"What follows from the Setup, at the layout\u2019s operating point",on:"each",make:()=>({kind:"characteristics",groups:[]})},{kind:"results",label:"Results",what:"The events, times, energy and points",on:"each",make:()=>({kind:"results"})},{kind:"chart",label:"Chart",what:"Speed round a lap, the cornering limit or the torque curve",on:"both",make:()=>({kind:"chart",chart:"grip",others:!0,half:!0})},{kind:"changes",label:"Changes since",what:"What was changed since the version compared against",on:"each",make:()=>({kind:"changes"})},{kind:"checks",label:"Checks",what:"The car\u2019s errors and warnings",on:"each",make:()=>({kind:"checks"})},{kind:"notes",label:"Notes",what:"Free text, on every page or one car\u2019s",on:"both",make:()=>({kind:"notes",text:"",cars:{}})},{kind:"comparison",label:"Comparison table",what:"The rows the cars differ in, side by side",on:"all",make:()=>({kind:"comparison"})}];var T3=["setup:m","characteristics:peak_power","characteristics:power_to_weight","characteristics:cla","characteristics:cda","characteristics:pack_energy","characteristics:maxAy","characteristics:top_speed"];var Bce=new Set(C3.map(e=>e.kind));var $w={travel:{name:"Wheel travel",unit:"mm",axis:"Wheel travel (mm, + bump)",from:-25,to:25,step:1,reach:150},roll:{name:"Body roll",unit:"\xB0",axis:"Body roll (\xB0, + right side down)",from:-3,to:3,step:.25,reach:12},steer:{name:"Rack",unit:"mm",axis:"Rack (mm, + right)",from:-30,to:30,step:1,reach:80},pitch:{name:"Body pitch",unit:"\xB0",axis:"Body pitch (\xB0, + nose down)",from:-2,to:2,step:.25,reach:8}};var Ly=["FL","FR","RL","RR"],At=(e,t,r)=>({input:e,from:r?r[0]:$w[e].from,to:r?r[1]:$w[e].to,n:t}),Hce=[{id:"sides",name:"Inside and outside",cards:[{id:"camber-roll",form:"curves",title:"Camber to the road through roll",sweep:At("roll",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"toe-rack",form:"curves",title:"Wheel angle against the rack",sweep:At("steer",25),wheels:["FL","FR"],y:["toe"]},{id:"camber-rack",form:"curves",title:"Camber to the road through the steer",sweep:At("steer",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"load-roll",form:"curves",title:"Wheel loads through roll",sweep:At("roll",25),wheels:Ly,y:["wheelLoad"]},{id:"travel-roll",form:"curves",title:"Wheel travel through roll",sweep:At("roll",25),wheels:Ly,y:["travel"]},{id:"toe-roll",form:"curves",title:"Roll steer, all four",sweep:At("roll",25),wheels:Ly,y:["toe"]}]},{id:"maps",name:"Travel and steer together",cards:[{id:"camber-map",form:"surface",title:"Camber over travel and rack",sweep:At("travel",17),second:At("steer",13),wheels:["FL"],y:["camber"]},{id:"bump-steer-map",form:"map",title:"Bump steer over travel and rack",sweep:At("travel",17),second:At("steer",13),wheels:["FL"],y:["bumpSteer"]},{id:"bump-steer-family",form:"curves",title:"Bump steer through travel, at five rack positions",sweep:At("travel",25),second:At("steer",5,[-20,20]),wheels:["FL"],y:["bumpSteer"]},{id:"scrub-map",form:"surface",title:"Scrub radius over travel and rack",sweep:At("travel",17),second:At("steer",13),wheels:["FL"],y:["scrubRadius"]}]}];function Dy(e){let t=Number(e);return Number.isFinite(t)?Math.min(dh,Math.max(ph,t)):Tt}var Kw=6e4;var Ole=[{within:60*6e4,every:Kw},{within:1440*6e4,every:60*6e4},{within:720*60*6e4,every:1440*6e4},{within:1/0,every:10080*6e4}];var G3=new Set(["color","visible","source","origin"]),Ule=["id",...G3];var Yw=.18/1.18,Ww={induction:{kind:"natural"}},jw=e=>e.breathing??Ww;function $p(e){switch(e?.kind){case"sae-j1349":return sc(99e3,25);case"measured":return sc(e.hPa*100,e.tempC);default:return sc(101325,20)}}var H3=$p(void 0);function Uw(e,t){let r=$p(e.rated),n=e.induction;if(n.kind==="boosted"){let o=n.boostKPa*1e3;return Math.min(n.maxPressureRatio*t.p,o)/Math.min(n.maxPressureRatio*r.p,o)*(t.pDry/t.p)/(r.pDry/r.p)}return t.pDry/r.pDry*Math.sqrt(r.T/t.T)}function Xw(e,t){let r=e.induction;if(r.kind==="table"){let o=s=>Ge(r.densityAltitudeM,r.powerPct,s),a=o($p(e.rated).densityAltitudeM);return a>0?Math.max(0,o(t.densityAltitudeM)/a):0}let n=e.frictionShare??Yw;return Math.max(0,(Uw(e,t)-n)/(1-n))}var zw=new WeakMap;function Iy(e,t){let r=e.asRated??e,n=`${t.p}|${t.pDry}|${t.T}`,o=zw.get(r);o||zw.set(r,o=new Map);let a=o.get(n);if(a)return a;let s=Xw(jw(r),t),i={...r,torque:r.torque.map(c=>c*s),asRated:r};return o.set(n,i),i}function j3(e){return JSON.parse(_y(Ny(e,"public/laptime/index.json"),"utf8")).tracks}var U3=async e=>{let t=await fetch(e.url);if(!t.ok)throw new Error(`The track could not be read from ${qm(e)} (${t.status}).`);return new Uint8Array(await t.arrayBuffer())};function qw(e,t=new Map,r=U3){let n=j3(e);return async o=>{let a=o.kind==="catalogue"?`catalogue:${o.address}`:o.name,s=t.get(a);if(s)return structuredClone(s);let i;if(o.kind==="catalogue"&&o.link){if(!fc(o.address))throw new Error(`"${o.address}" is not a catalogue address`);if(!dc(o.link))throw new Error("This track is linked to a source this version does not read from.");i=await Jg(await r(o.link),o.link,o.address)}else if(o.kind==="catalogue"){if(!fc(o.address))throw new Error(`"${o.address}" is not a catalogue address`);let c=JSON.parse(_y(Ny(e,"public/catalogue",t0(o.address)),"utf8"));i=await n0(c,o.address)}else{let c=n.find(l=>l.name===o.name)?.file;if(!c)throw new Error(`"${o.name}" is not in the bundled catalogue`);i=JSON.parse(_y(Ny(e,"public/laptime",c),"utf8"))}return t.set(a,i),structuredClone(i)}}var X3=9.81;function Qw(e,t=e.tireModel,r=e.tireModelRear){if(!t)return e;let n=e.m.value*X3/4,o=La(e,t,r),a=Pe(o.front).rollingRadius(n),s=o.rear===o.front?a:Pe(o.rear).rollingRadius(n),i=q3(e,a,s);if(!(i>0))return e;let c={...e.r_dyn,value:i};return{...e,r_dyn:c,readouts:{...e.readouts,r_dyn:"the fitted tyre\u2019s rolling radius at the static load"}}}function q3(e,t,r){switch(e.motorPlacement??"rear"){case"front":return t;case"awd":return t>0&&r>0?.5*(t+r):0;default:return r}}var Q3=1e-6;function Zw(e,t,r){let n=e.cgReference;if(!n||!e.cg_height)return e;let o=rM(e,t,r);if(o===void 0||Math.abs(o-n.standingRadius)<Q3)return e;let a=n.typed??e.cg_height.value;return{...e,cg_height:{...e.cg_height,value:Pa(e.cg_height.value,n.standingRadius,o)},cgReference:{...n,standingRadius:o,typed:a}}}function Jw(e,t,r){let n=e.rcRoad,o=e.rc_front,a=e.rc_rear;if(!n||!o||!a)return e;let s=Yu(e,t,r),i=Wr(o.value,n.gainFront,n.radiusFront,s.front),c=Wr(a.value,n.gainRear,n.radiusRear,s.rear);return i===o.value&&c===a.value?e:{...e,rc_front:{...o,value:i},rc_rear:{...a,value:c},rcRoad:{...n,radiusFront:s.front??n.radiusFront,radiusRear:s.rear??n.radiusRear}}}var eC=e=>({brakeFade:e.brakeFade,airTempC:e.airTempC,diffYaw:e.diffYaw,...ic(e.air)?{air:e.air}:{}});var Do=(e,t)=>t?e.find(r=>r.id===t)?.model:void 0;function Eo(e){return{tire:t=>Do(e.tires,t),motor:t=>Do(e.motors,t),aero:t=>Do(e.aeros,t),battery:t=>Do(e.batteries,t),brake:t=>Do(e.brakes??[],t),damper:t=>Do(e.dampers??[],t),suspensionOf:t=>Za(Oy(e,t),t)}}function Oy(e,t){let r=Do(e.suspensions,t.suspensionId);if(r)return r;let n=e.suspensions.find(o=>o.id===e.activeSuspensionId)??e.suspensions[0];if(!n)throw new Error("this project holds no suspension, so no car can be resolved");return n.model}function Io(e,t,r){let n={front:t.tire(e.tireModelId),rear:t.tire(e.tireModelIdRear)};return Vy(Xk(t.suspensionOf(e),e,n),t,r)}function Z3(e){return ic(e.air)?dA(e.air,e.airTempC??Tt):void 0}var J3="the air the session states, at its venue";function e5(e,t){return t?{...e,rho:{...e.rho,value:t.rho},readouts:{...e.readouts,rho:J3}}:e}function t5(e,t,r){if(!r)return{rho:e.rho,motorModel:t,readouts:e.readouts};let{rho:n,readouts:o}=e5(e,r);return{rho:n,motorModel:t&&bt(t)?Iy(t,r):t,air:r,readouts:o}}function Vy(e,t,r){let n=t.tire(e.tireModelId),o=t.tire(e.tireModelIdRear),a=Jw(Zw(Qw(sM(nM(fM(e,t.aero(e.aeroModelId)),t.battery(e.batteryModelId)),t.damper(e.damperModelId),t.damper(e.damperModelIdRear)??t.damper(e.damperModelId)),n,o),n,o),n,o),{readouts:s,...i}=t5(a,t.motor(e.motorModelId),Z3(r));return{...a,...i,...s?{readouts:s}:{},tireModel:n,...o?{tireModelRear:o}:{},aeroModel:t.aero(e.aeroModelId),batteryModel:t.battery(e.batteryModelId),brakeModel:t.brake(e.brakeModelId),damperModel:t.damper(e.damperModelId),...vi(e,t.damper),ggvMode:r.ggvMode,quasiTransient:r.quasiTransient??!1,motorThermal:r.motorThermal??!1,brakeFade:r.brakeFade??!1,...r.airTempC!==void 0?{airTempC:r.airTempC}:{},...r.diffYaw?{diffYaw:!0}:{},airSettled:!0}}var a5=e=>e!==!1,s5=(e,t,r)=>r&&t>0?(e%t+t)%t:Math.min(Math.max(e,0),t);function i5(e,t,r){let n=e.points.filter(o=>Number.isFinite(o.at)&&Number.isFinite(o.z)).map(o=>({...o,at:s5(o.at,t,r)})).sort((o,a)=>o.at-a.at);return n.filter((o,a)=>a===0||o.at-n[a-1].at>1e-9)}function c5(e,t,r){let n=i5(e,t,r),o=n.length;if(o===0)return[];let a=p=>p<o-1?n[p+1].at-n[p].at:r?n[0].at+t-n[p].at:1/0,s=p=>p<o-1?(n[p+1].z-n[p].z)/a(p):r&&o>1?(n[0].z-n[p].z)/a(p):0,i=n.map(p=>Math.max(0,Number.isFinite(p.curve)?p.curve:0)/2),c=(p,f,h)=>i[p]+i[f]>h?h*i[p]/(i[p]+i[f]):i[p],l=p=>p<o-1||r?c(p,p<o-1?p+1:0,a(p)):Math.max(0,t-n[p].at),u=p=>p>0?c(p,p-1,a(p-1)):r?c(p,o-1,a(o-1)):n[p].at,m=p=>p>0?s(p-1):r&&o>1?s(o-1):n[p].at<=1e-9?s(p):0,d=p=>!r&&p===o-1&&o>1&&n[p].at>=t-1e-9?s(p-1):s(p);return n.map((p,f)=>{let h=l(f),b=u(f),g=Math.min(i[f],h,b),y=!r&&g<i[f]&&(f===o-1&&g===h||f===0&&g===b);return{at:p.at,z:p.z,gIn:m(f),gOut:d(f),half:g,asked:i[f],atEnd:y}})}function l5(e,t,r,n){let o=t-e.at;return n&&r>0?o-r*Math.round(o/r):o}function u5(e,t,r,n){for(let s of e){let i=l5(s,t,r,n);if(s.half>0&&Math.abs(i)<s.half){let c=i+s.half;return s.z-s.gIn*s.half+s.gIn*c+(s.gOut-s.gIn)/(4*s.half)*c*c}}let o=e[e.length-1],a=n?t-o.at+(t<o.at?r:0):t-o.at;for(let s of e)s.at<=t&&(o=s,a=t-s.at);return!n&&t<e[0].at?e[0].z:o.z+o.gOut*a}function tC(e,t,r,n){let o=a5(n),a=c5(e,r,o);return a.length?t.map(s=>u5(a,s,r,o)):t.map(()=>0)}function zc(e,t){if(!t?.points.length)return e;let r=Rc(e),{zSmoothing:n,...o}=e;return{...o,z:tC(t,r,A0(e),e.closed)}}var Gp={widthLeft:1.5,widthRight:1.5,bank:0,mu:1};function rC(e){return e.kind==="bundled"?{kind:"bundled",name:e.name}:e.kind==="catalogue"?{kind:"catalogue",id:e.id,address:e.address,...e.link?{link:e.link}:{}}:null}async function Yc(e,t){let r=rC(e.source);return nC(e,r?await t(r):void 0)}function nC(e,t){let{source:r}=e;if(r.kind==="segments"){let{segments:i,closed:c,spacing:l}=r,{asset:u}=kc(i,{name:e.name,closed:c,spacing:l,base:Gp});return zc(u,r.profile)}let n=r.sections??[];if(r.kind==="inline")return zc(ap(r.asset,n,Gp),r.profile);if(!t)throw new Error(`Track "${e.name}" has to be loaded before it can be resolved.`);let{widthLeft:o,widthRight:a,closed:s}=r;return zc(ap({...t,...o!==void 0?{widthLeft:o}:{},...a!==void 0?{widthRight:a}:{},...s!==void 0?{closed:s}:{}},n,Gp),r.profile)}var Mpe=1/500;var Spe=5*Math.PI/180;var Epe=1/3;var f5=[4,2,1,.5,.25,.125];function oC(e,t,r={}){let n=[...r.steps??f5].sort((g,y)=>y-g),o=it(r.numerics),a=r.tolPct??.5,s=Pt(e),i=e.ggvMode??"twoTrack",c=br(s,!1,i),l={...o,dsTarget:n[0]??o.dsTarget},u=n.length?mo(s,c,[ct(t,l)],l,i):void 0,m=Sn(s,c.rows),d=n.map((g,y)=>{let R={...o,dsTarget:g},k=Date.now(),v=ct(t,R),x=kt(c,v,R,{...u?{load:u}:{},...m?{shifts:m}:{}});return r.onStep?.(y+1,n.length),{dsTarget:g,npts:v.npts,lapTime:x.laptime,ms:Date.now()-k}}),p=d[d.length-1]?.lapTime??NaN,f=d.map(g=>{let y=g.lapTime-p;return{...g,delta:y,deltaPct:p?100*y/p:NaN}}),h=f.filter(g=>Math.abs(g.deltaPct)<=a),b=h.length?Math.max(...h.map(g=>g.dsTarget)):null;return{points:f,reference:p,recommended:b,tolPct:a}}function ss(e,t={}){let r=e.settings,n=t.ggvMode??r.ggvMode,o=(t.quasiTransient??r.quasiTransient)&&n!=="fast",a=e.tracks.find(s=>s.id===e.activeTrackId)??e.tracks[0];return{ggvMode:n,quasiTransient:o,motorThermal:t.motorThermal??r.motorThermal,brakeFade:t.brakeFade??r.brakeFade,airTempC:Dy(t.airTempC??r.airTempC),...ic(Gm(t.air??r.air))?{air:Gm(t.air??r.air)}:{},diffYaw:t.diffYaw??r.diffYaw,racingLine:t.racingLine??r.useRacingLine,standingStart:t.standingStart??(a?a.standingStart===!0:r.standingStart),lapCounts:t.lapCounts??r.lapCounts,numerics:it(r.numerics)}}async function Kp(e,t){let r=e.tracks.find(n=>n.id===e.activeTrackId)??e.tracks[0];if(!r)throw new Error("this project holds no track \u2014 add one with track_select before running a lap event");return{entry:r,asset:await Yc(r,t)}}function g5(e,t){let r=structuredClone(e);for(let[n,o]of Object.entries(t))if(!Zu(r,n,o))throw new Error(`no parameter is labelled "${n}" on this car \u2014 read vehicle_get for the labels it has`);return r}var By=(e,t)=>{let r=e?.name;return typeof r=="string"&&r?r:t};function y5(e,t){let r={};for(let n of wn){let o=e[n.doc]??[];for(let i of n.slots.slice(1)){let c=t[i.ref],l=typeof c=="string"?o.find(u=>u.id===c):void 0;l&&(r[i.key]={id:l.id,name:By(l.model,l.id)})}let a=t[n.ref],s=typeof a=="string"?o.find(i=>i.id===a):void 0;if(s){r[n.doc]={id:s.id,name:By(s.model,s.id)};continue}if(n.doc==="suspensions"){let i=o.find(c=>c.id===e.activeSuspensionId)??o[0];r[n.doc]=i?{id:i.id,name:By(i.model,i.id),byFallback:!0}:null;continue}r[n.doc]=null}return r}function x5(e){return Object.values(e.events).map(t=>({id:t.id,label:t.label,kind:t.kind,time:t.time,lapTime:t.lapTime,distance:t.distance,laps:t.laps,...t.energy?{energyConsumedKwh:t.energy.consumed,energyRemaining:t.energy.remainingFraction}:{},...t.lapsOverridden?{lapsOverridden:t.lapsOverridden}:{},...t.incomplete?{incomplete:t.incomplete}:{},...t.energyTarget?{energyTarget:t.energyTarget}:{}}))}function aC(e){let t=new Map;for(let{name:r,events:n}of e)for(let o of n){let a=t.get(o.label);a||t.set(o.label,a={event:o.label,finished:[],stopped:[]}),(o.incomplete?a.stopped:a.finished).push(r)}return[...t.values()].filter(r=>r.stopped.length>0)}var sC=e=>e.length<2?e[0]??"":`${e.slice(0,-1).join(", ")} and ${e[e.length-1]}`;async function Hp(e,t,r={}){let n=ss(e,r.settings),{entry:o,asset:a}=await Kp(e,t),s=Eo(e),i=r.vehicleIds?.length?r.vehicleIds.map(f=>{let h=e.vehicles.find(b=>b.id===f);if(!h)throw new Error(`this project holds no vehicle "${f}"`);return h}):e.vehicles.filter(f=>f.visible);if(!i.length)throw new Error("no vehicle is visible in this project \u2014 name some in vehicleIds");let c=i.map(f=>{let h=r.overrides?.[f.id]?g5(f.params,r.overrides[f.id]):f.params;return Io(structuredClone(h),s,n)}),l=ec(go(e.meta.rulesetId,e.rulesets)),u=ac(c,a,n.numerics,l,{racingLine:n.racingLine,standingStart:n.standingStart,lapCounts:n.lapCounts}),m={};i.forEach((f,h)=>{m[f.id]=u[h]});let{scores:d,field:p}=Pg(l,m);return{rulesetId:e.meta.rulesetId,track:o.name,settings:{ggvMode:n.ggvMode,quasiTransient:n.quasiTransient,motorThermal:n.motorThermal,brakeFade:n.brakeFade,airTempC:n.airTempC,...n.air?{air:n.air}:{},diffYaw:n.diffYaw,racingLine:n.racingLine,standingStart:n.standingStart},fleetScored:d!==null,vehicles:i.map((f,h)=>({id:f.id,name:u[h].name||String(f.params.name??f.id),events:x5(u[h]),metrics:Lg(l,u[h],p?.[f.id]),fitted:y5(e,f.params),...d?.[f.id]?{score:{total:d[f.id].total,parts:{...d[f.id].parts}}}:{}})),raw:{results:m,scores:d,field:p}}}async function iC(e,t,r){let n=e.vehicles.find(i=>i.id===r.vehicleId);if(!n)throw new Error(`this project holds no vehicle "${r.vehicleId}"`);let o=ss(e),{asset:a}=await Kp(e,t),s=Io(structuredClone(n.params),Eo(e),o);return oC(s,a,{...r.steps?{steps:r.steps}:{},numerics:o.numerics,...r.tolPct!==void 0?{tolPct:r.tolPct}:{},...r.onStep?{onStep:r.onStep}:{}})}var R5=(e,t)=>e[t]??[],v5=(e,t,r)=>r<=1?[e]:Array.from({length:r},(n,o)=>e+(t-e)*o/(r-1));function zp(e){return e.kind==="param"?v5(e.start,e.end,Math.max(1,Math.round(e.steps))):e.kind==="part"?[...e.partIds]:[...e.values]}var cC=e=>e.kind==="param"?e.label:e.kind==="part"?`${e.part} model`:e.setting;function k5(e,t){let r=e.vehicles.find(i=>i.id===t.vehicleId);if(!r)throw new Error(`this project holds no vehicle "${t.vehicleId}"`);if(!t.axes.length)throw new Error("a sweep needs at least one axis");let n=Io(structuredClone(r.params),Eo(e),ss(e)),o=pM(n,{geometry:!0}),a=Qu(n);for(let i of t.axes){if(i.kind==="param"){let c=a.find(u=>u.label===i.label);if(!c)throw new Error(`no parameter is labelled "${i.label}" on this car \u2014 read vehicle_get for the labels it has`);let l=o[c.key];if(l)throw new Error(`"${i.label}" is a readout on this car, not an input: ${l}. Sweeping it would report exactly zero. Sweep what produces it instead.`)}if(i.kind==="part"){let c=wn.find(l=>l.doc===i.part);if(!c)throw new Error(`"${i.part}" is not a library \u2014 it is one of ${wn.map(l=>l.doc).join(", ")}`);for(let l of i.partIds)if(!R5(e,c.doc).some(u=>u.id===l))throw new Error(`the ${c.label} library holds no "${l}"`)}}let s=t.axes.reduce((i,c)=>i*zp(c).length,1);if(s>Om)throw new Error(`that grid is ${s} runs, over the ${Om} cap \u2014 a run is a whole session. Drop an axis or use fewer steps.`)}var M5=e=>e.map(t=>String(typeof t=="number"?Number(t.toPrecision(4)):t)).join(" \xD7 ");function S5(e,t){let r=[...new Set(e.flatMap(o=>(o.didNotFinish??[]).map(a=>a.label)))],n=e.map(o=>({name:M5(o.at),events:r.map(a=>({label:a,incomplete:o.didNotFinish?.find(s=>s.label===a)}))}));return aC(n).map(({event:o,finished:a,stopped:s})=>{let i=`${s.length} of ${e.length} points did not finish ${o}`;if(!a.length)return`${i}: every time there is a part-distance${t?" and scores zero":""}, so compare laps before time.`;let c=s.length>6?`${s.slice(0,6).join(", ")}, \u2026`:sC(s);return t?`${i}: ${c}. Their time there is a part-distance and scores zero, so read them as stopped, not slow \u2014 a points ranking favours the points that finished over faster ones that stopped.`:`${i}: ${c}. Their time there is a part-distance, so read them as stopped, not slow.`})}function A5(e){let t=[[]];for(let r of e){let n=zp(r),o=[];for(let a of n)for(let s of t)o.push([...s,a]);t=o}return t}async function lC(e,t,r,n){k5(e,r);let o=A5(r.axes),a=[],s=!1;for(let[u,m]of o.entries()){let d=structuredClone(e),p=d.vehicles.find(k=>k.id===r.vehicleId),f={...r.settings},h={};r.axes.forEach((k,v)=>{let x=m[v];if(k.kind==="param")h[k.label]=x;else if(k.kind==="part"){let M=wn.find(A=>A.doc===k.part);p.params[M.ref]=x}else f[k.setting]=x});let b=r.fleet?d.vehicles.filter(k=>k.visible||k.id===r.vehicleId).map(k=>k.id):[r.vehicleId],g=await Hp(d,t,{vehicleIds:b,settings:f,...Object.keys(h).length?{overrides:{[r.vehicleId]:h}}:{}});s=g.fleetScored;let y=g.vehicles.find(k=>k.id===r.vehicleId),R=y.events.flatMap(k=>k.incomplete?[{label:k.label,...k.incomplete}]:[]);a.push({at:m,metrics:y.metrics,...R.length?{didNotFinish:R}:{}}),n?.(u+1,o.length)}let i=Object.keys(a[0]?.metrics??{}),c=[];r.axes.forEach((u,m)=>{if(zp(u).length<2)return;i.some(p=>{if(new Set(a.map(b=>`${b.at[m]}`)).size<2)return!1;let h=a.map(b=>b.metrics[p]).filter(Number.isFinite);return Math.max(...h)-Math.min(...h)>1e-9})||c.push(cC(u))});let l=[];return s&&!r.fleet&&l.push("Points here were scored with this car alone, so it takes the maximum in every event and the points axis is flat by construction. Re-run with fleet: true to price a change in points."),l.push(...S5(a,s)),c.length&&l.push(`Nothing moved along ${c.join(", ")}. Exactly zero is a wiring question before it is a finding: check that a library part is not superseding the value, and that the switch it needs is on.`),{axes:r.axes.map(u=>({kind:u.kind,label:cC(u),values:zp(u)})),runs:a,metricKeys:i,fleetScored:s,flat:c,caveats:l}}var Bfe=Math.PI/180;function $y(e){if(!e.chassis)return e;let{chassis:t,...r}=e;return t.boxes.length?{...r,chassis:{boxes:t.boxes}}:r}var oye=180/Math.PI;var xB={id:"racecar",label:"Race car",description:"Suspension kinematics, tyres, powertrain and quasi-steady-state lap simulation for a four-wheeled race car.",tools:["laptime","garage","kinematics","track","studies","dynamics","tires","aero","powertrain","battery","brakes","dampers","forces","calibration"],defaultRulesetId:bo,templateIds:["fs-ev-comparison","fs-endurance-energy","fs-ev-single","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor","formula-1","touring-car","street-car","cup-car","stock-car","hill-climb","race-truck","suspension","direct-coilover","pushrod","pullrod","third-spring","mcpherson-strut","tyre-study"],collections:[{id:"start",label:"Start here",description:"What the model answers, then cars to build from.",templateIds:["fs-ev-comparison","fs-endurance-energy","suspension","tyre-study","fs-ev-single","formula-1","touring-car"]},{id:"formula-student",label:"Formula Student",description:"Electric and combustion cars on the five Formula Student events, by drive layout.",templateIds:["fs-ev-comparison","fs-endurance-energy","suspension","tyre-study","fs-ev-single","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor"]},{id:"circuits",label:"Circuit racing",description:"Single-seaters, GT, cup and road cars and a race truck on real circuits, with their heights.",templateIds:["formula-1","touring-car","street-car","cup-car","race-truck"]},{id:"ovals-hill-climbs",label:"Ovals and hill climbs",description:"A banked oval, and an open course climbed from rest in thin air.",templateIds:["stock-car","hill-climb"]},{id:"kinematics",label:"Suspension and kinematics",description:"Each suspension architecture: its hardpoints, its roll centres and what it does on track.",templateIds:["suspension","direct-coilover","pushrod","pullrod","third-spring","mcpherson-strut"]},{id:"tyres",label:"Tyres",description:"Grip curves, and what a tyre is worth on track.",templateIds:["tyre-study"]},{id:"powertrain",label:"Energy and powertrain",description:"What a pack lasts, and how each drive layout puts its power down.",templateIds:["fs-endurance-energy","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor"]}]};var Lxe=xB.id;var Wc=.02;function MC(e){let t=Math.max(Wc,Math.abs(e.heaveMotionRatio)),r=Math.max(Wc,Math.abs(e.rollMotionRatio)),o=2*(e.cornerWheelRate+e.heaveWheelRate)/(t*t),a=2*(e.cornerDamper+(e.heaveWheelDamping??0))/(t*t),s=(e.cornerDamper+(e.rollWheelDamping??0))/(r*r);return{heaveRate:o,heaveDamper:a,rollWheelRate:e.cornerWheelRate+e.arbWheelRate,rollDamper:s}}var vB=(e,t)=>({od:t,id:Math.min(e.id,t-.5)}),kB=(e,t)=>e/(2*t*t);function kC(e,t){switch(e.kind){case"ubar":case"blade":case"torsionTube":return{...e,section:vB(e.section,t)};default:return e}}function SC(e,t,r){let n=Math.max(Wc,Math.abs(r));if(e?.kind==="coil"){let l=kB(t,n),u=e.rate;if(typeof u=="number")return{...e,rate:l};let m=zr(u,0);if(!(m>0))return{...e,rate:l};let d=l/m;return{...e,rate:{...u,y:u.y.map(p=>p*d)}}}let o=t/(n*n),a=e&&(e.kind==="ubar"||e.kind==="blade"||e.kind==="torsionTube")?e:{kind:"torsionTube",section:{od:20,id:16},length:400,leverArm:60,G:8e4},s=l=>Ai(kC(a,l),0).rateAtLink,i=4,c=60;if(s(c)<o)return{kind:"direct",wheelRate:t};for(let l=0;l<80&&c-i>1e-9;l++){let u=.5*(i+c);s(u)<o?i=u:c=u}return kC(a,c)}function AC(e,t,r,n){let o=e?.design,a=SC(t?.design,r.rollWheelRate,n);return{heave:{design:{kind:"coil",rate:r.heaveRate,motionRatio:o?.kind==="coil"?o.motionRatio:1,gap:0,bothWays:!0},linkage:e?.linkage,damper:r.heaveDamper},arb:{design:a,linkage:t?.linkage,damper:a.kind==="coil"?r.rollDamper/2:r.rollDamper}}}var MB=Math.PI/180,Yp=1e-6;function SB(e){return!(ve(e.rockerPivotA,e.rockerPivotB)<Yp||ve(e.rockerToPushrod,e.rockerPivotA)<Yp||ve(e.rockerToDamper,e.rockerPivotA)<Yp||ve(e.rockerToDamper,e.damperChassis)<Yp)}function TC(e){if(!SB(e.hardpoints))return!1;let t={...e,config:{...e.config,actuation:"rocker"}};try{let r=tt(t);for(let n of[-20,-1,0,1,20]){let o=ge(r,n,0);if(!o.ok||!Number.isFinite(o.state.metrics.damperLength))return!1}return!0}catch{return!1}}function PC(e){if(e.config.actuation!=="direct"||TC(e))return;let{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}=FB(e);return{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}}var FC=40;function Wp(e,t={}){let r=e.hardpoints,n=r.pushrodOuter,o=r.damperChassis,a=ve(n,o),s=ee(n,U(H(o,n),AB)),i=t.armRod??Math.max(25,.15*a),c=t.armDamper??i,l=[s[0]-FC,s[1],s[2]],u=[s[0]+FC,s[1],s[2]],m=q(H(u,l)),d=H(n,s),p=q(H(d,U(m,wC(d,m)))),f=Ot(p,m,(t.armAngleDeg??60)*MB),h=ee(s,U(f,i)),b=H(o,s),g=q(H(b,U(m,wC(b,m)))),y=U(q(ae(m,g)),t.damperSide??1),R=ee(s,U(y,c));return{...r,rockerPivotA:l,rockerPivotB:u,rockerToPushrod:h,rockerToDamper:R}}var AB=.72,wC=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2];function CC(e){let t=Ke(e,{travelMin:-5,travelMax:5,steps:3}),[r,,n]=t.samples;if(!r||!n)return 0;let o=n.travel-r.travel;return o!==0?Math.abs((n.metrics.damperLength-r.metrics.damperLength)/o):0}function FB(e,t={}){let r=t.target??CC(e),n=t.armAngleDeg,o=Wp(e,{armAngleDeg:n});if(!(r>0))return o;let a=ve(e.hardpoints.pushrodOuter,e.hardpoints.damperChassis),s=Math.max(25,.15*a),i=(()=>{for(let p of[1,-1]){let f=Wp(e,{armRod:s,armAngleDeg:n,damperSide:p}),h={...e,config:{...e.config,actuation:"rocker"},hardpoints:f};try{let b=tt(h),g=ge(b,15,0),y=ge(b,-15,0);if(g.ok&&y.ok&&g.state.metrics.damperLength<y.state.metrics.damperLength)return p}catch{}}return 1})(),c=(p,f)=>{try{return CC({...e,config:{...e.config,actuation:"rocker"},hardpoints:Wp(e,{armRod:p,armAngleDeg:n,armDamper:f,damperSide:i})})}catch{return Number.NaN}},l=[1,.6,.35,.2,1.7,2.6].map(p=>Math.max(12,s*p)),u=s,m=s,d=1/0;for(let p of l){let f=.25*p,h=6*p,b=p;for(let y=0;y<24;y++){let R=(f+h)/2,k=c(p,R);if(!Number.isFinite(k))break;b=R,k<r?f=R:h=R}let g=Math.abs(c(p,b)-r);if(Number.isFinite(g)&&g<d&&(d=g,u=p,m=b),d<1e-4*Math.max(1,r))break}return Wp(e,{armRod:u,armAngleDeg:n,armDamper:m,damperSide:i})}var Yxe=Array.from({length:19},(e,t)=>-45+5*t);var Wxe=Math.PI/180;function wB(e){let t=e.hardpoints,r=q(H(t.rockerPivotB,t.rockerPivotA)),n=cn(t.rockerToDamper,t.rockerPivotA,r),o=.6*sn(H(t.rockerToDamper,n)),a=ae(r,zx),s=sn(a)>1e-6?q(a):q(H(t.rockerToDamper,n));return{outer:ee(n,U(s,o)),inner:ee(n,U(s,-o)),attach:"rocker"}}var CB=(e,t)=>({...e,config:{...e.config,actuation:t}});function Hy(e,t,r,n){let o=r==="front"?e.front:e.rear,a=$u(o),s=o.config.springRate*a*a,i=Q(t,r==="front"?"damper_front":"damper_rear")*a*a,c=r==="front"?t.arbFrontDesign:t.arbRearDesign,l=oo(e,t)[r]??Q(t,r==="front"?"arb_front":"arb_rear"),u=Ta(e,t)[r]??Q(t,r==="front"?"heave_spring_front":"heave_spring_rear"),m=PC(o),d=CB(m?{...o,hardpoints:{...o.hardpoints,...m}}:o,"decoupled"),p=r==="front"?t.heaveFrontDesign:t.heaveRearDesign,f=n?.heave??LC(p?.linkage,w=>Bn(d,w).atDesign)??lf(d,"rockerToRocker"),h=!c||c.design.kind==="none"||c.design.kind==="coil",b=h?"coil":"ubar",g=c?.linkage&&(c.design.kind==="none"||c.linkage.attach!=="rocker")?c.linkage:void 0,y=n?.roll??LC(h?g:c?.linkage,w=>ta(d,w,{kind:b}).atDesign)??(h?wB(d):Dk(d)),R=Bn(d,f).atDesign,k=ta(d,y,{kind:b}).atDesign,v=Ku(e,t),x=MC({cornerWheelRate:s,cornerDamper:i,arbWheelRate:l,heaveWheelRate:u,heaveWheelDamping:r==="front"?v.heaveFront:v.heaveRear,rollWheelDamping:r==="front"?v.rollFront:v.rollRear,heaveMotionRatio:R,rollMotionRatio:k}),M=!c||c.design.kind==="none"?{design:{kind:"coil",rate:1},linkage:y}:{...c,linkage:y},A=AC({design:p?.design??{kind:"none"},linkage:f,damper:p?.damper},M,x,k);return m?{...A,crank:m}:A}function LC(e,t){return e&&Math.abs(t(e))>=Wc?e:void 0}var jp=[{id:"direct",name:"Direct-acting coilover",family:"GT / touring car",description:"Each lower wishbone drives a coilover straight into a chassis tower. No rod or rocker in the load path.",scope:"Both axles",tags:["Double wishbone","Coilover","Direct acting"]},{id:"pushrod",name:"Pushrod suspension",family:"Formula / prototype",description:"A rod from the lower wishbone pushes a rocker on the chassis shoulder. A 225 mm damper runs along the top at 1:1.",scope:"Both axles",tags:["Pushrod","Rocker","Inboard damper"]},{id:"pullrod",name:"Pullrod suspension",family:"Formula / low package",description:"A rod from the upper wishbone pulls a low rocker inside the side wall. A 225 mm damper runs along the floor at 1:1.",scope:"Both axles",tags:["Pullrod","Low rocker","Inboard damper"]},{id:"heave",name:"Third heave spring",family:"Formula / aero platform",description:"The pushrod car plus a front third spring worked by both rockers. It picks up after 5 mm of bump and stays out of roll.",scope:"Both axles, plus a front third spring",tags:["Pushrod","Third spring","Aero platform"]},{id:"decoupled",name:"Twin-rocker-bar decoupled modes",family:"Formula / prototype",description:"Each pushrod turns a long rocker bar. A shock between the bars takes heave, a diagonal one takes roll; no corner springs.",scope:"Both axles",tags:["Two rocker bars","Heave shock","Roll shock"]},{id:"mcpherson",name:"McPherson strut",family:"Road car",description:"A strut clamped to the upright runs up to a top mount on the tower: damper, spring seat and upper link in one. Coilover wishbones at the rear.",scope:"Front struts, rear double wishbones",tags:["McPherson","Strut","Road car"]}],zy=()=>({arbFront:void 0,arbRear:void 0,heaveFront:void 0,heaveRear:void 0}),TB={front:{rockerPivotA:[-47,223,405],rockerPivotB:[-47,267,445],rockerToPushrod:[8,242,429],rockerToDamper:[-47,190,485],damperChassis:[-272,190,485]},rear:{rockerPivotA:[65,228,415],rockerPivotB:[65,272,455],rockerToPushrod:[10,247,439],rockerToDamper:[65,195,495],damperChassis:[290,195,495]}},PB={front:{pushrodOuter:[-3,510,359],rockerPivotA:[-20,174,181],rockerPivotB:[-20,200,139],rockerToPushrod:[18,199,167],rockerToDamper:[-20,102,108],damperChassis:[205,102,108]},rear:{pushrodOuter:[-1,516,365],rockerPivotA:[39,177,181],rockerPivotB:[39,203,139],rockerToPushrod:[1,202,167],rockerToDamper:[39,112,111],damperChassis:[-186,112,111]}},LB=()=>({outer:[0,189,486],attach:"rocker",mount:{kind:"chassis",anchor:[-225,0,486]}}),DB={rate:60,motionRatio:1},EB={front:{rockerPivotA:[-50,310,621],rockerPivotB:[-50,357,659],rockerToPushrod:[10,330,644],rockerToDamper:[-50,281,704],damperChassis:[-275,281,704]},rear:{rockerPivotA:[73,306,621],rockerPivotB:[73,352,659],rockerToPushrod:[13,326,644],rockerToDamper:[73,271,710],damperChassis:[298,271,710]}},IB=e=>e==="front"?{outer:[-2,280,705],attach:"rocker",mount:{kind:"chassis",anchor:[-227,0,705]}}:{outer:[25,270,711],attach:"rocker",mount:{kind:"chassis",anchor:[250,0,711]}},_B={kind:"coil",rate:1560,motionRatio:1,gap:0,bothWays:!0},NB=40,OB={rockerPivotA:[50,130,440],rockerPivotB:[-50,130,440],rockerToPushrod:[10,170,460],rockerToDamper:[-20,64,440],damperChassis:[-20,64,215]},DC=()=>({outer:[-50,130,480],attach:"rocker",shaftStation:-50}),EC=()=>({outer:[50,130,400],inner:[50,130,480],attach:"rocker",shaftStationOuter:50,shaftStationInner:50}),VB=e=>[e[0],e[1],e[2]];function BB(e){let t=r=>({...r,hardpoints:{...r.hardpoints,..._C(OB)},config:{...r.config,actuation:"decoupled"}});return{...e,front:t(e.front),rear:t(e.rear)}}function _C(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,VB(r)]))}function NC(e,t=ko(),r=e==="pull"?PB:TB){let n=(o,a)=>({...o,hardpoints:{...o.hardpoints,..._C(r[a])},config:{...o.config,actuation:"rocker",rodType:e,...e==="pull"?{pushrodAttach:"upperArm"}:{}}});return{...t,front:n(t.front,"front"),rear:n(t.rear,"rear")}}function Up(e,t){let r=Yy(e),n=is(e);if(e==="heave")return{meta:r,vehicle:n,components:{...zy(),heaveFront:{design:{...Ab,...DB},linkage:LB()}}};if(e!=="decoupled")return{meta:r,vehicle:n,components:zy()};let o=Hy(n,t,"front",{heave:DC(),roll:EC()}),a=Hy(n,t,"rear",{heave:DC(),roll:EC()});return{meta:r,vehicle:n,components:{arbFront:o.arb,arbRear:a.arb,heaveFront:o.heave,heaveRear:a.heave}}}function is(e){let{name:t}=Yy(e);if(e==="direct")return{...lc(),name:t};if(e==="mcpherson"){let n=uc(),o=Hm();return{...n,front:{...o,config:{...o.config,loadedRadius:n.front.config.loadedRadius}},name:t}}let r=$B(NC(e==="pullrod"?"pull":"push"));return{...e==="decoupled"?BB(r):r,name:t}}var IC={front:221.7,rear:220.9};function $B(e){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:IC.front}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:IC.rear}}}}function Yy(e){let t=jp.find(r=>r.id===e);if(!t)throw new Error(`Unknown suspension template: ${e}`);return t}function Xp(){let e=t=>({design:{..._B},linkage:IB(t),damper:NB});return{meta:Yy("heave"),vehicle:NC("push",Vg(),EB),components:{...zy(),heaveFront:e("front"),heaveRear:e("rear")}}}var OC=[10,25,50,100,200,300],GB=[{id:"c1",label:"Soft",scale:.7},{id:"c2",label:"Medium",scale:1},{id:"c3",label:"Firm",scale:1.4}],VC=e=>Math.round(e*100)/100;function KB(e,t,r){let n=OC.map(o=>VC(r*o));return{id:e,label:t,speedMmS:[...OC],bumpN:n,reboundN:[...n]}}function HB(e){return{name:e.name,body:{...e.body},curves:GB.map(t=>KB(t.id,t.label,VC(e.coefficient*t.scale)))}}function jc(e,t){let r=(t.heave??t.car).coefficient,n=(t.roll??t.car).coefficient,o=(a,s)=>a?.damper?{...a,damper:s}:a;return{arbFront:o(e.arbFront,n),arbRear:o(e.arbRear,n),heaveFront:o(e.heaveFront,r),heaveRear:o(e.heaveRear,r)}}function Mr(e,t){let r=i=>{if(!i)return;let c=e.dampers.length+1;for(;e.dampers.some(u=>u.id===`dmp${c}`);)c++;let l=`dmp${c}`;return e.dampers.push({id:l,color:bc[e.dampers.length%bc.length],model:HB(i)}),l},n=r(t.car),o=r(t.rear),a=r(t.heave),s=r(t.roll);for(let i of e.vehicles){let c=i.params;c.damperModelId=n,o&&(c.damperModelIdRear=o),a&&(c.heaveDamperModelId=a),s&&(c.rollDamperModelId=s)}}var ut=e=>`${e} (typical)`,Wy={car:{name:ut("Formula Student damper"),coefficient:2.5,body:{extended:249,stroke:55}}},qp={car:Wy.car,heave:{name:ut("Formula Student heave damper"),coefficient:3.4,body:{extended:270,stroke:47}},roll:{name:ut("Formula Student roll damper"),coefficient:3.7,body:{extended:322,stroke:100}}},Qp={car:{name:ut("Formula 1 damper"),coefficient:6,body:{extended:240,stroke:40}},heave:{name:ut("Formula 1 heave damper"),coefficient:40,body:{extended:240,stroke:40}}},BC={car:{name:ut("GT damper"),coefficient:4.5,body:{extended:510,stroke:80}}},jy={car:{name:ut("Sports car damper"),coefficient:2.4,body:{extended:515,stroke:110}}},$C={car:{name:ut("Sports car strut"),coefficient:2.4,body:{extended:310,stroke:120}},rear:jy.car},GC={car:{name:ut("Cup car strut"),coefficient:4,body:{extended:285,stroke:75}},rear:{name:ut("Cup car rear damper"),coefficient:3.5,body:{extended:505,stroke:80}}},KC={car:{name:ut("Stock car front damper"),coefficient:7.5,body:{extended:555,stroke:110}},rear:{name:ut("Stock car rear damper"),coefficient:6.75,body:{extended:555,stroke:110}}},HC={car:{name:ut("Hill-climb front damper"),coefficient:3,body:{extended:285,stroke:65}},rear:{name:ut("Hill-climb rear damper"),coefficient:3.5,body:{extended:285,stroke:65}}},zC={car:{name:ut("Race truck front damper"),coefficient:12,body:{extended:780,stroke:160}},rear:{name:ut("Race truck rear damper"),coefficient:8.5,body:{extended:780,stroke:160}}};function ls(e){return e.vehicles=e.vehicles.slice(0,1),e.activeVehicleId=e.vehicles[0]?.id??null,e}function Dn(e,t){let r=gc(e);return r.meta.rulesetId=t,r}function _o(e,t,r,n){let o=Dn(e,t);return o.suspensions=[{...o.suspensions[0],model:n()}],o.vehicles=[u0(r,"v1",0)],o.activeVehicleId="v1",o}var[,zB,YB,WB,jB,UB,XB,qB]=Wg;function Uy(e,t){delete e.arbFrontDesign,delete e.arbRearDesign,delete e.heaveFrontDesign,delete e.heaveRearDesign,t.arbFront&&(e.arbFrontDesign=structuredClone(t.arbFront)),t.arbRear&&(e.arbRearDesign=structuredClone(t.arbRear)),t.heaveFront&&(e.heaveFrontDesign=structuredClone(t.heaveFront)),t.heaveRear&&(e.heaveRearDesign=structuredClone(t.heaveRear))}function YC(){return{...is("decoupled"),name:ko().name}}var QB=[{label:"Formula Student (decoupled)",vehicle:YC,components:e=>jc(Up("decoupled",e).components,qp)},{label:"Formula 1 (third springs)",vehicle:()=>Xp().vehicle,components:()=>jc(Xp().components,Qp)}],Xy={"direct-coilover":"direct",pushrod:"pushrod",pullrod:"pullrod","third-spring":"heave","mcpherson-strut":"mcpherson"},ZB=[...QB.map(e=>e.vehicle),...Object.values(Xy).map(e=>()=>is(e))];function cs(e){let t=jc(Up("decoupled",e.vehicles[0].params).components,qp);e.suspensions=[{...e.suspensions[0],model:YC()}];for(let r of e.vehicles)Uy(r.params,t);return Mr(e,qp),e}var No={title:"OpenStreetMap",url:"https://www.openstreetmap.org/copyright",licence:"ODbL-1.0",credit:"\xA9 OpenStreetMap contributors"},Zp={title:"USGS 3D Elevation Program, 1 m lidar terrain",url:"https://www.usgs.gov/3d-elevation-program",licence:"public-domain",credit:"U.S. Geological Survey, 3D Elevation Program"},WC={title:"Digitales Gel\xE4ndemodell DGM1 Rheinland-Pfalz",url:"https://www.geoportal.rlp.de/",licence:"dl-de-by-2.0",credit:"\xA9GeoBasis-DE / LVermGeoRP 2025, dl-de/by-2-0, www.lvermgeo.rlp.de [Daten bearbeitet]"},jC={title:"USDA National Agriculture Imagery Program (NAIP), 0.6 m aerial imagery",url:"https://imagery.nationalmap.gov/arcgis/rest/services/USGSNAIPImagery/ImageServer",licence:"public-domain",credit:"USDA Farm Service Agency, National Agriculture Imagery Program, via the USGS National Map"},JB={id:"cota",name:"Circuit of the Americas, Austin",address:"e0c6ea889d708cf15f9c",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[No,Zp,jC]}},e$={id:"laguna-seca",name:"Laguna Seca, Monterey",address:"185b5811b9c423ef44ef",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[No,Zp,jC]}},t$={id:"nordschleife",name:"Nordschleife, N\xFCrburg",address:"74c49603c7b2f15985c6",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[No,WC]}},r$={id:"brands-hatch",name:"Brands Hatch, Kent",address:"c4953e3c25eaba4a5b7e",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[No,{title:"Environment Agency LIDAR Composite DTM, 1 m",url:"https://environment.data.gov.uk/dataset/13787b9a-26a4-4775-8523-806d13af58fc",licence:"OGL-UK-3.0",credit:"\xA9 Environment Agency copyright and/or database right 2022. All rights reserved."}]}},n$={id:"bristol",name:"Bristol, Tennessee",address:"f0e23953669a414ad600",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[No,Zp]}},o$={id:"pikes-peak",name:"Pikes Peak, Colorado",address:"3de137fe33b5c2875036",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[No,Zp]},standingStart:!0},a$={source:"venue",altitudeM:3580,pressure:{kind:"standard"},humidityPct:0},s$=10,i$={id:"nurburg-sprint",name:"Sprintstrecke, N\xFCrburg",address:"1875636cdbb615aa2756",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[No,WC]}};function Oo(e,t){let{id:r,name:n,address:o,provenance:a,standingStart:s}=t,i={kind:"catalogue",id:r,address:o},c=mc(r0({name:n,source:i}).model,structuredClone(a));return e.tracks=[{id:"tr1",name:n,source:i,provenance:c,...s?{standingStart:s}:{}}],e.activeTrackId="tr1",e.settings.standingStart=s===!0,e}function En(e,t,r){let n=e.vehicles[0].params,o=`m${e.motors.length+1}`;e.motors=[...e.motors,{id:o,color:Cn[e.motors.length%Cn.length],model:t}];let a=Jk({},{...n,motorModel:t});n.motorModelId=o,n.motorCount=1,a&&(n.driveline=a),n.gear_ratio&&(n.gear_ratio={...n.gear_ratio,value:r})}var c$=3.8,Jp={hubPlanetary:14.5,inboardChain:4,engineChain:3.4},l$="Hub motor, 35 kW (example)";function qy(e,t,r,n,o,a){let s=e.vehicles[0].params;s.motorModelId=t,s.motorCount=r,s.motorPlacement=n,a&&(s.motorMount=a),s.driven_wheels={...s.driven_wheels,value:n==="awd"?4:2},s.gear_ratio={...s.gear_ratio,value:o}}function UC(e){let t=e.motors.find(r=>r.id==="m1");return t.model={...t.model,name:l$},t.id}function ed(e,t,r){let n=ls(cs(Dn(e,r)));return n.vehicles[0].params.name=t,n}function u$(){let e=ed("Formula Student combustion car","Formula Student combustion","fs-cv");En(e,Qg(),Jp.engineChain);let t=e.vehicles[0].params;return t.power_limit_kw&&(t.power_limit_kw={...t.power_limit_kw,value:0}),t.endurance_reserve&&(t.endurance_reserve={...t.endurance_reserve,value:0}),e}function m$(){let e=ed("Formula Student AWD car","Formula Student AWD","fs-ev");return qy(e,UC(e),4,"awd",Jp.hubPlanetary,"hub"),e}function p$(){let e=ed("Formula Student RWD hub-motor car","Formula Student RWD hub motors","fs-ev");return qy(e,UC(e),2,"rear",Jp.hubPlanetary,"hub"),e}function d$(){let e=ed("Formula Student one-motor car","Formula Student RWD one motor","fs-ev"),t=`m${e.motors.length+1}`;return e.motors=[...e.motors,{id:t,color:Cn[e.motors.length%Cn.length],model:qg()}],qy(e,t,1,"rear",Jp.inboardChain),e.vehicles[0].params.driveline={rear:structuredClone(vt.clutch)},e}function f$(){let e=ls(cs(Dn("Formula Student endurance energy","fs-ev"))),t=e.vehicles[0],r=structuredClone(t);if(r.id="v2",r.color=hc[1],r.params.name=`${t.params.name} flat out`,!r.params.endurance_reserve)throw new Error("the Formula Student preset states no energy reserve");return r.params.endurance_reserve={...r.params.endurance_reserve,value:0},e.vehicles.push(r),e}function h$(){let e=Xp(),t=_o("Formula 1 car","trackday",zB,()=>e.vehicle);return Uy(t.vehicles[0].params,jc(e.components,Qp)),Mr(t,Qp),En(t,Zg(),c$),Oo(t,JB)}function XC(e="GT car",t=lc){let r=_o(e,"trackday",YB,t);return Mr(r,BC),En(r,wA(),r.vehicles[0].params.gear_ratio.value),Oo(r,e$)}function qC(e="Sports car",t=uc,r=jy){let n=_o(e,"trackday",WB,t);return Mr(n,r),En(n,CA(),n.vehicles[0].params.gear_ratio.value),Oo(n,t$)}function b$(){let e=_o("Cup car","trackday",jB,hA);return Mr(e,GC),En(e,TA(),e.vehicles[0].params.gear_ratio.value),Oo(e,r$)}function g$(){let e=_o("Stock car","trackday",UB,bA);return Mr(e,KC),En(e,PA(),e.vehicles[0].params.gear_ratio.value),Oo(e,n$)}function y$(){let e=_o("Hill-climb prototype","trackday",XB,gA);return Mr(e,HC),En(e,LA(),e.vehicles[0].params.gear_ratio.value),e.settings.air=structuredClone(a$),e.settings.airTempC=s$,Oo(e,o$)}function x$(){let e=_o("Race truck","trackday",qB,yA);return Mr(e,zC),En(e,DA(),e.vehicles[0].params.gear_ratio.value),Oo(e,i$)}function R$(e){let t=jp.find(o=>o.id===e);if(e==="direct")return XC(t.name,()=>is(e));if(e==="mcpherson")return qC(t.name,()=>is(e),$C);let r=ls(Dn(t.name,"trackday")),n=Up(e,r.vehicles[0].params);return r.suspensions=[{...r.suspensions[0],model:n.vehicle}],Uy(r.vehicles[0].params,n.components),Mr(r,Wy),r}function Uc(e,t,r){let n=Xy[e],o=jp.find(a=>a.id===n);return{id:e,domain:"racecar",kind:"start",summary:t,title:o.name,blurb:`${o.description} ${r} Move a hardpoint in Kinematics and watch the motion ratio, camber and roll centre follow, then what it costs on track.`,tags:["kinematics","suspension",...o.tags.map(a=>a.toLowerCase())],openTool:"kinematics",load:()=>R$(n)}}var v$=[{id:"fs-ev-comparison",domain:"racecar",kind:"study",summary:"Four Formula Student cars scored on all five events: what mass, power and downforce buy.",title:"Formula Student \u2014 car comparison",blurb:"A generic Formula Student electric car and three what-ifs \u2014 15 % more downforce, 15 kg lighter, 15 % more power \u2014 scored side by side on the Formula Student electric events. All four run decoupled heave and roll suspension. A good first look at what each change buys.",tags:["formula student","comparison","lap sim"],openTool:"laptime",load:()=>cs(Dn("Formula Student comparison","fs-ev"))},{id:"fs-endurance-energy",domain:"racecar",kind:"study",summary:"The FS car flat out against its energy target: which finishes endurance, and the points.",title:"Formula Student \u2014 endurance energy",blurb:"The generic Formula Student electric car twice, scored together on the Formula Student electric events: once driven to its energy target, once flat out. The two differ in the endurance reserve and nothing else. Flat out the car laps faster and its pack runs out before the flag; on the target its speed is capped so the pack finishes with 5 % left. The endurance event shows the charge lap by lap, and the points what running dry costs.",tags:["formula student","endurance","energy","battery"],openTool:"laptime",load:f$},{id:"fs-ev-single",domain:"racecar",kind:"start",summary:"A generic Formula Student electric car on the five events, to set up as your own.",title:"Formula Student \u2014 single car",blurb:"One generic Formula Student electric car on the Formula Student electric events: 300 kg with driver, two motors, 80 kW, 10-inch tyres, decoupled heave and roll suspension. The uncluttered starting point for setting up your own car.",tags:["formula student","lap sim"],openTool:"laptime",load:()=>ls(cs(Dn("Formula Student car","fs-ev")))},{id:"fs-combustion",domain:"racecar",kind:"start",summary:"A restricted 600 cc four through six gears and a clutch-pack diff, on the CV events.",title:"Formula Student \u2014 combustion, LSD",blurb:"The generic Formula Student car with an engine: a restricted 600 cc four of about 64 kW through a six-speed box and a chain to a clutch-pack limited-slip diff, on the Formula Student combustion events. The same 300 kg chassis, tyres and decoupled suspension as the electric layouts, so the drive is the difference. Efficiency is scored on the work at the crankshaft until fuel is modelled. Representative of the class, not a measurement of any car.",tags:["formula student","combustion","engine","limited-slip diff","lsd","lap sim"],openTool:"laptime",load:u$},{id:"fs-ev-awd",domain:"racecar",kind:"start",summary:"All-wheel drive from a motor in each hub, held to 80 kW at the pack.",title:"Formula Student \u2014 AWD, four hub motors",blurb:"The generic Formula Student electric car with a motor in each of its four hubs: 35 kW hub motors on 14.5 : 1 planetaries, held to the rules\u2019 80 kW at the pack, each wheel\u2019s torque its own and every wheel braking back into the pack. The same 300 kg chassis, tyres, suspension and pack as the other layouts, so the drive is the difference; the hub motors\u2019 unsprung mass is not added. Representative of the class, not a measurement of any car.",tags:["formula student","awd","all-wheel drive","hub motors","outboard motors","lap sim"],openTool:"laptime",load:m$},{id:"fs-ev-rwd-hubs",domain:"racecar",kind:"start",summary:"Rear-wheel drive from a motor in each rear hub, with no diff between them.",title:"Formula Student \u2014 RWD, two hub motors",blurb:"The generic Formula Student electric car driven by a motor in each rear hub: two 35 kW hub motors on 14.5 : 1 planetaries with no differential between them, so each rear wheel\u2019s torque is set on its own. The pair cannot use all of the rules\u2019 80 kW. The same 300 kg chassis, tyres, suspension and pack as the other layouts, so the drive is the difference. Representative of the class, not a measurement of any car.",tags:["formula student","rwd","rear-wheel drive","hub motors","outboard motors","lap sim"],openTool:"laptime",load:p$},{id:"fs-ev-one-motor",domain:"racecar",kind:"start",summary:"One inboard motor chained to a clutch-pack diff on the rear axle.",title:"Formula Student \u2014 RWD, one motor, LSD",blurb:"The generic Formula Student electric car on one inboard motor: an axial-flux motor of 230 Nm on the chassis, chained at 4 : 1 to a clutch-pack limited-slip diff on the rear axle. The rules\u2019 80 kW at the pack holds it below its peak, and it brakes back into the pack through the diff. The same 300 kg chassis, tyres, suspension and pack as the other layouts, so the drive is the difference. Representative of the class, not a measurement of any car.",tags:["formula student","rwd","inboard motor","limited-slip diff","lsd","lap sim"],openTool:"laptime",load:d$},{id:"formula-1",domain:"racecar",kind:"start",summary:"A generic Formula 1 car on a flying lap of Austin.",title:"Formula 1 car",blurb:"A generic Formula 1 car of the 18-inch era at Austin: 798 kg with driver, a 735 kW power unit through eight gears and a clutch-pack diff, four and a half square metres of lift area on a 3.6 m wheelbase, pushrods with a third spring and heave damper on each axle, slicks with 1.8 of peak grip. One flying lap, no scoring. Every number is representative of the class, none is a measurement.",tags:["formula 1","lap sim","aero"],openTool:"laptime",load:h$},{id:"touring-car",domain:"racecar",kind:"start",summary:"A generic GT car on a flying lap of Laguna Seca.",title:"GT car",blurb:"A generic GT car at Laguna Seca: 1300 kg with driver, a 410 kW four-litre through six gears and a clutch-pack diff, 2.8 m\xB2 of lift area, coilovers on double wishbones, 18-inch slicks. One flying lap, no scoring. Representative of the class, not a measurement of any car.",tags:["gt","lap sim"],openTool:"laptime",load:XC},{id:"street-car",domain:"racecar",kind:"start",summary:"A generic sports car on road tyres, round the Nordschleife.",title:"Sports car",blurb:"A generic sports car on the Nordschleife: 1600 kg with driver, a 220 kW turbocharged six through a six-speed double-clutch box and an open diff, road tyres with about 1.0 of grip, soft springs and a little aerodynamic lift. One flying lap, no scoring. The car to start from when the question is a road car, and the one that shows what a race car's numbers actually buy.",tags:["sports car","road car","lap sim"],openTool:"laptime",load:qC},{id:"cup-car",domain:"racecar",kind:"start",summary:"A generic front-driven cup hatchback round Brands Hatch.",title:"Cup car",blurb:"A generic front-wheel-drive cup hatchback at Brands Hatch: 1265 kg with driver, a 250 kW two-litre turbo through six gears and a clutch-pack diff, a splitter and a wing, a McPherson strut front, 18-inch slicks. One flying lap, no scoring. Representative of the class, not a measurement of any car.",tags:["cup car","front-wheel drive","lap sim"],openTool:"laptime",load:b$},{id:"stock-car",domain:"racecar",kind:"start",summary:"A generic stock car on Bristol\u2019s half-mile, banked 25\xB0.",title:"Stock car",blurb:"A generic stock car of the American oval series at Bristol, the half-mile banked 25\xB0: 1620 kg with driver, a 500 kW 5.9-litre V8 through five gears and a clutch-pack diff, double wishbones on stiff springs, 18-inch slicks, set up the same on both sides. One flying lap, no scoring. Representative of the class, not a measurement of any car.",tags:["stock car","oval","lap sim"],openTool:"laptime",load:g$},{id:"hill-climb",domain:"racecar",kind:"start",summary:"A generic hill-climb prototype up Pikes Peak, from rest, in thin air.",title:"Hill-climb prototype",blurb:"A generic hill-climb sports prototype on Pikes Peak, 19.99 km and 1,440 m up to the summit: 650 kg with driver, a 330 kW turbocharged two-litre through six gears and a clutch-pack diff, 3 m\xB2 of lift area, pushrods, 13-inch slicks. It runs in the mountain\u2019s thin air, which costs its wings a third of their downforce. One run, no scoring. Representative of the class, not a measurement of any car.",tags:["hill climb","altitude","lap sim"],openTool:"laptime",load:y$},{id:"race-truck",domain:"racecar",kind:"start",summary:"A generic European race truck round the N\xFCrburg Sprintstrecke, held to 160 km/h.",title:"Race truck",blurb:"A generic European circuit race truck on the N\xFCrburg Grand Prix circuit\u2019s 3.6 km Sprintstrecke: a cab-over tractor at the class\u2019s 5300 kg minimum, 60 % of it on the front axle, an 880 kW 13-litre diesel through a twelve-speed box to a locked rear axle, geared to the 160 km/h the rules hold it to, 315/70 R22.5 tyres. One flying lap, no scoring. Representative of the class, not a measurement of any truck.",tags:["race truck","truck racing","lap sim"],openTool:"laptime",load:x$},{id:"suspension",domain:"racecar",kind:"study",summary:"The FS car\u2019s decoupled wishbones: move a hardpoint and watch the roll centre follow.",title:"Suspension kinematics study",blurb:"Opens on the double-wishbone editor with one Formula Student car. Move a hardpoint and watch camber, bump steer, motion ratio and roll-centre migration follow \u2014 then see what it costs on track.",tags:["kinematics","geometry"],openTool:"kinematics",load:()=>ls(cs(Dn("Suspension study","trackday")))},Uc("direct-coilover","The GT car\u2019s wishbones driving coilovers straight into the towers, at Laguna Seca.","On the GT car, at Laguna Seca."),Uc("pushrod","The FS car on pushrods: a rod from each lower wishbone works a rocker.","On the Formula Student car, at FSG."),Uc("pullrod","The FS car on pullrods: a rod from each upper wishbone pulls a low rocker.","On the Formula Student car, at FSG."),Uc("third-spring","The pushrod FS car plus a front third spring that picks up after 5 mm of bump.","On the Formula Student car, at FSG."),Uc("mcpherson-strut","The sports car on McPherson struts at the front and double wishbones at the rear.","On the sports car, at the Nordschleife."),{id:"tyre-study",domain:"racecar",kind:"study",summary:"The FS tyre\u2019s grip curves at three loads, beside the other classes\u2019 tyres.",title:"Tyre model study",blurb:"One Formula Student car on its Magic Formula tyre, opened on the tyre analysis, where the grip curves that drive the whole lap come from. The library beside it holds the other seven classes' tyres and the illustrative MF6.2 example to compare against.",tags:["tyres","magic formula"],openTool:"tires",load:()=>ls(cs(Dn("Tyre study","fs-ev")))}],QC=v$.map(e=>({...e,load:()=>m0(e.load())}));var ZC={width:320,height:200},PRe=[.6*ZC.width-9,.6*ZC.height-9];var JC=new WeakMap,eT=new WeakMap,Qy=e=>JSON.stringify(e,(t,r)=>r===1/0?"Infinity":r);function tT(e,t){if(!t){let a=JC.get(e);return a||(a=Dt(e),JC.set(e,a)),a}let r=eT.get(e);r||(r=new Map,eT.set(e,r));let n=Qy(t),o=r.get(n);return o||(r.size>=4&&r.clear(),o=Dt(e,t),r.set(n,o)),o}var S$=Math.PI/180,A$=e=>e>1?e/100:e;function Xc(e){let t=null;return()=>(t??={v:e()}).v}function rT(e){let t=Ke(e,{travelMin:-1,travelMax:1,steps:3}).samples[1],r=t.metrics.motionRatio??1;return{motionRatio:r,wheelRate:t.metrics.wheelRate??e.config.springRate*r*r}}var nT=new WeakMap,Zy={heave:0,pitch:0,roll:0,steer:0},oT=[0,1,2,3,4],aT=[-20,-10,0,10,20];function iT(e,t){let r=Yr(e,Zy),n=["front","rear"],o=c=>{let l=wi(c);return l?(l.left+l.right)/2:Number.NaN},a=n.map(c=>o(r[c])),s=n.map(()=>({rc:[],split:[]}));for(let c of oT){let l=c===0?null:Yr(e,{...Zy,roll:c*S$});n.forEach((u,m)=>{let d=l?wi(l[u]):null,p=d&&Number.isFinite(a[m]);s[m].rc.push(p?t[m]+(d.left+d.right)/2-a[m]:t[m]),s[m].split.push(p?(d.left-d.right)/2:0)})}let i=n.map(()=>[]);for(let c of aT){let l=c===0?null:Yr(e,{...Zy,heave:-c});n.forEach((u,m)=>{let d=l&&l[u].valid&&r[u].valid;i[m].push(d?t[m]+l[u].height-r[u].height:t[m])})}return{roll:{rollDeg:oT,rcFront:s[0].rc,rcRear:s[1].rc,rcSplitFront:s[0].split,rcSplitRear:s[1].split},heave:{drop:aT,rcFront:i[0],rcRear:i[1]}}}var sT=new WeakMap;function F$(e,t,r,n){let o=sT.get(e);o||(o=new Map,sT.set(e,o));let a=`${Qy(r)}|${n[0]}|${n[1]}`,s=o.get(a);if(!s){o.size>=4&&o.clear();try{s=iT(tT(e,r),n)}catch{s=t.rigidMigration(n)}o.set(a,s)}return s}function w$(e){let t=nT.get(e);if(t)return t;let r=Dt(e),n=Yr(r,{heave:0,pitch:0,roll:0,steer:0}),o=rT(e.front),a=rT(e.rear),s={wheelbase:e.config.wheelbase,trackFront:gt(e.front),trackRear:gt(e.rear),mrFront:o.motionRatio,mrRear:a.motionRatio,wheelRateFront:o.wheelRate,wheelRateRear:a.wheelRate,unsprungCgHeight:e.front.config.loadedRadius,rcHeightFront:n.front.valid?n.front.heightAboveGround:0,rcHeightRear:n.rear.valid?n.rear.heightAboveGround:0,rcGainFront:Ca(n.front),rcGainRear:Ca(n.rear),rigidMigration:i=>iT(r,i),kinFront:Xc(()=>pa(e.front)),kinRear:Xc(()=>pa(e.rear))};return nT.set(e,s),s}function cT(e,t,r,n){let o=w$(e),a=oo(e,t),s=Ta(e,t),i=Wk(e,t),c=Ku(e,t),l=jk(e,t),u=Uk(t),m=Hu(e,t),d=no(e.front),p=no(e.rear),f=ro(t.damperModel,t.damperSetup,o.mrFront,o.mrRear,t.damperModelRear??t.damperModel),h={rho:t.rho.value,area:t.A.value,cl:t.c_l.value,cw:t.c_w.value,copLongFront:1-Math.max(0,Math.min(1,Q(t,"cop_long"))),copHeight:Q(t,"cop_height"),...t.aeroModel?{model:t.aeroModel}:{},rideHeightFront:Q(t,"ride_height_front"),rideHeightRear:Q(t,"ride_height_rear")},b=9.81,g=A$(t.front_mass_diss.value),y=La(t,r,n),R=Pe(y.front),k=y.rear===y.front?R:Pe(y.rear),v=n??t.tireModelRear??r,x=t.m.value*b*g/2,M=t.m.value*b*(1-g)/2,A=R.corneringStiffness(x),w=k.corneringStiffness(M),C=(r?R.verticalStiffness():0)||Q(t,"tire_vertical_rate"),T=(v?k.verticalStiffness():0)||Q(t,"tire_vertical_rate"),F=lr(r)??0,S=lr(v)??0,P=Uu({freeRadius:F,staticLoad:x,tyreRate:C,surveyed:e.front.config.loadedRadius},{freeRadius:S,staticLoad:M,tyreRate:T,surveyed:e.rear.config.loadedRadius},g),L=Ht(F,x,C,e.front.config.loadedRadius),D=Ht(S,M,T,e.rear.config.loadedRadius),I=[Wr(o.rcHeightFront,o.rcGainFront,e.front.config.loadedRadius,L),Wr(o.rcHeightRear,o.rcGainRear,e.rear.config.loadedRadius,D)],O=Xc(()=>Di(o.kinFront(),Q(t,"camber_front_deg"))),_=Xc(()=>Di(o.kinRear(),Q(t,"camber_rear_deg"))),z=Xc(()=>F$(e,o,Ja(B),I)),E=ii({...t,wheelbase:{...t.wheelbase,value:o.wheelbase}}),N=Li(t),B={massTotal:t.m.value,frontMassFrac:g,steeringSystem:t.steeringSystem,tv:Cu(t),cgHeight:Pa(Q(t,"cg_height"),t.cgReference?.standingRadius,P),cgStandingRadius:P,wheelbase:o.wheelbase,trackFront:o.trackFront,trackRear:o.trackRear,wheelRateFront:d?0:o.wheelRateFront,wheelRateRear:p?0:o.wheelRateRear,decoupledFront:d,decoupledRear:p,...u.front?{elementLinkagesFront:u.front}:{},...u.rear?{elementLinkagesRear:u.rear}:{},...m.front.source==="part"?{cornerCoiloverFront:m.front.coilover}:{},...m.rear.source==="part"?{cornerCoiloverRear:m.rear.coilover}:{},...m.heaveFront.coilover?{heaveCoiloverFront:m.heaveFront.coilover}:{},...m.heaveRear.coilover?{heaveCoiloverRear:m.heaveRear.coilover}:{},...i.front&&!d?{heaveSeatFront:i.front}:{},...i.rear&&!p?{heaveSeatRear:i.rear}:{},...m.rollFront.coilover?{rollCoiloverFront:m.rollFront.coilover}:{},...m.rollRear.coilover?{rollCoiloverRear:m.rollRear.coilover}:{},tireRate:C,...T!==C?{tireRateRear:T}:{},tireDamping:Q(t,"tire_vertical_damping"),arbFront:a.front??Q(t,"arb_front"),arbRear:a.rear??Q(t,"arb_rear"),brakeBalanceFront:E.balanceFront,brakes:E,...N?{driveline:N}:{},heaveSpringFront:s.front??Q(t,"heave_spring_front"),heaveSpringRear:s.rear??Q(t,"heave_spring_rear"),unsprungPerCorner:Q(t,"unsprung_mass"),unsprungCgHeight:Ht(F,x,C,o.unsprungCgHeight),tyreFreeRadius:F,...S!==F?{tyreFreeRadiusRear:S}:{},rcHeightFront:I[0],rcHeightRear:I[1],corneringStiffnessFront:A,corneringStiffnessRear:w,get kinFront(){return O()},get kinRear(){return _()},damperFront:d?0:f?.front?.rate??Q(t,"damper_front")*o.mrFront*o.mrFront,damperRear:p?0:f?.rear?.rate??Q(t,"damper_rear")*o.mrRear*o.mrRear,...f?.front&&!d?{damperCurveFront:f.front.curve}:{},...f?.rear&&!p?{damperCurveRear:f.rear.curve}:{},heaveDamperFront:l.heaveFront?.rate??c.heaveFront,heaveDamperRear:l.heaveRear?.rate??c.heaveRear,rollDamperFront:l.rollFront?.rate??c.rollFront,rollDamperRear:l.rollRear?.rate??c.rollRear,...l.heaveFront?{heaveDamperCurveFront:l.heaveFront.curve}:{},...l.heaveRear?{heaveDamperCurveRear:l.heaveRear.curve}:{},...l.rollFront?{rollDamperCurveFront:l.rollFront.curve}:{},...l.rollRear?{rollDamperCurveRear:l.rollRear.curve}:{},unsprungCornerMass:Q(t,"unsprung_mass"),get rollCentreCurve(){return z().roll},get rcHeaveCurve(){return z().heave},aero:h,yawInertia:Q(t,"I_yaw"),rollInertia:Q(t,"I_roll"),pitchInertia:Q(t,"I_pitch"),get steerFront(){return zu(e.front,L)},ackermannPct:Q(t,"ackermann_pct"),toeFrontDeg:Q(t,"toe_front_deg"),toeRearDeg:Q(t,"toe_rear_deg")};return B}var uT=e=>({tire:t=>t==null?void 0:t===e.tireModelIdRear&&e.tireModelRear?e.tireModelRear:e.tireModel,motor:()=>e.motorModel,aero:()=>e.aeroModel,battery:()=>e.batteryModel,brake:()=>e.brakeModel,damper:t=>t!=null&&t===e.damperModelIdRear&&e.damperModelRear?e.damperModelRear:t!=null&&t===e.heaveDamperModelId?e.heaveDamperModel:t!=null&&t===e.rollDamperModelId?e.rollDamperModel:e.damperModel}),ex={ggvMode:"twoTrack"},lT=new WeakMap;function tx(e,t=ex){let r=lT.get(e.vehicle);r||lT.set(e.vehicle,r=new WeakMap);let n=r.get(e.params);n||r.set(e.params,n=new Map);let o=JSON.stringify(t),a=n.get(o);if(!a){n.size>=8&&n.clear();let s={...uT(e.params),suspensionOf:()=>e.vehicle};n.set(o,a=Io(e.params,s,t))}return a}var mT=(e=ex)=>t=>tx(t,e),pT=(e=ex)=>t=>cT(t.vehicle,Vy(t.params,uT(t.params),e),t.params.tireModel,t.params.tireModelRear);function C$(e,t){return tx(e,t.switches)}var rx=e=>en(e?.rulesets);function dT(e,t,r,n,o={},a=()=>r.standingStart){let s=tx(n,r.switches),i=(l,u)=>{let m=Nm(l,t,{racingLine:r.racingLine,params:s});return{asset:m.asset,numerics:m.numerics,standingStart:u,racingLine:r.racingLine}},c=Object.fromEntries(Object.entries(o).map(([l,u])=>[l,i(u,a(l))]));return{course:e?i(e,r.standingStart):null,numerics:t,tracks:c,switches:r.switches}}var fT=e=>[...new Set(e.lap.courses.flatMap(t=>t.course.kind==="track"?[t.course.trackId]:[]))],hT=e=>{let t=e?.session;return t?{sessionParams:r=>C$(r,t),session:()=>t}:{}},td=e=>({metrics:rx(e),assemble:pT(e?.switches),simParams:mT(e?.switches),projectTrack:()=>e?.course??null,libraryTrack:t=>e?.tracks?.[t]??null,numerics:e?.numerics,...hT(e)}),T$=(e,t)=>({density:e.density,envelope:e.envelope,states:e.states,operating:e.operating,lap:e.lap,assemble:pT(t?.switches),simParams:mT(t?.switches),projectTrack:()=>t?.course??null,libraryTrack:r=>t?.tracks?.[r]??null,numerics:t?.numerics,...hT(t)}),bT="nelder-mead",gT=600,qc=[0,.15,.15];function yT(e,t,r,n=qc.length){let o=ax(t);return qc.slice(0,Math.max(1,n)).map((a,s)=>({...e,seed:s+1,startJitter:a,car:o,...r?{lap:r}:{}}))}function xT(e,t,r=.5){let n=[];return e.forEach((o,a)=>{let s=o.hi-o.lo;if(s<=0)return;let i=Math.min(r,s*.01);t[a]<=o.lo+i?n.push({id:o.id,name:o.name,unit:o.unit,at:"lo",value:t[a],moved:t[a]-o.start}):t[a]>=o.hi-i&&n.push({id:o.id,name:o.name,unit:o.unit,at:"hi",value:t[a],moved:t[a]-o.start})}),n}function RT(e,t,r,n,o=.01){let a=rx(n).byId;return P$(e,t,r,n).filter(s=>s.excess>-o*(a[s.metricId]?.scale??1))}function P$(e,t,r,n){let o;try{o=Tn(Vp(e,t,r),T$(t,n))}catch{return[]}return L$(o,t,rx(n))}function L$(e,t,r){let n=[];for(let o of t.constraints){let a=r.byId[o.metricId];if(!a)continue;let s=St(e,a,o.at);if(!Number.isFinite(s))continue;let i=`${et(a)}${Hc(o.at,a)}`;n.push({key:o.key,metricId:o.metricId,label:i,unit:a.unit==="-"?"":a.unit,value:s,excess:Kc(o,s)})}return n}var D$=.05;function E$(e,t){if(t.id.startsWith("hp.")||_p(t.id))return 1;let r=/^rocker\.(front|rear)\.(\w+)$/.exec(t.id);if(r){let a=r[1]==="front"?e.vehicle.front:e.vehicle.rear;return hy(Ln(a.hardpoints),r[2],1)}let n=/^arm\.(front|rear)\.(uca|lca)\.(\w+)$/.exec(t.id);if(!n)return null;let o=n[1]==="front"?e.vehicle.front:e.vehicle.rear;return py(tn(o.hardpoints,n[2]),n[3],1)}function vT(e,t,r){let n=r.filter(d=>d.score.feasible);if(n.length<2)return null;let o=t.map(d=>E$(e,d)),a=o.every(d=>d!==null)?"mm":null,s=0,i="",c=0,l=n.reduce((d,p)=>p.score.total<d.score.total?p:d);for(let d of n)if(d!==l)for(let p=0;p<t.length;p++){let f=Math.abs(d.x[p]-l.x[p])*(o[p]??1);c+=f*f,f>s&&(s=f,i=t[p].name)}let u=n.map(d=>d.score.total),m=l.score.terms.reduce((d,p)=>d+(p.resolution??0),0);return{distance:Math.sqrt(c),worst:s,worstName:i,scoreSpread:Math.max(...u)-Math.min(...u),tolerance:Math.max(D$,m),unit:a}}var I$={steeringSystem:!0,brakeSetup:!0,driveline:!0,heaveFrontDesign:!0,heaveRearDesign:!0,arbFrontDesign:!0,arbRearDesign:!0},kT=e=>Object.hasOwn(I$,e);function Jy(e){let[t,r]=e.split("."),n=r==="front"?"Front":r==="rear"?"Rear":null;return n?t==="heave"?`heave${n}Design`:t==="roll"?`arb${n}Design`:null:null}function _$(e){let t=e.split(".")[0];return t==="hp"||t==="arm"||t==="rocker"?"hardpoint":t==="cfg"?"config":t==="kc"?"compliance":t==="param"?"param":t==="brakeModel"?"part":kT(t)||Jy(e)?"block":null}function nx(e,t){t=_t(e,t);let r=Wt(e);return[...t.variables,...t.followers??[]].filter(n=>r[n.id]&&!r[n.id].supersededBy&&!_$(n.id)).map(n=>lt(r[n.id]))}function MT(e,t,r){t=_t(e,t);let n=Wt(e),o=Vp(e,t,r),a=[],s=new Set,i=new Set;for(let c of[...t.variables,...t.followers??[]]){let l=n[c.id];if(!l||l.supersededBy)continue;let u=l.read(o),[m,d,p,f]=c.id.split(".");if(m==="rocker"){let h=`${d}.rocker`;if(i.has(h))continue;i.add(h);let b=d==="front"?o.vehicle.front:o.vehicle.rear;for(let g of[Po.fore,Po.aft]){let y=b.hardpoints[g];for(let R=0;R<3;R++)a.push({kind:"hardpoint",axle:d,key:g,axis:R,value:y[R]})}}else if(m==="arm"){let h=`${d}.${p}`;if(i.has(h))continue;i.add(h);let b=d==="front"?o.vehicle.front:o.vehicle.rear,g=er[p];for(let y of[g.fore,g.aft]){let R=b.hardpoints[y];for(let k=0;k<3;k++)a.push({kind:"hardpoint",axle:d,key:y,axis:k,value:R[k]})}}else if(m==="hp"&&kr(c.id)){let h=`${d}.${p}`;if(i.has(h))continue;i.add(h);let b=(d==="front"?o.vehicle.front:o.vehicle.rear).hardpoints[p];for(let g=0;g<3;g++)a.push({kind:"hardpoint",axle:d,key:p,axis:g,value:b[g]})}else if(m==="hp")a.push({kind:"hardpoint",axle:d,key:p,axis:"xyz".indexOf(f),value:u});else if(m==="cfg")a.push({kind:"config",axle:d,field:p,value:u});else if(m==="kc"){if(s.has(`kc.${d}`))continue;s.add(`kc.${d}`);let h=d==="front"?o.vehicle.front:o.vehicle.rear;a.push({kind:"compliance",axle:d,value:h.compliance})}else if(m==="param")a.push({kind:"param",label:lt(l),value:u});else if(m==="brakeModel"){if(s.has(m))continue;if(s.add(m),!o.params.brakeModel)throw new Error(`optimiser: "${c.id}" left the car with no brake part to adopt`);a.push({kind:"part",key:"brakeModel",fromId:e.params.brakeModelId,value:o.params.brakeModel})}else if(kT(m)||Jy(c.id)){let h=Jy(c.id)??m;if(s.has(h))continue;s.add(h);let b=o.params[h];if(!b)throw new Error(`optimiser: "${c.id}" left the car with no ${h} to adopt`);a.push({kind:"block",key:h,value:b})}else throw new Error(`optimiser: Adopt has no way to write "${c.id}" back into the project`)}return a}function ox(e){let t=performance.now(),r=td(e.lap),n=e.follow?Fy(e.car,e.spec,r):e.spec,{dead:o,unprobed:a,...s}=Py(e.car,n,r);return{...s,deadIds:o.map(i=>i.id),unprobedIds:a.map(i=>i.id),elapsedMs:performance.now()-t,...e.follow?{followed:!0,fromCar:n===e.spec?null:{states:n.states,envelope:n.envelope}}:{}}}var ax=e=>e.vehicle.chassis?{...e,vehicle:$y(e.vehicle)}:e;function ST(e,t){try{let r=sx(e.car,e.spec,e.lap),n=ha.find(u=>u.name===e.method);if(!n)throw new Error(`unknown method "${e.method}"`);t({kind:"progress",seed:e.seed,progress:{evaluations:0,budget:e.budget,x:Er(r.variables),score:Dr(r,Er(r.variables)),infeasible:0}});let o=e.from,a=o?{...r,variables:r.variables.map((u,m)=>({...u,start:Number.isFinite(o[m])?o[m]:u.start}))}:r,s=performance.now(),i=n.run(a,{budget:e.budget,seed:e.seed,startJitter:e.startJitter,progressEvery:20,onProgress:u=>t({kind:"progress",seed:e.seed,progress:u})}),c=performance.now()-s,l=i.score.feasible&&xy(r.variables)?vy(r,i.x,i.score):void 0;t({kind:"done",seed:e.seed,result:l?{...i,snapped:l}:i,elapsedMs:c})}catch(r){t({kind:"error",seed:e.seed,message:r instanceof Error?r.message:String(r)})}}var sx=(e,t,r)=>Bp(e,t,td(r));function AT(e,t){let r=e.tireModelIdRear?t.tire(e.tireModelIdRear):void 0;return{tireModel:t.tire(e.tireModelId),...r?{tireModelRear:r}:{},motorModel:t.motor(e.motorModelId),aeroModel:t.aero(e.aeroModelId),batteryModel:t.battery(e.batteryModelId),brakeModel:t.brake(e.brakeModelId),damperModel:t.damper(e.damperModelId),...vi(e,t.damper)}}function FT(e,t,r){let{tireModelRear:n,damperModelRear:o,heaveDamperModel:a,rollDamperModel:s,...i}=r;return{vehicle:e,params:{...t,...i,...n?{tireModelRear:n}:{},...o?{damperModelRear:o}:{},...a?{heaveDamperModel:a}:{},...s?{rollDamperModel:s}:{}}}}var wT=e=>({ggvMode:e.ggvMode,quasiTransient:e.quasiTransient===!0&&e.ggvMode!=="fast",motorThermal:e.motorThermal===!0,...eC({brakeFade:e.brakeFade===!0,airTempC:e.airTempC,diffYaw:e.diffYaw===!0,...e.air?{air:e.air}:{}})});function N$(e){if(!(e.plannedPath!==void 0||!e.track))return{track:e.track,numerics:e.numerics,settings:{racingLine:e.racingLine,standingStart:e.standingStart,...Object.keys(e.lapCounts).length?{lapCounts:e.lapCounts}:{}},switches:e.switches,rulesets:e.rulesets}}function CT(e,t){let r=t.plannedPath!==void 0,n=N$(t);return{...dT(r?t.plannedPath:t.track,t.numerics,{racingLine:r?!1:t.racingLine,standingStart:t.standingStart,switches:t.switches},e,t.library,t.standingOf),...n?{session:n}:{},rulesets:t.rulesets}}function ix(e,t){let r=e.vehicles.find(o=>o.id===t);if(!r)throw new Error(`this project holds no vehicle "${t}"`);let n=Eo(e);return FT(structuredClone(Oy(e,r.params)),structuredClone(r.params),AT(r.params,n))}var O$="this project's laps follow a fixed trajectory from the planner, which the server cannot read \u2014 set Laptime back to the track to run this study here, or run it in the Studies tool";async function cx(e,t,r,n){if(e.settings.pathPlanId)throw new Error(O$);let o=ss(e),a=e.tracks.length?(await Kp(e,t)).asset:null,s={};for(let i of n?fT(n):[]){let c=e.tracks.find(l=>l.id===i);c&&(s[i]=await Yc(c,t))}return CT(r,{track:a,numerics:o.numerics,racingLine:o.racingLine,standingStart:o.standingStart,lapCounts:o.lapCounts??{},switches:wT(o),rulesets:e.rulesets??[],library:s,standingOf:i=>e.tracks.find(c=>c.id===i)?.standingStart===!0})}async function TT(e,t,r,n){let o=ix(e,r),a=_t(o,n),s=await cx(e,t,o,a);return ox({id:0,car:o,spec:a,lap:s})}async function PT(e,t,r,n){let o=ix(e,r),a=_t(o,n),s=nx(o,a);if(s.length)return{problems:[`Adopt has no way to write ${s.join(", ")} back into the project. Take them out of the study.`]};let i;try{i=await cx(e,t,o,a)}catch(l){return{problems:[l instanceof Error?l.message:String(l)]}}let c=Ty(o,a,{...td(i),metrics:en(e.rulesets)});return c.length?{problems:c}:{problems:[],msPerEval:ox({id:0,car:o,spec:a,lap:i}).msPerEval,carFingerprint:ho(ax(o))}}async function V$(e,t,r,n,o,a=[]){let s=yT(t,e,r,n),i=s.length*t.budget,c=null,l=[];for(let[u,m]of s.entries()){if(a.includes(m.seed))continue;await o?.tick();let d=[],p=null,f=null;if(ST(m,y=>{y.kind==="progress"?(d.push([y.progress.evaluations,y.progress.score.total]),y.progress.evaluations===0&&(c??=y.progress.score),o?.progress(u*t.budget+y.progress.evaluations,i)):y.kind==="done"?p={result:y.result,elapsedMs:y.elapsedMs}:f=y.message}),f)throw new Error(f);if(!p)throw new Error("the search stopped without a result");let{result:h,elapsedMs:b}=p,g={seed:m.seed,startJitter:m.startJitter,x:h.x,score:h.score,evaluations:h.evaluations,infeasible:h.infeasible,history:h.history,trace:d,elapsedMs:b,...h.snapped?{snapped:h.snapped}:{}};l.push(g),o?.progress((u+1)*t.budget,i),await o?.finished?.(g)}if(!c)throw new Error("the search never scored the starting design");return{method:t.method,budget:t.budget,designScore:c,runs:l}}async function LT(e,t,r,n){let o=ix(e,r.vehicleId),a=_t(o,r.spec),s=nx(o,a);if(s.length)throw new Error(`study_adopt has no way to write ${s.join(", ")} back into the project \u2014 take them out of the study`);let i=await cx(e,t,o,a),c=r.method??bT;if(!ha.some(b=>b.name===c))throw new Error(`unknown method "${c}" \u2014 it is one of ${ha.map(b=>b.name).join(", ")}`);let l=r.budget??gT,u=Math.max(1,Math.min(r.seeds??qc.length,qc.length)),m=await V$(o,{spec:a,method:c,budget:l},i,u,n),d=sx(o,a,i),p=m.runs.map(b=>({seed:b.seed,startScore:m.designScore.total,score:b.score.total,feasible:b.score.feasible,...b.score.reason?{reason:b.score.reason}:{},terms:b.score.terms,x:b.x,evaluations:b.evaluations,infeasible:b.infeasible,bounds:xT(d.variables,b.x),constraints:RT(o,a,b.x,i),...b.snapped?{onSteps:{x:b.snapped.x,score:b.snapped.score.total,feasible:b.snapped.score.feasible,...b.snapped.score.reason?{reason:b.snapped.score.reason}:{},terms:b.snapped.score.terms}}:{}})),f=m.runs.reduce((b,g)=>qs(g.score,b.score)?g:b),h=f.snapped?.score.feasible?f.snapped:null;return{method:c,budget:l,seeds:p,spread:m.runs.length>1?vT(o,d.variables,m.runs.map(b=>({x:b.x,score:b.score}))):null,writes:MT(o,a,h?h.x:f.x),...f.snapped?{adopts:h?"on its steps":`as found: on its steps it breaks a hold (${f.snapped.score.reason??"not legal"})`}:{}}}function ET(){if(typeof process.threadCpuUsage!="function")return performance.now();let e=process.threadCpuUsage();return(e.user+e.system)/1e3}async function $$(e,t){let r=qw(e.root);switch(e.kind){case"sweep":return lC(e.doc,r,e.req,t);case"convergence":return iC(e.doc,r,{vehicleId:e.vehicleId,...e.steps?{steps:e.steps}:{},...e.tolPct!==void 0?{tolPct:e.tolPct}:{},onStep:t});case"study":return LT(e.doc,r,{vehicleId:e.vehicleId,spec:e.spec,...e.method?{method:e.method}:{},...e.budget?{budget:e.budget}:{},...e.seeds?{seeds:e.seeds}:{}},{progress:t,cancelled:()=>!1,tick:async()=>{}});case"fleet":return Hp(e.doc,r,{...e.vehicleIds?{vehicleIds:e.vehicleIds}:{},...e.settings?{settings:e.settings}:{},...e.overrides?{overrides:e.overrides}:{}});case"probe":return TT(e.doc,r,e.vehicleId,e.spec);case"quote":return PT(e.doc,r,e.vehicleId,e.spec)}}if(DT){let e=DT,t=r=>e.postMessage(r);(async()=>{try{let r=await $$(B$,(n,o)=>t({type:"progress",done:n,total:o}));t({type:"done",result:r,cpuMs:ET()})}catch(r){t({type:"failed",message:r instanceof Error?r.message:String(r),cpuMs:ET()})}})()}export{$$ as runJob,ET as threadCpuMs};
|
|
226
|
+
`)),this.name="RulesetDefError",this.problems=r}},rc=e=>typeof e=="number"&&Number.isFinite(e),tc=e=>rc(e)&&e>0,Nt=(e,t)=>e===void 0||t(e);function W_(e){let t=[],r=(o,a=null)=>t.push({key:a,message:o});if(typeof e.id!="string"||e.id===""?r("A ruleset needs an id"):/^[A-Za-z0-9_-]+$/.test(e.id)||r(`The id "${e.id}" is letters, digits, "-" and "_" only`),typeof e.label!="string"&&r("A ruleset needs a label"),typeof e.description!="string"&&r("A ruleset needs a description, even an empty one"),Array.isArray(e.events)||r("A ruleset\u2019s events are a list"),Array.isArray(e.kpis)||r("A ruleset\u2019s KPIs are a list"),t.length)return t;for(let o of e.events){let a=o,s=typeof a?.id=="string"?`Event "${a.id}"`:"An event";if(typeof a!="object"||a===null||typeof a.id!="string"||typeof a.label!="string"){r(`${s} needs an id and a label`);continue}switch(a.kind){case"straightLineAccel":tc(a.distance)||r(`${s} needs a distance above zero, in metres`),Nt(a.vStart,i=>rc(i)&&i>=0)||r(`${s}'s entry speed must be zero or more`);break;case"constantRadius":tc(a.radius)||r(`${s} needs a radius above zero, in metres`),Nt(a.laps,i=>rc(i)&&i>=1)||r(`${s} runs at least one lap`);break;case"trackLap":Nt(a.laps,i=>rc(i)&&i>=1)||r(`${s} runs at least one lap`),Nt(a.distance,tc)||r(`${s}'s distance must be above zero, in metres`),Nt(a.standingStart,i=>typeof i=="boolean")||r(`${s}'s standing start is yes or no`);break;default:r(`${s} is of a kind this build does not run: ${String(a.kind)}`)}}for(let o of e.kpis){let a=o;if(typeof a!="object"||a===null||typeof a.key!="string"){r("A KPI needs a key");continue}let s=a.key;typeof a.expr!="string"&&r("Needs a formula",s),typeof a.label!="string"&&r("Needs a label",s),Nt(a.unit,i=>typeof i=="string")||r("Its unit is text",s),Nt(a.over,i=>typeof i=="string")||r("Names its event by id",s),Nt(a.format,i=>i==="time"||i==="points")||r("Is shown as a time, as points, or as a number",s),Nt(a.max,rc)||r("Its maximum is a number",s),Nt(a.lowerBetter,i=>typeof i=="boolean")||r("Lower is better, or it is not",s),Nt(a.hidden,i=>typeof i=="boolean")||r("Is hidden, or it is not",s)}Nt(e.track?.minTurnRadius,tc)||r("The tightest turn the rules allow is a radius above zero");let n=e.battery;for(let o of["packVoltageMax","segmentVoltageMax","powerLimitKw"])Nt(n?.[o],tc)||r(`The pack's ${o} must be above zero`);if(e.score!==void 0){let o=e.score?.parts;typeof e.score?.total!="string"||typeof o!="object"||o===null||Array.isArray(o)?r("The score names its total and its parts"):Object.values(o).every(a=>typeof a=="string")||r("Each part of the score names a KPI")}return t}function qS(e){let t=W_(e);if(t.length)return{plan:null,problems:t};let r=[];e.events.length===0&&r.push({key:null,message:"A ruleset runs at least one event"});let n=e.events.map(i=>i.id);e.traceEventId!=null&&!n.includes(e.traceEventId)&&r.push({key:null,message:`The plotted event "${e.traceEventId}" is not one of this ruleset's events`});let{plan:o,problems:a}=Cm(e.kpis,e.events);r.push(...a);let s=new Set(e.kpis.map(i=>i.key));if(e.score){s.has(e.score.total)||r.push({key:null,message:`The total "${e.score.total}" is not one of this ruleset's KPIs`});let i=Object.entries(e.score.parts);i.length===0&&r.push({key:null,message:"A ruleset that awards points names at least one part"});for(let[c,l]of i)s.has(l)||r.push({key:null,message:`The part "${c}" reads "${l}", which is not one of this ruleset's KPIs`})}return{plan:r.length?null:o,problems:r}}function Pm(e){return qS(e).problems}var gg=e=>Number.isFinite(e)?e:NaN;function j_(e){return e.unit&&e.format!=="time"?`${e.label} (${e.unit})`:e.label}function Fn(e){let t=structuredClone(e),{plan:r,problems:n}=qS(t);if(!r)throw new Tm(t.id,n);let o=new WeakMap,a=p=>{let d=o.get(p);return d||(d=bg(r,p),o.set(p,d)),d},s=new Map(t.kpis.map(p=>[p.key,p])),i=new Map;for(let[p,d]of Object.entries(t.score?.parts??{}))i.has(d)||i.set(d,p);let c=p=>(d,h)=>{if(!h)return NaN;let b=h.kpis?.[p];if(b!==void 0)return gg(b);let g=h,y=i.get(p);return y!==void 0?gg(g.parts?.[y]):p===t.score?.total?gg(g.total):NaN},l=t.kpis.filter(p=>!p.hidden).map(p=>{let d=r.field.has(p.key);return{key:p.key,label:j_(p),lowerBetter:p.lowerBetter??!1,...p.format?{format:p.format}:{},...d?{field:!0}:{},value:d?c(p.key):h=>a(h)[p.key]}}),u=t.score,m=u?p=>{let d=ec(r,p),h={};for(let[b,g]of Object.entries(d)){let y={},R={};for(let[k,v]of Object.entries(u.parts)){y[k]=g[v];let x=s.get(v)?.max;x!=null&&(R[k]=x)}h[b]={total:g[u.total],parts:y,...Object.keys(R).length?{maxima:R}:{},kpis:Object.fromEntries(t.kpis.map(k=>[k.key,g[k.key]]))}}return h}:void 0,f=m||(r.field.size>0?p=>{let d=ec(r,p),h={};for(let[b,g]of Object.entries(d))h[b]={kpis:Object.fromEntries(t.kpis.map(y=>[y.key,g[y.key]]))};return h}:void 0);return{id:t.id,label:t.label,description:t.description,events:t.events,metrics:l,...t.track?{track:t.track}:{},...t.battery?{battery:t.battery}:{},...t.traceEventId?{traceEventId:t.traceEventId}:{},...m?{score:m}:{},...f?{field:f}:{},definition:t}}var Jt={accel:"accel",skidpad:"skidpad",autocross:"autocross",endurance:"endurance"},QS=[{kind:"straightLineAccel",id:Jt.accel,label:"Acceleration (75 m)",distance:75},{kind:"constantRadius",id:Jt.skidpad,label:"Skidpad",radius:8.375},{kind:"trackLap",id:Jt.autocross,label:"Autocross (1 lap)",laps:1},{kind:"trackLap",id:Jt.endurance,label:"Endurance (22 km)",distance:22e3}],ZS=[{key:"autocross",label:"Autocross lap",format:"time",lowerBetter:!0,expr:"autocross.time"},{key:"accel",label:"Acceleration",format:"time",lowerBetter:!0,expr:"accel.time"},{key:"skidpad",label:"Skidpad lap",format:"time",lowerBetter:!0,expr:"skidpad.lapTime"},{key:"endurance",label:"Endurance",format:"time",lowerBetter:!0,expr:"endurance.time"},{key:"energy",label:"Energy",unit:"kWh",lowerBetter:!0,expr:"endurance.energy"},{key:"overall",label:"Overall",unit:"pts",format:"points",expr:"accelPts + skidpadPts + autocrossPts + endurancePts + efficiencyPts"},{key:"endurancePts",label:"Endurance",unit:"pts",format:"points",max:250,expr:"if(finite(finishedEndurance), 0.9 * 250 * ((1.333 * fleetmin(finishedEndurance) / min(finishedEndurance, 1.333 * fleetmin(finishedEndurance)) - 1) / 0.333) + 0.1 * 250, 0)"},{key:"efficiencyPts",label:"Efficiency",unit:"pts",format:"points",max:100,expr:"if(and(finite(finishedEndurance), finishedEndurance <= 1.333 * fleetmin(finishedEndurance)), 100 * ((1.5 * fleetmin(efficiencyFactor) - min(1.5 * fleetmin(efficiencyFactor), efficiencyFactor)) / (1.5 * fleetmin(efficiencyFactor) - fleetmin(efficiencyFactor))), 0)"},{key:"finishedEndurance",label:"Endurance, if finished",unit:"s",hidden:!0,expr:"if(endurance.finished, endurance.time, nan)"},{key:"efficiencyFactor",label:"Efficiency factor",unit:"s\xB2\xB7kWh",hidden:!0,expr:"finishedEndurance ^ 2 * endurance.energy"},{key:"accelPts",label:"Acceleration",unit:"pts",format:"points",max:75,hidden:!0,expr:"0.95 * 75 * ((1.5 * fleetmin(accel) / min(accel, 1.5 * fleetmin(accel)) - 1) / 0.5) + 0.05 * 75"},{key:"skidpadPts",label:"Skidpad",unit:"pts",format:"points",max:75,hidden:!0,expr:"0.95 * 75 * (((1.25 * fleetmin(skidpad) / min(skidpad, 1.25 * fleetmin(skidpad))) ^ 2 - 1) / 0.5625) + 0.05 * 75"},{key:"autocrossPts",label:"Autocross",unit:"pts",format:"points",max:100,hidden:!0,expr:"0.95 * 100 * ((1.25 * fleetmin(autocross) / min(autocross, 1.25 * fleetmin(autocross)) - 1) / 0.25) + 0.05 * 100"}],JS={total:"overall",parts:{[Jt.accel]:"accelPts",[Jt.skidpad]:"skidpadPts",[Jt.autocross]:"autocrossPts",[Jt.endurance]:"endurancePts",efficiency:"efficiencyPts"}},eA={id:"fs-ev",label:"Formula Student \u2014 Electric",description:"The four dynamic events (acceleration, skidpad, autocross, endurance) scored on the Formula Student point table, with efficiency from battery energy.",events:QS,kpis:ZS,score:JS,track:{minTurnRadius:4.5},battery:fx,traceEventId:Jt.autocross},tA={id:"fs-cv",label:"Formula Student \u2014 Combustion",description:"Same events and point table as the electric class. An engine car\u2019s efficiency is scored on the work at its crankshaft until its fuel is modelled; an electric car\u2019s on its pack.",events:QS,kpis:ZS,score:JS,track:{minTurnRadius:4.5},traceEventId:Jt.autocross},nc=Fn(eA),yg=Fn(tA);var xg="lap",U_=[{kind:"trackLap",id:xg,label:Fm,laps:1}],rA={id:"trackday",label:"Track day",description:"One flying lap of the selected track. Times and traces only \u2014 no scoring.",events:U_,kpis:[{key:"lap",label:"Lap time",format:"time",lowerBetter:!0,expr:"lap.time"},{key:"topSpeed",label:"Top speed",unit:"km/h",over:xg,expr:"peak(speed)"},{key:"energy",label:"Energy / lap",unit:"kWh",lowerBetter:!0,expr:"lap.energy"}],traceEventId:xg},Rg=Fn(rA);function wn(e){if(e===null||typeof e!="object")return JSON.stringify(e)??"null";if(Array.isArray(e))return`[${e.map(wn).join(",")}]`;let t=e,r=Object.keys(t).sort(),n=[];for(let o of r)t[o]!==void 0&&n.push(`${JSON.stringify(o)}:${wn(t[o])}`);return`{${n.join(",")}}`}function go(e){let t=wn(e),r=2166136261;for(let n=0;n<t.length;n++)r^=t.charCodeAt(n),r=r+((r<<1)+(r<<4)+(r<<7)+(r<<8)+(r<<24))>>>0;return r.toString(16).padStart(8,"0").slice(-6)}var ja=[nc,yg,Rg],yo=nc.id,Ua=e=>ja.some(t=>t.id===e),nA=new WeakMap,oc=new Map,X_=64;function Lm(e){let t=nA.get(e);if(t!==void 0)return t;let r=wn(e),n=oc.get(r);return n===void 0&&(n=Pm(e).length?null:Fn(e),oc.size>=X_&&oc.delete(oc.keys().next().value),oc.set(r,n)),nA.set(e,n),n}function Dm(e,t=[]){if(e==null)return;if(typeof e!="string")return Lm(e)??void 0;let r=ja.find(o=>o.id===e);if(r)return r;let n=t.find(o=>o.id===e);return n?Lm(n)??void 0:void 0}function xo(e,t=[]){return Dm(e,t)??nc}function vg(e=[]){let t=e.filter(r=>!Ua(r.id)).map(r=>Lm(r)).filter(r=>r!==null);return[...ja,...t]}var ac=e=>e.definition??e.id;function Em(e,t,r){let n=e.length,o=new Array(n);for(let d=0;d<n;d++){let h=d+1<n?e[d+1]:r;o[d]=h-e[d]}let a=new Array(n).fill(0),s=new Array(n).fill(0),i=new Array(n).fill(0),c=new Array(n).fill(0);for(let d=0;d<n;d++){let h=o[(d-1+n)%n],b=o[d];a[d]=h,s[d]=2*(h+b),i[d]=b;let g=t[(d+1)%n],y=t[(d-1+n)%n];c[d]=6*((g-t[d])/b-(t[d]-y)/h)}let l=q_(a,s,i,c),u=new Array(n),m=new Array(n),f=new Array(n),p=new Array(n);for(let d=0;d<n;d++){let h=o[d],b=l[d],g=l[(d+1)%n],y=t[d],R=t[(d+1)%n];u[d]=y,f[d]=b/2,p[d]=(g-b)/(6*h),m[d]=(R-y)/h-h*(2*b+g)/6}return{n,eval:(d,h)=>u[d]+h*(m[d]+h*(f[d]+h*p[d])),d1:(d,h)=>m[d]+h*(2*f[d]+h*3*p[d]),d2:(d,h)=>2*f[d]+h*6*p[d]}}function Mg(e,t){let r=e.length,n=r-1,o=new Array(n);for(let u=0;u<n;u++)o[u]=e[u+1]-e[u];let a=new Array(r).fill(0);if(r>2){let u=r-2,m=new Array(u).fill(0),f=new Array(u).fill(0),p=new Array(u).fill(0),d=new Array(u).fill(0);for(let g=0;g<u;g++){let y=g+1;m[g]=o[y-1],f[g]=2*(o[y-1]+o[y]),p[g]=o[y],d[g]=6*((t[y+1]-t[y])/o[y]-(t[y]-t[y-1])/o[y-1])}let h=n>=3;if(h){let g=o[0]/o[1];f[0]+=o[0]*(1+g),p[0]-=o[0]*g;let y=o[n-1]/o[n-2];f[u-1]+=o[n-1]*(1+y),m[u-1]-=o[n-1]*y}let b=kg(m,f,p,d);for(let g=0;g<u;g++)a[g+1]=b[g];h&&(a[0]=(1+o[0]/o[1])*a[1]-o[0]/o[1]*a[2],a[r-1]=(1+o[n-1]/o[n-2])*a[r-2]-o[n-1]/o[n-2]*a[r-3])}let s=new Array(n),i=new Array(n),c=new Array(n),l=new Array(n);for(let u=0;u<n;u++)s[u]=t[u],c[u]=a[u]/2,l[u]=(a[u+1]-a[u])/(6*o[u]),i[u]=(t[u+1]-t[u])/o[u]-o[u]*(2*a[u]+a[u+1])/6;return{n,eval:(u,m)=>s[u]+m*(i[u]+m*(c[u]+m*l[u])),d1:(u,m)=>i[u]+m*(2*c[u]+m*3*l[u]),d2:(u,m)=>2*c[u]+m*6*l[u]}}function q_(e,t,r,n){let o=t.length;if(o===1)return[n[0]/(t[0]+e[0]+r[0])];if(o===2){let d=t[0],h=r[0]+e[0],b=e[1]+r[1],g=t[1],y=d*g-h*b;return[(n[0]*g-h*n[1])/y,(d*n[1]-n[0]*b)/y]}let a=e[0],s=r[o-1],i=-t[0]||1e-30,c=t.slice();c[0]=t[0]-i,c[o-1]=t[o-1]-a*s/i;let l=kg(e,c,r,n),u=new Array(o).fill(0);u[0]=i,u[o-1]=s;let m=kg(e,c,r,u),f=(l[0]+a*l[o-1]/i)/(1+m[0]+a*m[o-1]/i),p=new Array(o);for(let d=0;d<o;d++)p[d]=l[d]-f*m[d];return p}function kg(e,t,r,n){let o=t.length,a=new Array(o),s=new Array(o);a[0]=r[0]/t[0],s[0]=n[0]/t[0];for(let c=1;c<o;c++){let l=t[c]-e[c]*a[c-1];a[c]=r[c]/l,s[c]=(n[c]-e[c]*s[c-1])/l}let i=new Array(o);i[o-1]=s[o-1];for(let c=o-2;c>=0;c--)i[c]=s[c]-a[c]*i[c+1];return i}function sc(e){let t=e.z;if(!Array.isArray(t)||t.length<2)return null;let r=e.closed!==!1,n=e.x.length,o=r?n:n-1,a=[0];for(let l=0;l<o;l++){let u=(l+1)%n;a.push(a[l]+Math.hypot(e.x[u]-e.x[l],e.y[u]-e.y[l]))}let s=a[o],i=t.length,c=i===n?a.slice(0,n):Array.from({length:i},(l,u)=>r?u/i*s:u/(i-1)*s);return{z:t,pos:c,length:s,closed:r}}function oA(e,t,r){let n=e.pos[r]-e.pos[t];return e.closed?n>e.length/2?n-e.length:n<-e.length/2?n+e.length:n:n}function aA(e,t){let[r,n,o,a,s,i]=e,c=a*i-s*s,l=o*s-n*i,u=n*s-o*a,m=r*c+n*l+o*u;if(!(Math.abs(m)>1e-12*Math.max(1,Math.abs(r*a*i))))return null;let f=r*i-o*o,p=n*o-r*s,d=r*a-n*n;return[(c*t[0]+l*t[1]+u*t[2])/m,(l*t[0]+f*t[1]+p*t[2])/m,(u*t[0]+p*t[1]+d*t[2])/m]}function sA(e){let t=e.z.length;if(t<5)return 0;let r=[];for(let a=0;a<t;a++){let s=[a-2,a-1,a+1,a+2].map(h=>e.closed?(h+t)%t:h);if(s.some(h=>h<0||h>=t))continue;let i=s.map(h=>oA(e,a,h)),c=Math.max(...i.map(Math.abs));if(!(c>0))continue;let l=i.map(h=>h/c),u=[0,0,0,0,0];for(let h of l)for(let b=0;b<5;b++)u[b]+=h**b;let m=aA([u[0],u[1],u[2],u[2],u[3],u[4]],[1,0,0]);if(!m)continue;let f=l.map(h=>m[0]+m[1]*h+m[2]*h*h),p=0,d=1;f.forEach((h,b)=>{p+=h*e.z[s[b]],d+=h*h}),r.push(Math.abs(e.z[a]-p)/Math.sqrt(d))}if(!r.length)return 0;r.sort((a,s)=>a-s);let n=r.length>>1;return 1.4826*(r.length%2?r[n]:(r[n-1]+r[n])/2)}function Q_(e,t,r){let n=e.z.length,o=[t],a=[0];for(let s of[-1,1])for(let i=1;i<n;i++){let c=e.closed?((t+s*i)%n+n)%n:t+s*i;if(c<0||c>=n)break;let l=oA(e,t,c);if(Math.abs(l)>=r||Math.sign(l)!==s)break;o.push(c),a.push(l)}return{j:o,t:a}}function Z_(e,t,r){let{j:n,t:o}=Q_(e,t,r);if(n.length<4)return null;let a=o.map(l=>(1-Math.abs(l/r)**3)**3),s=o.map(l=>l/r),i=[0,0,0,0,0];s.forEach((l,u)=>{let m=a[u];for(let f=0;f<5;f++)i[f]+=m,m*=l});let c=aA([i[0],i[1],i[2],i[2],i[3],i[4]],[1,0,0]);return c?{j:n,value:s.map((l,u)=>a[u]*(c[0]+c[1]*l+c[2]*l*l))}:null}function Sg(e,t){return t>0?e.z.map((r,n)=>{let o=Z_(e,n,t/2);return o?o.value.reduce((a,s,i)=>a+s*e.z[o.j[i]],0):r}):[...e.z]}function J_(e,t){if(!(e>0)||!(t>0))return 0;let r=(22.5*t*e*e/1e-4**2)**.2;return Math.min(100/2,r)}function Im(e){let t=sc(e);if(!t)return 0;let r=sA(t);return r>1e-6?Math.max(10,J_(r,eN(t))):0}function eN(e){let t=[];for(let r=1;r<e.pos.length;r++)t.push(e.pos[r]-e.pos[r-1]);return e.closed&&e.pos.length&&t.push(e.length-e.pos[e.pos.length-1]+e.pos[0]),t.sort((r,n)=>r-n),t.length?t[t.length>>1]:0}function vr(e,t,r){let n=e.n;if(e.closed===!1){let a=r-t;return a===0?e.diag[t]:a===1?e.off1[t]:a===2?e.off2[t]:a===-1?e.off1[r]:a===-2?e.off2[r]:0}let o=((r-t)%n+n)%n;return o===0?e.diag[t]:o===1?e.off1[t]:o===2?e.off2[t]:o===n-1?e.off1[r]:o===n-2?e.off2[r]:0}function Nm(e,t){let r=e.n,n=new Array(r).fill(0);for(let o=0;o<r;o++){let a=e.diag[o]*t[o];for(let[s,i]of[[1,e.off1],[2,e.off2]]){(o+s<r||e.closed!==!1)&&(a+=i[o]*t[(o+s)%r]);let c=(o-s+r)%r;(o-s>=0||e.closed!==!1)&&(a+=i[c]*t[c])}n[o]=a}return n}function iA(e,t){let r=new Array(e).fill(0),n=new Array(e).fill(0),o=new Array(e).fill(0);for(let a=0;a<e;a++){a>=2&&(o[a]=r[a-2]!==0?t(a,a-2)/r[a-2]:0),a>=1&&(n[a]=r[a-1]!==0?(t(a,a-1)-o[a]*n[a-1])/r[a-1]:0);let s=t(a,a)-n[a]*n[a]-o[a]*o[a];if(!(s>0)||!Number.isFinite(s))return null;r[a]=Math.sqrt(s)}return{d:r,l1:n,l2:o}}function _m(e,t){let r=t.length,n=new Array(r).fill(0);for(let a=0;a<r;a++){let s=t[a];a>=1&&(s-=e.l1[a]*n[a-1]),a>=2&&(s-=e.l2[a]*n[a-2]),n[a]=s/e.d[a]}let o=new Array(r).fill(0);for(let a=r-1;a>=0;a--){let s=n[a];a+1<r&&(s-=e.l1[a+1]*o[a+1]),a+2<r&&(s-=e.l2[a+2]*o[a+2]),o[a]=s/e.d[a]}return o}function tN(e,t){let r=e[0][0]*e[1][1]-e[0][1]*e[1][0],n=Math.max(Math.abs(e[0][0]*e[1][1]),Math.abs(e[0][1]*e[1][0]),Number.MIN_VALUE);return!Number.isFinite(r)||Math.abs(r)<1e-12*n?null:[(t[0]*e[1][1]-e[0][1]*t[1])/r,(e[0][0]*t[1]-t[0]*e[1][0])/r]}function Ag(e,t){let r=e.n;if(r<7)throw new Error(`periodic band solver needs n >= 7, got ${r}`);if(e.closed===!1){let b=iA(r,(y,R)=>vr(e,y,R));if(!b)return null;let g=_m(b,t);return g.every(Number.isFinite)?g:null}let n=r-2,a=iA(n,(b,g)=>vr(e,b,g));if(!a)return null;let s=new Array(n).fill(0),i=new Array(n).fill(0);for(let b=0;b<n;b++)s[b]=vr(e,b,r-2),i[b]=vr(e,b,r-1);let c=_m(a,t.slice(0,n)),l=_m(a,s),u=_m(a,i),m=(b,g)=>{let y=0;for(let R=0;R<b.length;R++)y+=b[R]*g[R];return y},f=[[vr(e,r-2,r-2)-m(s,l),vr(e,r-2,r-1)-m(s,u)],[vr(e,r-1,r-2)-m(i,l),vr(e,r-1,r-1)-m(i,u)]],p=[t[r-2]-m(s,c),t[r-1]-m(i,c)],d=tN(f,p);if(!d)return null;let h=new Array(r).fill(0);for(let b=0;b<n;b++)h[b]=c[b]-l[b]*d[0]-u[b]*d[1];return h[r-2]=d[0],h[r-1]=d[1],h.every(Number.isFinite)?h:null}function cA(e,t,r=0){let n=Math.max(...e.diag.map(Math.abs),1e-30),o=r>0?r:n*1e-12,a=Math.sqrt(t.reduce((s,i)=>s+i*i,0));for(let s=0;s<40;s++){let i={...e,diag:e.diag.map(l=>l+o)},c=Ag(i,t);if(c){let l=Nm(i,c).map((m,f)=>m-t[f]);if(Math.sqrt(l.reduce((m,f)=>m+f*f,0))<=1e-6*Math.max(a,1e-12))return c}o=o===0?n*1e-12:o*10}return null}var lA=4,rN=8,Fg=.001;function nN(e,t,r){let n=[];for(let c=1;c<e.length;c++){let l=e[c]-e[c-1];l>=Fg&&n.push(l)}let o=Float64Array.from(n).sort(),a=o.length>>1,s=o.length?o.length%2?o[a]:.5*(o[a-1]+o[a]):0,i=t?n.length:n.length+1;return Math.max(3,Math.round(i/yM(r,s,i)))}function oN(e,t){let r=e.closed!==!1,n=[],o=[],a=(F,w)=>{let T=n.length-1;T>=0&&Math.hypot(F-n[T],w-o[T])<Fg||(n.push(F),o.push(w))},s=e.x.length,i=r?s:s-1,c=new Array(i+1);c[0]=0;for(let F=0;F<i;F++){let w=(F+1)%s;c[F+1]=c[F]+Math.hypot(e.x[w]-e.x[F],e.y[w]-e.y[F])}let l=c[i],u=e.fit==="interpolate",m=u?s:nN(c,r,t),f=r?m:m-1,p=0;for(let F=0;F<=f&&!(r&&F===f);F++){if(u){a(e.x[F],e.y[F]);continue}let w=F*l/f;for(;p<i-1&&c[p+1]<w;)p++;let T=c[p+1]-c[p],P=T>0?(w-c[p])/T:0,A=(p+1)%s;a(e.x[p]+P*(e.x[A]-e.x[p]),e.y[p]+P*(e.y[A]-e.y[p]))}if(r)for(;n.length>2&&Math.hypot(n[n.length-1]-n[0],o[o.length-1]-o[0])<Fg;)n.pop(),o.pop();let d=n.length,h=r?d:d-1,b=new Array(h+1);b[0]=0;for(let F=1;F<=h;F++){let w=F%d,T=n[w]-n[F-1],P=o[w]-o[F-1],A=Math.sqrt(Math.hypot(T,P))||1e-9;b[F]=b[F-1]+A}let g=r?Em(b.slice(0,d),n,b[d]):Mg(b,n),y=r?Em(b.slice(0,d),o,b[d]):Mg(b,o),R=new Array(h);for(let F=0;F<h;F++)R[F]=b[F+1]-b[F];let k=[0],v=[0],x=[0],M=0;for(let F=0;F<h;F++){let w=R[F]/lA;for(let T=0;T<lA;T++){let P=T*w;M+=Lh(A=>Math.hypot(g.d1(F,A),y.d1(F,A)),P,P+w),k.push(M),v.push(F),x.push(P+w)}}return{closed:r,sx:g,sy:y,h:R,sTable:k,segTable:v,uTable:x,length:M,rawCum:c,rawLength:l}}function ic(e,t,r,n){if(e===void 0)return r.map(()=>t);if(typeof e=="number")return r.map(()=>e);let o=e.length;if(o===0)return r.map(()=>t);if(o===1)return r.map(()=>e[0]);let a=n.rawCum.length-1,s=o===(n.closed?a:a+1);return r.map(i=>{let c;if(s){let f=i*n.rawLength,p=0,d=a;for(;p<d;){let b=p+d+1>>1;n.rawCum[b]<=f?p=b:d=b-1}let h=p<a?n.rawCum[p+1]-n.rawCum[p]:0;c=p+(h>0?(f-n.rawCum[p])/h:0)}else c=n.closed?i*o:i*(o-1);let l=Math.min(Math.floor(c),o-1)%o,u=c-Math.floor(c),m=n.closed?(l+1)%o:Math.min(l+1,o-1);return e[l]+u*(e[m]-e[l])})}var aN=.01,sN=3,uA=10;function iN(e,t,r,n=uA){let o={step:0,uncertainty:1/0},a=e.length;if(a<8||!(r>0))return o;let s=Math.max(uA,n,6*r/a),i=(r-t[a-1])/2,c=0;for(;c<a/2&&t[c]+i<=s;)c++;let l=0;for(;l<a/2&&r-t[a-1-l]-i<=s;)l++;let u=Math.min(c,l);if(u<3)return o;let m=[],f=[],p=(R,k,v)=>{let x=R/s;m.push([1,x,x*x,x*x*x,k]),f.push(v)};for(let R=0;R<u;R++)p(t[R]+i,1,e[R]);for(let R=0;R<u;R++)p(t[a-1-R]-r+i,0,e[a-1-R]);let d=Array.from({length:5},()=>new Array(5).fill(0)),h=new Array(5).fill(0);m.forEach((R,k)=>{for(let v=0;v<5;v++){h[v]+=R[v]*f[k];for(let x=0;x<5;x++)d[v][x]+=R[v]*R[x]}});let b=sr(d,h),g=sr(d,[0,0,0,0,1]);if(b.singular||g.singular)return o;let y=0;return m.forEach((R,k)=>{let v=0;for(let x=0;x<5;x++)v+=R[x]*b.x[x];y+=(f[k]-v)**2}),{step:b.x[4],uncertainty:Math.sqrt(y/(m.length-5)*g.x[4])}}function cN(e,t){let r=t[t.length-1];return{pos:e===t.length-1?t.slice(0,e):Array.from({length:e},(o,a)=>a/e*r),loop:r}}function lN(e,t,r){let{pos:n,loop:o}=cN(e.length,t),{step:a,uncertainty:s}=iN(e,n,o,r);return Math.abs(a)>Math.max(aN,sN*s)?{z:e.map((i,c)=>i+a*n[c]/o),drift:-a}:{z:e,drift:0}}function uN(e,t){let{sTable:r,segTable:n,uTable:o,h:a,sx:s,sy:i}=e,c=0,l=r.length-1;for(;c<l;){let y=c+l+1>>1;r[y]<=t?c=y:l=y-1}let u=Math.min(c,r.length-2),m=r[u],f=r[u+1],p=n[u+1],d=o[u+1],h=n[u]===p?o[u]:0,b=f-m,g=b>0?h+(t-m)/b*(d-h):h;for(let y=0;y<2;y++){let R=m+Lh(v=>Math.hypot(s.d1(p,v),i.d1(p,v)),h,g),k=Math.hypot(s.d1(p,g),i.d1(p,g));if(k<1e-12)break;g-=(R-t)/k}return{seg:p,du:Math.min(Math.max(g,0),a[p])}}var mN=3,wg=5;function pN(e,t,r,n=wg){return Vm(e,t,r,n)}function Vm(e,t,r,n,o=!1){let a=e.length;if(!(t>0)||!(n>0)||a<7)return[...e];let s=(n/(2*Math.PI*t))**4,i=new Array(a).fill(1+6*s),c=new Array(a).fill(-4*s),l=new Array(a).fill(s),u=[...e];if(!r&&(i[0]=i[a-1]=1+s,i[1]=i[a-2]=1+5*s,c[0]=c[a-2]=-2*s,o)){let m=1e9*(1+s);for(let f of[0,a-1])i[f]+=m,u[f]*=1+m}return Ag({n:a,diag:i,off1:c,off2:l,closed:r},u)??[...e]}function lt(e,t){let r=ct(t),n=oN(e,r.fitSpacing),o=n.length,a=Math.max(rN,Math.round(o/r.dsTarget)),s=n.closed?a:a+1,i=o/a,c=new Array(s),l=new Array(s),u=new Array(s),m=new Array(s).fill(i);n.closed||(m[s-1]=0);let f=new Array(s),p=new Array(s),d=new Array(s);for(let T=0;T<s;T++){let P=T*i,{seg:A,du:S}=uN(n,P);c[T]=n.sx.eval(A,S),l[T]=n.sy.eval(A,S),u[T]=P;let C=n.sx.d1(A,S),L=n.sy.d1(A,S),D=n.sx.d2(A,S),I=n.sy.d2(A,S),O=Math.hypot(C,L),N=Math.pow(C*C+L*L,1.5);f[T]=N>0?(C*I-L*D)/N:0,p[T]=O>0?-L/O:0,d[T]=O>0?C/O:0}let h=u.map(T=>o>0?Math.min(1,T/o):0),b=Array.isArray(e.z)&&e.z.length>1,g=b&&(e.zSmoothing??0)>0?e.zSmoothing:0,y=b&&n.closed?lN(e.z,n.rawCum,g):null,R=y?y.z:e.z,k=g>0?sc(e):null,v=k?Sg({...k,z:R},g):R,x=ic(v,0,h,n),M=new Array(s).fill(0);if(b){for(let P=0;P<s;P++){let A=n.closed?(P+1)%s:Math.min(P+1,s-1),S=n.closed?(P-1+s)%s:Math.max(P-1,0),C=n.closed?2:A-S,L=x[A]-x[S];M[P]=C>0?Math.atan2(L,C*i)*180/Math.PI:0}for(let P=0;P<s;P++){if(m[P]===0)continue;let A=n.closed?(P+1)%s:P+1,S=x[A]-x[P];m[P]=Math.hypot(i,S)}let T=0;for(let P=0;P<s;P++)u[P]=T,T+=m[P]}let F=b?m.reduce((T,P)=>T+P,0):o,w;if(b){w=new Array(s).fill(0);let T=Math.max(mN,e.zReach??Im(e)),P=Math.max(2,Math.round(T/i));if(n.closed?s>2*P:s>2*P+1){let A=0,S=0;for(let D=-P;D<=P;D++)A+=D*D,S+=D*D*D*D;let C=2*P+1,L=S-A*A/C;for(let D=0;D<s;D++){let I=n.closed?D:Math.min(Math.max(D,P),s-1-P),O=0,N=0;for(let _=-P;_<=P;_++){let B=x[n.closed?(I+_+s)%s:I+_];O+=(_*_-A/C)*B,N+=_*B}let z=2*O/L/(i*i),E=N/A/i;w[D]=z/Math.pow(1+E*E,1.5)}}}return{name:e.name,closed:n.closed,x:c,y:l,s:u,ds:m,curvature:e.turnReach?pN(f,i,n.closed,e.turnReach):f,npts:s,length:F,nx:p,ny:d,z:x,gradient:M,...w?{verticalCurvature:w}:{},widthLeft:ic(e.widthLeft,1.5,h,n),widthRight:ic(e.widthRight,1.5,h,n),bank:ic(e.bank,0,h,n),mu:ic(e.mu,1,h,n),...y?.drift?{elevationDrift:y.drift}:{}}}function mA(e,t,r){let n=Nm(e,r),o=0;for(let a=0;a<r.length;a++)o+=.5*r[a]*n[a]-t[a]*r[a];return o}function dN(e,t,r,n){let o=e.n,a=e.closed!==!1,s=(l,u)=>{let m=l+u;return a?(m%o+o)%o:m>=0&&m<o?m:null},i=[...t];for(let l=0;l<o;l++){if(r[l]==="free")continue;let u=n(l);if(u!==0)for(let m of[-2,-1,1,2]){let f=s(l,m);f!=null&&(i[f]-=vr(e,f,l)*u)}}let c={n:o,closed:e.closed,diag:[...e.diag],off1:[...e.off1],off2:[...e.off2]};for(let l=0;l<o;l++){if(r[l]==="free")continue;c.diag[l]=1,c.off1[l]=0,c.off2[l]=0;let u=s(l,-1),m=s(l,-2);u!=null&&(c.off1[u]=0),m!=null&&(c.off2[m]=0),i[l]=n(l)}return cA(c,i)}var fN=1e-4;function pA(e,t,r,n,o={}){let a=e.n,s=o.maxIter??60,i=o.tol??1e-9,c=o.bounds,l=(d,h)=>Math.min(n[h],Math.max(r[h],d)),u=r.map((d,h)=>c?.[h]==="hi"?n[h]:c?.[h]==="lo"?r[h]:l(0,h)),m=mA(e,t,u),f=new Array(a).fill("free"),p=!1;for(let d=0;d<s;d++){let h=Nm(e,u).map((R,k)=>R-t[k]),b=!1;for(let R=0;R<a;R++){let k=u[R]<=r[R]+i&&h[R]>=-i?"lo":u[R]>=n[R]-i&&h[R]<=i?"hi":"free";k!==f[R]&&(f[R]=k,b=!0)}if(p&&!b)return{x:u,iterations:d+1,converged:!0,bounds:f};let g=dN(e,t,f,R=>u[R]);if(!g)return{x:u,iterations:d+1,converged:!1,bounds:f};let y=!1;for(let R=1;R>1e-12;R*=.5){let k=!1,v=u.map((F,w)=>{if(f[w]!=="free")return F;let T=F+R*(g[w]-F),P=l(T,w);return P!==T&&(k=!0),P}),x=mA(e,t,v),M=0;for(let F=0;F<a;F++)M+=h[F]*(v[F]-u[F]);if(R===1&&!k||x<m&&x<=m+fN*M){u=v,m=x,p=R===1&&!k,y=!0;break}}if(!y)return{x:u,iterations:d+1,converged:!1,bounds:f}}return{x:u,iterations:s,converged:!1,bounds:f}}var Cg={lineStep:2,carHalfWidth:.75,margin:.1,foldMargin:.25,referenceReach:5,passes:40,iterations:400},hN=[1,.5,.25,.125,.0625,.03125,.015625,.0078125,.00390625,.001953125,.0009765625],bN=e=>Math.sqrt(e.reduce((t,r)=>t+r*r,0)/(e.length||1));function cc(e,t,r=!0){let n=e.length,o=new Array(n).fill(0);for(let a=0;a<n;a++){if(!r&&(a===0||a===n-1))continue;let s=(a-1+n)%n,i=(a+1)%n,c=e[a]-e[s],l=t[a]-t[s],u=e[i]-e[a],m=t[i]-t[a],f=e[i]-e[s],p=t[i]-t[s],d=Math.hypot(c,l),h=Math.hypot(u,m),b=Math.hypot(f,p),g=d*h*b;o[a]=g>1e-12?2*(c*m-l*u)/g:0}return o}var gN=Math.PI/180,dA=20;function yN(e,t){let r=e.npts,n=e.closed,o=e.x.map((p,d)=>p+t[d]*e.nx[d]),a=e.y.map((p,d)=>p+t[d]*e.ny[d]),s=[0];for(let p=1;p<r;p++)s.push(s[p-1]+Math.hypot(o[p]-o[p-1],a[p]-a[p-1]));let i=n?s[r-1]+Math.hypot(o[0]-o[r-1],a[0]-a[r-1]):s[r-1],c=n?[-1,0,1]:[0],l=[],u=[];for(let p of c)for(let d=0;d<r;d++)l.push(s[d]+p*i),u.push(d+p*r);n&&(l.push(2*i),u.push(2*r));let m=[0];for(let p=1;p<l.length;p++)m.push(m[p-1]+.5*(u[p]+u[p-1])*(l[p]-l[p-1]));let f=p=>{let d=0,h=l.length-1;for(;h-d>1;){let g=d+h>>1;l[g]<=p?d=g:h=g}let b=l[h]>l[d]?(p-l[d])/(l[h]-l[d]):0;return m[d]+(l[h]-l[d])*b*(u[d]+.5*b*(u[h]-u[d]))};return s.map((p,d)=>{let h=n?dA:Math.min(dA,p,i-p);if(!(h>0))return e.z[d];let b=(f(p+h)-f(p-h))/(2*h),g=n?(b%r+r)%r:Math.min(Math.max(b,0),r-1),y=Math.min(Math.floor(g),r-1),R=n?(y+1)%r:Math.min(y+1,r-1);return e.z[y]+(g-y)*(e.z[R]-e.z[y])})}function xN(e,t,r){let n=Array.isArray(e.z)&&e.z.length>1,o=t.bank.some(i=>i!==0),a=t.mu.some(i=>i!==1),s=n?yN(t,r):t.z;return{...n||o?{z:s.map((i,c)=>i+r[c]*Math.tan(t.bank[c]*gN))}:{},...n?{zReach:e.zReach??Im(e)}:{},...o?{bank:[...t.bank]}:{},...a?{mu:[...t.mu]}:{}}}function fA(e,t,r=!0){let n=e.length,o=new Array(n).fill(0);for(let a=0;a<n;a++){if(!r&&(a===0||a===n-1))continue;let s=(a-1+n)%n,i=(a+1)%n;o[a]=.5*(Math.hypot(e[a]-e[s],t[a]-t[s])+Math.hypot(e[i]-e[a],t[i]-t[a]))}return o}function RN(e,t,r,n,o){let a=e.length,s=new Array(a).fill(0),i={l:new Array(a).fill(0),d:new Array(a).fill(0),r:new Array(a).fill(0)},c=(l,u,m,f)=>l*f-u*m;for(let l=0;l<a;l++){if(!o&&(l===0||l===a-1))continue;let u=(l-1+a)%a,m=(l+1)%a,f=e[l]-e[u],p=t[l]-t[u],d=e[m]-e[l],h=t[m]-t[l],b=e[m]-e[u],g=t[m]-t[u],y=Math.hypot(f,p),R=Math.hypot(d,h),k=Math.hypot(b,g),v=y*R*k;if(!(v>1e-12))continue;let x=2*c(f,p,d,h)/v,M=Math.sqrt(.5*(y+R)),F=x/(2*M),w=(f*r[u]+p*n[u])/y,T=(b*r[u]+g*n[u])/k,P=(f*r[l]+p*n[l])/y,A=(d*r[l]+h*n[l])/R,S=(d*r[m]+h*n[m])/R,C=(b*r[m]+g*n[m])/k,L=-2*c(r[u],n[u],d,h)/v+x*(w/y+T/k),D=2*c(r[l],n[l],b,g)/v-x*(P/y-A/R),I=2*c(f,p,r[m],n[m])/v-x*(S/R+C/k);s[l]=x*M,i.l[l]=M*L-F*.5*w,i.d[l]=M*D+F*.5*(P-A),i.r[l]=M*I+F*.5*S}return{res:s,jac:i}}function vN(e,t,r,n,o){let a=n-r+1,s=e.l.slice(r,n+1),i=e.d.slice(r,n+1),c=e.r.slice(r,n+1),l=t.slice(r,n+1);o||(i[0]+=s[0],s[0]=0,i[a-1]+=c[a-1],c[a-1]=0);let u=(h,b)=>o?h[(b+a)%a]:b>=0&&b<a?h[b]:0,m=new Array(a),f=new Array(a),p=new Array(a),d=new Array(a);for(let h=0;h<a;h++){let b=u(c,h-1),g=u(s,h+1);m[h]=b*b+i[h]*i[h]+g*g,f[h]=i[h]*c[h]+g*u(i,h+1),p[h]=g*u(c,h+1),d[h]=-(b*u(l,h-1)+i[h]*l[h]+g*u(l,h+1))}return{M:{n:a,closed:o,diag:m,off1:f,off2:p},b:d}}function kN(e,t){let r=e.npts,n=e.closed;if(!(t>0)||r<7)return e;let o=n?r:r-1,a=0;for(let f=0;f<o;f++){let p=(f+1)%r;a+=Math.hypot(e.x[p]-e.x[f],e.y[p]-e.y[f])}let s=a/o,i=Vm(e.x,s,n,t,!0),c=Vm(e.y,s,n,t,!0),l=new Array(r),u=new Array(r);for(let f=0;f<r;f++){let p=n?(f-1+r)%r:Math.max(f-1,0),d=n?(f+1)%r:Math.min(f+1,r-1),h=i[d]-i[p],b=c[d]-c[p],g=Math.hypot(h,b)||1;l[f]=-b/g,u[f]=h/g}let m=cc(i,c,n);return n||(m[0]=m[1],m[r-1]=m[r-2]),{...e,x:i,y:c,nx:l,ny:u,curvature:m}}var MN=6;function SN(e,t,r,n){let o=e.npts,a=e.closed?o:o-1,s=new Array(a);for(let l=0;l<a;l++){let u=(l+1)%o,m=Math.atan2(e.nx[l]*e.ny[u]-e.ny[l]*e.nx[u],e.nx[l]*e.nx[u]+e.ny[l]*e.ny[u]),f=Math.hypot(e.x[u]-e.x[l],e.y[u]-e.y[l]);s[l]=f>1e-9?m/f:0}let i=Math.max(0,Math.round(MN/(e.ds[0]||1))),c=1-n;for(let l=0;l<o;l++){let u=0,m=0;for(let f=-i-1;f<=i;f++){let p=e.closed?((l+f)%o+o)%o:l+f;p<0||p>=a||(u=Math.max(u,s[p]),m=Math.max(m,-s[p]))}u>0&&(t[l]=Math.max(r[l],Math.min(t[l],c/u))),m>0&&(r[l]=Math.min(t[l],Math.max(r[l],-c/m)))}}function Tg(e,t={}){let r={...Cg,...t},n=lt(e,{dsTarget:r.lineStep}),o=kN(n,r.referenceReach),a=o.npts,s=P=>({x:o.x.map((A,S)=>A+o.nx[S]*P[S]),y:o.y.map((A,S)=>A+o.ny[S]*P[S])}),i=P=>{let A=cc(P.x,P.y,o.closed),S=fA(P.x,P.y,o.closed),C=0;for(let L=0;L<A.length;L++)C+=A[L]*A[L]*S[L];return C},c=bN(n.curvature),l=fA(n.x,n.y,n.closed).reduce((P,A)=>P+A,0),u=new Array(a).fill(0),m=r.carHalfWidth+r.margin,f=new Array(a),p=new Array(a),d=0;for(let P=0;P<a;P++){let A=o.widthLeft[P]-m,S=-(o.widthRight[P]-m);if(A<S){d++;let C=(o.widthLeft[P]-o.widthRight[P])/2;f[P]=C,p[P]=C}else f[P]=A,p[P]=S}let h=[...f],b=[...p];SN(o,f,p,r.foldMargin);let g=P=>{let A=s(P),S=xN(e,o,P),C={name:`${e.name} \u2014 racing line`,x:A.x,y:A.y,closed:o.closed,widthLeft:h.map((E,_)=>Math.max(0,E-P[_])),widthRight:b.map((E,_)=>Math.max(0,P[_]-E)),...S,fit:"interpolate",turnReach:wg},L=1e-6,D=P.filter((E,_)=>E>=f[_]-L||E<=p[_]+L).length,I=cc(A.x,A.y,o.closed),O=E=>1/Math.max(...E.map(Math.abs),1e-9),N=0,z=o.closed?A.x.length:A.x.length-1;for(let E=0;E<z;E++){let _=(E+1)%A.x.length,B=A.x[_]-A.x[E],V=A.y[_]-A.y[E];N+=S.z?Math.hypot(B,V,S.z[_]-S.z[E]):Math.hypot(B,V)}return{offset:P,s:[...o.s],asset:C,curvatureRms:{centreLine:c,racingLine:Math.sqrt(i(A)/(l||1))},infeasibleSamples:d,atBoundary:a?D/a:0,length:{centreLine:n.length,racingLine:N},worstRadius:{centreLine:O(n.curvature),racingLine:O(I)}}},y=o.closed?0:1,R=o.closed?a-1:a-2,k=R-y+1,v=new Array(k),x=new Array(k);for(let P=0;P<k;P++)v[P]=p[y+P],x[P]=f[y+P];if(!o.closed&&k>0){let P=(A,S)=>{if(v[A]=Math.max(v[A],p[S]),x[A]=Math.min(x[A],f[S]),v[A]>x[A]){let C=.5*(v[A]+x[A]);v[A]=C,x[A]=C}};P(0,0),P(k-1,a-1),v[0]=x[0]=Math.min(x[0],Math.max(v[0],0))}if(k<7)return g(u);let M=P=>{let A=s(P),C=[...cc(A.x,A.y,o.closed).map(Math.abs)].sort((L,D)=>L-D);return{integral:i(A),tail:C[Math.floor(.99*(C.length-1))]}},F=[...u],w=M(u),T;for(let P=0;P<r.passes;P++){let A=s(F),{res:S,jac:C}=RN(A.x,A.y,o.nx,o.ny,o.closed),{M:L,b:D}=vN(C,S,y,R,o.closed),I=pA(L,D,v.map((z,E)=>z-F[y+E]),x.map((z,E)=>z-F[y+E]),{maxIter:r.iterations,bounds:T});T=I.bounds;let O=new Array(a).fill(0);for(let z=0;z<k;z++)O[y+z]=I.x[z];o.closed||(O[0]=O[1],O[a-1]=O[a-2]);let N=!1;for(let z of hN){let E=F.map((B,V)=>B+z*O[V]),_=M(E);if(_.integral<w.integral*(1-1e-6)){F=E,w=_,N=!0;break}}if(!N)break}return g(F)}function Pg(e){let t=Math.max(Q(e,"track_front"),Q(e,"track_rear"));return(t>0?t/2e3:.6)+.1}function Bm(e,t,r={}){if(!r.racingLine)return{asset:e,numerics:t,line:null};let n=r.params?Pg(r.params):void 0,o=Tg(e,{...r.line,...n?{carHalfWidth:n}:{}});return{asset:o.asset,numerics:{...t,fitSpacing:0},line:o}}function lc(e,t,r={}){let n=Bm(e,t,r);return{track:lt(n.asset,n.numerics),line:n.line}}function Lg(e=4,t=lc){let r=new WeakMap;return(n,o,a={})=>{let s=a.racingLine===!0,i=s?[a.params?Pg(a.params):null,a.line??null]:null,c=JSON.stringify([o,s,i]),l=r.get(n);l||(l=new Map,r.set(n,l));let u=l.get(c);if(u)return l.delete(c),l.set(c,u),u;let m=t(n,o,a);return l.set(c,m),l.size>e&&l.delete(l.keys().next().value),m}}var hA={racingLine:!1,standingStart:!1},$m=256;function uc(e,t,r,n,o=hA,a=lc){let s=xo(n),{racingLine:i,standingStart:c,lapCounts:l}=o;return e.map(u=>{let{track:m}=a(t,r,{racingLine:i,params:u});return mg(qi(u,s,{track:m,numerics:r,standingStart:c,lapCounts:l}))})}function Dg(e,t){let r=xo(e),n=r.score?r.score(t):null,o=r.field===r.score?n:r.field?r.field(t):null;return{scores:n,field:o}}function Eg(e,t,r){let n={};for(let o of xo(e).metrics)n[o.key]=o.value(t,r);return n}var Gm=36;var Ng=287.05287,FN=461.495,Km=9.80665/(Ng*.0065),wN=101325/(Ng*288.15),CN=273.15,TN=-500,PN=6e3,LN=400,DN=1100,Hm={source:"car",altitudeM:0,pressure:{kind:"standard"},humidityPct:0};function EN(e){return 101325*Math.pow(1-.0065*e/288.15,Km)}function IN(e){return 288.15/.0065*(1-Math.pow(e/wN,1/(Km-1)))}function _N(e){return 288.15/.0065*(1-Math.pow(e/101325,1/Km))}function NN(e,t){return e*Math.pow(1-.0065*t/288.15,Km)}function ON(e){return 611.21*Math.exp((18.678-e/234.5)*(e/(257.14+e)))}function VN(e,t){switch(e.kind){case"standard":return EN(t);case"qnh":return NN(e.hPa*100,t);case"station":return e.hPa*100}}function mc(e,t,r=0,n=_N(e)){let o=t+CN,a=Math.min(.5*e,Math.max(0,Math.min(100,r))/100*ON(t)),s=e-a,i=s/(Ng*o)+a/(FN*o);return{altitudeM:n,p:e,pDry:s,T:o,rho:i,densityAltitudeM:IN(i)}}function bA(e,t){return mc(VN(e.pressure,e.altitudeM),t,e.humidityPct,e.altitudeM)}var Ig=(e,t,r)=>Math.min(r,Math.max(t,e)),_g=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function zm(e){if(!e||typeof e!="object")return structuredClone(Hm);let t=e,r=t.pressure??{},n=Ig(_g(r.hPa,1013.25),LN,DN),o=r.kind==="qnh"?{kind:"qnh",hPa:n}:r.kind==="station"?{kind:"station",hPa:n}:{kind:"standard"};return{source:t.source==="venue"?"venue":"car",altitudeM:Ig(_g(t.altitudeM,0),TN,PN),pressure:o,humidityPct:Ig(_g(t.humidityPct,0),0,100)}}var pc=e=>e?.source==="venue";var BN=Math.PI/180;function $N(){return{ucaFront:[110,245,330],ucaRear:[-110,258,335],lcaFront:[130,185,112],lcaRear:[-130,205,116],tieInner:[-92,210,132],uprightUpper:[-6,542,352],uprightLower:[4,560,120],tieOuter:[-78,556,146],wheelCenter:[0,600,230],pushrodOuter:[8,520,128],rockerPivotA:[70,380,440],rockerPivotB:[-50,383,442],rockerToPushrod:[10,480,420],rockerToDamper:[10,280,440],damperChassis:[10,275,245]}}function GN(){return{ucaFront:[120,250,340],ucaRear:[-120,262,345],lcaFront:[140,190,118],lcaRear:[-140,210,122],tieInner:[120,215,150],uprightUpper:[-4,548,360],uprightLower:[6,566,126],tieOuter:[108,560,158],wheelCenter:[0,610,232],pushrodOuter:[10,526,132],rockerPivotA:[70,385,450],rockerPivotB:[-50,388,452],rockerToPushrod:[12,486,430],rockerToDamper:[12,286,450],damperChassis:[12,281,255]}}function Og(e){let t=-e*BN;return q([0,Math.cos(t),Math.sin(t)])}function Ym(){let e={rodType:"push",pushrodAttach:"lowerArm",steerMode:"rack",spinAxis:Og(-1),loadedRadius:230,springRate:35,rackAxis:[0,1,0]};return{hardpoints:$N(),config:e}}function dc(){let e={rodType:"pull",pushrodAttach:"lowerArm",steerMode:"fixed",spinAxis:Og(-1.5),loadedRadius:232,springRate:40,rackAxis:[0,1,0]};return{hardpoints:GN(),config:e}}function Wm(){let e=[-25,635,460],t=[-40,600,710],r={layout:"mcpherson",actuation:"direct",rodType:"push",pushrodAttach:"upright",steerMode:"rack",spinAxis:Og(-.5),loadedRadius:320,springRate:38,rackAxis:[0,1,0],rackTravel:70};return{hardpoints:{ucaFront:[49,426,430],ucaRear:[-99,425,431],lcaFront:[60,395,180],lcaRear:[-280,415,185],tieInner:[-150,375,256],uprightUpper:[...e],uprightLower:[0,720,145],tieOuter:[-140,705,230],wheelCenter:[0,775,320],pushrodOuter:[...e],damperChassis:[...t],rockerPivotA:[...t],rockerPivotB:[...t],rockerToPushrod:[...e],rockerToDamper:[...t]},config:r}}function Vg(){return{front:Ym(),rear:dc(),config:{wheelbase:1600,trackFront:1200,trackRear:1220,frontAxleX:800}}}var KN=Math.PI/180;function gA(e){let t=-e*KN;return q([0,Math.cos(t),Math.sin(t)])}function Bg(e,t){let r=([l,u,m])=>[l*t.kx,u*t.ky,m*t.kz],n=e.hardpoints,o=Object.fromEntries(Object.entries(n).map(([l,u])=>[l,r(u)])),a=(l,u)=>{o[l]=[o[l][0],o[l][1],o[l][2]+u]},s=t.lowerInnerDz??0,i=t.upperInnerDz??0;a("lcaFront",s),a("lcaRear",s),a("tieInner",s),a("ucaFront",i),a("ucaRear",i);let c={...e.config,spinAxis:gA(t.camberDeg),loadedRadius:t.loadedRadius,springRate:t.springRate};if(t.actuation==="direct"){let l=o.pushrodOuter,u=[l[0],l[1]*.7,l[2]+1.3*t.loadedRadius];o.damperChassis=u,o.rockerPivotA=u,o.rockerPivotB=u,o.rockerToPushrod=l,o.rockerToDamper=u,c={...c,actuation:"direct",rodType:"push",pushrodAttach:"lowerArm"}}else c={...c,actuation:"rocker"};for(let l of Object.keys(o))o[l]=HN(o[l]);return{hardpoints:o,config:c}}function HN(e){return e.map(t=>Math.round(t*10)/10+0)}function vo(e){return{name:e.name,front:Bg(Ym(),e.front),rear:Bg(dc(),e.rear),config:{wheelbase:e.wheelbase,trackFront:e.trackFront,trackRear:e.trackRear,frontAxleX:e.wheelbase/2}}}function Xa(e,t,r){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:t}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:r}}}}var qa=600,ko=610,Qa=230,Mo=232;function So(){let e=Vg();return{...e,name:"Formula Student",front:{...e.front,config:{...e.front.config,actuation:"rocker"}},rear:{...e.rear,config:{...e.rear.config,actuation:"rocker"}}}}function $g(){return vo({name:"Formula 1",wheelbase:3600,trackFront:1600,trackRear:1600,front:{kx:1.3,ky:800/qa,kz:355/Qa,lowerInnerDz:-5,upperInnerDz:0,camberDeg:-3,loadedRadius:355,springRate:200},rear:{kx:1.3,ky:800/ko,kz:355/Mo,lowerInnerDz:35,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:220}})}function fc(){return Xa(vo({name:"GT car",wheelbase:2700,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/qa,kz:325/Qa,lowerInnerDz:18,upperInnerDz:5,camberDeg:-3.5,loadedRadius:325,springRate:110,actuation:"direct"},rear:{kx:1.2,ky:825/ko,kz:325/Mo,lowerInnerDz:36,upperInnerDz:15,camberDeg:-2,loadedRadius:325,springRate:120,actuation:"direct"}}),318.6,318.6)}function hc(){return Xa(vo({name:"Sports car",wheelbase:2750,trackFront:1550,trackRear:1550,front:{kx:1.15,ky:775/qa,kz:320/Qa,lowerInnerDz:36,upperInnerDz:15,camberDeg:-.5,loadedRadius:320,springRate:55,actuation:"direct"},rear:{kx:1.15,ky:775/ko,kz:320/Mo,lowerInnerDz:57,upperInnerDz:25,camberDeg:-1,loadedRadius:320,springRate:60,actuation:"direct"}}),305.4,309)}function zN(e,t,r,n,o,a){let s=Wm(),i=Object.fromEntries(Object.entries(s.hardpoints).map(([l,[u,m,f]])=>[l,[u,m+e,f]])),c=(l,u)=>{i[l]=[i[l][0],i[l][1],i[l][2]+u]};return c("lcaFront",t),c("lcaRear",t),c("tieInner",r),{hardpoints:i,config:{...s.config,spinAxis:gA(n),springRate:o,rackTravel:a}}}function yA(){return Xa({name:"Cup car",front:zN(55,-25,-23,-3.5,150,55),rear:Bg(dc(),{kx:1.15,ky:820/ko,kz:320/Mo,lowerInnerDz:37,upperInnerDz:12,camberDeg:-2,loadedRadius:320,springRate:130,actuation:"direct"}),config:{wheelbase:2650,trackFront:1660,trackRear:1640,frontAxleX:2650/2},chassis:{boxes:[],body:"cup"}},306.3,311.6)}function xA(){return{...Xa(vo({name:"Stock car",wheelbase:2794,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/qa,kz:355/Qa,lowerInnerDz:20,upperInnerDz:5,camberDeg:-2.5,loadedRadius:355,springRate:175,actuation:"direct"},rear:{kx:1.2,ky:825/ko,kz:355/Mo,lowerInnerDz:40,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:150,actuation:"direct"}}),343.8,345.3),chassis:{boxes:[],body:"nascar"}}}function RA(){let e=Xa(vo({name:"Hill-climb prototype",wheelbase:2550,trackFront:1580,trackRear:1540,front:{kx:1.1,ky:790/qa,kz:300/Qa,lowerInnerDz:10,upperInnerDz:5,camberDeg:-2.5,loadedRadius:300,springRate:90},rear:{kx:1.1,ky:770/ko,kz:300/Mo,lowerInnerDz:30,upperInnerDz:15,camberDeg:-1.5,loadedRadius:300,springRate:120}}),293.3,290.8);return{...e,front:{...e.front,config:{...e.front.config,rackTravel:45}},chassis:{boxes:[],body:"hillclimb"}}}function vA(){let e=Xa(vo({name:"Race truck",wheelbase:3700,trackFront:2050,trackRear:1950,front:{kx:1.5,ky:1025/qa,kz:506/Qa,lowerInnerDz:40,upperInnerDz:10,camberDeg:-.5,loadedRadius:506,springRate:200,actuation:"direct"},rear:{kx:1.5,ky:975/ko,kz:506/Mo,lowerInnerDz:60,upperInnerDz:20,camberDeg:-.25,loadedRadius:506,springRate:160,actuation:"direct"}}),490.4,495.6);return{...e,front:{...e.front,config:{...e.front.config,rackTravel:60}},chassis:{boxes:[],body:"truck"}}}var nt=(e,t,r)=>({value:e,label:t,unit:r}),kA=(e,t)=>({...fr[e],value:t});function MA(e,t,r){let n=[],o=[];for(let a=0;a<=r;a+=500)n.push(a),o.push(a<=t?e:e*t/a);return{rpm:n,torque:o}}function Ao(e,t,r,n,o){let a=[],s=[];for(let i=0;i<=r;i+=500){a.push(i);let c=i<=t?n:Math.min(n,9549*e/i);s.push(c/o)}return{rpm:a,torque:s}}function Jr(e){let t={name:e.name,m:nt(e.m,"vehicle mass (with driver)","kg"),A:nt(e.A,"frontal area","m^2"),c_l:nt(e.cl,"downforce coefficient","-"),c_w:nt(e.cw,"drag coefficient","-"),l_to_d_ratio:nt(e.cw>0?e.cl/e.cw:0,"lift-to-drag ratio","-"),driven_wheels:nt(e.drivenWheels,"driven wheels","-"),fr_0:nt(-.012,"rolling-resistance coefficient","-"),front_aero_diss:nt(e.frontAero,"front aero distribution","-"),front_mass_diss:nt(e.frontMass,"front mass distribution","-"),r_dyn:nt(e.rDyn,"dynamic tyre radius","m"),rho:nt(1.2,"air density","kg/m^3"),gear_ratio:nt(e.gearRatio,"gear ratio","-"),effi_pgb:nt(e.drivetrainEfficiency,"drivetrain efficiency","-"),capacity:nt(e.capacityAh,"pack capacity","Ah"),soc:nt(1,"state of charge","-"),ocv:nt(e.ocv,"pack open-circuit voltage","V"),power_scale:nt(1,"power scaling factor","-"),power_limit_kw:kA("power_limit_kw",e.powerLimitKw),motor:e.motor,tireModelId:e.tireModelId};e.motorCount!==void 0&&(t.motorCount=e.motorCount),e.driveline&&(t.driveline=structuredClone(e.driveline)),e.motorPlacement&&(t.motorPlacement=e.motorPlacement);for(let[r,n]of Object.entries(e.dynamics))t[r]=kA(r,n);return t}var Za={name:"Formula Student",m:300,A:1,cl:3,cw:1.3,frontMass:.47,frontAero:.45,rDyn:.222,drivenWheels:2,gearRatio:11.5,motor:MA(25,15e3,2e4),capacityAh:12,ocv:550,drivetrainEfficiency:.95,powerLimitKw:80,tireModelId:"t3",dynamics:{grip_scale:1,stiffness_scale:1,endurance_reserve:5,cg_height:300,tire_vertical_rate:110,unsprung_mass:8,brake_balance:.62,arb_front:20,arb_rear:15,damper_front:2.5,damper_rear:2.5,spring_front:35,spring_rear:40,mr_front:.94,mr_rear:.92,cop_long:.55,cop_height:300,ride_height_front:30,ride_height_rear:35,I_yaw:140,I_roll:45,I_pitch:130,camber_front_deg:-1,camber_rear_deg:-1.5,track_front:1200,track_rear:1220,wheelbase:1600,rc_front:5,rc_rear:4}},Kg={name:"Formula 1",m:798,A:1.5,cl:3,cw:.9,frontMass:.46,frontAero:.44,rDyn:.35,drivenWheels:2,gearRatio:4.9,motor:Ao(735,2e3,12500,2500,2),motorCount:1,driveline:{rear:St.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t4",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:290,tire_vertical_rate:300,unsprung_mass:30,brake_balance:.58,arb_front:250,arb_rear:150,damper_front:6,damper_rear:6,spring_front:200,spring_rear:220,mr_front:.95,mr_rear:.91,heave_spring_front:800,heave_spring_rear:800,tire_vertical_damping:.5,cop_long:.56,cop_height:400,ride_height_front:35,ride_height_rear:70,I_yaw:800,I_roll:150,I_pitch:800,camber_front_deg:-3,camber_rear_deg:-1.5,track_front:1600,track_rear:1600,wheelbase:3600,rc_front:-4,rc_rear:78}},jm={name:"GT car",m:1300,A:2,cl:1.4,cw:.42,frontMass:.5,frontAero:.42,rDyn:.33,drivenWheels:2,gearRatio:3.43,motor:Ao(410,2e3,8e3,2e3,2),motorCount:1,driveline:{rear:St.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t5",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:450,tire_vertical_rate:280,unsprung_mass:45,brake_balance:.6,arb_front:40,arb_rear:25,damper_front:4.5,damper_rear:4.5,spring_front:110,spring_rear:120,mr_front:.79,mr_rear:.77,cop_long:.58,cop_height:500,ride_height_front:55,ride_height_rear:75,I_yaw:1800,I_roll:450,I_pitch:1800,camber_front_deg:-3.5,camber_rear_deg:-2,track_front:1650,track_rear:1650,wheelbase:2700,rc_front:48,rc_rear:80}},Um={name:"Sports car",m:1600,A:2.2,cl:-.1,cw:.3,frontMass:.55,frontAero:.5,rDyn:.32,drivenWheels:2,gearRatio:3.14,motor:Ao(220,1500,6500,1400,2),motorCount:1,driveline:{rear:St.open},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t6",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:520,tire_vertical_rate:220,unsprung_mass:50,brake_balance:.65,arb_front:25,arb_rear:12,damper_front:2.4,damper_rear:2.4,spring_front:55,spring_rear:60,mr_front:.78,mr_rear:.75,cop_long:.5,cop_height:500,ride_height_front:130,ride_height_rear:140,I_yaw:2600,I_roll:550,I_pitch:2500,camber_front_deg:-.5,camber_rear_deg:-1,track_front:1550,track_rear:1550,wheelbase:2750,rc_front:80,rc_rear:122}},Hg={name:"Cup car",m:1265,A:2.1,cl:.45,cw:.4,frontMass:.62,frontAero:.45,rDyn:.31,drivenWheels:2,gearRatio:3.5,motor:Ao(250,2e3,7e3,1190,2),motorCount:1,motorPlacement:"front",driveline:{front:St.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t7",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:480,tire_vertical_rate:280,unsprung_mass:40,brake_balance:.68,arb_front:20,arb_rear:90,damper_front:4,damper_rear:3.5,spring_front:150,spring_rear:130,mr_front:.95,mr_rear:.76,cop_long:.55,cop_height:450,ride_height_front:64,ride_height_rear:78,I_yaw:1700,I_roll:400,I_pitch:1700,camber_front_deg:-3.5,camber_rear_deg:-2,track_front:1660,track_rear:1640,wheelbase:2650,rc_front:60,rc_rear:84}},zg={name:"Stock car",m:1620,A:2.2,cl:.6,cw:.45,frontMass:.53,frontAero:.45,rDyn:.35,drivenWheels:2,gearRatio:4.1,motor:Ao(500,2500,9e3,1680,2),motorCount:1,driveline:{rear:St.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t8",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:430,tire_vertical_rate:320,unsprung_mass:55,brake_balance:.6,arb_front:60,arb_rear:15,damper_front:7.5,damper_rear:6.75,spring_front:175,spring_rear:150,mr_front:.8,mr_rear:.78,cop_long:.55,cop_height:500,ride_height_front:75,ride_height_rear:90,I_yaw:2500,I_roll:550,I_pitch:2500,camber_front_deg:-2.5,camber_rear_deg:-1.5,track_front:1650,track_rear:1650,wheelbase:2794,rc_front:53,rc_rear:91}},Yg={name:"Hill-climb prototype",m:650,A:1.2,cl:2.5,cw:.9,frontMass:.42,frontAero:.42,rDyn:.29,drivenWheels:2,gearRatio:4,motor:Ao(330,3e3,8500,1240,2),motorCount:1,driveline:{rear:St.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t9",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:280,tire_vertical_rate:200,unsprung_mass:25,brake_balance:.58,arb_front:40,arb_rear:30,damper_front:3,damper_rear:3.5,spring_front:90,spring_rear:120,mr_front:.94,mr_rear:.91,cop_long:.58,cop_height:350,ride_height_front:45,ride_height_rear:55,I_yaw:550,I_roll:120,I_pitch:550,camber_front_deg:-2.5,camber_rear_deg:-1.5,track_front:1580,track_rear:1540,wheelbase:2550,rc_front:27,rc_rear:65}},Wg={name:"Race truck",m:5300,A:6.2,cl:-.1,cw:.65,frontMass:.6,frontAero:.6,rDyn:.502,drivenWheels:2,gearRatio:3.55,motor:Ao(880,100,3e3,88e3,2),motorCount:1,driveline:{rear:St.spool},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t10",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:950,tire_vertical_rate:1e3,unsprung_mass:350,brake_balance:.75,arb_front:350,arb_rear:150,damper_front:12,damper_rear:8.5,spring_front:200,spring_rear:160,mr_front:.81,mr_rear:.8,cop_long:.4,cop_height:1500,ride_height_front:110,ride_height_rear:240,I_yaw:16e3,I_roll:3500,I_pitch:16e3,camber_front_deg:-.5,camber_rear_deg:-.25,track_front:2050,track_rear:1950,wheelbase:3700,rc_front:95,rc_rear:134}};function Gg(e,t,r){return Jr(r({...structuredClone(e),name:t}))}var Xm={[Za.name]:Jr(Za),"Formula Student +15% downforce":Gg(Za,"Formula Student +15% downforce",e=>({...e,cl:e.cl*1.15,cw:e.cw*1.08})),"Formula Student -15 kg":Gg(Za,"Formula Student -15 kg",e=>({...e,m:e.m-15})),"Formula Student +15% power":Gg(Za,"Formula Student +15% power",e=>({...e,motor:MA(25*1.15,15e3,2e4),powerLimitKw:80*1.15})),[Kg.name]:Jr(Kg),[jm.name]:Jr(jm),[Um.name]:Jr(Um),[Hg.name]:Jr(Hg),[zg.name]:Jr(zg),[Yg.name]:Jr(Yg),[Wg.name]:Jr(Wg)},SA=Object.keys(Xm),jg=SA.slice(0,4),Ug=[Za.name,Kg.name,jm.name,Um.name,Hg.name,zg.name,Yg.name,Wg.name];var qne={"Touring car":jm.name,"Street car":Um.name};var YN={bg:"#0e1116",panel:"#161b22",panel2:"#1c232d",border:"#2a323d",borderBright:"#39424e",sunken:"#11161c",ink:"#06090d"},WN={normal:"#d6dde6",dim:"#8b96a3",bright:"#e7ecf3",white:"#ffffff"},jN={label:"#c8d2dc",grid:"#39424e",gridFaint:"#232b35",empty:"#1a2028"},UN={accent:"#4aa3ff",accentInk:"#04121f",warn:"#ffb454",good:"#4ec9a0",bad:"#ff6b6b",badSoft:"#ff8f8f"},XN=["#f0e442","#7b68ee","#f7a8b8","#d55e00","#d8b4fe","#b5e48c"],qm={front:"#a6e22e",rear:"#00b4d8"},AA=["#5b4bd6","#4aa3ff","#4ec9a0","#f0e442"],Xg={power:"#ffb454",traction:"#f0845c",front:qm.front,rear:qm.rear,grip:"#73c9b3",braking:"#b48aff",crest:"#e88fd0",below:"rgba(214, 221, 230, 0.32)"},qN={chassis:"#4aa3ff",ballJoint:"#ffb454",arm:"#b8c3cf",tie:"#73c9b3",pushrod:"#e5c65f",rocker:"#9f91d4",kingpin:"#d8c968",arbBar:"#cf7898",arbArm:"#b96b86",arbLink:"#ffb454",heaveSpring:"#7ad7f0",wheelCentre:"#e7ecf3",contactPatch:"#ff6b6b",ground:"#15222e",groundFaint:"#0b151f"},QN={x:"#ff6b6b",y:"#57c75a",z:"#4aa3ff"},ZN={line:"#b4bfcb"},JN={compression:"#b48aff",tension:"#ff6b6b"},eO={fz:"#e7ecf3",fx:"#7ad7f0",fy:"#ff54c8"},tO={drivenLine:"#4d7cff",axis:"#eef3fa",slip:"#ffe81a",drive:Xg.power,brake:Xg.braking},rO={ground:"#101920",grid:"#1a2630",gridMajor:"#26343f",horizon:"#1d2833",bridge:"#6f7a86",coneLeft:"#2f63c9",coneRight:"#d9b51f",coneStart:"#ee7a2c"},nO={chassis:"#435160",volume:"#303b47",tyre:"#435160",tyreLine:"#39424e",tyreFace:"#1c232d"},oO={centreLine:"#4aa3ff",corridorFill:"rgba(74,163,255,0.10)",boundary:"#3d4956",racingLine:"#ffb454",start:"#e7ecf3",finish:"#ff6b6b",direction:"#8b96a3"},aO={SURFACE:YN,TEXT:WN,CHART:jN,ROLE:UN,SERIES:XN,AXLE:qm,LAP_SPEED:AA,LIMITER:Xg,RIG:qN,AXIS:QN,CONSTRUCTION:ZN,FORCE:JN,TYRE_FORCE:eO,REPLAY:tO,SCENERY:rO,BODY:nO,TRACK:oO},FA=e=>Object.fromEntries(Object.entries(e).map(([t,r])=>[t,Array.isArray(r)?Object.freeze([...r]):Object.freeze({...r})])),Qm=FA(aO),Ft=Qm.SERIES,wA=(()=>{let e="#b06400",t="#d1343a",r={front:"#70bf03",rear:"#3392d0"},n={power:e,traction:"#d05a2a",front:r.front,rear:r.rear,grip:"#2a9a83",braking:"#7b55d0",crest:"#c2479f",below:"rgba(34, 39, 45, 0.28)"};return FA({SURFACE:{bg:"#f4f5f3",panel:"#fbfbfa",panel2:"#ffffff",border:"#d6dadd",borderBright:"#b7bec4",sunken:"#eceeeb",ink:"#ffffff"},TEXT:{normal:"#22272d",dim:"#5c6570",bright:"#0f1215",white:"#000000"},CHART:{label:"#3a424b",grid:"#c2c8cd",gridFaint:"#e2e5e7",empty:"#e8eae7"},ROLE:{accent:"#1a64c2",accentInk:"#ffffff",warn:e,good:"#0f8a66",bad:t,badSoft:"#e2696d"},SERIES:["#b5a11a","#2844e3","#f47ec1","#9b3a1b","#764299","#58b977"],AXLE:r,LAP_SPEED:["#4b3bc4","#1a64c2","#0f8a66","#a87e00"],LIMITER:n,RIG:{chassis:"#1a64c2",ballJoint:"#c27200",arm:"#56616d",tie:"#24907b",pushrod:"#a3820f",rocker:"#6656b8",kingpin:"#8f7f10",arbBar:"#b04d77",arbArm:"#9a4767",arbLink:"#c27200",heaveSpring:"#1688ad",wheelCentre:"#15181c",contactPatch:t,ground:"#e2e6e8",groundFaint:"#edf0f1"},AXIS:{x:"#d93a3a",y:"#2f9d34",z:"#1a64c2"},CONSTRUCTION:{line:"#5a6570"},FORCE:{compression:"#7b55d0",tension:t},TYRE_FORCE:{fz:"#15181c",fx:"#0f8fb0",fy:"#c8198f"},REPLAY:{drivenLine:"#2f5be0",axis:"#15181c",slip:"#c79a00",drive:n.power,brake:n.braking},SCENERY:{ground:"#dde3e1",grid:"#ccd3d1",gridMajor:"#b5bfbc",horizon:"#e8edf0",bridge:"#9aa3ab",coneLeft:"#2f63c9",coneRight:"#d9b51f",coneStart:"#ee7a2c"},BODY:{chassis:"#a9b3bd",volume:"#c7ced5",tyre:"#24282c",tyreLine:"#2c333a",tyreFace:"#c3cad0"},TRACK:{centreLine:"#1a64c2",corridorFill:"rgba(26,100,194,0.10)",boundary:"#a3acb4",racingLine:e,start:"#15181c",finish:t,direction:"#5c6570"}})})();var CA=e=>{let t=/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(e.trim());return t?`#${(t[1].length===3?t[1].replace(/./g,n=>n+n):t[1]).toLowerCase()}`:null},Zne=(()=>{let e=new Map,t=["SERIES","AXLE","LAP_SPEED","LIMITER","ROLE","RIG","FORCE","TYRE_FORCE","REPLAY","AXIS","TRACK","CONSTRUCTION","TEXT","CHART","SCENERY","BODY","SURFACE"];for(let r of t){let n=Qm[r],o=wA[r];for(let a of Object.keys(n)){let s=CA(n[a]);s&&!e.has(s)&&e.set(s,o[a])}}return e})();var TA=(e,t)=>new Set(t.flatMap(r=>{let n=e[r];return Array.isArray(n)?[...n]:Object.values(n)}).map(CA).filter(r=>r!==null)),Jne=TA(wA,["SERIES","AXLE","LAP_SPEED","LIMITER","ROLE","RIG","FORCE","TYRE_FORCE","REPLAY","AXIS","TRACK","CONSTRUCTION"]),eoe=TA(Qm,Object.keys(Qm).filter(e=>e!=="SURFACE"));function qg(){return{kind:"simple",name:"Simple motor",rpm:[0,16e3,2e4],torque:[21,21,14],efficiency:.95}}function Qg(){return{kind:"map",name:"Mapped motor",rpm:[0,8e3,16e3,2e4],torque:[24,24,21,16],effRpm:[1e3,5e3,9e3,13e3,17e3,2e4],effTorque:[4,8,12,16,21],effGrid:[[.78,.84,.86,.85,.82,.79],[.83,.9,.93,.92,.89,.86],[.85,.93,.96,.95,.92,.89],[.84,.92,.95,.94,.91,.88],[.82,.89,.92,.9,.87,.84]]}}function Zg(){return{kind:"simple",name:"Inboard motor, axial flux (example)",rpm:[0,4e3,4500,5e3,5500,6e3],torque:[230,230,204,184,167,153],efficiency:.95}}function Jg(){return{kind:"ice",name:"600 cc four, restricted (example)",rpm:[3e3,4e3,5e3,6e3,7e3,8e3,9e3,1e4,11e3,12e3,12500],torque:[40,46,52,56,59,61,62,60,56,49,45],idleRpm:3e3,limitRpm:12500,inertia:.012,gearbox:{primary:76/36,ratios:[33/12,32/16,30/18,26/18,30/23,29/24],efficiency:.9,upshiftTime:.1,downshiftTime:.08},breathing:{induction:{kind:"natural"}}}}function e0(){return{kind:"ice",name:"Formula 1 power unit (example)",rpm:[4e3,5e3,6e3,7e3,8e3,9e3,1e4,10500,11e3,11500,12e3,12500],torque:[896,822,773,738,712,692,675,668,638,610,585,545],idleRpm:4e3,limitRpm:12500,inertia:.02,gearbox:{primary:1,ratios:[4,3.15,2.575,2.175,1.85,1.6,1.375,1.18],efficiency:.94,upshiftTime:0,downshiftTime:0,driveKept:1},breathing:{induction:{kind:"boosted",boostKPa:350,maxPressureRatio:5}}}}function PA(){return{kind:"ice",name:"GT race engine, 4.0 l (example)",rpm:[2500,3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3,7500,8e3],torque:[380,410,440,465,485,500,515,525,530,540,522,480],idleRpm:2500,limitRpm:8e3,inertia:.15,gearbox:{primary:1,ratios:[3,2.15,1.7,1.4,1.17,.98],efficiency:.93,upshiftTime:.05,downshiftTime:.08},breathing:{induction:{kind:"natural"}}}}function LA(){return{kind:"ice",name:"Turbocharged 3.0 l six (example)",rpm:[1e3,1500,1800,2500,3500,4500,5e3,5500,6e3,6500,7e3],torque:[230,340,400,400,400,400,400,382,350,315,280],idleRpm:1e3,limitRpm:7e3,inertia:.2,gearbox:{primary:1,ratios:[3.6,2.19,1.54,1.21,1,.83],efficiency:.92,upshiftTime:.2,downshiftTime:.2,driveKept:.8},breathing:{induction:{kind:"boosted",boostKPa:220,maxPressureRatio:3}}}}function DA(){return{kind:"ice",name:"Turbocharged 2.0 l four (example)",rpm:[2e3,2500,3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3],torque:[330,400,420,420,420,420,415,410,398,365,330],idleRpm:2e3,limitRpm:7e3,inertia:.15,gearbox:{primary:1,ratios:[2.92,2.05,1.61,1.32,1.12,.97],efficiency:.93,upshiftTime:.07,downshiftTime:.08},breathing:{induction:{kind:"boosted",boostKPa:250,maxPressureRatio:3.2}}}}function EA(){return{kind:"ice",name:"Stock car V8, 5.9 l (example)",rpm:[2500,3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3,7500,8e3,8500,9e3],torque:[450,480,510,535,555,570,585,595,600,598,590,578,562,525],idleRpm:2500,limitRpm:9e3,inertia:.18,gearbox:{primary:1,ratios:[2.8,2,1.55,1.24,1],efficiency:.93,upshiftTime:.1,downshiftTime:.1},breathing:{induction:{kind:"natural"}}}}function IA(){return{kind:"ice",name:"Turbocharged 2.0 l four, hill climb (example)",rpm:[3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3,7500,8e3,8500],torque:[314,380,446,462,462,462,458,450,437,420,388,347],idleRpm:3e3,limitRpm:8500,inertia:.1,gearbox:{primary:1,ratios:[2.69,2,1.6,1.33,1.14,1],efficiency:.93,upshiftTime:.05,downshiftTime:.08},breathing:{induction:{kind:"boosted",boostKPa:250,maxPressureRatio:4.5}}}}function _A(){return{kind:"ice",name:"Race truck diesel six, 13 l (example)",rpm:[800,1e3,1200,1400,1600,1800,2e3,2200,2400,2600,2800,3e3],torque:[3e3,4e3,4900,5500,5250,4670,4200,3820,3500,3230,3e3,2700],idleRpm:800,limitRpm:3e3,inertia:1.5,gearbox:{primary:1,ratios:[16,12.44,9.67,7.51,5.84,4.54,3.53,2.74,2.13,1.66,1.29,1],efficiency:.92,upshiftTime:.35,downshiftTime:.35},breathing:{induction:{kind:"boosted",boostKPa:350,maxPressureRatio:4.3}}}}function NA(e){return go(sO(e))}function sO(e){if(e===null||typeof e!="object"||Array.isArray(e))return e;let t={...e};return delete t.name,Array.isArray(t.vehicles)&&(t.vehicles=t.vehicles.map(r=>{if(r===null||typeof r!="object"||Array.isArray(r))return r;let n={...r};return delete n.name,n})),t}function bc(e,t){return{...t,fingerprint:NA(e)}}var OA="CC-BY-4.0",iO={title:"PaceDynamics built-in library",url:"https://pacedyn.dev/",licence:OA},VA={fidelity:"generic",licence:OA,sources:[iO]};var Zm=e=>bc(e,VA);var BA=["raw.githubusercontent.com"],$A=["tum-csv"],lO=/^[0-9a-f]{64}$/;function yc(e){if(typeof e!="object"||e===null||Array.isArray(e))return!1;let{url:t,sha256:r,format:n}=e;if(typeof t!="string"||t.length>500||typeof r!="string"||!lO.test(r)||!$A.includes(n))return!1;try{let o=new URL(t);return o.protocol==="https:"&&BA.includes(o.hostname)&&!o.username&&!o.password&&!o.port}catch{return!1}}var Jm=e=>new URL(e.url).hostname;async function GA(e){let t=await globalThis.crypto.subtle.digest("SHA-256",e);return[...new Uint8Array(t)].map(r=>r.toString(16).padStart(2,"0")).join("")}function uO(e){let t=new URL(e).pathname.split("/").pop()??"";return decodeURIComponent(t).replace(/\.[^.]*$/,"")||"Linked track"}function mO(e,t){let r=[],n=[],o=[],a=[];for(let[s,i]of e.split(/\r?\n/).entries()){let c=i.trim();if(!c||c.startsWith("#"))continue;let l=c.split(",").map(u=>Number(u.trim()));if(l.length!==4||!l.every(Number.isFinite))throw new Error(`Line ${s+1} of ${t} is not four numbers.`);r.push(l[0]),n.push(l[1]),o.push(l[2]),a.push(l[3])}if(r.length<3)throw new Error(`${t} has ${r.length} points; a track needs at least 3.`);return{name:t,x:r,y:n,widthLeft:a,widthRight:o,closed:!0,fit:"interpolate"}}var pO={"tum-csv":mO};function KA(e,t){return pO[t.format](e,uO(t.url))}async function t0(e,t,r){let n=await GA(e);if(n!==t.sha256)throw new Error(`${Jm(t)} did not return the file that was reviewed (its SHA-256 is ${n.slice(0,12)}\u2026, not ${t.sha256.slice(0,12)}\u2026).`);let o=KA(new TextDecoder().decode(e),t),a=await ep(o);if(a!==r)throw new Error(`Linked track ${r} does not convert to its name (it is ${a}).`);return o}var r0=20,fO=new RegExp(`^[0-9a-f]{${r0}}$`),xc=e=>typeof e=="string"&&fO.test(e);async function ep(e){let t=new TextEncoder().encode(wn(e)),r=await globalThis.crypto.subtle.digest("SHA-256",t);return[...new Uint8Array(r)].map(n=>n.toString(16).padStart(2,"0")).join("").slice(0,r0)}var n0=e=>`tracks/${e}.json`;var hO=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function o0(e){return{model:{name:e.name,source:e.source},...e.provenance?{provenance:e.provenance}:{}}}async function a0(e,t){if(!hO(e)||typeof e.name!="string"||!Array.isArray(e.x)||!Array.isArray(e.y)||e.x.length!==e.y.length||e.x.length<2)throw new Error(`Catalogue track ${t} is not a track.`);let r=await ep(e);if(r!==t)throw new Error(`Catalogue track ${t} does not match its name (it is ${r}).`);return e}var Fo=(e,t,r,n=[])=>({doc:e,ref:t,refs:[t,...n.map(o=>o.ref)],slots:[{key:e,ref:t,label:r},...n],label:r}),Cn=[Fo("suspensions","suspensionId","suspension"),Fo("tires","tireModelId","tyre",[{key:"tiresRear",ref:"tireModelIdRear",label:"rear tyre"}]),Fo("motors","motorModelId","motor"),Fo("aeros","aeroModelId","aero map"),Fo("batteries","batteryModelId","battery"),Fo("brakes","brakeModelId","brakes"),Fo("dampers","damperModelId","dampers",[{key:"dampersRear",ref:"damperModelIdRear",label:"rear dampers"},{key:"dampersHeave",ref:"heaveDamperModelId",label:"heave dampers"},{key:"dampersRoll",ref:"rollDamperModelId",label:"roll dampers"}])];function tp(e){let t={...e};for(let r of Cn)for(let n of r.refs)delete t[n];return t}var rp=Ft,Rc=rp,s0=rp,Tn=[...Ft.slice(3),...Ft.slice(0,3)],l0=[...Ft.slice(1),Ft[0]],i0=[...Ft.slice(2),...Ft.slice(0,2)],c0=[...Ft.slice(4),...Ft.slice(0,4)],u0=[...Ft.slice(5),...Ft.slice(0,5)],vc=[...Ft.slice(2),...Ft.slice(0,2)];function m0(){let e=globalThis.crypto;return e&&typeof e.randomUUID=="function"?e.randomUUID():`p-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}function p0(e,t,r){let n=Xm[e];if(!n)throw new Error(`no preset vehicle named "${e}"`);return{id:t,params:{...ki(structuredClone(n)),energy:{...Br},suspensionId:"sus1"},visible:!0,color:Rc[r%Rc.length]}}function yO(){return jg.map((e,t)=>p0(e,`v${t+1}`,t))}function xO(){return[Js(),Xf(),qf(),Qf(),Zf(),Jf(),eh(),th(),rh(),nh()].map((t,r)=>({id:`t${r+1}`,color:s0[r%s0.length],model:t}))}function RO(){return[Td(),Pd(),Ld(),Dd(),Ed(),Id(),_d(),Nd()].map((t,r)=>({id:`a${r+1}`,color:i0[r%i0.length],model:t}))}function vO(){return[fd(),hd(),bd()].map((t,r)=>({id:`b${r+1}`,color:c0[r%c0.length],model:t}))}function kO(){return[{id:"brk1",color:u0[0],model:structuredClone(kh)}]}function MO(){return[{id:"dmp1",color:vc[0],model:structuredClone(Du)}]}function SO(){return[qg(),Qg()].map((t,r)=>({id:`m${r+1}`,color:Tn[r%Tn.length],model:t}))}function d0(e){let t=r=>({...r,provenance:Zm(r.model)});return{...e,suspensions:e.suspensions.map(t),vehicles:e.vehicles.map(r=>({...r,provenance:Zm(tp(r.params))})),tires:e.tires.map(t),motors:e.motors.map(t),aeros:e.aeros.map(t),batteries:e.batteries.map(t),brakes:e.brakes.map(t),dampers:e.dampers.map(t)}}function kc(e="Untitled project"){let t=new Date().toISOString(),r=yO();return d0({schemaVersion:Gm,meta:{id:m0(),name:e,domain:"racecar",rulesetId:yo,createdAt:t,updatedAt:t},suspensions:[{id:"sus1",color:l0[0],model:So()}],activeSuspensionId:"sus1",vehicles:r,activeVehicleId:r[0]?.id??null,tires:xO(),motors:SO(),aeros:RO(),batteries:vO(),brakes:kO(),dampers:MO(),tracks:[],activeTrackId:null,mathChannels:[],rulesets:[],studies:[],activeStudyId:null,loadCases:[],reportLayouts:[],tyreSheets:[],kinSheets:[],plans:[],results:[],settings:{numerics:{...Vi},ggvMode:"twoTrack",quasiTransient:!1,motorThermal:!1,brakeFade:!1,airTempC:Lt,air:structuredClone(Hm),diffYaw:!1,lapCounts:{},pathPlanId:null,useRacingLine:!0,standingStart:!1}})}var AO=["front","rear"],f0=9.81,FO=Math.PI/180;var kr="*",h0=40,HA=.8;function b0(e){let{s:t,curvature:r}=e;if(!t?.length||t.length!==r?.length)return null;let n=0,o=0,a=0,s=0;for(let i=0;i<t.length;i++){for(;a<t.length&&t[a]<=t[i]+2.5;)s+=Math.abs(r[a++]);for(;t[o]<t[i]-2.5;)s-=Math.abs(r[o++]);let c=s/Math.max(1,a-o);c>n&&(n=c)}return n>1e-6?1/n:null}function zA(e,t,r){let n=t.rows.map(c=>c.v),o=c=>ht(n,t.rows.map(l=>l.ayMax),Math.min(n[n.length-1],Math.max(n[0],c))),a=(c,l,u)=>({speedKmh:Math.round(c*36)/10,ayG:Math.round(l/f0*100)/100+0,axG:Math.round(u/f0*100)/100+0}),s=t.vMax,i=Array.from({length:41},(c,l)=>20/3.6+l*Math.max(0,s-20/3.6)/40);switch(e){case"slowCorner":{if(r===null)return a(h0/3.6,o(h0/3.6),0);let c=10;for(let l=0;l<30;l++)c=Math.min(s,Math.sqrt(r*o(c)));return a(c,o(c),0)}case"fastCorner":return a(HA*s,o(HA*s),0);case"braking":{let c=i.reduce((l,u)=>t.axDecel(u,0)<t.axDecel(l,0)?u:l);return a(c,0,t.axDecel(c,0))}case"traction":{let c=i.reduce((l,u)=>t.axAccel(u,0)>t.axAccel(l,0)?u:l);return a(c,0,t.axAccel(c,0))}case"topSpeed":return a(s,0,0)}}function g0(e,t,r){let n=!1,o=e.map(a=>{if(!a.follows)return a;let s=zA(a.follows,t,r);return![s.speedKmh,s.ayG,s.axG].every(Number.isFinite)||!t.rows.some(i=>i.ayMax>0)||s.speedKmh===a.speedKmh&&s.ayG===a.ayG&&s.axG===a.axG?a:(n=!0,{...a,...s})});return n?o:e}function y0(e,t){let r=e.speedKmh/3.6,n=e.ayG*f0;if(!(Math.abs(n)>1e-6)||!(r>.1))return 0;let o=r*r/Math.abs(n);return Math.sign(n)*Math.atan(t/1e3/o)/FO}var YA=e=>e.ayG<0?"L":"R";function x0(e,t=AO){if(!e.length||!t.length)return null;let r=t.flatMap(i=>i==="front"?["FL","FR"]:["RL","RR"]),n=0,o=0,a=0;for(let i of e){for(let c of r){let l=i.corners[c].travel;if(!Number.isFinite(l))return null;n=Math.min(n,l),o=Math.max(o,l)}a=Math.max(a,Math.abs(i.rollDeg))}let s=5;return{travelMin:Math.min(-1,Math.floor(n-s)),travelMax:Math.max(1,Math.ceil(o+s)),rollMaxDeg:Math.max(.5,Math.ceil((a+.5)*10)/10),rollAtLimitDeg:Math.ceil(a*10)/10}}var R0=(e,t)=>e.travelMin===t.travelMin&&e.travelMax===t.travelMax&&e.rollMaxDeg===t.rollMaxDeg&&e.rollAtLimitDeg===t.rollAtLimitDeg;var en=Math.PI/180,wO=9.81,Mc=.1,v0=20,WA=6,qA=50;function jA(e,t,r){let n=e(0),o=0;for(let f=t;f<=r+1e-9;f+=t){let p=e(f);if(p>n)n=p,o=f;else if(f>o+3*t)break}let a=Math.max(0,o-t),s=Math.min(r,o+t),i=.6180339887498949,c=s-i*(s-a),l=a+i*(s-a),u=e(c),m=e(l);for(let f=0;f<14;f++)u>m?(s=l,l=c,m=u,c=s-i*(s-a),u=e(c)):(a=c,c=l,u=m,l=a+i*(s-a),m=e(l));return u>n?u>=m?{force:u,at:c}:{force:m,at:l}:m>n?{force:m,at:l}:{force:n,at:o}}function k0(e,t,r,n,o){let a=o*en;if(t==="side")return jA(i=>r*e.Fy(r*i*en,n,a),1,45);let s=t==="drive"?1:-1;return jA(i=>s*e.Fx(s*i,n,a),.02,.6)}function op(e){let t=e?Ql(e)?.gamma:void 0,r=[t?.min,t?.max].filter(o=>o!==void 0&&Number.isFinite(o));if(!r.length)return{lo:-WA,hi:WA,stated:!1};let n=Math.max(...r.map(Math.abs))/en;return{lo:-n,hi:n,stated:!0}}function CO(e,t,r){if(!(r>t))return t;let n=Math.max(2,Math.ceil(r-t)+1),o=(r-t)/(n-1),a=t,s=-1/0;for(let h=0;h<n;h++){let b=t+h*o,g=e(b);g>s&&(s=g,a=b)}let i=Math.max(t,a-o),c=Math.min(r,a+o),l=.6180339887498949,u=c-l*(c-i),m=i+l*(c-i),f=e(u),p=e(m);for(let h=0;h<12;h++)f>p?(c=m,m=u,p=f,u=c-l*(c-i),f=e(u)):(i=u,u=m,f=p,m=i+l*(c-i),p=e(m));let d=f>=p?{g:u,v:f}:{g:m,v:p};return d.v>s?d.g:a}var UA=250,XA=new WeakMap;function TO(e,t,r,n,o,a,s){let i=XA.get(e);i||XA.set(e,i=new Map);let c=`${t}|${n}|${o}|${s.lo}|${s.hi}`,l=i.get(c);l||i.set(c,l=new Map);let u=d=>{let h=l.get(d);if(h===void 0){let b=Math.max(50,d*UA);h=CO(g=>k0(r,n,o,b,g).force,s.lo,s.hi),l.set(d,h)}return h},m=Math.max(0,a)/UA,f=Math.floor(m),p=m-f;return p<1e-9?u(f):u(f)*(1-p)+u(f+1)*p}function Ja(e,t){return t==="front"?e.tireModel:e.tireModelRear??e.tireModel}var PO=new WeakMap,LO=new WeakMap,DO=new WeakMap,M0=(e,t,r)=>{let n=e.get(t);return n===void 0&&e.set(t,n=r()),n};function ap(e,t){let r=Ja(e,t);return r?M0(PO,r,()=>Ws(r))?null:"This tyre\u2019s side force does not change with camber, so it wants no camber.":"The car runs the built-in simple tyre, which has no camber term."}function S0(e,t){let r=Ja(e,t);return r?M0(DO,r,()=>Zl(r).none)?"This tyre file has no drive or brake grip.":M0(LO,r,()=>{let n=Pe(r),o=r.kind==="magic"?r.fnomin:r.nominalLoad,a=n.Fx(.1,o,0),s=n.Fx(.1,o,3*en);return Number.isFinite(a)&&Number.isFinite(s)&&Math.abs(s-a)>1})?null:"This tyre\u2019s drive and brake grip does not change with camber.":"The car runs the built-in simple tyre, which has no camber term."}function wo(e,t){return e==="side"||e==="ackermann"?Math.abs(t.ayG)>=Mc?e==="ackermann"&&!(QA(t)<=v0)?`is a corner wider than ${v0} m`:null:"does not corner":(e==="drive"?t.axG:-t.axG)>=Mc?null:e==="drive"?"does not drive":"does not brake"}var EO=e=>e.axG>=Mc?"drive":e.axG<=-Mc?"brake":null;function QA(e){let t=e.speedKmh/3.6,r=Math.abs(e.ayG)*wO;return r>1e-9?t*t/r:1/0}var np=(e,t)=>`${e==="front"?"F":"R"}${t}`,IO=e=>e==="L"?"R":"L",_O=(e,t,r)=>Math.min(r,Math.max(t,e));function A0({ev:e,params:t,input:r,state:n,pose:o}){let a=`${Q(t,"grip_scale")}|${Q(t,"stiffness_scale")}`,s=QA(n),i=r.wheelbase*(1-r.frontMassFrac)/1e3,c=r.wheelbase*r.frontMassFrac/1e3,l=r.wheelbase/1e3,u=k=>(k==="front"?r.trackFront:r.trackRear)/2e3,m=(k,v,x,M,F)=>{let w=ye(e,k),T=Ja(t,k),P=Math.max(0,o.loads[v]),A=o.camber[v],S=_O(A,F.lo,F.hi),C=k0(w,x,M,P,S),L=P<qA,D=T&&!L?TO(T,a,w,x,M,P,F):S,I=L?C.force:k0(w,x,M,P,D).force,O=.05;return{corner:v,Fz:P,lifted:L,camber:A,read:S,outside:S!==A,wants:D,atEdge:!L&&(D-F.lo<O||F.hi-D<O),peak:C.force,slip:C.at,best:I}},f=(k,v,x)=>{let M=v[0].best+v[1].best,F=v[0].peak+v[1].peak;return{kind:k,wheels:v,lossCamber:M>0?Math.max(0,1-F/M):NaN,range:x}},p=new Map,d=k=>{if(p.has(k))return p.get(k)??null;let v=null;if(!wo("side",n)){let x=op(Ja(t,k));v=[m(k,np(k,o.outer),"side",1,x),m(k,np(k,IO(o.outer)),"side",-1,x)]}return p.set(k,v),v},h=new Map,b=new Map,g=new Map,y=(k,v,x)=>{let M=k==="front"?i:-c,F=(v?1:-1)*u(k),w=x*en;return Math.atan2(M+s*Math.sin(w),s*Math.cos(w)-F)/en},R=k=>(n.ayG<0?-1:1)*o.steer[k];return{side(k){if(h.has(k))return h.get(k)??null;let v=ap(t,k)?null:d(k),x=v?f("side",v,op(Ja(t,k))):null;return h.set(k,x),x},long(k){if(b.has(k))return b.get(k)??null;let v=EO(n),x=null;if(v&&!S0(t,k)){let M=op(Ja(t,k));x=f(v,[m(k,np(k,"L"),v,1,M),m(k,np(k,"R"),v,1,M)],M)}return b.set(k,x),x},toeLoss(k){let v=g.get(k);if(v!==void 0)return v;let x=d(k),M=NaN;if(x&&x[0].peak+x[1].peak>0){let F=ye(e,k),[w,T]=x,P=[{g:w,dt:1,inner:!1,steer:R(w.corner)},{g:T,dt:-1,inner:!0,steer:R(T.corner)}],A=I=>P.reduce((O,N)=>{let z=N.steer-y(k,N.inner,I);return O+N.dt*F.Fy(N.dt*z*en,N.g.Fz,N.g.read*en)},0),S=P.map(I=>I.steer-I.g.slip-y(k,I.inner,0)),C=Math.min(...S)-2,L=Math.max(...S)+2,D=NO(A,C,L,.25);M=Math.max(0,1-D/(w.peak+T.peak))}return g.set(k,M),M},ackermann(){if(wo("ackermann",n))return NaN;let k=d("front");if(!k||k[0].lifted||k[1].lifted)return NaN;let[v,x]=k,M=Math.sqrt(Math.max(s*s-c*c,1e-6)),F=u("front"),w=(Math.atan(l/(M-F))-Math.atan(l/(M+F)))/en;if(!(w>.001))return NaN;let T=R(x.corner)-R(v.corner),P=w+(x.slip-v.slip);return 100*(T-P)/w}}}function NO(e,t,r,n){let o=-1/0,a=t;for(let p=t;p<=r+1e-9;p+=n){let d=e(p);d>o&&(o=d,a=p)}let s=a-n,i=a+n,c=.6180339887498949,l=i-c*(i-s),u=s+c*(i-s),m=e(l),f=e(u);for(let p=0;p<14;p++)m>f?(i=u,u=l,f=m,l=i-c*(i-s),m=e(l)):(s=l,l=u,m=f,u=s+c*(i-s),f=e(u));return Math.max(o,m,f)}var OO=9.81,ZA=Math.PI/180,Sc={speed:20,ayG:1.2};function F0(e,t={}){let r=t.operating??Sc,n=t.assemble,o,a,s,i=new Map,c=new Map,l=new Map,u=new Map,m=new Map,f=v=>({speed:v?.speed!==void 0&&Number.isFinite(v.speed)&&v.speed>0?v.speed:r.speed,ayG:v?.ayG!==void 0&&Number.isFinite(v.ayG)?v.ayG:r.ayG}),p=()=>{if(o!==void 0)return o;if(!n)return o=null;try{o=n(e)}catch{o=null}return o},d=()=>{if(a!==void 0)return a;try{a=gr(e.params)}catch{a=null}return a},h=v=>{let x=f(v),M=`${x.speed}|${x.ayG}`,F=i.get(M);if(F!==void 0)return F;let w=d();if(!w)return i.set(M,null),null;let T={cornerStiffness:P=>w.corneringStiffness(P),ayG:x.ayG,speed:x.speed,fyAxle:(P,A)=>2*w.Fy(P,A/2),tire:w};return i.set(M,T),T},b=()=>{if(s!==void 0)return s;let v=p(),x=d();if(!v||!x)return s=null;try{s=to(x,v.massTotal*OO*1.2)}catch{s=null}return s},g=v=>{let x=f(v).speed,M=`${x}`,F=c.get(M);if(F!==void 0)return F;let w=p(),T=d(),P=null;if(w&&T)try{P=yb(w,T,x,{steering:!1})}catch{P=null}return c.set(M,P),P},y=v=>{let x=`${v.speedKmh}|${v.ayG}|${v.axG}`,M=m.get(x);if(M!==void 0)return M;let F=null,w=p();try{let T=w?.kinFront,P=w?.kinRear;if(w&&T&&P){let A=y0(v,w.wheelbase),S=v.speedKmh/3.6,C=hn(w,T,P,S)(v.ayG,v.axG,0,A),L={FL:C.FL.travel,FR:C.FR.travel},D=no(w,A*ZA,L),I=A?D.camber:null,O={},N={};for(let E of["FL","FR","RL","RR"]){let _=E[1]==="R"?C[E].camberRoad:0-C[E].camberRoad;O[E]=_+(I?.[E]??0),N[E]=D.steer[E]/ZA+(E[1]==="R"?1:-1)*C[E].bumpToe}let z=Ce(w,v.ayG,v.axG,S,0,A,L,C.steeringJacking);F={corners:C,rollDeg:C.FL.camberRoad-C.FL.camber,steerDeg:A,camber:O,outer:YA(v),loads:z,steer:N}}}catch{F=null}return m.set(x,F),F},R=new Map;return{operating:r,dynAvailable:!!n,poseAt:y,tyreAt:v=>{let x=`${v.speedKmh}|${v.ayG}|${v.axG}`,M=R.get(x);if(M!==void 0)return M;let F=y(v),w=p(),T=d(),P=F&&w&&T?A0({ev:T,params:e.params,input:w,state:v,pose:F}):null;return R.set(x,P),P},operatingAt:f,dynInput:p,tyre:d,dynCtx:h,grip:b,ymd:g,ymdLimit:v=>{let x=`${f(v).speed}`,M=l.get(x);if(M!==void 0)return M;let F=g(v),w=F?Xb(F):null;return l.set(x,w),w},reserves:(v,x)=>{let M=f(x),F=`${v}|${M.speed}|${M.ayG}`,w=u.get(F);if(w!==void 0)return w;let T=p(),P=h(x),A=null;if(T&&P)try{A=zi(T,P,v,b()??void 0)}catch{A=null}return u.set(F,A),A}}}var JA=["widthLeft","widthRight","bank","mu"];function Ac(e){let t=e.x.length,r=new Array(t).fill(0);for(let n=1;n<t;n++)r[n]=r[n-1]+Math.hypot(e.x[n]-e.x[n-1],e.y[n]-e.y[n-1]);return r}function w0(e){let t=Ac(e),r=e.x.length;return r===0?0:e.closed===!1||r<2?t[r-1]:t[r-1]+Math.hypot(e.x[0]-e.x[r-1],e.y[0]-e.y[r-1])}function ip(e,t,r,n={}){let o=t.length,a=l=>{let u=n[l];return u&&u.length===o?u.slice():new Array(o).fill(r[l])},s={widthLeft:a("widthLeft"),widthRight:a("widthRight"),bank:a("bank"),mu:a("mu")};if(!e.length)return s;let i=[...e].sort((l,u)=>l.from-u.from),c=o?t[o-1]:0;for(let l of i){if(!(l.to>l.from))continue;let u=Math.max(0,l.ramp??0),m=l.to>=c-1e-9;for(let f of JA){let p=l[f];if(p===void 0)continue;let d=s[f],h=r[f];for(let b=0;b<o&&t[b]<l.from;b++)h=d[b];for(let b=0;b<o;b++){let g=t[b];if(g<l.from||g>=l.to&&!(m&&g>=c-1e-9))continue;let y=g-l.from;d[b]=u>0&&y<u?h+(p-h)*(y/u):p}}}return s}function cp(e,t,r){if(!t.length)return e;let n=Ac(e),o=n.length,a={widthLeft:sp(e.widthLeft,r.widthLeft),widthRight:sp(e.widthRight,r.widthRight),bank:sp(e.bank,r.bank),mu:sp(e.mu,r.mu)},s={};for(let c of JA){let l=e[c];Array.isArray(l)&&l.length===o&&(s[c]=l)}let i=ip(t,n,a,s);return{...e,...i}}function sp(e,t){return typeof e=="number"?e:t}var rF=1,eF=4,up=Math.PI/180,C0=e=>e===null||!Number.isFinite(e)||e===0?0:1/e;function T0(e){return e.kind==="arc"?Math.abs(e.radius)*Math.abs(e.angle)*up:e.length}function lp(e,t){return e.kind==="straight"?0:e.kind==="arc"?C0(e.radius):t}function tF(e){return e.kind==="straight"?0:e.kind==="arc"?C0(e.radius):C0(e.endRadius)}var Fc=(e,t,r,n,o)=>e+t*o+(n>0?(r-t)*o*o/(2*n):0);function wc(e,t={}){let r=Math.max(.05,t.spacing??rF),n=t.closed!==!1,o=t.start??{x:0,y:0,heading:0},a=t.base??{widthLeft:1.5,widthRight:1.5,bank:0,mu:1},s=[],i=[],c=[],l=[],u=e.reduce((A,S)=>A+T0(S),0),m=Math.max(n?3:2,Math.round(u/r)),f=u>0?u/m:r,p=o.x,d=o.y,h=o.heading*up,b=e.length?lp(e[0],0):0,g=0,y=f,R=(A,S,C)=>{s.push(A),i.push(S),c.push(C)};R(p,d,0);let k=(A,S,C,L,D)=>{let I=D-L;if(I<=0)return;if(Math.abs(S-A)<1e-12){let N=Fc(h,A,A,C,L);if(Math.abs(A)<1e-12)p+=I*Math.cos(N),d+=I*Math.sin(N);else{let z=N+A*I;p+=(Math.sin(z)-Math.sin(N))/A,d+=-(Math.cos(z)-Math.cos(N))/A}return}let O=I/eF;for(let N=0;N<eF;N++){let z=L+N*O,E=Fc(h,A,S,C,z),_=Fc(h,A,S,C,z+O/2),B=Fc(h,A,S,C,z+O);p+=O/6*(Math.cos(E)+4*Math.cos(_)+Math.cos(B)),d+=O/6*(Math.sin(E)+4*Math.sin(_)+Math.sin(B))}};for(let A of e){let S=T0(A),C=lp(A,b),L=tF(A);if(l.push({from:g,to:g+S,...A.widthLeft!==void 0?{widthLeft:A.widthLeft}:{},...A.widthRight!==void 0?{widthRight:A.widthRight}:{},...A.bank!==void 0?{bank:A.bank}:{},...A.mu!==void 0?{mu:A.mu}:{},...A.ramp!==void 0?{ramp:A.ramp}:{}}),S<=0){b=L;continue}let D=0;for(;y<=g+S+1e-9;){let I=Math.min(S,y-g);k(C,L,S,D,I),D=I,R(p,d,g+I),y+=f}k(C,L,S,D,S),h=Fc(h,C,L,S,S),b=L,g+=S}let v=s.length>1?Math.hypot(s[0]-s[s.length-1],i[0]-i[i.length-1]):0,x=g;n&&s.length>1&&(s.pop(),i.pop(),c.pop());let M=e.length?lp(e[0],b):0,F={gap:v,headingError:VO((h-o.heading*up)/up),curvatureError:b-M},w=[];for(let A=0;A<e.length;A++){let S=tF(e[A]),C=A+1<e.length?e[A+1]:n?e[0]:null;if(!C)continue;let L=lp(C,S);w.push({index:A,before:S,after:L,jump:Math.abs(L-S)})}let T=ip(l,c,a);return{asset:{name:t.name??"Track",x:s,y:i,fit:"interpolate",...n?{}:{closed:!1},...T},sections:l,joints:w,closure:F,length:x}}function VO(e){let t=e%360;return t>180&&(t-=360),t<-180&&(t+=360),t}var BO={halfWidthM:1.5,spacingM:.5};function Cc(e){switch(e.kind){case"skidpad":return`${e.radiusM.toFixed(2)} m constant-radius circle`;case"acceleration":return`${e.distanceM.toFixed(0)} m straight from rest`;case"slalom":return`${e.gates} gates at ${e.pitchM.toFixed(1)} m, \xB1${e.offsetM.toFixed(2)} m`;case"curves":{let t=e.segments.filter(r=>r.kind==="arc").length;return`${t} ${t===1?"curve":"curves"} over ${oF(e).toFixed(0)} m`}}}function oF(e){switch(e.kind){case"skidpad":return 2*Math.PI*e.radiusM;case"acceleration":return e.distanceM;case"slalom":return e.leadInM+Math.max(1,e.gates)*e.pitchM;case"curves":return e.segments.reduce((t,r)=>t+(r.kind==="arc"?Math.abs(r.angle)*Math.PI*Math.abs(r.radius)/180:r.length),0)}}var aF=e=>e.kind==="skidpad"||e.kind==="curves"&&e.closed===!0,sF=e=>e.kind==="acceleration",iF=1.5,cF=3;function $O(e,t){let r=e.offsetM,n=e.pitchM,o=Math.max(1,e.gates)*n,a=Math.max(0,e.leadInM),s=iF*n,i=h=>{let b=Math.min(1,Math.max(0,h));return b*b*b*(b*(b*6-15)+10)},c=h=>Math.min(i(h/s),i((o-h)/s)),l=r*(Math.PI/n)**2,u=l>0?Math.max(.05,Math.min(t.spacingM,1/l*(cF*Math.PI/180))):t.spacingM,m=[],f=[],p=Math.max(1,Math.round(a/u));for(let h=0;h<p;h++)m.push(-a+a*h/p),f.push(0);let d=Math.max(8,Math.round(o/u));for(let h=0;h<=d;h++){let b=o*h/d;m.push(b),f.push(r*c(b)*Math.sin(Math.PI*b/n))}return{name:Cc(e),x:m,y:f,closed:!1,widthLeft:t.halfWidthM,widthRight:t.halfWidthM,fit:"interpolate"}}function GO(e){switch(e.kind){case"skidpad":return[{kind:"arc",radius:e.radiusM,angle:360}];case"acceleration":return[{kind:"straight",length:e.distanceM}];case"curves":return e.segments;case"slalom":return null}}function P0(e,t={}){let r={...BO,...t},n=sF(e),o=GO(e);if(!o){let u=$O(e,r);return{asset:u,peakCurvature:nF(u),worstJoint:0,standingStart:n}}let a=aF(e),s=o.reduce((u,m)=>m.kind==="arc"?Math.min(u,Math.abs(m.radius)):u,1/0),i=Number.isFinite(s)?Math.max(.05,Math.min(r.spacingM,s*(cF*Math.PI/180))):r.spacingM,c=wc(o,{name:Cc(e),spacing:i,closed:a,base:{widthLeft:r.halfWidthM,widthRight:r.halfWidthM,bank:0,mu:1}}),l=a?c.joints:c.joints.filter(u=>u.index<o.length-1);return{asset:c.asset,peakCurvature:nF(c.asset),worstJoint:l.reduce((u,m)=>Math.max(u,m.jump),0),standingStart:n}}function nF(e){try{return Math.max(...lt(e).curvature.map(Math.abs))}catch{return NaN}}var pp={courses:[{id:"c1",course:{kind:"manoeuvre",spec:{kind:"skidpad",radiusM:8.375}}}],ggvMode:"twoTrack"};function L0(e){return e.course.kind==="project"?"the project\u2019s track":e.course.kind==="track"?e.course.name:Cc(e.course.spec)}var lF=new WeakMap,mp=new Map;function uF(e,t,r){if(e.kind==="project"||e.kind==="track"){let i=(e.kind==="project"?t.projectTrack?.():t.libraryTrack?.(e.trackId))??null;return i?{asset:i.asset,standingStart:i.standingStart,numerics:i.numerics}:null}let n=JSON.stringify(e.spec),o=mp.get(n);if(o)return{...o,numerics:r};let a=P0(e.spec),s={asset:a.asset,standingStart:a.standingStart};return mp.size>64&&mp.clear(),mp.set(n,s),{...s,numerics:r}}function D0(e,t,r={}){let n=r.lap??pp,o=r.simParams,a=r.numerics??{},s=n.courses.length?n.courses:pp.courses,i,c,l,u=new Map,m=new Map,f=new Map,p=new Map,d=k=>(k?.courseId?s.find(v=>v.id===k.courseId):void 0)??s[0],h=()=>{if(i!==void 0)return i;if(!o)return i=null;try{i={...o(e),ggvMode:n.ggvMode}}catch{i=null}return i},b=k=>{let v=d(k);if(!v)return null;let x=m.get(v.id);if(x!==void 0)return x;let M=uF(v.course,r,a),F=null;if(M)try{let w=JSON.stringify(M.numerics),T=lF.get(M.asset);T||(T=new Map,lF.set(M.asset,T));let P=T.get(w);P||(P=lt(M.asset,M.numerics),T.set(w,P)),F={id:v.id,track:P,standingStart:M.standingStart,numerics:M.numerics,name:M.asset.name}}catch{F=null}return m.set(v.id,F),F},g=()=>{if(c!==void 0)return c;let k=h();if(!k)return c=null;try{l=Dt(k),c=yr(l,!1,n.ggvMode)}catch{c=null}return c},y=k=>{let v=b(k);if(!v)return null;let x=f.get(v.id);if(x!==void 0)return x;let M=g(),F=null;if(M)try{let w=l?fo(l,M,[v.track],v.numerics,n.ggvMode,u):void 0,T=l?An(l,M.rows):void 0;F=At(M,v.track,v.numerics,{standingStart:v.standingStart,...w?{load:w}:{},...T?{shifts:T}:{}})}catch{F=null}return f.set(v.id,F),F};return{lapSettings:n,get lapAvailable(){return!!o&&s.some(k=>!!uF(k.course,r,a))},lapParams:h,courses:()=>s,course:b,ggv:g,lap:y,lapReserve:k=>{let v=b(k);if(!v)return null;let x=p.get(v.id);if(x!==void 0)return x;let M=y(k),F=t.dynInput(),w=t.tyre(),T=null;if(M&&F&&w)try{let P=h();T=gm(F,w,{v:M.v,ax:M.ax,ay:M.ay,ds:v.track.ds,axDrag:za(g()?.rows,M.v),...M.axScrub?{axScrub:M.axScrub}:{},axGrade:Sn(v.track.gradient,M.v.length),bank:v.track.bank,...M.loadFactor?{loadFactor:M.loadFactor}:{}},P?{driven:Oh(P)}:{})}catch{T=null}return p.set(v.id,T),T}}}var mF=180/Math.PI,E0={rise:0,sinPitch:0,sinRoll:0};function pF(e){let t=e.kc;return t?dF(e.vehicle,r=>t.ground0[r]):E0}function dF(e,t){let r=e.config,n=un(r),o=0,a=0,s=0,i=0,c=0,l=0,u=0,m=0,f=0;for(let g of ir){let y=Ze(g,r),R=y.axleX-n,k=y.sideSign*Gt(e,y.isFront)/2,v=t(g);if(!Number.isFinite(v))return E0;o++,a+=R,s+=k,i+=v,c+=R*R,l+=k*k,u+=R*k,m+=R*v,f+=k*v}let p=o*(c*l-u*u)-a*(a*l-u*s)+s*(a*u-c*s);if(!(Math.abs(p)>1e-9))return{rise:i/o,sinPitch:0,sinRoll:0};let d=(i*(c*l-u*u)-a*(m*l-u*f)+s*(m*u-c*f))/p,h=(o*(m*l-u*f)-i*(a*l-u*s)+s*(a*f-m*s))/p,b=(o*(c*f-m*u)-a*(a*f-m*s)+i*(a*u-c*s))/p;return{rise:d,sinPitch:h,sinRoll:-b}}function Tc(e,t){let r=e.kc,n=dF(e.vehicle,o=>(r?r.ground0[o]:0)+t[o]);return q([-n.sinPitch,n.sinRoll,1])}function I0(e,t,r,n){let o=q(Tr(e,Ze(t,r)));return-Math.asin(Math.max(-1,Math.min(1,X(o,n))))*mF}function dp(e,t,r,n,o){let a=q(Tr(n,Ze(t,r))),s=q([1-a[0]*a[0],-a[0]*a[1],-a[0]*a[2]]),i=ae(a,s),c=p=>[X(p,s),X(p,i),X(p,a)],l=p=>ee(ee(U(s,p[0]),U(i,p[1])),U(a,p[2])),u=e.points,m=c(u.spinAxis),f=Ms({uprightUpper:c(u.uprightUpper),uprightLower:c(u.uprightLower),wheelCenter:c(u.wheelCenter),spinAxis:m,tieOuter:c(u.tieOuter),loadedRadius:o.loadedRadius,patchShift:o.patchShift&&KO(o.patchShift,e.metrics.toe/mF,Math.atan2(m[0],m[1]))});return{caster:f.caster,kpi:f.kpi,scrubRadius:f.scrubRadius,mechanicalTrail:f.mechanicalTrail,scrubAtWheel:f.scrubAtWheel,trailAtWheel:f.trailAtWheel,kingpinOffset:f.kingpinOffset,casterOffset:f.casterOffset,kingpinGround:l(f.kingpinGround),contactPatch:l(f.contactPatch),elbow:l([f.contactPatch[0],f.kingpinGround[1],f.kingpinGround[2]]),kingpinAtHub:l(f.kingpinAtHub)}}function KO(e,t,r){if(r===t)return e;let n=e.x*Math.cos(t)-e.y*Math.sin(t),o=e.x*Math.sin(t)+e.y*Math.cos(t);return{x:n*Math.cos(r)+o*Math.sin(r),y:o*Math.cos(r)-n*Math.sin(r)}}function fp(e,t){let r=pF(t);if(r===E0)return e;let n=o=>Math.max(-1,Math.min(1,o));return{...e,heave:e.heave-r.rise,pitch:Math.asin(n(Math.sin(e.pitch)-r.sinPitch)),roll:Math.asin(n(Math.sin(e.roll)-r.sinRoll))}}function es(e,t,r){let n=fp({heave:0,pitch:0,roll:0,steer:0},r);return e-qd(n,[t,0,0],un(r.vehicle.config))}var HO=180/Math.PI;function _0(e,t){return!e.valid||!e.ic?!1:Math.hypot(e.ic[0]-e.cp[0],e.ic[1]-e.cp[1])<=t}function hp(e,t,r){let n=Ze(t,e.vehicle.config),o=vt(e,r),a=Bu(e,t,o[t]),s=a.at("uprightUpper"),i=a.at("uprightLower"),c=a.at("contactPatch"),l=a.at("wheelCenter"),u=S=>{let C=a.velocity(S);return[C[0],C[2]]},m=u(c),f=u(l),p=[c[0],c[2]],d=[l[0],l[2]];if(!a.solved)return{ic:null,line:null,cp:p,wc:d,road:[1,0],swingArmAngleDeg:NaN,tanTheta:NaN,tanThetaHub:NaN,valid:!1,unsolved:!0,sinAngle:0};let h=Tc(e,{FL:o.FL.ground,FR:o.FR.ground,RL:o.RL.ground,RR:o.RR.ground}),b=Math.hypot(h[0],h[2]),g=[h[0]/b,h[2]/b],y=[g[1],-g[0]],R=S=>{let C=S[0]*g[0]+S[1]*g[1];return Math.abs(C)>1e-9?-(S[0]*y[0]+S[1]*y[1])/C:0},k=a.omega[1],v=Math.hypot(m[0],m[1]),x=Math.abs(k)*1e9>v?[p[0]+m[1]/k,p[1]-m[0]/k]:null,F=x?(S=>{let C=[s[0]-S[0],s[2]-S[1]],L=[i[0]-S[0],i[2]-S[1]];return Math.abs(C[0]*L[1]-C[1]*L[0])/(Math.hypot(...C)*Math.hypot(...L))})(x):0;if(!(Math.abs(m[0]*g[0]+m[1]*g[1])>1e-9))return{ic:x,line:null,cp:p,wc:d,road:y,swingArmAngleDeg:0,tanTheta:0,tanThetaHub:0,valid:!1,sinAngle:F};let w=[m[1]/v,-m[0]/v],T=x?[x[0]-p[0],x[1]-p[1]]:[n.isFront?-1:1,0],P=w[0]*T[0]+w[1]*T[1]<0?[-w[0],-w[1]]:w,A=R(m);return{ic:x,line:P,cp:p,wc:d,road:y,swingArmAngleDeg:Math.atan(A)*HO,tanTheta:A,tanThetaHub:R(f),valid:!0,sinAngle:F}}function fF(e,t,r,n){let o=r/Math.max(1e-6,n.cgHeight),a=t==="front",s=a?n.drive.front:1-n.drive.front,i=a?n.brakeBalanceFront:1-n.brakeBalanceFront,c=(a?n.drive.inboard.front:n.drive.inboard.rear)?e.tanThetaHub:e.tanTheta,l=(a?n.brakeInboard?.front:n.brakeInboard?.rear)?e.tanThetaHub:e.tanTheta,u=a?-1:1;return{brake:u*100*l*o*i,drive:u*100*c*o*s}}var YO=180/Math.PI,WO=Math.PI/180,N0=.5,bp=2,O0=.25,jO={heave:0,pitch:0,roll:0,steer:0},UO={FL:"FR",FR:"FL",RL:"RR",RR:"RL"},gp=e=>e.ok?e.state:{...e.nearest,converged:!1};function V0(e,t,r){return t.state?t.solved===!1?{...t.state,converged:!1}:t.state:gp(ge(e,t.travel,t.steer,void 0,r))}var hF=new WeakMap;function bF(e,t){let r=e.ctx[t],n=_e(e.vehicle,t).config.loadedRadius,o=Kt(n,e.kc,t),a=hF.get(r);a||(a=new Map,hF.set(r,a));let s=a.get(o);if(!s){let i=mn(t,e.vehicle.config,jO,e.vehicle);s=gp(ge(r,i.travel,i.steer,void 0,o===n?void 0:{loadedRadius:o})),a.set(o,s)}return s}var Mr=(e,t)=>!e||!e.lo.converged||!e.hi.converged?NaN:(t(e.hi)-t(e.lo))/(2*e.step),gF=(e,t,r)=>{if(!e||!e.lo.converged||!e.hi.converged)return NaN;let n=r(e.hi)-r(e.lo);return Math.abs(n)<1e-9?NaN:(t(e.hi)-t(e.lo))/n};function xF(e,t,r,n,o){let a=e.vehicle.config,s=Jo(r),i=_e(e.vehicle,r),c=Ze(r,a),l=e.ctx[r],u=vt(e,t),m=u[r],f={travel:m.travel,steer:m.steer},p=m.rigid?void 0:{loadedRadius:m.loadedRadius},d=V0(l,m,p),h=bF(e,r),b={lo:gp(ge(l,f.travel-N0,f.steer,void 0,p)),hi:gp(ge(l,f.travel+N0,f.steer,void 0,p)),step:N0},g=c.isFront?{lo:Ie(l,d.beta,f.steer-bp,void 0,p),hi:Ie(l,d.beta,f.steer+bp,void 0,p),step:bp}:null,y=Y=>{let j=vt(e,{...t,roll:t.roll+Y*WO})[r];return V0(l,j,j.rigid?void 0:{loadedRadius:j.loadedRadius})},R={lo:y(-O0),hi:y(O0),step:O0},k=qO(e,t,r,c.isFront,u,g),v=Tt(d.points.contactPatch,c),x=Tt(h.points.contactPatch,c),M=Math.abs(v[1])-Math.abs(x[1]),F=UO[r],w=u[F],T=V0(e.ctx[F],w,w.rigid?void 0:{loadedRadius:w.loadedRadius}),P=T.converged?M+Math.abs(T.points.contactPatch[1])-Math.abs(bF(e,F).points.contactPatch[1]):NaN,A=o??hr(e,t,s),S=$u(A,Rt(i)),C=S?null:Gk(A),L=c.sideSign>0?A.icRight:A.icLeft,D=L?Math.hypot(L[0]-v[1],L[1]-v[2]):1/0,I=hp(e,r,t),O=I.ic?Math.hypot(I.ic[0]-I.cp[0],I.ic[1]-I.cp[1]):1/0,N=fF(I,s,a.wheelbase,n),z=-Mr(b,Y=>Y.points.damperLength),E=i.config.springRate,_=Mr(R,Y=>Y.metrics.camber),B=Tc(e,{FL:u.FL.ground,FR:u.FR.ground,RL:u.RL.ground,RR:u.RR.ground}),V=e.kc?.loadCase,G=Y=>V?dp(Y,r,a,B,{loadedRadius:m.loadedRadius,patchShift:V.patchShift[r]}):Y.metrics,K=G(d);return{id:r,converged:d.converged,travel:d.travel,camber:d.metrics.camber,camberRoad:I0(d.points.spinAxis,r,a,B),toe:d.metrics.toe,caster:K.caster,kpi:K.kpi,scrubRadius:K.scrubRadius,mechanicalTrail:K.mechanicalTrail,scrubAtWheel:K.scrubAtWheel,trailAtWheel:K.trailAtWheel,kingpinOffset:K.kingpinOffset,casterOffset:K.casterOffset,steeringArm:d.metrics.steeringArm,camberGain:Mr(b,Y=>Y.metrics.camber),bumpSteer:Mr(b,Y=>Y.metrics.toe),trackScrubRate:Mr(b,Y=>Math.abs(Tt(Y.points.contactPatch,c)[1])),casterGain:Mr(b,Y=>G(Y).caster),kpiGain:Mr(b,Y=>G(Y).kpi),scrubGain:Mr(b,Y=>G(Y).scrubRadius),trailGain:Mr(b,Y=>G(Y).mechanicalTrail),...c.isFront?{camberPerSteer:gF(g,Y=>Y.metrics.camber,Y=>Y.metrics.toe),steerJacking:-gF(g,Y=>Y.points.contactPatch[2],Y=>Y.metrics.toe),...k!==void 0?{steerLoad:k}:{}}:{},rollCamber:_,camberRecovery:-100*c.sideSign*_,rollSteer:c.sideSign*Mr(R,Y=>Y.metrics.toe),halfTrackChange:M,trackChange:P,longitudinal:v[0]-x[0],rollCentreHeight:C?C.heightAboveGround:A.heightAboveGround,rollCentreHeightChassis:(C?C.height:A.height)-es(0,c.axleX,e),rollCentreLateral:A.lateralAlongGround,rollCentreValid:A.valid,rollCentreUsable:S,rollCentreHeightUsable:S||C!==null,rollCentreSinAngle:A.sinAngle,fvsaLength:D,svsaLength:O,swingArmAngle:I.swingArmAngleDeg,svsaUsable:_0(I,a.wheelbase),svsaSinAngle:I.sinAngle,...s==="front"?{antiDive:N.brake,antiLift:N.drive}:{antiSquat:N.drive,antiLift:N.brake},decoupled:i.config.actuation==="decoupled",mcpherson:i.config.layout==="mcpherson",springRate:E,motionRatio:z,wheelRate:E*z*z,damperLength:d.points.damperLength,damperTravel:h.points.damperLength-d.points.damperLength,...XO(i,h.points.damperLength,d.points.damperLength,e.kc?.curve[r].spring?.law),rockerAngle:i.config.actuation==="direct"?0:(d.points.rockerAngle-h.points.rockerAngle)*YO,groundDisplacement:m.rigid?d.travel:m.ground,tyreDeflection:m.tyreDeflection,wheelLoad:m.load,loadedRadiusAt:m.loadedRadius,rideRate:m.rideRate,wheelRateAtLoad:m.wheelRateAtLoad,lifted:m.lifted,clearance:m.clearance??0,tyreRigid:m.rigid}}function XO(e,t,r,n){if(e.config.actuation==="decoupled")return{};let o=n?{droop:n.droopStated?n.droop:null,bump:n.bump}:ta(t,e.config.coilover),a=t-r;return{...o.droop!==null?{damperToExtended:a-o.droop}:{},...o.bump!==null?{damperToClosed:o.bump-a}:{}}}function qO(e,t,r,n,o,a){if(!a||!n)return;let s=Cl(e,t,"front"),i=e.kc;if(!s||!i)return;let c=["FL","FR"],l=[0,0],u=[0,0],m={lo:[],hi:[]},f=0;for(let h=0;h<2;h++){let b=c[h],g=o[b],y=e.ctx[b],R=g.rigid?void 0:{loadedRadius:g.loadedRadius},x=(b==="FR"?1:-1)*(r==="FR"?1:-1)*bp,M=g.state?{q:[...g.state.pose.t,...g.state.pose.omega],phi:g.state.points.rockerAngle}:void 0,F=dt(ge(y,g.travel,g.steer-x,M,R)),w=dt(ge(y,g.travel,g.steer+x,M,R));if(!F||!w)return NaN;l[h]=w.points.contactPatch[2]-F.points.contactPatch[2],u[h]=Pr(i.curve[b],g.travel,w.points.damperLength)-Pr(i.curve[b],g.travel,F.points.damperLength),m.lo.push(F),m.hi.push(w),b===r&&(f=w.metrics.toe-F.metrics.toe)}let p=i.elements?.front;if(p){let h=[o.FL.travel,o.FR.travel],b=Is(p,h,[m.hi[0],m.hi[1]]),g=Is(p,h,[m.lo[0],m.lo[1]]);u[0]+=b[0]-g[0],u[1]+=b[1]-g[1]}return Math.abs(f)>1e-9?s([0,0],l,u)[r==="FL"?0:1]/f:NaN}function Pc(e,t,r,n,o){return xF(e,t,r==="front"?"FL":"RL",n,o)}function B0(e,t,r,n){let o=Pc(e,t,"front",r,n?.front),a=Pc(e,t,"rear",r,n?.rear);return{front:o,rear:a,wheelbaseChange:o.longitudinal-a.longitudinal}}function yp(e,t){let r=t.vehicle.config;return e.map(n=>{let o=n.axle==="front"?r.frontAxleX:r.frontAxleX-r.wheelbase,a=o+Math.min(n.xMin,n.xMax),s=o+Math.max(n.xMin,n.xMax),i=(a+s)/2;return{...n,min:[a,Math.min(n.yMin,n.yMax),es(Math.min(n.zMin,n.zMax),i,t)],max:[s,Math.max(n.yMin,n.yMax),es(Math.max(n.zMin,n.zMax),i,t)]}})}var Co=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],Wt=(e,t)=>[e[0]+t[0],e[1]+t[1],e[2]+t[2]],ot=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],er=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],Lc=e=>Math.sqrt(er(e,e));function QO(e,t){return{min:e,max:t,support:r=>[r[0]>=0?t[0]:e[0],r[1]>=0?t[1]:e[1],r[2]>=0?t[2]:e[2]]}}function ZO(e,t){return{min:[Math.min(e[0],t[0]),Math.min(e[1],t[1]),Math.min(e[2],t[2])],max:[Math.max(e[0],t[0]),Math.max(e[1],t[1]),Math.max(e[2],t[2])],support:r=>er(r,e)>=er(r,t)?e:t,samples:()=>Array.from({length:41},(r,n)=>Wt(e,ot(Co(t,e),n/40)))}}function JO(e,t,r,n){let o=ot(t,1/(Lc(t)||1)),a=n/2,s=o.map(i=>r*Math.sqrt(Math.max(0,1-i*i))+a*Math.abs(i));return{min:Co(e,s),max:Wt(e,s),support:i=>{let c=er(i,o),l=Co(i,ot(o,c)),u=Lc(l),m=u>1e-12?ot(l,r/u):[0,0,0];return Wt(Wt(e,ot(o,c>=0?a:-a)),m)},samples:()=>{let i=Math.abs(o[0])<.9?[1,0,0]:[0,1,0],c=Co(i,ot(o,er(i,o))),l=ot(c,1/Lc(c)),u=[o[1]*l[2]-o[2]*l[1],o[2]*l[0]-o[0]*l[2],o[0]*l[1]-o[1]*l[0]],m=[];for(let f of[-1,-.5,0,.5,1]){let p=Wt(e,ot(o,f*a));m.push(p);let d=Math.abs(f)===1?[.5,1]:[1];for(let h of d)for(let b=0;b<72;b++){let g=b/72*2*Math.PI;m.push(Wt(p,Wt(ot(l,h*r*Math.cos(g)),ot(u,h*r*Math.sin(g)))))}}return m}}}function eV(e){let t=e[0],r=e.slice(1).map(c=>Co(c,t)),n=r.length;if(n===0)return{v:t,w:[1]};let o=r.map(c=>r.map(l=>er(c,l))),a=r.map(c=>-er(c,t));for(let c=0;c<n;c++){let l=c;for(let u=c+1;u<n;u++)Math.abs(o[u][c])>Math.abs(o[l][c])&&(l=u);if(Math.abs(o[l][c])<1e-12)return null;[o[c],o[l]]=[o[l],o[c]],[a[c],a[l]]=[a[l],a[c]];for(let u=0;u<n;u++){if(u===c)continue;let m=o[u][c]/o[c][c];for(let f=c;f<n;f++)o[u][f]-=m*o[c][f];a[u]-=m*a[c]}}let s=a.map((c,l)=>c/o[l][l]),i=t;for(let c=0;c<n;c++)i=Wt(i,ot(r[c],s[c]));return{v:i,w:[1-s.reduce((c,l)=>c+l,0),...s]}}function tV(e){let t=null,r=1/0,n=e.length;for(let o=1;o<1<<n;o++){let a=e.filter((c,l)=>o&1<<l),s=eV(a.map(c=>c.w));if(!s||s.w.some(c=>c<-1e-9))continue;let i=er(s.v,s.v);(i<r-1e-12||Math.abs(i-r)<=1e-12&&t&&a.length<t.keep.length)&&(r=i,t={v:s.v,keep:a,weights:s.w})}return t??{v:e[0].w,keep:[e[0]],weights:[1]}}function rV(e,t){let r=s=>{let i=e.support(s),c=t.support(ot(s,-1));return{w:Co(i,c),a:i,b:c}},n=(s,i)=>{let c=[0,0,0],l=[0,0,0];return s.keep.forEach((u,m)=>{c=Wt(c,ot(u.a,s.weights[m])),l=Wt(l,ot(u.b,s.weights[m]))}),{distance:i,onA:c,onB:l}},o=r([1,0,0]),a={v:o.w,keep:[o],weights:[1]};for(let s=0;s<64;s++){let i=a.v,c=er(i,i);if(c<1e-12)return n(a,0);let l=r(ot(i,-1));if(c-er(i,l.w)<=1e-9*Math.max(1,c))return n(a,Math.sqrt(c));let u=tV([...a.keep,l]);if(u.keep.length===4)return n(u,0);if(er(u.v,u.v)>=c-1e-12)return n(a,Math.sqrt(c));a=u}return n(a,Lc(a.v))}function nV(e,t){let r=null;for(let o of t.samples?.()??[]){let a=1/0,s=0,i=0;for(let c=0;c<3;c++)o[c]-e.min[c]<a&&(a=o[c]-e.min[c],s=c,i=e.min[c]),e.max[c]-o[c]<a&&(a=e.max[c]-o[c],s=c,i=e.max[c]);a>0&&(!r||a>r.depth)&&(r={depth:a,point:o,axis:s,to:i})}if(!r)return null;let n=[...r.point];return n[r.axis]=r.to,{depth:r.depth,point:r.point,face:n}}function oV(e,t){let r=0;for(let n=0;n<3;n++){let o=Math.max(0,e.min[n]-t.max[n],t.min[n]-e.max[n]);r+=o*o}return Math.sqrt(r)}var kF={linkRadius:8,mountAllowance:15},aV=(e,t,r)=>e.z0+e.dzdx*t+e.dzdy*r;function sV(e,t){let r=Math.sin(e.pitch);return{z0:-e.heave+t*r,dzdx:-r,dzdy:Math.sin(e.roll)}}function MF(e){return sV(fp({heave:0,pitch:0,roll:0,steer:0},e),un(e.vehicle.config))}var iV=[{name:"upper wishbone, front leg",inboard:"ucaFront",outboard:"uprightUpper"},{name:"upper wishbone, rear leg",inboard:"ucaRear",outboard:"uprightUpper"},{name:"lower wishbone, front leg",inboard:"lcaFront",outboard:"uprightLower"},{name:"lower wishbone, rear leg",inboard:"lcaRear",outboard:"uprightLower"},{name:"tie rod",inboard:"tieInner",outboard:"tieOuter"},{name:"pushrod",inboard:"rockerToPushrod",outboard:"pushrodOuter"},{name:"strut",inboard:"damperChassis",outboard:"pushrodOuter"}];function cV(e){return iV.filter(t=>t.name==="strut"?e.mcpherson:t.name==="pushrod"?!e.direct:!(e.mcpherson&&t.name.startsWith("upper")))}var lV=(e,t,r)=>e.every((n,o)=>n>=t.min[o]-r&&n<=t.max[o]+r);function RF(e,t,r){let n=Co(t,e),o=Lc(n);return o>1e-9?Wt(e,ot(n,r/o)):e}function vF(e,t){let r=null;for(let{shape:n,pad:o,part:a,pose:s}of t){if(r&&oV(e,n)-o>=r.distance)continue;let i=rV(e,n),c=i.distance>0?null:nV(e,n),l=i.distance>0?i.distance-o:-((c?.depth??0)+o);if(Number.isFinite(l)&&(!r||l<r.distance)){let u=i.distance>0?{part:RF(i.onB,i.onA,o),box:i.onA}:c?{part:RF(c.point,c.face,-o),box:c.face}:{part:i.onB,box:i.onA};r={distance:l,part:a,corner:s.corner,travel:s.travel,rack:s.rack,gap:u}}}return r}function uV(e,t){let r=[];for(let c of[e.min[0],e.max[0]])for(let l of[e.min[1],e.max[1]])r.push([c,l,e.min[2]]);let n=r.map(t),o=Math.min(...n),a=r.filter((c,l)=>n[l]<=o+.5),s=new Set(a.map(c=>c[0])),i=new Set(a.map(c=>c[1]));return{height:o,lowest:{x:s.size>1||e.min[0]===e.max[0]?null:a[0][0]===e.max[0]?"front":"rear",y:i.size>1||e.min[1]===e.max[1]?null:a[0][1]===e.max[1]?"right":"left"},at:ot(a.reduce((c,l)=>Wt(c,l),[0,0,0]),1/a.length)}}function SF(e,t){return{...uV(e,r=>r[2]-aV(t,r[0],r[1])),road:t}}function AF(e,t){let r=(a,s,i)=>a[0]*(s[1]*i[2]-s[2]*i[1])-a[1]*(s[0]*i[2]-s[2]*i[0])+a[2]*(s[0]*i[1]-s[1]*i[0]),n=r(e[0],e[1],e[2]);if(Math.abs(n)<1e-12)return null;let o=a=>e.map((s,i)=>s.map((c,l)=>l===a?t[i]:c));return[r(...o(0))/n,r(...o(1))/n,r(...o(2))/n]}function mV(e,t){let r=e.map(o=>({pose:o,part:`${o.corner} tyre`,pad:0,shape:JO(o.g.wheelCenter,o.g.spinAxis,o.corner[0]==="F"?t.tyreRadius.front:t.tyreRadius.rear,t.tyreWidth)})),n=e.flatMap(o=>cV(o.g).map(a=>{let s=o.g[a.inboard],i=o.g[a.outboard];return{pose:o,part:`${o.corner} ${a.name}`,pad:t.linkRadius,inboard:s,shape:ZO(s,i)}})).filter(o=>o.inboard.every(Number.isFinite)&&[o.shape.min,o.shape.max].every(a=>a.every(Number.isFinite)));return{tyres:r,links:n}}function pV(e,t,r){let n=QO(e.min,e.max),o=t.links.filter(a=>!lV(a.inboard,e,r.mountAllowance+r.linkRadius));return{tyre:vF(n,t.tyres),link:vF(n,o)}}function FF(e,t,r){let n=mV(t,r);return e.map(o=>({boxId:o.id,...pV(o,n,r)}))}var DF=152,EF={travelSteps:9,rackSteps:5},To=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],tn=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],Dc=(e,t)=>[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]],tr=e=>{let t=Math.hypot(e[0],e[1],e[2]);return t>0?[e[0]/t,e[1]/t,e[2]/t]:[NaN,NaN,NaN]},IF=180/Math.PI,dV=[[1,0,0],[0,1,0],[0,0,1]],wF=(e,t)=>[e[0][0]*t[0]+e[1][0]*t[1]+e[2][0]*t[2],e[0][1]*t[0]+e[1][1]*t[1]+e[2][1]*t[2],e[0][2]*t[0]+e[1][2]*t[1]+e[2][2]*t[2]],fV=(e,t)=>[tn(e[0],t),tn(e[1],t),tn(e[2],t)];function CF(e,t,r){let n=tr(To(t,e)),o=tr(Dc(n,To(r,e)));return[n,Dc(o,n),o]}function hV(e,t){let r=n=>[t[0][0]*e[0][n]+t[1][0]*e[1][n]+t[2][0]*e[2][n],t[0][1]*e[0][n]+t[1][1]*e[1][n]+t[2][1]*e[2][n],t[0][2]*e[0][n]+t[1][2]*e[1][n]+t[2][2]*e[2][n]];return[r(0),r(1),r(2)]}function $0(e,t,r,n){let o=tr(To(t,e)),a=b=>{let g=To(b,e),y=tn(g,o);return[g[0]-y*o[0],g[1]-y*o[1],g[2]-y*o[2]]},s=tr(a(r)),i=tr(a(n)),c=tn(Dc(s,i),o),u=tn(s,i),m=c,f=1-u,[p,d,h]=o;return[[f*p*p+u,f*p*d+m*h,f*p*h-m*d],[f*p*d-m*h,f*d*d+u,f*d*h+m*p],[f*p*h+m*d,f*d*h-m*p,f*h*h+u]]}var bV=(e,t)=>Math.acos(Math.max(-1,Math.min(1,tn(tr(e),tr(t)))))*IF;function gV(e,t){return{upright:hV(CF(e.uprightLower,e.tieOuter,e.wheelCenter),CF(t.uprightLower,t.tieOuter,t.wheelCenter)),uca:t.mcpherson?null:$0(t.ucaFront,t.ucaRear,e.uprightUpper,t.uprightUpper),lca:$0(t.lcaFront,t.lcaRear,e.uprightLower,t.uprightLower),rocker:t.direct?null:$0(t.rockerPivotA,t.rockerPivotB,e.rockerToPushrod,t.rockerToPushrod)}}function _F(e){let t=tr(e[0]),r=Math.abs(t[0])<.9?[1,0,0]:[0,1,0],n=tr(Dc(t,r)),o=Dc(t,n),a=e.map(d=>{let h=tr(d);return[tn(h,n),tn(h,o)]}),s=d=>{let h=Math.cos(d),b=Math.sin(d),g=0;for(let[y,R]of a)g=Math.max(g,Math.abs(y*h+R*b));return g},i=Math.PI/180,c=0,l=1/0;for(let d=0;d<180;d++){let h=s(d*i);h<l&&([c,l]=[d*i,h])}let u=c-i,m=c+i,f=(Math.sqrt(5)-1)/2;for(let d=0;d<30;d++){let h=m-f*(m-u),b=u+f*(m-u);s(h)<s(b)?m=b:u=h}let p=Math.min(l,s((u+m)/2));return Math.asin(Math.min(1,p))*IF}function TF(e){let t=null;for(let r of e)Number.isFinite(r.angle)&&(!t||r.angle>t.angle)&&(t=r);return t}var yV={upright:"upright",lowerArm:"lca",upperArm:"uca"};function NF(e,t,r,n){let o=t.map(m=>gV(e,m)),a=tr(To(e.uprightUpper,e.uprightLower)),s=m=>Math.max(0,...o.map(f=>f[m]?bV(wF(f.upright,a),wF(f[m],a)):0)),i=[{angle:s("lca"),joint:"lower ball joint"}];e.mcpherson||i.push({angle:s("uca"),joint:"upper ball joint"});let c=(m,f,p)=>{let d=[To(e[f],e[m])];for(let h=0;h<t.length;h++){let b=p(o[h]);if(!b)return null;d.push(fV(b,To(t[h][f],t[h][m])))}return d},l=[["tie rod, inner end",c("tieInner","tieOuter",()=>dV)],["tie rod, outer end",c("tieInner","tieOuter",m=>m.upright)]];e.direct||l.push([`${n}, rocker end`,c("rockerToPushrod","pushrodOuter",m=>m.rocker)],[`${n}, outer end`,c("rockerToPushrod","pushrodOuter",m=>m[yV[r]])]);let u=l.filter(m=>m[1]!==null).map(([m,f])=>({joint:m,angle:_F(f)}));return{ballJoint:TF(i),rodEnd:TF(u)}}function xV(e){let t=(r,n)=>{let o=Kt(n,e.kc,r),a=e.kc?.input.corners[r];return a&&a.tyreRate>0&&Number.isFinite(a.tyreRate)?o+Math.max(0,a.staticLoad)/a.tyreRate:o};return{front:t("FL",e.vehicle.front.config.loadedRadius),rear:t("RL",e.vehicle.rear.config.loadedRadius)}}function OF(e,t){let r=eu(t);return{...kF,tyreRadius:xV(e),tyreWidth:r!==null?r*1e3:DF}}var PF={front:["FL","FR"],rear:["RL","RR"]},LF=(e,t,r)=>r<=1||t===e?[e]:Array.from({length:r},(n,o)=>e+(t-e)*o/(r-1));function G0(e,t,r,n,o=EF){let a=e.vehicle,[s]=PF[t],i=Ou(e,s,0,0)?.geometry;if(!i)return null;let c=yp(a.chassis?.boxes??[],{vehicle:a,kc:e.kc}),l=t==="front"?kt(a.front.config):0,u=l>0?LF(-l,l,Math.max(3,o.rackSteps|1)):[0],m=LF(Math.min(0,r.min),Math.max(0,r.max),Math.max(2,o.travelSteps)),f=[];for(let b of c.length?PF[t]:[s])for(let g of m)for(let y of u){let R=Ou(e,b,g,y)?.geometry;R&&f.push({corner:b,travel:g,rack:y,g:R})}let p=null;if(c.length){for(let b of FF(c,f,OF(e,n)))for(let g of[b.tyre,b.link])g&&(!p||g.distance<p.distance)&&(p={distance:g.distance,part:g.part,boxId:b.boxId});p??={distance:NaN,part:"",boxId:""}}let d=a[t].config,h=NF(i,f.filter(b=>b.corner===s).map(b=>b.g),d.pushrodAttach,d.rodType==="pull"?"pullrod":"pushrod");return{chassis:p,...h}}var xp=Math.PI/180,Ec={travelSteps:9,heaveSteps:5,rollSteps:4,rackSteps:6},Rp={travelMin:-25,travelMax:25,rollMaxDeg:3,rollAtLimitDeg:2.5};function RV(e){let t=e.params;return{cgHeight:t.cg_height?gt({...t,surveyedRadiusFront:e.vehicle.front.config.loadedRadius,surveyedRadiusRear:e.vehicle.rear.config.loadedRadius}).cgHeight:300,...Gh(t),drive:Vh(t)}}function VF(e,t){for(let r=1;r<e.length;r++){let n=3*t(r)+10;for(let o of["cpLeft","cpRight"]){let a=e[r-1][o],s=e[r][o];if(a&&s&&Math.hypot(s[0]-a[0],s[1]-a[1])>n)return r}}return-1}function K0(e,t=Ec,r=Rp,n){let o=null,a=(S,C)=>(o||(o={violation:S,reason:C}),null),s=e.vehicle,i=S=>S==="front"?s.front:s.rear,c=null,l=null,u=()=>{if(c)return c;if(n)try{let S=n();if(S)return c=It(s,S.kc),l=S.cgHeight,c}catch{a(500,"the car could not be stood on its tyre: its rates did not assemble")}return c=It(s)},m=S=>S==="front"?"FL":"RL",f=S=>{let C=u();if(!C.kc)return;let L=i(S).config.loadedRadius,D=Kt(L,C.kc,m(S));return D===L?void 0:{loadedRadius:D}},p=(S,C)=>-_s(u(),m(S),C),d=new Map,h=new Map,b=new Map,g=new Map,y=new Map,R=new Map,k=new Map,v=new Map,x=null,M=()=>{if(x)return x;u();let S=RV(e);return x=l!==null&&Number.isFinite(l)?{...S,cgHeight:l}:S},F,w,T=()=>{if(w!==void 0)return w;let S=Il(u().ctx.FL,kt(s.front.config));return w=S?_l(S):null,w},P=(S,C,L)=>{if(S.has(C))return S.get(C)??null;let D=L();return S.set(C,D),D};return{car:e,density:t,envelope:r,get failure(){return o},axisLength:(S,C)=>{let L=i(S),D=L.hardpoints;return C==="uca"&&L.config.layout==="mcpherson"?NaN:C==="uca"?ve(D.ucaFront,D.ucaRear):ve(D.lcaFront,D.lcaRear)},linkLength:S=>{let C=i(S).hardpoints;return ve(C.tieInner,C.tieOuter)},compliance:S=>P(h,S,()=>Hf(i(S))??null),sweep:S=>P(d,S,()=>{let C;try{C=Ke(i(S),{travelMin:r.travelMin,travelMax:r.travelMax,steps:t.travelSteps})}catch{return a(500,`the ${S} travel sweep threw`)}if(!C.covered){let D=C.samples.map(N=>N.travel),I=Math.max(...D)-Math.min(...D),O=r.travelMax-r.travelMin;return a(Math.max(0,O-I),`the ${S} linkage reaches only ${I.toFixed(0)} mm of the ${O.toFixed(0)} mm travel range`)}if(C.fold)return a(200,`the ${S} travel(beta) folds \u2014 the suspension goes over centre in range`);let L=C.samples.filter(D=>!D.converged).length;if(L>0)return a(100+10*L,`${L} of ${C.samples.length} ${S} travel solves did not converge`);if(S==="front"&&i("front").config.steerMode==="rack"){let D=T();if(D)return a(D.violation,D.reason)}return C}),rcHeave:S=>P(b,S,()=>{let C=[],L=[],D=Math.max(2,t.heaveSteps);try{for(let O=0;O<D;O++){let N=r.travelMin+(r.travelMax-r.travelMin)*O/(D-1);C.push(N),L.push(hr(u(),{heave:p(S,N),pitch:0,roll:0,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in heave`)}let I=VF(L,O=>Math.abs(C[O]-C[O-1]));return I>0?a(300,`the ${S} roll-centre construction lands on another branch at ${C[I].toFixed(0)} mm of travel`):{at:C,rc:L}}),rcRoll:S=>P(g,S,()=>{let C=[],L=[],D=Math.max(2,t.rollSteps);try{for(let O=0;O<D;O++){let N=r.rollMaxDeg*O/(D-1);C.push(N),L.push(hr(u(),{heave:0,pitch:0,roll:N*xp,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in roll`)}let I=VF(L,O=>Math.abs(L[O].cpLeft?.[0]??0)*Math.abs(C[O]-C[O-1])*xp);return I>0?a(300,`the ${S} roll-centre construction lands on another branch at ${C[I].toFixed(1)}\xB0 of roll`):{at:C,rc:L}}),steer:()=>{if(F!==void 0)return F;try{F=Sf(u(),{steerMax:kt(s.front.config),steps:t.rackSteps})}catch{F=a(500,"the steering sweep threw")}let S=F?.filter(C=>!C.converged).length??0;if(F&&S>0){let C=T();F=C?a(C.violation,C.reason):a(100+10*S,`${S} of ${F.length} steering solves did not converge`)}return F??null},solveAt:(S,C,L=0)=>P(y,`${S}:${C}:${L}`,()=>{try{let D=ge(u().ctx[m(S)],C,L,void 0,f(S));return D.ok?D.state:D.why==="unconverged"?a(100,`the ${S} corner did not solve at ${C.toFixed(0)} mm of travel`):a(100+Math.abs(D.travelMiss),`the ${S} corner reaches only ${(C+D.travelMiss).toFixed(0)} of ${C.toFixed(0)} mm of travel`)}catch{return a(150,`the ${S} corner solve threw at ${C.toFixed(0)} mm of travel`)}}),readout:S=>P(k,`${S.heave}:${S.pitch}:${S.roll}:${S.steer}`,()=>{try{return B0(u(),S,M())}catch{return a(500,"the derived readout threw")}}),readoutAtTravel:(S,C)=>P(v,`${S}:${C}`,()=>{try{return Pc(u(),{heave:p(S,C),pitch:0,roll:0,steer:0},S,M())}catch{return a(500,`the ${S} readout threw at ${C.toFixed(0)} mm of travel`)}}),travelAtRoll:(S,C)=>{let L=i(S).hardpoints.wheelCenter[1]*Math.sin(C*xp),D=u();if(!D.kc)return L;try{let I=vt(D,{heave:0,pitch:0,roll:C*xp,steer:0}),O=S==="front"?Math.max(I.FL.travel,I.FR.travel):Math.max(I.RL.travel,I.RR.travel);return Number.isFinite(O)?O:L}catch{return a(500,`the ${S} axle could not be rolled on its tyre`),L}},onTyre:()=>!!u().kc,contexts:u,keepOuts:S=>P(R,S,()=>{try{let C=e.params,L=S==="front"?C.tireModel:C.tireModelRear??C.tireModel,D={min:r.travelMin,max:r.travelMax};return G0(u(),S,D,L)??a(100,`the ${S} corner did not solve at its design ride`)}catch{return a(500,`the ${S} keep-outs threw`)}})}}var vV=Lg();function H0(e,t={}){let r=new Map;return{session(n){if(r.has(n))return r.get(n);let o=null,a=t.session?.();if(t.sessionParams&&a)try{let s=Dm(n,a.rulesets),i=s?.events.some(c=>c.kind==="trackLap");if(s&&(a.track||!i)){let c=t.sessionParams(e),{standingStart:l,lapCounts:u}=a.settings,m=a.track?uc([c],a.track,a.numerics,ac(s),a.settings,vV)[0]:qi(c,s,{numerics:a.numerics,standingStart:l,lapCounts:u});o={};for(let f of s.metrics)rl(f)&&(o[f.key]=f.value(m,void 0))}}catch{o=null}return r.set(n,o),o}}}var vp=.01;function kV(e,t){return t.bump!==null&&e>t.bump-vp?{at:"closed",past:Math.max(0,e-t.bump)}:t.droopStated&&e<t.droop+vp?{at:"toppedOut",past:Math.max(0,t.droop-e)}:t.seat!==null&&e<t.seat+vp?{at:"unseated",past:Math.max(0,t.seat-e)}:{at:"free",past:0}}var BF=e=>({droop:e.droop,droopStated:e.droopStated,bump:e.bump,seat:e.holdsLoad&&Number.isFinite(e.free)?e.free:null}),MV=[["front","FL","FR"],["rear","RL","RR"]];function Y0(e,t){let r=[];for(let[n,o,a]of MV){let s=[t[o],t[a]];for(let m of[o,a]){let f=e.curve[m],p=f.spring?.law;if(!f.spring||!p)continue;let d=nf(f,t[m]);d===null||!Number.isFinite(d)||r.push(z0(m,n,n,d,f.spring.length0-d,BF(p),!0))}let i=e.elements?.[n];if(!i)continue;let c=i.heave?.law;if(c){let m=_R(i,s),f=i.read.heave?.span0,p=n==="front"?"heaveFront":"heaveRear";r.push(z0(p,p,n,m,f!==void 0?f-m:null,BF(c),i.carriesLoad))}let l=i.rollStop,u=l?NR(i,s):null;if(l&&u!==null){let m=l.length0-u,f=n==="front"?"rollFront":"rollRear",p={droop:l.droop??-1/0,droopStated:l.droop!==null,bump:l.bump,seat:null};r.push(z0(f,f,n,m,u,p,i.carriesLoad))}}return r}function z0(e,t,r,n,o,a,s){return{damper:e,place:t,axle:r,length:o,compression:n,toToppedOut:a.droopStated?n-a.droop:null,toClosed:a.bump!==null?a.bump-n:null,...kV(n,a),bumpStated:a.bump!==null,bounds:s}}var KF=Math.PI/180;function W0(e,t,r,n){let o=t.speedKmh/3.6,a=Bd(e,o,t.axG,sn(e,t.ayG,0));if(!a||!e.aero)return null;let s=e.wheelbase,i=Qo(e.aero,s),c=(h,b)=>Math.atan((b-h)/s)/KF,l={},u={};for(let h of ir)l[h]=r.corners[h].travel,u[h]=r.corners[h].ground;let m=n.kc?Y0(n.kc,l):[],f=e.aero.model,p=a.downFront+a.downRear,d=f?{balance:Math.abs(p)>1e-9?100*a.downFront/p:NaN,clA:(a.clFront+a.clRear)*a.area,cdA:a.cd*a.area,loopMargin:1-a.gain,dataMargin:HF(f,s,a.hFront,a.hRear)}:null;return{front:{height:a.hFront,...$F(m,"front")},rear:{height:a.hRear,...$F(m,"rear")},rakeDeg:c(a.hFront,a.hRear),pitchDeg:c(a.hFront,a.hRear)-c(i.hFront,i.hRear),rollDeg:Math.abs(r.rollDeg),aero:d,clearance:SV(n,u)}}function $F(e,t){let r=e.filter(o=>o.axle===t&&o.bounds),n=o=>{let a=o.filter(s=>s!==null&&Number.isFinite(s));return a.length?Math.min(...a):null};return{toBump:n(r.map(o=>o.toClosed)),toDroop:n(r.map(o=>o.toToppedOut))}}function HF(e,t,r,n){let o=(a,[s,i])=>Math.min(a-s,i-a);if(Cx(e)){let{x:a,y:s}=jo(e),i=[a[0],a[a.length-1]],c=[s[0],s[s.length-1]];return on(e)?GF(e.frame,t,i,c,r,n):Math.min(o(r,i),o(n,c))}return cl(e)?GF(e.frame,t,e.range.h,e.range.pitch,r,n):Math.min(o(r,e.range.hFront),o(n,e.range.hRear))}function GF(e,t,r,n,o,a){let s=Uo(e,t,o,a),i=l=>t*Math.tan(l*KF),c=a-o;return Math.min(s.h-r[0],r[1]-s.h,c-i(n[0]),i(n[1])-c)}function SV(e,t){let r=e.vehicle.chassis?.boxes;if(!r?.length)return null;let n={vehicle:e.vehicle,kc:e.kc},o=e.vehicle.config,a=o.frontAxleX,s=o.frontAxleX-o.wheelbase,i=Gt(e.vehicle,!0)/2,c=Gt(e.vehicle,!1)/2,l={FL:[a,-i],FR:[a,i],RL:[s,-c],RR:[s,c]},u=[[0,0,0],[0,0,0],[0,0,0]],m=[0,0,0];for(let b of ir){let g=[1,l[b][0],l[b][1]];for(let y=0;y<3;y++){m[y]+=g[y]*t[b];for(let R=0;R<3;R++)u[y][R]+=g[y]*g[R]}}let f=AF(u,m);if(!f)return null;let p=MF(n),d={z0:p.z0+f[0],dzdx:p.dzdx+f[1],dzdy:p.dzdy+f[2]},h=null;for(let b of yp(r,n)){let g=SF(b,d);(!h||g.height<h.height)&&(h={height:g.height,volume:b.name})}return h}function kp(e){return e.aeroModel?null:"The car runs on aero constants, which do not move with the platform; attach an aero model in Aerodynamics"}var AV={front:"front",rear:"rear",heaveFront:"front",heaveRear:"rear",rollFront:"front",rollRear:"rear"};function Ic(e,t,r,n){let o=Wu(e,t);return _u.some(s=>{if(AV[s]!==r)return!1;let i=o[s].coilover,c=i?.extended!==void 0&&i.extended>0;return n==="droop"?c:c&&i?.stroke!==void 0&&i.stroke>0})?null:n==="droop"?`No ${r} damper states its extended length; state it on its part in Dampers, or under Elements \u203A Stops`:`No ${r} damper states its stroke; state its extended length and stroke on its part in Dampers, or under Elements \u203A Stops`}function j0(e){return e.chassis?.boxes.length?null:"This suspension has no mockup volumes to measure the ground from; draw one under Kinematics \u203A Chassis"}var Mp=Math.PI/180,Sp=1e-6;function YF(e,t){let r=e.length;if(r===0)return 0;if(0<=e[0])return t[0];if(0>=e[r-1])return t[r-1];let n=0;for(;e[n+1]<0;)n++;let o=(0-e[n])/(e[n+1]-e[n]);return t[n]+o*(t[n+1]-t[n])}function _c(e){let t=e.measured;if(t)return YF(t.travel,t.camber);let r=q(e.config.spinAxis);return-Math.asin(Math.max(-1,Math.min(1,r[2])))/Mp}function Nc(e){let t=e.measured;if(t)return YF(t.travel,t.toe);let[r,n]=e.config.spinAxis;return Math.atan2(r,n)/Mp}function U0(e,t){let r=Math.abs(t.camber)>=Sp,n=Math.abs(t.toe)>=Sp;if(!r&&!n)return e;let o=e.measured;if(o)return{...e,measured:{...o,...r?{camber:o.camber.map(p=>p+t.camber)}:{},...n?{toe:o.toe.map(p=>p+t.toe)}:{}}};let[a,s]=e.config.spinAxis,i=Math.hypot(a,s);if(!(i>0))return e;let c=(_c(e)+t.camber)*Mp,l=(Nc(e)+t.toe)*Mp,[u,m]=n?[Math.sin(l),Math.cos(l)]:[a/i,s/i],f=[u*Math.cos(c),m*Math.cos(c),-Math.sin(c)];return{...e,config:{...e.config,spinAxis:f}}}function Ap(e){let t=e&&typeof e=="object"?e.value:void 0;return typeof t=="number"&&Number.isFinite(t)?t:void 0}function FV(e,t){let r=t;return{front:Ap(r.camber_front_deg)??_c(e.front),rear:Ap(r.camber_rear_deg)??_c(e.rear)}}function wV(e,t){let r=t;return{front:Ap(r.toe_front_deg)??Nc(e.front),rear:Ap(r.toe_rear_deg)??Nc(e.rear)}}function CV(e){return{camber:{front:_c(e.front),rear:_c(e.rear)},toe:{front:Nc(e.front),rear:Nc(e.rear)}}}var zF=new WeakMap;function TV(e,t){let r=CV(e),n={front:{camber:t.camber.front-r.camber.front,toe:t.toe.front-r.toe.front},rear:{camber:t.camber.rear-r.camber.rear,toe:t.toe.rear-r.toe.rear}},o=u=>Math.abs(u.camber)<Sp&&Math.abs(u.toe)<Sp;if(o(n.front)&&o(n.rear))return e;let a=`${t.camber.front}|${t.camber.rear}|${t.toe.front}|${t.toe.rear}`,s=zF.get(e),i=s?.get(a);if(i)return i;let c=e.corners?Object.fromEntries(Object.entries(e.corners).map(([u,m])=>[u,m&&U0(m,n[Jo(u)])])):void 0,l={...e,front:U0(e.front,n.front),rear:U0(e.rear,n.rear),...c?{corners:c}:{}};return s||zF.set(e,s=new Map),s.size>=16&&s.clear(),s.set(a,l),l}function ts(e,t){return t?TV(e,{camber:FV(e,t),toe:wV(e,t)}):e}var PV=9.81;function rs(e){let t=zn(e),r=Math.max(0,e.unsprungPerCorner)*PV,n=a=>{let s=a==="FL"||a==="FR",i=s?"front":"rear",c=qe(e,i),l=c>0?c:1/0,u=xd(e,i);return{staticLoad:t[a],springLoad:Math.max(0,t[a]-r),tyreRate:l,arbRate:s?e.arbFront:e.arbRear,heaveRate:(s?e.heaveSpringFront:e.heaveSpringRear)??0,...u>0?{staticLoadedRadius:Yt(u,t[a],l,u)}:{}}},o={};for(let[a,s,i,c,l,u]of[["front",e.elementLinkagesFront,!!e.decoupledFront,e.heaveCoiloverFront,e.heaveSeatFront,e.rollCoiloverFront],["rear",e.elementLinkagesRear,!!e.decoupledRear,e.heaveCoiloverRear,e.heaveSeatRear,e.rollCoiloverRear]]){let m=!i&&!!l&&(l.gap>0||!l.bothWays);(s?.heave||s?.roll||i||m)&&(o[a]={...s,carriesLoad:i,...c?{coilover:c}:{},...l&&!i?{heaveSeat:l}:{},...u?{rollCoilover:u}:{}})}return{corners:{FL:n("FL"),FR:n("FR"),RL:n("RL"),RR:n("RR")},...o.front||o.rear?{elements:o}:{},...e.cornerCoiloverFront||e.cornerCoiloverRear?{cornerCoilover:{...e.cornerCoiloverFront?{front:e.cornerCoiloverFront}:{},...e.cornerCoiloverRear?{rear:e.cornerCoiloverRear}:{}}}:{}}}var WF=new WeakMap;function LV(e){let t=ts(e.vehicle,e.params);if(t===e.vehicle)return e;let r=WF.get(e);return(!r||r.vehicle!==t)&&WF.set(e,r={...e,vehicle:t}),r}function Pn(e,t={}){let r=LV(e),n=F0(r,t),o=t.assemble?()=>{let m=n.dynInput();if(!m)throw new Error("the car did not assemble");return{kc:rs(m),cgHeight:m.cgHeight}}:void 0,a=K0(r,t.density,t.envelope,o),s=D0(r,n,t),i=H0(r,t),c=t.states??[],l=new Map;return{...a,...n,...s,...i,get failure(){return a.failure},values:new Map,states:c,stateOf:m=>m===void 0?c[0]??null:c.find(f=>f.id===m)??null,platformAt:m=>{let f=`${m.speedKmh}|${m.ayG}|${m.axG}`,p=l.get(f);if(p!==void 0)return p;let d=n.poseAt(m),h=n.dynInput(),b=null;if(d&&h)try{b=W0(h,m,d,a.contexts())}catch{b=null}return l.set(f,b),b}}}var DV=["x","y","z"],EV=/^(line|plane)\((-?\d+),(-?\d+)\)([uv]?)$/,jF=Math.PI/18e3,UF=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],XF=(e,t)=>[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]],IV=e=>Math.hypot(e[0],e[1],e[2]),X0=(e,t)=>[e[0]*t,e[1]*t,e[2]*t];function q0(e){let t=IV(e);return t>1e-9?X0(e,1/t):null}function _V(e,t){let r=e*jF,n=t*jF;return[Math.cos(n)*Math.cos(r),Math.cos(n)*Math.sin(r),Math.sin(n)]}function jt(e){let t=e.lastIndexOf(".");if(t<0)return null;let r=EV.exec(e.slice(t+1));if(!r)return null;let n=r[1];return n==="line"!=(r[4]==="")?null:{point:e.slice(0,t),shape:{kind:n,dir:_V(Number(r[2]),Number(r[3]))},coord:n==="line"?"along":r[4]}}function qF(e){let t=q0(XF([0,0,1],e))??[1,0,0];(t[0]<-1e-9||Math.abs(t[0])<=1e-9&&t[1]<0)&&(t=X0(t,-1));let r=q0(XF(e,t))??[0,1,0];return(r[2]<-1e-9||Math.abs(r[2])<=1e-9&&r[1]<0)&&(r=X0(r,-1)),[t,r]}function Q0(e){if(e.coord==="along")return e.shape.dir;let[t,r]=qF(e.shape.dir);return e.coord==="u"?t:r}function QF(e,t){let r=jt(t);if(!r)return;let n=DV.map(u=>e[`${r.point}.${u}`]);if(n.some(u=>!u))return;let o=Q0(r),a=[0,1,2].filter(u=>Math.abs(o[u])>1e-12),s=u=>n.map(m=>m.read(u)),i=n[0],c=a.map(u=>n[u].supersededBy).find(Boolean),l=i.label.replace(/ x$/,"");return{id:t,group:i.group,label:r.coord==="along"?`${l} along its line`:`${l} in its plane, ${r.coord}`,...i.scope?{scope:i.scope}:{},unit:i.unit,defaultSpan:i.defaultSpan,read:u=>UF(s(u),o),write:(u,m)=>{let f=s(u),p=m-UF(f,o),d=u;for(let h of a)d=n[h].write(d,f[h]+p*o[h]);return d},...c?{supersededBy:c}:{}}}var ns=["x","y","z"];var NV=/^(?:hp\.(?:front|rear)\.\w+|(?:heave|roll)\.(?:front|rear)\.(?:outer|inner|anchor))$/;function Po(e){let t=e.lastIndexOf("."),r=e.slice(0,t);if(t<0||!NV.test(r))return null;let n=e.slice(t+1);if(n==="x"||n==="y"||n==="z")return{point:r,axis:n};let o=jt(e);return o?{point:r,axis:o.coord}:null}var Oc="*";function Z0(e){let t={sum:"summed",min:"lowest",max:"highest",distance:"by length",harmonic:"overall"};return e?.across?`all courses, ${t[e.across]}`:"all courses"}var J0=e=>e?.reads==="speed"||e?.reads==="operating",ey=e=>e?.reads==="lateral"||e?.reads==="operating";function Lo(e){if(!e)return"";let t=[];return e.speed!==void 0&&Number.isFinite(e.speed)&&t.push(`v${e.speed}`),e.ayG!==void 0&&Number.isFinite(e.ayG)&&t.push(`a${e.ayG}`),e.courseId&&t.push(`c${e.courseId}`),e.stateId&&t.push(`s${e.stateId}`),t.join(",")}function Fp(e,t){return e?.appliesAt?t.find(r=>!e.appliesAt(r)):t[0]}function os(e,t,r){let n=r?.stateId?e.stateOf(r.stateId):Fp(t,e.states)??null;return n&&!t.appliesAt?.(n)?n:null}function ut(e,t,r){let n=`${t.id}@${Lo(r)}`,o=e.values.get(n);if(o!==void 0)return o;let a;try{a=r?.courseId===Oc&&t.reads==="course"?OV(e,t,r):r?.stateId===kr&&t.reads==="state"?VV(e,t,r):t.read(e,r)}catch{a=NaN}return e.values.set(n,a),a}function OV(e,t,r){if(!t.across)return NaN;let n=e.courses();if(!n.length)return NaN;let o=n.map(s=>{let i={...r,courseId:s.id};return{v:ut(e,t,i),length:e.course(i)?.track.length??NaN}});if(o.some(s=>!Number.isFinite(s.v)))return NaN;if(t.across==="sum")return o.reduce((s,i)=>s+i.v,0);if(t.across==="min")return Math.min(...o.map(s=>s.v));if(t.across==="max")return Math.max(...o.map(s=>s.v));let a=o.reduce((s,i)=>s+i.length,0);return a>0?t.across==="harmonic"?a/o.reduce((s,i)=>s+i.length/i.v,0):o.reduce((s,i)=>s+i.v*i.length,0)/a:NaN}function VV(e,t,r){let n=t.appliesAt?e.states.filter(i=>!t.appliesAt(i)):e.states;if(!t.acrossStates||!n.length)return NaN;let o=n.map(i=>({v:ut(e,t,{...r,stateId:i.id}),w:i.weight,s:i})),a=t.appliesAt?o.filter(i=>Number.isFinite(i.v)||!e.poseAt(i.s)):o;if(!a.length||a.some(i=>!Number.isFinite(i.v)))return NaN;if(t.acrossStates==="max")return Math.max(...a.map(i=>i.v));if(t.acrossStates==="min")return Math.min(...a.map(i=>i.v));if(t.acrossStates==="span")return Math.max(...a.map(i=>i.v))-Math.min(...a.map(i=>i.v));let s=a.reduce((i,c)=>i+c.w,0);return s>0?a.reduce((i,c)=>i+c.v*c.w,0)/s:NaN}function ty(e){let t={mean:"weighted mean",max:"highest",min:"lowest",span:"span"};return e?.acrossStates?`every state, ${t[e.acrossStates]}`:"every state"}function je(e){return`${e.quantity??e.groupShort??e.group} \xB7 ${e.label}`}var BV={front:"Front",rear:"Rear"},Vc={heave:0,pitch:0,roll:0,steer:0};function ZF(e,t){let r=0,n=0;for(let o=1;o<e.length;o++){let a=e[o]-e[o-1];if(Math.abs(a)<1e-9)continue;let s=(t[o]-t[o-1])/a;r+=s*s,n++}return n?Math.sqrt(r/n):NaN}function $V(e,t){let r=0;for(let n=1;n<e.length;n++){let o=e[n]-e[n-1];Math.abs(o)<1e-9||(r=Math.max(r,Math.abs((t[n]-t[n-1])/o)))}return r}var Bc=e=>e.length?Math.max(...e)-Math.min(...e):NaN;function JF(e){let t=(e??[]).filter(Number.isFinite);if(!t.length)return NaN;let r=t.reduce((n,o)=>n+o,0)/t.length;return Math.abs(r)>0?(Math.max(...t)-Math.min(...t))/Math.abs(r):NaN}function ew(e,t){if(!e.length)return;let r=0;for(let n=1;n<e.length;n++)Math.abs(e[n])<Math.abs(e[r])&&(r=n);return t[r]}function as(e,t,r){let n=e.stateOf(t?.stateId),o=n?e.poseAt(n):null;return o?r(o):NaN}var $c=(e,t)=>`${e==="front"?"F":"R"}${t}`,tw=e=>e==="L"?"R":"L";function rw(e){let t=BV[e],r=x=>`kin.${e}.${x}`,n=(x,M)=>{let F=x.sweep(e);return F?{x:F.samples.map(w=>w.travel),y:F.samples.map(M)}:{x:[],y:[]}},o=x=>e==="front"?x.vehicle.front:x.vehicle.rear,a=x=>x.params[e==="front"?"heaveFrontDesign":"heaveRearDesign"],s=x=>x.params[e==="front"?"arbFrontDesign":"arbRearDesign"],i=e==="front"?"the front axle":"the rear axle";function c(x){return o(x).config.actuation==="decoupled"?`${i} is decoupled, with no corner damper \u2014 read its heave and roll elements`:null}function l(x){let M=a(x);return M&&M.design.kind!=="none"?null:`${i} has no heave element`}function u(x){let M=a(x);return M?.design.kind==="coil"&&M.linkage?null:`${i} has no heave element on a linkage`}function m(x){let M=s(x);return M&&M.design.kind!=="none"?null:`${i} has no roll element`}function f(x){let M=s(x);return M?.linkage&&M.design.kind!=="none"&&M.design.kind!=="direct"?null:`${i} has no roll element on a linkage`}let p=x=>{if(u(x.car))return null;let M=x.sweep(e);return M?lf(o(x.car),a(x.car).linkage,M.samples):null},d=x=>{if(f(x.car))return null;let M=x.sweep(e);if(!M)return null;let F=s(x.car),w=af(o(x.car),F.linkage,F.design.kind,M.samples),T=w.atDesign<0?-1:1;return{travel:w.travel,ratio:w.ratio.map(P=>P*T),atDesign:w.atDesign*T}},h=x=>x.readout(Vc)?.[e],b=x=>x.readoutAtTravel(e,x.envelope.travelMax),g=x=>{let M=n(x,F=>F.metrics.camber);return M.x.length?{key:r("camberGain"),title:`${t} camber vs travel`,xLabel:"travel [mm]",yLabel:"camber [\xB0]",...M}:null},y=x=>{let M=n(x,F=>F.metrics.toe);return M.x.length?{key:r("bumpSteer"),title:`${t} toe vs travel`,xLabel:"travel [mm]",yLabel:"toe [\xB0]",...M}:null},R=[{id:r("rcStatic"),group:`${t} roll centre`,label:"static height",unit:"mm",scale:30,scope:e,cost:"cheap",read:x=>x.rcRoll(e)?.rc[0]?.heightAboveGround??NaN},{id:r("rcHeaveWorst"),group:`${t} roll centre`,label:"worst migration vs travel",unit:"mm/mm",scale:.5,scope:e,cost:"cheap",read:x=>{let M=x.rcHeave(e);return M?$V(M.at,M.rc.map(F=>F.height)):NaN},curve:x=>{let M=x.rcHeave(e);return M?{key:r("rcHeaveWorst"),title:`${t} roll-centre height vs wheel travel`,xLabel:"travel [mm]",yLabel:"RC height [mm]",x:M.at,y:M.rc.map(F=>F.height)}:null}},{id:r("rcRollSpan"),group:`${t} roll centre`,label:"height span over the roll envelope",unit:"mm",scale:15,scope:e,cost:"cheap",read:x=>{let M=x.rcRoll(e);return M?Bc(M.rc.map(F=>F.height)):NaN},curve:x=>{let M=x.rcRoll(e);return M?{key:r("rcRollSpan"),title:`${t} roll-centre height vs body roll`,xLabel:"roll [\xB0]",yLabel:"RC height [mm]",x:M.at,y:M.rc.map(F=>F.height)}:null}},{id:r("rcLateralSpan"),group:`${t} roll centre`,label:"lateral migration over roll",unit:"mm",scale:50,scope:e,cost:"cheap",read:x=>{let M=x.rcRoll(e);return M?Bc(M.rc.map(F=>F.lateral)):NaN},curve:x=>{let M=x.rcRoll(e);return M?{key:r("rcLateralSpan"),title:`${t} roll-centre lateral position vs body roll`,xLabel:"roll [\xB0]",yLabel:"RC lateral [mm]",x:M.at,y:M.rc.map(F=>F.lateral)}:null}},{id:r("minSinAngle"),group:`${t} roll centre`,label:"construction conditioning (min sinAngle)",unit:"-",scale:.04,scope:e,cost:"cheap",read:x=>{let M=x.rcHeave(e),F=x.rcRoll(e);return!M||!F?NaN:Math.min(...M.rc.map(w=>w.sinAngle),...F.rc.map(w=>w.sinAngle))},curve:x=>{let M=x.rcHeave(e);return M?{key:r("minSinAngle"),title:`${t} construction conditioning vs travel`,xLabel:"travel [mm]",yLabel:"sinAngle",x:M.at,y:M.rc.map(F=>F.sinAngle)}:null}},{id:r("fvsaLength"),group:`${t} roll centre`,label:"front-view swing-arm length",unit:"mm",scale:500,scope:e,cost:"readout",read:x=>h(x)?.fvsaLength??NaN},{id:r("complianceSteer"),group:`${t} compliance`,label:"compliance steer",unit:"\xB0/kN lateral",scale:.05,scope:e,cost:"readout",read:x=>(x.compliance(e)?.toePerFy??0)*1e3},{id:r("complianceCamber"),group:`${t} compliance`,label:"compliance camber",unit:"\xB0/kN lateral",scale:.05,scope:e,cost:"readout",read:x=>(x.compliance(e)?.camberPerFy??0)*1e3},{id:r("complianceSteerLong"),group:`${t} compliance`,label:"compliance steer under braking",unit:"\xB0/kN longitudinal",scale:.05,scope:e,cost:"readout",read:x=>(x.compliance(e)?.toePerFx??0)*1e3},{id:r("steeringCompliance"),group:`${t} compliance`,label:"steer given back under aligning torque",unit:"\xB0/100 N\xB7m",scale:.2,scope:e,cost:"readout",read:x=>(x.compliance(e)?.toePerMz??0)*1e5},{id:r("staticCamber"),group:`${t} camber & toe`,label:"static camber",unit:"\xB0",scale:1,scope:e,cost:"cheap",read:x=>{let M=x.solveAt(e,0);return M?M.metrics.camber:NaN}},{id:r("staticToe"),group:`${t} camber & toe`,label:"static toe",unit:"\xB0",scale:.5,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.toe??NaN},{id:r("camberGainDesign"),group:`${t} camber & toe`,label:"camber gain in bump",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.camberGain??NaN,curve:x=>g(x)},{id:r("rollCamber"),group:`${t} camber & toe`,label:"camber gain in roll",unit:"\xB0/\xB0",scale:.2,scope:e,cost:"readout",read:x=>h(x)?.rollCamber??NaN},{id:r("rollCamberRecovery"),group:`${t} camber & toe`,label:"camber recovery in roll",unit:"%",scale:20,scope:e,cost:"readout",read:x=>h(x)?.camberRecovery??NaN},{id:r("bumpSteerDesign"),group:`${t} camber & toe`,label:"bump steer at design",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.bumpSteer??NaN,curve:x=>y(x)},{id:r("rollSteer"),group:`${t} camber & toe`,label:"roll steer",unit:"\xB0/\xB0",scale:.1,scope:e,cost:"readout",read:x=>h(x)?.rollSteer??NaN},{id:r("bumpSteer"),group:`${t} camber & toe`,label:"bump steer, RMS over the travel",unit:"\xB0/mm",scale:.02,scope:e,cost:"cheap",read:x=>{let M=n(x,F=>F.metrics.toe);return M.x.length?ZF(M.x,M.y):NaN},curve:x=>y(x)},{id:r("camberGain"),group:`${t} camber & toe`,label:"camber gain, RMS over the travel",unit:"\xB0/mm",scale:.02,scope:e,cost:"cheap",read:x=>{let M=n(x,F=>F.metrics.camber);return M.x.length?ZF(M.x,M.y):NaN},curve:x=>g(x)},{id:r("camberSpan"),group:`${t} camber & toe`,label:"camber range over travel",unit:"\xB0",scale:1,scope:e,cost:"cheap",read:x=>Bc(n(x,M=>M.metrics.camber).y)},{id:r("toeSpan"),group:`${t} camber & toe`,label:"toe range over travel",unit:"\xB0",scale:.5,scope:e,cost:"cheap",read:x=>Bc(n(x,M=>M.metrics.toe).y)},{id:r("camberRecovery"),group:`${t} camber & toe`,label:"outer camber at limit roll",unit:"\xB0",scale:2,scope:e,cost:"cheap",read:x=>{let M=x.solveAt(e,x.travelAtRoll(e,x.envelope.rollAtLimitDeg)),F=x.solveAt(e,0);return!M||!F?NaN:Math.abs(M.metrics.camber-F.metrics.camber+x.envelope.rollAtLimitDeg)}},{id:r("stateCamberOuter"),group:`${t} camber & toe`,label:"outer camber to the road at a state",unit:"\xB0",scale:1,scope:e,cost:"cheap",reads:"state",acrossStates:"mean",read:(x,M)=>as(x,M,F=>F.camber[$c(e,F.outer)])},{id:r("stateCamberInner"),group:`${t} camber & toe`,label:"inner camber to the road at a state",unit:"\xB0",scale:1,scope:e,cost:"cheap",reads:"state",acrossStates:"mean",read:(x,M)=>as(x,M,F=>F.camber[$c(e,tw(F.outer))])},{id:r("stateToeOuter"),group:`${t} camber & toe`,label:"outer toe change at a state",unit:"\xB0",scale:.2,scope:e,cost:"cheap",reads:"state",acrossStates:"mean",read:(x,M)=>as(x,M,F=>F.corners[$c(e,F.outer)].bumpToe)},{id:r("caster"),group:`${t} upright`,label:"caster",unit:"\xB0",scale:5,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.caster??NaN},{id:r("kpi"),group:`${t} upright`,label:"kingpin inclination",unit:"\xB0",scale:5,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.kpi??NaN},{id:r("scrubRadius"),group:`${t} upright`,label:"scrub radius",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.scrubRadius??NaN},{id:r("mechanicalTrail"),group:`${t} upright`,label:"mechanical trail",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.mechanicalTrail??NaN},{id:r("kingpinOffset"),group:`${t} upright`,label:"kingpin offset at hub height",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.kingpinOffset??NaN},{id:r("casterOffset"),group:`${t} upright`,label:"caster offset at hub height",unit:"mm",scale:10,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.casterOffset??NaN},{id:r("steeringArm"),group:`${t} upright`,label:"steering arm",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.steeringArm??NaN},{id:r("casterGain"),group:`${t} upright`,label:"caster gain in bump",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.casterGain??NaN},{id:r("kpiGain"),group:`${t} upright`,label:"kingpin inclination gain in bump",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.kpiGain??NaN},{id:r("scrubGain"),group:`${t} upright`,label:"scrub radius gain in bump",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:x=>h(x)?.scrubGain??NaN},{id:r("trailGain"),group:`${t} upright`,label:"mechanical trail gain in bump",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:x=>h(x)?.trailGain??NaN},{id:r("motionRatio"),group:`${t} rates`,label:"motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let M=x.sweep(e);return M?ew(M.samples.map(F=>F.travel),M.samples.map(F=>F.metrics.motionRatio??NaN))??NaN:NaN},curve:x=>{if(c(x.car))return null;let M=n(x,F=>F.metrics.motionRatio??NaN);return M.x.length?{key:r("motionRatio"),title:`${t} motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",...M}:null}},{id:r("mrSpread"),group:`${t} rates`,label:"motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let M=x.sweep(e);if(!M)return NaN;let F=M.samples.map(T=>T.metrics.motionRatio??NaN).filter(Number.isFinite);if(!F.length)return NaN;let w=F.reduce((T,P)=>T+P,0)/F.length;return w>0?(Math.max(...F)-Math.min(...F))/w:NaN}},{id:r("wheelRate"),group:`${t} rates`,label:"wheel rate at design",unit:"N/mm",scale:10,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let M=x.sweep(e);return M?ew(M.samples.map(F=>F.travel),M.samples.map(F=>F.metrics.wheelRate??NaN))??NaN:NaN}},{id:r("heaveMotionRatio"),group:`${t} rates`,label:"heave element motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:u,read:x=>p(x)?.atDesign??NaN,curve:x=>{let M=p(x);return M?{key:r("heaveMotionRatio"),title:`${t} heave element motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",x:M.travel,y:M.ratio}:null}},{id:r("heaveMrSpread"),group:`${t} rates`,label:"heave element motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:u,read:x=>JF(p(x)?.ratio)},{id:r("heaveWheelRate"),group:`${t} rates`,label:"heave element wheel rate at design",unit:"N/mm",scale:10,scope:e,cost:"cheap",unavailable:l,read:x=>l(x.car)||!x.sweep(e)?NaN:Da(x.car.vehicle,x.car.params)[e]??NaN},{id:r("rollMotionRatio"),group:`${t} rates`,label:"roll element motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:f,read:x=>d(x)?.atDesign??NaN,curve:x=>{let M=d(x);return M?{key:r("rollMotionRatio"),title:`${t} roll element motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",x:M.travel,y:M.ratio}:null}},{id:r("rollMrSpread"),group:`${t} rates`,label:"roll element motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:f,read:x=>JF(d(x)?.ratio)},{id:r("rollWheelRate"),group:`${t} rates`,label:"roll element wheel rate at design",unit:"N/mm",scale:10,scope:e,cost:"cheap",unavailable:m,read:x=>m(x.car)||!x.sweep(e)?NaN:so(x.car.vehicle,x.car.params)[e]??NaN},{id:r("ucaAxisLength"),group:`${t} package`,label:"upper arm pivot-axis length",unit:"mm",scale:80,scope:e,cost:"geometry",read:x=>x.axisLength(e,"uca")},{id:r("lcaAxisLength"),group:`${t} package`,label:"lower arm pivot-axis length",unit:"mm",scale:80,scope:e,cost:"geometry",read:x=>x.axisLength(e,"lca")},{id:r("linkLength"),group:`${t} package`,label:"tie/toe link length",unit:"mm",scale:100,scope:e,cost:"geometry",read:x=>x.linkLength(e)},{id:r("trackScrubRate"),group:`${t} package`,label:"track scrub rate",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:x=>x.readout(Vc)?.[e].trackScrubRate??NaN},{id:r("trackChange"),group:`${t} package`,label:"track change at full bump",unit:"mm",scale:2,scope:e,cost:"readout",read:x=>b(x)?.trackChange??NaN},{id:r("stateTravelOuter"),group:`${t} package`,label:"outer wheel travel at a state",unit:"mm",scale:10,scope:e,cost:"cheap",reads:"state",acrossStates:"max",read:(x,M)=>as(x,M,F=>F.corners[$c(e,F.outer)].travel)},{id:r("stateTravelInner"),group:`${t} package`,label:"inner wheel travel at a state",unit:"mm",scale:10,scope:e,cost:"cheap",reads:"state",acrossStates:"min",read:(x,M)=>as(x,M,F=>F.corners[$c(e,tw(F.outer))].travel)},{id:r("damperStroke"),group:`${t} package`,label:"damper stroke over the travel",unit:"mm",scale:20,scope:e,cost:"cheap",unavailable:c,read:x=>c(x.car)?NaN:Bc(n(x,M=>M.metrics.damperLength).y),curve:x=>{if(c(x.car))return null;let M=n(x,F=>F.metrics.damperLength);return M.x.length?{key:r("damperStroke"),title:`${t} damper length vs travel`,xLabel:"travel [mm]",yLabel:"length [mm]",...M}:null}}];e==="front"&&R.push({id:r("camberPerSteer"),group:`${t} camber & toe`,label:"camber change with steer",unit:"\xB0/\xB0",scale:.05,scope:"front",cost:"readout",read:x=>h(x)?.camberPerSteer??NaN},{id:r("steerJacking"),group:`${t} upright`,label:"corner rise per degree of steer",unit:"mm/\xB0",scale:.05,scope:"front",cost:"readout",read:x=>h(x)?.steerJacking??NaN}),e==="front"?R.push({id:r("antiDive"),group:`${t} anti geometry`,label:"anti-dive",unit:"%",scale:20,scope:"front",cost:"readout",read:x=>x.readout(Vc)?.front.antiDive??NaN}):R.push({id:r("antiSquat"),group:`${t} anti geometry`,label:"anti-squat (driving)",unit:"%",scale:20,scope:"rear",cost:"readout",read:x=>x.readout(Vc)?.rear.antiSquat??NaN},{id:r("antiLift"),group:`${t} anti geometry`,label:"anti-lift (braking)",unit:"%",scale:20,scope:"rear",cost:"readout",read:x=>x.readout(Vc)?.rear.antiLift??NaN});let k=x=>{let M=x.slice(t.length+1);return M.charAt(0).toUpperCase()+M.slice(1)};return[...new Set(R.map(x=>x.group))].flatMap(x=>R.filter(M=>M.group===x)).map(x=>({...x,quantity:`${t} \xB7 ${k(x.group)}`}))}function nw(e,t){let r=e.steer();if(!r)return NaN;let n=r.filter(a=>Number.isFinite(a.ackermannPct)&&a.inner>.3&&a.outer>.3);return n.length?n.reduce((a,s)=>t==="centre"?s.inner<a.inner?s:a:s.inner>a.inner?s:a).ackermannPct:NaN}var GV=[{id:"kin.front.ackermannCentre",group:"Steering",label:"Ackermann near centre",unit:"%",scale:25,scope:"front",cost:"cheap",read:e=>nw(e,"centre"),curve:e=>{let t=e.steer();if(!t)return null;let r=t.filter(n=>Number.isFinite(n.ackermannPct)&&n.inner>.3&&n.outer>.3);return r.length?{key:"kin.front.ackermann",title:"Ackermann vs steer",xLabel:"inner wheel steer [\xB0]",yLabel:"Ackermann [%]",x:r.map(n=>n.inner),y:r.map(n=>n.ackermannPct)}:null}},{id:"kin.front.ackermannLock",group:"Steering",label:"Ackermann at lock",unit:"%",scale:25,scope:"front",cost:"cheap",read:e=>nw(e,"lock")},{id:"kin.front.lockInner",group:"Steering",label:"inner wheel angle at full rack",unit:"\xB0",scale:5,scope:"front",cost:"cheap",read:e=>{let t=e.steer();return t?.length?Math.max(...t.map(r=>r.inner)):NaN}}],KV=[{id:"kin.car.trackFront",group:"Whole car",label:"front track",unit:"mm",scale:50,scope:"front",cost:"geometry",read:e=>2*e.car.vehicle.front.hardpoints.wheelCenter[1]},{id:"kin.car.trackRear",group:"Whole car",label:"rear track",unit:"mm",scale:50,scope:"rear",cost:"geometry",read:e=>2*e.car.vehicle.rear.hardpoints.wheelCenter[1]},{id:"kin.car.stateRoll",group:"Whole car",label:"body roll at a state",unit:"\xB0",scale:1,scope:"car",cost:"cheap",reads:"state",acrossStates:"max",read:(e,t)=>as(e,t,r=>Math.abs(r.rollDeg))},{id:"kin.car.wheelbaseChange",group:"Whole car",label:"wheelbase change at full bump",unit:"mm",scale:2,scope:"car",cost:"readout",read:e=>{let t=e.readoutAtTravel("front",e.envelope.travelMax),r=e.readoutAtTravel("rear",e.envelope.travelMax);return t&&r?t.longitudinal-r.longitudinal:NaN}}],ry=[...rw("front"),...rw("rear"),...GV,...KV];var HV={front:"Front",rear:"Rear"};function aw(e){return e.chassis?.boxes.length?null:"This suspension has no mockup volumes to keep its parts out of; draw one under Kinematics \u203A Chassis"}function ow(e){let t=HV[e],r=s=>`kin.${e}.${s}`,n=e==="front"?"over the travel and the rack":"over the travel",o=(s,i)=>{let c=s.keepOuts(e);return c?i(c)??NaN:NaN},a={group:`${t} keep-outs`,quantity:`${t} \xB7 Keep-outs`,scope:e,cost:"readout"};return[{...a,id:r("chassisClearance"),label:`least clearance to the chassis volumes ${n}`,unit:"mm",scale:5,unavailable:s=>aw(s.vehicle),read:s=>o(s,i=>i.chassis?.distance)},{...a,id:r("ballJointAngle"),label:`largest ball-joint angle ${n}`,unit:"\xB0",scale:1,read:s=>o(s,i=>i.ballJoint?.angle)},{...a,id:r("rodEndAngle"),label:`largest rod-end angle ${n}`,unit:"\xB0",scale:1,read:s=>o(s,i=>i.rodEnd?.angle)}]}var ny=[...ow("front"),...ow("rear")];var uw={front:"Front",rear:"Rear"},sw=e=>wo("side",e),zV=e=>wo("drive",e)&&wo("brake",e)?"neither brakes nor drives":null;function YV(e,t,r,n){let o=os(e,t,r),a=o?e.tyreAt(o):null;return a?n(a):NaN}function ss(e,t){let r={...e,read:(n,o)=>YV(n,r,o,t)};return r}var iw=e=>e?100*e.lossCamber:NaN,cw=e=>e&&!e.lifted?e.camber-e.wants:NaN;function lw(e){let t=uw[e],r=s=>`tyre.${e}.${s}`,n={group:`${t} tyre`,quantity:`${t} \xB7 Tyre`,scope:e,cost:"cheap",reads:"state",acrossStates:"mean"},o={...n,appliesAt:sw,unavailable:s=>ap(s.params,e)},a=[ss({...o,id:r("camberErrorOuter"),label:"camber error at the outer wheel",unit:"\xB0",scale:.5},s=>cw(s.side(e)?.wheels[0])),ss({...o,id:r("camberErrorInner"),label:"camber error at the inner wheel",unit:"\xB0",scale:.5},s=>cw(s.side(e)?.wheels[1])),ss({...o,id:r("sideLossCamber"),label:"side grip lost to camber",unit:"%",scale:1},s=>iw(s.side(e))),ss({...n,appliesAt:sw,id:r("sideLossToe"),label:"side grip lost to the toe split",unit:"%",scale:1},s=>100*s.toeLoss(e)),ss({...n,appliesAt:zV,unavailable:s=>S0(s.params,e),id:r("longLossCamber"),label:"drive and brake grip lost to camber",unit:"%",scale:1},s=>iw(s.long(e)))];return e==="front"&&a.push(ss({...n,appliesAt:s=>wo("ackermann",s),id:r("ackermannError"),label:"Ackermann against the tyre",unit:"%",scale:25},s=>s.ackermann())),a}var oy=[...lw("front"),...lw("rear")],WV=/^tyre\.(front|rear)\.(camberErrorOuter|camberErrorInner|sideLossCamber|longLossCamber)$/;function ay(e,t){let r=new Map,n=a=>a.name.charAt(0).toLowerCase()+a.name.slice(1),o=a=>`${a>0?"+":a<0?"\u2212":""}${Math.abs(a).toFixed(1)}\xB0`;for(let{m:a,at:s}of t){let i=WV.exec(a.id);if(!i)continue;let c=i[1],l=i[2]==="longLossCamber",u=s?.stateId==="*"?e.states.filter(m=>!a.appliesAt?.(m)):[os(e,a,s)].filter(m=>!!m);for(let m of u){let f=`${c}|${m.id}|${l}`;if(r.has(f))continue;let p=e.tyreAt(m),d=p?l?p.long(c):p.side(c):null;if(!d)continue;let{lo:h,hi:b,stated:g}=d.range,y=g?`the ${o(h)} \u2026 ${o(b)} its data covers`:`the \xB1${b.toFixed(0)}\xB0 read without a stated range`,R=M=>l?M===0?"left":"right":M===0?"outer":"inner",k=d.wheels.findIndex(M=>M.atEdge),v=d.wheels.findIndex(M=>M.outside&&!M.lifted),x=[];k>=0&&x.push(`the ${uw[c].toLowerCase()} ${R(k)} tyre wants ${o(d.wheels[k].wants)}, the edge of ${y}, and may want more`),v>=0&&x.push(`the ${R(v)} wheel has ${o(d.wheels[v].camber)}, past it, and is read at ${o(d.wheels[v].read)}`),x.length&&r.set(f,`In the ${n(m)} ${x.join("; ")}.`)}}return[...r.values()]}function sy(e,t){let r=e.appliesAt?.(t);return r?`is read at ${t.name}, which ${r}`:null}var jV={front:"Front",rear:"Rear"};function UV(e,t,r,n){let o=os(e,t,r),a=o?e.platformAt(o):null;return(a?n(a):null)??NaN}function Ut(e,t){let r={...e,read:(n,o)=>UV(n,r,o,t)};return r}var iy={cost:"cheap",reads:"state"},XV={unavailable:e=>kp(e.params)};function mw(e){let t=jV[e],r=o=>`platform.${e}.${o}`,n={...iy,group:`${t} platform`,quantity:`${t} \xB7 Platform`,scope:e};return[Ut({...n,id:r("rideHeight"),label:"ride height at a state",unit:"mm",scale:5,acrossStates:"min"},o=>o[e].height),Ut({...n,id:r("toBumpStop"),label:"travel left to the bump stop",unit:"mm",scale:5,acrossStates:"min",unavailable:o=>Ic(o.vehicle,o.params,e,"bump")},o=>o[e].toBump),Ut({...n,id:r("toDroopStop"),label:"travel left to the droop stop",unit:"mm",scale:5,acrossStates:"min",unavailable:o=>Ic(o.vehicle,o.params,e,"droop")},o=>o[e].toDroop)]}var wp={...iy,group:"Platform",scope:"car"},Gc={...iy,...XV,group:"Aero platform",groupShort:"Aero",scope:"car"},cy=[...mw("front"),...mw("rear"),Ut({...wp,id:"platform.rake",label:"rake at a state",unit:"\xB0",scale:.2,acrossStates:"span"},e=>e.rakeDeg),Ut({...wp,id:"platform.pitch",label:"pitch at a state",unit:"\xB0",scale:.2,acrossStates:"max"},e=>e.pitchDeg),Ut({...wp,id:"platform.roll",label:"body roll at a state",unit:"\xB0",scale:.2,acrossStates:"max"},e=>e.rollDeg),Ut({...wp,id:"platform.groundClearance",label:"ground clearance at a state",unit:"mm",scale:5,acrossStates:"min",unavailable:e=>j0(e.vehicle)},e=>e.clearance?.height),Ut({...Gc,id:"platform.balance",label:"balance at a state",unit:"%",scale:1,acrossStates:"span"},e=>e.aero?.balance),Ut({...Gc,id:"platform.clA",label:"downforce Cl\xB7A at a state",unit:"m\xB2",scale:.1,acrossStates:"mean"},e=>e.aero?.clA),Ut({...Gc,id:"platform.cdA",label:"drag Cd\xB7A at a state",unit:"m\xB2",scale:.05,acrossStates:"mean"},e=>e.aero?.cdA),Ut({...Gc,id:"platform.dataMargin",label:"margin to the model\u2019s data",unit:"mm",scale:5,acrossStates:"min"},e=>e.aero?.dataMargin),Ut({...Gc,id:"platform.loopMargin",label:"aero-elastic margin, 1 \u2212 loop gain",unit:"-",scale:.1,acrossStates:"min"},e=>e.aero?.loopMargin)];var pw={understeer:"operating",yawFreq:"speed",yawZeta:"speed",yawStiffness:"operating",steeringTorque:"operating",steeringTorqueGradient:"operating"};function at(e,t,r,n="cheap"){let o=qb[e];if(!o)throw new Error(`no DYN_METRIC "${e}"`);return{id:`dyn.${e}`,group:t,label:o.label,unit:o.unit,scale:r,scope:"car",cost:n,...pw[e]?{reads:pw[e]}:{},read:(a,s)=>{let i=a.dynInput(),c=a.dynCtx(s);return i&&c?o.compute(i,c):NaN}}}var qV=[at("understeer","Handling \u2014 balance",.1),at("tlltdFront","Handling \u2014 balance",5),at("rollStiffFront","Handling \u2014 balance",5)],QV=[at("yawFreq","Handling \u2014 response",.5),at("yawZeta","Handling \u2014 response",.2),at("stabilitySpeed","Handling \u2014 response",50),at("yawStiffness","Handling \u2014 response",2e4,"trim")],ZV=[at("steeringTorque","Steering feel",1,"trim"),at("steeringTorqueGradient","Steering feel",2,"trim")],JV=[at("rollGradient","Ride & body",.5),at("pitchGradient","Ride & body",.5),at("rideFreqFront","Ride & body",.5),at("rideFreqRear","Ride & body",.5),at("rollFreq","Ride & body",.5),at("pitchFreq","Ride & body",.5),at("zetaFront","Ride & body",.2),at("zetaRear","Ride & body",.2)],e3=[{id:"dyn.reserveStabil",group:"What the car has left",label:"Yaw stability reserve",unit:"N\xB7m",scale:200,scope:"car",cost:"trim",reads:"operating",read:(e,t)=>e.reserves("operating",t)?.stabil??NaN},{id:"dyn.reserveAgil",group:"What the car has left",label:"Yaw agility reserve",unit:"N\xB7m",scale:200,scope:"car",cost:"trim",reads:"operating",read:(e,t)=>e.reserves("operating",t)?.agil??NaN},{id:"dyn.limitBalance",group:"What the car has left",label:"Limit balance (+US / \u2212OS)",unit:"-",scale:.5,scope:"car",cost:"trim",reads:"speed",read:(e,t)=>e.reserves("limit",t)?.rel??NaN}],t3=[{id:"dyn.ymdMaxAy",group:"Yaw-moment diagram",label:"Max lateral acceleration",unit:"g",scale:.2,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymd(t)?.maxAy??NaN},{id:"dyn.ymdStability",group:"Yaw-moment diagram",label:"Stability \u2202CN/\u2202\u03B2 at the origin",unit:"1/rad",scale:5,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymd(t)?.stability??NaN},{id:"dyn.ymdControl",group:"Yaw-moment diagram",label:"Control \u2202CN/\u2202\u03B4 at the origin",unit:"1/rad",scale:.5,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymd(t)?.control??NaN},{id:"dyn.trimAy",group:"Yaw-moment diagram",label:"Trim limit \u2014 the fastest corner it can hold",unit:"g",scale:.2,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.ay??NaN},{id:"dyn.trimBeta",group:"Yaw-moment diagram",label:"Body slip at the trim limit",unit:"\xB0",scale:2,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.betaDeg??NaN},{id:"dyn.trimDelta",group:"Yaw-moment diagram",label:"Steer at the trim limit",unit:"\xB0",scale:2,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.deltaDeg??NaN},{id:"dyn.trimControlFrac",group:"Yaw-moment diagram",label:"Control left at the trim limit",unit:"-",scale:.25,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.controlFrac??NaN},{id:"dyn.trimStiffnessFrac",group:"Yaw-moment diagram",label:"Yaw stiffness left at the trim limit",unit:"-",scale:.25,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.stiffnessFrac??NaN}],ly=[...qV,...QV,...ZV,...JV,...e3,...t3];function r3(e,t){let r=e.lap(t),n=e.course(t);if(!r||!n)return NaN;let o=n.track.ds,a=0,s=0;for(let i=0;i<r.v.length-1;i++){let c=o[i]??0,l=.5*(r.v[i]+r.v[i+1]);c>0&&l>0&&(a+=c,s+=c/l)}return s>0?a/s:NaN}var uy=[{id:"lap.time",group:"Lap & manoeuvre",label:"Time",unit:"s",scale:.1,scope:"car",cost:"lap",reads:"course",across:"sum",read:(e,t)=>e.lap(t)?.laptime??NaN},{id:"lap.vMean",group:"Lap & manoeuvre",label:"Mean speed",unit:"km/h",scale:2,scope:"car",cost:"lap",reads:"course",across:"harmonic",read:(e,t)=>r3(e,t)*3.6},{id:"lap.vMin",group:"Lap & manoeuvre",label:"Minimum speed",unit:"km/h",scale:2,scope:"car",cost:"lap",reads:"course",across:"min",read:(e,t)=>{let r=e.lap(t);return r?Math.min(...r.v)*3.6:NaN}},{id:"lap.vMax",group:"Lap & manoeuvre",label:"Maximum speed",unit:"km/h",scale:5,scope:"car",cost:"lap",reads:"course",across:"max",read:(e,t)=>{let r=e.lap(t);return r?Math.max(...r.v)*3.6:NaN}},{id:"lap.ayPeak",group:"Lap & manoeuvre",label:"Peak lateral acceleration",unit:"g",scale:.1,scope:"car",cost:"lap",reads:"course",across:"max",read:(e,t)=>{let r=e.lap(t);return r?Math.max(...r.ay.map(Math.abs))/9.81:NaN}},{id:"lap.minStabil",group:"What the car had left",label:"Worst stability reserve",unit:"N\xB7m",scale:50,scope:"car",cost:"lap",reads:"course",across:"min",read:(e,t)=>e.lapReserve(t)?.minStabil??NaN},{id:"lap.understeerFrac",group:"What the car had left",label:"Lap fraction front-limited",unit:"-",scale:.1,scope:"car",cost:"lap",reads:"course",across:"distance",read:(e,t)=>e.lapReserve(t)?.understeerFrac??NaN},{id:"lap.beyondFrac",group:"What the car had left",label:"Beyond the tyre ellipse \u2014 a health warning, not a target",unit:"-",scale:.05,scope:"car",cost:"lap",reads:"course",across:"distance",read:(e,t)=>e.lapReserve(t)?.beyondFrac??NaN}];function n3(e,t){let r=/^(.*?)\s*\(([^)]+)\)\s*$/.exec(e);return r?{label:r[1],unit:r[2]}:{label:e,unit:t?"s":""}}function o3(e){return e==="s"||e==="kWh"?.1:e==="km/h"?2:1}var dw=new WeakMap;function Cp(e){let t=dw.get(e);return t||(t=e.metrics.filter(rl).map(r=>{let{label:n,unit:o}=n3(r.label,r.format==="time");return{id:`event.${e.id}.${r.key}`,group:`Events \xB7 ${e.label}`,groupShort:"Events",label:n,unit:o,scale:o3(o),scope:"car",cost:"session",read:a=>a.session(e.id)?.[r.key]??NaN}}),dw.set(e,t),t)}var my=ja.flatMap(Cp);var Tp=[...ry,...ny,...oy,...cy,...ly,...uy,...my],is=Object.fromEntries(Tp.map(e=>[e.id,e]));var fw={all:Tp,byId:is},hw=new WeakMap;function rr(e=[]){if(e.length===0)return fw;let t=hw.get(e);if(t)return t;let r=vg(e).filter(n=>!Ua(n.id)).flatMap(Cp);return t=r.length?{all:[...Tp,...r],byId:{...is,...Object.fromEntries(r.map(n=>[n.id,n]))}}:fw,hw.set(e,t),t}var Kc=180/Math.PI,cs=Math.PI/180,s3=.2;function Pp(e,t){let r=H(t,e);return q(r[0]<0?Gd(r):r)}var Lp=e=>({side:Math.atan2(e[2],e[0])*Kc,plan:Math.atan2(e[1],e[0])*Kc}),Dp=(e,t)=>q([1,Math.tan(t*cs),Math.tan(e*cs)]),Hc=e=>Math.abs(e[0])>=s3,Ep=(e,t)=>Math.atan(t/Math.max(e,1))*Kc,Ip=(e,t)=>Math.tan(t*cs)*Math.max(e,1);var Ln=["side","plan","clock","len"],Ot={uca:{fore:"ucaFront",aft:"ucaRear",ball:"uprightUpper"},lca:{fore:"lcaFront",aft:"lcaRear",ball:"uprightLower"}},zc={uca:"upper arm",lca:"lower arm"},i3=1,bw=(e,t)=>Pp(e[Ot[t].fore],e[Ot[t].aft]);function gw(e){let t=q(H($d,U(e,X($d,e))));return{e1:t,e2:ae(e,t)}}function py(e,t){let r=bw(e,t);if(!Hc(r))return`the ${zc[t]}'s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it`;let n=Ot[t],o=ln(e[n.ball],e[n.fore],r);return Math.hypot(...H(o,e[n.ball]))>=i3?null:`the ${zc[t]}'s ball joint sits on its own pivot axis, so the arm has no length to swing on`}function rn(e,t){let r=Ot[t],n=e[r.ball],o=bw(e,t),a=ln(n,e[r.fore],o),s=H(a,n),i=Math.hypot(s[0],s[1],s[2]),{e1:c,e2:l}=gw(o),u=i>0?U(s,1/i):c;return{...Lp(o),clock:Math.atan2(X(u,l),X(u,c))*Kc,len:i,sFront:X(H(e[r.fore],a),o),sRear:X(H(e[r.aft],a),o)}}function dy(e,t){let r=Dp(e.side,e.plan),{e1:n,e2:o}=gw(r),a=ee(U(n,Math.cos(e.clock*cs)),U(o,Math.sin(e.clock*cs))),s=ee(t,U(a,e.len));return{fore:ee(s,U(r,e.sFront)),aft:ee(s,U(r,e.sRear))}}function yw(e,t,r,n){let o=Ot[t],a={...rn(e,t),[r]:n},{fore:s,aft:i}=dy(a,e[o.ball]);return{...e,[o.fore]:s,[o.aft]:i}}function xw(e,t){return t==="clock"?e.len:Math.abs(e.sFront-e.sRear)/2}function _p(e,t,r){return t==="len"?r:Ep(xw(e,t),r)}function fy(e,t,r){return t==="len"?r:Ip(xw(e,t),r)}var Do=["side","plan","atY","atZ"],Sr={fore:"rockerPivotA",aft:"rockerPivotB"},c3=5,Rw=e=>Pp(e.rockerPivotA,e.rockerPivotB);function ls(e){return Math.hypot(...H(e.rockerPivotB,e.rockerPivotA))<c3?"the rocker\u2019s two pivots are the same point, so there is no axis to describe":Hc(Rw(e))?null:"the rocker\u2019s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it"}function Dn(e){let t=Rw(e),r=Hc(t)?t:[1,0,0],n=e.rockerPivotA,o=ee(n,U(r,-n[0]/r[0]));return{...Lp(r),atY:o[1],atZ:o[2],sA:X(H(n,o),r),sB:X(H(e.rockerPivotB,o),r)}}function hy(e){let t=Dp(e.side,e.plan),r=[0,e.atY,e.atZ];return{a:ee(r,U(t,e.sA)),b:ee(r,U(t,e.sB))}}function vw(e,t,r){if(ls(e))return e;let{a:n,b:o}=hy({...Dn(e),[t]:r});return{...e,rockerPivotA:n,rockerPivotB:o}}var kw=e=>Math.abs(e.sA-e.sB)/2;function by(e,t,r){return t==="side"||t==="plan"?Ep(kw(e),r):r}function gy(e,t,r){return t==="side"||t==="plan"?Ip(kw(e),r):r}var or={front:"Front",rear:"Rear"},nr=["x","y","z"],Be=(e,t)=>t==="front"?e.front:e.rear,Yc=(e,t,r)=>t==="front"?{...e,front:r}:{...e,rear:r},Mw=[{kind:"inboard",keys:[{key:"ucaFront",label:"UCA front pivot"},{key:"ucaRear",label:"UCA rear pivot"},{key:"lcaFront",label:"LCA front pivot"},{key:"lcaRear",label:"LCA rear pivot"},{key:"tieInner",label:"tie/toe link inner"}]},{kind:"outboard",keys:[{key:"uprightUpper",label:"upper ball joint"},{key:"uprightLower",label:"lower ball joint"},{key:"tieOuter",label:"tie/toe link outer"},{key:"wheelCenter",label:"wheel centre"}]},{kind:"actuation",keys:[{key:"pushrodOuter",label:"push/pull rod outer"},{key:"rockerPivotA",label:"rocker pivot A"},{key:"rockerPivotB",label:"rocker pivot B"},{key:"rockerToPushrod",label:"rocker \u2014 rod end"},{key:"rockerToDamper",label:"rocker \u2014 damper end"},{key:"damperChassis",label:"damper chassis mount"}]}],Sw={damperChassis:"strut top mount",pushrodOuter:"strut lower mount"},Eo=30;function l3(e){let t=[];for(let r of["front","rear"]){let n=Be(e.vehicle,r).config.layout==="mcpherson";for(let o of Mw)for(let{key:a,label:s}of o.keys){let i=n&&Sw[a]||s;for(let c=0;c<3;c++)t.push({id:`hp.${r}.${a}.${nr[c]}`,group:`${or[r]} hardpoints \u2014 ${o.kind}`,label:`${i} ${nr[c]}`,scope:or[r],unit:"mm",defaultSpan:Eo,read:l=>Be(l.vehicle,r).hardpoints[a][c],write:(l,u)=>{let m=Be(l.vehicle,r),f=[...m.hardpoints[a]];f[c]=u;let p={...m.hardpoints,[a]:f};return{...l,vehicle:Yc(l.vehicle,r,{...m,hardpoints:p})}}})}}return t}var u3={side:"axis side-view angle",plan:"axis plan-view angle",clock:"arm clock angle",len:"effective arm length"},m3={side:"\xB0",plan:"\xB0",clock:"\xB0",len:"mm"};function p3(e){let t=[];for(let r of["front","rear"]){let n=Be(e.vehicle,r).config.layout==="mcpherson";for(let o of["uca","lca"]){let a=Be(e.vehicle,r).hardpoints,s=py(a,o)?null:rn(a,o);for(let i of Ln)t.push({id:`arm.${r}.${o}.${i}`,group:`${or[r]} ${n?"arm axes":"wishbone axes"}`,label:`${zc[o]} \u2014 ${u3[i]}`,scope:or[r],unit:m3[i],defaultSpan:s?_p(s,i,Eo):Eo,read:c=>rn(Be(c.vehicle,r).hardpoints,o)[i],write:(c,l)=>{let u=Be(c.vehicle,r),m=yw(u.hardpoints,o,i,l);return{...c,vehicle:Yc(c.vehicle,r,{...u,hardpoints:m})}}})}}return t}var d3={side:"pivot axis side-view angle",plan:"pivot axis plan-view angle",atY:"pivot axis outboard, at the wheel-centre plane",atZ:"pivot axis height, at the wheel-centre plane"},f3={side:"\xB0",plan:"\xB0",atY:"mm",atZ:"mm"};function h3(e){let t=[];for(let r of["front","rear"]){let n=Be(e.vehicle,r).hardpoints,o=ls(n)?null:Dn(n);for(let a of Do)t.push({id:`rocker.${r}.${a}`,group:`${or[r]} rocker axis`,label:`rocker \u2014 ${d3[a]}`,scope:or[r],unit:f3[a],defaultSpan:o?by(o,a,Eo):Eo,read:s=>Dn(Be(s.vehicle,r).hardpoints)[a],write:(s,i)=>{let c=Be(s.vehicle,r),l=vw(c.hardpoints,a,i);return{...s,vehicle:Yc(s.vehicle,r,{...c,hardpoints:l})}}})}return t}var Np={front:"heaveFrontDesign",rear:"heaveRearDesign"},yy={front:"arbFrontDesign",rear:"arbRearDesign"};function b3(e,t){return{heave:e.config.actuation==="decoupled"?"heave element":"third spring",roll:t?.design.kind==="coil"?"roll shock":"anti-roll bar"}}var Op=e=>/^(heave|roll)\.(front|rear)\.(outer|inner|anchor)\.[xyz]$/.test(e);function g3(e){let t=[];for(let r of["front","rear"]){let n=Be(e.vehicle,r),o=e.params[Np[r]],a=e.params[yy[r]],s=b3(n,a),i=d=>d.params[Np[r]],c=d=>d.params[yy[r]],l=(d,h)=>({...d,params:{...d.params,[Np[r]]:h}}),u=(d,h)=>({...d,params:{...d.params,[yy[r]]:h}}),m={group:`${or[r]} heave & roll elements`,scope:or[r]},f=(d,h,b,g,y)=>{for(let R of b)t.push({...m,id:`${d}.${nr[R]}`,label:`${h} ${nr[R]}`,unit:"mm",defaultSpan:Eo,read:k=>g(k)[R],write:(k,v)=>{let x=[...g(k)];return x[R]=v,y(k,x)}})},p=(d,h,b,g,y)=>{t.push({...m,id:d,label:h,unit:"N/mm",defaultSpan:Math.max(5,b*.4),read:g,write:y})};if(o?.design.kind==="coil"){if(o.linkage){let d=b=>i(b).linkage;f(`heave.${r}.outer`,`${s.heave} eye`,[0,1,2],b=>d(b).outer,(b,g)=>l(b,{...i(b),linkage:{...d(b),outer:g}})),o.linkage.mount?.kind==="chassis"&&f(`heave.${r}.anchor`,`${s.heave} chassis anchor`,[0,2],b=>d(b).mount.anchor,(b,g)=>l(b,{...i(b),linkage:{...d(b),mount:{kind:"chassis",anchor:g}}}))}if(typeof o.design.rate=="number"){let d=h=>i(h).design;p(`heave.${r}.rate`,`${s.heave} spring rate (@element)`,o.design.rate,h=>d(h).rate,(h,b)=>l(h,{...i(h),design:{...d(h),rate:b}}))}}if(a&&a.design.kind!=="none"){if(a.linkage&&a.design.kind!=="direct"){let h=R=>c(R).linkage,b=pn(n,a.linkage,a.design.kind),[g,y]=b?["left arm eye","right arm eye"]:["drop-link pickup","arm tip"];f(`roll.${r}.outer`,`${s.roll} ${g}`,[0,1,2],R=>h(R).outer,(R,k)=>u(R,{...c(R),linkage:{...h(R),outer:k}})),f(`roll.${r}.inner`,`${s.roll} ${y}`,[0,1,2],R=>h(R).inner,(R,k)=>u(R,{...c(R),linkage:{...h(R),inner:k}}))}let d=a.design;if(d.kind==="coil"&&typeof d.rate=="number"){let h=b=>c(b).design;p(`roll.${r}.rate`,`${s.roll} spring rate (@element)`,d.rate,b=>h(b).rate,(b,g)=>u(b,{...c(b),design:{kind:"coil",rate:g}}))}else d.kind==="direct"&&p(`roll.${r}.wheelRate`,`${s.roll} rate (@wheel)`,d.wheelRate,h=>c(h).design.wheelRate,(h,b)=>u(h,{...c(h),design:{kind:"direct",wheelRate:b}}))}}return t}var y3=[{axle:"front",field:"springRate",group:"Springs & bars",label:"spring rate (@spring)",unit:"N/mm",fallback:35,span:e=>Math.max(5,e*.4)},{axle:"rear",field:"springRate",group:"Springs & bars",label:"spring rate (@spring)",unit:"N/mm",fallback:40,span:e=>Math.max(5,e*.4)},{axle:"front",field:"rackTravel",group:"Steering",label:"rack travel from centre",unit:"mm",fallback:35,span:()=>15,frontOnly:!0},{axle:"front",field:"rackRatio",group:"Steering",label:"rack per steering-wheel turn",unit:"mm/rev",fallback:55,span:()=>15,frontOnly:!0},{axle:"front",field:"loadedRadius",group:"Wheel & tyre",label:"loaded radius",unit:"mm",fallback:228,span:()=>15},{axle:"rear",field:"loadedRadius",group:"Wheel & tyre",label:"loaded radius",unit:"mm",fallback:228,span:()=>15}];function x3(e){let t=[];for(let r of["front","rear"]){let n=Be(e.vehicle,r).compliance;if(!n)continue;let o=(a,s,i,c)=>{let l=i(n);l===void 0||!(l>0)||!Number.isFinite(l)||t.push({id:`kc.${r}.${a}`,group:"Compliance",label:s,scope:or[r],unit:"N/mm",defaultSpan:Math.max(500,l*.4),read:u=>i(Be(u.vehicle,r).compliance??{})??l,write:(u,m)=>{let f=Be(u.vehicle,r),p={...f,compliance:c(f.compliance??{},Math.max(1,m))};return{...u,vehicle:Yc(u.vehicle,r,p)}}})};for(let a of["ucaFront","ucaRear","lcaFront","lcaRear","tieRod","pushRod"])o(`link.${a}`,`${R3[a]} (link)`,s=>s.links?.[a],(s,i)=>({...s,links:{...s.links,[a]:i}}));for(let a of["ucaFront","ucaRear","lcaFront","lcaRear","tieInner","topMount"])o(`bush.${a}`,`${v3[a]} (bushing)`,s=>s.bushings?.[a],(s,i)=>({...s,bushings:{...s.bushings,[a]:i}}));r==="front"&&o("rack","rack to housing",a=>a.rack,(a,s)=>({...a,rack:s}))}return t}var R3={ucaFront:"UCA front leg",ucaRear:"UCA rear leg",lcaFront:"LCA front leg",lcaRear:"LCA rear leg",tieRod:"tie rod",pushRod:"push/pull rod"},v3={ucaFront:"UCA front pickup",ucaRear:"UCA rear pickup",lcaFront:"LCA front pickup",lcaRear:"LCA rear pickup",tieInner:"tie-rod inner",topMount:"strut top mount"};function k3(){return y3.map(e=>({id:`cfg.${e.axle}.${e.field}`,group:e.group,label:e.label,scope:or[e.axle],unit:e.unit,defaultSpan:e.span(e.fallback),read:t=>Be(t.vehicle,e.axle).config[e.field]??e.fallback,write:(t,r)=>{let n=Be(t.vehicle,e.axle),o={...n,config:{...n.config,[e.field]:r}};return{...t,vehicle:Yc(t.vehicle,e.axle,o)}}}))}function M3(e){let t=jn(e.params.steeringSystem);if(!t.enabled)return[];let r=(n,o,a,s,i)=>({id:`steeringSystem.${n}`,group:"Steering",label:o,unit:a,defaultSpan:s,read:c=>jn(c.params.steeringSystem)[n],write:(c,l)=>({...c,params:{...c.params,steeringSystem:jn({...c.params.steeringSystem,enabled:!0,[n]:i(l)})}})});return[r("roadFeedbackGain","road feedback gain","\xD7",Math.max(.1,.25*t.roadFeedbackGain),n=>Math.min(2,Math.max(0,n))),r("turnInFrictionNm","turn-in friction","N\xB7m",Math.max(.1,.5*t.turnInFrictionNm),n=>Math.max(0,n))]}function S3(e){let t=_i(e.params),r=[];for(let n of["front","rear"]){if(t[n]!=="diff")continue;let o=co(e.params.driveline?.[n]);if(o?.kind!=="clutch"&&o?.kind!=="torsen")continue;let a=(s,i)=>{let c=qu[`${n}.${s}`];return{id:`driveline.${n}.${s}`,group:"Differential",label:c.label.charAt(0).toLowerCase()+c.label.slice(1),scope:or[n],unit:c.unit===": 1"?"":c.unit??"",defaultSpan:i,read:l=>co(l.params.driveline?.[n])?.[s],write:(l,u)=>({...l,params:{...l.params,driveline:Xu({...l.params.driveline,[n]:{...l.params.driveline?.[n],[s]:u}})}})}};o.kind==="clutch"?r.push(a("preloadNm",Math.max(5,.2*o.preloadNm)),a("rampDriveDeg",5),a("rampCoastDeg",5)):r.push(a("tbrDrive",Math.max(.25,.2*o.tbrDrive)),a("tbrCoast",Math.max(.25,.2*o.tbrCoast)))}return r}function A3(e){if(hu(e.params)!=="hydraulic")return[];let t=[{id:"brakeSetup.barFront",group:"Brakes",label:`${Wh("barFront").toLowerCase()}, front share`,unit:"-",defaultSpan:.05,read:a=>Vr(a.params.brakeSetup).barFront,write:(a,s)=>({...a,params:{...a.params,brakeSetup:Vr({...Vr(a.params.brakeSetup),barFront:s})}})}];if(!e.params.brakeModel)return t;let r=pr(e.params.brakeModel),n=(a,s)=>s.circuit?a[s.circuit][s.key]:a[s.key],o=(a,s,i)=>({id:`brakeModel.${a.circuit?`${a.circuit}.`:""}${String(a.key)}`,group:"Brakes",label:Yh(a.circuit?`${a.circuit}.${String(a.key)}`:a.key),unit:s,defaultSpan:i,read:c=>n(pr(c.params.brakeModel),a),write:(c,l)=>{let u=pr(c.params.brakeModel),m=a.circuit?{...u,[a.circuit]:{...u[a.circuit],[a.key]:l}}:{...u,[a.key]:l};return{...c,params:{...c.params,brakeModel:pr(m)}}}});return t.push(o({key:"masterFrontMm"},"mm",1.5),o({key:"masterRearMm"},"mm",1.5),o({key:"pedalRatio"},"-",.5),o({key:"pistonDiaMm",circuit:"front"},"mm",2),o({key:"pistonDiaMm",circuit:"rear"},"mm",2),o({key:"effRadiusMm",circuit:"front"},"mm",10),o({key:"effRadiusMm",circuit:"rear"},"mm",10)),r.valve!=="none"&&t.push(o({key:"valveKneeBar"},"bar",5)),r.valve==="proportioning"&&t.push(o({key:"valveSlope"},"-",.1)),t}var Aw=e=>!!e&&typeof e=="object"&&"value"in e&&"label"in e;function Fw(e){let t={...e};for(let r of Object.keys(t)){let n=t[r];Aw(n)&&(t[r]={...n})}return t}function F3(e){let t=[];for(let r of dM(e))for(let n of r.rows){let o=Math.abs(n.value);t.push({id:`param.${n.key}`,group:r.title,label:n.label,unit:n.unit,defaultSpan:o>0?o*.2:1,read:a=>{let s=a.params[n.key];return Aw(s)?s.value:NaN},write:(a,s)=>{let i=Fw(a.params);return tm(i,n.label,s),{...a,params:i}}})}return t}function ww(e){let t={};for(let s of["front","rear"]){if(!Be(e.vehicle,s).measured)continue;let c="this axle is described by measured curves, so its linkage is not solved";for(let l of Mw)for(let{key:u}of l.keys)for(let m of nr)t[`hp.${s}.${u}.${m}`]={why:c};for(let l of["uca","lca"])for(let u of Ln)t[`arm.${s}.${l}.${u}`]={why:c};for(let l of Do)t[`rocker.${s}.${l}`]={why:c};for(let l of["heave.outer","heave.anchor","roll.outer","roll.inner"]){let[u,m]=l.split(".");for(let f of nr)t[`${u}.${s}.${m}.${f}`]={why:c}}t[`cfg.${s}.springRate`]={why:"the measured curve set carries its own spring rate"}}let r=["rockerPivotA","rockerPivotB","rockerToPushrod","rockerToDamper"];for(let s of["front","rear"]){if(Be(e.vehicle,s).config.actuation!=="direct")continue;let i="this axle is direct-acting \u2014 there is no bell-crank";for(let c of r)for(let l of nr)t[`hp.${s}.${c}.${l}`]={why:i};for(let c of Do)t[`rocker.${s}.${c}`]={why:i}}for(let s of["front","rear"]){let i=Be(e.vehicle,s);if(i.measured||i.config.actuation!=="decoupled")continue;let c="this axle is decoupled \u2014 the corner damper is out of circuit";for(let l of["rockerToDamper","damperChassis"])for(let u of nr)t[`hp.${s}.${l}.${u}`]={why:c,useInstead:`heave.${s}.outer.${u}`};t[`cfg.${s}.springRate`]={why:"a decoupled axle has no corner spring \u2014 its elements hold it up",useInstead:`heave.${s}.rate`}}for(let s of["front","rear"]){let i=Be(e.vehicle,s),c=e.params[Np[s]]?.linkage;if(i.measured||!c||c.attach!=="rocker"||c.mount?.kind==="chassis")continue;let l=i.hardpoints,u=[0,1,2].map(f=>l.rockerPivotB[f]-l.rockerPivotA[f]),m=Math.hypot(u[0],u[1],u[2]);if(m>0)for(let f=0;f<3;f++)Math.abs(u[f]/m)<1-1e-12||(t[`heave.${s}.outer.${nr[f]}`]={why:`the rocker shaft runs along ${nr[f]} \u2014 this only slides the eye along it`})}for(let s of["front","rear"]){let i=Be(e.vehicle,s);if(i.measured||i.config.layout!=="mcpherson")continue;let c="this axle is a McPherson strut \u2014 there is no upper arm";for(let l of["ucaFront","ucaRear","uprightUpper"])for(let u of nr)t[`hp.${s}.${l}.${u}`]={why:c,useInstead:`hp.${s}.damperChassis.${u}`};for(let l of Ln)t[`arm.${s}.uca.${l}`]={why:c};for(let l of["link.ucaFront","link.ucaRear","bush.ucaFront","bush.ucaRear"])t[`kc.${s}.${l}`]={why:c}}for(let s of["front","rear"]){let i=Be(e.vehicle,s);if(i.measured)continue;for(let l of["uca","lca"]){if(l==="uca"&&i.config.layout==="mcpherson")continue;let u=py(i.hardpoints,l);if(u)for(let m of Ln)t[`arm.${s}.${l}.${m}`]={why:u,useInstead:`hp.${s}.${Ot[l].fore}.z`}}let c=ls(i.hardpoints);if(c&&i.config.actuation!=="direct")for(let l of Do)t[`rocker.${s}.${l}`]={why:c,useInstead:`hp.${s}.${Sr.fore}.z`}}let n=[["arbFrontDesign","param.arb_front","the front anti-roll bar design in Vehicle Dynamics","front","roll"],["arbRearDesign","param.arb_rear","the rear anti-roll bar design in Vehicle Dynamics","rear","roll"],["heaveFrontDesign","param.heave_spring_front","the front third-spring design","front","heave"],["heaveRearDesign","param.heave_spring_rear","the rear third-spring design","rear","heave"]];for(let[s,i,c,l,u]of n){let m=e.params[s];if(!m?.design||m.design.kind==="none")continue;let f=m.design.kind==="direct"?`${u}.${l}.wheelRate`:`${u}.${l}.rate`;t[i]={why:`computed from ${c}`,useInstead:f}}let o=e.params.aeroModelId||e.params.aeroModel?Eb:Ib;for(let[s,i]of Object.entries(o))t[`param.${s}`]={why:i};if(e.params.batteryModelId||e.params.batteryModel)for(let[s,i]of Object.entries(Zu))t[`param.${s}`]={why:i};for(let[s,i]of Object.entries(Ju(e.params)))t[`param.${s}`]={why:i};let a=hu(e.params);return a==="hydraulic"?t["param.brake_balance"]={why:"set by the balance bar and the brake hardware",useInstead:"brakeSetup.barFront"}:a==="tyre"&&(t["param.brake_balance"]={why:"tyre-limited brakes split as the grip does"}),t}function Cw(e){let t={...C3,...ww(e)};for(let[n,o]of Object.entries(t))o.useInstead&&t[o.useInstead]&&(t[n]={why:o.why});let r=n=>{let o=t[n.id];return o?{...n,supersededBy:o}:n};return[...l3(e),...p3(e),...h3(e),...g3(e),...k3(),...M3(e),...A3(e),...S3(e),...x3(e),...F3(e.params)].map(r)}var w3={spring_front:"cfg.front.springRate",spring_rear:"cfg.rear.springRate"},C3=Object.fromEntries(Object.entries(Db).map(([e,t])=>[`param.${e}`,{why:t,useInstead:w3[e]}])),tt=e=>e.scope?`${e.scope} \xB7 ${e.label}`:e.label;function yt(e){let t={};for(let n of Cw(e))t[n.id]=n;let r=(n,o)=>{if(typeof o!="string")return;let a=QF(n,o);return a&&(n[o]=a),a};return new Proxy(t,{get:(n,o,a)=>typeof o=="string"&&!Object.hasOwn(n,o)?r(n,o)??Reflect.get(n,o,a):Reflect.get(n,o,a),has:(n,o)=>Reflect.has(n,o)||!!r(n,o)})}var xy=e=>e.step!==void 0&&Number.isFinite(e.step)&&e.step>0?e.step:0,Ry=e=>xy(e)>0||(e.values?.length??0)>0,vy=e=>e.some(Ry),Tw=e=>1e-9*Math.max(1,Math.abs(e.lo),Math.abs(e.hi));function Pw(e,t){if(!Number.isFinite(t))return t;if(e.values?.length){let s=e.values[0];for(let i of e.values)Math.abs(i-t)<Math.abs(s-t)&&(s=i);return s}let r=xy(e);if(!r||!Number.isFinite(e.start))return t;let n=Tw(e),o=Math.round((t-e.start)/r),a=s=>e.start+s*r;return a(o)>e.hi+n&&a(o-1)>=e.lo-n?a(o-1):a(o)<e.lo-n&&a(o+1)<=e.hi+n?a(o+1):a(o)}var Lw=(e,t)=>t.map((r,n)=>e[n]&&Ry(e[n])?Pw(e[n],r):r);function ky(e,t=1e3){if(e.values?.length)return e.values.length;let r=xy(e);if(!r||!Number.isFinite(e.start))return 1/0;let n=Tw(e),o=Math.ceil((e.lo-n-e.start)/r),a=Math.floor((e.hi+n-e.start)/r);return Math.max(0,Math.min(t,a-o+1))}function My(e,t,r){let n=Lw(e.variables,t),o=n.every((a,s)=>a===t[s]);return{x:n,score:o?r:Ir(e,n)}}function Fy(e,t){if(!e.variables.some(Ew))return e;let r=e.variables.filter(o=>o.follows&&!o.fixed).map(o=>({id:o.id,follows:o.follows})),n=e.variables.filter(o=>!o.fixed&&!o.follows).map(o=>{if(Iw(o))return{...o,lo:Math.min(...o.values),hi:Math.max(...o.values)};if(!o.around)return o;let{around:a,fixed:s,...i}=o,c=t(o.id);return Number.isFinite(c)?{...i,lo:c-a.minus,hi:c+a.plus}:i});return r.length?{...e,variables:n,followers:r}:{...e,variables:n}}var Ew=e=>!!(e.fixed||e.around||e.follows)||Iw(e),Iw=e=>!!e.values?.length&&(e.lo!==Math.min(...e.values)||e.hi!==Math.max(...e.values));function mt(e,t){if(!t.variables.some(Ew))return t;let r=yt(e);return Fy(t,n=>{let o=r[n];if(!o)return NaN;try{return o.read(e)}catch{return NaN}})}function ar(e){return[...e.objectives,...e.constraints,...e.watches??[]]}var Bp=e=>(e.metrics??rr()).byId;function wy(e,t){t=mt(e,t);let r=yt(e),n=[];for(let o of t.variables){let a=r[o.id];a&&n.push({id:a.id,name:tt(a),unit:a.unit,lo:o.lo,hi:o.hi,start:a.read(e),...o.step!==void 0?{step:o.step}:{},...o.values?{values:o.values}:{}})}return n}function us(e,t,r){t=mt(e,t);let n=yt(e),o=e;return t.variables.forEach((a,s)=>{let i=n[a.id];i&&Number.isFinite(r[s])&&(o=i.write(o,r[s]))}),Py(e,o,t.followers,n)}function Cy(e,t,r={}){let n=t.states??[],o=n.some(c=>c.follows);if(!o&&!t.envelopeFollows)return t;let a=Pn(e,{density:t.density,envelope:t.envelope,states:n,operating:t.operating,lap:t.lap,assemble:r.assemble,simParams:r.simParams,projectTrack:r.projectTrack,libraryTrack:r.libraryTrack,numerics:r.numerics}),s=n;if(o&&r.simParams)try{let c=a.ggv();c&&(s=g0(n,c,L3(r)))}catch{s=n}let i=t.envelope;if(t.envelopeFollows&&s.length){let c=s.map(h=>a.poseAt(h)).filter(h=>h!==null),l=Bp(r),u=Ty(t,l),m=ar(t).map(h=>({r:h,m:l[h.metricId]})).filter(({m:h})=>h&&h.id.startsWith("kin.")&&h.reads!=="state"&&(h.scope==="car"||u.includes(h.scope))),f=h=>{let b=Pn(e,{density:t.density,envelope:h,assemble:r.assemble,numerics:r.numerics});return m.every(({r:g,m:y})=>Number.isFinite(ut(b,y,g.at)))},p=c.length===s.length?P3(e,x0(c,u),u):null,d=p&&m.length?T3(p,f):p;d&&!R0(d,t.envelope)&&(i=d)}return s===n&&i===t.envelope?t:{...t,states:s,envelope:i}}var Vp=3;function T3(e,t){let r=(c,l)=>t({...e,travelMin:c,travelMax:l}),n=e.travelMin-Vp,o=e.travelMax+Vp;if(r(n,o))return e;let a=(c,l,u)=>{for(;Math.abs(l-c)>1;){let m=Math.round((c+l)/2);u(m)?c=m:l=m}return c};if(r(n,1))o=a(1,o,c=>r(n,c));else if(r(-1,1))n=a(-1,n,c=>r(c,1)),o=a(1,o,c=>r(n,c));else return e;let s=Math.min(-1,Math.max(e.travelMin,n+Vp)),i=Math.max(1,Math.min(e.travelMax,o-Vp));return s===e.travelMin&&i===e.travelMax?e:{...e,travelMin:s,travelMax:i}}function Ty(e,t){let r=new Set;for(let n of ar(e)){let o=t[n.metricId];if(!(!o||!o.id.startsWith("kin.")||o.reads==="state")){if(o.scope==="car")return["front","rear"];r.add(o.scope)}}return r.size?["front","rear"].filter(n=>r.has(n)):["front","rear"]}function P3(e,t,r){if(!t)return null;let n=ts(e.vehicle,e.params),{travelMin:o,travelMax:a}=t;for(let s of r.map(i=>n[i]))try{let i=Ke(s,{travelMin:o,travelMax:a,steps:Ec.travelSteps});if(i.covered)continue;let c=i.samples.filter(l=>l.converged).map(l=>l.travel);if(!c.length)continue;o=Math.max(o,Math.min(-1,Math.ceil(Math.min(...c))+1)),a=Math.min(a,Math.max(1,Math.floor(Math.max(...c))-1))}catch{continue}return o===t.travelMin&&a===t.travelMax?t:{...t,travelMin:o,travelMax:a}}function L3(e){let t=e.projectTrack?.();if(!t)return null;try{return b0(lt(t.asset,t.numerics))}catch{return null}}function Py(e,t,r,n){if(!r?.length)return t;let o=t;for(let a of r){let s=n[a.id],i=n[a.follows];if(!s||!i)continue;let c=i.read(t)-i.read(e);Number.isFinite(c)&&c!==0&&(o=s.write(o,s.read(e)+c))}return o}function En(e,t){if(!Number.isFinite(t))return NaN;if(e.op==="max")return t-e.limit;if(e.op==="min")return e.limit-t;let r=e.limit2??e.limit;return Math.max(e.limit-t,t-r)}var _w=(e,t="")=>t&&t!=="-"?`${e} ${t}`:`${e}`;function Nw(e,t,r){let n=t??is[e.metricId],o=(n?je(n):e.metricId)+Io(e.at,n,r),a=s=>_w(s,n?.unit);return e.op==="max"?`${o} \u2264 ${a(e.limit)}`:e.op==="min"?`${o} \u2265 ${a(e.limit)}`:`${o} between ${e.limit} and ${a(e.limit2??e.limit)}`}function Io(e,t,r){if(!e&&t?.reads!=="state")return"";e??={};let n=[];if(t?.reads==="state")if(e.stateId===kr)n.push(ty(t));else{let o=e.stateId===void 0?r?.states?.[0]:r?.states?.find(a=>a.id===e.stateId);o&&n.push(o.name)}if(e.speed!==void 0&&J0(t)&&n.push(`${(e.speed*3.6).toFixed(0)} km/h`),e.ayG!==void 0&&ey(t)&&n.push(`${e.ayG.toFixed(2)} g`),e.courseId===Oc&&t?.reads==="course")n.push(Z0(t));else if(e.courseId&&t?.reads==="course"){let o=r?.lap.courses.find(a=>a.id===e.courseId);o&&n.push(L0(o))}return n.length?` @ ${n.join(", ")}`:""}function Ow(e,t,r){let n=r/t.scale;return e.goal==="min"?e.weight*n:e.goal==="max"?-e.weight*n:e.weight*Math.max(0,Math.abs(r-(e.target??0))-Math.max(0,e.tolerance??0))/t.scale}var Vw=5e-4;function Bw(e,t){return e.cost!=="lap"&&e.cost!=="session"?0:Number.isFinite(t)?Vw*Math.abs(t):0}function $p(e,t,r={}){return Pn(e,{density:t.density,envelope:t.envelope,states:t.states,operating:t.operating,lap:t.lap,assemble:r.assemble,simParams:r.simParams,projectTrack:r.projectTrack,libraryTrack:r.libraryTrack,sessionParams:r.sessionParams,session:r.session,numerics:r.numerics})}function Gp(e,t,r={}){t=mt(e,t);let n=wy(e,t),o=yt(e),a=Bp(r),s=t.constraints.map(m=>({spec:m,metric:a[m.metricId]})).filter(m=>!!m.metric),i=s.filter(m=>m.metric.cost==="geometry"),c=s.filter(m=>m.metric.cost!=="geometry"),l=t.objectives.map(m=>({spec:m,metric:a[m.metricId]})).filter(m=>!!m.metric),u=(m,f)=>{let p=0,d=[];for(let{spec:h,metric:b}of m){let g=ut(f,b,h.at);if(!Number.isFinite(g))return{ok:!1,violation:f.failure?.violation??400,reason:f.failure?.reason??`${je(b)} could not be computed`};let y=En(h,g);y>0&&(p+=y/b.scale,d.push(`${Nw(h,b,t)} (${_w(g.toFixed(3),b.unit)})`))}return d.length===0?ei:{ok:!1,violation:p,reason:d.join("; ")}};return{name:"study",variables:n,build:m=>{let f=e;return t.variables.forEach((p,d)=>{let h=o[p.id];h&&(f=h.write(f,m[d]))}),f=Py(e,f,t.followers,o),{car:f,ev:$p(f,t,r)}},feasible:({ev:m})=>{let f=u(i,m);if(!f.ok)return f;for(let{spec:p,metric:d}of c)ut(m,d,p.at);for(let{spec:p,metric:d}of l)ut(m,d,p.at);return m.failure?{ok:!1,violation:m.failure.violation,reason:m.failure.reason}:u(c,m)},terms:({ev:m})=>l.map(({spec:f,metric:p})=>{let d=ut(m,p,f.at);return{name:je(p)+Io(f.at,p,t),raw:d,unit:p.unit,weight:f.weight,contribution:Ow(f,p,d),resolution:Math.abs(f.weight)*Bw(p,d)/p.scale}})}}function Sy(e){let t=/^arm\.(front|rear)\.(uca|lca)\./.exec(e);if(t)return`${t[1]}.${t[2]}`;let r=/^rocker\.(front|rear)\./.exec(e);if(r)return`${r[1]}.rocker`;let n=/^hp\.(front|rear)\.(ucaFront|ucaRear|lcaFront|lcaRear|rockerPivotA|rockerPivotB)\./.exec(e);return n?n[2].startsWith("rocker")?`${n[1]}.rocker`:`${n[1]}.${n[2].startsWith("uca")?"uca":"lca"}`:null}function $w(e,t){if(e.variables.some(o=>o.id===t))return!0;let r=Po(t);if(!r||!ns.includes(r.axis))return!1;if(e.variables.some(o=>jt(o.id)?.point===r.point))return!0;let n=Sy(t);return!!n&&e.variables.some(o=>/^(arm|rocker)\./.test(o.id)&&Sy(o.id)===n)}function D3(e,t){let r=e.followers??[],n=new Map(r.map(i=>[i.id,i.follows])),o=i=>{let c=t[i],l=Po(i);return c&&l&&ns.includes(l.axis)?{name:tt({...c,label:c.label.replace(/ [xyz]$/,"")}),axis:l.axis}:{name:c?tt(c):`\u201C${i}\u201D`}},a=new Map,s=(i,c,l)=>{let u=a.get(i);u||a.set(i,u={text:l,axes:[]}),c&&u.axes.push(c)};for(let i of r){let c=t[i.id],l=t[i.follows],u=o(i.id),m=o(i.follows),f=p=>p&&p!=="x, y, z"?` in ${p}`:"";if(!c){s(`missing:${i.id}`,void 0,()=>`\u201C${i.id}\u201D is not a variable this car has.`);continue}if(c.supersededBy&&s(`superseded:${u.name}`,u.axis,p=>`${u.name}${f(p)} cannot be moved: ${c.supersededBy.why}.`),!l)s(`no-lead:${u.name}:${i.follows}`,u.axis,p=>`${u.name}${f(p)} moves with \u201C${i.follows}\u201D, which is not a variable this car has.`);else if(i.follows===i.id)s(`self:${u.name}`,u.axis,p=>`${u.name}${f(p)} cannot move with itself.`);else if(l.unit!==c.unit)s(`unit:${u.name}:${m.name}`,u.axis,p=>`${u.name}${f(p)} moves with ${m.name}, which is in ${l.unit} where it is in ${c.unit}. Link it to one in the same unit.`);else if(n.has(i.follows)){let p=o(n.get(i.follows));s(`chain:${u.name}:${m.name}`,u.axis,d=>`${u.name}${f(d)} moves with ${m.name}, which itself moves with ${p.name}. Link it to ${p.name}.`)}else $w(e,i.follows)||s(`still:${u.name}:${m.name}`,u.axis,p=>`${u.name}${f(p)} moves with ${m.name}, which the study does not move${f(p)}. Free that one, or give this its own bound.`)}return[...a.values()].map(i=>i.text(i.axes.join(", ")))}function Ly(e,t,r={}){let n=t.variables.length>0&&t.variables.every(y=>y.fixed||y.follows),o=t.variables.some(y=>y.follows&&!y.fixed);t=mt(e,t);let a=yt(e),s=[],i=Bp(r),c=ar(t).map(y=>y.metricId),l=c.some(y=>y.startsWith("dyn.")),u=c.some(y=>y.startsWith("lap."));if(c.some(y=>y.startsWith("kin."))){let y=t.envelope;y.travelMin<0&&y.travelMax>0||s.push("The travel the linkage is read over must reach both ways from the design ride: droop below zero, bump above."),(!(y.rollMaxDeg>0)||!(y.rollAtLimitDeg>=0))&&s.push("The roll the linkage is read over must be above zero.")}let m=ar(t).filter(y=>i[y.metricId]?.reads==="state");if(m.length){let y=t.states??[];if(!y.length)s.push("This study reads targets at a state and has none. Take the car\u2019s five under Conditions.");else{let R=new Set([...y.map(k=>k.id),kr]);for(let k of m){let v=i[k.metricId];if(k.at?.stateId&&!R.has(k.at.stateId))s.push(`${je(v)} names a state this study no longer has. Point it at one of the states under Conditions.`);else if(k.at?.stateId===kr&&!v.acrossStates)s.push(`${je(v)} is read at one state at a time, not over every state.`);else if(v.appliesAt){let x=k.at?.stateId&&k.at.stateId!==kr?y.find(F=>F.id===k.at.stateId):void 0,M=x?sy(v,x):null;M?s.push(`${je(v)} ${M}. Point it at a state that does.`):!x&&!Fp(v,y)&&s.push(`${je(v)} has no state to be read at: ${v.appliesAt(y[0])} in every state of this study.`)}}}r.assemble||s.push("This study reads targets at a state, and nothing here can assemble the car to find its pose.")}for(let y of t.states??[])(!(y.speedKmh>=0)||!Number.isFinite(y.ayG)||!Number.isFinite(y.axG))&&s.push(`The state \u201C${y.name}\u201D needs a speed of zero or more and finite accelerations.`),y.weight>0||s.push(`The state \u201C${y.name}\u201D needs a weight above zero.`);if(l&&!r.assemble&&s.push("This study reads whole-car metrics, and nothing here can assemble the car to read them from."),u&&!r.simParams&&s.push("This study reads lap metrics, and nothing here can prepare the car for a lap."),u&&!t.lap.courses.length&&s.push("This study reads lap metrics and has no course to drive. Add one under \u201CWhat the car drives\u201D."),u&&t.lap.courses.some(y=>y.course.kind==="project")&&!r.projectTrack?.()&&s.push("This study laps the project\u2019s track, and the project has none. Pick a manoeuvre, or load a track."),u)for(let y of t.lap.courses)y.course.kind==="track"&&!r.libraryTrack?.(y.course.trackId)&&s.push(`This study drives ${y.course.name}, which is not in the project\u2019s tracks, or has not loaded yet.`);let f=new Set([...t.lap.courses.map(y=>y.id),Oc]);for(let y of ar(t))if(y.at?.courseId&&!f.has(y.at.courseId)){let R=i[y.metricId];s.push(`${R?je(R):y.metricId} names a course this study no longer has. Point it at one of the courses below.`)}u&&t.lap.ggvMode==="fast"&&t.variables.some(R=>/arb_|spring|heave_|front_mass_diss|cg_height|^hp\./.test(R.id.replace("param.","")))&&s.push("The fast grip envelope is a point mass: no load transfer, no trim. It cannot see bars, springs, roll centres or where the mass sits, and this study moves at least one of those."),n?s.push(o?"Every variable is fixed or moves with another \u2014 there is nothing to search.":"Every variable is fixed \u2014 there is nothing to search."):t.variables.length===0&&s.push("No variables selected \u2014 there is nothing to search."),t.objectives.length===0&&s.push("No objective selected. Constraints alone say which designs are legal, not which is better.");for(let y of t.variables){let R=a[y.id];if(!R){s.push(`\u201C${y.id}\u201D is not a variable this car has.`);continue}if(y.values&&y.values.length<2?s.push(`${tt(R)}: list two values or more, or fix it where it is.`):y.hi>y.lo?y.step!==void 0&&ky({...y,start:R.read(e)})<2&&s.push(`${tt(R)}: a step of ${y.step} ${R.unit} leaves no other place to land in its box. Make the step finer or the box wider, or fix it.`):s.push(`${tt(R)}: the upper bound must be above the lower one (${y.lo} to ${y.hi}).`),R.supersededBy){let v=R.supersededBy.useInstead?a[R.supersededBy.useInstead]:void 0,x=v?tt(v):void 0;s.push(`${tt(R)} cannot be searched: ${R.supersededBy.why}.`+(x?` Use ${x} instead.`:""))}let k=R.read(e);Number.isFinite(k)&&(k<y.lo||k>y.hi)&&s.push(`${tt(R)} starts at ${k.toFixed(1)} ${R.unit}, outside its own bounds.`)}let p=t.followers??[],d=new Map;for(let y of[...t.variables.map(R=>R.id),...p.map(R=>R.id)]){let R=Sy(y);if(!R)continue;let k=d.get(R);k||d.set(R,k={arms:[],coords:[]}),(/^(arm|rocker)\./.test(y)?k.arms:k.coords).push(y)}for(let[y,R]of d){if(R.arms.length===0||R.coords.length===0)continue;let k=x=>a[x]?tt(a[x]):x,v=y.endsWith("rocker")?"rocker":`${y.endsWith("uca")?"upper":"lower"} arm`;s.push(`${y.startsWith("front")?"The front":"The rear"} ${v} is being moved two ways at once \u2014 as an axis (${R.arms.map(k).join(", ")}) and as pivot coordinates (${R.coords.map(k).join(", ")}). They describe the same ${v}, so whichever is applied second overwrites the other. Keep one.`)}let h=new Map,b=new Set(p.map(y=>y.id));for(let y of[...t.variables.map(R=>R.id),...b]){let R=Po(y);if(!R)continue;let k=jt(y),v=b.has(y)?"with":k?`${k.shape.kind}:${y.slice(y.lastIndexOf(".")+1).replace(/[uv]$/,"")}`:"axes",x=h.get(R.point);x||h.set(R.point,x=new Set),x.add(v)}for(let[y,R]of h){if(R.size<2||R.size===2&&R.has("axes")&&R.has("with"))continue;let k=[...R].map(w=>w.split(":")[0]),v=w=>k.filter(T=>T===w).length,x=[v("axes")?"in its axes":"",v("line")===1?"along a line":v("line")>1?"along two lines":"",v("plane")===1?"in a plane":v("plane")>1?"in two planes":"",v("with")?"with another point":""].filter(Boolean),M=a[`${y}.x`],F=M?tt({...M,label:M.label.replace(/ x$/,"")}):y;s.push(`${F} is moved more than one way at once \u2014 ${x.join(" and ")}. Each write moves it off the other's, so keep one.`)}s.push(...D3(t,a));for(let y of t.constraints){let R=i[y.metricId];if(!R){s.push(`\u201C${y.metricId}\u201D is not a metric.`);continue}y.op==="band"&&!((y.limit2??y.limit)>y.limit)&&s.push(`${je(R)}: the band's upper limit must be above its lower one.`)}l&&!(t.operating.speed>0)&&s.push("Whole-car metrics need a speed to be read at; a yaw-moment diagram at rest is degenerate.");for(let y of ar(t))if(y.at?.speed!==void 0&&!(y.at.speed>0)){let R=i[y.metricId];s.push(`${R?je(R):y.metricId} is asked for at rest, where a yaw-moment diagram is degenerate.`)}for(let y of t.watches??[])i[y.metricId]||s.push(`\u201C${y.metricId}\u201D is not a metric.`);let g=new Set;for(let y of ar(t)){let R=i[y.metricId],k=R?.unavailable?.(e);!R||!k||g.has(R.id)||(g.add(R.id),s.push(`${je(R)} cannot be read on this car: ${k}.`))}for(let y of t.objectives)i[y.metricId]?y.weight>0?y.goal==="target"&&!Number.isFinite(y.target)?s.push(`${je(i[y.metricId])}: \u201Chit a value\u201D needs a value.`):y.goal==="target"&&y.tolerance!==void 0&&!(y.tolerance>=0)&&s.push(`${je(i[y.metricId])}: the tolerance must be zero or more.`):s.push(`${je(i[y.metricId])}: weight must be positive.`):s.push(`\u201C${y.metricId}\u201D is not a metric.`);return s}var Gw=.1,Kw=2e3,Ay=3;function Dy(e,t,r={},n=Kw){t=mt(e,t);let o=Gp(e,t,r),a=Bp(r),s=yt(e),i=o.variables.map(A=>A.start),c=A=>{let S=o.build(A);return o.feasible(S).ok&&o.terms(S),S},l=c(i),u=o.feasible(l),m=[...t.objectives,...t.constraints],f=(A,S=m)=>{let C={};for(let L of S){let D=a[L.metricId];D&&(C[`${L.metricId}@${Lo(L.at)}`]=ut(A.ev,D,L.at))}return C},p=A=>m.map(S=>A[`${S.metricId}@${Lo(S.at)}`]).map(S=>Number.isFinite(S)?S.toFixed(9):"x").join("|"),d=f(l,ar(t)),h=p(d),b=[],g=[],y={},R=[],k=0;t.variables.forEach((A,S)=>{let C=s[A.id];if(!C)return;if(R.length>=Ay&&k>n){g.push(C);return}let L=[...i];L[S]=i[S]+(A.hi-i[S])*.25||A.hi;let D=performance.now(),I=c(L),O=performance.now()-D;k+=O,R.push(O);let N=f(I);y[C.id]=N,p(N)===h&&b.push(C)});let v=t.variables[0],x=v?t.variables.indexOf(v):-1;for(let A=0;v&&R.length>0&&R.length<Ay;A++){let S=[...i];S[x]=i[x]+(v.hi-i[x])*(.4+.15*A)||v.hi;let C=performance.now();c(S),R.push(performance.now()-C)}let M=[...R].sort((A,S)=>A-S),F=M.length?M[M.length>>1]:0,w=[],T=ar(t).map(A=>A.metricId);if(T.some(A=>A.startsWith("dyn.trim")||A==="dyn.ymdMaxAy")){let A=l.ev.ymdLimit();A?.onGridEdge&&w.push("The yaw-moment diagram peaks on the edge of its swept grid, so the trim readings are where the sweep stopped rather than where the car does. Widen the \u03B2/\u03B4 envelope before trusting them."),!A&&l.ev.dynAvailable&&w.push("The yaw-moment diagram found no trim point, so anything read off the limit is unavailable.")}if(T.some(A=>A==="dyn.steeringTorque"||A==="dyn.steeringTorqueGradient")){let A=l.ev.tyre()?.model,S=A?dn(A):null;S==="assumed"?w.push("This tyre carries no explicit Mz coefficient block. Its steering-aligning contribution uses Magic Formula defaults, so optimise the curve only as a qualitative placeholder until Mz is imported or fitted."):S==="none"&&w.push("This tyre model has no aligning-moment curve. Steering metrics contain contact-patch force and jacking, but not the pneumatic-trail signal that normally warns the driver at the tyre limit.")}let P=["lap.minStabil","lap.understeerFrac"];if(T.some(A=>P.includes(A))){let S=l.ev.lapReserve()?.beyondFrac;if(S!==void 0&&Number.isFinite(S)){let C=(S*100).toFixed(0);S>=Gw?w.push(`Over ${C} % of this course, some wheel is asked for more longitudinal force than its own tyre ellipse allows \u2014 the speed profile and the per-wheel reconstruction disagree that far. A reserve read there is the two models disagreeing rather than the car having nothing left, and a search pointed at one will optimise the disagreement. It concentrates in high-speed braking, so a shorter straight into the first corner is the usual cure.`):S>0&&w.push(`${C} % of this course is beyond the per-wheel tyre ellipse, which is the usual level of disagreement between the speed profile and the reconstruction. Reserves are readable; treat small differences between designs as smaller than they look.`)}}return w.push(...ay(l.ev,ar(t).map(A=>({m:a[A.metricId],at:A.at})).filter(A=>!!A.m))),{msPerEval:F,values:d,samples:R.length,times:R,dead:b,moves:y,unprobed:g,warnings:w,beyondFrac:T.some(A=>P.includes(A))?l.ev.lapReserve()?.beyondFrac:void 0,startFeasible:u.ok,startReason:u.reason}}var I3=[{kind:"title",label:"Title",what:"The name, what it changes against the Reference, the version and the date",on:"both",make:()=>({kind:"title"})},{kind:"picture",label:"Picture",what:"The car in plan, to scale",on:"each",make:()=>({kind:"picture",half:!0})},{kind:"keyFigures",label:"Key figures",what:"Large numbers picked from the sheet, or formulas",on:"each",make:()=>({kind:"keyFigures",rows:_3.slice(0,4),half:!0})},{kind:"spec",label:"Setup",what:"The Setup by group, or rows picked one by one",on:"each",make:()=>({kind:"spec",rows:"essential"})},{kind:"parts",label:"Parts",what:"Each part by name",on:"each",make:()=>({kind:"parts"})},{kind:"characteristics",label:"Characteristics",what:"What follows from the Setup, at the layout\u2019s operating point",on:"each",make:()=>({kind:"characteristics",groups:[]})},{kind:"results",label:"Results",what:"The events, times, energy and points",on:"each",make:()=>({kind:"results"})},{kind:"chart",label:"Chart",what:"Speed round a lap, the cornering limit or the torque curve",on:"both",make:()=>({kind:"chart",chart:"grip",others:!0,half:!0})},{kind:"changes",label:"Changes since",what:"What was changed since the version compared against",on:"each",make:()=>({kind:"changes"})},{kind:"checks",label:"Checks",what:"The car\u2019s errors and warnings",on:"each",make:()=>({kind:"checks"})},{kind:"notes",label:"Notes",what:"Free text, on every page or one car\u2019s",on:"both",make:()=>({kind:"notes",text:"",cars:{}})},{kind:"comparison",label:"Comparison table",what:"The rows the cars differ in, side by side",on:"all",make:()=>({kind:"comparison"})}];var _3=["setup:m","characteristics:peak_power","characteristics:power_to_weight","characteristics:cla","characteristics:cda","characteristics:pack_energy","characteristics:maxAy","characteristics:top_speed"];var jce=new Set(I3.map(e=>e.kind));var Hw={travel:{name:"Wheel travel",unit:"mm",axis:"Wheel travel (mm, + bump)",from:-25,to:25,step:1,reach:150},roll:{name:"Body roll",unit:"\xB0",axis:"Body roll (\xB0, + right side down)",from:-3,to:3,step:.25,reach:12},steer:{name:"Rack",unit:"mm",axis:"Rack (mm, + right)",from:-30,to:30,step:1,reach:80},pitch:{name:"Body pitch",unit:"\xB0",axis:"Body pitch (\xB0, + nose down)",from:-2,to:2,step:.25,reach:8}};var Ey=["FL","FR","RL","RR"],wt=(e,t,r)=>({input:e,from:r?r[0]:Hw[e].from,to:r?r[1]:Hw[e].to,n:t}),Qce=[{id:"sides",name:"Inside and outside",cards:[{id:"camber-roll",form:"curves",title:"Camber to the road through roll",sweep:wt("roll",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"toe-rack",form:"curves",title:"Wheel angle against the rack",sweep:wt("steer",25),wheels:["FL","FR"],y:["toe"]},{id:"camber-rack",form:"curves",title:"Camber to the road through the steer",sweep:wt("steer",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"load-roll",form:"curves",title:"Wheel loads through roll",sweep:wt("roll",25),wheels:Ey,y:["wheelLoad"]},{id:"travel-roll",form:"curves",title:"Wheel travel through roll",sweep:wt("roll",25),wheels:Ey,y:["travel"]},{id:"toe-roll",form:"curves",title:"Roll steer, all four",sweep:wt("roll",25),wheels:Ey,y:["toe"]}]},{id:"maps",name:"Travel and steer together",cards:[{id:"camber-map",form:"surface",title:"Camber over travel and rack",sweep:wt("travel",17),second:wt("steer",13),wheels:["FL"],y:["camber"]},{id:"bump-steer-map",form:"map",title:"Bump steer over travel and rack",sweep:wt("travel",17),second:wt("steer",13),wheels:["FL"],y:["bumpSteer"]},{id:"bump-steer-family",form:"curves",title:"Bump steer through travel, at five rack positions",sweep:wt("travel",25),second:wt("steer",5,[-20,20]),wheels:["FL"],y:["bumpSteer"]},{id:"scrub-map",form:"surface",title:"Scrub radius over travel and rack",sweep:wt("travel",17),second:wt("steer",13),wheels:["FL"],y:["scrubRadius"]}]}];function Iy(e){let t=Number(e);return Number.isFinite(t)?Math.min(hh,Math.max(fh,t)):Lt}var Yw=6e4;var Yle=[{within:60*6e4,every:Yw},{within:1440*6e4,every:60*6e4},{within:720*60*6e4,every:1440*6e4},{within:1/0,every:10080*6e4}];var j3=new Set(["color","visible","source","origin"]),rue=["id",...j3];var Uw=.18/1.18,Xw={induction:{kind:"natural"}},qw=e=>e.breathing??Xw;function Kp(e){switch(e?.kind){case"sae-j1349":return mc(99e3,25);case"measured":return mc(e.hPa*100,e.tempC);default:return mc(101325,20)}}var X3=Kp(void 0);function Qw(e,t){let r=Kp(e.rated),n=e.induction;if(n.kind==="boosted"){let o=n.boostKPa*1e3;return Math.min(n.maxPressureRatio*t.p,o)/Math.min(n.maxPressureRatio*r.p,o)*(t.pDry/t.p)/(r.pDry/r.p)}return t.pDry/r.pDry*Math.sqrt(r.T/t.T)}function Zw(e,t){let r=e.induction;if(r.kind==="table"){let o=s=>Ge(r.densityAltitudeM,r.powerPct,s),a=o(Kp(e.rated).densityAltitudeM);return a>0?Math.max(0,o(t.densityAltitudeM)/a):0}let n=e.frictionShare??Uw;return Math.max(0,(Qw(e,t)-n)/(1-n))}var jw=new WeakMap;function Ny(e,t){let r=e.asRated??e,n=`${t.p}|${t.pDry}|${t.T}`,o=jw.get(r);o||jw.set(r,o=new Map);let a=o.get(n);if(a)return a;let s=Zw(qw(r),t),i={...r,torque:r.torque.map(c=>c*s),asRated:r};return o.set(n,i),i}function J3(e){return JSON.parse(Oy(Vy(e,"public/laptime/index.json"),"utf8")).tracks}var e5=async e=>{let t=await fetch(e.url);if(!t.ok)throw new Error(`The track could not be read from ${Jm(e)} (${t.status}).`);return new Uint8Array(await t.arrayBuffer())};function Jw(e,t=new Map,r=e5){let n=J3(e);return async o=>{let a=o.kind==="catalogue"?`catalogue:${o.address}`:o.name,s=t.get(a);if(s)return structuredClone(s);let i;if(o.kind==="catalogue"&&o.link){if(!xc(o.address))throw new Error(`"${o.address}" is not a catalogue address`);if(!yc(o.link))throw new Error("This track is linked to a source this version does not read from.");i=await t0(await r(o.link),o.link,o.address)}else if(o.kind==="catalogue"){if(!xc(o.address))throw new Error(`"${o.address}" is not a catalogue address`);let c=JSON.parse(Oy(Vy(e,"public/catalogue",n0(o.address)),"utf8"));i=await a0(c,o.address)}else{let c=n.find(l=>l.name===o.name)?.file;if(!c)throw new Error(`"${o.name}" is not in the bundled catalogue`);i=JSON.parse(Oy(Vy(e,"public/laptime",c),"utf8"))}return t.set(a,i),structuredClone(i)}}var t5=9.81;function eC(e,t=e.tireModel,r=e.tireModelRear){if(!t)return e;let n=e.m.value*t5/4,o=Ia(e,t,r),a=Pe(o.front).rollingRadius(n),s=o.rear===o.front?a:Pe(o.rear).rollingRadius(n),i=r5(e,a,s);if(!(i>0))return e;let c={...e.r_dyn,value:i};return{...e,r_dyn:c,readouts:{...e.readouts,r_dyn:"the fitted tyre\u2019s rolling radius at the static load"}}}function r5(e,t,r){switch(e.motorPlacement??"rear"){case"front":return t;case"awd":return t>0&&r>0?.5*(t+r):0;default:return r}}var n5=1e-6;function tC(e,t,r){let n=e.cgReference;if(!n||!e.cg_height)return e;let o=aM(e,t,r);if(o===void 0||Math.abs(o-n.standingRadius)<n5)return e;let a=n.typed??e.cg_height.value;return{...e,cg_height:{...e.cg_height,value:Ea(e.cg_height.value,n.standingRadius,o)},cgReference:{...n,standingRadius:o,typed:a}}}function rC(e,t,r){let n=e.rcRoad,o=e.rc_front,a=e.rc_rear;if(!n||!o||!a)return e;let s=Uu(e,t,r),i=Ur(o.value,n.gainFront,n.radiusFront,s.front),c=Ur(a.value,n.gainRear,n.radiusRear,s.rear);return i===o.value&&c===a.value?e:{...e,rc_front:{...o,value:i},rc_rear:{...a,value:c},rcRoad:{...n,radiusFront:s.front??n.radiusFront,radiusRear:s.rear??n.radiusRear}}}var nC=e=>({brakeFade:e.brakeFade,airTempC:e.airTempC,diffYaw:e.diffYaw,...pc(e.air)?{air:e.air}:{}});var _o=(e,t)=>t?e.find(r=>r.id===t)?.model:void 0;function No(e){return{tire:t=>_o(e.tires,t),motor:t=>_o(e.motors,t),aero:t=>_o(e.aeros,t),battery:t=>_o(e.batteries,t),brake:t=>_o(e.brakes??[],t),damper:t=>_o(e.dampers??[],t),suspensionOf:t=>ts(By(e,t),t)}}function By(e,t){let r=_o(e.suspensions,t.suspensionId);if(r)return r;let n=e.suspensions.find(o=>o.id===e.activeSuspensionId)??e.suspensions[0];if(!n)throw new Error("this project holds no suspension, so no car can be resolved");return n.model}function Oo(e,t,r){let n={front:t.tire(e.tireModelId),rear:t.tire(e.tireModelIdRear)};return $y(Zk(t.suspensionOf(e),e,n),t,r)}function o5(e){return pc(e.air)?bA(e.air,e.airTempC??Lt):void 0}var a5="the air the session states, at its venue";function s5(e,t){return t?{...e,rho:{...e.rho,value:t.rho},readouts:{...e.readouts,rho:a5}}:e}function i5(e,t,r){if(!r)return{rho:e.rho,motorModel:t,readouts:e.readouts};let{rho:n,readouts:o}=s5(e,r);return{rho:n,motorModel:t&&xt(t)?Ny(t,r):t,air:r,readouts:o}}function $y(e,t,r){let n=t.tire(e.tireModelId),o=t.tire(e.tireModelIdRear),a=rC(tC(eC(lM(sM(gM(e,t.aero(e.aeroModelId)),t.battery(e.batteryModelId)),t.damper(e.damperModelId),t.damper(e.damperModelIdRear)??t.damper(e.damperModelId)),n,o),n,o),n,o),{readouts:s,...i}=i5(a,t.motor(e.motorModelId),o5(r));return{...a,...i,...s?{readouts:s}:{},tireModel:n,...o?{tireModelRear:o}:{},aeroModel:t.aero(e.aeroModelId),batteryModel:t.battery(e.batteryModelId),brakeModel:t.brake(e.brakeModelId),damperModel:t.damper(e.damperModelId),...Fi(e,t.damper),ggvMode:r.ggvMode,quasiTransient:r.quasiTransient??!1,motorThermal:r.motorThermal??!1,brakeFade:r.brakeFade??!1,...r.airTempC!==void 0?{airTempC:r.airTempC}:{},...r.diffYaw?{diffYaw:!0}:{},airSettled:!0}}var m5=e=>e!==!1,p5=(e,t,r)=>r&&t>0?(e%t+t)%t:Math.min(Math.max(e,0),t);function d5(e,t,r){let n=e.points.filter(o=>Number.isFinite(o.at)&&Number.isFinite(o.z)).map(o=>({...o,at:p5(o.at,t,r)})).sort((o,a)=>o.at-a.at);return n.filter((o,a)=>a===0||o.at-n[a-1].at>1e-9)}function f5(e,t,r){let n=d5(e,t,r),o=n.length;if(o===0)return[];let a=p=>p<o-1?n[p+1].at-n[p].at:r?n[0].at+t-n[p].at:1/0,s=p=>p<o-1?(n[p+1].z-n[p].z)/a(p):r&&o>1?(n[0].z-n[p].z)/a(p):0,i=n.map(p=>Math.max(0,Number.isFinite(p.curve)?p.curve:0)/2),c=(p,d,h)=>i[p]+i[d]>h?h*i[p]/(i[p]+i[d]):i[p],l=p=>p<o-1||r?c(p,p<o-1?p+1:0,a(p)):Math.max(0,t-n[p].at),u=p=>p>0?c(p,p-1,a(p-1)):r?c(p,o-1,a(o-1)):n[p].at,m=p=>p>0?s(p-1):r&&o>1?s(o-1):n[p].at<=1e-9?s(p):0,f=p=>!r&&p===o-1&&o>1&&n[p].at>=t-1e-9?s(p-1):s(p);return n.map((p,d)=>{let h=l(d),b=u(d),g=Math.min(i[d],h,b),y=!r&&g<i[d]&&(d===o-1&&g===h||d===0&&g===b);return{at:p.at,z:p.z,gIn:m(d),gOut:f(d),half:g,asked:i[d],atEnd:y}})}function h5(e,t,r,n){let o=t-e.at;return n&&r>0?o-r*Math.round(o/r):o}function b5(e,t,r,n){for(let s of e){let i=h5(s,t,r,n);if(s.half>0&&Math.abs(i)<s.half){let c=i+s.half;return s.z-s.gIn*s.half+s.gIn*c+(s.gOut-s.gIn)/(4*s.half)*c*c}}let o=e[e.length-1],a=n?t-o.at+(t<o.at?r:0):t-o.at;for(let s of e)s.at<=t&&(o=s,a=t-s.at);return!n&&t<e[0].at?e[0].z:o.z+o.gOut*a}function oC(e,t,r,n){let o=m5(n),a=f5(e,r,o);return a.length?t.map(s=>b5(a,s,r,o)):t.map(()=>0)}function Wc(e,t){if(!t?.points.length)return e;let r=Ac(e),{zSmoothing:n,...o}=e;return{...o,z:oC(t,r,w0(e),e.closed)}}var Hp={widthLeft:1.5,widthRight:1.5,bank:0,mu:1};function aC(e){return e.kind==="bundled"?{kind:"bundled",name:e.name}:e.kind==="catalogue"?{kind:"catalogue",id:e.id,address:e.address,...e.link?{link:e.link}:{}}:null}async function jc(e,t){let r=aC(e.source);return sC(e,r?await t(r):void 0)}function sC(e,t){let{source:r}=e;if(r.kind==="segments"){let{segments:i,closed:c,spacing:l}=r,{asset:u}=wc(i,{name:e.name,closed:c,spacing:l,base:Hp});return Wc(u,r.profile)}let n=r.sections??[];if(r.kind==="inline")return Wc(cp(r.asset,n,Hp),r.profile);if(!t)throw new Error(`Track "${e.name}" has to be loaded before it can be resolved.`);let{widthLeft:o,widthRight:a,closed:s}=r;return Wc(cp({...t,...o!==void 0?{widthLeft:o}:{},...a!==void 0?{widthRight:a}:{},...s!==void 0?{closed:s}:{}},n,Hp),r.profile)}var Lpe=1/500;var Dpe=5*Math.PI/180;var Gpe=1/3;var R5=[4,2,1,.5,.25,.125];function iC(e,t,r={}){let n=[...r.steps??R5].sort((g,y)=>y-g),o=ct(r.numerics),a=r.tolPct??.5,s=Dt(e),i=e.ggvMode??"twoTrack",c=yr(s,!1,i),l={...o,dsTarget:n[0]??o.dsTarget},u=n.length?fo(s,c,[lt(t,l)],l,i):void 0,m=An(s,c.rows),f=n.map((g,y)=>{let R={...o,dsTarget:g},k=Date.now(),v=lt(t,R),x=At(c,v,R,{...u?{load:u}:{},...m?{shifts:m}:{}});return r.onStep?.(y+1,n.length),{dsTarget:g,npts:v.npts,lapTime:x.laptime,ms:Date.now()-k}}),p=f[f.length-1]?.lapTime??NaN,d=f.map(g=>{let y=g.lapTime-p;return{...g,delta:y,deltaPct:p?100*y/p:NaN}}),h=d.filter(g=>Math.abs(g.deltaPct)<=a),b=h.length?Math.max(...h.map(g=>g.dsTarget)):null;return{points:d,reference:p,recommended:b,tolPct:a}}function ms(e,t={}){let r=e.settings,n=t.ggvMode??r.ggvMode,o=(t.quasiTransient??r.quasiTransient)&&n!=="fast",a=e.tracks.find(s=>s.id===e.activeTrackId)??e.tracks[0];return{ggvMode:n,quasiTransient:o,motorThermal:t.motorThermal??r.motorThermal,brakeFade:t.brakeFade??r.brakeFade,airTempC:Iy(t.airTempC??r.airTempC),...pc(zm(t.air??r.air))?{air:zm(t.air??r.air)}:{},diffYaw:t.diffYaw??r.diffYaw,racingLine:t.racingLine??r.useRacingLine,standingStart:t.standingStart??(a?a.standingStart===!0:r.standingStart),lapCounts:t.lapCounts??r.lapCounts,numerics:ct(r.numerics)}}async function zp(e,t){let r=e.tracks.find(n=>n.id===e.activeTrackId)??e.tracks[0];if(!r)throw new Error("this project holds no track \u2014 add one with track_select before running a lap event");return{entry:r,asset:await jc(r,t)}}function M5(e,t){let r=structuredClone(e);for(let[n,o]of Object.entries(t))if(!tm(r,n,o))throw new Error(`no parameter is labelled "${n}" on this car \u2014 read vehicle_get for the labels it has`);return r}var Gy=(e,t)=>{let r=e?.name;return typeof r=="string"&&r?r:t};function S5(e,t){let r={};for(let n of Cn){let o=e[n.doc]??[];for(let i of n.slots.slice(1)){let c=t[i.ref],l=typeof c=="string"?o.find(u=>u.id===c):void 0;l&&(r[i.key]={id:l.id,name:Gy(l.model,l.id)})}let a=t[n.ref],s=typeof a=="string"?o.find(i=>i.id===a):void 0;if(s){r[n.doc]={id:s.id,name:Gy(s.model,s.id)};continue}if(n.doc==="suspensions"){let i=o.find(c=>c.id===e.activeSuspensionId)??o[0];r[n.doc]=i?{id:i.id,name:Gy(i.model,i.id),byFallback:!0}:null;continue}r[n.doc]=null}return r}function A5(e){return Object.values(e.events).map(t=>({id:t.id,label:t.label,kind:t.kind,time:t.time,lapTime:t.lapTime,distance:t.distance,laps:t.laps,...t.energy?{energyConsumedKwh:t.energy.consumed,energyRemaining:t.energy.remainingFraction}:{},...t.lapsOverridden?{lapsOverridden:t.lapsOverridden}:{},...t.incomplete?{incomplete:t.incomplete}:{},...t.energyTarget?{energyTarget:t.energyTarget}:{}}))}function cC(e){let t=new Map;for(let{name:r,events:n}of e)for(let o of n){let a=t.get(o.label);a||t.set(o.label,a={event:o.label,finished:[],stopped:[]}),(o.incomplete?a.stopped:a.finished).push(r)}return[...t.values()].filter(r=>r.stopped.length>0)}var lC=e=>e.length<2?e[0]??"":`${e.slice(0,-1).join(", ")} and ${e[e.length-1]}`;async function Yp(e,t,r={}){let n=ms(e,r.settings),{entry:o,asset:a}=await zp(e,t),s=No(e),i=r.vehicleIds?.length?r.vehicleIds.map(d=>{let h=e.vehicles.find(b=>b.id===d);if(!h)throw new Error(`this project holds no vehicle "${d}"`);return h}):e.vehicles.filter(d=>d.visible);if(!i.length)throw new Error("no vehicle is visible in this project \u2014 name some in vehicleIds");let c=i.map(d=>{let h=r.overrides?.[d.id]?M5(d.params,r.overrides[d.id]):d.params;return Oo(structuredClone(h),s,n)}),l=ac(xo(e.meta.rulesetId,e.rulesets)),u=uc(c,a,n.numerics,l,{racingLine:n.racingLine,standingStart:n.standingStart,lapCounts:n.lapCounts}),m={};i.forEach((d,h)=>{m[d.id]=u[h]});let{scores:f,field:p}=Dg(l,m);return{rulesetId:e.meta.rulesetId,track:o.name,settings:{ggvMode:n.ggvMode,quasiTransient:n.quasiTransient,motorThermal:n.motorThermal,brakeFade:n.brakeFade,airTempC:n.airTempC,...n.air?{air:n.air}:{},diffYaw:n.diffYaw,racingLine:n.racingLine,standingStart:n.standingStart},fleetScored:f!==null,vehicles:i.map((d,h)=>({id:d.id,name:u[h].name||String(d.params.name??d.id),events:A5(u[h]),metrics:Eg(l,u[h],p?.[d.id]),fitted:S5(e,d.params),...f?.[d.id]?{score:{total:f[d.id].total,parts:{...f[d.id].parts}}}:{}})),raw:{results:m,scores:f,field:p}}}async function uC(e,t,r){let n=e.vehicles.find(i=>i.id===r.vehicleId);if(!n)throw new Error(`this project holds no vehicle "${r.vehicleId}"`);let o=ms(e),{asset:a}=await zp(e,t),s=Oo(structuredClone(n.params),No(e),o);return iC(s,a,{...r.steps?{steps:r.steps}:{},numerics:o.numerics,...r.tolPct!==void 0?{tolPct:r.tolPct}:{},...r.onStep?{onStep:r.onStep}:{}})}var F5=(e,t)=>e[t]??[],w5=(e,t,r)=>r<=1?[e]:Array.from({length:r},(n,o)=>e+(t-e)*o/(r-1));function Wp(e){return e.kind==="param"?w5(e.start,e.end,Math.max(1,Math.round(e.steps))):e.kind==="part"?[...e.partIds]:[...e.values]}var mC=e=>e.kind==="param"?e.label:e.kind==="part"?`${e.part} model`:e.setting;function C5(e,t){let r=e.vehicles.find(i=>i.id===t.vehicleId);if(!r)throw new Error(`this project holds no vehicle "${t.vehicleId}"`);if(!t.axes.length)throw new Error("a sweep needs at least one axis");let n=Oo(structuredClone(r.params),No(e),ms(e)),o=hM(n,{geometry:!0}),a=em(n);for(let i of t.axes){if(i.kind==="param"){let c=a.find(u=>u.label===i.label);if(!c)throw new Error(`no parameter is labelled "${i.label}" on this car \u2014 read vehicle_get for the labels it has`);let l=o[c.key];if(l)throw new Error(`"${i.label}" is a readout on this car, not an input: ${l}. Sweeping it would report exactly zero. Sweep what produces it instead.`)}if(i.kind==="part"){let c=Cn.find(l=>l.doc===i.part);if(!c)throw new Error(`"${i.part}" is not a library \u2014 it is one of ${Cn.map(l=>l.doc).join(", ")}`);for(let l of i.partIds)if(!F5(e,c.doc).some(u=>u.id===l))throw new Error(`the ${c.label} library holds no "${l}"`)}}let s=t.axes.reduce((i,c)=>i*Wp(c).length,1);if(s>$m)throw new Error(`that grid is ${s} runs, over the ${$m} cap \u2014 a run is a whole session. Drop an axis or use fewer steps.`)}var T5=e=>e.map(t=>String(typeof t=="number"?Number(t.toPrecision(4)):t)).join(" \xD7 ");function P5(e,t){let r=[...new Set(e.flatMap(o=>(o.didNotFinish??[]).map(a=>a.label)))],n=e.map(o=>({name:T5(o.at),events:r.map(a=>({label:a,incomplete:o.didNotFinish?.find(s=>s.label===a)}))}));return cC(n).map(({event:o,finished:a,stopped:s})=>{let i=`${s.length} of ${e.length} points did not finish ${o}`;if(!a.length)return`${i}: every time there is a part-distance${t?" and scores zero":""}, so compare laps before time.`;let c=s.length>6?`${s.slice(0,6).join(", ")}, \u2026`:lC(s);return t?`${i}: ${c}. Their time there is a part-distance and scores zero, so read them as stopped, not slow \u2014 a points ranking favours the points that finished over faster ones that stopped.`:`${i}: ${c}. Their time there is a part-distance, so read them as stopped, not slow.`})}function L5(e){let t=[[]];for(let r of e){let n=Wp(r),o=[];for(let a of n)for(let s of t)o.push([...s,a]);t=o}return t}async function pC(e,t,r,n){C5(e,r);let o=L5(r.axes),a=[],s=!1;for(let[u,m]of o.entries()){let f=structuredClone(e),p=f.vehicles.find(k=>k.id===r.vehicleId),d={...r.settings},h={};r.axes.forEach((k,v)=>{let x=m[v];if(k.kind==="param")h[k.label]=x;else if(k.kind==="part"){let M=Cn.find(F=>F.doc===k.part);p.params[M.ref]=x}else d[k.setting]=x});let b=r.fleet?f.vehicles.filter(k=>k.visible||k.id===r.vehicleId).map(k=>k.id):[r.vehicleId],g=await Yp(f,t,{vehicleIds:b,settings:d,...Object.keys(h).length?{overrides:{[r.vehicleId]:h}}:{}});s=g.fleetScored;let y=g.vehicles.find(k=>k.id===r.vehicleId),R=y.events.flatMap(k=>k.incomplete?[{label:k.label,...k.incomplete}]:[]);a.push({at:m,metrics:y.metrics,...R.length?{didNotFinish:R}:{}}),n?.(u+1,o.length)}let i=Object.keys(a[0]?.metrics??{}),c=[];r.axes.forEach((u,m)=>{if(Wp(u).length<2)return;i.some(p=>{if(new Set(a.map(b=>`${b.at[m]}`)).size<2)return!1;let h=a.map(b=>b.metrics[p]).filter(Number.isFinite);return Math.max(...h)-Math.min(...h)>1e-9})||c.push(mC(u))});let l=[];return s&&!r.fleet&&l.push("Points here were scored with this car alone, so it takes the maximum in every event and the points axis is flat by construction. Re-run with fleet: true to price a change in points."),l.push(...P5(a,s)),c.length&&l.push(`Nothing moved along ${c.join(", ")}. Exactly zero is a wiring question before it is a finding: check that a library part is not superseding the value, and that the switch it needs is on.`),{axes:r.axes.map(u=>({kind:u.kind,label:mC(u),values:Wp(u)})),runs:a,metricKeys:i,fleetScored:s,flat:c,caveats:l}}var jfe=Math.PI/180;var jp=.5,Y5=new Set(["lap","session"]);function W5(e){return tt({...e,label:e.label.replace(/ [xyz]$/,"")})}function fC(e){let t=Po(e);if(t)return[t.point];let r=jt(e);if(r)return[r.point];let n=/^arm\.(front|rear)\.(uca|lca)\./.exec(e);if(n){let a=Ot[n[2]];return[`hp.${n[1]}.${a.fore}`,`hp.${n[1]}.${a.aft}`]}let o=/^rocker\.(front|rear)\./.exec(e);return o?[`hp.${o[1]}.${Sr.fore}`,`hp.${o[1]}.${Sr.aft}`]:[]}function hC(e,t){let r=mt(e,t),n=yt(e),o=new Map;for(let a of[...r.variables,...r.followers??[]])for(let s of fC(a.id)){if(o.has(s))continue;let i=ns.map(c=>`${s}.${c}`).filter(c=>n[c]&&!n[c].supersededBy);i.length&&o.set(s,{id:s,name:W5(n[i[0]]),coords:i})}return[...o.values()]}function Ky(e,t,r,n={},o=jp){let a=mt(e,t),s=(n.metrics??rr()).byId,i=us(e,a,r),c=hC(e,a),l=yt(i),u=[];a.objectives.forEach((A,S)=>{let C=s[A.metricId];C&&u.push({key:A.key??`target:${S}`,role:"target",metric:C,at:A.at})}),a.constraints.forEach((A,S)=>{let C=s[A.metricId];C&&u.push({key:A.key??`hold:${S}`,role:"hold",metric:C,at:A.at,hold:A})}),(a.watches??[]).forEach((A,S)=>{let C=s[A.metricId];C&&u.push({key:A.key??`watch:${S}`,role:"watch",metric:C,at:A.at})});let m=u.filter(A=>!Y5.has(A.metric.cost)),f=A=>{let S=$p(A,a,n),C=m.map(L=>ut(S,L.metric,L.at));return S.failure?null:C},p=f(i)??m.map(()=>NaN),d=[],h=[],b=[],g=1,y=[...p],R=[...p],k=A=>A.forEach((S,C)=>{Number.isFinite(S)&&(S>=y[C]||(y[C]=S),S<=R[C]||(R[C]=S))}),v=A=>{g++;try{return f(A())}catch{return null}};for(let A of c)for(let S of A.coords){let C=l[S],L=C.read(i),D=S.slice(S.lastIndexOf(".")+1),I=v(()=>C.write(i,L+o)),O=v(()=>C.write(i,L-o));if(!I||!O){b.push(`${A.name} ${D}`);continue}d.push({id:S,def:C,now:L,point:A,axis:D}),h.push([I,O]),k(I),k(O)}let x=new Map,M=A=>{let S=A.join("");if(x.has(S))return;let C=v(()=>d.reduce((L,D,I)=>D.def.write(L,D.now+A[I]*o),i));x.set(S,C),C&&k(C)};d.length>1&&m.forEach((A,S)=>{let C=h.map(([L,D])=>L[S]-p[S]>=D[S]-p[S]?1:-1);Number.isFinite(p[S])&&(M(C),M(C.map(L=>-L)))});let F=[...x.values()].filter(A=>!A).length;F&&b.push(`${F} of ${x.size} corners`);let w=u.map(A=>{let S={key:A.key,role:A.role,name:je(A.metric)+Io(A.at,A.metric,a),unit:A.metric.unit==="-"?"":A.metric.unit,...A.hold?{limit:{op:A.hold.op,limit:A.hold.limit,...A.hold.limit2!==void 0?{limit2:A.hold.limit2}:{}}}:{}},C=m.indexOf(A);if(C<0)return{...S,value:NaN,lo:NaN,hi:NaN,skipped:"read off a lap"};let L=p[C],D=Number.isFinite(L)?y[C]:NaN,I=Number.isFinite(L)?R[C]:NaN,O=h.map(([_,B])=>Math.max(Math.abs(_[C]-L),Math.abs(B[C]-L))),N=O.filter(Number.isFinite).reduce((_,B)=>_+B,0),z;if(N>0){let _=O.indexOf(Math.max(...O.filter(Number.isFinite)));z={point:d[_].point.name,axis:d[_].axis,share:O[_]/N}}let E=A.hold?Math.max(En(A.hold,D),En(A.hold,I)):void 0;return{...S,value:L,lo:D,hi:I,...z?{most:z}:{},...E!==void 0?{excess:E}:{}}}),T=new Set(c.flatMap(A=>A.coords)),P=a.variables.filter(A=>!fC(A.id).length&&!T.has(A.id)).length;return{mm:o,points:c,rows:w,evaluations:g,unsolved:b,settings:P}}function Hy(e){if(!e.chassis)return e;let{chassis:t,...r}=e;return t.boxes.length?{...r,chassis:{boxes:t.boxes}}:r}var kye=180/Math.PI;var wB={id:"racecar",label:"Race car",description:"Suspension kinematics, tyres, powertrain and quasi-steady-state lap simulation for a four-wheeled race car.",tools:["laptime","garage","kinematics","track","studies","dynamics","tires","aero","powertrain","battery","brakes","dampers","forces","calibration"],defaultRulesetId:yo,templateIds:["fs-ev-comparison","fs-endurance-energy","fs-ev-single","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor","formula-1","touring-car","street-car","cup-car","stock-car","hill-climb","race-truck","suspension","direct-coilover","pushrod","pullrod","third-spring","mcpherson-strut","tyre-study"],collections:[{id:"start",label:"Start here",description:"What the model answers, then cars to build from.",templateIds:["fs-ev-comparison","fs-endurance-energy","suspension","tyre-study","fs-ev-single","formula-1","touring-car"]},{id:"formula-student",label:"Formula Student",description:"Electric and combustion cars on the five Formula Student events, by drive layout.",templateIds:["fs-ev-comparison","fs-endurance-energy","suspension","tyre-study","fs-ev-single","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor"]},{id:"circuits",label:"Circuit racing",description:"Single-seaters, GT, cup and road cars and a race truck on real circuits, with their heights.",templateIds:["formula-1","touring-car","street-car","cup-car","race-truck"]},{id:"ovals-hill-climbs",label:"Ovals and hill climbs",description:"A banked oval, and an open course climbed from rest in thin air.",templateIds:["stock-car","hill-climb"]},{id:"kinematics",label:"Suspension and kinematics",description:"Each suspension architecture: its hardpoints, its roll centres and what it does on track.",templateIds:["suspension","direct-coilover","pushrod","pullrod","third-spring","mcpherson-strut"]},{id:"tyres",label:"Tyres",description:"Grip curves, and what a tyre is worth on track.",templateIds:["tyre-study"]},{id:"powertrain",label:"Energy and powertrain",description:"What a pack lasts, and how each drive layout puts its power down.",templateIds:["fs-endurance-energy","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor"]}]};var Xxe=wB.id;var Uc=.02;function CC(e){let t=Math.max(Uc,Math.abs(e.heaveMotionRatio)),r=Math.max(Uc,Math.abs(e.rollMotionRatio)),o=2*(e.cornerWheelRate+e.heaveWheelRate)/(t*t),a=2*(e.cornerDamper+(e.heaveWheelDamping??0))/(t*t),s=(e.cornerDamper+(e.rollWheelDamping??0))/(r*r);return{heaveRate:o,heaveDamper:a,rollWheelRate:e.cornerWheelRate+e.arbWheelRate,rollDamper:s}}var TB=(e,t)=>({od:t,id:Math.min(e.id,t-.5)}),PB=(e,t)=>e/(2*t*t);function wC(e,t){switch(e.kind){case"ubar":case"blade":case"torsionTube":return{...e,section:TB(e.section,t)};default:return e}}function TC(e,t,r){let n=Math.max(Uc,Math.abs(r));if(e?.kind==="coil"){let l=PB(t,n),u=e.rate;if(typeof u=="number")return{...e,rate:l};let m=Wr(u,0);if(!(m>0))return{...e,rate:l};let f=l/m;return{...e,rate:{...u,y:u.y.map(p=>p*f)}}}let o=t/(n*n),a=e&&(e.kind==="ubar"||e.kind==="blade"||e.kind==="torsionTube")?e:{kind:"torsionTube",section:{od:20,id:16},length:400,leverArm:60,G:8e4},s=l=>Pi(wC(a,l),0).rateAtLink,i=4,c=60;if(s(c)<o)return{kind:"direct",wheelRate:t};for(let l=0;l<80&&c-i>1e-9;l++){let u=.5*(i+c);s(u)<o?i=u:c=u}return wC(a,c)}function PC(e,t,r,n){let o=e?.design,a=TC(t?.design,r.rollWheelRate,n);return{heave:{design:{kind:"coil",rate:r.heaveRate,motionRatio:o?.kind==="coil"?o.motionRatio:1,gap:0,bothWays:!0},linkage:e?.linkage,damper:r.heaveDamper},arb:{design:a,linkage:t?.linkage,damper:a.kind==="coil"?r.rollDamper/2:r.rollDamper}}}var LB=Math.PI/180,Up=1e-6;function DB(e){return!(ve(e.rockerPivotA,e.rockerPivotB)<Up||ve(e.rockerToPushrod,e.rockerPivotA)<Up||ve(e.rockerToDamper,e.rockerPivotA)<Up||ve(e.rockerToDamper,e.damperChassis)<Up)}function IC(e){if(!DB(e.hardpoints))return!1;let t={...e,config:{...e.config,actuation:"rocker"}};try{let r=rt(t);for(let n of[-20,-1,0,1,20]){let o=ge(r,n,0);if(!o.ok||!Number.isFinite(o.state.metrics.damperLength))return!1}return!0}catch{return!1}}function _C(e){if(e.config.actuation!=="direct"||IC(e))return;let{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}=IB(e);return{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}}var LC=40;function Xp(e,t={}){let r=e.hardpoints,n=r.pushrodOuter,o=r.damperChassis,a=ve(n,o),s=ee(n,U(H(o,n),EB)),i=t.armRod??Math.max(25,.15*a),c=t.armDamper??i,l=[s[0]-LC,s[1],s[2]],u=[s[0]+LC,s[1],s[2]],m=q(H(u,l)),f=H(n,s),p=q(H(f,U(m,DC(f,m)))),d=Bt(p,m,(t.armAngleDeg??60)*LB),h=ee(s,U(d,i)),b=H(o,s),g=q(H(b,U(m,DC(b,m)))),y=U(q(ae(m,g)),t.damperSide??1),R=ee(s,U(y,c));return{...r,rockerPivotA:l,rockerPivotB:u,rockerToPushrod:h,rockerToDamper:R}}var EB=.72,DC=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2];function EC(e){let t=Ke(e,{travelMin:-5,travelMax:5,steps:3}),[r,,n]=t.samples;if(!r||!n)return 0;let o=n.travel-r.travel;return o!==0?Math.abs((n.metrics.damperLength-r.metrics.damperLength)/o):0}function IB(e,t={}){let r=t.target??EC(e),n=t.armAngleDeg,o=Xp(e,{armAngleDeg:n});if(!(r>0))return o;let a=ve(e.hardpoints.pushrodOuter,e.hardpoints.damperChassis),s=Math.max(25,.15*a),i=(()=>{for(let p of[1,-1]){let d=Xp(e,{armRod:s,armAngleDeg:n,damperSide:p}),h={...e,config:{...e.config,actuation:"rocker"},hardpoints:d};try{let b=rt(h),g=ge(b,15,0),y=ge(b,-15,0);if(g.ok&&y.ok&&g.state.metrics.damperLength<y.state.metrics.damperLength)return p}catch{}}return 1})(),c=(p,d)=>{try{return EC({...e,config:{...e.config,actuation:"rocker"},hardpoints:Xp(e,{armRod:p,armAngleDeg:n,armDamper:d,damperSide:i})})}catch{return Number.NaN}},l=[1,.6,.35,.2,1.7,2.6].map(p=>Math.max(12,s*p)),u=s,m=s,f=1/0;for(let p of l){let d=.25*p,h=6*p,b=p;for(let y=0;y<24;y++){let R=(d+h)/2,k=c(p,R);if(!Number.isFinite(k))break;b=R,k<r?d=R:h=R}let g=Math.abs(c(p,b)-r);if(Number.isFinite(g)&&g<f&&(f=g,u=p,m=b),f<1e-4*Math.max(1,r))break}return Xp(e,{armRod:u,armAngleDeg:n,armDamper:m,damperSide:i})}var lRe=Array.from({length:19},(e,t)=>-45+5*t);var uRe=Math.PI/180;function _B(e){let t=e.hardpoints,r=q(H(t.rockerPivotB,t.rockerPivotA)),n=ln(t.rockerToDamper,t.rockerPivotA,r),o=.6*cn(H(t.rockerToDamper,n)),a=ae(r,jx),s=cn(a)>1e-6?q(a):q(H(t.rockerToDamper,n));return{outer:ee(n,U(s,o)),inner:ee(n,U(s,-o)),attach:"rocker"}}var NB=(e,t)=>({...e,config:{...e.config,actuation:t}});function Wy(e,t,r,n){let o=r==="front"?e.front:e.rear,a=Hu(o),s=o.config.springRate*a*a,i=Q(t,r==="front"?"damper_front":"damper_rear")*a*a,c=r==="front"?t.arbFrontDesign:t.arbRearDesign,l=so(e,t)[r]??Q(t,r==="front"?"arb_front":"arb_rear"),u=Da(e,t)[r]??Q(t,r==="front"?"heave_spring_front":"heave_spring_rear"),m=_C(o),f=NB(m?{...o,hardpoints:{...o.hardpoints,...m}}:o,"decoupled"),p=r==="front"?t.heaveFrontDesign:t.heaveRearDesign,d=n?.heave??NC(p?.linkage,w=>Gn(f,w).atDesign)??mf(f,"rockerToRocker"),h=!c||c.design.kind==="none"||c.design.kind==="coil",b=h?"coil":"ubar",g=c?.linkage&&(c.design.kind==="none"||c.linkage.attach!=="rocker")?c.linkage:void 0,y=n?.roll??NC(h?g:c?.linkage,w=>oa(f,w,{kind:b}).atDesign)??(h?_B(f):_k(f)),R=Gn(f,d).atDesign,k=oa(f,y,{kind:b}).atDesign,v=Yu(e,t),x=CC({cornerWheelRate:s,cornerDamper:i,arbWheelRate:l,heaveWheelRate:u,heaveWheelDamping:r==="front"?v.heaveFront:v.heaveRear,rollWheelDamping:r==="front"?v.rollFront:v.rollRear,heaveMotionRatio:R,rollMotionRatio:k}),M=!c||c.design.kind==="none"?{design:{kind:"coil",rate:1},linkage:y}:{...c,linkage:y},F=PC({design:p?.design??{kind:"none"},linkage:d,damper:p?.damper},M,x,k);return m?{...F,crank:m}:F}function NC(e,t){return e&&Math.abs(t(e))>=Uc?e:void 0}var qp=[{id:"direct",name:"Direct-acting coilover",family:"GT / touring car",description:"Each lower wishbone drives a coilover straight into a chassis tower. No rod or rocker in the load path.",scope:"Both axles",tags:["Double wishbone","Coilover","Direct acting"]},{id:"pushrod",name:"Pushrod suspension",family:"Formula / prototype",description:"A rod from the lower wishbone pushes a rocker on the chassis shoulder. A 225 mm damper runs along the top at 1:1.",scope:"Both axles",tags:["Pushrod","Rocker","Inboard damper"]},{id:"pullrod",name:"Pullrod suspension",family:"Formula / low package",description:"A rod from the upper wishbone pulls a low rocker inside the side wall. A 225 mm damper runs along the floor at 1:1.",scope:"Both axles",tags:["Pullrod","Low rocker","Inboard damper"]},{id:"heave",name:"Third heave spring",family:"Formula / aero platform",description:"The pushrod car plus a front third spring worked by both rockers. It picks up after 5 mm of bump and stays out of roll.",scope:"Both axles, plus a front third spring",tags:["Pushrod","Third spring","Aero platform"]},{id:"decoupled",name:"Twin-rocker-bar decoupled modes",family:"Formula / prototype",description:"Each pushrod turns a long rocker bar. A shock between the bars takes heave, a diagonal one takes roll; no corner springs.",scope:"Both axles",tags:["Two rocker bars","Heave shock","Roll shock"]},{id:"mcpherson",name:"McPherson strut",family:"Road car",description:"A strut clamped to the upright runs up to a top mount on the tower: damper, spring seat and upper link in one. Coilover wishbones at the rear.",scope:"Front struts, rear double wishbones",tags:["McPherson","Strut","Road car"]}],jy=()=>({arbFront:void 0,arbRear:void 0,heaveFront:void 0,heaveRear:void 0}),OB={front:{rockerPivotA:[-47,223,405],rockerPivotB:[-47,267,445],rockerToPushrod:[8,242,429],rockerToDamper:[-47,190,485],damperChassis:[-272,190,485]},rear:{rockerPivotA:[65,228,415],rockerPivotB:[65,272,455],rockerToPushrod:[10,247,439],rockerToDamper:[65,195,495],damperChassis:[290,195,495]}},VB={front:{pushrodOuter:[-3,510,359],rockerPivotA:[-20,174,181],rockerPivotB:[-20,200,139],rockerToPushrod:[18,199,167],rockerToDamper:[-20,102,108],damperChassis:[205,102,108]},rear:{pushrodOuter:[-1,516,365],rockerPivotA:[39,177,181],rockerPivotB:[39,203,139],rockerToPushrod:[1,202,167],rockerToDamper:[39,112,111],damperChassis:[-186,112,111]}},BB=()=>({outer:[0,189,486],attach:"rocker",mount:{kind:"chassis",anchor:[-225,0,486]}}),$B={rate:60,motionRatio:1},GB={front:{rockerPivotA:[-50,310,621],rockerPivotB:[-50,357,659],rockerToPushrod:[10,330,644],rockerToDamper:[-50,281,704],damperChassis:[-275,281,704]},rear:{rockerPivotA:[73,306,621],rockerPivotB:[73,352,659],rockerToPushrod:[13,326,644],rockerToDamper:[73,271,710],damperChassis:[298,271,710]}},KB=e=>e==="front"?{outer:[-2,280,705],attach:"rocker",mount:{kind:"chassis",anchor:[-227,0,705]}}:{outer:[25,270,711],attach:"rocker",mount:{kind:"chassis",anchor:[250,0,711]}},HB={kind:"coil",rate:1560,motionRatio:1,gap:0,bothWays:!0},zB=40,YB={rockerPivotA:[50,130,440],rockerPivotB:[-50,130,440],rockerToPushrod:[10,170,460],rockerToDamper:[-20,64,440],damperChassis:[-20,64,215]},OC=()=>({outer:[-50,130,480],attach:"rocker",shaftStation:-50}),VC=()=>({outer:[50,130,400],inner:[50,130,480],attach:"rocker",shaftStationOuter:50,shaftStationInner:50}),WB=e=>[e[0],e[1],e[2]];function jB(e){let t=r=>({...r,hardpoints:{...r.hardpoints,...$C(YB)},config:{...r.config,actuation:"decoupled"}});return{...e,front:t(e.front),rear:t(e.rear)}}function $C(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,WB(r)]))}function GC(e,t=So(),r=e==="pull"?VB:OB){let n=(o,a)=>({...o,hardpoints:{...o.hardpoints,...$C(r[a])},config:{...o.config,actuation:"rocker",rodType:e,...e==="pull"?{pushrodAttach:"upperArm"}:{}}});return{...t,front:n(t.front,"front"),rear:n(t.rear,"rear")}}function Qp(e,t){let r=Uy(e),n=ps(e);if(e==="heave")return{meta:r,vehicle:n,components:{...jy(),heaveFront:{design:{...wb,...$B},linkage:BB()}}};if(e!=="decoupled")return{meta:r,vehicle:n,components:jy()};let o=Wy(n,t,"front",{heave:OC(),roll:VC()}),a=Wy(n,t,"rear",{heave:OC(),roll:VC()});return{meta:r,vehicle:n,components:{arbFront:o.arb,arbRear:a.arb,heaveFront:o.heave,heaveRear:a.heave}}}function ps(e){let{name:t}=Uy(e);if(e==="direct")return{...fc(),name:t};if(e==="mcpherson"){let n=hc(),o=Wm();return{...n,front:{...o,config:{...o.config,loadedRadius:n.front.config.loadedRadius}},name:t}}let r=UB(GC(e==="pullrod"?"pull":"push"));return{...e==="decoupled"?jB(r):r,name:t}}var BC={front:221.7,rear:220.9};function UB(e){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:BC.front}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:BC.rear}}}}function Uy(e){let t=qp.find(r=>r.id===e);if(!t)throw new Error(`Unknown suspension template: ${e}`);return t}function Zp(){let e=t=>({design:{...HB},linkage:KB(t),damper:zB});return{meta:Uy("heave"),vehicle:GC("push",$g(),GB),components:{...jy(),heaveFront:e("front"),heaveRear:e("rear")}}}var KC=[10,25,50,100,200,300],XB=[{id:"c1",label:"Soft",scale:.7},{id:"c2",label:"Medium",scale:1},{id:"c3",label:"Firm",scale:1.4}],HC=e=>Math.round(e*100)/100;function qB(e,t,r){let n=KC.map(o=>HC(r*o));return{id:e,label:t,speedMmS:[...KC],bumpN:n,reboundN:[...n]}}function QB(e){return{name:e.name,body:{...e.body},curves:XB.map(t=>qB(t.id,t.label,HC(e.coefficient*t.scale)))}}function Xc(e,t){let r=(t.heave??t.car).coefficient,n=(t.roll??t.car).coefficient,o=(a,s)=>a?.damper?{...a,damper:s}:a;return{arbFront:o(e.arbFront,n),arbRear:o(e.arbRear,n),heaveFront:o(e.heaveFront,r),heaveRear:o(e.heaveRear,r)}}function Ar(e,t){let r=i=>{if(!i)return;let c=e.dampers.length+1;for(;e.dampers.some(u=>u.id===`dmp${c}`);)c++;let l=`dmp${c}`;return e.dampers.push({id:l,color:vc[e.dampers.length%vc.length],model:QB(i)}),l},n=r(t.car),o=r(t.rear),a=r(t.heave),s=r(t.roll);for(let i of e.vehicles){let c=i.params;c.damperModelId=n,o&&(c.damperModelIdRear=o),a&&(c.heaveDamperModelId=a),s&&(c.rollDamperModelId=s)}}var pt=e=>`${e} (typical)`,Xy={car:{name:pt("Formula Student damper"),coefficient:2.5,body:{extended:249,stroke:55}}},Jp={car:Xy.car,heave:{name:pt("Formula Student heave damper"),coefficient:3.4,body:{extended:270,stroke:47}},roll:{name:pt("Formula Student roll damper"),coefficient:3.7,body:{extended:322,stroke:100}}},ed={car:{name:pt("Formula 1 damper"),coefficient:6,body:{extended:240,stroke:40}},heave:{name:pt("Formula 1 heave damper"),coefficient:40,body:{extended:240,stroke:40}}},zC={car:{name:pt("GT damper"),coefficient:4.5,body:{extended:510,stroke:80}}},qy={car:{name:pt("Sports car damper"),coefficient:2.4,body:{extended:515,stroke:110}}},YC={car:{name:pt("Sports car strut"),coefficient:2.4,body:{extended:310,stroke:120}},rear:qy.car},WC={car:{name:pt("Cup car strut"),coefficient:4,body:{extended:285,stroke:75}},rear:{name:pt("Cup car rear damper"),coefficient:3.5,body:{extended:505,stroke:80}}},jC={car:{name:pt("Stock car front damper"),coefficient:7.5,body:{extended:555,stroke:110}},rear:{name:pt("Stock car rear damper"),coefficient:6.75,body:{extended:555,stroke:110}}},UC={car:{name:pt("Hill-climb front damper"),coefficient:3,body:{extended:285,stroke:65}},rear:{name:pt("Hill-climb rear damper"),coefficient:3.5,body:{extended:285,stroke:65}}},XC={car:{name:pt("Race truck front damper"),coefficient:12,body:{extended:780,stroke:160}},rear:{name:pt("Race truck rear damper"),coefficient:8.5,body:{extended:780,stroke:160}}};function fs(e){return e.vehicles=e.vehicles.slice(0,1),e.activeVehicleId=e.vehicles[0]?.id??null,e}function In(e,t){let r=kc(e);return r.meta.rulesetId=t,r}function Vo(e,t,r,n){let o=In(e,t);return o.suspensions=[{...o.suspensions[0],model:n()}],o.vehicles=[p0(r,"v1",0)],o.activeVehicleId="v1",o}var[,ZB,JB,e$,t$,r$,n$,o$]=Ug;function Qy(e,t){delete e.arbFrontDesign,delete e.arbRearDesign,delete e.heaveFrontDesign,delete e.heaveRearDesign,t.arbFront&&(e.arbFrontDesign=structuredClone(t.arbFront)),t.arbRear&&(e.arbRearDesign=structuredClone(t.arbRear)),t.heaveFront&&(e.heaveFrontDesign=structuredClone(t.heaveFront)),t.heaveRear&&(e.heaveRearDesign=structuredClone(t.heaveRear))}function qC(){return{...ps("decoupled"),name:So().name}}var a$=[{label:"Formula Student (decoupled)",vehicle:qC,components:e=>Xc(Qp("decoupled",e).components,Jp)},{label:"Formula 1 (third springs)",vehicle:()=>Zp().vehicle,components:()=>Xc(Zp().components,ed)}],Zy={"direct-coilover":"direct",pushrod:"pushrod",pullrod:"pullrod","third-spring":"heave","mcpherson-strut":"mcpherson"},s$=[...a$.map(e=>e.vehicle),...Object.values(Zy).map(e=>()=>ps(e))];function ds(e){let t=Xc(Qp("decoupled",e.vehicles[0].params).components,Jp);e.suspensions=[{...e.suspensions[0],model:qC()}];for(let r of e.vehicles)Qy(r.params,t);return Ar(e,Jp),e}var Bo={title:"OpenStreetMap",url:"https://www.openstreetmap.org/copyright",licence:"ODbL-1.0",credit:"\xA9 OpenStreetMap contributors"},td={title:"USGS 3D Elevation Program, 1 m lidar terrain",url:"https://www.usgs.gov/3d-elevation-program",licence:"public-domain",credit:"U.S. Geological Survey, 3D Elevation Program"},QC={title:"Digitales Gel\xE4ndemodell DGM1 Rheinland-Pfalz",url:"https://www.geoportal.rlp.de/",licence:"dl-de-by-2.0",credit:"\xA9GeoBasis-DE / LVermGeoRP 2025, dl-de/by-2-0, www.lvermgeo.rlp.de [Daten bearbeitet]"},ZC={title:"USDA National Agriculture Imagery Program (NAIP), 0.6 m aerial imagery",url:"https://imagery.nationalmap.gov/arcgis/rest/services/USGSNAIPImagery/ImageServer",licence:"public-domain",credit:"USDA Farm Service Agency, National Agriculture Imagery Program, via the USGS National Map"},i$={id:"cota",name:"Circuit of the Americas, Austin",address:"e0c6ea889d708cf15f9c",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Bo,td,ZC]}},c$={id:"laguna-seca",name:"Laguna Seca, Monterey",address:"185b5811b9c423ef44ef",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Bo,td,ZC]}},l$={id:"nordschleife",name:"Nordschleife, N\xFCrburg",address:"74c49603c7b2f15985c6",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Bo,QC]}},u$={id:"brands-hatch",name:"Brands Hatch, Kent",address:"c4953e3c25eaba4a5b7e",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Bo,{title:"Environment Agency LIDAR Composite DTM, 1 m",url:"https://environment.data.gov.uk/dataset/13787b9a-26a4-4775-8523-806d13af58fc",licence:"OGL-UK-3.0",credit:"\xA9 Environment Agency copyright and/or database right 2022. All rights reserved."}]}},m$={id:"bristol",name:"Bristol, Tennessee",address:"f0e23953669a414ad600",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Bo,td]}},p$={id:"pikes-peak",name:"Pikes Peak, Colorado",address:"3de137fe33b5c2875036",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Bo,td]},standingStart:!0},d$={source:"venue",altitudeM:3580,pressure:{kind:"standard"},humidityPct:0},f$=10,h$={id:"nurburg-sprint",name:"Sprintstrecke, N\xFCrburg",address:"1875636cdbb615aa2756",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Bo,QC]}};function $o(e,t){let{id:r,name:n,address:o,provenance:a,standingStart:s}=t,i={kind:"catalogue",id:r,address:o},c=bc(o0({name:n,source:i}).model,structuredClone(a));return e.tracks=[{id:"tr1",name:n,source:i,provenance:c,...s?{standingStart:s}:{}}],e.activeTrackId="tr1",e.settings.standingStart=s===!0,e}function _n(e,t,r){let n=e.vehicles[0].params,o=`m${e.motors.length+1}`;e.motors=[...e.motors,{id:o,color:Tn[e.motors.length%Tn.length],model:t}];let a=rM({},{...n,motorModel:t});n.motorModelId=o,n.motorCount=1,a&&(n.driveline=a),n.gear_ratio&&(n.gear_ratio={...n.gear_ratio,value:r})}var b$=3.8,rd={hubPlanetary:14.5,inboardChain:4,engineChain:3.4},g$="Hub motor, 35 kW (example)";function Jy(e,t,r,n,o,a){let s=e.vehicles[0].params;s.motorModelId=t,s.motorCount=r,s.motorPlacement=n,a&&(s.motorMount=a),s.driven_wheels={...s.driven_wheels,value:n==="awd"?4:2},s.gear_ratio={...s.gear_ratio,value:o}}function JC(e){let t=e.motors.find(r=>r.id==="m1");return t.model={...t.model,name:g$},t.id}function nd(e,t,r){let n=fs(ds(In(e,r)));return n.vehicles[0].params.name=t,n}function y$(){let e=nd("Formula Student combustion car","Formula Student combustion","fs-cv");_n(e,Jg(),rd.engineChain);let t=e.vehicles[0].params;return t.power_limit_kw&&(t.power_limit_kw={...t.power_limit_kw,value:0}),t.endurance_reserve&&(t.endurance_reserve={...t.endurance_reserve,value:0}),e}function x$(){let e=nd("Formula Student AWD car","Formula Student AWD","fs-ev");return Jy(e,JC(e),4,"awd",rd.hubPlanetary,"hub"),e}function R$(){let e=nd("Formula Student RWD hub-motor car","Formula Student RWD hub motors","fs-ev");return Jy(e,JC(e),2,"rear",rd.hubPlanetary,"hub"),e}function v$(){let e=nd("Formula Student one-motor car","Formula Student RWD one motor","fs-ev"),t=`m${e.motors.length+1}`;return e.motors=[...e.motors,{id:t,color:Tn[e.motors.length%Tn.length],model:Zg()}],Jy(e,t,1,"rear",rd.inboardChain),e.vehicles[0].params.driveline={rear:structuredClone(St.clutch)},e}function k$(){let e=fs(ds(In("Formula Student endurance energy","fs-ev"))),t=e.vehicles[0],r=structuredClone(t);if(r.id="v2",r.color=Rc[1],r.params.name=`${t.params.name} flat out`,!r.params.endurance_reserve)throw new Error("the Formula Student preset states no energy reserve");return r.params.endurance_reserve={...r.params.endurance_reserve,value:0},e.vehicles.push(r),e}function M$(){let e=Zp(),t=Vo("Formula 1 car","trackday",ZB,()=>e.vehicle);return Qy(t.vehicles[0].params,Xc(e.components,ed)),Ar(t,ed),_n(t,e0(),b$),$o(t,i$)}function eT(e="GT car",t=fc){let r=Vo(e,"trackday",JB,t);return Ar(r,zC),_n(r,PA(),r.vehicles[0].params.gear_ratio.value),$o(r,c$)}function tT(e="Sports car",t=hc,r=qy){let n=Vo(e,"trackday",e$,t);return Ar(n,r),_n(n,LA(),n.vehicles[0].params.gear_ratio.value),$o(n,l$)}function S$(){let e=Vo("Cup car","trackday",t$,yA);return Ar(e,WC),_n(e,DA(),e.vehicles[0].params.gear_ratio.value),$o(e,u$)}function A$(){let e=Vo("Stock car","trackday",r$,xA);return Ar(e,jC),_n(e,EA(),e.vehicles[0].params.gear_ratio.value),$o(e,m$)}function F$(){let e=Vo("Hill-climb prototype","trackday",n$,RA);return Ar(e,UC),_n(e,IA(),e.vehicles[0].params.gear_ratio.value),e.settings.air=structuredClone(d$),e.settings.airTempC=f$,$o(e,p$)}function w$(){let e=Vo("Race truck","trackday",o$,vA);return Ar(e,XC),_n(e,_A(),e.vehicles[0].params.gear_ratio.value),$o(e,h$)}function C$(e){let t=qp.find(o=>o.id===e);if(e==="direct")return eT(t.name,()=>ps(e));if(e==="mcpherson")return tT(t.name,()=>ps(e),YC);let r=fs(In(t.name,"trackday")),n=Qp(e,r.vehicles[0].params);return r.suspensions=[{...r.suspensions[0],model:n.vehicle}],Qy(r.vehicles[0].params,n.components),Ar(r,Xy),r}function qc(e,t,r){let n=Zy[e],o=qp.find(a=>a.id===n);return{id:e,domain:"racecar",kind:"start",summary:t,title:o.name,blurb:`${o.description} ${r} Move a hardpoint in Kinematics and watch the motion ratio, camber and roll centre follow, then what it costs on track.`,tags:["kinematics","suspension",...o.tags.map(a=>a.toLowerCase())],openTool:"kinematics",load:()=>C$(n)}}var T$=[{id:"fs-ev-comparison",domain:"racecar",kind:"study",summary:"Four Formula Student cars scored on all five events: what mass, power and downforce buy.",title:"Formula Student \u2014 car comparison",blurb:"A generic Formula Student electric car and three what-ifs \u2014 15 % more downforce, 15 kg lighter, 15 % more power \u2014 scored side by side on the Formula Student electric events. All four run decoupled heave and roll suspension. A good first look at what each change buys.",tags:["formula student","comparison","lap sim"],openTool:"laptime",load:()=>ds(In("Formula Student comparison","fs-ev"))},{id:"fs-endurance-energy",domain:"racecar",kind:"study",summary:"The FS car flat out against its energy target: which finishes endurance, and the points.",title:"Formula Student \u2014 endurance energy",blurb:"The generic Formula Student electric car twice, scored together on the Formula Student electric events: once driven to its energy target, once flat out. The two differ in the endurance reserve and nothing else. Flat out the car laps faster and its pack runs out before the flag; on the target its speed is capped so the pack finishes with 5 % left. The endurance event shows the charge lap by lap, and the points what running dry costs.",tags:["formula student","endurance","energy","battery"],openTool:"laptime",load:k$},{id:"fs-ev-single",domain:"racecar",kind:"start",summary:"A generic Formula Student electric car on the five events, to set up as your own.",title:"Formula Student \u2014 single car",blurb:"One generic Formula Student electric car on the Formula Student electric events: 300 kg with driver, two motors, 80 kW, 10-inch tyres, decoupled heave and roll suspension. The uncluttered starting point for setting up your own car.",tags:["formula student","lap sim"],openTool:"laptime",load:()=>fs(ds(In("Formula Student car","fs-ev")))},{id:"fs-combustion",domain:"racecar",kind:"start",summary:"A restricted 600 cc four through six gears and a clutch-pack diff, on the CV events.",title:"Formula Student \u2014 combustion, LSD",blurb:"The generic Formula Student car with an engine: a restricted 600 cc four of about 64 kW through a six-speed box and a chain to a clutch-pack limited-slip diff, on the Formula Student combustion events. The same 300 kg chassis, tyres and decoupled suspension as the electric layouts, so the drive is the difference. Efficiency is scored on the work at the crankshaft until fuel is modelled. Representative of the class, not a measurement of any car.",tags:["formula student","combustion","engine","limited-slip diff","lsd","lap sim"],openTool:"laptime",load:y$},{id:"fs-ev-awd",domain:"racecar",kind:"start",summary:"All-wheel drive from a motor in each hub, held to 80 kW at the pack.",title:"Formula Student \u2014 AWD, four hub motors",blurb:"The generic Formula Student electric car with a motor in each of its four hubs: 35 kW hub motors on 14.5 : 1 planetaries, held to the rules\u2019 80 kW at the pack, each wheel\u2019s torque its own and every wheel braking back into the pack. The same 300 kg chassis, tyres, suspension and pack as the other layouts, so the drive is the difference; the hub motors\u2019 unsprung mass is not added. Representative of the class, not a measurement of any car.",tags:["formula student","awd","all-wheel drive","hub motors","outboard motors","lap sim"],openTool:"laptime",load:x$},{id:"fs-ev-rwd-hubs",domain:"racecar",kind:"start",summary:"Rear-wheel drive from a motor in each rear hub, with no diff between them.",title:"Formula Student \u2014 RWD, two hub motors",blurb:"The generic Formula Student electric car driven by a motor in each rear hub: two 35 kW hub motors on 14.5 : 1 planetaries with no differential between them, so each rear wheel\u2019s torque is set on its own. The pair cannot use all of the rules\u2019 80 kW. The same 300 kg chassis, tyres, suspension and pack as the other layouts, so the drive is the difference. Representative of the class, not a measurement of any car.",tags:["formula student","rwd","rear-wheel drive","hub motors","outboard motors","lap sim"],openTool:"laptime",load:R$},{id:"fs-ev-one-motor",domain:"racecar",kind:"start",summary:"One inboard motor chained to a clutch-pack diff on the rear axle.",title:"Formula Student \u2014 RWD, one motor, LSD",blurb:"The generic Formula Student electric car on one inboard motor: an axial-flux motor of 230 Nm on the chassis, chained at 4 : 1 to a clutch-pack limited-slip diff on the rear axle. The rules\u2019 80 kW at the pack holds it below its peak, and it brakes back into the pack through the diff. The same 300 kg chassis, tyres, suspension and pack as the other layouts, so the drive is the difference. Representative of the class, not a measurement of any car.",tags:["formula student","rwd","inboard motor","limited-slip diff","lsd","lap sim"],openTool:"laptime",load:v$},{id:"formula-1",domain:"racecar",kind:"start",summary:"A generic Formula 1 car on a flying lap of Austin.",title:"Formula 1 car",blurb:"A generic Formula 1 car of the 18-inch era at Austin: 798 kg with driver, a 735 kW power unit through eight gears and a clutch-pack diff, four and a half square metres of lift area on a 3.6 m wheelbase, pushrods with a third spring and heave damper on each axle, slicks with 1.8 of peak grip. One flying lap, no scoring. Every number is representative of the class, none is a measurement.",tags:["formula 1","lap sim","aero"],openTool:"laptime",load:M$},{id:"touring-car",domain:"racecar",kind:"start",summary:"A generic GT car on a flying lap of Laguna Seca.",title:"GT car",blurb:"A generic GT car at Laguna Seca: 1300 kg with driver, a 410 kW four-litre through six gears and a clutch-pack diff, 2.8 m\xB2 of lift area, coilovers on double wishbones, 18-inch slicks. One flying lap, no scoring. Representative of the class, not a measurement of any car.",tags:["gt","lap sim"],openTool:"laptime",load:eT},{id:"street-car",domain:"racecar",kind:"start",summary:"A generic sports car on road tyres, round the Nordschleife.",title:"Sports car",blurb:"A generic sports car on the Nordschleife: 1600 kg with driver, a 220 kW turbocharged six through a six-speed double-clutch box and an open diff, road tyres with about 1.0 of grip, soft springs and a little aerodynamic lift. One flying lap, no scoring. The car to start from when the question is a road car, and the one that shows what a race car's numbers actually buy.",tags:["sports car","road car","lap sim"],openTool:"laptime",load:tT},{id:"cup-car",domain:"racecar",kind:"start",summary:"A generic front-driven cup hatchback round Brands Hatch.",title:"Cup car",blurb:"A generic front-wheel-drive cup hatchback at Brands Hatch: 1265 kg with driver, a 250 kW two-litre turbo through six gears and a clutch-pack diff, a splitter and a wing, a McPherson strut front, 18-inch slicks. One flying lap, no scoring. Representative of the class, not a measurement of any car.",tags:["cup car","front-wheel drive","lap sim"],openTool:"laptime",load:S$},{id:"stock-car",domain:"racecar",kind:"start",summary:"A generic stock car on Bristol\u2019s half-mile, banked 25\xB0.",title:"Stock car",blurb:"A generic stock car of the American oval series at Bristol, the half-mile banked 25\xB0: 1620 kg with driver, a 500 kW 5.9-litre V8 through five gears and a clutch-pack diff, double wishbones on stiff springs, 18-inch slicks, set up the same on both sides. One flying lap, no scoring. Representative of the class, not a measurement of any car.",tags:["stock car","oval","lap sim"],openTool:"laptime",load:A$},{id:"hill-climb",domain:"racecar",kind:"start",summary:"A generic hill-climb prototype up Pikes Peak, from rest, in thin air.",title:"Hill-climb prototype",blurb:"A generic hill-climb sports prototype on Pikes Peak, 19.99 km and 1,440 m up to the summit: 650 kg with driver, a 330 kW turbocharged two-litre through six gears and a clutch-pack diff, 3 m\xB2 of lift area, pushrods, 13-inch slicks. It runs in the mountain\u2019s thin air, which costs its wings a third of their downforce. One run, no scoring. Representative of the class, not a measurement of any car.",tags:["hill climb","altitude","lap sim"],openTool:"laptime",load:F$},{id:"race-truck",domain:"racecar",kind:"start",summary:"A generic European race truck round the N\xFCrburg Sprintstrecke, held to 160 km/h.",title:"Race truck",blurb:"A generic European circuit race truck on the N\xFCrburg Grand Prix circuit\u2019s 3.6 km Sprintstrecke: a cab-over tractor at the class\u2019s 5300 kg minimum, 60 % of it on the front axle, an 880 kW 13-litre diesel through a twelve-speed box to a locked rear axle, geared to the 160 km/h the rules hold it to, 315/70 R22.5 tyres. One flying lap, no scoring. Representative of the class, not a measurement of any truck.",tags:["race truck","truck racing","lap sim"],openTool:"laptime",load:w$},{id:"suspension",domain:"racecar",kind:"study",summary:"The FS car\u2019s decoupled wishbones: move a hardpoint and watch the roll centre follow.",title:"Suspension kinematics study",blurb:"Opens on the double-wishbone editor with one Formula Student car. Move a hardpoint and watch camber, bump steer, motion ratio and roll-centre migration follow \u2014 then see what it costs on track.",tags:["kinematics","geometry"],openTool:"kinematics",load:()=>fs(ds(In("Suspension study","trackday")))},qc("direct-coilover","The GT car\u2019s wishbones driving coilovers straight into the towers, at Laguna Seca.","On the GT car, at Laguna Seca."),qc("pushrod","The FS car on pushrods: a rod from each lower wishbone works a rocker.","On the Formula Student car, at FSG."),qc("pullrod","The FS car on pullrods: a rod from each upper wishbone pulls a low rocker.","On the Formula Student car, at FSG."),qc("third-spring","The pushrod FS car plus a front third spring that picks up after 5 mm of bump.","On the Formula Student car, at FSG."),qc("mcpherson-strut","The sports car on McPherson struts at the front and double wishbones at the rear.","On the sports car, at the Nordschleife."),{id:"tyre-study",domain:"racecar",kind:"study",summary:"The FS tyre\u2019s grip curves at three loads, beside the other classes\u2019 tyres.",title:"Tyre model study",blurb:"One Formula Student car on its Magic Formula tyre, opened on the tyre analysis, where the grip curves that drive the whole lap come from. The library beside it holds the other seven classes' tyres and the illustrative MF6.2 example to compare against.",tags:["tyres","magic formula"],openTool:"tires",load:()=>fs(ds(In("Tyre study","fs-ev")))}],rT=T$.map(e=>({...e,load:()=>d0(e.load())}));var nT={width:320,height:200},URe=[.6*nT.width-9,.6*nT.height-9];var oT=new WeakMap,aT=new WeakMap,ex=e=>JSON.stringify(e,(t,r)=>r===1/0?"Infinity":r);function sT(e,t){if(!t){let a=oT.get(e);return a||(a=It(e),oT.set(e,a)),a}let r=aT.get(e);r||(r=new Map,aT.set(e,r));let n=ex(t),o=r.get(n);return o||(r.size>=4&&r.clear(),o=It(e,t),r.set(n,o)),o}var D$=Math.PI/180,E$=e=>e>1?e/100:e;function Qc(e){let t=null;return()=>(t??={v:e()}).v}function iT(e){let t=Ke(e,{travelMin:-1,travelMax:1,steps:3}).samples[1],r=t.metrics.motionRatio??1;return{motionRatio:r,wheelRate:t.metrics.wheelRate??e.config.springRate*r*r}}var cT=new WeakMap,tx={heave:0,pitch:0,roll:0,steer:0},lT=[0,1,2,3,4],uT=[-20,-10,0,10,20];function pT(e,t){let r=jr(e,tx),n=["front","rear"],o=c=>{let l=Di(c);return l?(l.left+l.right)/2:Number.NaN},a=n.map(c=>o(r[c])),s=n.map(()=>({rc:[],split:[]}));for(let c of lT){let l=c===0?null:jr(e,{...tx,roll:c*D$});n.forEach((u,m)=>{let f=l?Di(l[u]):null,p=f&&Number.isFinite(a[m]);s[m].rc.push(p?t[m]+(f.left+f.right)/2-a[m]:t[m]),s[m].split.push(p?(f.left-f.right)/2:0)})}let i=n.map(()=>[]);for(let c of uT){let l=c===0?null:jr(e,{...tx,heave:-c});n.forEach((u,m)=>{let f=l&&l[u].valid&&r[u].valid;i[m].push(f?t[m]+l[u].height-r[u].height:t[m])})}return{roll:{rollDeg:lT,rcFront:s[0].rc,rcRear:s[1].rc,rcSplitFront:s[0].split,rcSplitRear:s[1].split},heave:{drop:uT,rcFront:i[0],rcRear:i[1]}}}var mT=new WeakMap;function I$(e,t,r,n){let o=mT.get(e);o||(o=new Map,mT.set(e,o));let a=`${ex(r)}|${n[0]}|${n[1]}`,s=o.get(a);if(!s){o.size>=4&&o.clear();try{s=pT(sT(e,r),n)}catch{s=t.rigidMigration(n)}o.set(a,s)}return s}function _$(e){let t=cT.get(e);if(t)return t;let r=It(e),n=jr(r,{heave:0,pitch:0,roll:0,steer:0}),o=iT(e.front),a=iT(e.rear),s={wheelbase:e.config.wheelbase,trackFront:Rt(e.front),trackRear:Rt(e.rear),mrFront:o.motionRatio,mrRear:a.motionRatio,wheelRateFront:o.wheelRate,wheelRateRear:a.wheelRate,unsprungCgHeight:e.front.config.loadedRadius,rcHeightFront:n.front.valid?n.front.heightAboveGround:0,rcHeightRear:n.rear.valid?n.rear.heightAboveGround:0,rcGainFront:La(n.front),rcGainRear:La(n.rear),rigidMigration:i=>pT(r,i),kinFront:Qc(()=>ha(e.front)),kinRear:Qc(()=>ha(e.rear))};return cT.set(e,s),s}function dT(e,t,r,n){let o=_$(e),a=so(e,t),s=Da(e,t),i=Xk(e,t),c=Yu(e,t),l=qk(e,t),u=Qk(t),m=Wu(e,t),f=ao(e.front),p=ao(e.rear),d=oo(t.damperModel,t.damperSetup,o.mrFront,o.mrRear,t.damperModelRear??t.damperModel),h={rho:t.rho.value,area:t.A.value,cl:t.c_l.value,cw:t.c_w.value,copLongFront:1-Math.max(0,Math.min(1,Q(t,"cop_long"))),copHeight:Q(t,"cop_height"),...t.aeroModel?{model:t.aeroModel}:{},rideHeightFront:Q(t,"ride_height_front"),rideHeightRear:Q(t,"ride_height_rear")},b=9.81,g=E$(t.front_mass_diss.value),y=Ia(t,r,n),R=Pe(y.front),k=y.rear===y.front?R:Pe(y.rear),v=n??t.tireModelRear??r,x=t.m.value*b*g/2,M=t.m.value*b*(1-g)/2,F=R.corneringStiffness(x),w=k.corneringStiffness(M),T=(r?R.verticalStiffness():0)||Q(t,"tire_vertical_rate"),P=(v?k.verticalStiffness():0)||Q(t,"tire_vertical_rate"),A=mr(r)??0,S=mr(v)??0,C=Qu({freeRadius:A,staticLoad:x,tyreRate:T,surveyed:e.front.config.loadedRadius},{freeRadius:S,staticLoad:M,tyreRate:P,surveyed:e.rear.config.loadedRadius},g),L=Yt(A,x,T,e.front.config.loadedRadius),D=Yt(S,M,P,e.rear.config.loadedRadius),I=[Ur(o.rcHeightFront,o.rcGainFront,e.front.config.loadedRadius,L),Ur(o.rcHeightRear,o.rcGainRear,e.rear.config.loadedRadius,D)],O=Qc(()=>Oi(o.kinFront(),Q(t,"camber_front_deg"))),N=Qc(()=>Oi(o.kinRear(),Q(t,"camber_rear_deg"))),z=Qc(()=>I$(e,o,rs(B),I)),E=pi({...t,wheelbase:{...t.wheelbase,value:o.wheelbase}}),_=Ni(t),B={massTotal:t.m.value,frontMassFrac:g,steeringSystem:t.steeringSystem,tv:Lu(t),cgHeight:Ea(Q(t,"cg_height"),t.cgReference?.standingRadius,C),cgStandingRadius:C,wheelbase:o.wheelbase,trackFront:o.trackFront,trackRear:o.trackRear,wheelRateFront:f?0:o.wheelRateFront,wheelRateRear:p?0:o.wheelRateRear,decoupledFront:f,decoupledRear:p,...u.front?{elementLinkagesFront:u.front}:{},...u.rear?{elementLinkagesRear:u.rear}:{},...m.front.source==="part"?{cornerCoiloverFront:m.front.coilover}:{},...m.rear.source==="part"?{cornerCoiloverRear:m.rear.coilover}:{},...m.heaveFront.coilover?{heaveCoiloverFront:m.heaveFront.coilover}:{},...m.heaveRear.coilover?{heaveCoiloverRear:m.heaveRear.coilover}:{},...i.front&&!f?{heaveSeatFront:i.front}:{},...i.rear&&!p?{heaveSeatRear:i.rear}:{},...m.rollFront.coilover?{rollCoiloverFront:m.rollFront.coilover}:{},...m.rollRear.coilover?{rollCoiloverRear:m.rollRear.coilover}:{},tireRate:T,...P!==T?{tireRateRear:P}:{},tireDamping:Q(t,"tire_vertical_damping"),arbFront:a.front??Q(t,"arb_front"),arbRear:a.rear??Q(t,"arb_rear"),brakeBalanceFront:E.balanceFront,brakes:E,..._?{driveline:_}:{},heaveSpringFront:s.front??Q(t,"heave_spring_front"),heaveSpringRear:s.rear??Q(t,"heave_spring_rear"),unsprungPerCorner:Q(t,"unsprung_mass"),unsprungCgHeight:Yt(A,x,T,o.unsprungCgHeight),tyreFreeRadius:A,...S!==A?{tyreFreeRadiusRear:S}:{},rcHeightFront:I[0],rcHeightRear:I[1],corneringStiffnessFront:F,corneringStiffnessRear:w,get kinFront(){return O()},get kinRear(){return N()},damperFront:f?0:d?.front?.rate??Q(t,"damper_front")*o.mrFront*o.mrFront,damperRear:p?0:d?.rear?.rate??Q(t,"damper_rear")*o.mrRear*o.mrRear,...d?.front&&!f?{damperCurveFront:d.front.curve}:{},...d?.rear&&!p?{damperCurveRear:d.rear.curve}:{},heaveDamperFront:l.heaveFront?.rate??c.heaveFront,heaveDamperRear:l.heaveRear?.rate??c.heaveRear,rollDamperFront:l.rollFront?.rate??c.rollFront,rollDamperRear:l.rollRear?.rate??c.rollRear,...l.heaveFront?{heaveDamperCurveFront:l.heaveFront.curve}:{},...l.heaveRear?{heaveDamperCurveRear:l.heaveRear.curve}:{},...l.rollFront?{rollDamperCurveFront:l.rollFront.curve}:{},...l.rollRear?{rollDamperCurveRear:l.rollRear.curve}:{},unsprungCornerMass:Q(t,"unsprung_mass"),get rollCentreCurve(){return z().roll},get rcHeaveCurve(){return z().heave},aero:h,yawInertia:Q(t,"I_yaw"),rollInertia:Q(t,"I_roll"),pitchInertia:Q(t,"I_pitch"),get steerFront(){return ju(e.front,L)},ackermannPct:Q(t,"ackermann_pct"),toeFrontDeg:Q(t,"toe_front_deg"),toeRearDeg:Q(t,"toe_rear_deg")};return B}var hT=e=>({tire:t=>t==null?void 0:t===e.tireModelIdRear&&e.tireModelRear?e.tireModelRear:e.tireModel,motor:()=>e.motorModel,aero:()=>e.aeroModel,battery:()=>e.batteryModel,brake:()=>e.brakeModel,damper:t=>t!=null&&t===e.damperModelIdRear&&e.damperModelRear?e.damperModelRear:t!=null&&t===e.heaveDamperModelId?e.heaveDamperModel:t!=null&&t===e.rollDamperModelId?e.rollDamperModel:e.damperModel}),nx={ggvMode:"twoTrack"},fT=new WeakMap;function ox(e,t=nx){let r=fT.get(e.vehicle);r||fT.set(e.vehicle,r=new WeakMap);let n=r.get(e.params);n||r.set(e.params,n=new Map);let o=JSON.stringify(t),a=n.get(o);if(!a){n.size>=8&&n.clear();let s={...hT(e.params),suspensionOf:()=>e.vehicle};n.set(o,a=Oo(e.params,s,t))}return a}var bT=(e=nx)=>t=>ox(t,e),gT=(e=nx)=>t=>dT(t.vehicle,$y(t.params,hT(t.params),e),t.params.tireModel,t.params.tireModelRear);function N$(e,t){return ox(e,t.switches)}var ax=e=>rr(e?.rulesets);function yT(e,t,r,n,o={},a=()=>r.standingStart){let s=ox(n,r.switches),i=(l,u)=>{let m=Bm(l,t,{racingLine:r.racingLine,params:s});return{asset:m.asset,numerics:m.numerics,standingStart:u,racingLine:r.racingLine}},c=Object.fromEntries(Object.entries(o).map(([l,u])=>[l,i(u,a(l))]));return{course:e?i(e,r.standingStart):null,numerics:t,tracks:c,switches:r.switches}}var xT=e=>[...new Set(e.lap.courses.flatMap(t=>t.course.kind==="track"?[t.course.trackId]:[]))],RT=e=>{let t=e?.session;return t?{sessionParams:r=>N$(r,t),session:()=>t}:{}},Jc=e=>({metrics:ax(e),assemble:gT(e?.switches),simParams:bT(e?.switches),projectTrack:()=>e?.course??null,libraryTrack:t=>e?.tracks?.[t]??null,numerics:e?.numerics,...RT(e)}),O$=(e,t)=>({density:e.density,envelope:e.envelope,states:e.states,operating:e.operating,lap:e.lap,assemble:gT(t?.switches),simParams:bT(t?.switches),projectTrack:()=>t?.course??null,libraryTrack:r=>t?.tracks?.[r]??null,numerics:t?.numerics,...RT(t)}),vT="nelder-mead",kT=600,Zc=[0,.15,.15];function MT(e,t,r,n=Zc.length){let o=cx(t);return Zc.slice(0,Math.max(1,n)).map((a,s)=>({...e,seed:s+1,startJitter:a,car:o,...r?{lap:r}:{}}))}function ST(e,t,r=.5){let n=[];return e.forEach((o,a)=>{let s=o.hi-o.lo;if(s<=0)return;let i=Math.min(r,s*.01);t[a]<=o.lo+i?n.push({id:o.id,name:o.name,unit:o.unit,at:"lo",value:t[a],moved:t[a]-o.start}):t[a]>=o.hi-i&&n.push({id:o.id,name:o.name,unit:o.unit,at:"hi",value:t[a],moved:t[a]-o.start})}),n}function AT(e,t,r,n,o=.01){let a=ax(n).byId;return V$(e,t,r,n).filter(s=>s.excess>-o*(a[s.metricId]?.scale??1))}function V$(e,t,r,n){let o;try{o=Pn(us(e,t,r),O$(t,n))}catch{return[]}return B$(o,t,ax(n))}function B$(e,t,r){let n=[];for(let o of t.constraints){let a=r.byId[o.metricId];if(!a)continue;let s=ut(e,a,o.at);if(!Number.isFinite(s))continue;let i=`${je(a)}${Io(o.at,a)}`;n.push({key:o.key,metricId:o.metricId,label:i,unit:a.unit==="-"?"":a.unit,value:s,excess:En(o,s)})}return n}var $$=.05;function G$(e,t){if(t.id.startsWith("hp.")||Op(t.id))return 1;let r=/^rocker\.(front|rear)\.(\w+)$/.exec(t.id);if(r){let a=r[1]==="front"?e.vehicle.front:e.vehicle.rear;return gy(Dn(a.hardpoints),r[2],1)}let n=/^arm\.(front|rear)\.(uca|lca)\.(\w+)$/.exec(t.id);if(!n)return null;let o=n[1]==="front"?e.vehicle.front:e.vehicle.rear;return fy(rn(o.hardpoints,n[2]),n[3],1)}function FT(e,t,r){let n=r.filter(f=>f.score.feasible);if(n.length<2)return null;let o=t.map(f=>G$(e,f)),a=o.every(f=>f!==null)?"mm":null,s=0,i="",c=0,l=n.reduce((f,p)=>p.score.total<f.score.total?p:f);for(let f of n)if(f!==l)for(let p=0;p<t.length;p++){let d=Math.abs(f.x[p]-l.x[p])*(o[p]??1);c+=d*d,d>s&&(s=d,i=t[p].name)}let u=n.map(f=>f.score.total),m=l.score.terms.reduce((f,p)=>f+(p.resolution??0),0);return{distance:Math.sqrt(c),worst:s,worstName:i,scoreSpread:Math.max(...u)-Math.min(...u),tolerance:Math.max($$,m),unit:a}}var K$={steeringSystem:!0,brakeSetup:!0,driveline:!0,heaveFrontDesign:!0,heaveRearDesign:!0,arbFrontDesign:!0,arbRearDesign:!0},wT=e=>Object.hasOwn(K$,e);function rx(e){let[t,r]=e.split("."),n=r==="front"?"Front":r==="rear"?"Rear":null;return n?t==="heave"?`heave${n}Design`:t==="roll"?`arb${n}Design`:null:null}function H$(e){let t=e.split(".")[0];return t==="hp"||t==="arm"||t==="rocker"?"hardpoint":t==="cfg"?"config":t==="kc"?"compliance":t==="param"?"param":t==="brakeModel"?"part":wT(t)||rx(e)?"block":null}function sx(e,t){t=mt(e,t);let r=yt(e);return[...t.variables,...t.followers??[]].filter(n=>r[n.id]&&!r[n.id].supersededBy&&!H$(n.id)).map(n=>tt(r[n.id]))}function CT(e,t,r){t=mt(e,t);let n=yt(e),o=us(e,t,r),a=[],s=new Set,i=new Set;for(let c of[...t.variables,...t.followers??[]]){let l=n[c.id];if(!l||l.supersededBy)continue;let u=l.read(o),[m,f,p,d]=c.id.split(".");if(m==="rocker"){let h=`${f}.rocker`;if(i.has(h))continue;i.add(h);let b=f==="front"?o.vehicle.front:o.vehicle.rear;for(let g of[Sr.fore,Sr.aft]){let y=b.hardpoints[g];for(let R=0;R<3;R++)a.push({kind:"hardpoint",axle:f,key:g,axis:R,value:y[R]})}}else if(m==="arm"){let h=`${f}.${p}`;if(i.has(h))continue;i.add(h);let b=f==="front"?o.vehicle.front:o.vehicle.rear,g=Ot[p];for(let y of[g.fore,g.aft]){let R=b.hardpoints[y];for(let k=0;k<3;k++)a.push({kind:"hardpoint",axle:f,key:y,axis:k,value:R[k]})}}else if(m==="hp"&&jt(c.id)){let h=`${f}.${p}`;if(i.has(h))continue;i.add(h);let b=(f==="front"?o.vehicle.front:o.vehicle.rear).hardpoints[p];for(let g=0;g<3;g++)a.push({kind:"hardpoint",axle:f,key:p,axis:g,value:b[g]})}else if(m==="hp")a.push({kind:"hardpoint",axle:f,key:p,axis:"xyz".indexOf(d),value:u});else if(m==="cfg")a.push({kind:"config",axle:f,field:p,value:u});else if(m==="kc"){if(s.has(`kc.${f}`))continue;s.add(`kc.${f}`);let h=f==="front"?o.vehicle.front:o.vehicle.rear;a.push({kind:"compliance",axle:f,value:h.compliance})}else if(m==="param")a.push({kind:"param",label:tt(l),value:u});else if(m==="brakeModel"){if(s.has(m))continue;if(s.add(m),!o.params.brakeModel)throw new Error(`optimiser: "${c.id}" left the car with no brake part to adopt`);a.push({kind:"part",key:"brakeModel",fromId:e.params.brakeModelId,value:o.params.brakeModel})}else if(wT(m)||rx(c.id)){let h=rx(c.id)??m;if(s.has(h))continue;s.add(h);let b=o.params[h];if(!b)throw new Error(`optimiser: "${c.id}" left the car with no ${h} to adopt`);a.push({kind:"block",key:h,value:b})}else throw new Error(`optimiser: Adopt has no way to write "${c.id}" back into the project`)}return a}function ix(e){let t=performance.now(),r=Jc(e.lap),n=e.follow?Cy(e.car,e.spec,r):e.spec,{dead:o,unprobed:a,...s}=Dy(e.car,n,r);return{...s,deadIds:o.map(i=>i.id),unprobedIds:a.map(i=>i.id),elapsedMs:performance.now()-t,...e.follow?{followed:!0,fromCar:n===e.spec?null:{states:n.states,envelope:n.envelope}}:{}}}function TT(e){let t=performance.now();return{tolerance:Ky(e.car,e.spec,e.x,Jc(e.lap),e.mm),elapsedMs:performance.now()-t}}var cx=e=>e.vehicle.chassis?{...e,vehicle:Hy(e.vehicle)}:e;function PT(e,t){try{let r=lx(e.car,e.spec,e.lap),n=ya.find(u=>u.name===e.method);if(!n)throw new Error(`unknown method "${e.method}"`);t({kind:"progress",seed:e.seed,progress:{evaluations:0,budget:e.budget,x:_r(r.variables),score:Ir(r,_r(r.variables)),infeasible:0}});let o=e.from,a=o?{...r,variables:r.variables.map((u,m)=>({...u,start:Number.isFinite(o[m])?o[m]:u.start}))}:r,s=performance.now(),i=n.run(a,{budget:e.budget,seed:e.seed,startJitter:e.startJitter,progressEvery:20,onProgress:u=>t({kind:"progress",seed:e.seed,progress:u})}),c=performance.now()-s,l=i.score.feasible&&vy(r.variables)?My(r,i.x,i.score):void 0;t({kind:"done",seed:e.seed,result:l?{...i,snapped:l}:i,elapsedMs:c})}catch(r){t({kind:"error",seed:e.seed,message:r instanceof Error?r.message:String(r)})}}var lx=(e,t,r)=>Gp(e,t,Jc(r));function LT(e,t){let r=e.tireModelIdRear?t.tire(e.tireModelIdRear):void 0;return{tireModel:t.tire(e.tireModelId),...r?{tireModelRear:r}:{},motorModel:t.motor(e.motorModelId),aeroModel:t.aero(e.aeroModelId),batteryModel:t.battery(e.batteryModelId),brakeModel:t.brake(e.brakeModelId),damperModel:t.damper(e.damperModelId),...Fi(e,t.damper)}}function DT(e,t,r){let{tireModelRear:n,damperModelRear:o,heaveDamperModel:a,rollDamperModel:s,...i}=r;return{vehicle:e,params:{...t,...i,...n?{tireModelRear:n}:{},...o?{damperModelRear:o}:{},...a?{heaveDamperModel:a}:{},...s?{rollDamperModel:s}:{}}}}var ET=e=>({ggvMode:e.ggvMode,quasiTransient:e.quasiTransient===!0&&e.ggvMode!=="fast",motorThermal:e.motorThermal===!0,...nC({brakeFade:e.brakeFade===!0,airTempC:e.airTempC,diffYaw:e.diffYaw===!0,...e.air?{air:e.air}:{}})});function z$(e){if(!(e.plannedPath!==void 0||!e.track))return{track:e.track,numerics:e.numerics,settings:{racingLine:e.racingLine,standingStart:e.standingStart,...Object.keys(e.lapCounts).length?{lapCounts:e.lapCounts}:{}},switches:e.switches,rulesets:e.rulesets}}function IT(e,t){let r=t.plannedPath!==void 0,n=z$(t);return{...yT(r?t.plannedPath:t.track,t.numerics,{racingLine:r?!1:t.racingLine,standingStart:t.standingStart,switches:t.switches},e,t.library,t.standingOf),...n?{session:n}:{},rulesets:t.rulesets}}function ux(e,t){let r=e.vehicles.find(o=>o.id===t);if(!r)throw new Error(`this project holds no vehicle "${t}"`);let n=No(e);return DT(structuredClone(By(e,r.params)),structuredClone(r.params),LT(r.params,n))}var Y$="this project's laps follow a fixed trajectory from the planner, which the server cannot read \u2014 set Laptime back to the track to run this study here, or run it in the Studies tool";async function mx(e,t,r,n){if(e.settings.pathPlanId)throw new Error(Y$);let o=ms(e),a=e.tracks.length?(await zp(e,t)).asset:null,s={};for(let i of n?xT(n):[]){let c=e.tracks.find(l=>l.id===i);c&&(s[i]=await jc(c,t))}return IT(r,{track:a,numerics:o.numerics,racingLine:o.racingLine,standingStart:o.standingStart,lapCounts:o.lapCounts??{},switches:ET(o),rulesets:e.rulesets??[],library:s,standingOf:i=>e.tracks.find(c=>c.id===i)?.standingStart===!0})}async function _T(e,t,r,n){let o=ux(e,r),a=mt(o,n),s=await mx(e,t,o,a);return ix({id:0,car:o,spec:a,lap:s})}async function NT(e,t,r,n){let o=ux(e,r),a=mt(o,n),s=sx(o,a);if(s.length)return{problems:[`Adopt has no way to write ${s.join(", ")} back into the project. Take them out of the study.`]};let i;try{i=await mx(e,t,o,a)}catch(l){return{problems:[l instanceof Error?l.message:String(l)]}}let c=Ly(o,a,{...Jc(i),metrics:rr(e.rulesets)});return c.length?{problems:c}:{problems:[],msPerEval:ix({id:0,car:o,spec:a,lap:i}).msPerEval,carFingerprint:go(cx(o))}}async function W$(e,t,r,n,o,a=[]){let s=MT(t,e,r,n),i=s.length*t.budget,c=null,l=[];for(let[u,m]of s.entries()){if(a.includes(m.seed))continue;await o?.tick();let f=[],p=null,d=null;if(PT(m,y=>{y.kind==="progress"?(f.push([y.progress.evaluations,y.progress.score.total]),y.progress.evaluations===0&&(c??=y.progress.score),o?.progress(u*t.budget+y.progress.evaluations,i)):y.kind==="done"?p={result:y.result,elapsedMs:y.elapsedMs}:d=y.message}),d)throw new Error(d);if(!p)throw new Error("the search stopped without a result");let{result:h,elapsedMs:b}=p,g={seed:m.seed,startJitter:m.startJitter,x:h.x,score:h.score,evaluations:h.evaluations,infeasible:h.infeasible,history:h.history,trace:f,elapsedMs:b,...h.snapped?{snapped:h.snapped}:{}};l.push(g),o?.progress((u+1)*t.budget,i),await o?.finished?.(g)}if(!c)throw new Error("the search never scored the starting design");return{method:t.method,budget:t.budget,designScore:c,runs:l}}async function OT(e,t,r,n){let o=ux(e,r.vehicleId),a=mt(o,r.spec),s=sx(o,a);if(s.length)throw new Error(`study_adopt has no way to write ${s.join(", ")} back into the project \u2014 take them out of the study`);let i=await mx(e,t,o,a),c=r.method??vT;if(!ya.some(R=>R.name===c))throw new Error(`unknown method "${c}" \u2014 it is one of ${ya.map(R=>R.name).join(", ")}`);let l=r.budget??kT,u=Math.max(1,Math.min(r.seeds??Zc.length,Zc.length)),m=await W$(o,{spec:a,method:c,budget:l},i,u,n),f=lx(o,a,i),p=m.runs.map(R=>({seed:R.seed,startScore:m.designScore.total,score:R.score.total,feasible:R.score.feasible,...R.score.reason?{reason:R.score.reason}:{},terms:R.score.terms,x:R.x,evaluations:R.evaluations,infeasible:R.infeasible,bounds:ST(f.variables,R.x),constraints:AT(o,a,R.x,i),...R.snapped?{onSteps:{x:R.snapped.x,score:R.snapped.score.total,feasible:R.snapped.score.feasible,...R.snapped.score.reason?{reason:R.snapped.score.reason}:{},terms:R.snapped.score.terms}}:{}})),d=m.runs.reduce((R,k)=>ti(k.score,R.score)?k:R),h=d.snapped?.score.feasible?d.snapped:null,b=h?h.x:d.x,g=r.tolerance??jp,y=d.score.feasible&&g>0?TT({id:0,car:o,spec:a,x:b,lap:i,mm:g}).tolerance:null;return{method:c,budget:l,seeds:p,spread:m.runs.length>1?FT(o,f.variables,m.runs.map(R=>({x:R.x,score:R.score}))):null,writes:CT(o,a,b),...d.snapped?{adopts:h?"on its steps":`as found: on its steps it breaks a hold (${d.snapped.score.reason??"not legal"})`}:{},...y?{asBuilt:y}:{}}}function BT(){if(typeof process.threadCpuUsage!="function")return performance.now();let e=process.threadCpuUsage();return(e.user+e.system)/1e3}async function U$(e,t){let r=Jw(e.root);switch(e.kind){case"sweep":return pC(e.doc,r,e.req,t);case"convergence":return uC(e.doc,r,{vehicleId:e.vehicleId,...e.steps?{steps:e.steps}:{},...e.tolPct!==void 0?{tolPct:e.tolPct}:{},onStep:t});case"study":return OT(e.doc,r,{vehicleId:e.vehicleId,spec:e.spec,...e.method?{method:e.method}:{},...e.budget?{budget:e.budget}:{},...e.seeds?{seeds:e.seeds}:{},...e.tolerance!==void 0?{tolerance:e.tolerance}:{}},{progress:t,cancelled:()=>!1,tick:async()=>{}});case"fleet":return Yp(e.doc,r,{...e.vehicleIds?{vehicleIds:e.vehicleIds}:{},...e.settings?{settings:e.settings}:{},...e.overrides?{overrides:e.overrides}:{}});case"probe":return _T(e.doc,r,e.vehicleId,e.spec);case"quote":return NT(e.doc,r,e.vehicleId,e.spec)}}if(VT){let e=VT,t=r=>e.postMessage(r);(async()=>{try{let r=await U$(j$,(n,o)=>t({type:"progress",done:n,total:o}));t({type:"done",result:r,cpuMs:BT()})}catch(r){t({type:"failed",message:r instanceof Error?r.message:String(r),cpuMs:BT()})}})()}export{U$ as runJob,BT as threadCpuMs};
|