@pacedyn/mcp 0.393.3 → 0.394.4
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 -3
- package/dist/cli.js +56 -56
- 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 FC,workerData as nB}from"node:worker_threads";import{readFileSync as ty}from"node:fs";import{join as ry}from"node:path";var Ic=e=>e.format!=="points"&&!e.field;var ft=e=>e?.kind==="ice";var Ly={packVoltageMax:600,segmentVoltageMax:120,powerLimitKw:80};var Ee=e=>typeof e=="number"&&Number.isFinite(e);function CC(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 TC(e){return!e||typeof e!="object"?"The cell has no curve.":e.kind==="table"?CC(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 _c(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=TC(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 Fn(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 Be(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 Nc(e,t,r,n,o){let a=e.length,s=t.length;if(a===0||s===0)return 0;let i=Fn(e,n),c=Fn(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 Co=[0,.05,.1,.2,.3,.4,.5,.6,.7,.8,.9,1],_p={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]},Dy=[0,.05,.1,.2,.5,.8,1],Ey=[2.2,1.55,1.3,1.12,1,.97,.98];function Iy(e){return Be(Dy,Ey,e)}var _y=[-20,-10,0,10,25,40,60],Ny=[4,2.8,2,1.4,1,.82,.75];function Np(e){return Be(_y,Ny,e)}var Oy=.5;function Op(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=_p[t]??_p.other,l=e.socAtNom??Oy,u=Co.includes(l)?[...Co]:[...Co,l].sort((h,b)=>h-b),m=Be(Co,c,l),f=m>0&&m<1?Math.log(i)/Math.log(m):1,p=[],d=[];for(let h of u){let b=Be(Co,c,h);p.push(o+s*Math.pow(b,f)),d.push(e.constantResistance?a:a*Iy(h))}return{kind:"table",soc:u,ocv:p,r0:d}}function Vp(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+=(Be(t,r,s)+Be(t,r,i))/2*(i-s)}return o}var To=25,Vy=new WeakMap;function hr(e){let t=Vy.get(e);if(t)return t;let r=_c(e);if(r)throw new Error(r);let{cell:n,pack:o}=e,a=n.curve.kind==="table"?n.curve:Op(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*Be(a.soc,a.ocv,F),g=(F,w=To)=>{let C=l&&u?Nc(a.soc,l,u,F,w):Be(a.soc,a.r0,F)*Np(w);return c*C+o.busResistance},y=(F,w,C)=>b(F)-w*g(F,C),R=(F,w,C)=>{if(!(F>0))return 0;let T=b(w),S=g(w,C);if(!(S>0))return F/T;let A=T*T-4*S*F;return A<0?NaN:2*F/(T+Math.sqrt(A))},k=(F,w,C)=>{if(!(F>0))return 0;let T=b(w),S=g(w,C);return S>0?2*F/(T+Math.sqrt(T*T+4*S*F)):F/T},v=F=>{let w=e.thermal;if(!w||w.derateFromC===void 0)return 1;let C=w.derateToC??w.derateFromC;return F<=w.derateFromC?1:!(C>w.derateFromC)||F>=C?0:1-(F-w.derateFromC)/(C-w.derateFromC)},x=(F,w,C=0)=>{let T=b(F),S=g(F,w),A=S>0?T/(2*S):1/0,P=G=>{if(!(S>0))return G*T;let K=Math.min(G,A);return K*(T-K*S)},L=S>0?Math.max(0,(T-f)/S):1/0,D=C>0&&Number.isFinite(C)?C:1/0,E=S>0?P(L):1/0,V=Number.isFinite(p)?P(p):1/0,N=S>0?T*T/(4*S):1/0,z=[["rules",D],["voltage-floor",E],["current",V],["matched-load",N]],I=z[0][0],_=z[0][1];for(let[G,K]of z)K<_&&(_=K,I=G);let B=v(w??To);B<1&&(_=Number.isFinite(_)?_*B:_,I="temperature");let O=Number.isFinite(_)?R(_,F,w):1/0;return{watts:_,binding:I,rules:D,voltageFloor:E,current:V,matchedLoad:N,derate:B,amps:O,volts:Number.isFinite(O)?T-O*S:T}},M={model:e,table:a,capacityAh:m,chargeC:m*3600,energyKwh:m*(s*Vp(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 Vy.set(e,M),M}function Bp(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 By={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},$y={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},Gy={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 $p(){return{name:"Formula Student accumulator",cell:Bp(By),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 Gp(){return{name:"LFP pack",cell:Bp($y),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 Kp(){return{name:"Road car pack",cell:Bp(Gy),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 Hp(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 Oc(e){if(e.kind==="ice"){let n=e.gearbox.efficiency;return{model:e,maxTorque:o=>o>e.limitRpm?0:Be(e.rpm,e.torque,o),efficiency:()=>n}}let t=n=>Be(e.rpm,e.torque,n),r=e.kind==="simple"?()=>e.efficiency:(n,o)=>Nc(e.effRpm,e.effTorque,e.effGrid,n,o);return{model:e,maxTorque:t,efficiency:r}}function zp(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 Xe(e,t){return t==="rear"&&e.tireRateRear!==void 0?e.tireRateRear:e.tireRate}function Yp(e,t){let r=e.tyreFreeRadiusRear;return(t==="rear"&&r!==void 0?r:e.tyreFreeRadius)??0}var Vc=9.81,Ky=(e,t)=>e*(t*t)/2*(Math.PI/180)/1e3,Qa=(e,t)=>e+t>0?e*t/(e+t):0,Hy=.5;function Bc(e,t,r){if(!(r>0))return 1;let n=e*Vc*t*(Math.PI/180)/r;return 1/(1-Math.min(Hy,n))}function Wp(e,t,r){return r>0?e*Vc*t/(r*r):0}function zy(e,t,r,n,o){if(!(n>0)||!(o>0))return 1;let a=Wp(e,t,r)*(1/n+1/o);return 1/(1-Math.min(Hy,a))}function Te(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=Qa(i,a),u=Qa(c,s),m=(V,N)=>{let z=N/2;return z>0?1/(2*Math.PI)*Math.sqrt(V*1e3/z):0},f=m(l,n),p=m(u,o),d=Qa(e.wheelRateFront+e.arbFront,a),h=Qa(e.wheelRateRear+e.arbRear,s),b=Ky(d,e.trackFront),g=Ky(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*Vc*v,M=Bc(r,v,y),F=y>0?x/y*M:0,w=e.massTotal*Vc*e.cgHeight/e.wheelbase,C=2*l,T=2*u,S=zy(r,e.cgHeight,e.wheelbase,C,T),P=(C>0&&T>0?(w/C+w/T)/e.wheelbase*S:0)*(180/Math.PI),L=e.wheelbase*e.wheelbase*Qa(C,T)*(Math.PI/180)/1e3,D=e.damperFront??2.5,E=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:P,pitchRate:L,cgRollGain:M,cgPitchGain:S,rideDampingFront:D+(e.heaveDamperFront??0),rideDampingRear:E+(e.heaveDamperRear??0),rollDampingFront:D+(e.rollDamperFront??0),rollDampingRear:E+(e.rollDamperRear??0)}}var Wr=["clFront","clRear","cd"],Po=e=>e.frame?.kind==="pitch";function $c(e){return Po(e)?{x:e.axes.h,y:e.axes.pitch}:{x:e.axes.hFront,y:e.axes.hRear}}var Yy=e=>e.frame?.kind==="pitch";var Gc=45,Qe=e=>typeof e=="number"&&Number.isFinite(e);function Kc(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(Qe))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 Wy(e,t){if(t===void 0)return null;for(let r of Wr){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(Qe)||!n.factor.every(Qe))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 jy(e,t){return t===void 0?null:!Qe(t.dCl)||!Qe(t.dBalance)||!Qe(t.dCd)?`The ${e} slopes must be numbers.`:!Qe(t.maxDeg)||!(t.maxDeg>0)?`The ${e} response needs a positive angle to be valid to.`:null}function Za(e){if(!e||typeof e!="object")return"Not an aero model.";if(!Qe(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=Kc("front ride-height",e.axes?.hFront);if(i)return i;let c=Kc("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(!Qe(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=Kc("ride-height",e.axes?.h);if(i)return i;let c=Kc("pitch",e.axes?.pitch,"\xB0","pitch");if(c)return c;let l=e.axes.pitch.find(u=>Math.abs(u)>=Gc);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 Wr){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(Qe))return`${i} contains a value that is not a number.`}}return Wy("yaw",e.attitude?.yaw)??Wy("roll",e.attitude?.roll)}if(e.kind==="sensitivity"){let t;if(e.frame==null)t=["hFront","hRear"];else if(e.frame?.kind==="pitch"){if(!Qe(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||!Qe(r[t[0]])||!Qe(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 Wr){if(!e.at||!Qe(e.at[s]))return`${s} at the reference must be a number.`;let i=n?.[s];if(!i||!Qe(i[t[0]])||!Qe(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||!Qe(i[0])||!Qe(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])>=Gc||Math.abs(i[1])>=Gc))return`A pitch range reaching ${Math.abs(i[0])>=Gc?i[0]:i[1]}\xB0 is not a car's attitude. Pitch is in degrees.`}return jy("yaw",e.attitude?.yaw)??jy("roll",e.attitude?.roll)}return`Unknown aero model kind "${e.kind}".`}var Uy=180/Math.PI;function Hc(e,t,r,n){let o=(n-r)/t;return{h:r+e.refX*o,pitch:Math.atan(o)*Uy}}function Lo(e,t,r,n){let o=Math.tan(n/Uy);return{hFront:r-e.refX*o,hRear:r+(t-e.refX)*o}}var HB=180/Math.PI,PC=["hFront","hRear"],LC=["h","pitch"],Xp=e=>e?.kind==="pitch"?LC:PC,Mt=(e,t)=>e[t],zc=(e,t)=>e[t],jp=(e,t)=>({[e[0]]:t(e[0]),[e[1]]:t(e[1])});function DC(e){if(!(!e.yaw&&!e.roll))return{...e.yaw?{yaw:{...e.yaw}}:{},...e.roll?{roll:{...e.roll}}:{}}}function qp(e){let t=Xp(e.frame),r=e.balanceFront,n=e.cl*r,o=e.cl*(1-r),a=jp(t,c=>Mt(e.dCl,c)*r+e.cl*Mt(e.dBalance,c)),s=jp(t,c=>Mt(e.dCl,c)*(1-r)-e.cl*Mt(e.dBalance,c)),i=DC(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:jp(t,c=>Mt(e.dCd,c))},range:{[t[0]]:[...zc(e.range,t[0])],[t[1]]:[...zc(e.range,t[1])]},provenance:{...e.provenance},...i?{attitude:i}:{}}}function Yc(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 Up(e,t,r=11){let n=Array.from({length:r},(a,s)=>t.maxDeg*s/(r-1)),o=n.map(a=>Yc(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 Xy(e){if(!(!e.attitude?.yaw&&!e.attitude?.roll))return{...e.attitude.yaw?{yaw:Up(e.at,e.attitude.yaw)}:{},...e.attitude.roll?{roll:Up(e.at,e.attitude.roll)}:{}}}function qy(e,t,r,n=0,o=0){let[a,s]=Xp(e.frame),i=t-Mt(e.ref,a),c=r-Mt(e.ref,s),l={clFront:e.at.clFront+Mt(e.slope.clFront,a)*i+Mt(e.slope.clFront,s)*c,clRear:e.at.clRear+Mt(e.slope.clRear,a)*i+Mt(e.slope.clRear,s)*c,cd:e.at.cd+Mt(e.slope.cd,a)*i+Mt(e.slope.cd,s)*c},u=e.attitude?.yaw?Yc(e.at,e.attitude.yaw,n):{clFront:1,clRear:1,cd:1},m=e.attitude?.roll?Yc(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 Qp(e){let[t,r]=Xp(e.frame),n=[...zc(e.range,t)],o=[...zc(e.range,r)],a=i=>o.map(c=>n.map(l=>i(qy(e,l,c)))),s=Xy(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 Zp=180/Math.PI,Qy=new WeakMap,Zy=new WeakMap,Jp=new WeakMap;function jr(e,t){let r=Zy.get(e);if(r)return r;let n=t?.wheelbase,o=n!==void 0?Jp.get(e)?.get(n):void 0;if(o)return o;let a=EC(e),s=a.map;if(!Po(s)){let l=IC(e,a);return Zy.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=_C(e,a,s.frame,n),c=Jp.get(e);return c||(c=new Map,Jp.set(e,c)),c.set(n,i),i}function EC(e){let t=Qy.get(e);if(t)return t;let r=Za(e);if(r)throw new Error(r);let n=e.kind==="map"?e:Qp(e),{x:o,y:a}=$c(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:Be(y.clFront.deg,y.clFront.factor,k),clRear:Be(y.clRear.deg,y.clRear.factor,k),cd:Be(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=Fn(o,y),M=Fn(a,R),F=Math.min(x.i+1,s-1),w=Math.min(M.i+1,i-1),C=S=>{let A=S[M.i][x.i],P=S[M.i][F],L=S[w][x.i],D=S[w][F],E=A+x.t*(P-A),V=L+x.t*(D-L);return E+M.t*(V-E)},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),F=Fn(o,k?Math.min(Math.max(y,h.x[0]),h.x[1]):y),w=Fn(a,k?Math.min(Math.max(R,h.y[0]),h.y[1]):R),C=Math.min(F.i+1,s-1),T=Math.min(w.i+1,i-1),S=C>F.i?o[C]-o[F.i]:0,A=T>w.i?a[T]-a[w.i]:0,P={};for(let L of Wr){let D=n[L],E=D[w.i][F.i],V=D[w.i][C],N=D[T][F.i],z=D[T][C],I=F.clamped||S===0?0:((V-E)*(1-w.t)+(z-N)*w.t)/S,_=w.clamped||A===0?0:((N-E)*(1-F.t)+(z-V)*F.t)/A;P[L]=u?{x:I*M[L],y:_*M[L]}:{x:I,y:_}}return P},g={map:n,x:h.x,y:h.y,hasAttitude:u,factors:p,at:d,slopes:b};return Qy.set(e,g),g}function IC(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 Wr)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 _C(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)*Zp,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)*Zp,m,f,p),b=Zp/(n*(1+d*d)),g={};for(let y of Wr)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)=>Lo(r,n,l,u),fromAxles:(l,u)=>{let m=Hc(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 ed(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,Jy={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."},ex={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."},tx={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."},rx={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."},nx={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."},ox={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."},ax={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."},sx={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 br(e){return qp({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=()=>br(Jy),rd=()=>br(ex),nd=()=>br(tx),od=()=>br(rx),ad=()=>br(nx),sd=()=>br(ox),id=()=>br(ax),cd=()=>br(sx);function Do(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 Wc(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 jc(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 ld(e,t){return e.wheelbase>0?e.massTotal*t*9.81/e.wheelbase:0}function Eo(e,t,r){let n=2*t.rideRateFront,o=2*t.rideRateRear;return!(n>0)||!(o>0)?0:Math.min(Wp(t.sprungMass,r,e.wheelbase),.5*n*o/(n+o))}function Uc(e,t,r,n,o){let a=e.cgHeight,s=ld(e,r);if(n===0&&o===0&&s===0)return{height:a,forward:0,noseLoad:0,dropFront:0,dropRear:0};let i=Wc(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=Eo(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=jc(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 ud={yawDeg:0,rollDeg:0},ix=1e-4,NC=40,cx=50;function Io(e,t,r=0){let n=e.aero?.model;if(!(!n||!jr(n,e).hasAttitude))return{yawDeg:r,rollDeg:Te(e).rollGradient*t}}function md(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 Lo(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=Yy(r)?n(r.frame,r.ref.h,r.ref.pitch):r.ref;else if(r){let{x:a,y:s}=$c(r),i=(a[0]+a[a.length-1])/2,c=(s[0]+s[s.length-1])/2;o=Po(r)?n(r.frame,i,c):{hFront:i,hRear:c}}return{hFront:e.rideHeightFront??o.hFront,hRear:e.rideHeightRear??o.hRear}}var lx=new WeakMap;function Ur(e,t,r=0,n){let o=e.aero;if(!o?.model)return null;let a=lx.get(e);a||(a=new Map,lx.set(e,a));let s=n&&jr(o.model,e).hasAttitude?n:ud,i=s===ud?`${t}|${r}`:`${t}|${r}|${s.yawDeg.toFixed(3)}|${s.rollDeg.toFixed(3)}`,c=a.get(i);if(c)return c;let l=OC(e,o,t,r,s);return a.size>4096&&a.clear(),a.set(i,l),l}function OC(e,t,r,n,o){let a=jr(t.model,e),s=Te(e),i=2*s.rideRateFront,c=2*s.rideRateRear,l=md(t,e.wheelbase),u=.5*t.rho*r*r,m=a.area,f=e.wheelbase>0?t.copHeight/e.wheelbase:0,p=Wc(e,s),d=ld(e,n),h=(C,T)=>jc(e.cgHeight,p,l.hFront-C,l.hRear-T),b=(C,T)=>l.hFront-C-(l.hRear-T),g=(C,T)=>{let S=a.at(C,T,o.yawDeg,o.rollDeg),A=u*m*S.clFront,P=u*m*S.clRear,L=u*m*S.cd,D=L*f,E=h(C,T),V=d*E,N=Eo(e,s,E)*b(C,T),z=A-V-D+N,I=P+V+D-N,_=C-l.hFront+(i>0?z/i:0),B=T-l.hRear+(c>0?I/c:0);return{c:S,downFront:A,downRear:P,drag:L,rF:_,rR:B,norm:Math.hypot(_,B)}},y=(C,T,S=!1)=>{let A=a.slopes(C,T,S,o.yawDeg,o.rollDeg),P=i>0?u*m/i:0,L=c>0?u*m/c:0;return[[P*(A.clFront.hFront-f*A.cd.hFront),P*(A.clFront.hRear-f*A.cd.hRear)],[L*(A.clRear.hFront+f*A.cd.hFront),L*(A.clRear.hRear+f*A.cd.hRear)]]},R=l.hFront,k=l.hRear,v=g(R,k),x=0;for(;v.norm>=ix&&x<NC;){x++;let C=y(R,k),T=i>0?d/i:0,S=c>0?d/c:0,A=Eo(e,s,h(R,k)),P=i>0?A/i:0,L=c>0?A/c:0,D=1+C[0][0]-T*p.front-P,E=C[0][1]-T*p.rear+P,V=C[1][0]+S*p.front+L,N=1+C[1][1]+S*p.rear-L,z=D*N-E*V,I,_;Math.abs(z)>1e-9?(I=-(N*v.rF-E*v.rR)/z,_=-(-V*v.rF+D*v.rR)/z):(I=-.5*v.rF,_=-.5*v.rR);let B=Math.max(1,Math.abs(I)/cx,Math.abs(_)/cx);I/=B,_/=B;let O=1;for(let G=0;G<6;G++){let K=g(R+O*I,k+O*_);if(K.norm<=v.norm||G===5){R+=O*I,k+=O*_,v=K;break}O*=.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:Eo(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:VC(M),stable:w>0&&F>0,converged:v.norm<ix,iterations:x,clampedRide:v.c.clampedRide,yawDeg:o.yawDeg,rollDeg:o.rollDeg,clampedAttitude:v.c.clampedAttitude}}function VC(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 Ja(e,t,r=0,n){let o=Ur(e,t,r,n);return o?{downforce:o.downforce,drag:o.drag,downFront:o.downFront,downRear:o.downRear}:e.aero?Do(e.aero,t):{downforce:0,drag:0,downFront:0,downRear:0}}function Xc(e,t=0,r=0,n,o){if(e.aero&&t>0){if(e.aero.model){let i=Ur(e,t,r,n);return{height:i.cgHeight,forward:i.cgForward,noseLoad:i.cgNoseLoad}}let a=Do(e.aero,t),s=e.wheelbase>0?a.drag*e.aero.copHeight/e.wheelbase:0;return Uc(e,o??Te(e),r,a.downFront-s,a.downRear+s)}return r===0?{height:e.cgHeight,forward:0,noseLoad:0}:Uc(e,o??Te(e),r,0,0)}var ux=[0,1,0],pd=[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],dd=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]],BC=e=>X(e,e),Xr=e=>Math.sqrt(X(e,e)),es=(e,t)=>BC(H(e,t)),ve=(e,t)=>Xr(H(e,t)),q=e=>{let t=Xr(e);return t<1e-12?[0,0,0]:[e[0]/t,e[1]/t,e[2]/t]};var qr=(e,t,r)=>{let n=q(r),o=H(e,t);return ee(t,U(n,X(o,n)))},mx=(e,t,r)=>ve(e,qr(e,t,r));var GC=1e-6;function KC(e){if(e<GC){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 ot(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]=KC(r),a=ae(e,t),s=ae(e,a);return ee(t,ee(U(a,n),U(s,o)))}function It(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 ot(U(o,r),e)}function Qt(e,t){let r=t.length,n=e.map(a=>a.slice()),o=t.slice();return dx(n,o,r,new Array(r).fill(0))}function px(e,t,r){return dx(e,t,t.length,r)}function dx(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 fx=e=>{let t=0;for(let r of e)t=Math.max(t,Math.abs(r));return t},hx=e=>{let t=0;for(let r of e)t+=r*r;return t},HC=Math.sqrt(Number.EPSILON);function bx(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=fx(c),u=hx(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 C=0;C<a;C++){let T=HC*Math.max(Math.abs(i[C]),s[C]);for(let A=0;A<a;A++)k[A]=i[A];k[C]+=T;let S=e(k);for(let A=0;A<p;A++)d[A][C]=(S[A]-c[A])/T}let M=0;for(let C=0;C<a;C++){for(let S=0;S<a;S++){let A=0;for(let P=0;P<p;P++)A+=d[P][C]*d[P][S];h[C][S]=A}let T=0;for(let S=0;S<p;S++)T+=d[S][C]*c[S];g[C]=T,M=Math.max(M,h[C][C])}let F=Math.max(M,1e-9),w=!1;for(let C=0;C<18;C++){let T=m*F;for(let A=0;A<a;A++){let P=h[A],L=b[A];for(let D=0;D<a;D++)L[D]=A===D?P[D]+T:P[D];y[A]=-g[A]}let S=px(b,y,R);if(f=Math.max(f,S.condProxy),!S.singular){for(let L=0;L<a;L++)v[L]=i[L]+R[L];let A=e(v),P=hx(A);if(P<u){for(let L=0;L<a;L++)i[L]=v[L];c=A,u=P,l=fx(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 ts(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 fd(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 gx=e=>[e[0],-e[1],-e[2],-e[3]];function yx(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 xx(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 Rx(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 vx(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 kx(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 zC(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 YC(e){let t=e.hardpoints,r=q(H(t.damperChassis,t.pushrodOuter)),[n,o]=zC(r);return{top:t.damperChassis,lower0:t.pushrodOuter,axis0:r,e1:n,e2:o}}function bd(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=es(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:YC(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(ot(n,a),e.c0),o)}function gd(e,t){return ee(e.lcaFront,It(e.lbjRel0,e.lcaDir,t))}function _o(e,t){return e.steerMovesRack?ee(e.tieInner0,U(e.rackAxis,t)):e.tieInner0}function yd(e,t,r,n){let o=_t(e,t,e.lbj0),a=gd(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,ot(h,d.e1)),u=X(b,ot(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=_o(e,n),p=(es(m,f)-e.tieLen2)/e.tieLenRef;return[s,i,c,l,u,p]}var rs=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]),qc=e=>{let t=rs(e);return[e[0]/t,e[1]/t,e[2]/t]},WC=(e,t)=>H(e,U(t,X(e,t))),xd=e=>qc(ae(e,Math.abs(e[0])<.6?[1,0,0]:[0,1,0]));function jC(e,t){let r=e.ucaDir,n=ee(e.ucaFront,U(r,e.ubjAxial0)),o=Math.sqrt(e.ubjRadius2),a=WC(H(e.ubj0,e.ucaFront),r),s=rs(a)>1e-9?qc(a):xd(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=ts(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=qc(c),d=(h,b)=>{let g=ee(n,ee(U(s,o*h),U(i,o*b))),y=qc(H(g,t));return{q1:xx(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 UC(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=rs(a),i=s>1e-9?U(a,1/s):xd(n),c=H(t.top,r),l=rs(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=xd(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:fd(hd(R,y,ae(R,y)),gx(hd(i,n,ae(i,n)))),k:u,margin:f,ok:f>=0}};return f>0?[h(1),h(-1)]:[h(1)]}function XC(e,t,r,n){let{k:o}=n,a=yx(n.q1,H(e.tro0,e.lbj0)),s=X(a,o),i=H(a,U(o,s)),c=rs(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=ts(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:fd(Rx(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 Mx(e,t,r,n=[0,0,0,0,0,0]){let o=gd(e,t),a=_o(e,r),s=vx([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?UC(e,e.strut,o):jC(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=XC(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=kx(m),d=H(H(o,e.c0),ot(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 Ax(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:es(e.pushrodOuter,e.rockerToPushrod),damperLen0:ve(e.rockerToDamper,e.damperChassis)}}var qC=(e,t)=>ee(e.pivotA,It(e.rprRel0,e.axis,t)),Rd=(e,t)=>ee(e.pivotA,It(e.rdmRel0,e.axis,t));function ns(e,t){return{pushrod:qC(e,t),damper:Rd(e,t)}}function Fx(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=ts(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(Rd(e,r),e.damperChassis),converged:p,margin:0}}let u=Sx(Math.atan2(l.s1,l.c1),r),m=Sx(Math.atan2(l.s2,l.c2),r),f=Math.abs(m-r)<Math.abs(u-r)?m:u;return{phi:f,damperLength:ve(Rd(e,f),e.damperChassis),converged:l.ok,margin:l.margin}}function Sx(e,t){let r=2*Math.PI;return e+r*Math.round((t-e)/r)}function wx(e,t,r,n){return ee(t,ot(U(q(r),n),H(e,t)))}function Cx(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 Tx(e,t,r,n){return ee(t,ot(U(q(r),n),H(e,t)))}var Qc=180/Math.PI,QC=(e,t,r)=>Math.max(t,Math.min(r,e)),Px=[NaN,NaN,NaN];function os(e){let t=q(e.spinAxis),r=q(H(e.uprightUpper,e.uprightLower)),n=-Math.asin(QC(t[2],-1,1))*Qc,o=Math.atan2(t[0],t[1])*Qc,a=Math.atan2(-r[0],r[2])*Qc,s=Math.atan2(-r[1],r[2])*Qc,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]):Px,d=m?f(e.wheelCenter[2]):Px,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=mx(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 tt(e){return{corner:e,inv:bd(e),rocker:Ax(e.hardpoints)}}var ZC=[20,20,20,.2,.2,.2];function Dx(e,t,r,n=[0,0,0,0,0,0]){let o=Mx(e,t,r,n);if(!o.free)return o;let a=JC(e,t,r,n);return{x:a.x,converged:a.converged,margin:0}}function JC(e,t,r,n=[0,0,0,0,0,0]){return bx(o=>yd(e,o,t,r),n,{scales:ZC,tol:1e-10,maxIter:40})}var eT=.01,Zc=1.2,ht=e=>e.ok?e.state:null,at=e=>e.ok?e.state:e.nearest;function ye(e,t,r,n,o){let a=0,s=Ie(e,a,r,n,o);if(Math.abs(s.travel-t)<1e-4)return Lx(s,t,!1);let c=(Ie(e,.02,r,vd(s),o).travel-s.travel)/.02;(!Number.isFinite(c)||Math.abs(c)<1e-6)&&(c=1);let l=f=>Math.max(-Zc,Math.min(Zc,f)),u=l((t-s.travel)/c),m=Ie(e,u,r,vd(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,vd(s),o)}return Lx(m,t,Math.abs(u)===Zc)}function Lx(e,t,r){let n=e.travel-t,o=Math.abs(n)<=eT,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 vd(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 tT(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=Cx(t.ubj0,a,t.ucaFront,t.ucaDir);return Tx(o.pushrodOuter,t.ucaFront,t.ucaDir,s)}default:return wx(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=Dx(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(ot(u,p.spinAxis)),k=tT(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}:Fx(e.rocker,k,n?.phi??0),M=os({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 No=e=>e==="FL"||e==="FR"?"front":"rear",Ix=e=>e==="FL"||e==="RL"?"left":"right";function $e(e,t){return e.corners?.[t]??rT(e[No(t)],Ix(t))}function _x(e){let t=e.config.springSplit;return e.config.actuation==="decoupled"||t===void 0||!Number.isFinite(t)||Math.abs(t)>=1?0:t}var Ex=new WeakMap;function rT(e,t){let r=_x(e);if(r===0)return e;let n=Ex.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)},Ex.set(e,n)}return n[t]}var Oo=["FL","FR","RL","RR"],bt=e=>2*e.hardpoints.wheelCenter[1],Qr=(e,t)=>t?bt($e(e,"FL"))/2+bt($e(e,"FR"))/2:bt($e(e,"RL"))/2+bt($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 Nt(e,t){return[t.axleX+e[0],t.sideSign*e[1],e[2]]}function Zr(e,t){return[e[0],t.sideSign*e[1],e[2]]}function Vo(e){return e.frontAxleX-e.wheelbase/2}function kd(e,t,r){return t[2]+e.heave+(t[0]-r)*Math.sin(e.pitch)-t[1]*Math.sin(e.roll)}function Jr(e,t,r,n){let o=Ze(e,t),a=(n?Qr(n,o.isFront):o.isFront?t.trackFront:t.trackRear)/2,s=o.sideSign*a,i=o.axleX-Vo(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 nT={travelMin:-40,travelMax:40,steps:41,steer:0};function as(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 Ge(e,t={}){let r={...nT,...t},n=tt(e);return Bo(n,r)}function Bo(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:as(m),converged:m.converged});let f=as(m);for(let R=1;R<=l;R++){let k=c*R/l,v=Ie(e,k,r,f);f=as(v),u.push({beta:k,travel:v.travel,warm:f,converged:v.converged})}f=as(m);for(let R=1;R<=l;R++){let k=-c*R/l,v=Ie(e,k,r,f);f=as(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=oT(u,k,p),x=aT(u,v);y.push(Ie(e,v,r,x))}return sT(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 oT(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 aT(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 Md(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 sT(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=Md(n,r,s),c=Md(o,r,s),l=-Md(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 Jc=e=>e!==void 0&&Number.isFinite(e)&&e>0;function iT(e){return e&&Jc(e.helperRate)&&Jc(e.helperTravel)?{rate:e.helperRate,travel:e.helperTravel}:null}function Sd(e,t,r){let n=t/e;return r?n+Math.min(t/r.rate,r.travel):n}function ss(e,t,r,n){if(!(e>0)||!Number.isFinite(e)||!(t>0)||!Number.isFinite(t))return null;let o=iT(n),a=-Sd(e,t,o),s=$o(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 $o(e,t){if(!Number.isFinite(e))return{droop:null,bump:null};let r=Jc(t?.extended)&&t.extended>e?t.extended:null,n=r!==null&&Jc(t?.stroke)?r-t.stroke:null;return{droop:r!==null?e-r:null,bump:n!==null&&n<e?e-n:null}}function Ad(e,t){if(!(e>0)||!Number.isFinite(e))return null;let r=$o(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 cT(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=Sd(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 lT(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=Sd(r,n,o)+t;return a<=0?0:a>=o.rate*o.travel/r+o.travel?r:r*o.rate/(r+o.rate)}function Go(e,t){let r=cT(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 Fd(e,t){let r=lT(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 wd(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 el={min:-60,max:60,steps:61},Cd=e=>({travel:[e.min,e.max],force:[0,0],motionRatio:[0,0],spring:null}),Nx=new WeakMap;function uT(e,t){let r=Nx.get(e.corner);r||Nx.set(e.corner,r=new Map);let n=`${t.min}|${t.max}|${t.steps}`,o=r.get(n);return o||r.set(n,o=Bo(e,{travelMin:t.min,travelMax:t.max,steps:t.steps,steer:0})),o}function is(e,t,r=el,n=e.corner.config.coilover){let o=e.corner.config;if(o.actuation==="decoupled")return Cd(r);let a=uT(e,r),s=pT(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 Cd(r);let c=fT(i,0);if(!(Math.abs(c.mr)>1e-6))return Cd(r);let l=t/c.mr,u=ss(s,l,c.L,n),m=u?mT(i,wd(u).map(h=>c.L-h)):i,f=m.map(h=>(u?Go(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?wd(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 mT(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 pT(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:dT(e,n,r);return!(o>0)||!Number.isFinite(o)?t:t*o/(t+o)}function dT(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=ns(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 Td(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.motionRatio[0];let n=yr(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 gr(e,t,r){if(!e.spring)return Ht(e,t);let{rate:n,preload:o,length0:a,law:s}=e.spring,i=Td(e,0),c=a-r;return(s?Go(s,c):o+n*c)*Td(e,t)-o*i}function fT(e,t){let r=yr(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 yr(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 Ht(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.force[0];let n=yr(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 Ko(e,t){let r=e.travel.length;if(r<3)return cs(e,t);let n=yr(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=yr(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(ot(r.pose.omega,o),n.wheelCenter),r.pose.t)}case"lowerArm":{let o=q(H(n.lcaRear,n.lcaFront));return ee(n.lcaFront,ot(U(o,r.beta),H(t.outer,n.lcaFront)))}case"rocker":{let o=q(H(n.rockerPivotB,n.rockerPivotA));return ee(n.rockerPivotA,It(H(t.outer,n.rockerPivotA),o,r.points.rockerAngle))}}}function en(e,t,r){return e.config.actuation==="decoupled"&&t.attach==="rocker"&&r==="coil"}function Pd(e,t,r){return en(e,t,r)?[t.inner[0],-t.inner[1],t.inner[2]]:t.inner}function Ho(e,t,r){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return Ld(e,t,r.kind,Ge(e,{travelMin:n,travelMax:o,steps:a}).samples)}function Ld(e,t,r,n){let o=q(H(t.outer,Pd(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 Dd(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 Ed(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 ls=e=>e.mount??{kind:"rockerToRocker"},$x=e=>[e[0],0,e[2]],hT=e=>2*Math.abs(e[1]),bT=(e,t)=>Math.hypot(e[0]-t[0],e[2]-t[2]);function rl(e,t){return t.kind==="chassis"?bT(e,t.anchor):hT(e)}function us(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 wn(e,t,r={}){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return Id(e,t,Ge(e,{travelMin:n,travelMax:o,steps:a}).samples)}function Id(e,t,r){let n=ls(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(rl(o(d),n));let c=Vx(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=Ox(a,20),f=Ox(a,-20),p=us(o(m),o(f),n);return{travel:a,ratio:u,springTravel:s,atDesign:Vx(a,u,0),installedLength:c,rollSensitivity:c-p}}function Ox(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 Vx(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 _d(e,t,r){let n={outer:t.outer,attach:t.attach},o=Ge(e,{travelMin:-5,travelMax:5,steps:3}),a=d=>$x(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 Nd(e,t){let r=e.hardpoints,n=r.rockerPivotA,o=Bx(tl(r.rockerPivotB,r.rockerPivotA)),a=Math.max(30,.6*Gx(tl(r.rockerToDamper,n))),s=tl(r.rockerToDamper,n),i=Bx(tl(s,gT(o,yT(s,o)))),c=xT(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:_d(e,d)}}:d,b;try{b=wn(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 tl=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],gT=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],yT=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],Gx=e=>Math.hypot(e[0],e[1],e[2]),Bx=e=>{let t=Gx(e)||1;return[e[0]/t,e[1]/t,e[2]/t]},xT=(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 Od=.001,RT=e=>({outer:e.outer,inner:e.outer,attach:e.attach}),Xx=(e,t,r)=>(rl(e.at0,t)-rl(r,t))/2,vT=(e,t)=>X(H(t,e.pickup.at0),e.axis);function Vd(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 Kx(e,t){let r=[0,1,2].map(n=>Vd(e,t.map(o=>o[n])));return t.map((n,o)=>[r[0][o],r[1][o],r[2][o]])}function Bd(e){return{travel:e,heave:e.map(t=>t/2),heaveRatio:e.map(()=>.5),roll:[...e],rollRatio:e.map(()=>1)}}function Hx(e,t,r,n){let o=e.corner;if(!t.heave&&!t.roll)return{side:Bd([n.min,n.max]),pickups:{}};let a=at(ye(e,0,0)),s={};if(t.heave&&r){let h=RT(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,Pd(o,h,t.rollKind??"coil")))}}let i=t.roll&&en(o,t.roll,t.rollKind??"coil")?{near:t.roll,far:{...t.roll,outer:t.roll.inner}}:null,c=Bo(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?Xx(s.heave,r,De(o,s.heave.link,h)):h.travel/2),m.push(s.roll?vT(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:Bd([n.min,n.max]),pickups:{}};let d={travel:l,heave:u,heaveRatio:Vd(l,u),roll:m,rollRatio:Vd(l,m)};return i&&(d.eyes={near:f,nearRatio:Kx(l,f),far:p,farRatio:Kx(l,p)}),{side:d,pickups:s}}function nl(e,t,r){let n=yr(e,r);return t[n]+(r-e[n])/(e[n+1]-e[n])*(t[n+1]-t[n])}function zx(e,t,r){let n=yr(e,r);return(t[n+1]-t[n])/(e[n+1]-e[n])}function Ye(e,t){return{h:nl(e.travel,e.heave,t),dh:nl(e.travel,e.heaveRatio,t),ddh:zx(e.travel,e.heaveRatio,t),r:nl(e.travel,e.roll,t),dr:nl(e.travel,e.rollRatio,t),ddr:zx(e.travel,e.rollRatio,t)}}function Yx(e,t,r,n){let o=yr(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 $d=(e,t)=>Math.hypot(e[0]-t[0],e[1]+t[1],e[2]-t[2]);function qx(e,t){let r=e.side[0].eyes,n=e.side[1].eyes;if(!r||!n)return null;let o=Yx(e.side[0].travel,r.near,r.nearRatio,t[0]),a=Yx(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 Qx=(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,kT=(e,t)=>e.bump!==null&&t>e.bump||e.droop!==null&&t<e.droop?e.rate:0;function ms(e,t,r,n,o=0){let a=e.rollStop;if(!a)return r;let s=qx(e,t);if(!s)return r;let i=Qx(a,a.length0-(n??s.L+o));return i===0?r:[r[0]-i*s.dL[0],r[1]-i*s.dL[1]]}function ol(e,t){let r=Bd(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?Go(e.law,t):e.preload+e.rate*t:0,Wx=(e,t)=>e?e.law?Fd(e.law,t):e.rate:0;function ps(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 jx=(e,t)=>Ye(e[0],t).h+Ye(e[1],t).h;function MT(e,t){let r=e.gap>0?jx(t,e.gap):0;return e.bothWays?{free:r,pull:e.gap>0?jx(t,-e.gap):0}:{free:r,pull:null}}function ST(e,t,r){let n={...t,outer:t.inner},o=(u,m)=>{let f=ht(ye(e[0],u,0)),p=ht(ye(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=Ye(r[0],a).r-Ye(r[1],-a).r-(Ye(r[0],-a).r-Ye(r[1],a).r),l=i/c;return Number.isFinite(s)&&s>0&&Number.isFinite(l)&&Math.abs(l)>Od?{length0:s,scale:l}:null}function Zx(e,t,r,n=el){let o=r.heave?ls(r.heave):void 0,a=Hx(e[0],r,o,n),s=e[1].corner===e[0].corner?a:Hx(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(A=>Ye(A,0));c&&!(Math.abs(p[0].dh+p[1].dh)>Od)&&(i=[ol(i[0],"heave"),ol(i[1],"heave")],c=!1),l&&!(Math.abs(p[0].dr+p[1].dr)>Od)&&(i=[ol(i[0],"roll"),ol(i[1],"roll")],l=!1),p=i.map(A=>Ye(A,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 A=[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=(-A[0]*p[1].dr-A[1]*p[0].dr)/P,R=(p[0].dh*A[1]-p[1].dh*A[0])/P)}else b>0?y=(A[0]+A[1])/d:g>0&&(R=(A[0]-A[1])/h)}let k={};if(c&&o){let A=[a.pickups.heave,s.pickups.heave];k.heave={pickups:A,mount:o,span0:us(A[0].at0,A[1].at0,o)}}let v=k.heave?k.heave.span0:NaN,x=k.heave?r.coilover:void 0,M=r.carriesLoad?ss(b,y,v,x):u?Ad(b,{...MT(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&&en(e[0].corner,r.roll,r.rollKind??"coil"))){let A=ST(e,r.roll,i);A&&(k.roll.unit=A)}let w=g>0?{rate:g,preload:R}:null,C={side:i,heave:F,roll:w,force0:[0,0],carriesLoad:r.carriesLoad,read:k},T=k.roll?.unit,S=T&&g>0&&i[0].eyes&&i[1].eyes?$o(T.length0,r.rollCoilover):null;return T&&S&&(S.droop!==null||S.bump!==null)&&(C.rollStop={length0:T.length0,rate:1e3*g/(T.scale*T.scale),...S}),C.force0=ms(C,[0,0],ps(C,p[0],p[1],p[0].h+p[1].h,p[0].r-p[1].r)),C}function ds(e,t,r){let n=Ye(e.side[0],t[0]),o=Ye(e.side[1],t[1]),a=r?ms(e,t,ps(e,n,o,n.h+o.h+r.heave,n.r-o.r+r.roll),void 0,r.unit):ms(e,t,ps(e,n,o,n.h+o.h,n.r-o.r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function Gd(e,t,r){let n=Ye(e.side[0],t[0]),o=Ye(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=Wx(e.heave,a),c=Wx(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?qx(e,t):null;if(!p||!d)return f;let h=p.length0-(r?d.L+r.unit:d.L),b=kT(p,h);if(b===0)return f;let g=Qx(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 Kd(e,t,r){let n=Gd(e,t);return n[r][0]+n[r][1]}function AT(e,t,r){let n=e.read.heave;if(!n)return Ye(e.side[0],t[0]).h+Ye(e.side[1],t[1]).h;let[o,a]=n.pickups;return n.span0-us(De(o.corner,o.link,r[0]),De(a.corner,a.link,r[1]),n.mount)}function FT(e,t,r){let n=e.read.roll;if(!n)return Ye(e.side[0],t[0]).r-Ye(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 wT(e,t){let r=e.read.roll;if(!e.rollStop||!r)return;let[n,o]=r.pickups;return $d(De(n.corner,n.link,t[0]),De(o.corner,{...o.link,outer:o.link.inner},t[1]))}function fs(e,t,r){let n=Ye(e.side[0],t[0]),o=Ye(e.side[1],t[1]),a=ms(e,t,ps(e,n,o,AT(e,t,r),FT(e,t,r)),wT(e,r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function Hd(e,t,r,n){let o=Ye(e.side[0],r),a=Ye(e.side[1],r),s=e.read.heave,i=s?.pickups[t],c=s&&i&&n?2*Xx(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?$d(De(l.corner,l.link,n),De(l.corner,{...l.link,outer:l.link.inner},n)):void 0;return ms(e,[r,r],ps(e,o,a,c,n?0:o.r-a.r),u)[t]-e.force0[t]}function zd(e,t,r,n){let o=Ko(e,r[n]);return t?.carriesLoad?o+Kd(t,r,n):o}var Yd=e=>e==="FR"||e==="RR"?1:0,sl=(e,t)=>e.elements?.[t==="FL"||t==="FR"?"front":"rear"]??null;var Jx=e=>Number.isFinite(e)&&e>0?1/e:0;var eR=(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},CT=(e,t)=>[e[0][0]*t[0]+e[0][1]*t[1],e[1][0]*t[0]+e[1][1]*t[1]],tR=1e-8,TT=40;function PT(e,t,r,n){return{force:(s,i)=>{if(r){let u=ds(r,s,n);return[Ht(t[0],s[0])+i[0]+u[0],Ht(t[1],s[1])+i[1]+u[1]]}let c=(s[0]+s[1])/2,l=(s[0]-s[1])/2;return[Ht(t[0],s[0])+i[0]+e[0].heaveRate*c+e[0].arbRate*l,Ht(t[1],s[1])+i[1]+e[1].heaveRate*c-e[1].arbRate*l]},stiffness:(s,i=cs)=>{if(r){let c=Gd(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 zo(e,t,r,n,o,a=[0,0],s=[0,0],i=null,c){let l=[Jx(r[0].tyreRate),Jx(r[1].tyreRate)],u=[r[0].staticLoad,r[1].staticLoad],m=PT(r,n,i,c),f=P=>m.force(P,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=(P,L)=>{let D=L===1?f(P):m.force(P,[a[0]*L,a[1]*L]),E=[D[0]+s[0]*L,D[1]+s[1]*L],V=[P[0]+t[0]*L+E[0]*l[0]-e[0]*L,P[1]+t[1]*L+E[1]*l[1]-e[1]*L],N=[d[0]*(u[0]+E[0]),d[1]*(u[1]+E[1])],z=[N[0]<V[0],N[1]<V[1]];return{f:E,on:V,off:N,lifted:z,r:[Math.min(V[0],N[0]),Math.min(V[1],N[1])]}},b=(P,L)=>[L[0]?[d[0]*P[0][0],d[0]*P[0][1]]:[1+P[0][0]*l[0],P[0][1]*l[0]],L[1]?[d[1]*P[1][0],d[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]],E=h(D,L),V=!1,N=0;for(;N<TT;N++){if(g(E.r)<tR){V=!0;break}let z=eR(b(m.stiffness(D),E.lifted),[-E.r[0],-E.r[1]]);if(!z)break;let I=1,_=[D[0]+z[0],D[1]+z[1]],B=h(_,L);for(let O=0;O<8&&g(B.r)>g(E.r);O++)I/=2,_=[D[0]+I*z[0],D[1]+I*z[1]],B=h(_,L);D=_,E=B}return!V&&g(E.r)<tR&&(V=!0),{t:D,b:E,converged:V,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 P=0,L=[0,0],D=.25;for(;P<1&&D>=1/256;){let E=Math.min(1,P+D),V=y(L,E);k+=V.it,V.converged?(P=E,L=V.t,E===1&&(R=V)):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]],C=[F[0]?Math.max(0,x.on[0]):0,F[1]?Math.max(0,x.on[1]):0],T=m.stiffness(v,Ko),S=b(T,F);return{t:v,dF:w,lifted:F,clearance:C,converged:M,iterations:k,respond:(P,L,D=[0,0])=>{let E=[F[0]?-d[0]*D[0]:P[0]-L[0]-D[0]*l[0],F[1]?-d[1]*D[1]:P[1]-L[1]-D[1]*l[1]],V=eR(S,E);if(!V)return[NaN,NaN];let N=CT(T,V);return[F[0]?0:N[0]+D[0],F[1]?0:N[1]+D[1]]}}}var Cn=e=>!(Number.isFinite(e.tyreRate)&&e.tyreRate>0);function Zt(e,t,r){return t?.input.corners[r].staticLoadedRadius??e}var Wd=["FL","FR","RL","RR"],oR={front:["FL","FR"],rear:["RL","RR"]},LT=512,DT=5e-4,ET=8;function il(e,t){let r={},n={},o=new Map;for(let s of Wd){let i=e.ctx[s],c=t.corners[s],l=c.staticLoadedRadius;n[s]=at(ye(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=`${Wd.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?is(i,c.springLoad,void 0,u):is(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=oR[s];a[s]=Zx([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 aR(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 IT=e=>`${e.heave}|${e.pitch}|${e.roll}|${e.steer}`;function jd(e,t,r){return{travel:r.travel,steer:r.steer,ground:r.travel,tyreDeflection:0,load:NaN,loadedRadius:Zt($e(e.vehicle,t).config.loadedRadius,e.kc,t),lifted:!1,contactLength:0,converged:!0,rigid:!0,rideRate:NaN,wheelRateAtLoad:NaN}}var _T=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 rR(e,t,r,n){let o=oR[n],a=e.vehicle.config,s=o.map(w=>Jr(w,a,r,e.vehicle)),i=[t.input.corners[o[0]],t.input.corners[o[1]]],c=t.loadCase;if(!c&&i.every(Cn))return{corners:[jd(e,o[0],s[0]),jd(e,o[1],s[1])],respond:null};let l=o.map(w=>t.curve[w]),u=t.elements?.[n]??null,m=o.map(w=>Zt($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=zo(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<ET;w++){w>0&&(y=zo(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 C=[0,0],T=[0,0];for(let A=0;A<2;A++){let P=ye(e.ctx[o[A]],y.t[A],s[A].steer,_T(R[A]),{loadedRadius:m[A]-v[A],patchShift:d[A]}),L=at(P);R[A]=L,k[A]=P.ok,C[A]=L.points.contactPatch[2]-t.ground0[o[A]]-y.t[A]-v[A],T[A]=gr(l[A],y.t[A],L.points.damperLength)-Ht(l[A],y.t[A])}if(u){let A=fs(u,y.t,[R[0],R[1]]),P=ds(u,y.t);T[0]+=A[0]-P[0],T[1]+=A[1]-P[1]}let S=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,S<DT){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: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:aR(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:zd(l[w],u,y.t,w)}}),respond:y.respond}}function sR(e,t){let r=e.kc,n=IT(t),o=r.memo.get(n);if(o)return o;let a=rR(e,r,t,"front"),s=rR(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>=LT&&r.memo.clear(),r.memo.set(n,i),i}function gt(e,t){if(!e.kc){let r={};for(let n of Wd)r[n]=jd(e,n,Jr(n,e.vehicle.config,t,e.vehicle));return r}return sR(e,t).corners}function cl(e,t,r){return e.kc?sR(e,t).respond[r]:null}function hs(e,t,r,n=0){let o=e.kc;if(!o)return r;let a=o.input.corners[t];if(Cn(a))return r;let s=Jr(t,e.vehicle.config,{heave:0,pitch:0,roll:0,steer:n},e.vehicle).steer,i=Zt($e(e.vehicle,t).config.loadedRadius,o,t),c=o.loadCase,l=c?.linkLoad[t]??0,u=c?.patchShift[t],m=at(ye(e.ctx[t],r,s,void 0,{loadedRadius:i,patchShift:u})),f=sl(o,t),p=gr(o.curve[t],r,m.points.damperLength)+(f?Hd(f,Yd(t),r,m):a.heaveRate*r),h=Math.max(p+l,-a.staticLoad)/a.tyreRate;return(h===0?m:at(ye(e.ctx[t],r,s,void 0,{loadedRadius:i-h,patchShift:u}))).points.contactPatch[2]-o.ground0[t]-(c?.ground[t]??0)}var NT=180/Math.PI,OT=[0,0,1];function VT(e,t){let r=Zr(e,t),n=U(ae(OT,r),-t.sideSign);return-Math.atan2(n[1],n[0])*NT}var iR=e=>1/Math.tan(e*Math.PI/180),cR=.05,lR=.001;function uR(e,t,r){if(!Number.isFinite(e)||!Number.isFinite(t))return NaN;if(!(Math.abs(e)<lR&&Math.abs(t)<lR))return e>0&&t>0?100*(iR(t)-iR(e))/r:NaN}function BT(e,t){let r=Qr(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=[cR,-cR].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 Ud(e,t){let r=e.vehicle.config,n={FL:Ze("FL",r),FR:Ze("FR",r)},o=t.travel??0,a=BT(e,(i,c)=>{let l=ht(ye(e.ctx[i],o,n[i].sideSign*c));return{deg:l?VT(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 mR=35,pR=55,Ot=e=>e.rackTravel&&e.rackTravel>0?e.rackTravel:mR,Xd=e=>e.rackRatio&&e.rackRatio>0?e.rackRatio:pR;var qd=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 dR(e,t,r,n,o){let a=ye(e,n,0,void 0,o),s=at(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=qd(s);for(let b=1;b<=r;b++){let g=p*(t*b)/r,y=Ie(e,s.beta,g,h,o),R=ht(ye(e,n,g,qd(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=qd(y)}return d},m=u(1),f=u(-1);return{travelMm:n,unsolved:i,centre:l,positive:m,negative:f}}function $T(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 fR(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:$T(o,t)});return{travelMm:e.travelMm,inner:n(r?e.positive:e.negative),outer:n(r?e.negative:e.positive)}}function GT(e){return e.positive[1].steer-e.centre.steer<0}function KT(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:Xd(e.config),innerJacobian:r.inner.jacobian,outerJacobian:r.outer.jacobian}}function Qd(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=dR(i,t,r,0,s),u=GT(l),m=fR(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=dR(i,t,r,b,s);return d+=g.unsolved,fR(g,c,u)});return{...KT(e,c,m),...hR(l.unsolved),travelSurface:{rackMm:c,rows:h,...hR(d)}}}var hR=e=>e>0?{unsolved:e}:{};function Jt(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 ll(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 bR(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 Tn=(e,t,r)=>e+r*(t-e);function Yo(e,t,r,n,o){let a=Jt(e.rackMm,e.rows[n.lo][t][r],o);if(n.lo===n.hi)return a;let s=Jt(e.rackMm,e.rows[n.hi][t][r],o);return Tn(a,s,n.t)}function gR(e,t,r,n){let o=ll(e.rackMm,e.rows[r.lo][t].jacobian,n);if(r.lo===r.hi)return o;let a=ll(e.rackMm,e.rows[r.hi][t].jacobian,n);return{longitudinal:Tn(o.longitudinal,a.longitudinal,r.t),lateral:Tn(o.lateral,a.lateral,r.t),vertical:Tn(o.vertical,a.vertical,r.t),yaw:Tn(o.yaw,a.yaw,r.t)}}function Wo(e,t,r,n){let o=e.travelSurface;if(!o||o.rackMm.length<2||o.rows.length===0)return jo(e,t);let a=bR(o,r),s=bR(o,n),i=(p,d,h)=>{let b=o.rows[d.lo][p].steerDeg[h];return d.lo===d.hi?b:Tn(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=Tn(o.rackMm[d],o.rackMm[p],b)}return{innerDeg:Yo(o,"inner","steerDeg",a,m),outerDeg:Yo(o,"outer","steerDeg",s,m),innerCamber:Yo(o,"inner","camberDeg",a,m),outerCamber:Yo(o,"outer","camberDeg",s,m),innerLift:Yo(o,"inner","liftMm",a,m),outerLift:Yo(o,"outer","liftMm",s,m),innerJacobian:gR(o,"inner",a,m),outerJacobian:gR(o,"outer",s,m),atLock:f}}function jo(e,t){let r=e.meanDeg.length-1;return{innerDeg:Jt(e.meanDeg,e.innerDeg,t),outerDeg:Jt(e.meanDeg,e.outerDeg,t),innerCamber:Jt(e.meanDeg,e.innerCamber,t),outerCamber:Jt(e.meanDeg,e.outerCamber,t),innerLift:e.innerLift?Jt(e.meanDeg,e.innerLift,t):0,outerLift:e.outerLift?Jt(e.meanDeg,e.outerLift,t):0,...e.innerJacobian&&e.outerJacobian?{innerJacobian:ll(e.meanDeg,e.innerJacobian,t),outerJacobian:ll(e.meanDeg,e.outerJacobian,t)}:{},atLock:r>=0&&t>e.meanDeg[r]}}var HT=()=>({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 Uo(e,t,r=Te(e),n){let o=e.steerFront;if(!o?.innerLift||!o.outerLift||o.meanDeg.length<2||Math.abs(t)<1e-12)return HT();let a=Math.abs(t),s=t>0,i=n&&o.travelSurface?Wo(o,a,s?n.FL:n.FR,s?n.FR:n.FL):null,c=i?.innerLift??Jt(o.meanDeg,o.innerLift,a),l=i?.outerLift??Jt(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 Zd(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 bs=9.81;function Xo(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?Ur(e,t,r,Io(e,n,o)):Do(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 Jd(e,t,r=0,n=0,o=0){if(!e.aero?.model||t<=0)return!1;let a=Ur(e,t,r,Io(e,n,o));return a!=null&&(a.clampedRide||a.clampedAttitude)}function Pn(e){let t=e.loadFactor===void 0?e.massTotal*bs:e.massTotal*bs*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 yR(e,t=Te(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*Bc(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 ef(e){let{cf:t,cr:r}=yR(e);return t+r>0?t/(t+r):.5}function xR(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 we(e,t,r,n=0,o=0,a=0,s,i){return ul(e,t,r,n,o,a,s,i).loads}function ul(e,t,r,n=0,o=0,a=0,s,i){let c=Pn(e),l=Te(e),u=Xc(e,n,r,Io(e,t,o),l),{cf:m,cr:f}=yR(e,l,u.height),p=m*t*bs,d=f*t*bs,h=e.massTotal*(r*bs)*u.height/e.wheelbase-u.noseLoad,b=Xo(e,n,r,t,o),g=(i??Uo(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 xR(y,e.trackFront,e.trackRear)}var tf=Math.PI/180;function pl(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 RR(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 ys=.999;function St(e,t,r,n,o){if(t<=0)return 0;let{aPeak:a,fyPeak:s}=o??pl(e,t),i=Math.min(Math.abs(r),ys*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 C=.5*(v+x),T=l(C,a);T>=i?(v=C,M=T):(x=C,F=T)}Number.isNaN(M)&&(M=l(0,a)),m=M<i?0:RR(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 C=0;C<5;C++){let T=.5*(x+M),S=l(v,T);S<i?(x=T,F=S):(M=T,w=S)}return Number.isNaN(F)&&(F=l(v,0)),Number.isNaN(w)&&(w=l(v,a)),c*e.forces({Fz:t,kappa:c*v,alpha:RR(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=jT(p,h(g-1),h(Math.min(d,g+1)),h(g),b[g],h(y),b[y],h(R),b[R],zT);return c*Math.max(0,k)}var zT=.01,YT=20,WT=(3-Math.sqrt(5))/2;function jT(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<YT;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=WT*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 of(e,t){return e.model?.kind==="simple"?null:MR(e,t)}var vR=new WeakMap,rf=100,kR=1.35,nf=18,er=41,ml=41,gs=65;function MR(e,t){let r=vR.get(e);if(r)return r;let n=Math.log(kR),o=(p,d)=>{let h=M=>Math.abs(St(e,p,M,d)),b=h(0),g=t.muY(p)*p,y=new Float64Array(er),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 C=0;C<ml;C++){let T=Math.sin(.5*Math.PI*C/(ml-1));M.push(T),F.push(C===0?1:C===ml-1?0:Math.min(F[C-1],h(T*g)/b))}let w=ml-1;for(let C=0;C<er;C++){let T=C/(er-1);for(;w>0&&F[w-1]<T;)w--;let S=w>0?F[w-1]-F[w]:0;y[C]=w===0?M[0]:M[w]+(S>0?(T-F[w])/S:0)*(M[w-1]-M[w])}y[0]=1,y[er-1]=0}let k=new Float64Array(gs),v=M=>Math.atan2(y[M],M/(er-1)/R),x=er-2;for(let M=0;M<gs;M++){let F=.5*Math.PI*M/(gs-1),w=Math.cos(F),C=Math.sin(F);for(;x>0&&v(x)<F;)x--;let T=x/(er-1)/R,S=y[x],A=(x+1)/(er-1)/R,P=y[x+1],L=w*(P-S)-C*(A-T),D=Math.abs(L)>1e-12?(T*(P-S)-S*(A-T))/L:Math.hypot(T,S);k[M]=D>0?D:Math.hypot(T,S)}return{room:y,scale:R,edge:k}},a=Array.from({length:nf},(p,d)=>rf*kR**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)*(er-1),b=Math.min(er-2,Math.floor(h));return p.room[b]+(h-b)*(p.room[b+1]-p.room[b])},l=p=>{let d=p>rf?Math.log(p/rf)/n:0;if(d>=nf-1)return[nf-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)*(gs-1),k=Math.min(gs-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 vR.set(e,f),f}var UT=[["front","FL","FR"],["rear","RL","RR"]];function qo(e,t,r,n){let o={...e},a=0,s=ys;for(let[i,c,l]of UT){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 SR=.001,XT=1e-5,AR=100;function qT(e,t,r,n){if(!(n>SR))return r;let o=t,a=Math.abs(r-t)<AR?t+Math.sign(r-t)*AR:r;for(let s=0;s<60&&Math.abs(a-o)>XT;s++){let i=.5*(o+a);e(i)>SR?a=i:o=i}return o}function dl(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=qT(e,t,o,e(o));return a!==o&&(n=a),a},edge:()=>n}}function fl(e,t){let r=n=>{try{return ye(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 af=40;function hl(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 FR=[0,0,0];function QT(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 bl(e,t,r){if(e.mcpherson)return ZT(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??FR,c=[-t[0],-t[1],-t[2],-(s[0]+i[0]),-(s[1]+i[1]),-(s[2]+i[2])],l=Qt(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]:QT(e,u[5]),condProxy:l.condProxy,singular:l.singular}}function ZT(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??FR,l=[-t[0],-t[1],-t[2],-(i[0]+c[0]),-(i[1]+c[1]),-(i[2]+c[2])],u=Qt(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 sf(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 JT=[0,0,0];function xs(e,t,r,n){let o=e.direct?e.damperChassis:e.rockerToPushrod;if(e.mcpherson)return{...bl(e,r,n),armResidual:0};if(t==="upright")return{...bl(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??JT,b=[-r[0],-r[1],-r[2],-(d[0]+h[0]),-(d[1]+h[1]),-(d[2]+h[2])],g=Qt(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)),C=U(M,-1),T=(Z,ne)=>X(F,ae(H(Z,i.front),ne)),S=T(e.pushrodOuter,w),A=Math.abs(S)>1e-9?-T(i.bj,C)/S:NaN,P=ee(C,U(w,A)),L=U(P,-1),D=q(H(i.front,i.bj)),E=q(H(i.rear,i.bj)),V=X(D,D),N=X(D,E),z=X(E,E),I=X(D,L),_=X(E,L),B=V*z-N*N,O=NaN,G=NaN,K=NaN;if(Math.abs(B)>1e-12){O=(I*z-_*N)/B,G=(V*_-N*I)/B;let Z=ee(U(D,O),U(E,G)),ne=H(L,Z);K=Math.hypot(ne[0],ne[1],ne[2])}let Y=a?{f:k,r:v}:{f:O,r:G},j=a?{f:O,r:G}:{f:k,r:v};return{ucaFront:Y.f,ucaRear:Y.r,lcaFront:j.f,lcaRear:j.r,tieRod:x,pushRod:A,damper:y||!Number.isFinite(A)||e.decoupled?NaN:e.direct?A:eP(e,A),condProxy:g.condProxy,singular:y,armResidual:K}}function eP(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 bK=Math.PI/180;function Rs(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 CR=["QSX3","QSX8","QSX13","QSX14"],tP=["QSX1"],gl=["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",...CR];function rP(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 nP(e){let t=new Set(rP(e)),r=gl.filter(n=>!CR.includes(n));return[...r.filter(n=>!t.has(n)),...[...t].filter(n=>!r.includes(n)),...tP]}function oP(e,t){let r={...e};for(let n of t)r[n]!==void 0&&r[n]!==0&&(r[n]=-r[n]);return r}var xr=(e,t,r)=>Number.isFinite(e[t])?e[t]:r;function TR(e,t){return t!=="5.2"?xr(e,"PKY6",0)*xr(e,"LKYC",1):xr(e,"PKY1",-15)*Math.sin(xr(e,"PKY4",2)*Math.atan(1/xr(e,"PKY2",2)))*xr(e,"LKY",1)*xr(e,"PHY3",0)+xr(e,"PVY3",0)*xr(e,"LMUY",1)}var wR=.1;function PR(e){if(e.fitData)return"sae";let t=TR(e.coeffs,e.version);return t>wR?"sae":t<-wR?"iso":null}function vs(e){return e.axisSystem??PR(e)??"sae"}function yl(e){let t=new Set,r=n=>{for(let o of n)t.has(o)?t.delete(o):t.add(o)};return vs(e)==="iso"&&r(gl),e.axisSystem&&e.side==="left"&&r(nP(e.version)),t.size?oP(e.coeffs,t):e.coeffs}var yK=Math.PI/180;var $=(e,t)=>Number.isFinite(e)?e:t;function DR(e){let t=yl(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 LR=new WeakMap;function ks(e){let t=LR.get(e);return t===void 0&&(t=DR(e),LR.set(e,t)),t}var ER=e=>e>=0?1:-1;function xl(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 Rl(e,t,r=0,n){let o=xl(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),C=e.version!=="5.2",T=s*(a.PVX1+a.PVX2*c)*a.LVX*a.LMUX,S=a.REX1+a.REX2*c;S>1&&(S=1);let A=a.REY1+a.REY2*c;return A>1&&(A=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: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:S,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:A,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: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?d/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 Ms(e,t){let r=t+e.SHy,n=e.EyA*(e.EyG-e.EyS*ER(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*ER(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 IR(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 aP(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=IR(e,o,r),i=e.Bt*s;return e.Dt*Math.cos(e.Ct*Math.atan(i-a*(i-Math.atan(i))))*n}function sP(e,t,r,n){return e.Dr*Math.cos(Math.atan(e.Br*IR(e,t+e.SHy+e.arOff,r)))*n}function _R(e,t,r,n,o,a){let s=Math.cos(t),i=aP(e,t,r,s),c=sP(e,t,r,s);return-i*(o-a)+c+(e.sS0+e.sS2*o)*n}function NR(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 cf(e,t){let r=e.sS0===0&&e.sS2===0?0:NR(e,0,t);return _R(e,t,0,r,Ms(e,t),0)}function kl(e,t,r){let n=Ms(e,r),o=NR(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:_R(e,r,t,o,m,u)}}var Ss=(e,t)=>Math.max(.1,e.muY0+e.loadSensY*(t-e.nominalLoad)),As=(e,t)=>Math.max(.1,e.muX0+e.loadSensX*(t-e.nominalLoad)),OR=(e,t,r)=>Ss(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cy*Math.atan(e.By*r)),VR=(e,t,r)=>As(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cx*Math.atan(e.Bx*r));function lf(e,t){let r=Math.max(1,t.Fz),n=Ss(e,r)*r,o=As(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 Qo=Math.PI/180;function tn(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 BR(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?Rs(r,t):1,s=n?Rs(n,t):1,i=o?Rs(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 Zo(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=BR(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=Rl(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=xl(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):lf(n,v),h=(v,x,M=0,F)=>e.kind==="magic"?Ms(p(x,M,F),v):OR(n,x,v),b=(v,x,M=0,F)=>e.kind==="magic"?vl(c(x,M,F),v):VR(n,x,v),g=(v,x,M=0,F)=>e.kind==="magic"?cf(c(x,M,F),v):d({Fz:x,kappa:0,alpha:v,gamma:M,p:F}).Mz,y=v=>e.kind==="simple"?Ss(n,v):Zo(x=>h(x*Qo,v),45,1)/Math.max(1,v),R=v=>e.kind==="simple"?As(n,v):Zo(x=>b(x,v),.6,.02)/Math.max(1,v),k=v=>{let x=.1*Qo;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 Jo(e){let t=Math.max(1,e.model.kind==="magic"?e.model.fnomin:e.model.nominalLoad);return e.Fy(2*Qo,t,0)-e.Fy(-2*Qo,t,0)>=0?1:-1}function Fs(e,t=e.kind==="magic"?e.fnomin:e.nominalLoad){let r=Pe(e),n=2*Qo,o=3*Qo,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 iP=Math.PI/180;function ge(e,t){return e.axle?e.axle(t):e}function Sl(e,t){if(e===t)return e;let r=Jo(e)*Jo(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=>Zo(u=>s(u,l),.6,.02)/Math.max(1,l),muY:l=>Zo(u=>i(u*iP,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 ut(e){if($R.has(e))return e;let t=GR.get(e);if(t)return t;let r;if(e.axle){let n=e.axle("front"),o=e.axle("rear"),a=ut(n),s=ut(o);r=a===n&&s===o?e:Sl(a,s)}else Jo(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 $R.add(r),r!==e&&GR.set(e,r),r}var $R=new WeakSet,GR=new WeakMap;var Al=25*(Math.PI/180);function cP(e){let t=.6180339887,r=0,n=Al,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 ws(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=Al;if(s(Al)<=a){let u=cP(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(Al,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 uf={shaft:!1,trail:0,hub:[0,0,0]};function HR(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 mf(e,t,r){let n=r.shaft?sf(e,t):[0,0,0];if(r.trail!==0){let a=HR(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 lP=(e,t)=>{let r=e!==void 0&&e>0?1/e:0,n=t!==void 0&&t>0?1/t:0;return r+n},Fl={ucaFront:0,ucaRear:0,lcaFront:0,lcaRear:0,tieRod:0,pushRod:0,rack:0};function Ln(e){return!e.measured}function Dn(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 Cs(e,t){let r=e.corner.hardpoints,n=ns(e.rocker,t.points.rockerAngle);return{ucaFront:r.ucaFront,ucaRear:r.ucaRear,lcaFront:r.lcaFront,lcaRear:r.lcaRear,tieInner:_o(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 pf(e,t,r=0){let n=t.links??{},o=t.bushings??{},a=(l,u,m)=>{let f=lP(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 zR(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 Ts(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=zR(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=zR(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 uP=8,mP=1e-5,pP=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 df(e,t,r){let n=mf(e,r.force,r.extras??uf),o=r.alignMoment?ee(n.moment,[0,0,r.alignMoment]):n.moment;return xs(e,t,n.force,o)}function Cl(e,t,r,n,o,a,s=0){let i=Ie(e,t,r,o,a),c=e.corner.compliance;if(!(Dn(c)&&Ln(e.corner)))return{state:i,forces:df(Cs(e,i),e.corner.config.pushrodAttach,n),deflection:Fl,rigid:i,iterations:0,converged:!0,bypassed:!0};let u=i,m=e,f=e.corner.config.pushrodAttach,p=df(Cs(e,i),f,n),d=Fl,h=!1,b=0;for(;b<uP;b++){let g=Cs(m,u);if(p=df(g,f,n),p.singular)break;d=pf(p,c,s),m=Ts(e,d);let y=Ie(m,t,r,pP(u),a),R=ve(y.points.wheelCenter,u.points.wheelCenter);if(u=y,R<mP){h=!0;break}}return{state:u,forces:p,deflection:d,rigid:i,iterations:b+1,converged:h&&u.converged,bypassed:!1}}var wl=1e3,YR=1e5;function WR(e,t,r,n,o){let a=Cl(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 Tl(e,t,r,n,o){let a={force:[0,0,n]},s=(b,g=0)=>WR(e,t,r,{force:b,alignMoment:g},o),i=WR(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,wl,n]),l=s([0,-wl,n]),u=s([wl,0,n]),m=s([-wl,0,n]),f=s([0,0,n],YR),p=s([0,0,n],-YR),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 dP=1e3;function ff(e,t=dP){if(!Dn(e.compliance)||!Ln(e))return;let r=tt(e),n=Ie(r,0,0),o=Tl(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 ea(e,t=-af,r=af,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=Ge(e,{travelMin:t,travelMax:r,steps:n}),s=ff(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 Pl(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 rn(e,t){return{motionRatio:Pl(e.travel,e.motionRatio,t),camber:Pl(e.travel,e.camber,t),toe:Pl(e.travel,e.toe,t),damperLen:Pl(e.travel,e.damperLen,t)}}var jR=Math.PI/180,fP=9.81;function nn(e,t,r,n=0){let o=Te(e),a=e.wheelbase*(1-e.frontMassFrac),s=e.wheelbase*e.frontMassFrac,i=Xo(e,n),c=e.aero?.model?(k,v,x)=>Xo(e,n,v,k,x):()=>i,l=rn(t,0),u=rn(r,0),m=e.loadFactor,f=m!==void 0&&m!==1?(m-1)*e.massTotal*fP: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=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 F=c(k,v,x),w=o.rollGradient*k,C=w*jR,T=o.pitchGradient*v*jR,S=(V,N)=>{let z=N==="F"?e.trackFront:e.trackRear,I=N==="F"?o.rideRateFront:o.rideRateRear,_=(V==="R"?1:-1)*(z/2)*Math.tan(C),B=(N==="R"?s:-a)*Math.tan(T),O=`${N}${V}`,G=f?F[O]+(N==="F"?p:d):F[O],K=I>0?G/I:0;return{anti:_,sym:B+K}},A={FL:S("L","F"),FR:S("R","F"),RL:S("L","R"),RR:S("R","R")},P=V=>{let N=V[0];return A[V].sym*y[N]+A[V].anti*R[N]},L=Uo(e,M,o,{FL:P("FL"),FR:P("FR")}),D=w+L.rollDeg,E=(V,N)=>{let z=N==="F"?t:r,I=N==="F"?l:u,_=`${N==="F"?"F":"R"}${V}`,B=A[_].sym+A[_].anti+L.travel[_],O=P(_)+L.travel[_]*R[N],G=B-O,K=rn(z,O),Y=(V==="R"?1:-1)*K.camber;return{travel:O,tyre:G,ground:B,camber:Y,camberRoad:Y+D,toe:K.toe,bumpToe:K.toe-I.toe,damperTravel:I.damperLen-K.damperLen}};return{FL:E("L","F"),FR:E("R","F"),RL:E("L","R"),RR:E("R","R"),steeringJacking:L}}}var hf=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function En(e){return{enabled:e?.enabled===!0,roadFeedbackGain:Math.min(2,Math.max(0,hf(e?.roadFeedbackGain,1))),turnInFrictionNm:Math.max(0,hf(e?.turnInFrictionNm,0)),columnStiffnessNmPerRad:Math.max(0,hf(e?.columnStiffnessNmPerRad,0))}}function bf(e,t,r){let n=En(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 UR=()=>({totalNm:0,aligningNm:0,lateralNm:0,longitudinalNm:0,jackingNm:0});function In(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 Ps(e,t,r,n="model",o){let a=e.steerFront;if(!In(e)||!a)return null;let s=t<0?-1:1,c=a.rackRatioMmPerRev/(2*Math.PI)/1e3,l=t>=0,u=o&&a.travelSurface?Wo(a,Math.abs(t),l?o.FL:o.FR,l?o.FR:o.FL):jo(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=UR();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=UR();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=bf(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 hP=e=>"front"in e&&"rear"in e;function ta(e,t){return hP(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)),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 gf(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 XR(e,t,r){let n=gf(e,t),o=gf(e,r);return{left:n,right:o,fyRes:n.fyRes+o.fyRes}}function Rr(e,t,r){let n=XR(ta(e,"front"),t.FL,t.FR),o=XR(ta(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 Ls=[{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"}],gP=Ls.flatMap(e=>[e.min,e.max]);function yP(e){let t={};for(let r of Ls){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 Ll(e){if(e.kind==="magic")return e.range??yP(e.coeffs)}function xf(e){return Math.max(1,e.kind==="magic"?e.fnomin:e.nominalLoad)}function qR(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 zt(e){let t=QR.get(e);if(t!==void 0)return t;let r=10*xf(e.model),{turnover:n,collapse:o}=RP(e,r),a=n??o??r;return QR.set(e,a),a}var QR=new WeakMap;function RP(e,t){let r=xf(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=qR(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=qR(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 ZR=.1;function Dl(e,t=xf(e)){let r=Pe(e).muX(t);return{muX:r,none:Number.isFinite(r)&&r<ZR}}var JR=["FL","FR","RL","RR"],vP=e=>e==="FL"||e==="RL",kP=e=>e==="FL"||e==="FR"?"front":"rear";function El(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 JR)a[l]={...t[l]};let s=l=>{let u=0;for(let f of JR)kP(f)===e.axle&&(a[f].Fx=e.sense*(f===e.strong?l-e.open/2:e.open/2),u-=(vP(f)?o:-o)*a[f].Fx);let m=Rr(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 MP=[["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]],SP=[["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]],AP=[["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]],FP=[["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]],wP=[["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]],tv=[["lateral",MP],["longitudinal",SP],["aligning",AP],["combined",FP],["scaling",wP]].flatMap(([e,t])=>t.map(([r,n,o])=>({key:r,section:e,text:n,fallback:o}))),v4=new Map(tv.map(e=>[e.key,e]));var CP=/^\$\s*EDITED\s+([A-Z][A-Z0-9_]*)\s+was\s+(absent|[-+0-9.eE]+)\s*$/;function rv(e){let t={};for(let r of e.split(/\r?\n/)){let n=r.trim().match(CP);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 PP=/^\s*\$\s*UNLOADED_RADIUS_STAND_IN\s*=\s*([0-9.eE+-]+)/,LP=/^\$-+ written by (?:PaceDynamics|PaceLab)\b/m,DP=/^\$\s*AXIS_SYSTEM\s*=\s*(ISO-W|SAE)\b/m;function EP(e){let t=e.match(DP);return t?{axisSystem:t[1]==="SAE"?"sae":"iso",trustSide:!0}:LP.test(e)?{axisSystem:"sae",trustSide:!1}:{axisSystem:"iso",trustSide:!0}}function IP(e){return e>=62?"6.2":e>=61?"6.1":"5.2"}var nv=new Map([["pa",1],["pascal",1],["kpa",1e3],["kilopascal",1e3],["mpa",1e6],["megapascal",1e6],["bar",1e5],["psi",6894.757293168]]);function _P(e,t,r){let n=r.PRESSURE?.trim().toLowerCase(),o=n===void 0?1:nv.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 NP=new Map([["radians",1],["radian",1],["rad",1],["degrees",Math.PI/180],["degree",Math.PI/180],["deg",Math.PI/180]]);function OP(e,t){let r=(s,i)=>s===void 0?1:i.get(s.trim().toLowerCase()),n=r(t.ANGLE,NP),o={fz:1,kappa:1,alpha:n,gamma:n,p:r(t.PRESSURE,nv)},a={};for(let s of Ls){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 Ds(e,t="imported",r={}){let n=EP(e),o=r.axisSystem??n.axisSystem,a={},s={},i={},c="",l;for(let g of e.split(/\r?\n/)){let y=g.match(PP);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=IP(a.FITTYP??62),m=rv(e),f=m?Object.fromEntries(Object.entries(m).filter(([g])=>a[g]!==void 0)):void 0,p=a.VERTICAL_STIFFNESS??a.KZ??0,d=_P(a,s,i),h=OP(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 tr(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}var T4=Math.PI/180;var I4=Math.PI/180,_4=180/Math.PI;function Es(){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 sv=`$ AXIS_SYSTEM = SAE (authored in the evaluation frame: y right)
|
|
2
|
+
import{parentPort as eT,workerData as KB}from"node:worker_threads";import{readFileSync as Ry}from"node:fs";import{join as vy}from"node:path";var Hc=e=>e.format!=="points"&&!e.field;var ft=e=>e?.kind==="ice";var qy={packVoltageMax:600,segmentVoltageMax:120,powerLimitKw:80};var Ee=e=>typeof e=="number"&&Number.isFinite(e);function rT(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 nT(e){return!e||typeof e!="object"?"The cell has no curve.":e.kind==="table"?rT(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 zc(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=nT(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 Ln(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 $e(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 Yc(e,t,r,n,o){let a=e.length,s=t.length;if(a===0||s===0)return 0;let i=Ln(e,n),c=Ln(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 Io=[0,.05,.1,.2,.3,.4,.5,.6,.7,.8,.9,1],jp={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]},Qy=[0,.05,.1,.2,.5,.8,1],Zy=[2.2,1.55,1.3,1.12,1,.97,.98];function Jy(e){return $e(Qy,Zy,e)}var ex=[-20,-10,0,10,25,40,60],tx=[4,2.8,2,1.4,1,.82,.75];function Up(e){return $e(ex,tx,e)}var rx=.5;function Xp(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=jp[t]??jp.other,l=e.socAtNom??rx,u=Io.includes(l)?[...Io]:[...Io,l].sort((h,b)=>h-b),m=$e(Io,c,l),f=m>0&&m<1?Math.log(i)/Math.log(m):1,p=[],d=[];for(let h of u){let b=$e(Io,c,h);p.push(o+s*Math.pow(b,f)),d.push(e.constantResistance?a:a*Jy(h))}return{kind:"table",soc:u,ocv:p,r0:d}}function qp(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+=($e(t,r,s)+$e(t,r,i))/2*(i-s)}return o}var _o=25,nx=new WeakMap;function xr(e){let t=nx.get(e);if(t)return t;let r=zc(e);if(r)throw new Error(r);let{cell:n,pack:o}=e,a=n.curve.kind==="table"?n.curve:Xp(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*$e(a.soc,a.ocv,F),g=(F,w=_o)=>{let C=l&&u?Yc(a.soc,l,u,F,w):$e(a.soc,a.r0,F)*Up(w);return c*C+o.busResistance},y=(F,w,C)=>b(F)-w*g(F,C),R=(F,w,C)=>{if(!(F>0))return 0;let T=b(w),S=g(w,C);if(!(S>0))return F/T;let A=T*T-4*S*F;return A<0?NaN:2*F/(T+Math.sqrt(A))},k=(F,w,C)=>{if(!(F>0))return 0;let T=b(w),S=g(w,C);return S>0?2*F/(T+Math.sqrt(T*T+4*S*F)):F/T},v=F=>{let w=e.thermal;if(!w||w.derateFromC===void 0)return 1;let C=w.derateToC??w.derateFromC;return F<=w.derateFromC?1:!(C>w.derateFromC)||F>=C?0:1-(F-w.derateFromC)/(C-w.derateFromC)},x=(F,w,C=0)=>{let T=b(F),S=g(F,w),A=S>0?T/(2*S):1/0,P=G=>{if(!(S>0))return G*T;let K=Math.min(G,A);return K*(T-K*S)},L=S>0?Math.max(0,(T-f)/S):1/0,D=C>0&&Number.isFinite(C)?C:1/0,E=S>0?P(L):1/0,V=Number.isFinite(p)?P(p):1/0,N=S>0?T*T/(4*S):1/0,z=[["rules",D],["voltage-floor",E],["current",V],["matched-load",N]],I=z[0][0],_=z[0][1];for(let[G,K]of z)K<_&&(_=K,I=G);let B=v(w??_o);B<1&&(_=Number.isFinite(_)?_*B:_,I="temperature");let O=Number.isFinite(_)?R(_,F,w):1/0;return{watts:_,binding:I,rules:D,voltageFloor:E,current:V,matchedLoad:N,derate:B,amps:O,volts:Number.isFinite(O)?T-O*S:T}},M={model:e,table:a,capacityAh:m,chargeC:m*3600,energyKwh:m*(s*qp(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 nx.set(e,M),M}function Qp(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 ox={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},ax={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 Zp(){return{name:"Formula Student accumulator",cell:Qp(ox),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 Jp(){return{name:"LFP pack",cell:Qp(ax),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 ed(){return{name:"Road car pack",cell:Qp(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 td(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 Wc(e){if(e.kind==="ice"){let n=e.gearbox.efficiency;return{model:e,maxTorque:o=>o>e.limitRpm?0:$e(e.rpm,e.torque,o),efficiency:()=>n}}let t=n=>$e(e.rpm,e.torque,n),r=e.kind==="simple"?()=>e.efficiency:(n,o)=>Yc(e.effRpm,e.effTorque,e.effGrid,n,o);return{model:e,maxTorque:t,efficiency:r}}function rd(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 Xe(e,t){return t==="rear"&&e.tireRateRear!==void 0?e.tireRateRear:e.tireRate}function nd(e,t){let r=e.tyreFreeRadiusRear;return(t==="rear"&&r!==void 0?r:e.tyreFreeRadius)??0}var jc=9.81,ix=(e,t)=>e*(t*t)/2*(Math.PI/180)/1e3,ns=(e,t)=>e+t>0?e*t/(e+t):0,cx=.5;function Uc(e,t,r){if(!(r>0))return 1;let n=e*jc*t*(Math.PI/180)/r;return 1/(1-Math.min(cx,n))}function od(e,t,r){return r>0?e*jc*t/(r*r):0}function lx(e,t,r,n,o){if(!(n>0)||!(o>0))return 1;let a=od(e,t,r)*(1/n+1/o);return 1/(1-Math.min(cx,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=ns(i,a),u=ns(c,s),m=(V,N)=>{let z=N/2;return z>0?1/(2*Math.PI)*Math.sqrt(V*1e3/z):0},f=m(l,n),p=m(u,o),d=ns(e.wheelRateFront+e.arbFront,a),h=ns(e.wheelRateRear+e.arbRear,s),b=ix(d,e.trackFront),g=ix(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*jc*v,M=Uc(r,v,y),F=y>0?x/y*M:0,w=e.massTotal*jc*e.cgHeight/e.wheelbase,C=2*l,T=2*u,S=lx(r,e.cgHeight,e.wheelbase,C,T),P=(C>0&&T>0?(w/C+w/T)/e.wheelbase*S:0)*(180/Math.PI),L=e.wheelbase*e.wheelbase*ns(C,T)*(Math.PI/180)/1e3,D=e.damperFront??2.5,E=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:P,pitchRate:L,cgRollGain:M,cgPitchGain:S,rideDampingFront:D+(e.heaveDamperFront??0),rideDampingRear:E+(e.heaveDamperRear??0),rollDampingFront:D+(e.rollDamperFront??0),rollDampingRear:E+(e.rollDamperRear??0)}}var qr=["clFront","clRear","cd"],Qr=e=>e.frame?.kind==="pitch";function No(e){return Qr(e)?{x:e.axes.h,y:e.axes.pitch}:{x:e.axes.hFront,y:e.axes.hRear}}var Xc=e=>e.frame?.kind==="pitch",ux=e=>e.kind==="map";var qc=45,Qe=e=>typeof e=="number"&&Number.isFinite(e);function Qc(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(Qe))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 mx(e,t){if(t===void 0)return null;for(let r of qr){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(Qe)||!n.factor.every(Qe))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:!Qe(t.dCl)||!Qe(t.dBalance)||!Qe(t.dCd)?`The ${e} slopes must be numbers.`:!Qe(t.maxDeg)||!(t.maxDeg>0)?`The ${e} response needs a positive angle to be valid to.`:null}function os(e){if(!e||typeof e!="object")return"Not an aero model.";if(!Qe(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=Qc("front ride-height",e.axes?.hFront);if(i)return i;let c=Qc("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(!Qe(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=Qc("ride-height",e.axes?.h);if(i)return i;let c=Qc("pitch",e.axes?.pitch,"\xB0","pitch");if(c)return c;let l=e.axes.pitch.find(u=>Math.abs(u)>=qc);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 qr){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(Qe))return`${i} contains a value that is not a number.`}}return mx("yaw",e.attitude?.yaw)??mx("roll",e.attitude?.roll)}if(e.kind==="sensitivity"){let t;if(e.frame==null)t=["hFront","hRear"];else if(e.frame?.kind==="pitch"){if(!Qe(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||!Qe(r[t[0]])||!Qe(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 qr){if(!e.at||!Qe(e.at[s]))return`${s} at the reference must be a number.`;let i=n?.[s];if(!i||!Qe(i[t[0]])||!Qe(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||!Qe(i[0])||!Qe(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])>=qc||Math.abs(i[1])>=qc))return`A pitch range reaching ${Math.abs(i[0])>=qc?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 dx=180/Math.PI;function Oo(e,t,r,n){let o=(n-r)/t;return{h:r+e.refX*o,pitch:Math.atan(o)*dx}}function Vo(e,t,r,n){let o=Math.tan(n/dx);return{hFront:r-e.refX*o,hRear:r+(t-e.refX)*o}}var C$=180/Math.PI,oT=["hFront","hRear"],aT=["h","pitch"],id=e=>e?.kind==="pitch"?aT:oT,Mt=(e,t)=>e[t],Zc=(e,t)=>e[t],ad=(e,t)=>({[e[0]]:t(e[0]),[e[1]]:t(e[1])});function sT(e){if(!(!e.yaw&&!e.roll))return{...e.yaw?{yaw:{...e.yaw}}:{},...e.roll?{roll:{...e.roll}}:{}}}function cd(e){let t=id(e.frame),r=e.balanceFront,n=e.cl*r,o=e.cl*(1-r),a=ad(t,c=>Mt(e.dCl,c)*r+e.cl*Mt(e.dBalance,c)),s=ad(t,c=>Mt(e.dCl,c)*(1-r)-e.cl*Mt(e.dBalance,c)),i=sT(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:ad(t,c=>Mt(e.dCd,c))},range:{[t[0]]:[...Zc(e.range,t[0])],[t[1]]:[...Zc(e.range,t[1])]},provenance:{...e.provenance},...i?{attitude:i}:{}}}function Jc(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 sd(e,t,r=11){let n=Array.from({length:r},(a,s)=>t.maxDeg*s/(r-1)),o=n.map(a=>Jc(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 fx(e){if(!(!e.attitude?.yaw&&!e.attitude?.roll))return{...e.attitude.yaw?{yaw:sd(e.at,e.attitude.yaw)}:{},...e.attitude.roll?{roll:sd(e.at,e.attitude.roll)}:{}}}function hx(e,t,r,n=0,o=0){let[a,s]=id(e.frame),i=t-Mt(e.ref,a),c=r-Mt(e.ref,s),l={clFront:e.at.clFront+Mt(e.slope.clFront,a)*i+Mt(e.slope.clFront,s)*c,clRear:e.at.clRear+Mt(e.slope.clRear,a)*i+Mt(e.slope.clRear,s)*c,cd:e.at.cd+Mt(e.slope.cd,a)*i+Mt(e.slope.cd,s)*c},u=e.attitude?.yaw?Jc(e.at,e.attitude.yaw,n):{clFront:1,clRear:1,cd:1},m=e.attitude?.roll?Jc(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 ld(e){let[t,r]=id(e.frame),n=[...Zc(e.range,t)],o=[...Zc(e.range,r)],a=i=>o.map(c=>n.map(l=>i(hx(e,l,c)))),s=fx(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 ud=180/Math.PI,bx=new WeakMap,gx=new WeakMap,md=new WeakMap;function Zr(e,t){let r=gx.get(e);if(r)return r;let n=t?.wheelbase,o=n!==void 0?md.get(e)?.get(n):void 0;if(o)return o;let a=iT(e),s=a.map;if(!Qr(s)){let l=cT(e,a);return gx.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=lT(e,a,s.frame,n),c=md.get(e);return c||(c=new Map,md.set(e,c)),c.set(n,i),i}function iT(e){let t=bx.get(e);if(t)return t;let r=os(e);if(r)throw new Error(r);let n=e.kind==="map"?e:ld(e),{x:o,y:a}=No(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:$e(y.clFront.deg,y.clFront.factor,k),clRear:$e(y.clRear.deg,y.clRear.factor,k),cd:$e(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=Ln(o,y),M=Ln(a,R),F=Math.min(x.i+1,s-1),w=Math.min(M.i+1,i-1),C=S=>{let A=S[M.i][x.i],P=S[M.i][F],L=S[w][x.i],D=S[w][F],E=A+x.t*(P-A),V=L+x.t*(D-L);return E+M.t*(V-E)},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),F=Ln(o,k?Math.min(Math.max(y,h.x[0]),h.x[1]):y),w=Ln(a,k?Math.min(Math.max(R,h.y[0]),h.y[1]):R),C=Math.min(F.i+1,s-1),T=Math.min(w.i+1,i-1),S=C>F.i?o[C]-o[F.i]:0,A=T>w.i?a[T]-a[w.i]:0,P={};for(let L of qr){let D=n[L],E=D[w.i][F.i],V=D[w.i][C],N=D[T][F.i],z=D[T][C],I=F.clamped||S===0?0:((V-E)*(1-w.t)+(z-N)*w.t)/S,_=w.clamped||A===0?0:((N-E)*(1-F.t)+(z-V)*F.t)/A;P[L]=u?{x:I*M[L],y:_*M[L]}:{x:I,y:_}}return P},g={map:n,x:h.x,y:h.y,hasAttitude:u,factors:p,at:d,slopes:b};return bx.set(e,g),g}function cT(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 qr)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 lT(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)*ud,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)*ud,m,f,p),b=ud/(n*(1+d*d)),g={};for(let y of qr)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)=>Vo(r,n,l,u),fromAxles:(l,u)=>{let m=Oo(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 pd(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,yx={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."},xx={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."},Rx={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."},vx={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."},kx={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."},Mx={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."},Sx={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."},Ax={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 Rr(e){return cd({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 dd=()=>Rr(yx),fd=()=>Rr(xx),hd=()=>Rr(Rx),bd=()=>Rr(vx),gd=()=>Rr(kx),yd=()=>Rr(Mx),xd=()=>Rr(Sx),Rd=()=>Rr(Ax);function Dn(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 el(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 tl(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 vd(e,t){return e.wheelbase>0?e.massTotal*t*9.81/e.wheelbase:0}function Bo(e,t,r){let n=2*t.rideRateFront,o=2*t.rideRateRear;return!(n>0)||!(o>0)?0:Math.min(od(t.sprungMass,r,e.wheelbase),.5*n*o/(n+o))}function as(e,t,r,n,o){let a=e.cgHeight,s=vd(e,r);if(n===0&&o===0&&s===0)return{height:a,forward:0,noseLoad:0,dropFront:0,dropRear:0};let i=el(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=Bo(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=tl(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 kd={yawDeg:0,rollDeg:0},Fx=1e-4,uT=40,wx=50;function Jr(e,t,r=0){let n=e.aero?.model;if(!(!n||!Zr(n,e).hasAttitude))return{yawDeg:r,rollDeg:we(e).rollGradient*t}}function $o(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 Vo(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=Xc(r)?n(r.frame,r.ref.h,r.ref.pitch):r.ref;else if(r){let{x:a,y:s}=No(r),i=(a[0]+a[a.length-1])/2,c=(s[0]+s[s.length-1])/2;o=Qr(r)?n(r.frame,i,c):{hFront:i,hRear:c}}return{hFront:e.rideHeightFront??o.hFront,hRear:e.rideHeightRear??o.hRear}}var Cx=new WeakMap;function vr(e,t,r=0,n){let o=e.aero;if(!o?.model)return null;let a=Cx.get(e);a||(a=new Map,Cx.set(e,a));let s=n&&Zr(o.model,e).hasAttitude?n:kd,i=s===kd?`${t}|${r}`:`${t}|${r}|${s.yawDeg.toFixed(3)}|${s.rollDeg.toFixed(3)}`,c=a.get(i);if(c)return c;let l=mT(e,o,t,r,s);return a.size>4096&&a.clear(),a.set(i,l),l}function mT(e,t,r,n,o){let a=Zr(t.model,e),s=we(e),i=2*s.rideRateFront,c=2*s.rideRateRear,l=$o(t,e.wheelbase),u=.5*t.rho*r*r,m=a.area,f=e.wheelbase>0?t.copHeight/e.wheelbase:0,p=el(e,s),d=vd(e,n),h=(C,T)=>tl(e.cgHeight,p,l.hFront-C,l.hRear-T),b=(C,T)=>l.hFront-C-(l.hRear-T),g=(C,T)=>{let S=a.at(C,T,o.yawDeg,o.rollDeg),A=u*m*S.clFront,P=u*m*S.clRear,L=u*m*S.cd,D=L*f,E=h(C,T),V=d*E,N=Bo(e,s,E)*b(C,T),z=A-V-D+N,I=P+V+D-N,_=C-l.hFront+(i>0?z/i:0),B=T-l.hRear+(c>0?I/c:0);return{c:S,downFront:A,downRear:P,drag:L,rF:_,rR:B,norm:Math.hypot(_,B)}},y=(C,T,S=!1)=>{let A=a.slopes(C,T,S,o.yawDeg,o.rollDeg),P=i>0?u*m/i:0,L=c>0?u*m/c:0;return[[P*(A.clFront.hFront-f*A.cd.hFront),P*(A.clFront.hRear-f*A.cd.hRear)],[L*(A.clRear.hFront+f*A.cd.hFront),L*(A.clRear.hRear+f*A.cd.hRear)]]},R=l.hFront,k=l.hRear,v=g(R,k),x=0;for(;v.norm>=Fx&&x<uT;){x++;let C=y(R,k),T=i>0?d/i:0,S=c>0?d/c:0,A=Bo(e,s,h(R,k)),P=i>0?A/i:0,L=c>0?A/c:0,D=1+C[0][0]-T*p.front-P,E=C[0][1]-T*p.rear+P,V=C[1][0]+S*p.front+L,N=1+C[1][1]+S*p.rear-L,z=D*N-E*V,I,_;Math.abs(z)>1e-9?(I=-(N*v.rF-E*v.rR)/z,_=-(-V*v.rF+D*v.rR)/z):(I=-.5*v.rF,_=-.5*v.rR);let B=Math.max(1,Math.abs(I)/wx,Math.abs(_)/wx);I/=B,_/=B;let O=1;for(let G=0;G<6;G++){let K=g(R+O*I,k+O*_);if(K.norm<=v.norm||G===5){R+=O*I,k+=O*_,v=K;break}O*=.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:Bo(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:pT(M),stable:w>0&&F>0,converged:v.norm<Fx,iterations:x,clampedRide:v.c.clampedRide,yawDeg:o.yawDeg,rollDeg:o.rollDeg,clampedAttitude:v.c.clampedAttitude}}function pT(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 ss(e,t,r=0,n){let o=vr(e,t,r,n);return o?{downforce:o.downforce,drag:o.drag,downFront:o.downFront,downRear:o.downRear}:e.aero?Dn(e.aero,t):{downforce:0,drag:0,downFront:0,downRear:0}}function dT(e,t,r,n){let o=Dn(t,r),a=we(e),s=$o(t,e.wheelbase),i=e.wheelbase>0?o.drag*t.copHeight/e.wheelbase:0,c=as(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 Md(e,t,r=0,n){let o=vr(e,t,r,n);return o||(e.aero?dT(e,e.aero,t,r):null)}function rl(e,t=0,r=0,n,o){if(e.aero&&t>0){if(e.aero.model){let i=vr(e,t,r,n);return{height:i.cgHeight,forward:i.cgForward,noseLoad:i.cgNoseLoad}}let a=Dn(e.aero,t),s=e.wheelbase>0?a.drag*e.aero.copHeight/e.wheelbase:0;return as(e,o??we(e),r,a.downFront-s,a.downRear+s)}return r===0?{height:e.cgHeight,forward:0,noseLoad:0}:as(e,o??we(e),r,0,0)}var Tx=[0,1,0],Sd=[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],Ad=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]],fT=e=>X(e,e),en=e=>Math.sqrt(X(e,e)),is=(e,t)=>fT(H(e,t)),ve=(e,t)=>en(H(e,t)),q=e=>{let t=en(e);return t<1e-12?[0,0,0]:[e[0]/t,e[1]/t,e[2]/t]};var tn=(e,t,r)=>{let n=q(r),o=H(e,t);return ee(t,U(n,X(o,n)))},Px=(e,t,r)=>ve(e,tn(e,t,r));var bT=1e-6;function gT(e){if(e<bT){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 ot(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]=gT(r),a=ae(e,t),s=ae(e,a);return ee(t,ee(U(a,n),U(s,o)))}function It(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 ot(U(o,r),e)}function Jt(e,t){let r=t.length,n=e.map(a=>a.slice()),o=t.slice();return Dx(n,o,r,new Array(r).fill(0))}function Lx(e,t,r){return Dx(e,t,t.length,r)}function Dx(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 Ex=e=>{let t=0;for(let r of e)t=Math.max(t,Math.abs(r));return t},Ix=e=>{let t=0;for(let r of e)t+=r*r;return t},yT=Math.sqrt(Number.EPSILON);function _x(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=Ex(c),u=Ix(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 C=0;C<a;C++){let T=yT*Math.max(Math.abs(i[C]),s[C]);for(let A=0;A<a;A++)k[A]=i[A];k[C]+=T;let S=e(k);for(let A=0;A<p;A++)d[A][C]=(S[A]-c[A])/T}let M=0;for(let C=0;C<a;C++){for(let S=0;S<a;S++){let A=0;for(let P=0;P<p;P++)A+=d[P][C]*d[P][S];h[C][S]=A}let T=0;for(let S=0;S<p;S++)T+=d[S][C]*c[S];g[C]=T,M=Math.max(M,h[C][C])}let F=Math.max(M,1e-9),w=!1;for(let C=0;C<18;C++){let T=m*F;for(let A=0;A<a;A++){let P=h[A],L=b[A];for(let D=0;D<a;D++)L[D]=A===D?P[D]+T:P[D];y[A]=-g[A]}let S=Lx(b,y,R);if(f=Math.max(f,S.condProxy),!S.singular){for(let L=0;L<a;L++)v[L]=i[L]+R[L];let A=e(v),P=Ix(A);if(P<u){for(let L=0;L<a;L++)i[L]=v[L];c=A,u=P,l=Ex(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 cs(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 Fd(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 Nx=e=>[e[0],-e[1],-e[2],-e[3]];function Ox(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 Vx(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 Bx(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 wd(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 $x(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 Gx(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 xT(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 RT(e){let t=e.hardpoints,r=q(H(t.damperChassis,t.pushrodOuter)),[n,o]=xT(r);return{top:t.damperChassis,lower0:t.pushrodOuter,axis0:r,e1:n,e2:o}}function Cd(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=is(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:RT(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(ot(n,a),e.c0),o)}function Td(e,t){return ee(e.lcaFront,It(e.lbjRel0,e.lcaDir,t))}function Go(e,t){return e.steerMovesRack?ee(e.tieInner0,U(e.rackAxis,t)):e.tieInner0}function Pd(e,t,r,n){let o=_t(e,t,e.lbj0),a=Td(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,ot(h,d.e1)),u=X(b,ot(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=Go(e,n),p=(is(m,f)-e.tieLen2)/e.tieLenRef;return[s,i,c,l,u,p]}var ls=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]),nl=e=>{let t=ls(e);return[e[0]/t,e[1]/t,e[2]/t]},vT=(e,t)=>H(e,U(t,X(e,t))),Ld=e=>nl(ae(e,Math.abs(e[0])<.6?[1,0,0]:[0,1,0]));function kT(e,t){let r=e.ucaDir,n=ee(e.ucaFront,U(r,e.ubjAxial0)),o=Math.sqrt(e.ubjRadius2),a=vT(H(e.ubj0,e.ucaFront),r),s=ls(a)>1e-9?nl(a):Ld(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=cs(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=nl(c),d=(h,b)=>{let g=ee(n,ee(U(s,o*h),U(i,o*b))),y=nl(H(g,t));return{q1:Vx(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 MT(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=ls(a),i=s>1e-9?U(a,1/s):Ld(n),c=H(t.top,r),l=ls(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=Ld(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:Fd(wd(R,y,ae(R,y)),Nx(wd(i,n,ae(i,n)))),k:u,margin:f,ok:f>=0}};return f>0?[h(1),h(-1)]:[h(1)]}function ST(e,t,r,n){let{k:o}=n,a=Ox(n.q1,H(e.tro0,e.lbj0)),s=X(a,o),i=H(a,U(o,s)),c=ls(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=cs(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:Fd(Bx(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 Kx(e,t,r,n=[0,0,0,0,0,0]){let o=Td(e,t),a=Go(e,r),s=$x([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?MT(e,e.strut,o):kT(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=ST(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=Gx(m),d=H(H(o,e.c0),ot(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 zx(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:is(e.pushrodOuter,e.rockerToPushrod),damperLen0:ve(e.rockerToDamper,e.damperChassis)}}var AT=(e,t)=>ee(e.pivotA,It(e.rprRel0,e.axis,t)),Dd=(e,t)=>ee(e.pivotA,It(e.rdmRel0,e.axis,t));function us(e,t){return{pushrod:AT(e,t),damper:Dd(e,t)}}function Yx(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=cs(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(Dd(e,r),e.damperChassis),converged:p,margin:0}}let u=Hx(Math.atan2(l.s1,l.c1),r),m=Hx(Math.atan2(l.s2,l.c2),r),f=Math.abs(m-r)<Math.abs(u-r)?m:u;return{phi:f,damperLength:ve(Dd(e,f),e.damperChassis),converged:l.ok,margin:l.margin}}function Hx(e,t){let r=2*Math.PI;return e+r*Math.round((t-e)/r)}function Wx(e,t,r,n){return ee(t,ot(U(q(r),n),H(e,t)))}function jx(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 Ux(e,t,r,n){return ee(t,ot(U(q(r),n),H(e,t)))}var ol=180/Math.PI,FT=(e,t,r)=>Math.max(t,Math.min(r,e)),Xx=[NaN,NaN,NaN];function ms(e){let t=q(e.spinAxis),r=q(H(e.uprightUpper,e.uprightLower)),n=-Math.asin(FT(t[2],-1,1))*ol,o=Math.atan2(t[0],t[1])*ol,a=Math.atan2(-r[0],r[2])*ol,s=Math.atan2(-r[1],r[2])*ol,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]):Xx,d=m?f(e.wheelCenter[2]):Xx,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=Px(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 tt(e){return{corner:e,inv:Cd(e),rocker:zx(e.hardpoints)}}var wT=[20,20,20,.2,.2,.2];function Qx(e,t,r,n=[0,0,0,0,0,0]){let o=Kx(e,t,r,n);if(!o.free)return o;let a=CT(e,t,r,n);return{x:a.x,converged:a.converged,margin:0}}function CT(e,t,r,n=[0,0,0,0,0,0]){return _x(o=>Pd(e,o,t,r),n,{scales:wT,tol:1e-10,maxIter:40})}var TT=.01,al=1.2,ht=e=>e.ok?e.state:null,at=e=>e.ok?e.state:e.nearest;function ye(e,t,r,n,o){let a=0,s=Ie(e,a,r,n,o);if(Math.abs(s.travel-t)<1e-4)return qx(s,t,!1);let c=(Ie(e,.02,r,Ed(s),o).travel-s.travel)/.02;(!Number.isFinite(c)||Math.abs(c)<1e-6)&&(c=1);let l=f=>Math.max(-al,Math.min(al,f)),u=l((t-s.travel)/c),m=Ie(e,u,r,Ed(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,Ed(s),o)}return qx(m,t,Math.abs(u)===al)}function qx(e,t,r){let n=e.travel-t,o=Math.abs(n)<=TT,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 Ed(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 PT(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=jx(t.ubj0,a,t.ucaFront,t.ucaDir);return Ux(o.pushrodOuter,t.ucaFront,t.ucaDir,s)}default:return Wx(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=Qx(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(ot(u,p.spinAxis)),k=PT(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}:Yx(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 Ko=e=>e==="FL"||e==="FR"?"front":"rear",Jx=e=>e==="FL"||e==="RL"?"left":"right";function Ge(e,t){return e.corners?.[t]??LT(e[Ko(t)],Jx(t))}function eR(e){let t=e.config.springSplit;return e.config.actuation==="decoupled"||t===void 0||!Number.isFinite(t)||Math.abs(t)>=1?0:t}var Zx=new WeakMap;function LT(e,t){let r=eR(e);if(r===0)return e;let n=Zx.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)},Zx.set(e,n)}return n[t]}var er=["FL","FR","RL","RR"],bt=e=>2*e.hardpoints.wheelCenter[1],Nt=(e,t)=>t?bt(Ge(e,"FL"))/2+bt(Ge(e,"FR"))/2:bt(Ge(e,"RL"))/2+bt(Ge(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 Ot(e,t){return[t.axleX+e[0],t.sideSign*e[1],e[2]]}function rn(e,t){return[e[0],t.sideSign*e[1],e[2]]}function nn(e){return e.frontAxleX-e.wheelbase/2}function Id(e,t,r){return t[2]+e.heave+(t[0]-r)*Math.sin(e.pitch)-t[1]*Math.sin(e.roll)}function on(e,t,r,n){let o=Ze(e,t),a=(n?Nt(n,o.isFront):o.isFront?t.trackFront:t.trackRear)/2,s=o.sideSign*a,i=o.axleX-nn(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 DT={travelMin:-40,travelMax:40,steps:41,steer:0};function ps(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={...DT,...t},n=tt(e);return Ho(n,r)}function Ho(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:ps(m),converged:m.converged});let f=ps(m);for(let R=1;R<=l;R++){let k=c*R/l,v=Ie(e,k,r,f);f=ps(v),u.push({beta:k,travel:v.travel,warm:f,converged:v.converged})}f=ps(m);for(let R=1;R<=l;R++){let k=-c*R/l,v=Ie(e,k,r,f);f=ps(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=ET(u,k,p),x=IT(u,v);y.push(Ie(e,v,r,x))}return _T(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 ET(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 IT(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 _d(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 _T(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=_d(n,r,s),c=_d(o,r,s),l=-_d(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 sl=e=>e!==void 0&&Number.isFinite(e)&&e>0;function NT(e){return e&&sl(e.helperRate)&&sl(e.helperTravel)?{rate:e.helperRate,travel:e.helperTravel}:null}function Nd(e,t,r){let n=t/e;return r?n+Math.min(t/r.rate,r.travel):n}function ds(e,t,r,n){if(!(e>0)||!Number.isFinite(e)||!(t>0)||!Number.isFinite(t))return null;let o=NT(n),a=-Nd(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=sl(t?.extended)&&t.extended>e?t.extended:null,n=r!==null&&sl(t?.stroke)?r-t.stroke:null;return{droop:r!==null?e-r:null,bump:n!==null&&n<e?e-n:null}}function Od(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 OT(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=Nd(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 VT(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=Nd(r,n,o)+t;return a<=0?0:a>=o.rate*o.travel/r+o.travel?r:r*o.rate/(r+o.rate)}function Yo(e,t){let r=OT(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 Vd(e,t){let r=VT(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 Bd(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 il={min:-60,max:60,steps:61},$d=e=>({travel:[e.min,e.max],force:[0,0],motionRatio:[0,0],spring:null}),tR=new WeakMap;function BT(e,t){let r=tR.get(e.corner);r||tR.set(e.corner,r=new Map);let n=`${t.min}|${t.max}|${t.steps}`,o=r.get(n);return o||r.set(n,o=Ho(e,{travelMin:t.min,travelMax:t.max,steps:t.steps,steer:0})),o}function hs(e,t,r=il,n=e.corner.config.coilover){let o=e.corner.config;if(o.actuation==="decoupled")return $d(r);let a=BT(e,r),s=GT(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 $d(r);let c=HT(i,0);if(!(Math.abs(c.mr)>1e-6))return $d(r);let l=t/c.mr,u=ds(s,l,c.L,n),m=u?$T(i,Bd(u).map(h=>c.L-h)):i,f=m.map(h=>(u?Yo(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?Bd(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 Gd(e,t){if(!e.spring)return null;let r=e.travel.length,n=e.length;if(n&&n.length===r&&r>=2){let s=tr(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 $T(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 GT(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:KT(e,n,r);return!(o>0)||!Number.isFinite(o)?t:t*o/(t+o)}function KT(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=us(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=tr(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 kr(e,t,r){if(!e.spring)return Yt(e,t);let{rate:n,preload:o,length0:a,law:s}=e.spring,i=fs(e,0),c=a-r;return(s?Yo(s,c):o+n*c)*fs(e,t)-o*i}function HT(e,t){let r=tr(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 tr(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 Yt(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.force[0];let n=tr(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 Wo(e,t){let r=e.travel.length;if(r<3)return bs(e,t);let n=tr(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 bs(e,t){if(e.travel.length<2)return 0;let n=tr(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(ot(r.pose.omega,o),n.wheelCenter),r.pose.t)}case"lowerArm":{let o=q(H(n.lcaRear,n.lcaFront));return ee(n.lcaFront,ot(U(o,r.beta),H(t.outer,n.lcaFront)))}case"rocker":{let o=q(H(n.rockerPivotB,n.rockerPivotA));return ee(n.rockerPivotA,It(H(t.outer,n.rockerPivotA),o,r.points.rockerAngle))}}}function an(e,t,r){return e.config.actuation==="decoupled"&&t.attach==="rocker"&&r==="coil"}function Kd(e,t,r){return an(e,t,r)?[t.inner[0],-t.inner[1],t.inner[2]]:t.inner}function jo(e,t,r){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return Hd(e,t,r.kind,Ke(e,{travelMin:n,travelMax:o,steps:a}).samples)}function Hd(e,t,r,n){let o=q(H(t.outer,Kd(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 zd(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 Yd(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 gs=e=>e.mount??{kind:"rockerToRocker"},aR=e=>[e[0],0,e[2]],zT=e=>2*Math.abs(e[1]),YT=(e,t)=>Math.hypot(e[0]-t[0],e[2]-t[2]);function ll(e,t){return t.kind==="chassis"?YT(e,t.anchor):zT(e)}function ys(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 En(e,t,r={}){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return Wd(e,t,Ke(e,{travelMin:n,travelMax:o,steps:a}).samples)}function Wd(e,t,r){let n=gs(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(ll(o(d),n));let c=nR(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=ys(o(m),o(f),n);return{travel:a,ratio:u,springTravel:s,atDesign:nR(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 nR(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 jd(e,t,r){let n={outer:t.outer,attach:t.attach},o=Ke(e,{travelMin:-5,travelMax:5,steps:3}),a=d=>aR(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 Ud(e,t){let r=e.hardpoints,n=r.rockerPivotA,o=oR(cl(r.rockerPivotB,r.rockerPivotA)),a=Math.max(30,.6*sR(cl(r.rockerToDamper,n))),s=cl(r.rockerToDamper,n),i=oR(cl(s,WT(o,jT(s,o)))),c=UT(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:jd(e,d)}}:d,b;try{b=En(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 cl=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],WT=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],jT=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],sR=e=>Math.hypot(e[0],e[1],e[2]),oR=e=>{let t=sR(e)||1;return[e[0]/t,e[1]/t,e[2]/t]},UT=(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 Xd=.001,XT=e=>({outer:e.outer,inner:e.outer,attach:e.attach}),fR=(e,t,r)=>(ll(e.at0,t)-ll(r,t))/2,qT=(e,t)=>X(H(t,e.pickup.at0),e.axis);function qd(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 iR(e,t){let r=[0,1,2].map(n=>qd(e,t.map(o=>o[n])));return t.map((n,o)=>[r[0][o],r[1][o],r[2][o]])}function Qd(e){return{travel:e,heave:e.map(t=>t/2),heaveRatio:e.map(()=>.5),roll:[...e],rollRatio:e.map(()=>1)}}function cR(e,t,r,n){let o=e.corner;if(!t.heave&&!t.roll)return{side:Qd([n.min,n.max]),pickups:{}};let a=at(ye(e,0,0)),s={};if(t.heave&&r){let h=XT(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,Kd(o,h,t.rollKind??"coil")))}}let i=t.roll&&an(o,t.roll,t.rollKind??"coil")?{near:t.roll,far:{...t.roll,outer:t.roll.inner}}:null,c=Ho(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?fR(s.heave,r,De(o,s.heave.link,h)):h.travel/2),m.push(s.roll?qT(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:Qd([n.min,n.max]),pickups:{}};let d={travel:l,heave:u,heaveRatio:qd(l,u),roll:m,rollRatio:qd(l,m)};return i&&(d.eyes={near:f,nearRatio:iR(l,f),far:p,farRatio:iR(l,p)}),{side:d,pickups:s}}function ul(e,t,r){let n=tr(e,r);return t[n]+(r-e[n])/(e[n+1]-e[n])*(t[n+1]-t[n])}function lR(e,t,r){let n=tr(e,r);return(t[n+1]-t[n])/(e[n+1]-e[n])}function _e(e,t){return{h:ul(e.travel,e.heave,t),dh:ul(e.travel,e.heaveRatio,t),ddh:lR(e.travel,e.heaveRatio,t),r:ul(e.travel,e.roll,t),dr:ul(e.travel,e.rollRatio,t),ddr:lR(e.travel,e.rollRatio,t)}}function uR(e,t,r,n){let o=tr(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 Zd=(e,t)=>Math.hypot(e[0]-t[0],e[1]+t[1],e[2]-t[2]);function Jd(e,t){let r=e.side[0].eyes,n=e.side[1].eyes;if(!r||!n)return null;let o=uR(e.side[0].travel,r.near,r.nearRatio,t[0]),a=uR(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 hR=(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,QT=(e,t)=>e.bump!==null&&t>e.bump||e.droop!==null&&t<e.droop?e.rate:0;function xs(e,t,r,n,o=0){let a=e.rollStop;if(!a)return r;let s=Jd(e,t);if(!s)return r;let i=hR(a,a.length0-(n??s.L+o));return i===0?r:[r[0]-i*s.dL[0],r[1]-i*s.dL[1]]}function ml(e,t){let r=Qd(e.travel);return t==="heave"?{...e,heave:r.heave,heaveRatio:r.heaveRatio}:{...e,roll:r.roll,rollRatio:r.rollRatio}}var pl=(e,t)=>e?e.law?Yo(e.law,t):e.preload+e.rate*t:0,mR=(e,t)=>e?e.law?Vd(e.law,t):e.rate:0;function Rs(e,t,r,n,o){let a=pl(e.heave,n),s=pl(e.roll,o);return[a*t.dh+s*t.dr,a*r.dh-s*r.dr]}var pR=(e,t)=>_e(e[0],t).h+_e(e[1],t).h;function ZT(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 JT(e,t,r){let n={...t,outer:t.inner},o=(u,m)=>{let f=ht(ye(e[0],u,0)),p=ht(ye(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=_e(r[0],a).r-_e(r[1],-a).r-(_e(r[0],-a).r-_e(r[1],a).r),l=i/c;return Number.isFinite(s)&&s>0&&Number.isFinite(l)&&Math.abs(l)>Xd?{length0:s,scale:l}:null}function bR(e,t,r,n=il){let o=r.heave?gs(r.heave):void 0,a=cR(e[0],r,o,n),s=e[1].corner===e[0].corner?a:cR(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(A=>_e(A,0));c&&!(Math.abs(p[0].dh+p[1].dh)>Xd)&&(i=[ml(i[0],"heave"),ml(i[1],"heave")],c=!1),l&&!(Math.abs(p[0].dr+p[1].dr)>Xd)&&(i=[ml(i[0],"roll"),ml(i[1],"roll")],l=!1),p=i.map(A=>_e(A,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 A=[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=(-A[0]*p[1].dr-A[1]*p[0].dr)/P,R=(p[0].dh*A[1]-p[1].dh*A[0])/P)}else b>0?y=(A[0]+A[1])/d:g>0&&(R=(A[0]-A[1])/h)}let k={};if(c&&o){let A=[a.pickups.heave,s.pickups.heave];k.heave={pickups:A,mount:o,span0:ys(A[0].at0,A[1].at0,o)}}let v=k.heave?k.heave.span0:NaN,x=k.heave?r.coilover:void 0,M=r.carriesLoad?ds(b,y,v,x):u?Od(b,{...ZT(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&&an(e[0].corner,r.roll,r.rollKind??"coil"))){let A=JT(e,r.roll,i);A&&(k.roll.unit=A)}let w=g>0?{rate:g,preload:R}:null,C={side:i,heave:F,roll:w,force0:[0,0],carriesLoad:r.carriesLoad,read:k},T=k.roll?.unit,S=T&&g>0&&i[0].eyes&&i[1].eyes?zo(T.length0,r.rollCoilover):null;return T&&S&&(S.droop!==null||S.bump!==null)&&(C.rollStop={length0:T.length0,rate:1e3*g/(T.scale*T.scale),...S}),C.force0=xs(C,[0,0],Rs(C,p[0],p[1],p[0].h+p[1].h,p[0].r-p[1].r)),C}function vs(e,t,r){let n=_e(e.side[0],t[0]),o=_e(e.side[1],t[1]),a=r?xs(e,t,Rs(e,n,o,n.h+o.h+r.heave,n.r-o.r+r.roll),void 0,r.unit):xs(e,t,Rs(e,n,o,n.h+o.h,n.r-o.r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function ef(e,t,r){let n=_e(e.side[0],t[0]),o=_e(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=mR(e.heave,a),c=mR(e.roll,s),l=pl(e.heave,a),u=pl(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?Jd(e,t):null;if(!p||!d)return f;let h=p.length0-(r?d.L+r.unit:d.L),b=QT(p,h);if(b===0)return f;let g=hR(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 tf(e,t,r){let n=ef(e,t);return n[r][0]+n[r][1]}function eP(e,t,r){let n=e.read.heave;if(!n)return _e(e.side[0],t[0]).h+_e(e.side[1],t[1]).h;let[o,a]=n.pickups;return n.span0-ys(De(o.corner,o.link,r[0]),De(a.corner,a.link,r[1]),n.mount)}function tP(e,t,r){let n=e.read.roll;if(!n)return _e(e.side[0],t[0]).r-_e(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 rP(e,t){let r=e.read.roll;if(!e.rollStop||!r)return;let[n,o]=r.pickups;return Zd(De(n.corner,n.link,t[0]),De(o.corner,{...o.link,outer:o.link.inner},t[1]))}function ks(e,t,r){let n=_e(e.side[0],t[0]),o=_e(e.side[1],t[1]),a=xs(e,t,Rs(e,n,o,eP(e,t,r),tP(e,t,r)),rP(e,r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function rf(e,t,r,n){let o=_e(e.side[0],r),a=_e(e.side[1],r),s=e.read.heave,i=s?.pickups[t],c=s&&i&&n?2*fR(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?Zd(De(l.corner,l.link,n),De(l.corner,{...l.link,outer:l.link.inner},n)):void 0;return xs(e,[r,r],Rs(e,o,a,c,n?0:o.r-a.r),u)[t]-e.force0[t]}function nf(e,t,r,n){let o=Wo(e,r[n]);return t?.carriesLoad?o+tf(t,r,n):o}function gR(e,t){return _e(e.side[0],t[0]).h+_e(e.side[1],t[1]).h}function yR(e,t){return Jd(e,t)?.L??null}var of=e=>e==="FR"||e==="RR"?1:0,dl=(e,t)=>e.elements?.[t==="FL"||t==="FR"?"front":"rear"]??null;var xR=e=>Number.isFinite(e)&&e>0?1/e:0;var RR=(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},nP=(e,t)=>[e[0][0]*t[0]+e[0][1]*t[1],e[1][0]*t[0]+e[1][1]*t[1]],vR=1e-8,oP=40;function aP(e,t,r,n){return{force:(s,i)=>{if(r){let u=vs(r,s,n);return[Yt(t[0],s[0])+i[0]+u[0],Yt(t[1],s[1])+i[1]+u[1]]}let c=(s[0]+s[1])/2,l=(s[0]-s[1])/2;return[Yt(t[0],s[0])+i[0]+e[0].heaveRate*c+e[0].arbRate*l,Yt(t[1],s[1])+i[1]+e[1].heaveRate*c-e[1].arbRate*l]},stiffness:(s,i=bs)=>{if(r){let c=ef(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 Uo(e,t,r,n,o,a=[0,0],s=[0,0],i=null,c){let l=[xR(r[0].tyreRate),xR(r[1].tyreRate)],u=[r[0].staticLoad,r[1].staticLoad],m=aP(r,n,i,c),f=P=>m.force(P,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=(P,L)=>{let D=L===1?f(P):m.force(P,[a[0]*L,a[1]*L]),E=[D[0]+s[0]*L,D[1]+s[1]*L],V=[P[0]+t[0]*L+E[0]*l[0]-e[0]*L,P[1]+t[1]*L+E[1]*l[1]-e[1]*L],N=[d[0]*(u[0]+E[0]),d[1]*(u[1]+E[1])],z=[N[0]<V[0],N[1]<V[1]];return{f:E,on:V,off:N,lifted:z,r:[Math.min(V[0],N[0]),Math.min(V[1],N[1])]}},b=(P,L)=>[L[0]?[d[0]*P[0][0],d[0]*P[0][1]]:[1+P[0][0]*l[0],P[0][1]*l[0]],L[1]?[d[1]*P[1][0],d[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]],E=h(D,L),V=!1,N=0;for(;N<oP;N++){if(g(E.r)<vR){V=!0;break}let z=RR(b(m.stiffness(D),E.lifted),[-E.r[0],-E.r[1]]);if(!z)break;let I=1,_=[D[0]+z[0],D[1]+z[1]],B=h(_,L);for(let O=0;O<8&&g(B.r)>g(E.r);O++)I/=2,_=[D[0]+I*z[0],D[1]+I*z[1]],B=h(_,L);D=_,E=B}return!V&&g(E.r)<vR&&(V=!0),{t:D,b:E,converged:V,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 P=0,L=[0,0],D=.25;for(;P<1&&D>=1/256;){let E=Math.min(1,P+D),V=y(L,E);k+=V.it,V.converged?(P=E,L=V.t,E===1&&(R=V)):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]],C=[F[0]?Math.max(0,x.on[0]):0,F[1]?Math.max(0,x.on[1]):0],T=m.stiffness(v,Wo),S=b(T,F);return{t:v,dF:w,lifted:F,clearance:C,converged:M,iterations:k,respond:(P,L,D=[0,0])=>{let E=[F[0]?-d[0]*D[0]:P[0]-L[0]-D[0]*l[0],F[1]?-d[1]*D[1]:P[1]-L[1]-D[1]*l[1]],V=RR(S,E);if(!V)return[NaN,NaN];let N=nP(T,V);return[F[0]?0:N[0]+D[0],F[1]?0:N[1]+D[1]]}}}var In=e=>!(Number.isFinite(e.tyreRate)&&e.tyreRate>0);function rr(e,t,r){return t?.input.corners[r].staticLoadedRadius??e}var af=["FL","FR","RL","RR"],SR={front:["FL","FR"],rear:["RL","RR"]},sP=512,iP=5e-4,cP=8;function fl(e,t){let r={},n={},o=new Map;for(let s of af){let i=e.ctx[s],c=t.corners[s],l=c.staticLoadedRadius;n[s]=at(ye(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=`${af.findIndex(p=>Ge(e.vehicle,p)===Ge(e.vehicle,s))}|${c.springLoad}|${u?`${u.extended}/${u.stroke}`:""}`,f=o.get(m);f?r[s]=f:(r[s]=u?hs(i,c.springLoad,void 0,u):hs(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=SR[s];a[s]=bR([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 AR(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 lP=e=>`${e.heave}|${e.pitch}|${e.roll}|${e.steer}`;function sf(e,t,r){return{travel:r.travel,steer:r.steer,ground:r.travel,tyreDeflection:0,load:NaN,loadedRadius:rr(Ge(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 kR(e,t,r,n){let o=SR[n],a=e.vehicle.config,s=o.map(w=>on(w,a,r,e.vehicle)),i=[t.input.corners[o[0]],t.input.corners[o[1]]],c=t.loadCase;if(!c&&i.every(In))return{corners:[sf(e,o[0],s[0]),sf(e,o[1],s[1])],respond:null};let l=o.map(w=>t.curve[w]),u=t.elements?.[n]??null,m=o.map(w=>rr(Ge(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=Uo(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<cP;w++){w>0&&(y=Uo(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 C=[0,0],T=[0,0];for(let A=0;A<2;A++){let P=ye(e.ctx[o[A]],y.t[A],s[A].steer,uP(R[A]),{loadedRadius:m[A]-v[A],patchShift:d[A]}),L=at(P);R[A]=L,k[A]=P.ok,C[A]=L.points.contactPatch[2]-t.ground0[o[A]]-y.t[A]-v[A],T[A]=kr(l[A],y.t[A],L.points.damperLength)-Yt(l[A],y.t[A])}if(u){let A=ks(u,y.t,[R[0],R[1]]),P=vs(u,y.t);T[0]+=A[0]-P[0],T[1]+=A[1]-P[1]}let S=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,S<iP){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: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:AR(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:nf(l[w],u,y.t,w)}}),respond:y.respond}}function FR(e,t){let r=e.kc,n=lP(t),o=r.memo.get(n);if(o)return o;let a=kR(e,r,t,"front"),s=kR(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>=sP&&r.memo.clear(),r.memo.set(n,i),i}function gt(e,t){if(!e.kc){let r={};for(let n of af)r[n]=sf(e,n,on(n,e.vehicle.config,t,e.vehicle));return r}return FR(e,t).corners}function hl(e,t,r){return e.kc?FR(e,t).respond[r]:null}function Ms(e,t,r,n=0){let o=e.kc;if(!o)return r;let a=o.input.corners[t];if(In(a))return r;let s=on(t,e.vehicle.config,{heave:0,pitch:0,roll:0,steer:n},e.vehicle).steer,i=rr(Ge(e.vehicle,t).config.loadedRadius,o,t),c=o.loadCase,l=c?.linkLoad[t]??0,u=c?.patchShift[t],m=at(ye(e.ctx[t],r,s,void 0,{loadedRadius:i,patchShift:u})),f=dl(o,t),p=kr(o.curve[t],r,m.points.damperLength)+(f?rf(f,of(t),r,m):a.heaveRate*r),h=Math.max(p+l,-a.staticLoad)/a.tyreRate;return(h===0?m:at(ye(e.ctx[t],r,s,void 0,{loadedRadius:i-h,patchShift:u}))).points.contactPatch[2]-o.ground0[t]-(c?.ground[t]??0)}var mP=180/Math.PI,pP=[0,0,1];function dP(e,t){let r=rn(e,t),n=U(ae(pP,r),-t.sideSign);return-Math.atan2(n[1],n[0])*mP}var wR=e=>1/Math.tan(e*Math.PI/180),CR=.05,TR=.001;function PR(e,t,r){if(!Number.isFinite(e)||!Number.isFinite(t))return NaN;if(!(Math.abs(e)<TR&&Math.abs(t)<TR))return e>0&&t>0?100*(wR(t)-wR(e))/r:NaN}function fP(e,t){let r=Nt(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=[CR,-CR].map(l=>{let{inner:u,outer:m}=a(t("FL",l).deg-n,t("FR",l).deg-o);return PR(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=PR(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 cf(e,t){let r=e.vehicle.config,n={FL:Ze("FL",r),FR:Ze("FR",r)},o=t.travel??0,a=fP(e,(i,c)=>{let l=ht(ye(e.ctx[i],o,n[i].sideSign*c));return{deg:l?dP(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 LR=35,DR=55,Vt=e=>e.rackTravel&&e.rackTravel>0?e.rackTravel:LR,lf=e=>e.rackRatio&&e.rackRatio>0?e.rackRatio:DR;var uf=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 ER(e,t,r,n,o){let a=ye(e,n,0,void 0,o),s=at(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=uf(s);for(let b=1;b<=r;b++){let g=p*(t*b)/r,y=Ie(e,s.beta,g,h,o),R=ht(ye(e,n,g,uf(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=uf(y)}return d},m=u(1),f=u(-1);return{travelMm:n,unsolved:i,centre:l,positive:m,negative:f}}function hP(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 IR(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:hP(o,t)});return{travelMm:e.travelMm,inner:n(r?e.positive:e.negative),outer:n(r?e.negative:e.positive)}}function bP(e){return e.positive[1].steer-e.centre.steer<0}function gP(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:lf(e.config),innerJacobian:r.inner.jacobian,outerJacobian:r.outer.jacobian}}function mf(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=ER(i,t,r,0,s),u=bP(l),m=IR(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=ER(i,t,r,b,s);return d+=g.unsolved,IR(g,c,u)});return{...gP(e,c,m),..._R(l.unsolved),travelSurface:{rackMm:c,rows:h,..._R(d)}}}var _R=e=>e>0?{unsolved:e}:{};function nr(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 bl(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 NR(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 _n=(e,t,r)=>e+r*(t-e);function Xo(e,t,r,n,o){let a=nr(e.rackMm,e.rows[n.lo][t][r],o);if(n.lo===n.hi)return a;let s=nr(e.rackMm,e.rows[n.hi][t][r],o);return _n(a,s,n.t)}function OR(e,t,r,n){let o=bl(e.rackMm,e.rows[r.lo][t].jacobian,n);if(r.lo===r.hi)return o;let a=bl(e.rackMm,e.rows[r.hi][t].jacobian,n);return{longitudinal:_n(o.longitudinal,a.longitudinal,r.t),lateral:_n(o.lateral,a.lateral,r.t),vertical:_n(o.vertical,a.vertical,r.t),yaw:_n(o.yaw,a.yaw,r.t)}}function qo(e,t,r,n){let o=e.travelSurface;if(!o||o.rackMm.length<2||o.rows.length===0)return Qo(e,t);let a=NR(o,r),s=NR(o,n),i=(p,d,h)=>{let b=o.rows[d.lo][p].steerDeg[h];return d.lo===d.hi?b:_n(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=_n(o.rackMm[d],o.rackMm[p],b)}return{innerDeg:Xo(o,"inner","steerDeg",a,m),outerDeg:Xo(o,"outer","steerDeg",s,m),innerCamber:Xo(o,"inner","camberDeg",a,m),outerCamber:Xo(o,"outer","camberDeg",s,m),innerLift:Xo(o,"inner","liftMm",a,m),outerLift:Xo(o,"outer","liftMm",s,m),innerJacobian:OR(o,"inner",a,m),outerJacobian:OR(o,"outer",s,m),atLock:f}}function Qo(e,t){let r=e.meanDeg.length-1;return{innerDeg:nr(e.meanDeg,e.innerDeg,t),outerDeg:nr(e.meanDeg,e.outerDeg,t),innerCamber:nr(e.meanDeg,e.innerCamber,t),outerCamber:nr(e.meanDeg,e.outerCamber,t),innerLift:e.innerLift?nr(e.meanDeg,e.innerLift,t):0,outerLift:e.outerLift?nr(e.meanDeg,e.outerLift,t):0,...e.innerJacobian&&e.outerJacobian?{innerJacobian:bl(e.meanDeg,e.innerJacobian,t),outerJacobian:bl(e.meanDeg,e.outerJacobian,t)}:{},atLock:r>=0&&t>e.meanDeg[r]}}var yP=()=>({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 Zo(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 yP();let a=Math.abs(t),s=t>0,i=n&&o.travelSurface?qo(o,a,s?n.FL:n.FR,s?n.FR:n.FL):null,c=i?.innerLift??nr(o.meanDeg,o.innerLift,a),l=i?.outerLift??nr(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 pf(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 Ss=9.81;function Jo(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?vr(e,t,r,Jr(e,n,o)):Dn(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 df(e,t,r=0,n=0,o=0){if(!e.aero?.model||t<=0)return!1;let a=vr(e,t,r,Jr(e,n,o));return a!=null&&(a.clampedRide||a.clampedAttitude)}function Nn(e){let t=e.loadFactor===void 0?e.massTotal*Ss:e.massTotal*Ss*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 VR(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*Uc(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 ff(e){let{cf:t,cr:r}=VR(e);return t+r>0?t/(t+r):.5}function BR(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 gl(e,t,r,n,o,a,s,i).loads}function gl(e,t,r,n=0,o=0,a=0,s,i){let c=Nn(e),l=we(e),u=rl(e,n,r,Jr(e,t,o),l),{cf:m,cr:f}=VR(e,l,u.height),p=m*t*Ss,d=f*t*Ss,h=e.massTotal*(r*Ss)*u.height/e.wheelbase-u.noseLoad,b=Jo(e,n,r,t,o),g=(i??Zo(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 BR(y,e.trackFront,e.trackRear)}var hf=Math.PI/180;function xl(e,t){let r=8*hf,n=0,o=0;for(let a=1;a<=90;a++){let s=a*.5,i=Math.abs(e.Fy(s*hf,t,0));if(i>n&&(n=i,r=s*hf,o=a),a>o+12&&i<.995*n)break}return{aPeak:r,fyPeak:n}}function $R(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 Fs=.999;function St(e,t,r,n,o){if(t<=0)return 0;let{aPeak:a,fyPeak:s}=o??xl(e,t),i=Math.min(Math.abs(r),Fs*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 C=.5*(v+x),T=l(C,a);T>=i?(v=C,M=T):(x=C,F=T)}Number.isNaN(M)&&(M=l(0,a)),m=M<i?0:$R(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 C=0;C<5;C++){let T=.5*(x+M),S=l(v,T);S<i?(x=T,F=S):(M=T,w=S)}return Number.isNaN(F)&&(F=l(v,0)),Number.isNaN(w)&&(w=l(v,a)),c*e.forces({Fz:t,kappa:c*v,alpha:$R(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=kP(p,h(g-1),h(Math.min(d,g+1)),h(g),b[g],h(y),b[y],h(R),b[R],xP);return c*Math.max(0,k)}var xP=.01,RP=20,vP=(3-Math.sqrt(5))/2;function kP(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<RP;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=vP*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 yf(e,t){return e.model?.kind==="simple"?null:HR(e,t)}var GR=new WeakMap,bf=100,KR=1.35,gf=18,or=41,yl=41,As=65;function HR(e,t){let r=GR.get(e);if(r)return r;let n=Math.log(KR),o=(p,d)=>{let h=M=>Math.abs(St(e,p,M,d)),b=h(0),g=t.muY(p)*p,y=new Float64Array(or),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 C=0;C<yl;C++){let T=Math.sin(.5*Math.PI*C/(yl-1));M.push(T),F.push(C===0?1:C===yl-1?0:Math.min(F[C-1],h(T*g)/b))}let w=yl-1;for(let C=0;C<or;C++){let T=C/(or-1);for(;w>0&&F[w-1]<T;)w--;let S=w>0?F[w-1]-F[w]:0;y[C]=w===0?M[0]:M[w]+(S>0?(T-F[w])/S:0)*(M[w-1]-M[w])}y[0]=1,y[or-1]=0}let k=new Float64Array(As),v=M=>Math.atan2(y[M],M/(or-1)/R),x=or-2;for(let M=0;M<As;M++){let F=.5*Math.PI*M/(As-1),w=Math.cos(F),C=Math.sin(F);for(;x>0&&v(x)<F;)x--;let T=x/(or-1)/R,S=y[x],A=(x+1)/(or-1)/R,P=y[x+1],L=w*(P-S)-C*(A-T),D=Math.abs(L)>1e-12?(T*(P-S)-S*(A-T))/L:Math.hypot(T,S);k[M]=D>0?D:Math.hypot(T,S)}return{room:y,scale:R,edge:k}},a=Array.from({length:gf},(p,d)=>bf*KR**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)*(or-1),b=Math.min(or-2,Math.floor(h));return p.room[b]+(h-b)*(p.room[b+1]-p.room[b])},l=p=>{let d=p>bf?Math.log(p/bf)/n:0;if(d>=gf-1)return[gf-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)*(As-1),k=Math.min(As-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 GR.set(e,f),f}var MP=[["front","FL","FR"],["rear","RL","RR"]];function ea(e,t,r,n){let o={...e},a=0,s=Fs;for(let[i,c,l]of MP){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 zR=.001,SP=1e-5,YR=100;function AP(e,t,r,n){if(!(n>zR))return r;let o=t,a=Math.abs(r-t)<YR?t+Math.sign(r-t)*YR:r;for(let s=0;s<60&&Math.abs(a-o)>SP;s++){let i=.5*(o+a);e(i)>zR?a=i:o=i}return o}function Rl(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=AP(e,t,o,e(o));return a!==o&&(n=a),a},edge:()=>n}}function vl(e,t){let r=n=>{try{return ye(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 xf=40;function kl(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 WR=[0,0,0];function FP(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 Ml(e,t,r){if(e.mcpherson)return wP(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??WR,c=[-t[0],-t[1],-t[2],-(s[0]+i[0]),-(s[1]+i[1]),-(s[2]+i[2])],l=Jt(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]:FP(e,u[5]),condProxy:l.condProxy,singular:l.singular}}function wP(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??WR,l=[-t[0],-t[1],-t[2],-(i[0]+c[0]),-(i[1]+c[1]),-(i[2]+c[2])],u=Jt(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 Rf(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 CP=[0,0,0];function ws(e,t,r,n){let o=e.direct?e.damperChassis:e.rockerToPushrod;if(e.mcpherson)return{...Ml(e,r,n),armResidual:0};if(t==="upright")return{...Ml(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??CP,b=[-r[0],-r[1],-r[2],-(d[0]+h[0]),-(d[1]+h[1]),-(d[2]+h[2])],g=Jt(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)),C=U(M,-1),T=(Z,ne)=>X(F,ae(H(Z,i.front),ne)),S=T(e.pushrodOuter,w),A=Math.abs(S)>1e-9?-T(i.bj,C)/S:NaN,P=ee(C,U(w,A)),L=U(P,-1),D=q(H(i.front,i.bj)),E=q(H(i.rear,i.bj)),V=X(D,D),N=X(D,E),z=X(E,E),I=X(D,L),_=X(E,L),B=V*z-N*N,O=NaN,G=NaN,K=NaN;if(Math.abs(B)>1e-12){O=(I*z-_*N)/B,G=(V*_-N*I)/B;let Z=ee(U(D,O),U(E,G)),ne=H(L,Z);K=Math.hypot(ne[0],ne[1],ne[2])}let Y=a?{f:k,r:v}:{f:O,r:G},j=a?{f:O,r:G}:{f:k,r:v};return{ucaFront:Y.f,ucaRear:Y.r,lcaFront:j.f,lcaRear:j.r,tieRod:x,pushRod:A,damper:y||!Number.isFinite(A)||e.decoupled?NaN:e.direct?A:TP(e,A),condProxy:g.condProxy,singular:y,armResidual:K}}function TP(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 t4=Math.PI/180;function Cs(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 UR=["QSX3","QSX8","QSX13","QSX14"],PP=["QSX1"],Sl=["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",...UR];function LP(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 DP(e){let t=new Set(LP(e)),r=Sl.filter(n=>!UR.includes(n));return[...r.filter(n=>!t.has(n)),...[...t].filter(n=>!r.includes(n)),...PP]}function EP(e,t){let r={...e};for(let n of t)r[n]!==void 0&&r[n]!==0&&(r[n]=-r[n]);return r}var Mr=(e,t,r)=>Number.isFinite(e[t])?e[t]:r;function XR(e,t){return t!=="5.2"?Mr(e,"PKY6",0)*Mr(e,"LKYC",1):Mr(e,"PKY1",-15)*Math.sin(Mr(e,"PKY4",2)*Math.atan(1/Mr(e,"PKY2",2)))*Mr(e,"LKY",1)*Mr(e,"PHY3",0)+Mr(e,"PVY3",0)*Mr(e,"LMUY",1)}var jR=.1;function qR(e){if(e.fitData)return"sae";let t=XR(e.coeffs,e.version);return t>jR?"sae":t<-jR?"iso":null}function Ts(e){return e.axisSystem??qR(e)??"sae"}function Al(e){let t=new Set,r=n=>{for(let o of n)t.has(o)?t.delete(o):t.add(o)};return Ts(e)==="iso"&&r(Sl),e.axisSystem&&e.side==="left"&&r(DP(e.version)),t.size?EP(e.coeffs,t):e.coeffs}var n4=Math.PI/180;var $=(e,t)=>Number.isFinite(e)?e:t;function ZR(e){let t=Al(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 QR=new WeakMap;function Ps(e){let t=QR.get(e);return t===void 0&&(t=ZR(e),QR.set(e,t)),t}var JR=e=>e>=0?1:-1;function Fl(e,t,r=0,n){let o=Ps(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 wl(e,t,r=0,n){let o=Fl(e,t,r,n),a=Ps(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),C=e.version!=="5.2",T=s*(a.PVX1+a.PVX2*c)*a.LVX*a.LMUX,S=a.REX1+a.REX2*c;S>1&&(S=1);let A=a.REY1+a.REY2*c;return A>1&&(A=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: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:S,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:A,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: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?d/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 Ls(e,t){let r=t+e.SHy,n=e.EyA*(e.EyG-e.EyS*JR(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 Cl(e,t){let r=t+e.SHx,n=e.ExA*(1-e.PEX4*JR(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 ev(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 IP(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=ev(e,o,r),i=e.Bt*s;return e.Dt*Math.cos(e.Ct*Math.atan(i-a*(i-Math.atan(i))))*n}function _P(e,t,r,n){return e.Dr*Math.cos(Math.atan(e.Br*ev(e,t+e.SHy+e.arOff,r)))*n}function tv(e,t,r,n,o,a){let s=Math.cos(t),i=IP(e,t,r,s),c=_P(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*Cl(e,t)}function vf(e,t){let r=e.sS0===0&&e.sS2===0?0:rv(e,0,t);return tv(e,t,0,r,Ls(e,t),0)}function Tl(e,t,r){let n=Ls(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:tv(e,r,t,o,m,u)}}var Ds=(e,t)=>Math.max(.1,e.muY0+e.loadSensY*(t-e.nominalLoad)),Es=(e,t)=>Math.max(.1,e.muX0+e.loadSensX*(t-e.nominalLoad)),nv=(e,t,r)=>Ds(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cy*Math.atan(e.By*r)),ov=(e,t,r)=>Es(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cx*Math.atan(e.Bx*r));function kf(e,t){let r=Math.max(1,t.Fz),n=Ds(e,r)*r,o=Es(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 ta=Math.PI/180;function sn(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 av(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?Cs(r,t):1,s=n?Cs(n,t):1,i=o?Cs(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 ra(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=av(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=wl(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=Fl(r,v,x,M),u=v,m=x,f=M),l),d=v=>e.kind==="magic"?Tl(c(v.Fz,v.gamma??0,v.p),v.kappa,v.alpha):kf(n,v),h=(v,x,M=0,F)=>e.kind==="magic"?Ls(p(x,M,F),v):nv(n,x,v),b=(v,x,M=0,F)=>e.kind==="magic"?Cl(c(x,M,F),v):ov(n,x,v),g=(v,x,M=0,F)=>e.kind==="magic"?vf(c(x,M,F),v):d({Fz:x,kappa:0,alpha:v,gamma:M,p:F}).Mz,y=v=>e.kind==="simple"?Ds(n,v):ra(x=>h(x*ta,v),45,1)/Math.max(1,v),R=v=>e.kind==="simple"?Es(n,v):ra(x=>b(x,v),.6,.02)/Math.max(1,v),k=v=>{let x=.1*ta;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 na(e){let t=Math.max(1,e.model.kind==="magic"?e.model.fnomin:e.model.nominalLoad);return e.Fy(2*ta,t,0)-e.Fy(-2*ta,t,0)>=0?1:-1}function Is(e,t=e.kind==="magic"?e.fnomin:e.nominalLoad){let r=Pe(e),n=2*ta,o=3*ta,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 NP=Math.PI/180;function ge(e,t){return e.axle?e.axle(t):e}function Ll(e,t){if(e===t)return e;let r=na(e)*na(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=>ra(u=>s(u,l),.6,.02)/Math.max(1,l),muY:l=>ra(u=>i(u*NP,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 ut(e){if(sv.has(e))return e;let t=iv.get(e);if(t)return t;let r;if(e.axle){let n=e.axle("front"),o=e.axle("rear"),a=ut(n),s=ut(o);r=a===n&&s===o?e:Ll(a,s)}else na(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&&iv.set(e,r),r}var sv=new WeakSet,iv=new WeakMap;var Dl=25*(Math.PI/180);function OP(e){let t=.6180339887,r=0,n=Dl,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 _s(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=Dl;if(s(Dl)<=a){let u=OP(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(Dl,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 Mf={shaft:!1,trail:0,hub:[0,0,0]};function lv(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 Sf(e,t,r){let n=r.shaft?Rf(e,t):[0,0,0];if(r.trail!==0){let a=lv(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 VP=(e,t)=>{let r=e!==void 0&&e>0?1/e:0,n=t!==void 0&&t>0?1/t:0;return r+n},El={ucaFront:0,ucaRear:0,lcaFront:0,lcaRear:0,tieRod:0,pushRod:0,rack:0};function On(e){return!e.measured}function Vn(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 Ns(e,t){let r=e.corner.hardpoints,n=us(e.rocker,t.points.rockerAngle);return{ucaFront:r.ucaFront,ucaRear:r.ucaRear,lcaFront:r.lcaFront,lcaRear:r.lcaRear,tieInner:Go(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 Af(e,t,r=0){let n=t.links??{},o=t.bushings??{},a=(l,u,m)=>{let f=VP(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 uv(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 Os(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=uv(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=uv(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 BP=8,$P=1e-5,GP=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 Ff(e,t,r){let n=Sf(e,r.force,r.extras??Mf),o=r.alignMoment?ee(n.moment,[0,0,r.alignMoment]):n.moment;return ws(e,t,n.force,o)}function _l(e,t,r,n,o,a,s=0){let i=Ie(e,t,r,o,a),c=e.corner.compliance;if(!(Vn(c)&&On(e.corner)))return{state:i,forces:Ff(Ns(e,i),e.corner.config.pushrodAttach,n),deflection:El,rigid:i,iterations:0,converged:!0,bypassed:!0};let u=i,m=e,f=e.corner.config.pushrodAttach,p=Ff(Ns(e,i),f,n),d=El,h=!1,b=0;for(;b<BP;b++){let g=Ns(m,u);if(p=Ff(g,f,n),p.singular)break;d=Af(p,c,s),m=Os(e,d);let y=Ie(m,t,r,GP(u),a),R=ve(y.points.wheelCenter,u.points.wheelCenter);if(u=y,R<$P){h=!0;break}}return{state:u,forces:p,deflection:d,rigid:i,iterations:b+1,converged:h&&u.converged,bypassed:!1}}var Il=1e3,mv=1e5;function pv(e,t,r,n,o){let a=_l(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 Nl(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,Il,n]),l=s([0,-Il,n]),u=s([Il,0,n]),m=s([-Il,0,n]),f=s([0,0,n],mv),p=s([0,0,n],-mv),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 KP=1e3;function wf(e,t=KP){if(!Vn(e.compliance)||!On(e))return;let r=tt(e),n=Ie(r,0,0),o=Nl(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 oa(e,t=-xf,r=xf,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=wf(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 Ol(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 cn(e,t){return{motionRatio:Ol(e.travel,e.motionRatio,t),camber:Ol(e.travel,e.camber,t),toe:Ol(e.travel,e.toe,t),damperLen:Ol(e.travel,e.damperLen,t)}}var dv=Math.PI/180,HP=9.81;function ln(e,t,r,n=0){let o=we(e),a=e.wheelbase*(1-e.frontMassFrac),s=e.wheelbase*e.frontMassFrac,i=Jo(e,n),c=e.aero?.model?(k,v,x)=>Jo(e,n,v,k,x):()=>i,l=cn(t,0),u=cn(r,0),m=e.loadFactor,f=m!==void 0&&m!==1?(m-1)*e.massTotal*HP: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=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 F=c(k,v,x),w=o.rollGradient*k,C=w*dv,T=o.pitchGradient*v*dv,S=(V,N)=>{let z=N==="F"?e.trackFront:e.trackRear,I=N==="F"?o.rideRateFront:o.rideRateRear,_=(V==="R"?1:-1)*(z/2)*Math.tan(C),B=(N==="R"?s:-a)*Math.tan(T),O=`${N}${V}`,G=f?F[O]+(N==="F"?p:d):F[O],K=I>0?G/I:0;return{anti:_,sym:B+K}},A={FL:S("L","F"),FR:S("R","F"),RL:S("L","R"),RR:S("R","R")},P=V=>{let N=V[0];return A[V].sym*y[N]+A[V].anti*R[N]},L=Zo(e,M,o,{FL:P("FL"),FR:P("FR")}),D=w+L.rollDeg,E=(V,N)=>{let z=N==="F"?t:r,I=N==="F"?l:u,_=`${N==="F"?"F":"R"}${V}`,B=A[_].sym+A[_].anti+L.travel[_],O=P(_)+L.travel[_]*R[N],G=B-O,K=cn(z,O),Y=(V==="R"?1:-1)*K.camber;return{travel:O,tyre:G,ground:B,camber:Y,camberRoad:Y+D,toe:K.toe,bumpToe:K.toe-I.toe,damperTravel:I.damperLen-K.damperLen}};return{FL:E("L","F"),FR:E("R","F"),RL:E("L","R"),RR:E("R","R"),steeringJacking:L}}}var Cf=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function Bn(e){return{enabled:e?.enabled===!0,roadFeedbackGain:Math.min(2,Math.max(0,Cf(e?.roadFeedbackGain,1))),turnInFrictionNm:Math.max(0,Cf(e?.turnInFrictionNm,0)),columnStiffnessNmPerRad:Math.max(0,Cf(e?.columnStiffnessNmPerRad,0))}}function Tf(e,t,r){let n=Bn(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 fv=()=>({totalNm:0,aligningNm:0,lateralNm:0,longitudinalNm:0,jackingNm:0});function $n(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 Vs(e,t,r,n="model",o){let a=e.steerFront;if(!$n(e)||!a)return null;let s=t<0?-1:1,c=a.rackRatioMmPerRev/(2*Math.PI)/1e3,l=t>=0,u=o&&a.travelSurface?qo(a,Math.abs(t),l?o.FL:o.FR,l?o.FR:o.FL):Qo(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=fv();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=fv();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=Tf(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 zP=e=>"front"in e&&"rear"in e;function aa(e,t){return zP(e)?e[t]:e}function Lf(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 Pf(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 hv(e,t,r){let n=Pf(e,t),o=Pf(e,r);return{left:n,right:o,fyRes:n.fyRes+o.fyRes}}function Sr(e,t,r){let n=hv(aa(e,"front"),t.FL,t.FR),o=hv(aa(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 Bs=[{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"}],WP=Bs.flatMap(e=>[e.min,e.max]);function jP(e){let t={};for(let r of Bs){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 Vl(e){if(e.kind==="magic")return e.range??jP(e.coeffs)}function Df(e){return Math.max(1,e.kind==="magic"?e.fnomin:e.nominalLoad)}function bv(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 Wt(e){let t=gv.get(e);if(t!==void 0)return t;let r=10*Df(e.model),{turnover:n,collapse:o}=XP(e,r),a=n??o??r;return gv.set(e,a),a}var gv=new WeakMap;function XP(e,t){let r=Df(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=bv(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=bv(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 yv=.1;function Bl(e,t=Df(e)){let r=Pe(e).muX(t);return{muX:r,none:Number.isFinite(r)&&r<yv}}var xv=["FL","FR","RL","RR"],qP=e=>e==="FL"||e==="RL",QP=e=>e==="FL"||e==="FR"?"front":"rear";function $l(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 xv)a[l]={...t[l]};let s=l=>{let u=0;for(let f of xv)QP(f)===e.axle&&(a[f].Fx=e.sense*(f===e.strong?l-e.open/2:e.open/2),u-=(qP(f)?o:-o)*a[f].Fx);let m=Sr(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 ZP=[["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]],JP=[["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]],eL=[["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]],tL=[["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]],rL=[["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]],vv=[["lateral",ZP],["longitudinal",JP],["aligning",eL],["combined",tL],["scaling",rL]].flatMap(([e,t])=>t.map(([r,n,o])=>({key:r,section:e,text:n,fallback:o}))),sH=new Map(vv.map(e=>[e.key,e]));var nL=/^\$\s*EDITED\s+([A-Z][A-Z0-9_]*)\s+was\s+(absent|[-+0-9.eE]+)\s*$/;function kv(e){let t={};for(let r of e.split(/\r?\n/)){let n=r.trim().match(nL);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 aL=/^\s*\$\s*UNLOADED_RADIUS_STAND_IN\s*=\s*([0-9.eE+-]+)/,sL=/^\$-+ written by (?:PaceDynamics|PaceLab)\b/m,iL=/^\$\s*AXIS_SYSTEM\s*=\s*(ISO-W|SAE)\b/m;function cL(e){let t=e.match(iL);return t?{axisSystem:t[1]==="SAE"?"sae":"iso",trustSide:!0}:sL.test(e)?{axisSystem:"sae",trustSide:!1}:{axisSystem:"iso",trustSide:!0}}function lL(e){return e>=62?"6.2":e>=61?"6.1":"5.2"}var Mv=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:Mv.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 mL=new Map([["radians",1],["radian",1],["rad",1],["degrees",Math.PI/180],["degree",Math.PI/180],["deg",Math.PI/180]]);function pL(e,t){let r=(s,i)=>s===void 0?1:i.get(s.trim().toLowerCase()),n=r(t.ANGLE,mL),o={fz:1,kappa:1,alpha:n,gamma:n,p:r(t.PRESSURE,Mv)},a={};for(let s of Bs){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 $s(e,t="imported",r={}){let n=cL(e),o=r.axisSystem??n.axisSystem,a={},s={},i={},c="",l;for(let g of e.split(/\r?\n/)){let y=g.match(aL);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=lL(a.FITTYP??62),m=kv(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=pL(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 ar(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}var fH=Math.PI/180;var xH=Math.PI/180,RH=180/Math.PI;function Gs(){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 Fv=`$ 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 Ef(){return $s(Fv,"Example MF6.2")}var fL=Math.PI/180,wv=2,Cv=2;function Tv(e){let t=Math.sin(Cv*Math.atan(1/wv)),r=-e.corneringStiffness/(e.Fz0*t),n=e.camberStiffness/fL/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(wv)}
|
|
174
174
|
PKY3 = 0.8
|
|
175
|
-
PKY4 = ${o(
|
|
175
|
+
PKY4 = ${o(Cv)}
|
|
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 vr(e){let t=Ds(lv(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},mv={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},pv={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},dv={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},fv={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},hv={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},bv={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},gv={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},vf=()=>vr(uv),kf=()=>vr(mv),Mf=()=>vr(pv),Sf=()=>vr(dv),Af=()=>vr(fv),Ff=()=>vr(hv),wf=()=>vr(bv),Cf=()=>vr(gv);var yv=e=>Number.isFinite(e)&&e>0;function Il(e,t){let r=yv(t.grip)?t.grip:1,n=yv(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 Is={ok:!0,violation:0},_n=1e7;function kr(e,t){let r;try{r=e.build(t)}catch(s){return{total:_n*2,feasible:!1,terms:[],reason:`build failed: ${String(s)}`}}let n=e.feasible(r);if(!n.ok)return{total:_n+Math.max(0,n.violation),feasible:!1,terms:[],reason:n.reason};let o;try{o=e.terms(r)}catch(s){return{total:_n*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:_n*2,feasible:!1,terms:o,reason:"objective was not finite"}}var _s=(e,t)=>!t||(e.feasible!==t.feasible?e.feasible:e.total<t.total);function Tf(e,t){return t.map((r,n)=>Math.min(e[n].hi,Math.max(e[n].lo,r)))}var Mr=e=>e.map(t=>t.start);function _l(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 $P(e){let t=0;for(;t===0;)t=e();return Math.sqrt(-2*Math.log(t))*Math.cos(2*Math.PI*e())}function Pf(e,t){let{budget:r}=t,n=Math.max(1,Math.floor(t.progressEvery??1)),o=e.variables,a=p=>Tf(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=kr(e,a(d));h.feasible||c++;let b=_s(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):Mr(o),score:l??kr(e,Mr(o)),evaluations:i,history:m,infeasible:c})}}var Lf=(e,t,r,n=0,o)=>{let a=t?r.norm(Mr(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 xv(e,t){let r=Pf(e,t),n=_l(t.seed??1),o=e.variables.length;for(r.evaluate(Lf(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 ra(e,t){let r=Pf(e,t),n=e.variables.length,o=_l(t.seed??1),a=1,s=2,i=.5,c=.5,l=Lf(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 Rv(e,t){let r=Pf(e,t),n=e.variables.length,o=_l(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=Lf(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 S=0;S<a&&r.left()>0;S++){let A=[];for(let L=0;L<n;L++)A.push($P(o));let P=g.map((L,D)=>L+y*R[D]*A[D]);M.push({z:A,u:P,f:r.evaluate(P)})}if(M.length<s)break;M.sort((S,A)=>S.f-A.f);let F=g.slice(),w=new Array(n).fill(0);g=new Array(n).fill(0);for(let S=0;S<s;S++)for(let A=0;A<n;A++)g[A]+=i[S]*M[S].u[A],w[A]+=i[S]*M[S].z[A];g=g.map(S=>Math.min(1,Math.max(0,S)));for(let S=0;S<n;S++)k[S]=(1-u)*k[S]+Math.sqrt(u*(2-u)*l)*w[S];let C=Math.sqrt(k.reduce((S,A)=>S+A*A,0)),T=C/Math.sqrt(1-(1-u)**(2*x))/b<1.4+2/(n+1)?1:0;for(let S=0;S<n;S++){let A=(g[S]-F[S])/(y*R[S]);v[S]=(1-f)*v[S]+T*Math.sqrt(f*(2-f)*l)*A}for(let S=0;S<n;S++){let A=0;for(let D=0;D<s;D++)A+=i[D]*M[D].z[S]*M[D].z[S];let P=R[S]*R[S],L=(1-d-h)*P+d*(v[S]*v[S]+(1-T)*f*(2-f)*P)+h*A*P;R[S]=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 na=[{name:"random",run:xv},{name:"nelder-mead",run:ra},{name:"sep-cma-es",run:Rv}];var Z4=Math.PI/180;var Nl=Math.PI/180;var rH={Fz:100,alpha:.25*Nl,kappa:.005,gamma:.5*Nl,p:6900},vv={Fz:100,alpha:1*Nl,kappa:.02,gamma:.5*Nl,p:6900};var kv=Math.PI/180,cH={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:kv},gamma:{rad:1,deg:kv},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 dH=Math.PI/180;var ZP=Math.PI/180;var RH=3*ZP;var AH=Math.PI/180;var OH=Math.PI/180;var sL={RCX1:1,RCY1:1,REX1:0,REY1:0,RBY3:0,RHX1:0,RHY1:0},Av={RBX1:15,RBX2:15,RBY1:18,RBY2:19,...sL};var UH=Math.PI/180;var pL=Math.PI/180,Ol=[{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"}],l6=new Map(Ol.map(e=>[e.id,e]));var u6=.01*pL;var We=Math.PI/180;var Cv=new Set(Ol.filter(e=>e.group!=="inputs"&&(e.unit==="N"||e.unit==="N\xB7m"||e.unit==="N/rad")).map(e=>e.id)),Tv={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}},Nf={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 Of={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,...Tv[t],...o}],x:t,y:r,...n}),Vl=(e,[t,r],n,o,a={})=>({id:e,form:"carpet",sweep:[{input:t,...Nf[t]},{input:r,...Nf[r]}],x:n,y:[o],...a}),Sr=(e,t)=>({id:e,fixed:t}),Vt={input:"Fz",values:"car"},_f={alpha:0,kappa:0},yt={kappa:0},Fv={alpha:0},fL={input:"Fz",values:[500,1e3,1500]},hL=[{id:"overview",name:"Overview",cards:[Sr("tyre","tyre"),ke("fy","alpha",["Fy"],{title:"Lateral force",hold:yt}),ke("mz","alpha",["Mz"],{title:"Aligning moment",hold:yt}),ke("fx","kappa",["Fx"],{title:"Longitudinal force",hold:Fv}),Vl("combined-carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Sr("ellipse","ellipse")]},{id:"lateral",name:"Lateral",cards:[ke("fy-load","alpha",["Fy"],{title:"Lateral force per wheel load",series:Vt,hold:yt}),ke("muy-load","alpha",["muY"],{title:"Lateral force per unit load",series:Vt,hold:yt}),ke("fy-peak","alpha",["Fy"],{title:"Lateral force over its peak",series:Vt,hold:yt,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:Vt,hold:yt}),ke("trail","alpha",["t"],{title:"Pneumatic trail",series:Vt,hold:yt},{from:0,to:12*We,n:49}),ke("mzr","alpha",["Mzr"],{title:"Residual aligning moment",series:Vt,hold:yt},{from:0,to:12*We,n:49}),Vl("gough",["alpha","Fz"],"Fy","Mz",{title:"Gough plot",hold:yt}),ke("steering-feel","alpha",["t"],{title:"Steering feel",x:"FyRel",series:Vt,hold:yt},{from:0,to:12*We,n:49})]},{id:"longitudinal",name:"Longitudinal",cards:[ke("fx-load","kappa",["Fx"],{title:"Longitudinal force per wheel load",series:Vt,hold:Fv}),ke("mux-peak","Fz",["muXPeak"],{title:"Peak longitudinal \u03BC over load"}),ke("kx","Fz",["dFxdk"],{title:"Slip stiffness at zero slip over load",hold:_f}),ke("kappa-peak","Fz",["kappaPeak"],{title:"Slip ratio at the peak over load"})]},{id:"combined",name:"Combined",cards:[Vl("carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Vl("envelope-load",["kappa","alpha"],"Fy","Fx",{title:"Friction envelope per load",scale:{per:"Fz"},facet:fL}),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]}}),Sr("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:yt}),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",...Of.gamma},{input:"Fz",...Of.Fz,follow:!0}],x:"gamma",y:["Fz"],z:"muYPeak"},ke("camber-stiffness","alpha",["dFydg"],{title:"Camber stiffness at the point",series:Vt,hold:yt}),ke("mx","alpha",["Mx"],{title:"Overturning moment",series:Vt,hold:yt})]},{id:"rolling",name:"Rolling and radius",cards:[ke("my","V",["My"],{title:"Rolling-resistance moment",series:Vt,hold:_f}),ke("radius","Fz",["R0","Rl","Re"],{title:"Radius over load"},{from:0}),ke("p-roll","V",["Proll"],{title:"Rolling power",series:Vt,hold:_f})]},{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:yt,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:[Sr("operating","operating"),Sr("wheels","wheels")]},{id:"fit",name:"Fit check",cards:[Sr("fitLateral","fitLateral"),Sr("fitLongitudinal","fitLongitudinal"),Sr("fitCoupling","fitCoupling"),Sr("fitEnvelope","fitEnvelope")]}];var kL=5670374e-14,Vf=273.15,Dv=.95,Ev=60,Bl=10,ML=.55,At=25,Bf=-20,$f=50,Os={tempC:[20,100,200,550,650,750],factor:[.8,.92,1,1,.85,.65]},Vs={discMassKg:.5,discOuterMm:220,specificHeatJPerKgK:460,emissivity:.6,coolingWPerM2K:200,padCurve:{tempC:[...Os.tempC],factor:[...Os.factor]}},$l={...Vs,discMassKg:.4,discOuterMm:200,padCurve:{tempC:[...Os.tempC],factor:[...Os.factor]}};function Gf(e,t){let r=t==="front"?Vs:$l,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 SL=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},Ns=(e,t,r,n)=>Math.min(r,Math.max(t,SL(e,n)));function AL(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 Kf(e,t){return{discMassKg:Ns(e?.discMassKg,.05,20,t.discMassKg),discOuterMm:Ns(e?.discOuterMm,50,600,t.discOuterMm),specificHeatJPerKgK:Ns(e?.specificHeatJPerKgK,100,3e3,t.specificHeatJPerKgK),emissivity:Ns(e?.emissivity,.02,1,t.emissivity),coolingWPerM2K:Ns(e?.coolingWPerM2K,Bl,5e3,t.coolingWPerM2K),padCurve:AL(e?.padCurve,t.padCurve)}}function Gl(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 Hf(e,t=1){let r=e.discMassKg*e.specificHeatJPerKgK,n=e.discOuterMm*.001/2,o=2*Math.PI*n*n,a=Ev/3.6,s=e.emissivity*kL*o,i=m=>Bl+(e.coolingWPerM2K-Bl)*Math.pow(Math.max(0,m)*t/a,ML),c=(m,f,p)=>{let d=m+Vf,h=p+Vf;return i(f)*o*(m-p)+s*(d**4-h**4)},l=(m,f)=>i(f)*o+4*s*Math.max(0,m+Vf)**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=>Gl(e.padCurve,m),window:Iv(e.padCurve)}}function Kl(e,t,r,n,o,a,s=At){let i=n.length,c=new Array(i),l=new Array(i),u=new Array(i),m=Dv/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 Iv(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])&&Gl(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 zf=1e5,Vv=.001,Nn={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},Wf={fullAtBar:10,maxPowerKw:0,fadeBelowKmh:0,distribution:"equal"};var jf=$v(zl(Nn,"Formula Student brakes")),Uf=40,Bv={ideal:!1,barFront:Nn.barFront,pedalForceMaxN:0,testSpeedKmh:Uf,regen:Wf};function _v(e){let{heat:t,...r}=e;return t?{...r,heat:{...t,padCurve:{tempC:[...t.padCurve.tempC],factor:[...t.padCurve.factor]}}}:r}function $v(e){let t=(r,n)=>r.heat?r:{...r,heat:Gf(r,n)};return{...e,front:t(e.front,"front"),rear:t(e.rear,"rear")}}function zl(e,t){return{name:t,pedalRatio:e.pedalRatio,masterFrontMm:e.masterFrontMm,masterRearMm:e.masterRearMm,valve:e.valve,valveKneeBar:e.valveKneeBar,valveSlope:e.valveSlope,front:_v(e.front),rear:_v(e.rear),adjusterPitchMm:e.adjusterPitchMm,barLengthMm:e.barLengthMm}}function Xf(e,t){return Gv({...e,barFront:t.barFront,pedalForceMaxN:t.pedalForceMaxN})}function qf(e,t){let r=Fr(t),n=e?rr(e):void 0;return{mode:r.ideal?"tyre":n?"hydraulic":"balance",hydraulic:n?Xf(n,r):Nn,regen:r.regen}}var FL=["none","proportioning","limiter"],Hl=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},Je=(e,t,r,n)=>Math.min(r,Math.max(t,Hl(e,n))),wL=(e,t)=>{let r=Hl(e,t);return r>0?r:t};function Nv(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(Hl(e?.discs,n==="inboard"?1:t.discs)))),pistonsPerSide:Math.max(1,Math.min(6,Math.round(Hl(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:Kf(e.heat,t.heat??r)}:{}}}function Gv(e){let t=Nn;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:FL.includes(e?.valve)?e?.valve:t.valve,valveKneeBar:Je(e?.valveKneeBar,0,200,t.valveKneeBar),valveSlope:Je(e?.valveSlope,0,1,t.valveSlope),front:Nv(e?.front,t.front,Vs),rear:Nv(e?.rear,t.rear,$l),adjusterPitchMm:wL(e?.adjusterPitchMm,t.adjusterPitchMm),barLengthMm:Je(e?.barLengthMm,0,500,t.barLengthMm)}}function CL(e){let t=Wf;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 rr(e){let t=Gv(e??void 0),r=typeof e?.name=="string"&&e.name.trim()?e.name:TL;return zl(t,r)}function Fr(e){return{ideal:e?.ideal===!0,barFront:Je(e?.barFront,.05,.95,Nn.barFront),pedalForceMaxN:Je(e?.pedalForceMaxN,0,5e3,0),testSpeedKmh:Je(e?.testSpeedKmh,5,150,Uf),regen:CL(e?.regen)}}var TL="Formula Student brakes";var Yf=e=>Math.PI/4*(e*Vv)**2;function on(e,t){let r=e.pistonsPerSide*Yf(e.pistonDiaMm)*zf;return e.discs*2*e.padMu*r*e.effRadiusMm*Vv*e.ratio/Math.max(.05,t)}function Kv(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 Bs(e,t){let r=Math.max(0,t)*e.pedalRatio,n=e.barFront*r/Yf(e.masterFrontMm)/zf,o=(1-e.barFront)*r/Yf(e.masterRearMm)/zf;return{front:n,rearIn:o,rear:Kv(e,o)}}function PL(e,t){let r=Bs(e,1);return{front:on(e.front,t)*r.front,rear:on(e.rear,t)*r.rearIn}}function $s(e,t){let r=PL(e,t);return r.front/Math.max(1e-12,r.front+r.rear)}function Gs(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=Hv(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 Hv(e,t){let r=e.fadeBelowKmh/3.6;return r>0?Math.max(0,Math.min(1,t/r)):1}function Ar(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 Ov=new WeakMap;function On(e){let t=Ov.get(e);return t||(t=e.mode==="hydraulic"&&e.hydraulic?DL(e,e.hydraulic):LL(e),Ov.set(e,t)),t}function LL(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 DL(e,t){let r=on(t.front,e.tyreRadiusM),n=on(t.rear,e.tyreRadiusM),o=e.regen,a=(c,l)=>{let u=Bs(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*Ar(o.v,o.front,l),f=p*Ar(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 Qf(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 Yl=ys,EL=.1,Vn=(e,t)=>e.a*Math.sqrt(Math.max(0,1-(t/Math.max(1e-9,e.b))**2));function Wl(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 eh(e,t,r){let n=Math.max(0,r-Yl*t.b),o=Math.min(r,Yl*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 th(e,t,r,n,o=0){let a=Math.max(0,r),s=eh(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/EL)),d=p>0&&a<Yl*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:T=>2*Math.max(0,l-T)};let{lo:R,hi:k}=s,v=Wl(T=>{let S=Vn(e,T),A=Vn(t,a-T);return Math.min(S+A,2*Math.min(S,A)+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=(T,S,A)=>Math.min(y,Math.max(0,T-A))+Math.min(y,Math.max(0,S-A));return{...g,regenWheel:y,mixedMax:F,regenRoom:T=>{let S=w(i,c,T);if(!(a>0))return S;let A=E=>Yl*E.b*Math.sqrt(Math.max(0,1-(T/Math.max(1e-9,E.a))**2)),P=Math.max(R,a-A(t)),L=Math.min(k,A(e));if(!(P<=L))return S;let D=Wl(E=>Math.min(y,Vn(e,E)-T)+Math.min(y,Vn(t,a-E)-T),P,L);return Math.max(S,w(e.cap(D),t.cap(a-D),T))}}}var Zf=e=>Math.max(e.xNoLock,e.xLock),Jf=e=>Math.max(e.mixedMax,2*e.xLock);function oa(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 aa(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 Ks(e,t,r,n){return e.shares?IL(e,e.shares,t,r,n):_L(e,t,r,n)}function zv(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 IL(e,t,r,n,o){let a=Jf(r),s=Jf(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=aa(r,t.front*b),y=aa(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}=zv(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 _L(e,t,r,n){let o=Zf(t),a=Zf(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 C=.5*(M+F);v(e.demand(C,n))?M=C:F=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),f=Number.isFinite(e.uMax)&&m>=e.uMax,p=v=>{let x=e.demand(v,n),M=oa(t,s(x),x.regenFront),F=oa(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}=zv(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 wr={regen:!0,regenEfficiency:.6};function Cr(e,t){let r=e.energy??t??wr;return{regen:r.regen===!0,regenEfficiency:Math.min(1,Math.max(0,Number.isFinite(r.regenEfficiency)?r.regenEfficiency:0))}}function Tr(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 Yv(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 mt(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 jl(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 Hs(e,t,r){return r.map(n=>mt(e,t,n))}var zs=e=>e.reduce((t,r)=>r>t?r:t,-1/0),sa=e=>e.reduce((t,r)=>r<t?r:t,1/0);var NL=[-.906179845938664,-.538469310105683,0,.538469310105683,.906179845938664],OL=[.236926885056189,.478628670499366,.568888888888889,.478628670499366,.236926885056189];function rh(e,t,r){let n=.5*(r-t),o=.5*(t+r),a=0;for(let s=0;s<5;s++)a+=OL[s]*e(n*NL[s]+o);return n*a}var VL=Math.PI*2,BL=.5/3.6;function Ys(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 nh(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*VL;c[g]=y*o/n,l[g]=s[g]*n/o}let u=zs(c),m=Tr(sa(c),u,u/BL),f=Hs(c,l,m),{front:p,rear:d}=Ys(t,r),h=f.map(g=>g*p),b=f.map(g=>g*d);return{vVehicle:m,fFront:h,fRear:b,vMax:u}}var Wv=60/(2*Math.PI),jv=.1,Uv=.08,Xv=0;function oh(e){let t=(r,n)=>r===void 0||!Number.isFinite(r)?n:Math.max(0,r);return{up:t(e.upshiftTime,jv),down:t(e.downshiftTime,Uv)}}function ah(e){let t=e.driveKept;return t===void 0||!Number.isFinite(t)?Xv:Math.max(0,Math.min(1,t))}function sh(e,t,r){let{primary:n,ratios:o,efficiency:a}=e.gearbox,s=t>0&&r>0&&n>0,i=(b,g)=>b/Wv*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,Be(e.rpm,e.torque,b)),f=(b,g)=>{let y=c[g];return y?b*y.ratio/r*Wv: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 ia(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 qv=9.81,Qv=Math.PI*2;function Ft(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]*(Qv/60),a[v]=t[v]/60*Qv,s[v]=a[v]*u/l,i[v]=r[v]*l,c[v]=i[v]/u;let m=zs(s),f=m,p=.5/3.6,d=Tr(sa(s),m,m/p),h=Hs(s,c,d),b=Tr(sa(t),zs(t),250),g=Hs(t,o,b).map(v=>v*e.power_scale.value),y,R=f,k;if(e.motorModel?.kind==="ice"){k=sh(e.motorModel,l,u);let v=Tr(0,k.vMax,Math.max(2,Math.ceil(k.vMax/p)+1)),x=v.map(w=>ih(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=nh(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:qv,FG:e.m.value*qv,vMax:R,vVehicle:d,fRad:h,uMotor:b,pMotor:g,vRad:s,fAxle:y,...k?{engine:k}:{}}}var an=e=>e.motorModel?.kind==="ice"?Ys(1,e.motorPlacement==="front"?"front":"rear"):Ys(Math.max(1,Math.round(e.motorCount??e.driven_wheels?.value??2)),e.motorPlacement??"rear");function Zv(e){let t=an(e);return t.front>=2||t.rear>=2}function Jv(e){return Zv(e)?e.motorMount??"hub":"chassis"}function ch(e){if(!e.motorModel)return{front:!1,rear:!0};let t=an(e);return{front:t.front>0,rear:t.rear>0}}function lh(e){let t=an(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=Jv(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 pt(e){return qf(e.brakeModel,e.brakeSetup)}function Ul(e){return Fr(e.brakeSetup).ideal?"tyre":e.brakeModel||e.brakeModelId?"hydraulic":"balance"}function e1(e,t){if(!(ft(e.motorModel)||!Cr(e).regen))return Gs(Xl(Ft(e)),t??pt(e).regen)}function Xl(e){return e.fAxle??{vVehicle:e.vVehicle,fFront:e.vVehicle.map(()=>0),fRear:e.fRad.map(t=>t*e.params.driven_wheels.value)}}function uh(e,t=pt(e)){if(t.mode==="hydraulic")return $s(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 mh(e,t=pt(e)){return{front:t.hydraulic.front.location==="inboard",rear:t.hydraulic.rear.location==="inboard"}}function ph(e){let t=pt(e);return{brakeBalanceFront:uh(e,t),brakeInboard:mh(e,t)}}function t1(e,t=pt(e)){if(t.mode==="tyre"||t.regen.distribution!=="wheel"||ft(e.motorModel))return;let r=an(e),n={front:r.front>=2,rear:r.rear>=2};return n.front||n.rear?n:void 0}function Ws(e){let t=pt(e),r=e.r_dyn.value,n=mh(e,t),o=uh(e,t),a=t1(e,t),s=t.mode==="hydraulic"||a?e1(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 GL=9.81;function dh(e,t){if(ft(e.motorModel))return()=>0;let r=pt(e),n=Gs(t,r.regen);if(r.mode==="hydraulic"){let a=On({mode:"hydraulic",balanceFront:$s(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"?KL(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,Ar(n.v,n.front,s))+Math.min((1-c)*a,Ar(n.v,n.rear,s))}}function KL(e){let t=e.m.value*GL,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 r1(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 fh={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"},...r1("front"),...r1("rear")},hh={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 bh(e){let t=fh[e];return`${t.label}, ${t.section}`.toLowerCase()}function gh(e){let t=hh[e];return t.section?`${t.section} ${t.label.charAt(0).toLowerCase()}${t.label.slice(1)}`:t.label}var n1=new WeakMap;function nr(e){if(e.brakes)return e.brakes;let t=n1.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},n1.set(e,t)}return t}var Pr=e=>On(nr(e));var WL=Math.PI/180,ca=Object.freeze({tbr:1,preloadN:0}),ql=Object.freeze({tbr:1/0,preloadN:0}),xh=e=>e.faces*e.muClutch*e.rFrictionMm/e.rRampMm;function Rh(e,t){if(!(e>0)||Number.isNaN(t))return 0;let r=Math.tan(Math.min(90,t)*WL);return r>0?Math.min(1,e/r):1}function a1(e){if(e>=1)return 1/0;let t=e>0?e:0;return(1+t)/(1-t)}function Ql(e){return e===1/0?1:e>1?(e-1)/(e+1):0}function la(e,t){return e.tbr===1/0?1/0:(e.preloadN>0?e.preloadN:0)+Ql(e.tbr)*Math.abs(t)}function Us(e,t,r){let n=o=>o!==void 0&&o>0&&r>0?o/r:0;switch(e.kind){case"open":return ca;case"spool":return ql;case"independent":return t==="hubs"?ca:ql;case"clutch":{let o=n(e.preloadNm);return t==="hubs"?{tbr:1,preloadN:o}:{tbr:a1(Rh(xh(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 js(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 o1=4;function yh(e,t){let r=0;for(let a of e)r=Math.max(r,js(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,js(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 Xs(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=eh(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=Wl(b=>Vn(e,b)+Vn(t,c-b),l.lo,l.hi),f=[{m1:l.c1,m2:l.c2}];for(let b=1;b<=o1&&m!==l.y1;b++){let g=l.y1+(m-l.y1)*b/o1;f.push({m1:e.cap(g),m2:t.cap(c-g)})}let p=yh(f,ca),d=yh(f,ql);if(!(d>p))return u;let h=(yh(f,{tbr:s,preloadN:i})-p)/(d-p);return Math.min(a,u+(a-u)*Math.min(1,Math.max(0,h)))}function s1(e,t,r,n,o,a){return vh(e,o,Xs(t,r,n,o,a))}function vh(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 kh(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 i1(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 l1(e,s,c,d,h,b,n,l,a);s=d,c=b}return null}function c1(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 l1(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 l1(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 Zl(e,t){return Math.abs(e.fx-e.x)>t?e.x:e.fx}var jL=(e,t)=>{let r=e.brakes?.hydraulic?.[t];return!!r&&r.location==="inboard"&&r.discs===1};function Bt(e,t,r){let n=e.driveline?.[t];if(n)return r>=0?n.drive:jL(e,t)?n.coast:n.hubs}var u1=e=>e.tbr>1||e.preloadN>0;var UL=9.81,m1=["FL","FR","RL","RR"],Mh=e=>e==="FL"||e==="FR",Jl=e=>Mh(e)?"front":"rear",p1={front:["FL","FR"],rear:["RL","RR"]},Zs=()=>({peak:new Map,freeBrake:new Map}),Qs=25;function qs(e,t){let r=Math.max(0,e)/Qs,n=Math.floor(r),o=r-n,a=t(n);return o>0?a+o*(t(n+1)-a):a}var sn=1e-4,XL=.05;function Lr(e,t,r,n=Zs(),o=!1){let a=r,s=e.massTotal,i=n.peak,c=(S,A)=>{let P=`${S}:${A}`,L=i.get(P);return L||(L=pl(ge(t,S),Math.max(1,A*Qs)),i.set(P,L)),L},l=(S,A)=>({aPeak:qs(A,P=>c(S,P).aPeak),fyPeak:qs(A,P=>c(S,P).fyPeak)}),u=n.freeBrake,m=(S,A)=>{let P=`${S}:${A}`,L=u.get(P);if(L===void 0){let D=Math.max(1,A*Qs);L=St(ge(t,S),D,0,!0,c(S,A)),u.set(P,L)}return L},f=(S,A)=>A>0?qs(A,P=>m(S,P)):0,p=Pr(e),d=nr(e),h=S=>d.regen&&d.regenPerWheel?.[S]?Ar(d.regen.v,d.regen[S],a)/2:0,b=h("front"),g=h("rear"),y=(S,A,P)=>{let L=Math.max(0,A[S]),D=l(Jl(S),L);return St(ge(t,Jl(S)),L,P[S]*D.fyPeak,!0,D)},R=(S,A,P,L,D=!0)=>{let E=te=>{let fe=Math.max(0,A[te]),W=ge(t,S),J=l(S,fe);return{Fz:fe,a:Math.abs(f(S,fe)),b:J.fyPeak,slide:fe>0?Math.abs(W.forces({Fz:fe,kappa:-1,alpha:0}).Fx):0,cap:re=>Math.abs(St(W,fe,re,!0,J))}},V=te=>Math.abs(P[te])*l(Jl(te),Math.max(0,A[te])).fyPeak,[N,z]=p1[S],I=E(N),_=E(z),B=V(N)+V(z),O=th(I,_,B,L,S==="front"?b:g),G=D?O:{...O,xLock:0},K=Bt(e,S,-1),Y=K&&u1(K)?K:void 0;if(!Y)return{axle:S,eq:G,cap:G};let j=Number.isFinite(L)?L:I.cap(V(N))+_.cap(V(z)),Z=s1(G,I,_,B,Y,j);return{axle:S,eq:G,cap:Z,law:Y,strong:()=>I.cap(V(N))>=_.cap(V(z))?N:z}},k=(S,A,P,L)=>R(S,A,P,L).cap,v=(S,A,P)=>{let L=S.demand,D=p.shares?aa(A,L.front):oa(A,(L.front-L.regenFront)/2,L.regenFront),E=p.shares?aa(P,L.rear):oa(P,(L.rear-L.regenRear)/2,L.regenRear);return{front:Number.isFinite(D)?D:0,rear:Number.isFinite(E)?E:0}},x=S=>({muX:A=>A>0?Math.abs(f(S,A))/A:0,muY:A=>A>0?l(S,A).fyPeak/A: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},C=(S,A,P,L,D)=>{let E=L.cap,V=D.cap,N=Ks(p,E,V,a),z={arms:F,halfTrack:w,ayDir:Math.sign(S)};for(let I=0;I<2;I++){let _=v(N,E,V),B={};for(let G of m1){let K=Math.max(0,A[G]);B[G]={Fz:K,Fy:Math.abs(P[G])*l(Jl(G),K).fyPeak,Fx:-(Mh(G)?_.front:_.rear)/2}}let O=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 vh(G.eq,G.law,El(K,B,M,z))};E=O(L),V=O(D),N=Ks(p,E,V,a)}return{limit:N,front:E,rear:V}};return{peakAt:l,axle:k,ceiling:(S,A,P)=>{let[L,D]=p1[S];return Math.abs(y(L,A,P)+y(D,A,P))},limitAt:(S,A,P,L=0)=>{let D={FL:0,FR:0,RL:0,RR:0},E=we(e,S,0,a,0,A),V,N=fe=>(V?.ax!==fe&&(V={ax:fe,loads:we(e,S,(fe+L)/UL,a,0,A)}),V.loads),z=dl(fe=>qo(P,N(fe),E,l).short,-L,-1),I=P,_={front:0,rear:0},B,O,G=(fe,W=!0)=>{let J=z.at(fe);D=N(J),I=qo(P,D,E,l).util;let re=0,pe=0,de=0;for(let ie of m1){let oe=y(ie,D,I);re+=oe,Mh(ie)?pe+=oe:de+=oe}if(_={front:Math.abs(pe),rear:Math.abs(de)},p.mode!=="tyre"){let ie=R("front",D,I,Math.abs(pe),W),oe=R("rear",D,I,Math.abs(de),W);if(o&&(ie.law||oe.law)){let ue=C(S,D,I,ie,oe);B=ue.limit,O={front:ue.front,rear:ue.rear}}else B=Ks(p,ie.cap,oe.cap,a),O={front:ie.cap,rear:oe.cap};re=-B.force}return re/s},K=kh(G,0,sn),Y=Zl(K,sn),j=Y;if(B?.lockFront||B?.lockRear){let fe=kh(J=>G(J,!1),0,sn);j=Zl(fe,sn);let W=i1(G,fe.x,K.x,sn,XL);W||G(K.x),Y=Zl(W??K,sn)}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:O};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 tu=9.81;function qL(e,t,r){let n=we(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 h1=(e,t)=>t.mode==="hydraulic"&&!!nr(e).regen;function ua(e,t,r=0,n,o=0){if(!e.brakes&&e.brakeBalanceFront==null)return e.frontMassFrac;let a=Pr(e);if(a.shares&&a.mode!=="tyre")return a.shares.front;let s=n&&h1(e,a)?b1(e,n):void 0,i=s?.shares??d1.get(e);i||d1.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=g1(c,l,u),f=i.get(m);if(f===void 0){let p=-c*.005,d=l*.25,h=e.massTotal*Math.abs(p)*tu;if(s){let b=x1(a,y1(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"?qL(e,p,d):Qf(a,h,d);i.size>5e4&&i.clear(),i.set(m,f)}return f}var d1=new WeakMap;function ru(e,t,r,n,o=0){let a=Pr(e);if(!h1(e,a))return;let s=Math.round(Math.max(0,r)/(e.massTotal*tu)/.005),i=Math.round(Math.max(0,n)/.25);return x1(a,y1(e,b1(e,t),s,i,Math.round(o/.01)),Math.max(0,r),n)}var f1=new WeakMap;function b1(e,t){let r=f1.get(e);r||f1.set(e,r=new WeakMap);let n=r.get(t);return n||r.set(t,n={ev:t,tyres:Zs(),shares:new Map,rooms:new Map,speeds:new Map}),n}var g1=(e,t,r)=>(r*1001+e)*100003+t;function y1(e,t,r,n,o){let a=g1(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:Lr(e,t.ev,i,t.tyres),dragG:-Math.max(0,Ja(e,i).drag)/(e.massTotal*tu)},t.speeds.set(n,l));let{cap:u}=l,m=we(e,c,-r*.005+l.dragG,i),f=Math.abs(c)*e.massTotal*tu,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 eu(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 x1(e,t,r,n){if(!(r>0))return eu(e,t,1,n);let o=c=>c.front+c.rear,a=e.controlFor(r,n),s=eu(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=eu(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=eu(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},Sh={rel:1e-6,abs:.001,kappa:1e-12,iters:40};function Bn(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)),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=JL(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 R1=1e-6,QL=40,ZL=(3-Math.sqrt(5))/2;function JL(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-R1),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<QL;g++){let y=R1*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),C=(o-u)*w-(o-l)*F;w=2*(w-F),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 S=o+b;(S-r<2*y||c-S<2*y)&&(b=R>=o?y:-y),k=!1}}k&&(h=o>=R?r-o:c-o,b=ZL*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 nu=e=>Math.max(2,.003*Math.abs(e)),eD=(e,t)=>Math.max(t.abs,t.rel*Math.abs(e)),Ah=.5,tD=.03;function rD(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=eD(r,o),c=Math.max(-Ah,Math.min(Ah,n)),l=s(c);if(Math.abs(c)>tD){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)>Ah)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 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 v1(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 Fh(e,t,r,n,o,a=ma){let s=rD(e,t,r,o,a),i=s.fr.Fx-s.fl.Fx,c=la(n,r);if(Math.abs(i)<=c){let R=r-(s.fl.Fx+s.fr.Fx),k=Math.max(0,Math.abs(R)-nu(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=Bn(e.at,u,e.seed||s.kl,a),p=Bn(t.at,m,t.seed||s.kr,a),d=Math.abs(u-f.forces.Fx)>nu(u),h=Math.abs(m-p.forces.Fx)>nu(m),b=Math.max(0,n.preloadN),g=Ql(n.tbr);d&&!h?p=Bn(t.at,v1(f.forces.Fx,l,b,g),p.kappa,a):h&&!d&&(f=Bn(e.at,v1(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)-nu(k))});return{left:y(f,u),right:y(p,m),locked:!1,spoolKappa:s.kappaM}}var nD={front:["FL","FR"],rear:["RL","RR"]},oD=Object.freeze({Fx:0,Fy:0,Mz:0});function ou(e,t,r,n){let o=r;for(let a of["front","rear"]){let[s,i]=nD[a],c=r[s]+r[i],l=Bt(e,a,c);if(!l||!(la(l,c)>0))continue;let u=ge(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}):()=>oD,vx:Math.max(.05,1-b*n.curvature),seed:0}},d=Fh(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,aD=8,sD=1e-6,ln=["FL","FR","RL","RR"],Yt=e=>e==="FL"||e==="FR",cn=e=>Yt(e)?"front":"rear";function ei(e,t){let r=ge(e,"front"),n=ge(e,"rear");return r===n?Gn(r,t):{front:Gn(r,t),rear:Gn(n,t)}}function Gn(e,t){return yf(e,Math.min(t,zt(e)))}var su=e=>e==="FL"||e==="RL";function da(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,ua(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 Eh(e,t,r,n){return Math.abs(Kn(e,t,r,n!==void 0?{steerMaxDeg:n}:{}).peak.steerDeg)}function Ih(e,t,r,n){let o=e.tv;if(!o?.enabled)return 0;let a=K1(o)(t,Math.abs(r),n);return r<0?-a:a}function _h(e,t,r=0,n,o=0,a=0,s){let i=da(e,{axG:t,driveFrontFrac:a},r,n,o),c=i?i.fx:{FL:0,FR:0,RL:0,RR:0};return i&&s&&n?ou(e,n,c,s):c}var ti=e=>su(e)?-1:1,Nh=(e,t,r,n,o)=>t*e.Fy(t*r,n,t*o);function Lh(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 iD(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?Wo(o,n/se,u?r.FL:r.FR,u?r.FR:r.FL):jo(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 Hn(e,t,r){let n=(e.toeFrontDeg??0)*se,o=(e.toeRearDeg??0)*se,a=iD(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 Oh(e,t,r){if(r.Fz<=0)return 0;let n=ut(ge(e,cn(t))),o=ti(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 k1(e,t,r,n){if(!In(e))return null;let o=ut(ge(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:Oh(o,s,i)}}return Ps(e,r/se,a,tn(o.model),{FL:n.FL.travelMm,FR:n.FR.travelMm})}var M1=()=>({totalNm:[],aligningNm:[],lateralNm:[],longitudinalNm:[],jackingNm:[]});function S1(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 cD=Object.freeze({Fx:0,Fy:0,Mz:0});function A1(e,t,r){let n=t==="front"?(r?.FL??0)+(r?.FR??0):(r?.RL??0)+(r?.RR??0),o=Bt(e,t,n);return o&&la(o,n)>0?{F:n,law:o}:null}function wt(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}=Lh(e),h=A1(e,"front",l),b=A1(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=ut(ge(t,"front")),v=ut(ge(t,"rear")),x=e.trackFront/2e3,M=e.trackRear/2e3,F=!!(e.kinFront&&e.kinRear),w=F&&y===null?nn(e,e.kinFront,e.kinRear,r):null,C=NaN,T=null,S=W=>{if(!F)return null;if(y===null)return w;let J=R(W);return J!==C&&(C=J,T=nn(e,e.kinFront,e.kinRear,J)),T},A={},P={FL:0,FR:0,RL:0,RR:0},L=e.kinFront?.compliance,D=e.kinRear?.compliance,E=!!(L||D),V=!!(L?.toePerMz||D?.toePerMz),N=W=>Yt(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}},I=!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=S(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,Ve=ul(e,W/Me,u,ie,n/se,o/se,ue,oe?.steeringJacking),Ae=Ve.loads;I=Ve.overturned;let le=Hn(e,o,ue),Re=le.steer,Ce=0,He=be=>{let Fe=Math.max(0,Ae[be]),xe=ti(be),me=Yt(be)?k:v,Le=N(be),Se=0,ze=0;if(Le){let An=z[be];Se=Le.toePerFy*An.fy+Le.toePerFx*An.fx+Le.toePerMz*An.mz,ze=Le.camberPerFy*An.fy+Le.camberPerFx*An.fx}let Ue=Re[be]+(oe?xe*oe[be].bumpToe*se:0)+xe*Se*se,Kt=Ue-(Yt(be)?re:pe),Sn=(oe?oe[be].camberRoad:0)*se+xe*(le.camber[be]+ze)*se;return{Fz:Fe,mir:xe,t:me,gains:Le,complianceToe:Se,steerK:Ue,slip:Kt,camberRad:Sn}},je=(be,Fe)=>{let xe=y===null?J/r:1/y,me=Yt(be)?f:-p,Le=(su(be)?1:-1)*(Yt(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?ze=>Fe.t.forces({Fz:Fe.Fz,kappa:ze,alpha:Fe.mir*Fe.slip,gamma:Fe.mir*Fe.camberRad}):()=>cD,vx:Math.max(.05,Se),seed:P[be]}};for(let be=0;be<(E?aD:1);be++){Ce=0;let Fe=0,xe={};for(let me of ln){let Le=Yt(me)?h:b;if(Le&&!xe[me]){let[wo,Et]=Yt(me)?["FL","FR"]:["RL","RR"],Ec=He(wo),Ty=He(Et),Py=cn(me),Ip=Fh(je(wo,Ec),je(Et,Ty),Le.F,Le.law,g[Py],Sh);g[Py]=Ip.spoolKappa,xe[wo]={w:Ec,share:Ip.left},xe[Et]={w:Ty,share:Ip.right}}let Se=xe[me]?.w??He(me),{Fz:ze,mir:Ue,t:Kt,gains:Sn,complianceToe:An,steerK:Pp,slip:Lp,camberRad:Dp}=Se,qa=l?.[me]??0,So,Ao=0,Ep=0,Dc=0,Fo=xe[me]?.share;if(Fo)P[me]=Fo.kappa,Ep=Fo.kappa,Ao=Fo.forces.Fx,Dc=Fo.short,So=Ue*Fo.forces.Fy;else if(qa===0||ze<=0)So=Nh(Kt,Ue,Lp,ze,Dp),Dc=ze<=0?Math.abs(qa):0;else{let Et=Bn(Ec=>Kt.forces({Fz:ze,kappa:Ec,alpha:Ue*Lp,gamma:Ue*Dp}),qa,P[me],Sh);P[me]=Et.kappa,Ep=Et.kappa,Ao=Et.forces.Fx,Dc=Math.max(0,Math.abs(qa-Ao)-Math.max(ma.abs,ma.rel*Math.abs(qa))),So=Ue*Et.forces.Fy}if(A[me]={Fz:ze,travelMm:oe?.[me].travel??0,steerRad:Pp,slipRad:Lp,camberRad:Dp,Fy:So,Fx:Ao,kappa:Ep,fxShort:Dc,lifted:Ve.lifted[me]},Sn){let wo=V&&Sn.toePerMz?Oh(Kt,me,A[me]):0;z[me]={fy:-Ue*So,fx:Ao,mz:-Ue*wo*1e3};let Et=z[me];Fe=Math.max(Fe,Math.abs(Sn.toePerFy*Et.fy+Sn.toePerFx*Et.fx+Sn.toePerMz*Et.mz-An))}Ce+=So*Math.cos(Pp)+Ao*Math.sin(Pp)}if(Fe<sD)break}return Ce/d},B=W=>{let J=we(e,0,u,W,0,o/se);return J.FL+J.FR+J.RL+J.RR},O=Math.max(20,3.5*B(r)/d);if(y!==null){O=4*Me;for(let W=0;W<8;W++){let J=Math.min(40*Me,3.5*B(R(O))/d);if(J<=O)break;O=J}O=Math.max(20,O)}let G=W=>_(W)-W,K=Math.max(.001,O*1e-4),Y=(W,J,re,pe)=>{let de=W,ie=re,oe=J,ue=pe,Ve=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),Ce=Math.min(de,ie),He=Math.max(de,ie);Re>Ce&&Re<He||(Re=.5*(de+ie));let je=G(Re);if(Ve=Re,Math.abs(je)<1e-4||He-Ce<1e-6)break;je<0==oe<0?(de=Re,oe=je,ue*=.5):(ie=Re,ue=je,oe*=.5)}return Ve},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),O);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 Ve=pe?O/24:Math.max(O/24,Math.abs(ue-W)/4);for(let Ae=1;Ae<=24;Ae++){let le=ie+re*Ve;if(Math.abs(le)>O)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)<=O){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||(A.RL.Fy+A.RR.Fy)*W<0){let J={...A},re=I,pe=W*Math.max(Z*W+K,n*W*r*r/p),de=null;if(pe*W<O){let ie=G(pe);if(ie*W>0)de=j(pe,ie,W).root;else{let oe=pe+W*O/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(A,J),I=re)}}let fe=f*(A.FL.Fy*Math.cos(A.FL.steerRad)+A.FR.Fy*Math.cos(A.FR.steerRad))-p*(A.RL.Fy+A.RR.Fy);if(s||h||b){let W=J=>(su(J)?1:-1)*(Yt(J)?x:M);for(let J of ln){let re=A[J],pe=Yt(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:A,overturned:I,res:NaN}:{ay:Z/Me,cn:fe/(d*Me*m),wheels:A,overturned:I,res:te-Z}}function lD(e,t,r,n,o,a,s,i=0){let c=20*se,l=.001,u=(h,b)=>{let g=wt(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 C of[v.pos,v.neg]){let T=C===v.pos?1:-1,S=h+T*b[w];if(Math.abs(S)>c)continue;let A=u(S,C.ay);if(Math.abs(A.cn)<F&&m(A.ay)&&(F=Math.abs(A.cn),M=S),A.cn===0&&m(A.ay))return{beta:S,trimmed:!0};if(A.cn<0!=C.cn<0){let P={lo:C.b,hi:S,ayLo:C.ay},L=F1(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=S,C.cn=A.cn,y!==void 0&&(C.ay=A.ay)}return x?{beta:F1(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=uD(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 F1(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 uD(e,t,r,n,o,a,s){let i=(f,p)=>{let d=wt(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<mD;f++){let p=i(c+wh,l),d=i(c,l+Ch),h=(p.r-u.r)/wh,b=(d.r-u.r)/Ch,g=(p.c-u.c)/wh,y=(d.c-u.c)/Ch,R=h*y-b*g;if(!Number.isFinite(R)||R===0||Math.abs(R)<hD*(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,pD/Math.max(Math.abs(k),1e-300),dD/Math.max(Math.abs(v),1e-300));if(c+=x*k,l+=x*v,Math.abs(c-o)>fD||Math.abs(c)>s||l*a<0)return null;u=i(c,l)}return null}var mD=8,wh=1e-5,Ch=.001,pD=1*se,dD=2,fD=5*se,hD=.5;function E1(e,t,r,n,o,a,s,i){let c=wt(e,t,r,n,o,a,s,void 0,i),l=c.ay*Me/r,u={},m=0;for(let d of ln){let h=c.wheels[d],b=ge(t,cn(d)),g=zt(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:Oh(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=Ps(e,o/se,u,tn(ge(t,"front").model),{FL:c.wheels.FL.travelMm,FR:c.wheels.FR.travelMm}),p=Hn(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 Er(e,t,r,n,o,a,s=0){let i=Math.max(8,r),c=$n(e,t,i,n,o,a,s);return n!==0&&o?.driving===void 0&&(c.driving=PD(e,t,i,c,a,s)),c}function $n(e,t,r,n,o,a,s){let i=n*se,c=da(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}=lD(e,t,r,i,u,l,c,s),d=E1(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)<=bD,h}var bD=3;function Kn(e,t,r,n={}){let o=Math.max(8,r),a=n.direction??1,s=n.yawDemandCn??0,i=n.steerMaxDeg??gD,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=Th.get(e)?.get(t)?.get(l);if(x)return x}let u=(x,M)=>M.trimmed&&Math.abs(M.beta-x.beta)<=iu&&Math.abs(M.ay-x.ay)*Me<=cu,m=!1,f=(x,M)=>{let F=$n(e,t,o,a*x,M,c(a*x),s);return u(M,F)?(F.driving=!0,F):(m=F.overturned,null)},p=[$n(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=C=>x.sb*(C.beta-x.state.beta)>0||a*C.steerDeg>=a*x.state.steerDeg||F&&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),d=Math.abs(x.state.steerDeg)},y=(x,M=!1)=>M||wD(p[p.length-1],x)?CD(e,t,o,a,p,x,c,s):null,R=p[0].trimmed?p[0]:null;if(!R){let x=0;for(let M=w1;M<=i&&!R;M+=w1){let F=$n(e,t,o,a*M,void 0,c(a*M),s);if(F.trimmed){let w=M;R=F;for(let C=0;C<6;C++){let T=.5*(x+w),S=$n(e,t,o,a*T,void 0,c(a*T),s);S.trimmed?(w=T,R=S):x=T}}else x=M}R&&(R.driving=!0,p.push(R))}if(R){let x=Math.abs(R.steerDeg),M=Math.min(Ph,100/(o*o)),F=R;for(;x<i;){let w=Math.min(i,x+M),C=f(w,F);if(C){let L=y(C);if(L){g(L);break}if(p.push(C),w>=i||G1(e,a*w))break;Math.abs(C.beta-F.beta)<.5*iu&&Math.abs(C.ay-F.ay)*Me<.5*cu&&(M=Math.min(Ph,1.5*M)),x=w,F=C;continue}if(M>yD){M*=.5;continue}let T=m,S=!1,A=null;for(let L of xD){let D=Math.min(i,x+L);if(D<=x)continue;let E=f(D,F);if(E){if(A=y(E,!0),A)break;p.push(E),x=D,F=E,M=Math.min(Ph,100/(o*o)),S=!0;break}}if(S)continue;if(A){g(A);break}d=x,h=T;let P=T?null:FD(e,t,o,a,p,c,s);P&&g(P);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=Th.get(e);x||(x=new WeakMap,Th.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 Th=new WeakMap,gD=90,iu=1.5,cu=2.5,Ph=5,yD=.002,xD=[.5,1],w1=2.5,I1=.01,Dr=.001,RD=.05,vD=.25,kD=5,MD=2,C1=1e-8,SD=1e-7,AD=1e-6;function _1(e,t,r,n,o,a,s){let i=n*se,c=o.ay*Me,l=b=>{let g=wt(e,t,r,i,b*se,c,da(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)<C1;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)>MD)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)>C1;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>cu?null:{steerDeg:h.x,ay:h.ay}}function Js(e,t,r,n,o){let a=E1(e,t,r,n.beta*se,n.steerDeg*se,n.ay*Me,da(e,o(n.steerDeg),r,t));return{...a,trimmed:!a.overturned,driving:!a.overturned}}function FD(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=N1(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=I1;Math.abs(g.beta-c.beta)<=iu;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=O1(f,n,b,g,R);if(!k)return null;let v=Js(e,t,r,k,a);return!v.trimmed||Math.abs(v.beta-c.beta)>iu||Math.abs(v.ay-c.ay)*Me>cu?null:{state:v,sb:m}}function N1(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=_1(e,t,r,s,i,n,o);if(!c)return null;let l={beta:s,...c};return a.push(l),l}}function wD(e,t){let r=Math.abs(t.beta-e.beta);return r>vD&&r>kD*Math.abs(t.steerDeg-e.steerDeg)}function CD(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=N1(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=I1;f*(a.beta-g.beta)>0;R=Math.min(RD,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=O1(p,n,...y);if(!x)return null;let M=Js(e,t,r,x,s);return M.trimmed?{state:M,sb:f}:null}b=g,g=k}return null}function O1(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*Dr-.5*(i-s))break;let h=!0;if(Math.abs(m)>Dr){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*Dr||i-v<2*Dr)&&(f=d>=c.beta?Dr:-Dr),h=!1}}h&&(m=c.beta>=d?s-c.beta:i-c.beta,f=B1*m);let b=e(Math.abs(f)>=Dr?c.beta+f:c.beta+(f>=0?Dr:-Dr));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 Vh(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 Js(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=_1(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?SD:AD))break;v<0?(m=k,p=v,d*=.5):(f=k,d=v,p*=.5)}return Js(e,t,r,h,i)}function TD(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 Vh(e,t,r,n.fold,a,{steerDeg:o});let u=typeof a.op=="function"?a.op(o):a.op,m=$n(e,t,r,o,l,u,a.yawDemandCn??0);return m.driving?m:null}function PD(e,t,r,n,o,a){if(!n.trimmed)return!1;let s=n.steerDeg<0?-1:1,{states:i}=Kn(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 un(e,t,r,n,o){let a=Math.max(8,r),s=n>=0?1:-1,i=Math.abs(n),c=(b,g)=>Er(e,t,a,s*b,g,o),l=Kn(e,t,a,{direction:s,op:o}),{fold:u}=l;if(u&&Math.abs(u.state.steerDeg)<=pa){if(i>Math.abs(u.state.ay))return P1(e,t,a,s,i,o);if(i>Math.abs(u.stall.ay)){let b=Vh(e,t,a,u,{direction:s,op:o},{ayG:i});if(b)return b}}let m=l.states.filter(b=>Math.abs(b.steerDeg)<=pa),f=m[m.length-1],p=l.states.length>m.length;p&&Math.abs(f.steerDeg)<pa&&m.push(c(pa,f));let d=m.findIndex(b=>Math.abs(b.ay)>=i);if(d===0)return Er(e,t,a,0,void 0,o);if(d>0)return T1(m[d-1],m[d],i,c);let h=V1(m,c,void 0,p||l.foldDeg===null);return h.ay>=i?T1(h.below,h.state,i,c):l.foldDeg!==null&&l.foldDeg<pa?P1(e,t,a,s,i,o):h.state}var pa=20;function T1(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)<=LD||a.steer-o.steer<=DD)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 LD=1e-9,DD=1e-7;function V1(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=ED/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 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,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-ID,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 S=(u-f)*(m-h),A=(u-d)*(m-p),P=(u-d)*A-(u-f)*S;A=2*(A-S),A>0&&(P=-P),A=Math.abs(A);let L=y;if(y=R,Math.abs(P)<Math.abs(.5*A*L)&&P>A*(c-u)&&P<A*(l-u)){R=P/A;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=B1*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,d=f,h=p,f=u,p=m,u=w,m=T,b=C):(w<u?c=w:l=w,T<=p||f===u?(d=f,h=p,f=w,p=T):(T<=h||d===u||d===f)&&(d=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 ED=.001,ID=.01,B1=(3-Math.sqrt(5))/2;function P1(e,t,r,n,o,a){let s=l=>Math.abs(Er(e,t,r,n*l,void 0,a).ay),i=0,c=pa;if(s(c)<o)return Er(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 Er(e,t,r,n*.5*(i+c),void 0,a)}function Bh(e,t,r,n,o){let a=un(e,t,r,n,o);return a.steering?Math.abs(a.steering.totalNm):NaN}function $h(e,t,r,n,o){if(!In(e))return NaN;let a=n<0?-1:1,s=Math.abs(n),i=un(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=Er(e,t,r,a*u,void 0,o),p=Er(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 Dh(e,t,r,n,o,a){let s=Math.max(8,r),i=wt(e,t,s,n*se,o*se,void 0,da(e,a,s,t));return{ay:i.ay,cn:i.cn}}function Gh(e,t,r,n,o){let a=Math.max(8,r),s=un(e,t,a,n,o),i=.5,c=Dh(e,t,a,s.beta+i,s.steerDeg,o).cn,l=Dh(e,t,a,s.beta-i,s.steerDeg,o).cn;return(c-l)/(2*i*se)*e.massTotal*Me*(e.wheelbase/1e3)}function Kh(e,t,r,n){let o=Math.max(8,r),{branch:a,opts:s}=_D(e,t,o,n);return $1(e,t,o,a,s)}function _D(e,t,r,n){if(!e.tv?.enabled){let s=n?{op:n}:{};return{branch:Kn(e,t,r,s),opts:s}}let o=Eh(e,t,r),a={op:s=>{let i=Ih(e,r,s,o);return i===0?n:{axG:n?.axG??0,driveFrontFrac:n?.driveFrontFrac,tvRearDiffN:i}}};return{branch:Kn(e,t,r,a),opts:a}}function $1(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 Js(e,t,r,n.peak,a);let i=(l,u)=>$n(e,t,r,l,u,a(l),s),c=n.states[0].driving||!n.peak.driving?n.states:n.states.slice(1);return V1(c,i,c.indexOf(n.peak),n.foldDeg===null).state}function Hh(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}=Lh(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&&In(e),R=y?tn(ge(t,"front").model):void 0,k=(I,_,B,O)=>B===1?I:I+(_-I)*O/(B-1),v=e.tv?.enabled?Eh(e,t,a):0,x=I=>{let _=Ih(e,a,I/se,v);return!n.axG&&_===0?null:da(e,{axG:n.axG??0,driveFrontFrac:n.driveFrontFrac,tvRearDiffN:_},a,t)},{lf:M,lr:F}=Lh(e),w=n.reserves?ei(t,e.massTotal*Me*1.2):null,C=I=>w?Rr(w,{FL:I.FL,FR:I.FR,RL:I.RL,RR:I.RR},{lf:M,lr:F}):null,T=[],S={ay:[],cn:[]},A=0;for(let I=0;I<b;I++){let _=k(u,m,b,I),B=x(_),O=[],G=[],K=[],Y=[],j=w?{stabil:[],agil:[]}:void 0,Z=y?M1():void 0,ne;for(let W=0;W<g;W++){let J=k(c,l,g,W),re=wt(e,t,a,J,_,ne,B,o);if(ne=Number.isFinite(re.ay)?re.ay*Me:void 0,O.push(re.ay),G.push(re.cn),K.push(J/se),Y.push(_/se),j){let pe=C(re.wheels);j.stabil.push(pe.stabil),j.agil.push(pe.agil)}Z&&S1(Z,k1(e,t,_,re.wheels)),Math.abs(re.ay)>A&&(A=Math.abs(re.ay))}T.push({label:`\u03B4 ${(_/se).toFixed(0)}\xB0`,ay:O,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=O[W-1]+J*(O[W]-O[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&&(S.ay.push(te),S.cn.push(0))}let P=[];for(let I=0;I<b;I++){let _=k(c,l,b,I),B=[],O=[],G=[],K=[],Y=w?{stabil:[],agil:[]}:void 0,j=y?M1():void 0,Z;for(let ne=0;ne<g;ne++){let te=k(u,m,g,ne),fe=wt(e,t,a,_,te,Z,x(te),o);if(Z=Number.isFinite(fe.ay)?fe.ay*Me:void 0,B.push(fe.ay),O.push(fe.cn),G.push(_/se),K.push(te/se),Y){let W=C(fe.wheels);Y.stabil.push(W.stabil),Y.agil.push(W.agil)}j&&S1(j,k1(e,t,te,fe.wheels))}P.push({label:`\u03B2 ${(_/se).toFixed(0)}\xB0`,ay:B,cn:O,betaDeg:G,deltaDeg:K,reserve:Y,steering:j})}let L=.5*se,D=x(h),E,V;if(o===void 0)E=(wt(e,t,a,d+L,h,void 0,D,o).cn-wt(e,t,a,d-L,h,void 0,D,o).cn)/(2*L),V=(wt(e,t,a,d,h+L,void 0,x(h+L),o).cn-wt(e,t,a,d,h-L,void 0,x(h-L),o).cn)/(2*L);else{let I=(O,G)=>wt(e,t,a,O,G,void 0,x(G),o).cn,_=(O,G,K)=>Number.isFinite(O)?(-3*O+4*G-K)/(2*L):(K-G)/L,B=I(d,h);E=-_(B,I(d-L,h),I(d-2*L,h)),V=_(B,I(d,h+L),I(d,h+2*L))}let N=0;if(D&&D.axG){let I=wt(e,t,a,d,h,void 0,D,o),_=0;for(let B of ln)_+=I.wheels[B].fxShort;N=_/Math.abs(e.massTotal*D.axG*Me)}let z=S.ay.reduce((I,_)=>Math.max(I,Math.abs(_)),0);return{isoBeta:P,isoDelta:T,trim:S,maxAy:A,stability:E,control:V,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 G1(e,t){return Hn(e,t*se).atLock}function ND(e,t,r,n,o=Lr(e,t,r)){let a=r,s=e.massTotal,i=ln.filter(g=>Yt(g)?n.drivenFront:n.drivenRear),c=o.peakAt,l={front:n.drivenFront?Bt(e,"front",1):void 0,rear:n.drivenRear?Bt(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*Qs);k=St(ge(t,g),v,0,!1,c(g,v)),u.set(R,k)}return k},f=(g,y)=>y>0?qs(y,R=>m(g,R)):0,p=(g,y,R,k)=>{let v=ge(t,g),x=D=>{let E=Math.max(0,R[D]),V=c(g,E);return{Fz:E,a:f(g,E),b:V.fyPeak,slide:0,cap:N=>E>0?St(v,E,N,!1,V):0}},[M,F]=g==="front"?["FL","FR"]:["RL","RR"],w=x(M),C=x(F),T=k[M]*w.b,S=k[F]*C.b,A=w.cap(T)+C.cap(S),P=Xs(w,C,T+S,y,A);return{l:M,r:F,full:P,asHeld:()=>({axle:g,strong:w.cap(T)>=C.cap(S)?M:F,full:P,open:Xs(w,C,T+S,ca,A),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=we(e,g,0,a,0,y),M,F=P=>(M?.ax!==P&&(M={ax:P,loads:we(e,g,(P+k)/Me,a,0,y)}),M.loads),w=dl(P=>qo(R,F(P),x,c).short,-k,1),C=R,T=P=>{let L=w.at(P);v=F(L),C=qo(R,v,x,c).util;let D=0,E=n.diffYaw?{fx:{FL:0,FR:0,RL:0,RR:0},axles:[]}:null;for(let V of i){let N=l[cn(V)];if(N){if(su(V)){let B=p(cn(V),N,v,C);D+=B.full,E&&(E.fx[B.l]=E.fx[B.r]=B.full/2,E.axles.push(B.asHeld()))}continue}let z=Math.max(0,v[V]),I=c(cn(V),z),_=St(ge(t,cn(V)),z,C[V]*I.fyPeak,!1,I);D+=_,E&&(E.fx[V]=_)}if(E){let V={};for(let N of ln){let z=Math.max(0,v[N]);V[N]={Fz:z,Fy:C[N]*c(cn(N),z).fyPeak,Fx:E.fx[N]}}for(let N of E.axles)D+=El(N,V,h,b(g))-N.full}return D/s},S=c1(T,-k,sn).fx,A=w.edge();return A!==void 0&&S>A&&(S=A,T(S)),{ax:S,loads:v}}}}var au=.05,L1=.001,D1=16,lu=8;function zh(e,t,r,n){let o=Math.max(lu,r),a=n.nSteer??7,s=e.tv?.enabled?Eh(e,t,o,n.steerMaxDeg):0,i=I=>{let _=Ih(e,o,I,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=Kn(e,t,o,l),m=I=>{let _={},B={};for(let O of ln)_[O]=I.wheels[O].slipDeg*se,B[O]=Math.min(1,I.wheels[O].gripUtil);return{steerDeg:I.steerDeg,ayMs:Math.max(0,I.ay*Me),ayG:I.ay,slip:_,util:B,scrub:I.ay>0?OD(I,e.massTotal):0}},f=null,p=I=>{if(f&&I===f.steerDeg)return m(f);let _=TD(e,t,o,u,I,l);if(_)return m(_);let B=u.states[0];for(let O of u.states)O.steerDeg<=I&&(B=O);return m(B)},d=u.peak.driving&&u.peak.ay>0?$1(e,t,o,u,l):null,h=d?Math.max(0,d.ay*Me):0,b=d?[...u.states.filter(I=>I.steerDeg<d.steerDeg),d]:u.states,g=d?b.findIndex(I=>I.ay*Me>=.995*h):0,y=b[g].steerDeg,{fold:R}=u;if(d&&R&&u.peak===R.state){let I=.995*h/Me,_=u.states.indexOf(R.stall),B=_-1;for(;B>0&&u.states[B].beta===R.stall.beta;)B--;let O=Math.sign(R.stall.beta-u.states[B].beta),G=_;for(;G>0&&u.states[G].ay>=I&&Math.sign(u.states[G].beta-u.states[G-1].beta)!==-O;)G--;u.states[G].ay<I&&(f=Vh(e,t,o,R,l,{ayG:I},u.states.slice(G,_+1)))}if(f)y=f.steerDeg;else if(g>0){let I=b[g-1].steerDeg,_=y;for(let B=0;B<8&&_-I>.001;B++){let O=.5*(I+_);p(O).ayMs>=.995*h?_=O:I=O}y=_}let k=[];for(let I=0;I<(h>0?a:1);I++){let _=I/(a-1);k.push(p(y*(_+Math.sin(Math.PI/2*_))/2))}k[0].ayMs=0;let v=[],x=[],M=[],F=[],w=Lr(e,t,o,void 0,n.diffYaw===!0),C=ND(e,t,o,n,w),T=n.axDrag??0,S=I=>{let _=w.limitAt(I.ayMs/Me,I.steerDeg,I.util,T+I.scrub);return{axD:_.edge!==void 0&&_.edge>0?_.edge:_.ax,locked:_.axUnlocked-_.ax>au}},A=I=>C.limitAt(I.ayMs/Me,I.steerDeg,I.util,T+I.scrub).ax,P=k.map(I=>({p:I,axA:A(I),...S(I)})),L=[];for(let I=0;I+1<P.length;I++){let _=P[I],B=P[I+1],O=[];_.locked!==B.locked?O.push({read:S,past:G=>G.locked===B.locked,braking:!0}):(B.axA>_.axA+au&&O.push({read:G=>({axA:A(G)}),past:G=>(G.axA??-1/0)>_.axA}),-B.axD>-_.axD+au&&O.push({read:S,past:G=>-(G.axD??0)>-_.axD}));for(let{read:G,past:K,braking:Y}of O){let j=_.p.steerDeg,Z=B.p.steerDeg,ne=null,te=_.axD,fe=B.axD;for(let W=0;W<D1&&Z-j>L1&&!(Y&&Math.abs(fe-te)<=au);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}:S(W);L.push({p:W,axA:J.axA??A(W),...re})}}}P.push(...L),P.sort((I,_)=>I.p.steerDeg-_.p.steerDeg);let D=I=>I.axA+T+I.p.scrub,E=.001*Math.max(1,k[k.length-1].ayMs),V=[];for(let I=0;I+1<P.length;I++){let _=P[I],B=P[I+1];if(!(D(_)>=0&&D(B)<0))continue;let O=_.p.steerDeg,G=B.p.steerDeg,K=null,Y=null;for(let Z=0;Z<D1&&G-O>L1;Z++){let ne=.5*(O+G),te=p(ne);D({p:te,axA:A(te)})>=0?(O=ne,K=te):(G=ne,Y=te)}let j=K??Y;j&&j.ayMs>_.p.ayMs&&j.ayMs<B.p.ayMs&&V.push({p:j,axA:-(T+j.scrub),steady:!0,...S(j)})}P.push(...V),P.sort((I,_)=>I.p.steerDeg-_.p.steerDeg);let N=!1;for(let{p:I,axA:_,axD:B,steady:O}of P){let G=v.length-1,K=G>=0&&(O||N?!(I.ayMs>v[G]):I.ayMs-v[G]<E);N=O===!0&&!K,K?(x[G]=Math.max(x[G],_),M[G]=Math.min(M[G],B)):(v.push(I.ayMs),x.push(_),M.push(B),F.push(I.scrub))}for(let I=v.length-2;I>=0;I--)x[I]=Math.max(x[I],x[I+1]),M[I]=Math.min(M[I],M[I+1]);return{ayMax:v[v.length-1],ay:v,axAccel:x,axDecel:M,axScrub:F,rollover:u.rollover,atLock:d!==null&&G1(e,d.steerDeg)}}function OD(e,t){let r=e.beta*se,n=0;for(let o of ln){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 wj=Math.PI/180,Cj={speeds:Array.from({length:23},(e,t)=>8+t),steerMaxDeg:14,steerSteps:29};function H1(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},K1=e=>H1(e.ffLow,e.ffHigh,e.vLow,e.vHigh);var or={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"}},VD=["k_yaw","k_roll","k_pitch"];function ri(e){for(let t of VD)delete e[t];for(let t of Object.keys(or)){let r=e[t];if(!r){e[t]={...or[t]};continue}e[t]={...r,label:or[t].label,unit:or[t].unit}}return e}function Q(e,t){return e[t]?.value??or[t].value}function uu(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 z1=[10,25,50,100,200,300];function Yh(e,t,r,n,o){let s=z1.map(i=>Math.round(i<=25?r*i:r*25+n*(i-25)));return{id:e,label:t,speedMmS:[...z1],reboundN:s,bumpN:s.map(i=>Math.round(i*o))}}var mu={name:"Generic FS damper",curves:[Yh("c1","Soft",1.6,1,.65),Yh("c2","Medium",3,1.6,.65),Yh("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 mn=25;function ha(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 Y1(e,t){return t>=0?ha(e.rebound,t):-ha(e.bump,-t)}function W1(e,t,r){return t*Y1(e,t*r)}var Wh=(e,t)=>e.curves.find(r=>r.id===t);function ni(e,t){let r=Wh(e,pu(e)),n=(t&&Wh(e,t.bump))??r,o=(t&&Wh(e,t.rebound))??r;return{bump:{speedMmS:n?.speedMmS??[],forceN:n?.bumpN??[]},rebound:{speedMmS:o?.speedMmS??[],forceN:o?.reboundN??[]}}}var du=5e3;function oi(e,t){let r=t>0?t:1,n=[],o=[],a=e.bump.speedMmS.map(c=>c/r).filter(c=>c<du),s=e.rebound.speedMmS.map(c=>c/r).filter(c=>c<du),i=c=>{n.push(c),o.push(W1(e,r,c))};i(-du);for(let c=a.length-1;c>=0;c--)i(-a[c]);i(0);for(let c of s)i(c);return i(du),{kind:"map",input:"velocity",x:n,y:o}}var jh=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<jh;s++){let i=Math.sin((s+.5)*Math.PI/jh),c=n*o*i;a+=n*(ha(e.rebound,c)+ha(e.bump,c))*i}return a*(Math.PI/jh)/(Math.PI*o)}function zn(e,t,r,n,o=e){let a=(c,l,u)=>{if(!c||c.curves.length===0)return;let m=ni(c,l);return{law:m,curve:oi(m,u),rate:ai(m,u,mn)}},s=a(e,t?.front,r),i=a(o??e,t?.rear,n);return!s&&!i?null:{...s?{front:s}:{},...i?{rear:i}:{}}}var j1=(e,t)=>({...e,y:e.y.map(r=>r*t)}),BD=e=>({...e,x:e.x.map(t=>-t).reverse(),y:e.y.map(t=>-t).reverse()});function Uh(e,t,r){let n=Math.abs(r)>0?Math.abs(r):1,o=ni(e,t);return{law:o,curve:j1(oi(o,n),.5),rate:ai(o,n,mn)/2,mr:n,ratio:n,share:.5}}function Xh(e,t,r,n,o){let a=n*(Math.abs(r)>0?Math.abs(r):1),s=ni(e,t),i=j1(oi(s,a),1/n);return{law:s,curve:o?BD(i):i,rate:ai(s,a,mn)/n,mr:a/n,ratio:a,share:1/n}}function si(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}:{}}}function ii(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 Ir(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 li(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 X1(e){return ci(e)/2}function q1(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 U1(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 $D(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 ui(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=X1(e.armSection??e.section),i=3*e.E*s/n**3,c=e.dropLinkRate??1/0;return{rateAtLink:U1([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*q1(e.blade)/n**3,i=e.dropLinkRate??1/0;return{rateAtLink:U1([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=Ir(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=$D(e.linkTravel,e.force,t);return{rateAtLink:Math.max(0,n),contributions:{},torsional:0}}}}function fu(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?Dd(t,r):1,o=t?Ed(t,r):0,a=ui(e,o).rateAtLink;return{wheelRate:Math.max(0,a*n*n),motionRatio:n,rateAtLink:a}}function mi(e,t){let r=e.damper??0;return!r||e.design.kind==="none"?0:li(e.design)*r*t*t}var GD=150;function KD(e){return X(e,[0,-.5,1])<-1e-9?U(e,-1):e}function Q1(e){let t=e.hardpoints,r=H(t.rockerPivotB,t.rockerPivotA),n=ee(t.rockerPivotA,U(H(t.rockerToDamper,t.rockerPivotA),.6)),o=KD(q(ae(r,H(t.rockerToDamper,t.rockerPivotA))));return{outer:n,inner:ee(n,U(o,GD)),attach:"rocker"}}function Ct(e,t){let r={};for(let o of Oo)r[o]=tt($e(e,o));let n={vehicle:e,ctx:r};return t&&(n.kc=il(n,t)),n}var hu=.5;function HD(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 Z1=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:ye(o,r.travel,r.steer,void 0,a),i=r.state??at(s),c=ye(o,r.travel+hu,r.steer,void 0,a),l=ye(o,r.travel-hu,r.steer,void 0,a),u=(s?s.ok:r.converged)&&c.ok&&l.ok,m=at(c),f=at(l),p=(C,T)=>Nt(C.points[T],n),d=o.inv.strut?"pushrodOuter":"uprightUpper",h=p(i,d),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=>HD(R,[p(C,d),p(C,"uprightLower"),p(C,y)]),v=k(m),x=k(f),M=Z1(v.rot),F=Z1(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*hu)):w,omega:u?U(H(M,F),1/(2*hu)):w}}function qh(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 J1(e,t,r){let n=bu(e,t,gt(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 ek(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 tk(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 zD(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 YD=.1*Math.PI/180;function rk(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]))*YD<=o*n}function gu(e,t){return!e.valid||!e.cpLeft||!e.cpRight?!1:rk([e.lateral,e.height],e.cpLeft,e.cpRight,e.sinAngle,t)}function pi(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 WD=1;function nk(e){let t=pi(e);if(!t||!e.cpLeft||!e.cpRight||Math.abs(t.left-t.right)>WD)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 ba(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 ar(e,t,r){let n=r==="front"?"FL":"RL",o=r==="front"?"FR":"RR",a=J1(e,n,t),s=J1(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=ek(a),c=ek(s),l=tk(a,i),u=tk(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=qh(a.cp,f,s.cp,p)??zD(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,C=(g[0]-M)*v+(g[1]-F)*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 _r(e,t){return{front:ar(e,t,"front"),rear:ar(e,t,"rear")}}function yu(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 jD(e,t){return{camber:yu(e.travel,e.camber,t),toe:yu(e.travel,e.toe,t),motionRatio:yu(e.travel,e.motionRatio,t),damperLen:e.damperLen?yu(e.travel,e.damperLen,t):0}}var ok=e=>jD(e,0).motionRatio;function Qh(e,t){if(e.kind!=="coil")return null;let r=t??e.motionRatio,n=Ir(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 xu(e,t){if(e.kind==="none")return 0;if(e.kind==="tabulated"){let n=a=>UD(e,a);return(n(.5)-n(-.5))/(2*.5)/2}if((e.gap??0)>0)return 0;let r=t??e.motionRatio;return Ir(e.rate,0)*r*r/2}function di(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 UD(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 Zh={kind:"coil",rate:120,motionRatio:.7,gap:5,bothWays:!1};var ak=new WeakMap;function vu(e,t){let r=ak.get(e);r||(r=new Map,ak.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=wn(e,t);return r.set(n,a),a}var XD=32,fi=new Map,sk=new WeakMap,qD=1;function QD(e){let t=sk.get(e);return t===void 0&&(t=qD++,sk.set(e,t)),t}function Jh(e,t){if(!t.linkage)return null;let r=en(e,t.linkage,t.design.kind),n=`${QD(e)}|${r?"unit":"bar"}|${JSON.stringify(t.linkage)}`,o=fi.get(n);if(o)return o;let a=Ho(e,t.linkage,{kind:t.design.kind});return fi.size>=XD&&fi.delete(fi.keys().next().value),fi.set(n,a),a}function Wn(e,t,r=0){let n=(o,a)=>{if(!(!o||o.design.kind==="none"))return fu(o.design,Jh(a,o),r).wheelRate};return{front:n(t.arbFrontDesign,e.front),rear:n(t.arbRearDesign,e.rear)}}function ga(e,t){let r=(n,o)=>{if(!n||n.design.kind==="none")return;let a=n.linkage?vu(o,n.linkage).atDesign:void 0;return xu(n.design,a)};return{front:r(t.heaveFrontDesign,e.front),rear:r(t.heaveRearDesign,e.rear)}}function mk(e,t){let r=(a,s)=>{if(!a||a.design.kind!=="coil")return;let i=a.linkage?vu(s,a.linkage).atDesign:void 0;return Qh(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?di(o,eb(o,a)):0,n=(o,a)=>o?mi(o,tb(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 eb=(e,t)=>e.linkage?vu(t,e.linkage).atDesign:void 0,tb=(e,t)=>fu(e.design,Jh(t,e),0).motionRatio;function pk(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=eb(f,p);if(di(f,h)>0)return Uh(n,r?.[d],h??(f.design.kind==="coil"?f.design.motionRatio:1))},s=(f,p,d)=>{if(!f||!o?.curves.length)return;let h=tb(f,p);if(!(mi(f,h)>0))return;let b=Jh(p,f)!==null;return Xh(o,r?.[d],h,li(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 dk(e,t){let r=t.heaveDamperModel??t.damperModel,n=t.rollDamperModel??t.damperModel,o=(i,c)=>Yn(i)?{source:"none"}:ii(i.config.coilover,c),a=(i,c)=>{if(!i)return{source:"none"};let l=di(i,eb(i,c))>0;return ii(i.coilover,l?r:void 0)},s=(i,c)=>{if(!i||i.design.kind!=="coil")return{source:"none"};let l=mi(i,tb(i,c))>0;return ii(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 fk(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 Yn=e=>e.config.actuation==="decoupled",jn="a decoupled axle damps in its heave and roll elements, set below";function hk(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}=Wn(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?vu(f,m.linkage).atDesign:void 0;o(p,xu(m.design,d))}let i=JD(e,t,r),c=ZD(e,i);n.kinFront=c.kinFront,n.kinRear=c.kinRear;let l=rE(e,i);n.steerFront=c.steerFront,Number.isFinite(l.ackermannPct)&&o("ackermann_pct",l.ackermannPct);let u=m=>Yn(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"]])Yn(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"]])Yn(m)&&(o(f,0),n.readouts={...n.readouts,[f]:jn});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 ZD(e,t){return{kinFront:ck(e.front),kinRear:ck(e.rear),steerFront:e.front.measured?void 0:Mu(e.front,t)}}var ik=new WeakMap;function ck(e){let t=ik.get(e);return t||ik.set(e,t=ea(e)),t}function JD(e,t,r={}){return eE(e,t,r.front,r.rear)}function eE(e,t,r,n){let o=e.front.config.loadedRadius;if(!((tr(r??t.tireModel)??0)>0))return o;let a={...t,surveyedRadiusFront:o,surveyedRadiusRear:e.rear.config.loadedRadius};return Su(a,r,n).front??o}var lk=new WeakMap;function Mu(e,t=e.config.loadedRadius){let r=lk.get(e);r||(r=new Map,lk.set(e,r));let n=r.get(t);if(n)return n;let o=t===e.config.loadedRadius?void 0:{loadedRadius:t},a=Qd(e,Ot(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 tE(e){return Ge(e,{travelMin:-1,travelMax:1,steps:3}).samples[1].metrics.motionRatio??1}var Ru=e=>e.measured?ok(e.measured):tE(e);function rE(e,t=e.front.config.loadedRadius){let r=()=>e.front.measured?void 0:Mu(e.front,t);return{...nE(e),get steerFront(){return r()},get ackermannPct(){let n=r();return n?Zd(n,bt(e.front),e.config.wheelbase):Number.NaN}}}function nE(e){let t=uk.get(e);if(t)return t;let r=e.front.measured,n=e.rear.measured,a=!r||!n?_r(Ct(e),{heave:0,pitch:0,roll:0,steer:0}):null,s={wheelbase:e.config.wheelbase,trackFront:r?r.track:bt(e.front),trackRear:n?n.track:bt(e.rear),mrFront:Ru(e.front),mrRear:Ru(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:ba(a.front),rcGainRear:n||!a?0:ba(a.rear),rcFrontValid:r?!0:!!a?.front.valid,rcRearValid:n?!0:!!a?.rear.valid};return uk.set(e,s),s}var xt={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}},yk=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),sr=(e,t,r,n=1/0)=>typeof e=="number"&&Number.isFinite(e)?Math.min(n,Math.max(r,e)):t;function Un(e){if(yk(e))switch(e.kind){case"open":case"spool":return{kind:e.kind};case"clutch":{let t=xt.clutch;return{kind:"clutch",preloadNm:sr(e.preloadNm,t.preloadNm,0),rampDriveDeg:sr(e.rampDriveDeg,t.rampDriveDeg,1,90),rampCoastDeg:sr(e.rampCoastDeg,t.rampCoastDeg,1,90),faces:Math.round(sr(e.faces,t.faces,0)),muClutch:sr(e.muClutch,t.muClutch,0,1),rFrictionMm:sr(e.rFrictionMm,t.rFrictionMm,1),rRampMm:sr(e.rRampMm,t.rRampMm,1)}}case"torsen":{let t=xt.torsen,r=sr(e.preloadNm,0,0);return{kind:"torsen",tbrDrive:sr(e.tbrDrive,t.tbrDrive,1),tbrCoast:sr(e.tbrCoast,t.tbrCoast,1),...r>0?{preloadNm:r}:{}}}default:return}}function Au(e){if(!yk(e))return;let t=Un(e.front),r=Un(e.rear);return t||r?{...t?{front:t}:{},...r?{rear:r}:{}}:void 0}function hi(e){let t=an(e),r=n=>n>=2?"independent":n===1?"diff":"none";return{front:r(t.front),rear:r(t.rear)}}function bi(e){if(!e.driveline)return;let t=hi(e),r=e.r_dyn.value,n=s=>{if(t[s]!=="diff")return;let i=Un(e.driveline?.[s]);if(!(!i||i.kind==="independent"))return{kind:i.kind,drive:Us(i,"drive",r),coast:Us(i,"coast",r),hubs:Us(i,"hubs",r)}},o=n("front"),a=n("rear");return o||a?{...o?{front:o}:{},...a?{rear:a}:{}}:void 0}var oE={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"}},bk=e=>{let t=e==="front"?"Front":"Rear";return Object.fromEntries(Object.entries(oE).map(([r,n])=>[`${e}.${r}`,{section:t,...n}]))},Fu={...bk("front"),...bk("rear")},gk=e=>e.motorModel?.kind==="ice"?e.motorPlacement==="front"?"front":"rear":null;function xk(e,t){let r=gk(t);if(!(!r||gk(e)===r||t.driveline?.[r]))return{...t.driveline,[r]:{...xt.clutch}}}function $t(e,t,r,n){return e>0?!(r>0)||!Number.isFinite(r)?e:Math.max(1,e-t/r):n}function wu(e,t,r){let n=Math.max(0,Math.min(1,r)),o=$t(e.freeRadius,e.staticLoad,e.tyreRate,e.surveyed),a=$t(t.freeRadius,t.staticLoad,t.tyreRate,t.surveyed);return n*o+(1-n)*a}function ya(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 Nr(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 gi(e,t){if(!e)return sE(t);let r=t-rn(e,0).camber;return r?{...e,camber:e.camber.map(n=>n+r)}:e}function aE(e){return{kinFront:gi(e.kinFront,Q(e,"camber_front_deg")),kinRear:gi(e.kinRear,Q(e,"camber_rear_deg"))}}function sE(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 Rk=9.81,vk=e=>e>1?e/100:e;function xa(e,t,r){let n=t??e.tireModel??Es(),o=r??e.tireModelRear??n,a={grip:Q(e,"grip_scale"),stiffness:Q(e,"stiffness_scale")},s=Il(n,a);return{front:s,rear:o===n?s:Il(o,a)}}function ir(e,t,r){let n=xa(e,t,r),o=Pe(n.front);return ut(n.rear===n.front?o:Sl(o,Pe(n.rear)))}function rb(e,t,r){let n=vk(e.front_mass_diss.value),o=xa(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*Rk*n/2,u=e.m.value*Rk*(1-n)/2,m=(i?a.verticalStiffness():0)||Q(e,"tire_vertical_rate"),f=(c?s.verticalStiffness():0)||Q(e,"tire_vertical_rate"),p=tr(i)??0,d=tr(c)??0,h=e.surveyedRadiusFront&&e.surveyedRadiusRear?wu({freeRadius:p,staticLoad:l,tyreRate:m,surveyed:e.surveyedRadiusFront},{freeRadius:d,staticLoad:u,tyreRate:f,surveyed:e.surveyedRadiusRear},n):void 0,b=e.surveyedRadiusFront?$t(p,l,m,e.surveyedRadiusFront):void 0,g=e.surveyedRadiusRear?$t(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 Su(e,t,r){let n=rb(e,t,r);return{front:n.standingFront,rear:n.standingRear}}function kk(e,t,r){return rb(e,t,r).cgStandingRadius}function dt(e,t,r){let n=vk(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}=rb(e,t,r),g=Ws(e),y=bi(e),R=zn(e.damperModel,e.damperSetup,o,a,e.damperModelRear??e.damperModel),k=e.readouts?.damper_front===jn,v=e.readouts?.damper_rear===jn,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:uu(e),cgHeight:ya(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:iE(e,{Wf:c,Wr:l,tireRate:u,tireRateRear:m,tyreFreeRadius:f,tyreFreeRadiusRear:p,standingFront:h,standingRear:b}),tyreFreeRadius:f,...p!==f?{tyreFreeRadiusRear:p}:{},rcHeightFront:Nr(Q(e,"rc_front"),e.rcRoad?.gainFront,e.rcRoad?.radiusFront,h),rcHeightRear:Nr(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,...aE(e)}}function iE(e,t){let r=(a,s,i,c)=>a??(s>0?$t(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 Cu={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 Mk(e,t=e.batteryModel){if(!t)return e;let r=hr(t),n=(o,a)=>({...o,value:a});return{...e,capacity:n(e.capacity,r.capacityAh),ocv:n(e.ocv,r.voltageAtFull)}}var Ak={damper_front:`the damper part sets it: its front curve at ${mn} mm/s`,damper_rear:`the damper part sets it (the rear's own, where the car names one): its rear curve at ${mn} mm/s`};function Tu(e){let t=!!(e.damperModelId||e.damperModel),r=t||!!(e.damperModelIdRear||e.damperModelRear);return{...t?{damper_front:Ak.damper_front}:{},...r?{damper_rear:Ak.damper_rear}:{}}}function Fk(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=zn(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!==jn&&(i.damper_front=s(e.damper_front,"damper front",a.front.rate/(n*n))),a.rear&&e.readouts?.damper_rear!==jn&&(i.damper_rear=s(e.damper_rear,"damper rear",a.rear.rate/(o*o))),i}var wk={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 Or(e){return!!e&&typeof e=="object"&&"value"in e&&"label"in e}var pE={Batteriekapazit\u00E4t:"pack capacity",Rollwiderstandsbeiwert:"rolling-resistance coefficient"},Tk=e=>pE[e]??e;function Pu(e){let t=[];for(let r of Object.keys(e)){if(r==="motor"||r==="name")continue;let n=e[r];Or(n)&&t.push({key:r,label:Tk(n.label),value:n.value,unit:n.unit})}return t}var dE=[{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"]}],fE=.5,Ck=e=>e==="infinite"?1/0:typeof e=="number"?e:null,hE=e=>/front/.test(e)?e.replace("front","rear"):/rear/.test(e)?e.replace("rear","front"):null,aX=(()=>{let e=wk.rows,t=o=>{let a=hE(o),s=Ck(e[o]?.score),i=a&&e[a]?Ck(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>=fE&&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 nb={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 Pk(e){let t=new Map;for(let a of Pu(e))t.set(a.key,a);let r=new Set,n=[];for(let a of dE){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=Pu(e).filter(a=>!r.has(a.key));return o.length&&n.push({title:"Other",rows:o}),n}var ob={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"},ab={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"},Lk=e=>!!(e.aeroModelId||e.aeroModel);function bE(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 gE=e=>!!(e.batteryModelId||e.batteryModel);function yE(e,t){let r={};return t.geometry&&Object.assign(r,nb,bE(e)),Lk(e)&&Object.assign(r,ob),gE(e)&&Object.assign(r,Cu),Object.assign(r,Tu(e)),e.readouts&&Object.assign(r,e.readouts),r}function Dk(e,t){let r=yE(e,t);return Lk(e)||Object.assign(r,ab),r}function sb(e){let t=e.cop_long;return Or(t)?1-t.value:.5}function xE(e,t){let r=e.front_aero_diss,n=e.cop_long;!Or(r)||!Or(n)||(t===r.label?n.value=1-r.value:t===n.label&&(r.value=1-n.value))}function RE(e,t){xE(e,t);let r=e.c_l,n=e.c_w,o=e.l_to_d_ratio;!Or(r)||!Or(n)||(t===r.label||t===n.label?Or(o)&&n.value!==0&&(o.value=r.value/n.value):Or(o)&&t===o.label&&o.value!==0&&(n.value=r.value/o.value))}function Lu(e,t,r){let n=!1;for(let o of Object.keys(e)){if(o==="motor"||o==="name")continue;let a=e[o];if(Or(a)&&Tk(a.label)===t){a.value=r,n=!0;break}}return n&&RE(e,t),n}function Du(e,t,r=0,n,o){let a=()=>({cl:e.c_l.value,cw:e.c_w.value,frontShare:sb(e),A:e.A.value,platform:null});if(!e.aeroModel)return a();let s=Ur(n??dt(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:sb(e),A:s.area,platform:s}}var Ek=e=>typeof e=="object"&&e!==null&&typeof e.value=="number"&&typeof e.label=="string";function Ik(e,t=e.aeroModel){if(!t)return e;let r=jr(t,{wheelbase:Q(e,"wheelbase")}).at(Q(e,"ride_height_front"),Q(e,"ride_height_rear")),{cl:n,balanceFront:o}=ed(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(Ek(e.cop_long)?e.cop_long:void 0,or.cop_long,1-o)};return Ek(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 yi={dsTarget:.25,accelStep:.25,vTol:.002,scanSteps:24,seamIters:8,fitSpacing:1},vE=32;function _k(e,t,r){let n=Math.round(e/t);return Math.max(1,Math.min(Number.isFinite(n)?n:1,Math.floor(r/vE)||1))}function st(e){let t=yi,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 Nk=Math.PI/180,Eu=.02,Ok=new WeakMap;function xi(e){let t=Ok.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)*Nk,l=(e.bank?.[i]??0)*Nk,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 Ok.set(e,s),s}function Iu(e,t,r){return e.n0[t]+e.k[t]*r*r}function Vk(e,t){return e.k[t]<0?Math.sqrt(Math.max(0,e.n0[t])/-e.k[t]):1/0}function Bk(e,t){if(!e)return null;let r=1/0,n=-1/0;for(let o=0;o<e.n0.length;o++){let a=Iu(e,o,t[o]??0);a<r&&(r=a),a>n&&(n=a)}return r>=1-Eu&&n<=1+Eu?null:{lo:r,hi:n}}var Ra=[.1,.25,.5,.75,1,1.25,1.5,2,2.5];function $k(e){let t=e.lo>=1-Eu?1:1-1.25*(1-e.lo)-.05,r=e.hi<=1+Eu?1:1+1.25*(e.hi-1)+.05,n=[...Ra].reverse().find(a=>a<=t)??Ra[0],o=Ra.find(a=>a>=r)??Ra[Ra.length-1];return Ra.filter(a=>a>=n&&a<=o)}function ib(e,t,r){return r<1?Math.max(e,t):Math.min(e,t)}function Gk(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):ib(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 _u(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}=kE(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:C,tau:T,target:S}=F;d=0,h=0,b=0;for(let A=0;A<s;A++){let P=i(A),L=e[P];for(let V=0;T<=0&&V<n.count;V++){let N=C;if(w<L-1e-9?n.best(w)>C&&(n.rpm(w,C)>=n.limitRpm||c[A]>=w*k)?N=C+1:C>0&&w<n.vIdle(C)&&(N=C-1):L<w-1e-9&&C>0&&n.best(l[A])<C&&n.rpm(w,C-1)<=n.limitRpm&&(N=C-1),N===C)break;S=N,N>C?d++:h++,T=N>C?y:R,T<=0&&(C=S)}u[A]=w,m[A]=C+1,f[A]=n.rpm(w,C);let D=T>0;p[A]=D?1:0;let E=L;if(!D)w<L&&(E=Math.min(L,Math.sqrt(Math.max(0,w*w+2*o(A,w,n.share(w,C))*t[A]))));else if(w<L){let V=o(A,w,g>0?g*n.share(w,C):0),N=Math.min(L,Math.sqrt(Math.max(0,w*w+2*V*t[A]))),z=w+N>0?2*t[A]/(w+N):1/0;if(z<=T)E=N,b+=z,T-=z;else{let I=Math.min(L,Math.max(0,w+V*T)),_=Math.max(0,t[A]-(w+I)*.5*T);b+=T,T=0,C=S,E=Math.min(L,Math.sqrt(Math.max(0,I*I+2*o(A,I,n.share(I,C))*_)))}}else{let V=w+E>0?2*t[A]/(w+E):0;b+=Math.min(V,T),T-=V,T<=0&&(C=S)}w=E}return{v:w,gear:C,tau:T,target:S}},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),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 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 kE(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 cb=.001,lb=9.81,Ri=(e,t)=>Nu(e?.gradient?.[t]??0);function Nu(e){return e===0?0:-lb*Math.sin(e*Math.PI/180)}function dn(e,t){let r=new Array(t);for(let n=0;n<t;n++)r[n]=Nu(e?.[n]??0);return r}var pn=(e,t)=>{let r=e?.mu?.[t];return r!=null&&r>0?r:1},Xn=(e,t)=>e?.bank?.[t]??0;function ME(e,t,r,n,o,a){let s=e.ay(t,r,pn(o,a)),i=Xn(o,a);if(!i)return s;let c=i*Math.PI/180,l=n===0?0:-Math.sign(n)*lb*Math.sin(c);return Math.max(0,(s+l)/Math.cos(c))}function Ke(e,t){if(!t)return e;let r=t*Math.PI/180;return e*Math.cos(r)+lb*Math.sin(r)}function ub(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 qn=(e,t,r)=>t?t(r):e,SE=1e-4;function va(e,t,r,n,o,a,s){let i=st(r),c=[];for(let l=0;l<t.length;l++){let u=t[l],m=Math.abs(u),f=qn(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:ub(b=>b*b*m-ME(f,b,0,u,n,l),cb,d,i.scanSteps,Math.min(i.vTol,SE));c.push({v:h,ax:0,ay:h*h*u})}return c}function AE(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=Ke(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=ub(p=>u(p)-t.v,cb,r.v,a.scanSteps,a.vTol),r.ay=r.v*r.v*n;let f=Math.abs(Ke(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 FE(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(Ke(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 Kk(e,t,r,n,o,a){let s=st(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,AE(qn(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],s,pn(r,m),Ri(r,m),Xn(r,m),a?p=>a(m,p):void 0))}if(u<=s.vTol)break}return c}function Hk(e,t,r,n,o,a){let s=st(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,FE(qn(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],pn(r,m),Ri(r,m),Xn(r,m),a?a[m]:1))}if(u<=s.vTol)break}return c}function wE(e,t,r){let n=r.load?xi(t):null;if(!n||!r.load)return{pick:r.envelope};let o=t.npts;return{pick:Gk(n,r.load,e,r.envelope),cap:a=>Vk(n,a%o),n:(a,s)=>Iu(n,a,s)}}function zk(e,t,r,n,o,a,s){return _u(n,r.ds,o,a,(i,c,l)=>{let u=c*c*r.curvature[i];return qn(e,t,i).axAccel(c,Math.abs(Ke(u,Xn(r,i))),pn(r,i),s?l*s[i]:l)+Ri(r,i)})}function Yk(e,t){return{gear:e.gear.slice(0,t),engineRpm:e.rpm.slice(0,t),shifting:e.shifting.slice(0,t)}}function Wk(e,t,r,n){if(!e.scrub)return{};let o=!1,a=n.map((s,i)=>{let c=qn(e,t,i),l=Ke(s*s*r.curvature[i],Xn(r,i)),u=c.scrub?c.scrub(s,Math.abs(l),pn(r,i)):0;return u!==0&&(o=!0),u});return o?{axScrub:a}:{}}function Rt(e,t,r,n={}){let o=st(r),a=t.npts,s=t.closed&&!n.standingStart,{pick:i,cap:c,n:l}=wE(e,t,n),u=n.driveDerate,m=n.brakeFade;if(!s)return CE(e,t,o,n.standingStart===!0,i,u,n.vCeiling,m,c,l,n.shifts);let f=va(e,t.curvature,o,t,i,n.vCeiling,c),p=Kk(e,f,t,o,i,m),d=Hk(e,f,t,o,i,u),h=n.shifts?zk(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))}:{},...Wk(e,i,t,b),...h?Yk(h,a):{}}}function CE(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=va(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=qn(e,o,R),M=w=>{let C=Ke(w*w*t.curvature[R],Xn(t,R)),T=(i?x.axDecel(w,Math.abs(C),pn(t,R),i(R,w)):x.axDecel(w,Math.abs(C),pn(t,R)))+Ri(t,R);return Math.sqrt(Math.max(0,w*w+2*T*t.ds[R]))},F=n&&R===0?k.v:cb;k.v=ub(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=Ke(k.ay,Xn(t,R));k.ax=qn(e,o,R).axAccel(k.v,Math.abs(x),pn(t,R),a?a[R]:1)+Ri(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?zk(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))}:{},...Wk(e,o,t,y.map(R=>R.v)),...b?Yk(b,m):{}}}var jk=(e,t)=>{let r=e[t]?.value;return Number.isFinite(r)&&r>0?r:0};function Qn(e,t,r){let n=e.m.value,o=e.r_dyn?.value??0,a=jk(e,"I_wheel"),s=e.motorModel?.kind==="ice"?0:jk(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 Zn(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 vi=36e5,Qk=Math.PI*2,mb=e=>Math.max(0,Math.min(1,e));function pb(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=Oc(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/Qk),l=Math.max(0,i*o/(n*a)),u=r.efficiency(c,l);return u>.01?u:.5}}var Uk=new WeakMap;function ka(e){if(e.batteryModel)return e.batteryModel;let t=e.capacity.value,r=e.ocv.value,n=Uk.get(e);if(n&&n.capacityAh===t&&n.ocv===r)return n.model;let o=Hp(t,r);return Uk.set(e,{capacityAh:t,ocv:r,model:o}),o}function db(e){let t=e.params,r=dh(t,Xl(e));if(ft(t.motorModel)||pt(t).mode!=="hydraulic")return r;let n;return(o,a,s,i=0)=>{if(!(o>0))return 0;n??=TE(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 Xk=new WeakMap;function TE(e){let t=e.params,r=Xk.get(t);if(!r){let n=Cr(t);r={inp:dt(n.regen?t:{...t,energy:{...n,regen:!0}}),ev:ir(t)},Xk.set(t,r)}return r}var ki=e=>e.airTempC??At;function Ou(e,t){return e.thermal?e.thermal.startC??t:To}function qk(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 Zk=()=>({windingC:[],derate:[],lossW:[],torqueNm:[],ampsRms:[]});function PE(e){let t=e.motorModel;if(!t?.thermal)return;let r=zp(t.thermal),n=Oc(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/Qk),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 LE(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 DE(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 EE(e){let{drivenFront:t,drivenRear:r}=Zn(e);return Qn(e.params,t,r)}function Ma(e,t,r,n,o=wr,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?dt(m):void 0,g=pb(m),y=hr(ka(m)),R=y.chargeC,k=mb(a??m.soc.value),v=ki(m),x=s??Ou(y,v),M=x,F=0,w=0,C=0,T=0,S=-1,A=-1,P=-1,L=PE(m),D=L?L.th.startC:0,E=D,V=0,N=1,z=-1,I=0,_=0,B=db(e),O=m.motorModel?.kind==="ice",G=u?.scrub,K=G?d/EE(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}=Du(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],Ve=j+1<r.length?r[j+1]:Z,Ae=.5*(Z+Ve),le=Ae>0?t[j]/Ae:0,Re=0,Ce=k,He=x,je=0,be=0,Fe=le;if(O){oe>0&&(be=ue/g(Z,oe),F+=be/vi),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=LE(y,xe,le,k,x);me.short&&S<0&&(S=j),me.cutoff&&A<0&&(A=j);let Le=k*R,Se=Math.min(me.dq,Le),ze=me.dq>0?Se/me.dq:1;Se>=Le&&P<0&&(P=j),F+=me.energyJ*ze/vi,be=me.energyJ*ze,Fe=me.seconds,C+=me.lossJ*ze,T+=Se,le>0&&(je=Se/me.seconds),k=mb(k-Se/R),x=qk(y,x,me.dq>0&&le>0?Se/le:0,me.lossJ*ze,le,v),x>M&&(M=x),Re=oe}else if(o.regen){let xe=u?Ke(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=DE(y,Le,le,k,x),ze=(1-k)*R,Ue=Math.min(Se.dq,ze),Kt=Se.dq>0?Ue/Se.dq:1;w+=Se.energyJ*Kt/vi,be=-Se.energyJ*Kt,C+=Se.lossJ*Kt,T-=Ue,le>0&&(je=-Ue/le),k=mb(k+Ue/R),x=qk(y,x,Ue>0&&le>0?-Ue/le:0,Se.lossJ*Kt,le,v),x>M&&(M=x),Re=-me*Kt}if(l?.netKwh.push(F-w),l?.powerKw?.push(le>0?be/Fe/1e3:0),l?.pack){let xe=l.pack;xe.soc.push(Ce),xe.amps.push(je),xe.volts.push(y.ocv(Ce)-je*y.resistance(Ce,He)),xe.cellC.push(He)}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&&(I+=le);let Le=L.torque(Re,xe,me),Se=L.th.lossW(xe,Le,D);V+=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>E&&(E=D)}}return{drive:F,regen:w,net:F-w,chargeAh:T/3600,loss:C/vi,socEnd:k,shortAt:S,cutoffAt:A,emptyAt:P,tempEndC:x,tempMaxC:M,...L?{motorTempEndC:D,motorTempMaxC:E,motorLossKwh:V/vi,motorDerateMin:N,motorDerateAt:z,motorDerateTimeFrac:_>0?I/_:0}:{}}}var IE=.5,_E=.02,NE=6;function Jk(e,t,r,n,o,a,s,i){let c=n(),l=1,u=d=>{let h=Zk(),b=Ma(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<NE;d++){let h=n(f);l++;let b=Math.abs(h.laptime-c.laptime);if(c=h,m=u(c),b<_E){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]+IE*((g[R]??1)-f[R]);f=y}return{lap:c,derate:f,solves:l,converged:p,peakWindingC:m.peak,derateTimeFrac:m.frac}}var OE=.1;function eM(e){let t=e.power_limit_kw?.value??0;return t>0?t*1e3:0}function fb(e,t,r){return e.motorModel?.kind==="ice"?1/0:hr(ka(e)).maxPower(t??e.soc.value,r,eM(e)).watts}function Vu(e,t,r,n){let o=fb(e,r,n);if(!Number.isFinite(o))return 1/0;if(o<=0)return 0;let a=Math.max(OE,t),s=pb(e),i=o*(e.effi_pgb?.value??.9)/a;return o*s(t,i)/a}var VE=180/Math.PI;function Bu(e,t,r,n){let o=e*t,a=e*(1-t);return o/r-a/n}var $u=e=>e*9.81*VE;var zX=Math.PI/180;function Gu(e,t,r,n=0){let o=we(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?Bu(e.massTotal,e.frontMassFrac,2*i,2*c):0,u=$u(l),m=u>.15?"understeer":u<-.15?"oversteer":"neutral";return{gradient:u,balance:m,cAlphaFront:i,cAlphaRear:c}}var ZX=Math.PI/180,JX=180/Math.PI;var tM=2220446049250313e-31;function GE(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 KE(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 HE(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])<=tM*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<=tM*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 rM(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 GE(r),KE(r),HE(r)}function nM(e){let t=[],r=new Array(e.length).fill(!1),n=rM(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 hb(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 zE(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 hb(r,n)}function Ku(e,t=r=>zE(e,r)){return nM(e).map(r=>({...r,vector:t(r.eigenvalue)}))}function Sa(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 oM(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 Sa(Ku(i),c,0)}function aM(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=oM({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 Hu(e,t,r){let n=Te(e);return{front:aM(e,n,"front",t??n.rideDampingFront),rear:aM(e,n,"rear",r??n.rideDampingRear)}}var p7=180/Math.PI;var bb=["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},Aa=20,sM=[ce.zFL,ce.zFR,ce.zRL,ce.zRR],iM=[ce.vzFL,ce.vzFR,ce.vzRL,ce.vzRR],Vr={fzFL:0,fzFR:1,fzRL:2,fzRR:3,fzBody:4,myBody:5,mxBody:6,fx:7,fy:8,mz:9},gb=10;function zu(e){let t=Array.from({length:Aa},()=>new Array(Aa).fill(0)),r=Array.from({length:Aa},()=>new Array(gb).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[sM[i]]-=c,s[iM[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(Aa).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=sM[s],x=iM[s];for(let M=0;M<Aa;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][Vr.fzFL+s]=1/y}return r[ce.vzBody][Vr.fzBody]=1/e.bodyMass,r[ce.pitchRate][Vr.myBody]=1/n.yy,r[ce.rollRate][Vr.mxBody]=1/n.xx,r[ce.vx][Vr.fx]=1/e.totalMass,r[ce.vy][Vr.fy]=1/e.totalMass,r[ce.yawRate][Vr.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,f=Xe(e,"front")*1e3,p=Xe(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 cM=ce.rollRate+1;function lM(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,cM).map(i=>i.slice(0,cM));if(!n.every(i=>i.every(Number.isFinite)))return{};let a=Ku(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 hb(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:Sa(a,s,1),pitch:Sa(a,s,2),roll:Sa(a,s,3)}}function uM(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 Yu(e){let t=Te(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=lM(zu(yb(e)));return{roll:uM(m.roll,a,s),pitch:uM(m.pitch,l,u)}}var Wu=9.81,Br=Math.PI/180;function mM(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 Fa(e,t,r,n,o){let{wb:a,lf:s,lr:i,m:c}=mM(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=we(e,l/Wu,0,r),F=Math.max(0,M.FL+M.FR),w=Math.max(0,M.RL+M.RR),C=t(v,F),T=t(x,w),S=(C*Math.cos(o)+T)/c;if(l=.5*(l+S),Math.abs(S-l)<1e-4)break}let u=l/r,m=o-n-s*u/r,f=-n+i*u/r,p=we(e,l/Wu,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/Wu,cn:y/(c*Wu*a)}}function xb(e,t,r,n={}){let o=Math.max(8,r),a=(n.betaMaxDeg??10)*Br,s=(n.deltaMaxDeg??10)*Br,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=Fa(e,t,o,F,y);R.push(w.ay),k.push(w.cn),v.push(F/Br),x.push(y/Br),Math.abs(w.ay)>f&&(f=Math.abs(w.ay))}u.push({label:`\u03B4 ${(y/Br).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=Fa(e,t,o,y,F);R.push(w.ay),k.push(w.cn),v.push(y/Br),x.push(F/Br)}p.push({label:`\u03B2 ${(y/Br).toFixed(0)}\xB0`,ay:R,cn:k,betaDeg:v,deltaDeg:x})}let d=.5*Br,h=(Fa(e,t,o,d,0).cn-Fa(e,t,o,-d,0).cn)/(2*d),b=(Fa(e,t,o,0,d).cn-Fa(e,t,o,0,-d).cn)/(2*d);return{isoBeta:p,isoDelta:u,trim:m,maxAy:f,stability:h,control:b,speed:o}}function YE(e){return!e.corneringStiffnessFront||!e.corneringStiffnessRear?null:{Cf:2*e.corneringStiffnessFront,Cr:2*e.corneringStiffnessRear}}function Mi(e,t){let r=YE(e);if(!r)return null;let{Cf:n,Cr:o}=r,{wb:a,lf:s,lr:i,m:c}=mM(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 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=Bu(c,e.frontMassFrac,n,o),M=$u(x),F=M>.15?"understeer":M<-.15?"oversteer":"neutral",w=s*n-i*o,C=P=>P*3.6,T=null,S=null;w>1e-6?S=C(Math.sqrt(n*o*a*a/(c*w))):w<-1e-6&&(T=C(Math.sqrt(n*o*a*a/(c*-w))));let A=u/(a+x*u*u);return{stable:v,yawFreq:R/(2*Math.PI),dampingRatio:k,eigReal:y,understeerGradient:M,balance:F,characteristicSpeed:T,criticalSpeed:S,yawRateGain:A}}var pM=Math.PI/180;function hM(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 dM(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 bM(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 gM(e,t,r){let n=e.isoDelta[0],o=(n.betaDeg[1]-n.betaDeg[0])*pM||1,a=e.isoDelta.length>1?(e.isoDelta[1].deltaDeg[0]-e.isoDelta[0].deltaDeg[0])*pM:1,s=x=>bM(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)=>dM(x.cn,M,o)),f=s((x,M,F)=>dM(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(`${hM(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 fM=1e-4;function Rb(e){let t=null,r=f=>{if(!t)return!0;let p=Math.abs(f),d=Math.abs(t.ay);return p>d*(1+fM)?!0:p<d*(1-fM)?!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=gM(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 WE=["tv_kp"];function yM(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"},...WE.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 jE=yM(0);function xM(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 UE=xM(0);var XE=9.81;function qE(e){let t=e.wheelbase/1e3;return{lf:t*(1-e.frontMassFrac),lr:t*e.frontMassFrac}}function Si(e,t,r,n){let o=t.tire;if(!o)return null;let s=(r==="limit"?Kh(e,o,t.speed):un(e,o,t.speed,t.ayG)).wheels;return Rr(n??Gn(o,e.massTotal*XE*1.2),{FL:s.FL,FR:s.FR,RL:s.RL,RR:s.RR},qE(e))}function QE(e){if(!e.tire)return e.cornerStiffness;let t=ge(e.tire,"front"),r=ge(e.tire,"rear");return{front:n=>t.corneringStiffness(n),rear:n=>r.corneringStiffness(n)}}var RM=[{key:"understeer",label:"Understeer gradient",unit:"\xB0/g",compute:(e,t)=>Gu(e,t.ayG,QE(t),t.speed).gradient},{key:"rollGradient",label:"Roll gradient",unit:"\xB0/g",compute:e=>Te(e).rollGradient},{key:"pitchGradient",label:"Pitch gradient",unit:"\xB0/g",compute:e=>Te(e).pitchGradient},{key:"tlltdFront",label:"TLLTD front",unit:"%",compute:e=>100*ef(e)},{key:"rollStiffFront",label:"Front roll-stiffness",unit:"%",compute:e=>100*Te(e).frontRollStiffFrac},{key:"rideFreqFront",label:"Ride freq front",unit:"Hz",compute:e=>Te(e).rideFreqFront},{key:"rideFreqRear",label:"Ride freq rear",unit:"Hz",compute:e=>Te(e).rideFreqRear},{key:"rollFreq",label:"Roll-mode freq",unit:"Hz",compute:e=>Yu(e).roll.freq},{key:"pitchFreq",label:"Pitch-mode freq",unit:"Hz",compute:e=>Yu(e).pitch.freq},{key:"zetaFront",label:"Damping \u03B6 front",unit:"-",compute:e=>Hu(e).front.dampingRatio},{key:"zetaRear",label:"Damping \u03B6 rear",unit:"-",compute:e=>Hu(e).rear.dampingRatio},{key:"yawFreq",label:"Yaw natural freq",unit:"Hz",compute:(e,t)=>Mi(e,t.speed)?.yawFreq??NaN},{key:"yawZeta",label:"Yaw damping \u03B6",unit:"-",compute:(e,t)=>Mi(e,t.speed)?.dampingRatio??NaN},{key:"stabilitySpeed",label:"Char./critical speed",unit:"km/h",compute:(e,t)=>{let r=Mi(e,t.speed);return r?r.criticalSpeed??r.characteristicSpeed??NaN:NaN}},{key:"maxAy",label:"Max lateral accel",unit:"g",compute:(e,t)=>t.fyAxle?xb(e,t.fyAxle,t.speed,{betaMaxDeg:12,deltaMaxDeg:12}).maxAy:NaN},{key:"yawReserveRear",label:"Yaw stability reserve",unit:"N\xB7m",compute:(e,t)=>Si(e,t,"operating")?.stabil??NaN},{key:"yawReserveFront",label:"Yaw agility reserve",unit:"N\xB7m",compute:(e,t)=>Si(e,t,"operating")?.agil??NaN},{key:"limitBalance",label:"Limit balance (+US / \u2212OS)",unit:"-",compute:(e,t)=>Si(e,t,"limit")?.rel??NaN},{key:"yawStiffness",label:"Yaw stiffness N_\u03B2",unit:"N\xB7m/rad",compute:(e,t)=>t.tire?Gh(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorque",label:"Steering holding torque",unit:"N\xB7m",compute:(e,t)=>t.tire?Bh(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorqueGradient",label:"Steering feedback gradient",unit:"N\xB7m/g",compute:(e,t)=>t.tire?$h(e,t.tire,t.speed,t.ayG):NaN}],vb=Object.fromEntries(RM.map(e=>[e.key,e]));var $r=9.81;function ZE(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 JE={front:!1,rear:!0};function wa(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 vM(e,t,r,n,o,a){let s=e[t]+e[r];if(!(s>0))return;let i=wa(n,o[t],a[t]),c=wa(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 kM(e,t,r,n,o,a={},s="open"){if(!e.rear)return 1;if(!e.front)return 0;let i=(f,p,d)=>d?js(f,p,d):s==="own"?f+p:2*Math.min(f,p),c=i(wa(n,t.FL,r.FL),wa(n,t.FR,r.FR),a.front),l=i(wa(o,t.RL,r.RL),wa(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 kb(e,t,r,n){return{car:t?AM(t,r.loadFactor[n]):e,ayTyre:Ke(r.ay[n],r.bank?.[n]??0),axCar:r.ax[n]-(r.axGrade?.[n]??0)}}function MM(e,t){if(!e.aero?.model)return 0;let r=Math.min(t.v.length,t.ax.length,t.ay.length),n=t.loadFactor?Uu(e):void 0,o=0,a=0;for(let s=0;s<r;s++){let i=t.ds?.[s]??1,c=kb(e,n,t,s);o+=i,Jd(c.car,t.v[s],c.axCar/$r,c.ayTyre/$r)&&(a+=i)}return o>0?a/o:0}function SM(e,t,r){let n=zt(ge(t,"front")),o=zt(ge(t,"rear")),a=Math.min(r.v.length,r.ax.length,r.ay.length),s=r.loadFactor?Uu(e):void 0,i=0,c=0;for(let l=0;l<a;l++){let u=r.ds?.[l]??1,m=kb(e,s,r,l);i+=u;let f=we(m.car,m.ayTyre/$r,m.axCar/$r,r.v[l]);(f.FL>n||f.FR>n||f.RL>o||f.RR>o)&&(c+=u)}return i>0?c/i:0}function ju(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=ei(t,e.massTotal*$r*1.2),l=ta(c,"front"),u=ta(c,"rear"),m=ut(ge(t,"front")),f=ut(ge(t,"rear")),p=n.perWheel?of(m,l):null,d=n.perWheel?f===m?p:of(f,u):null,h=n.driven??JE,b={front:Bt(e,"front",1),rear:Bt(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=zt(m),w=zt(f),C=0,T=0,S=0,A=0,P=0,L=0,D=["FL","FR","RL","RR"],E=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,V=r.loadFactor?Uu(e):void 0;for(let N=0;N<o;N++){let z=kb(e,V,r,N),{ayTyre:I,axCar:_}=z,B=I/$r,O=we(z.car,B,_/$r,r.v[N]),G=e.massTotal*I,K=G*i/a,Y=G*s/a,j=ws(m,K,O.FL,O.FR,P),Z=ws(f,Y,O.RL,O.RR,L);P=j,L=Z;let ne={FL:Math.abs(m.Fy(j,O.FL,0)),FR:Math.abs(m.Fy(j,O.FR,0)),RL:Math.abs(f.Fy(Z,O.RL,0)),RR:Math.abs(f.Fy(Z,O.RR,0))},te=(_-(r.axDrag?.[N]??0)-(r.axScrub?.[N]??0))/$r,fe=te>0&&h.front?kM(h,O,ne,l,u,b,"own"):0,W=r.v[N]*r.v[N],J=e.driveline?{Fz:O,alpha:{front:j,rear:Z},curvature:W>1?r.ay[N]/W:0,seed:g}:void 0,re={..._h(e,te,r.v[N],t,B,fe,J)};te>0&&(b.front||vM(re,"FL","FR",l,O,ne),b.rear||vM(re,"RL","RR",u,O,ne));let pe=!1,de=!1;for(let ue of["FL","FR","RL","RR"]){let Ve=(ue==="FL"||ue==="FR"?l:u).muX(O[ue])*O[ue];Math.abs(re[ue])>Ve&&(pe=!0),O[ue]>(ue==="FL"||ue==="FR"?F:w)&&(de=!0)}de&&(M+=r.ds?.[N]??1);let ie=Rr(c,{FL:{Fz:O.FL,Fy:ne.FL,Fx:re.FL},FR:{Fz:O.FR,Fy:ne.FR,Fx:re.FR},RL:{Fz:O.RL,Fy:ne.RL,Fx:re.RL},RR:{Fz:O.RR,Fy:ne.RR,Fx:re.RR}},{lf:s,lr:i});if(y[N]=ie.stabil,R[N]=ie.agil,k[N]=ie.rel,E){let ue=.5*(O.FL+O.FR),Ve=.5*(O.RL+O.RR),Ae=l.muX(ue)*ue,le=u.muX(Ve)*Ve;for(let Re of D){let Ce=O[Re],He=Re==="FL"||Re==="FR",je=He?l:u,be=je.muY(Ce)*Ce,Fe=je.muX(Ce)*Ce,xe=E[Re],me=He?j:Z;xe.Fz[N]=Ce,xe.alpha[N]=me,xe.Fy[N]=ne[Re],xe.Fx[N]=re[Re],xe.Mz[N]=Ce>0?(He?m:f).Mz(me,Ce,0):0,xe.FxCap[N]=Fe,xe.FyCap[N]=be;let Le=be>0?Math.min(1,Math.abs(ne[Re])/be):0,Se=ZE(re[Re],Fe,He?Ae:le),ze=He?p:d,Ue=ze&&Ce>0?ze.reach(Ce,Math.sign(re[Re])*Se,Le):1;xe.used[N]=Math.hypot(Le,Se)/Ue}}ie.stabil<v&&(v=ie.stabil,x=N);let oe=r.ds?.[N]??1;A+=oe,ie.diff>0&&(C+=oe),pe&&(T+=oe),Jd(z.car,r.v[N],_/$r,B)&&(S+=oe)}return{stabil:y,agil:R,rel:k,minStabil:Number.isFinite(v)?v:0,minStabilAt:x,pastTurnoverFrac:A>0?M/A:0,understeerFrac:A>0?C/A:0,beyondFrac:A>0?T/A:0,aeroOutsideFrac:A>0?S/A:0,wheels:E}}function Uu(e){return Object.create(e,{loadFactor:{value:1,writable:!0,enumerable:!0}})}function AM(e,t){return e.loadFactor=t,e}var Mb=9.81;function Sb(e,t,r,n={}){let o=r.v.length,a=e.massTotal,s=Pr(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=Ke(r.ay[l],r.bank?.[l]??0)/Mb,h=Math.min(.99,Math.max(.01,ua(e,f/Mb,u,t,d)));c.front[l]=p*h,c.rear[l]=p*(1-h);let b=i?ru(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/Mb)),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 kq=Math.PI/180;var Mq=bb.map(ti);var Sq=[ce.zFL,ce.zFR,ce.zRL,ce.zRR];var Aq=Array.from({length:ce.rollRate+1},(e,t)=>t);var pI=9.81,dI=.001,fI=.6,hI=2,TM=4;function PM(e,t,r,n=TM){let o=Math.min(e.v.length,t.npts),{ds:a,closed:s}=t,i=r.massTotal*pI*r.wheelbase,c=bI(e.ay.slice(0,o).map((m,f)=>m/Math.max(dI,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 bI(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 LM(e,t,r,n,o={}){let a=o.maxIter??20,s=o.tol??.001,i=Math.min(1,Math.max(.001,o.relax??fI)),c=o.smoothM??TM,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=Rt(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=PM(d,t,r,c);f=v.demand.map((F,w)=>f[w]+i*(F-f[w])),p=v.rdot;let x=Rt(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>=hI){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 Iq=Math.PI/180;var pQ=180/Math.PI;function Ca(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 EM(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=>Ca(p.vs,h,d)),axDecelN:p.decel.map(h=>Ca(p.vs,h,d)),axScrubN:p.scrub.map(h=>Ca(p.vs,h,d))});if(!o){let p=a(e);return d=>({ayMax:Ca(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/Ca(i.vs,i.radius,p),f=p=>p>=u||c.vs.length<2?Ca(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 EI(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 IM(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=EM(s,t),c=[],l=a,u=(f,p)=>{let d=.5*(f+p),h=e(d);l++;let b=EI(i(d),h);s.splice(s.findIndex(g=>g.v>d),0,h),i=EM(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 II=2,_I=.5,Ai=Math.PI/180,_M=21,NI={nCoarse:11,nSteer:13,nNorm:41,nAngle:45},OI={nCoarse:11,nSteer:13,nNorm:41,nAngle:61},VI=.005,BI=.05,Ab=e=>e<0?0:e>1?1:e;function $I(e,t,r,n){let o=e.massTotal,a=n.nSteer??7,s=(n.drivenFront?2:0)+(n.drivenRear?2:0),i=we(e,0,0,r),c=Math.max(1,(i.FL+i.FR+i.RL+i.RR)/4),l=8*Ai,u=0,m=(b,g,y)=>{for(let R=b;R<=g;R+=y){let k=Math.abs(t.Fy(R*Ai,c,0));k>u&&(u=k,l=R*Ai)}};m(1,45,1),m(Math.max(.1,l/Ai-1),l/Ai+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*St(t,c,R,!1)/o),d.push(4*St(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 cr(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?OI:NI),{nCoarse:c,nSteer:l,nAngle:u}=i,m=Tr(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=dt(f);s!==1&&(R.loadFactor=s);let k=ir(f),v=Yv(0,n?.vRes??(e.engine?_I:II),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}=Zn(e),C=Qn(f,F,w),T=(B,O)=>{let G=M?mt(M.vVehicle,B,O):NaN;return Number.isFinite(G)?G:1/0},S=B=>{let O=B*B,{cl:G,cw:K,A:Y}=Du(f,B,0,R),j=.5*d*-K*Y*O,Z=.5*d*-G*Y*O,ne=h*(-Z+y);return j+ne},A=B=>{let O=S(B)/p*C.powerFactor,G=S(B)/p*C.tractionFactor,K;if(e.engine){let j=S(B);K=ia(e.engine,B,C.effective,j,g).accel-O}else if(M){let j=0;F&&(j+=T(M.fFront,B)),w&&(j+=T(M.fRear,B)),K=g*j/p*C.powerFactor}else{let j=mt(e.vVehicle,x,B),Z=g*j/p*C.powerFactor;K=Number.isFinite(Z)?Z:1/0}let Y=Vu(f,B,o)/p*C.powerFactor;return{axDrag:O,axDragTyre:G,axDrive:K,axPackCap:Y,axPower:Math.min(K,Y)}},P=v.map(A),L=e.vMax;for(let B=1;B<v.length;B++){let O=P[B].axDrive+P[B].axDrag;if(O>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-O):v[B-1];break}let D=Math.min(e.vMax,(1+BI)*L),E=r==="fast"?$I:zh,V=B=>{let O=E(R,k,B,{drivenFront:F,drivenRear:w,nSteer:l,yawDemandCn:a,axDrag:S(B)/p,...f.diffYaw?{diffYaw:!0}:{}}),G=O.ay[0],K=O.ay[O.ay.length-1],Y=te=>Math.min(Math.max(te*O.ayMax,G),K),j=m.map(te=>jl(O.ay,O.axAccel,Y(te))*C.tractionFactor),Z=m.map(te=>jl(O.ay,O.axDecel,Y(te))),ne=m.map(te=>jl(O.ay,O.axScrub,Y(te))*C.tractionFactor);return{v:B,ayMax:O.ayMax,axAccelN:j,axDecelN:Z,axScrubN:ne,atLock:O.atLock===!0}},N=r==="fast"?0:Math.min(lu,D),z=IM(V,N,D,c,i.anchorTol??VI),I=[],_=[];for(let B=0;B<v.length;B++){let O=v[B],{axDrag:G,axDragTyre:K,axDrive:Y,axPackCap:j,axPower:Z}=P[B],{ayMax:ne,axAccelN:te,axDecelN:fe,axScrubN:W}=z.at(O);I.push({v:O,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=Ab(Math.abs(Math.cos(ie)));J.push({ax:Math.min(mt(m,te,ue)+K,Z+G)+mt(m,W,ue),ay:oe,v:O})}for(let de=u-1;de>=0;de--){let ie=Math.PI*de/(u-1),oe=ne*Math.cos(ie),ue=Ab(Math.abs(Math.cos(ie)));re.push({ax:mt(m,fe,ue)+G+mt(m,W,ue),ay:oe,v:O})}let pe=(de,ie,oe)=>Array.from({length:_M},(ue,Ve)=>({ax:ie+(oe-ie)*(Ve+1)/(_M+1),ay:de,v:O}));_.push([...J,...pe(-ne,J[J.length-1].ax,re[0].ax),...re,...pe(ne,re[re.length-1].ax,J[0].ax)])}return{...OM(I,m),rows:I,norm:m,surf:_}}function Ta(e,t){return e?.length?t.map(r=>qu(e,r)):t.map(()=>0)}function qu(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 OM(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?mt(t,h,g):a(d,mt(t,h,g),mt(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?Ab(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,C=E=>k[E]+b*(v[E]-k[E]),T=E=>x[E]+b*(M[E]-x[E]),S=E=>F?y*(F[E]+b*(w[E]-F[E])):0,A=a(b,d.ayMax,h.ayMax),P=a(b,d.axDrag,h.axDrag),L=a(b,l(d),l(h)),D=a(b,d.axPower,h.axPower);for(let E=R;E>=0;E--){let V=Math.min(y*C(E)+L,D+P)+S(E),N=y*T(E)+P+S(E);if(!(g<=V+1e-6&&g>=N-1e-6))continue;if(E===R)return t[E]*y*A;let z=(O,G,K)=>{if(K(G))return 1;let Y=(O-g)/(O-G);return Y>0?Math.min(Y,1):0},I=O=>g<=O+1e-6,_=O=>g>=O-1e-6,B=Math.min(z(y*C(E)+L+S(E),y*C(E+1)+L+S(E+1),I),z(D+P+S(E),D+P+S(E+1),I),z(y*T(E)+P+S(E),y*T(E+1)+P+S(E+1),_));return(t[E]+B*(t[E+1]-t[E]))*y*A}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 GI(e,t,r){let n=e.params,o=n.m.value,{drivenFront:a,drivenRear:s}=Zn(e),i=Qn(n,a,s);return c=>Vu(n,c,t,r)/o*i.powerFactor}function Fi(e,t,r,n){let o=GI(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{...OM(a,e.norm),rows:a,norm:e.norm}}var KI=[-.2,-.08,0,.06,.12,.2,.3];function VM(e,t=!1,r="twoTrack",n,o,a=KI){let s=[...new Set([...a,0])].sort((d,h)=>d-h),i=s.map(d=>cr(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=>Fi(y,d,h,b));return{anchors:s,steady:g[s.indexOf(0)],clamps:p,at:f(g)}}}}function BM(e,t,r,n="twoTrack",o){let a=[...new Set([...t,1])].sort((i,c)=>i-c),s=a.map(i=>i===1?r:cr(e,!1,n,o,void 0,0,i));return{...NM(a,s),atSoc:(i,c,l)=>NM(a,s.map(u=>Fi(u,i,c,l)))}}function NM(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):ib(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 $M=new WeakMap;function Fb(e,t){let r=$M.get(e);if(!r){let n=Cr(e).regen?db(t??Ft(e)):void 0;r={inp:dt(e),ev:ir(e),...n?{regen:n}:{}},$M.set(e,r)}return r}function wb(e,t,r){let n=Fb(e,r);return Sb(n.inp,n.ev,t,n.regen?{regen:n.regen}:{})}function Cb(e){let t=pt(e);if(t.mode!=="hydraulic")return null;let r=a=>a.heat?{heat:Hf(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 HI(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 Tb(e,t,r,n,o,a=At){if(!e)return null;let s=HI(t);return{...e.front?{front:Kl(e.front.heat,e.front.discs,s.front,r,n,o.front,a)}:{},...e.rear?{rear:Kl(e.rear.heat,e.rear.discs,s.rear,r,n,o.rear,a)}:{}}}var zI=.5,YI=.02,WI=6,Qu=9,GM=1e-9,jI={FL:0,FR:0,RL:0,RR:0};function Pb(e){return e?[...new Set([...e.padCurve.factor,1])].sort((t,r)=>t-r):[1]}function UI(e,t,r){let n=nr(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 KM(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 HM(e,t,r,n,o=()=>0){let a=Array.from({length:Qu},(m,f)=>r*f/(Qu-1)),s=Zs(),{front:i,rear:c}=n,l=a.map(m=>{let f=o(m),p=h=>Lr(h,t,m,s).limitAt(0,0,jI,f).ax,d=p(e);return i.map(h=>c.map(b=>{if(h===1&&b===1)return 1;let g=d<0?p(UI(e,h,b))/d:1;return Math.abs(g-1)<GM?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(Qu-2,Math.max(0,Math.floor(m/u))):0,h=u>0?Math.min(1,Math.max(0,(m-a[d])/u)):0,b=KM(i,f),g=KM(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(Qu-1,d+1))-y(d));return Math.abs(R-1)<GM?1:R}}}function XI(e,t){let{front:r,rear:n}=t;return(o,a)=>e.share(a,r?.[o]??1,n?.[o]??1)}var qI=e=>(e.front??[]).every(t=>t===1)&&(e.rear??[]).every(t=>t===1);function zM(e,t,r){let n=e(),o=1,a=t(n);if(qI(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<WI;c++){let l=e(XI(r,s));o++;let u=Math.abs(l.laptime-n.laptime);if(n=l,u<YI){i=!0;break}a=t(n);let m=(d,h)=>d&&h?d.map((b,g)=>b+zI*((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 fn(e,t){let r=e.engine;if(!r||r.gears.length===0||t.length===0)return;let n=e.params,{drivenFront:o,drivenRear:a}=Zn(e),s=Qn(n,o,a).effective,i=n.power_scale.value,{up:c,down:l}=oh(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:ah(r.engine.gearbox),limitRpm:r.engine.limitRpm,best:f=>ia(r,f,s,qu(t,f)*s,i).gear,share:(f,p)=>{let d=qu(t,f),h=d*s,b=ia(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 YM=new WeakMap;function Db(e){let t=YM.get(e.ggv);return t===void 0&&(t=fn(e.vehicle,e.ggv.rows)??null,YM.set(e.ggv,t)),t??void 0}function QI(e){return e.gear&&e.engineRpm&&e.shifting?{gear:e.gear,rpm:e.engineRpm,shifting:e.shifting}:{}}var Ju=class extends Error{constructor(t){super(t),this.name="EventError"}};function ZI(e,t){let{ggv:r}=t,n=st(t.numerics),o=n.accelStep,a=Math.max(1,Math.round(e.distance/o)),s=va(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=Db(t),c=i?_u(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:eS(t,f,[...u,s[a].v],m,1)}}function JI(e,t){let r=Math.max(1,Math.round(e.laps??1)),[n]=va(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=eS(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 em(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 e2(e,t){let r=e.distance!=null?t.v_limit_endurance?.value??0:0;return r>0?r/3.6:void 0}function t2(e,t){if(e.distance==null||ft(t.motorModel))return 0;let r=t.endurance_reserve?.value??0;return r>0?Math.min(r,95)/100:0}var WM=1;function QM(e,t,r,n){return{v:r.v,ax:r.ax,ay:r.ay,ds:t.ds,axDrag:Ta(e.ggv.rows,r.v),...r.axScrub?{axScrub:r.axScrub}:{},axGrade:n,...t.bank?{bank:t.bank}:{}}}var jM=new WeakMap;function ZM(e){let t=e.vehicle.params;if(!t.brakeFade)return null;let r=jM.get(t);if(r===void 0){let n=Cb(t),o=n?pt(t):null;if(!n||!o||o.mode!=="hydraulic")r=null;else{let a=Fb(t,e.vehicle),s=e.ggv.rows,i=HM(a.inp,a.ev,e.vehicle.vMax,{front:Pb(o.hydraulic.front.heat),rear:Pb(o.hydraulic.rear.heat)},c=>Ta(s,[c])[0]);r={discs:n,table:i}}jM.set(t,r)}return r}function r2(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=Db(e),u=(g,y)=>e.yaw?LM(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}:{}}):Rt(Fi(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=dn(t.gradient,t.npts),f=g=>n.motorThermal?Jk(e.vehicle,t.ds,e.energyOpts??wr,y=>u(y,g),o,a,m,t.bank).lap:u(void 0,g),p=ZM(e);if(!p)return f();let d=ki(n),h=r.discC??{front:d,rear:d};return zM(f,g=>{let y=Tb(p.discs,wb(n,QM(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 n2(e,t){let r=e2(e,t.vehicle.params),n=t2(e,t.vehicle.params);return n>0?s2(e,t,n,r):wi(e,t,r)}function Zu(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 UM=5,o2=.1,a2=.005,XM=12;function s2(e,t,r,n){let o=wi(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=Zu(o,r);if(i>=0)return s(o,n,!0);let c=Math.min(n??1/0,t.ggv.vMax),l=c/2,u=wi(e,t,l);a++;let m=Zu(u,r);for(;m<0&&l>UM&&a<XM;)c=l,i=m,l=Math.max(UM,l/2),u=wi(e,t,l),a++,m=Zu(u,r);if(m<0)return s(u,l,!1);let f=l,p=0;for(;a<XM&&c-l>o2&&m>a2;){let d=c-l,h=Math.min(c-.05*d,Math.max(l+.05*d,l+m*d/(m-i))),b=wi(e,t,h);a++;let g=Zu(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 JM(e,t,r){return r===0?e:e&&!t}function wi(e,t,r){let n=t.track;if(!n)throw new Ju(`Event "${e.id}" needs a track.`);let o=em(e,n),a=e.standingStart??t.standingStart??!1,s=K=>JM(a,n.closed,K),i=t.vehicle.params,c=hr(ka(i)),l=c.capacityAh,u=i.soc.value,m=ki(i),f=Ou(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,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,F+=(K.motorDerateTimeFrac??0)*Y,v+=(K.motorLossKwh??0)/j,w+=(K.motorLossKwh??0)/j)},S=null,A,P=Cb(i),L={front:m,rear:m},D=null,E=ZM(t)!==null,V=(K,Y)=>E&&(Math.abs(K.front-Y.front)>WM||Math.abs(K.rear-Y.rear)>WM),N=(K,Y,j)=>{let Z=fb(i,K,Y);if(D&&D.launch===j&&!l2(Z,D.pw)&&!V(L,D.discC))return D.lap;let ne=r2(t,n,{soc:K,packTempC:Y,launched:j,...r?{vCeiling:r}:{},...E?{discC:L}:{}});return D={pw:Z,launch:j,discC:L,lap:ne},ne},z=dn(n.gradient,n.npts),I=(K,Y,j)=>Ma(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=wb(i,QM(t,n,K,z),t.vehicle),_.set(K,j)),Tb(P,j,K.v,n.ds,Y,m)},O=(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){A={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,C=-1/0;let ne=N(u,f,Y),te=I(ne,u,f);if(te.emptyAt>=0){A=O(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,Ve=1;if(W<=Lb)J=ne.laptime,re=te.net,pe=te.loss,de=te.chargeAh,ie=te.tempEndC,T(te,J),Ve=1;else{let le=Math.min(i2,Math.max(2,Math.ceil(W/(2*Lb))));Ve=le;let Re=u,Ce=f;J=0,re=0,pe=0,de=0;for(let He=0;He<le;He++){let je=N(Re,Ce,Y),be=I(je,Re,Ce),Fe=be.emptyAt>=0?be.emptyAt/n.npts:1;if(Fe*le<1){oe=Math.round(n.npts*(He/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,Ce+=(be.tempEndC-Ce)/le,Re<=0){oe=Math.round(n.npts*(He+1)/le),ue=be;break}}if(ie=Ce,oe>=0&&ue){A=O(K,ue,oe);break}u=Re}p+=J,d+=re,h+=pe,b+=de,W<=Lb&&(u=te.socEnd),f=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:f,packTempMaxC:Number.isFinite(C)?C:Z,energyKwh:re,lossKwh:pe,chargeAh:de,launched:Y,substeps:Ve,...r?{vCeiling:r}:{},...x?{motor:{peakWindingC:M,derateTimeFrac:J>0?F/J:0,lossKwh:w}}:{},...Ae?{brakes:{...Ae.front?{front:qM(Ae.front)}:{},...Ae.rear?{rear:qM(Ae.rear)}:{}}}:{}}),S=ne}if(!S){let K=Db(t);S=Rt(Fi(t.ggv,t.vehicle,u),n,t.numerics,{standingStart:a,...t.load?{load:t.load.atSoc(t.vehicle,u)}:{},...K?{shifts:K}:{}}),A=A??{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:S.laptime,trace:{v:S.v,ax:S.ax,ay:S.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}:{},...S.loadFactor?{loadFactor:S.loadFactor}:{},...S.axScrub?{axScrub:S.axScrub}:{},...QI(S)},energy:{consumed:d,loss:h,...ft(i.motorModel)?{}:{native:{value:b,unit:"Ah"}},remainingFraction:ft(i.motorModel)?1:u,...y?{motor:{peakWindingC:R,derateTimeFrac:p>0?k/p:0,lossKwh:v}}:{}},lapLog:g,...A?{incomplete:A}:{}}}var Lb=.05;function qM(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 i2=4,c2=.001;function l2(e,t){return e===t?!1:!Number.isFinite(e)||!Number.isFinite(t)?!0:Math.abs(e-t)>c2*Math.max(1,Math.abs(t))}function eS(e,t,r,n,o,a){return u2(e,t,o,()=>({v:r,ax:n,...a?{lateral:a}:{}}))}function u2(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=Ma(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 ft(e.vehicle.params.motorModel)?{consumed:s,loss:i,remainingFraction:1}:{consumed:s,loss:i,native:{value:c,unit:"Ah"},remainingFraction:a}}function tS(e,t){switch(e.kind){case"straightLineAccel":return ZI(e,t);case"constantRadius":return JI(e,t);case"trackLap":return n2(e,t)}}function Eb(e,t){let r={};for(let n of e)r[n.id]=tS(n,t);return r}function rS(e,t){if(e.kind!=="trackLap")return e;let{distance:r,...n}=e;return{...n,laps:Math.max(1,Math.round(t))}}function Jn(e,t,r,n,o="twoTrack",a){let s=1/0,i=-1/0;for(let f of r){let p=xi(f);if(!p)continue;let d=Bk(p,Rt(t,f,n).v);d&&(s=Math.min(s,d.lo),i=Math.max(i,d.hi))}if(!(i>=s))return;let c=$k({lo:s,hi:i}),l=c.join(","),u=a?.get(l);if(u)return u;let m=BM(e,c,t,o);return a?.set(l,m),m}var Ci=e=>e.distance/Math.max(1,e.laps);function Ti(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 m2=e=>e.v.map(t=>t*3.6),p2=e=>e.ax.map(t=>t/9.81),d2=e=>e.ay.map(t=>t/9.81),f2=e=>e.ay.map((t,r)=>e.v[r]>1e-6?t/(e.v[r]*e.v[r]):0),tm=(e,t,r)=>e?.slice()??new Array(t.s.length).fill(r),h2=e=>tm(e.z,e,0),b2=e=>e.gradient?e.gradient.map(t=>100*Math.tan(t*Math.PI/180)):tm(void 0,e,0),g2=e=>tm(e.bank,e,0),y2=e=>tm(e.mu,e,1);function x2(e){let t=e.s.length,r=Ti(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 Ib=[{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 nS(e){let t=Ti(e);return{ds:t,vars:{s:e.s,ds:t,t:x2(e),v:e.v,speed:m2(e),ax:e.ax,ay:e.ay,axg:p2(e),ayg:d2(e),curv:f2(e),z:h2(e),grade:b2(e),bank:g2(e),grip:y2(e)}}}function oS(e,t){return{v:e.v,ax:e.ax,ay:e.ay,ds:Ti({s:e.s,length:t}),axGrade:dn(e.gradient,e.v.length),...e.bank?{bank:e.bank}:{},...e.loadFactor?{loadFactor:e.loadFactor}:{}}}function aS(e,t){let r=dt(e);return{pastTurnover:SM(r,ir(e),t),...e.aeroModel?{aeroOutside:MM(r,t)}:{}}}var rm="Flying lap";function _b(e,t){return e.kind!=="trackLap"||e.label!==rm?e.label:e.standingStart??t?"Run":e.label}function R2(e){let t=dt(e);return{yawInertia:t.yawInertia??0,massTotal:t.massTotal,wheelbase:t.wheelbase/1e3}}function v2(e,t,r){let n=e.params,o=n.ggvMode??"twoTrack",a=n.quasiTransient?VM(e,!1,o):null,s=a?a.steady:cr(e,!1,o),i=t?Jn(e,s,[t],r,o):void 0;return{ggv:s,...a?{yaw:{family:a,car:R2(n)}}:{},...i?{load:i}:{}}}function k2(e,t){let r=t.lapCounts,n=t.standingStart??!1,o=!1,a=e.events.map(s=>{let i=r?.[s.id]!=null?rS(s,r[s.id]):s,c=_b(i,n),l=c===i.label?i:{...i,label:c};return l!==s&&(o=!0),l});return o?a:e.events}function M2(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=em(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 S2(e,t){for(let[r,n]of Object.entries(e))n.trace&&(e[r]={...n,...aS(t,oS(n.trace,Ci(n)))})}function Pi(e,t,r={}){let n=Ft(e),o=v2(n,r.track,r.numerics),{ggv:a}=o,s=Eb(k2(t,r),{vehicle:n,...o,track:r.track,energyOpts:Cr(e,r.energyOpts),numerics:r.numerics,standingStart:r.standingStart});return M2(s,t,r),S2(s,n.params),{name:e.name,rulesetId:t.id,events:s,ggv:a}}function Nb(e){return{...e,ggv:{rows:e.ggv.rows,vMax:e.ggv.vMax,surf:e.ggv.surf}}}var Ob=["<","<=",">",">=","==","!="],_e=class extends Error{at;constructor(t,r){super(t),this.name="ExprError",this.at=r}},Li=e=>e>="0"&&e<="9",sS=e=>/[A-Za-z_]/.test(e),A2=e=>/[A-Za-z0-9_]/.test(e);function F2(e){let t=[],r=0;for(;r<e.length;){let n=e[r];if(n===" "||n===" "||n===`
|
|
224
|
-
`||n==="\r"){r++;continue}if(Li(n)||n==="."&&Li(e[r+1]??"")){let o=r;for(;r<e.length&&(Li(e[r])||e[r]===".");)r++;if(e[r]==="e"||e[r]==="E"){let i=r;if(r++,(e[r]==="+"||e[r]==="-")&&r++,Li(e[r]??""))for(;r<e.length&&Li(e[r]);)r++;else r=i}let a=e.slice(o,r),s=Number(a);if(!Number.isFinite(s))throw new _e(`"${a}" is not a number`,o);t.push({t:"num",value:s,at:o});continue}if(sS(n)){let o=r;for(;;){for(;r<e.length&&A2(e[r]);)r++;if(e[r]==="."&&sS(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(Ob.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 _e(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 _e(`"${n}" is not something this expression can contain`,r)}return t.push({t:"end",at:e.length}),t}function Vb(e){let t=F2(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 _e(`Expected ${b} here`,n().at)};function i(){let h=c(),b=n();if(b.t!=="op"||!Ob.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"&&Ob.includes(y.value))throw new _e("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 _e("The expression ends before it is finished",h.at):new _e(`"${h.value}" cannot start a value`,h.at)}let p=i(),d=n();if(d.t!=="end")throw new _e(`"${d.value}" is left over \u2014 check for a missing operator`,d.at);return p}function Bb(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 Di=(e,t)=>typeof e=="number"?new Array(t).fill(e):e;function w2(e){let t=1;for(let r of e)Array.isArray(r)&&(t=Math.max(t,r.length));return t}function Tt(e,t){if(e.every(a=>typeof a=="number"))return t(...e);let r=w2(e),n=e.map(a=>Di(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 Ne=(e,t)=>({arity:e,call:r=>Tt(r,t)}),eo=e=>e!==0&&!Number.isNaN(e),lr=e=>e?1:0;function iS(e,t,r){let n=cS(t,r,"integrate"),o=n.length,a=Di(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 cS(e,t,r){if(!e.ds||e.ds.length===0)throw new _e(`${r}() needs to know the sample spacing, and this context has none`,t);return e.ds}var nm={abs:Ne(1,Math.abs),sqrt:Ne(1,Math.sqrt),sign:Ne(1,Math.sign),floor:Ne(1,Math.floor),ceil:Ne(1,Math.ceil),round:Ne(1,Math.round),exp:Ne(1,Math.exp),log:Ne(1,Math.log),sin:Ne(1,Math.sin),cos:Ne(1,Math.cos),tan:Ne(1,Math.tan),atan:Ne(1,Math.atan),atan2:Ne(2,Math.atan2),hypot:Ne(2,Math.hypot),min:Ne(2,Math.min),max:Ne(2,Math.max),clamp:Ne(3,(e,t,r)=>Math.min(r,Math.max(t,e))),if:Ne(3,(e,t,r)=>eo(e)?t:r),and:Ne(2,(e,t)=>lr(eo(e)&&eo(t))),or:Ne(2,(e,t)=>lr(eo(e)||eo(t))),not:Ne(1,e=>lr(!eo(e))),finite:Ne(1,e=>lr(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=iS(e,t,0),n=t.ds,o=Di(e,n.length),a=n.length-1;return r[a]+(o[a]+o[0])/2*n[a]}},integrate:{arity:1,call:([e],t)=>iS(e,t,0)},cum:{arity:1,call:([e],t)=>{let r=t.ds?.length??(Array.isArray(e)?e.length:1),n=Di(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=cS(t,0,"deriv"),n=r.length,o=Di(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}}},Pa={g:9.81,pi:Math.PI,e:Math.E,nan:NaN,inf:1/0},Ei={fleetmin:"min",fleetmax:"max"};function to(e){switch(e.kind){case"call":return Object.hasOwn(Ei,e.name)||e.args.some(to);case"unary":return to(e.arg);case"binary":return to(e.left)||to(e.right);default:return!1}}var C2=e=>typeof e=="number"?`${e}`:`between ${e[0]} and ${e[1]}`;function T2(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 P2(e,t){let r=t.map(c=>({k:c,d:T2(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 ur(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(Pa,e.name))return Pa[e.name];let r=[...Object.keys(t.vars),...Object.keys(Pa)].sort();throw new _e(P2(e.name,r),e.at)}case"unary":return Tt([ur(e.arg,t)],r=>-r);case"binary":{let r=ur(e.left,t),n=ur(e.right,t);switch(e.op){case"+":return Tt([r,n],(o,a)=>o+a);case"-":return Tt([r,n],(o,a)=>o-a);case"*":return Tt([r,n],(o,a)=>o*a);case"/":return Tt([r,n],(o,a)=>a===0?0:o/a);case"^":return Tt([r,n],(o,a)=>o**a);case"<":return Tt([r,n],(o,a)=>lr(o<a));case"<=":return Tt([r,n],(o,a)=>lr(o<=a));case">":return Tt([r,n],(o,a)=>lr(o>a));case">=":return Tt([r,n],(o,a)=>lr(o>=a));case"==":return Tt([r,n],(o,a)=>lr(o===a));case"!=":return Tt([r,n],(o,a)=>lr(o!==a))}break}case"call":{let r=Object.hasOwn(Ei,e.name)?Ei[e.name]:void 0;if(r){if(!t.fleet)throw new _e(`${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 _e(`${e.name}() takes 1 argument, not ${e.args.length}`,e.at);return t.fleet(e.args[0],r,e.at)}let n=Object.hasOwn(nm,e.name)?nm[e.name]:void 0;if(!n){let s=[...Object.keys(nm),...t.fleet?Object.keys(Ei):[]];throw new _e(`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 _e(`${e.name}() takes ${C2(n.arity)} argument${o===1&&a===1?"":"s"}, not ${e.args.length}`,e.at);return n.call(e.args.map(s=>ur(s,t)),t)}}throw new _e("Unreachable node",0)}var La=e=>Number.isFinite(e)?e:NaN,$b=[{name:"time",unit:"s",what:"the whole event, every lap",read:e=>La(e?.time)},{name:"lapTime",unit:"s",what:"one lap \u2014 the last one completed",read:e=>La(e?.lapTime)},{name:"distance",unit:"m",what:"distance covered",read:e=>La(e?.distance)},{name:"laps",unit:"-",what:"laps completed",read:e=>La(e?.laps)},{name:"energy",unit:"kWh",what:"energy drawn over the event",read:e=>La(e?.energy?.consumed)},{name:"remaining",unit:"-",what:"share of the pack or tank left afterwards",read:e=>La(e?.energy?.remainingFraction)},{name:"finished",unit:"-",what:"1 when the car ran the whole event, else 0",read:e=>e&&!e.incomplete?1:0}],lS=/^[A-Za-z_][A-Za-z0-9_]*$/,L2=new Set([...Object.keys(Pa),...Ib.map(e=>e.name)]);function om(e,t,r=[]){let n=[],o=new Set(r),a=t.map(b=>b.id),s=new Set;for(let b of a)lS.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(!lS.test(b.key)){n.push({key:b.key,message:`"${b.key}" must be one word \u2014 letters, digits and _`});continue}if(L2.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,Vb(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,[...Bb(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=D2(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 _e("fleetmin() and fleetmax() cannot sit inside one another",y)},p=new Set,d={};for(let b of a)for(let g of $b)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 Ib)h[b.name]=[1,1];for(let b of m){let g=i.get(b),y=c.get(b);(to(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=ur(x,{vars:R,ds:k,fleet:f});if(Array.isArray(w))throw new _e("fleetmin() and fleetmax() compare one number per car \u2014 reduce the channel first, e.g. peak(v)",F);return w};try{let x=ur(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 D2(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 E2(e,t,r={}){let n={...r};for(let o of e.eventIds){let a=t.events[o];for(let s of $b)n[`${o}.${s.name}`]=s.read(a)}return{vars:n,laps:new Map,events:t.events}}function uS(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?nS({...n.trace,length:Ci(n)}):null,e.laps.set(t.over,r)}return r?{vars:{...e.vars,...r.vars},ds:r.ds}:null}var mS=e=>Array.isArray(e)?NaN:e;function pS(e,t,r,n={}){let o=Object.keys(t),a=o.map(i=>E2(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=uS(b,i);if(!g)continue;let y=mS(ur(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=uS(f,i);f.vars[i.key]=p?mS(ur(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 Ii(e,t,r){return pS(e,t,!0,r)}function Gb(e,t,r){return pS(e,{car:t},!1,r?{car:r}:void 0).car}var am=class extends Error{problems;constructor(t,r){super(`Ruleset "${t}" does not compile:
|
|
223
|
+
`}function Ar(e){let t=$s(Tv(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 Pv={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},Lv={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},Dv={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},Ev={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},Iv={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},_v={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},Nv={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},Ov={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},If=()=>Ar(Pv),_f=()=>Ar(Lv),Nf=()=>Ar(Dv),Of=()=>Ar(Ev),Vf=()=>Ar(Iv),Bf=()=>Ar(_v),$f=()=>Ar(Nv),Gf=()=>Ar(Ov);var Vv=e=>Number.isFinite(e)&&e>0;function Gl(e,t){let r=Vv(t.grip)?t.grip:1,n=Vv(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 Ks={ok:!0,violation:0},Gn=1e7;function Fr(e,t){let r;try{r=e.build(t)}catch(s){return{total:Gn*2,feasible:!1,terms:[],reason:`build failed: ${String(s)}`}}let n=e.feasible(r);if(!n.ok)return{total:Gn+Math.max(0,n.violation),feasible:!1,terms:[],reason:n.reason};let o;try{o=e.terms(r)}catch(s){return{total:Gn*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:Gn*2,feasible:!1,terms:o,reason:"objective was not finite"}}var Hs=(e,t)=>!t||(e.feasible!==t.feasible?e.feasible:e.total<t.total);function Kf(e,t){return t.map((r,n)=>Math.min(e[n].hi,Math.max(e[n].lo,r)))}var wr=e=>e.map(t=>t.start);function Kl(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 hL(e){let t=0;for(;t===0;)t=e();return Math.sqrt(-2*Math.log(t))*Math.cos(2*Math.PI*e())}function Hf(e,t){let{budget:r}=t,n=Math.max(1,Math.floor(t.progressEvery??1)),o=e.variables,a=p=>Kf(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=Fr(e,a(d));h.feasible||c++;let b=Hs(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):wr(o),score:l??Fr(e,wr(o)),evaluations:i,history:m,infeasible:c})}}var zf=(e,t,r,n=0,o)=>{let a=t?r.norm(wr(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 Bv(e,t){let r=Hf(e,t),n=Kl(t.seed??1),o=e.variables.length;for(r.evaluate(zf(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 sa(e,t){let r=Hf(e,t),n=e.variables.length,o=Kl(t.seed??1),a=1,s=2,i=.5,c=.5,l=zf(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 $v(e,t){let r=Hf(e,t),n=e.variables.length,o=Kl(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=zf(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 S=0;S<a&&r.left()>0;S++){let A=[];for(let L=0;L<n;L++)A.push(hL(o));let P=g.map((L,D)=>L+y*R[D]*A[D]);M.push({z:A,u:P,f:r.evaluate(P)})}if(M.length<s)break;M.sort((S,A)=>S.f-A.f);let F=g.slice(),w=new Array(n).fill(0);g=new Array(n).fill(0);for(let S=0;S<s;S++)for(let A=0;A<n;A++)g[A]+=i[S]*M[S].u[A],w[A]+=i[S]*M[S].z[A];g=g.map(S=>Math.min(1,Math.max(0,S)));for(let S=0;S<n;S++)k[S]=(1-u)*k[S]+Math.sqrt(u*(2-u)*l)*w[S];let C=Math.sqrt(k.reduce((S,A)=>S+A*A,0)),T=C/Math.sqrt(1-(1-u)**(2*x))/b<1.4+2/(n+1)?1:0;for(let S=0;S<n;S++){let A=(g[S]-F[S])/(y*R[S]);v[S]=(1-f)*v[S]+T*Math.sqrt(f*(2-f)*l)*A}for(let S=0;S<n;S++){let A=0;for(let D=0;D<s;D++)A+=i[D]*M[D].z[S]*M[D].z[S];let P=R[S]*R[S],L=(1-d-h)*P+d*(v[S]*v[S]+(1-T)*f*(2-f)*P)+h*A*P;R[S]=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 ia=[{name:"random",run:Bv},{name:"nelder-mead",run:sa},{name:"sep-cma-es",run:$v}];var OH=Math.PI/180;var Hl=Math.PI/180;var GH={Fz:100,alpha:.25*Hl,kappa:.005,gamma:.5*Hl,p:6900},Gv={Fz:100,alpha:1*Hl,kappa:.02,gamma:.5*Hl,p:6900};var Kv=Math.PI/180,jH={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:Kv},gamma:{rad:1,deg:Kv},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 ZH=Math.PI/180;var wL=Math.PI/180;var az=3*wL;var uz=Math.PI/180;var kz=Math.PI/180;var _L={RCX1:1,RCY1:1,REX1:0,REY1:0,RBY3:0,RHX1:0,RHY1:0},Yv={RBX1:15,RBX2:15,RBY1:18,RBY2:19,..._L};var Ez=Math.PI/180;var GL=Math.PI/180,zl=[{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"}],Uz=new Map(zl.map(e=>[e.id,e]));var Xz=.01*GL;var We=Math.PI/180;var Uv=new Set(zl.filter(e=>e.group!=="inputs"&&(e.unit==="N"||e.unit==="N\xB7m"||e.unit==="N/rad")).map(e=>e.id)),Xv={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}},Xf={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 qf={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,...Xv[t],...o}],x:t,y:r,...n}),Yl=(e,[t,r],n,o,a={})=>({id:e,form:"carpet",sweep:[{input:t,...Xf[t]},{input:r,...Xf[r]}],x:n,y:[o],...a}),Cr=(e,t)=>({id:e,fixed:t}),Bt={input:"Fz",values:"car"},Uf={alpha:0,kappa:0},yt={kappa:0},Wv={alpha:0},HL={input:"Fz",values:[500,1e3,1500]},zL=[{id:"overview",name:"Overview",cards:[Cr("tyre","tyre"),ke("fy","alpha",["Fy"],{title:"Lateral force",hold:yt}),ke("mz","alpha",["Mz"],{title:"Aligning moment",hold:yt}),ke("fx","kappa",["Fx"],{title:"Longitudinal force",hold:Wv}),Yl("combined-carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Cr("ellipse","ellipse")]},{id:"lateral",name:"Lateral",cards:[ke("fy-load","alpha",["Fy"],{title:"Lateral force per wheel load",series:Bt,hold:yt}),ke("muy-load","alpha",["muY"],{title:"Lateral force per unit load",series:Bt,hold:yt}),ke("fy-peak","alpha",["Fy"],{title:"Lateral force over its peak",series:Bt,hold:yt,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:Bt,hold:yt}),ke("trail","alpha",["t"],{title:"Pneumatic trail",series:Bt,hold:yt},{from:0,to:12*We,n:49}),ke("mzr","alpha",["Mzr"],{title:"Residual aligning moment",series:Bt,hold:yt},{from:0,to:12*We,n:49}),Yl("gough",["alpha","Fz"],"Fy","Mz",{title:"Gough plot",hold:yt}),ke("steering-feel","alpha",["t"],{title:"Steering feel",x:"FyRel",series:Bt,hold:yt},{from:0,to:12*We,n:49})]},{id:"longitudinal",name:"Longitudinal",cards:[ke("fx-load","kappa",["Fx"],{title:"Longitudinal force per wheel load",series:Bt,hold:Wv}),ke("mux-peak","Fz",["muXPeak"],{title:"Peak longitudinal \u03BC over load"}),ke("kx","Fz",["dFxdk"],{title:"Slip stiffness at zero slip over load",hold:Uf}),ke("kappa-peak","Fz",["kappaPeak"],{title:"Slip ratio at the peak over load"})]},{id:"combined",name:"Combined",cards:[Yl("carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Yl("envelope-load",["kappa","alpha"],"Fy","Fx",{title:"Friction envelope per load",scale:{per:"Fz"},facet:HL}),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]}}),Cr("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:yt}),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",...qf.gamma},{input:"Fz",...qf.Fz,follow:!0}],x:"gamma",y:["Fz"],z:"muYPeak"},ke("camber-stiffness","alpha",["dFydg"],{title:"Camber stiffness at the point",series:Bt,hold:yt}),ke("mx","alpha",["Mx"],{title:"Overturning moment",series:Bt,hold:yt})]},{id:"rolling",name:"Rolling and radius",cards:[ke("my","V",["My"],{title:"Rolling-resistance moment",series:Bt,hold:Uf}),ke("radius","Fz",["R0","Rl","Re"],{title:"Radius over load"},{from:0}),ke("p-roll","V",["Proll"],{title:"Rolling power",series:Bt,hold:Uf})]},{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:yt,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:[Cr("operating","operating"),Cr("wheels","wheels")]},{id:"fit",name:"Fit check",cards:[Cr("fitLateral","fitLateral"),Cr("fitLongitudinal","fitLongitudinal"),Cr("fitCoupling","fitCoupling"),Cr("fitEnvelope","fitEnvelope")]}];var QL=5670374e-14,Qf=273.15,Zv=.95,Jv=60,Wl=10,ZL=.55,At=25,Zf=-20,Jf=50,Ys={tempC:[20,100,200,550,650,750],factor:[.8,.92,1,1,.85,.65]},Ws={discMassKg:.5,discOuterMm:220,specificHeatJPerKgK:460,emissivity:.6,coolingWPerM2K:200,padCurve:{tempC:[...Ys.tempC],factor:[...Ys.factor]}},jl={...Ws,discMassKg:.4,discOuterMm:200,padCurve:{tempC:[...Ys.tempC],factor:[...Ys.factor]}};function eh(e,t){let r=t==="front"?Ws:jl,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 JL=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},zs=(e,t,r,n)=>Math.min(r,Math.max(t,JL(e,n)));function eD(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 th(e,t){return{discMassKg:zs(e?.discMassKg,.05,20,t.discMassKg),discOuterMm:zs(e?.discOuterMm,50,600,t.discOuterMm),specificHeatJPerKgK:zs(e?.specificHeatJPerKgK,100,3e3,t.specificHeatJPerKgK),emissivity:zs(e?.emissivity,.02,1,t.emissivity),coolingWPerM2K:zs(e?.coolingWPerM2K,Wl,5e3,t.coolingWPerM2K),padCurve:eD(e?.padCurve,t.padCurve)}}function Ul(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 rh(e,t=1){let r=e.discMassKg*e.specificHeatJPerKgK,n=e.discOuterMm*.001/2,o=2*Math.PI*n*n,a=Jv/3.6,s=e.emissivity*QL*o,i=m=>Wl+(e.coolingWPerM2K-Wl)*Math.pow(Math.max(0,m)*t/a,ZL),c=(m,f,p)=>{let d=m+Qf,h=p+Qf;return i(f)*o*(m-p)+s*(d**4-h**4)},l=(m,f)=>i(f)*o+4*s*Math.max(0,m+Qf)**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=>Ul(e.padCurve,m),window:e1(e.padCurve)}}function Xl(e,t,r,n,o,a,s=At){let i=n.length,c=new Array(i),l=new Array(i),u=new Array(i),m=Zv/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 e1(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])&&Ul(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 nh=1e5,o1=.001,Kn={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},ah={fullAtBar:10,maxPowerKw:0,fadeBelowKmh:0,distribution:"equal"};var sh=s1(Ql(Kn,"Formula Student brakes")),ih=40,a1={ideal:!1,barFront:Kn.barFront,pedalForceMaxN:0,testSpeedKmh:ih,regen:ah};function t1(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:eh(r,n)};return{...e,front:t(e.front,"front"),rear:t(e.rear,"rear")}}function Ql(e,t){return{name:t,pedalRatio:e.pedalRatio,masterFrontMm:e.masterFrontMm,masterRearMm:e.masterRearMm,valve:e.valve,valveKneeBar:e.valveKneeBar,valveSlope:e.valveSlope,front:t1(e.front),rear:t1(e.rear),adjusterPitchMm:e.adjusterPitchMm,barLengthMm:e.barLengthMm}}function ch(e,t){return i1({...e,barFront:t.barFront,pedalForceMaxN:t.pedalForceMaxN})}function lh(e,t){let r=Pr(t),n=e?sr(e):void 0;return{mode:r.ideal?"tyre":n?"hydraulic":"balance",hydraulic:n?ch(n,r):Kn,regen:r.regen}}var tD=["none","proportioning","limiter"],ql=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},Je=(e,t,r,n)=>Math.min(r,Math.max(t,ql(e,n))),rD=(e,t)=>{let r=ql(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(ql(e?.discs,n==="inboard"?1:t.discs)))),pistonsPerSide:Math.max(1,Math.min(6,Math.round(ql(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:th(e.heat,t.heat??r)}:{}}}function i1(e){let t=Kn;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:tD.includes(e?.valve)?e?.valve:t.valve,valveKneeBar:Je(e?.valveKneeBar,0,200,t.valveKneeBar),valveSlope:Je(e?.valveSlope,0,1,t.valveSlope),front:r1(e?.front,t.front,Ws),rear:r1(e?.rear,t.rear,jl),adjusterPitchMm:rD(e?.adjusterPitchMm,t.adjusterPitchMm),barLengthMm:Je(e?.barLengthMm,0,500,t.barLengthMm)}}function nD(e){let t=ah;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 sr(e){let t=i1(e??void 0),r=typeof e?.name=="string"&&e.name.trim()?e.name:oD;return Ql(t,r)}function Pr(e){return{ideal:e?.ideal===!0,barFront:Je(e?.barFront,.05,.95,Kn.barFront),pedalForceMaxN:Je(e?.pedalForceMaxN,0,5e3,0),testSpeedKmh:Je(e?.testSpeedKmh,5,150,ih),regen:nD(e?.regen)}}var oD="Formula Student brakes";var oh=e=>Math.PI/4*(e*o1)**2;function un(e,t){let r=e.pistonsPerSide*oh(e.pistonDiaMm)*nh;return e.discs*2*e.padMu*r*e.effRadiusMm*o1*e.ratio/Math.max(.05,t)}function c1(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 js(e,t){let r=Math.max(0,t)*e.pedalRatio,n=e.barFront*r/oh(e.masterFrontMm)/nh,o=(1-e.barFront)*r/oh(e.masterRearMm)/nh;return{front:n,rearIn:o,rear:c1(e,o)}}function aD(e,t){let r=js(e,1);return{front:un(e.front,t)*r.front,rear:un(e.rear,t)*r.rearIn}}function Us(e,t){let r=aD(e,t);return r.front/Math.max(1e-12,r.front+r.rear)}function Xs(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=l1(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 l1(e,t){let r=e.fadeBelowKmh/3.6;return r>0?Math.max(0,Math.min(1,t/r)):1}function Tr(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 n1=new WeakMap;function Hn(e){let t=n1.get(e);return t||(t=e.mode==="hydraulic"&&e.hydraulic?iD(e,e.hydraulic):sD(e),n1.set(e,t)),t}function sD(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 iD(e,t){let r=un(t.front,e.tyreRadiusM),n=un(t.rear,e.tyreRadiusM),o=e.regen,a=(c,l)=>{let u=js(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*Tr(o.v,o.front,l),f=p*Tr(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 uh(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 Zl=Fs,cD=.1,zn=(e,t)=>e.a*Math.sqrt(Math.max(0,1-(t/Math.max(1e-9,e.b))**2));function Jl(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 dh(e,t,r){let n=Math.max(0,r-Zl*t.b),o=Math.min(r,Zl*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 fh(e,t,r,n,o=0){let a=Math.max(0,r),s=dh(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/cD)),d=p>0&&a<Zl*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:T=>2*Math.max(0,l-T)};let{lo:R,hi:k}=s,v=Jl(T=>{let S=zn(e,T),A=zn(t,a-T);return Math.min(S+A,2*Math.min(S,A)+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=(T,S,A)=>Math.min(y,Math.max(0,T-A))+Math.min(y,Math.max(0,S-A));return{...g,regenWheel:y,mixedMax:F,regenRoom:T=>{let S=w(i,c,T);if(!(a>0))return S;let A=E=>Zl*E.b*Math.sqrt(Math.max(0,1-(T/Math.max(1e-9,E.a))**2)),P=Math.max(R,a-A(t)),L=Math.min(k,A(e));if(!(P<=L))return S;let D=Jl(E=>Math.min(y,zn(e,E)-T)+Math.min(y,zn(t,a-E)-T),P,L);return Math.max(S,w(e.cap(D),t.cap(a-D),T))}}}var mh=e=>Math.max(e.xNoLock,e.xLock),ph=e=>Math.max(e.mixedMax,2*e.xLock);function ca(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 la(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 qs(e,t,r,n){return e.shares?lD(e,e.shares,t,r,n):uD(e,t,r,n)}function u1(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 lD(e,t,r,n,o){let a=ph(r),s=ph(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=la(r,t.front*b),y=la(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}=u1(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 uD(e,t,r,n){let o=mh(t),a=mh(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 C=.5*(M+F);v(e.demand(C,n))?M=C:F=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),f=Number.isFinite(e.uMax)&&m>=e.uMax,p=v=>{let x=e.demand(v,n),M=ca(t,s(x),x.regenFront),F=ca(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}=u1(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 Lr={regen:!0,regenEfficiency:.6};function Dr(e,t){let r=e.energy??t??Lr;return{regen:r.regen===!0,regenEfficiency:Math.min(1,Math.max(0,Number.isFinite(r.regenEfficiency)?r.regenEfficiency:0))}}function Er(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 m1(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 mt(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 eu(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 Qs(e,t,r){return r.map(n=>mt(e,t,n))}var Zs=e=>e.reduce((t,r)=>r>t?r:t,-1/0),ua=e=>e.reduce((t,r)=>r<t?r:t,1/0);var mD=[-.906179845938664,-.538469310105683,0,.538469310105683,.906179845938664],pD=[.236926885056189,.478628670499366,.568888888888889,.478628670499366,.236926885056189];function hh(e,t,r){let n=.5*(r-t),o=.5*(t+r),a=0;for(let s=0;s<5;s++)a+=pD[s]*e(n*mD[s]+o);return n*a}var dD=Math.PI*2,fD=.5/3.6;function Js(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 bh(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*dD;c[g]=y*o/n,l[g]=s[g]*n/o}let u=Zs(c),m=Er(ua(c),u,u/fD),f=Qs(c,l,m),{front:p,rear:d}=Js(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),d1=.1,f1=.08,h1=0;function gh(e){let t=(r,n)=>r===void 0||!Number.isFinite(r)?n:Math.max(0,r);return{up:t(e.upshiftTime,d1),down:t(e.downshiftTime,f1)}}function yh(e){let t=e.driveKept;return t===void 0||!Number.isFinite(t)?h1:Math.max(0,Math.min(1,t))}function xh(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,$e(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 ma(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 Rh(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 b1=9.81,g1=Math.PI*2;function Ft(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]*(g1/60),a[v]=t[v]/60*g1,s[v]=a[v]*u/l,i[v]=r[v]*l,c[v]=i[v]/u;let m=Zs(s),f=m,p=.5/3.6,d=Er(ua(s),m,m/p),h=Qs(s,c,d),b=Er(ua(t),Zs(t),250),g=Qs(t,o,b).map(v=>v*e.power_scale.value),y,R=f,k;if(e.motorModel?.kind==="ice"){k=xh(e.motorModel,l,u);let v=Er(0,k.vMax,Math.max(2,Math.ceil(k.vMax/p)+1)),x=v.map(w=>Rh(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=bh(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:b1,FG:e.m.value*b1,vMax:R,vVehicle:d,fRad:h,uMotor:b,pMotor:g,vRad:s,fAxle:y,...k?{engine:k}:{}}}var mn=e=>e.motorModel?.kind==="ice"?Js(1,e.motorPlacement==="front"?"front":"rear"):Js(Math.max(1,Math.round(e.motorCount??e.driven_wheels?.value??2)),e.motorPlacement??"rear");function y1(e){let t=mn(e);return t.front>=2||t.rear>=2}function x1(e){return y1(e)?e.motorMount??"hub":"chassis"}function vh(e){if(!e.motorModel)return{front:!1,rear:!0};let t=mn(e);return{front:t.front>0,rear:t.rear>0}}function kh(e){let t=mn(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=x1(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 pt(e){return lh(e.brakeModel,e.brakeSetup)}function tu(e){return Pr(e.brakeSetup).ideal?"tyre":e.brakeModel||e.brakeModelId?"hydraulic":"balance"}function R1(e,t){if(!(ft(e.motorModel)||!Dr(e).regen))return Xs(ru(Ft(e)),t??pt(e).regen)}function ru(e){return e.fAxle??{vVehicle:e.vVehicle,fFront:e.vVehicle.map(()=>0),fRear:e.fRad.map(t=>t*e.params.driven_wheels.value)}}function Mh(e,t=pt(e)){if(t.mode==="hydraulic")return Us(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 Sh(e,t=pt(e)){return{front:t.hydraulic.front.location==="inboard",rear:t.hydraulic.rear.location==="inboard"}}function Ah(e){let t=pt(e);return{brakeBalanceFront:Mh(e,t),brakeInboard:Sh(e,t)}}function v1(e,t=pt(e)){if(t.mode==="tyre"||t.regen.distribution!=="wheel"||ft(e.motorModel))return;let r=mn(e),n={front:r.front>=2,rear:r.rear>=2};return n.front||n.rear?n:void 0}function ei(e){let t=pt(e),r=e.r_dyn.value,n=Sh(e,t),o=Mh(e,t),a=v1(e,t),s=t.mode==="hydraulic"||a?R1(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 bD=9.81;function Fh(e,t){if(ft(e.motorModel))return()=>0;let r=pt(e),n=Xs(t,r.regen);if(r.mode==="hydraulic"){let a=Hn({mode:"hydraulic",balanceFront:Us(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"?gD(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,Tr(n.v,n.front,s))+Math.min((1-c)*a,Tr(n.v,n.rear,s))}}function gD(e){let t=e.m.value*bD,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 k1(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 wh={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"},...k1("front"),...k1("rear")},Ch={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 Th(e){let t=wh[e];return`${t.label}, ${t.section}`.toLowerCase()}function Ph(e){let t=Ch[e];return t.section?`${t.section} ${t.label.charAt(0).toLowerCase()}${t.label.slice(1)}`:t.label}var M1=new WeakMap;function ir(e){if(e.brakes)return e.brakes;let t=M1.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},M1.set(e,t)}return t}var Ir=e=>Hn(ir(e));var vD=Math.PI/180,pa=Object.freeze({tbr:1,preloadN:0}),nu=Object.freeze({tbr:1/0,preloadN:0}),Dh=e=>e.faces*e.muClutch*e.rFrictionMm/e.rRampMm;function Eh(e,t){if(!(e>0)||Number.isNaN(t))return 0;let r=Math.tan(Math.min(90,t)*vD);return r>0?Math.min(1,e/r):1}function A1(e){if(e>=1)return 1/0;let t=e>0?e:0;return(1+t)/(1-t)}function ou(e){return e===1/0?1:e>1?(e-1)/(e+1):0}function da(e,t){return e.tbr===1/0?1/0:(e.preloadN>0?e.preloadN:0)+ou(e.tbr)*Math.abs(t)}function ri(e,t,r){let n=o=>o!==void 0&&o>0&&r>0?o/r:0;switch(e.kind){case"open":return pa;case"spool":return nu;case"independent":return t==="hubs"?pa:nu;case"clutch":{let o=n(e.preloadNm);return t==="hubs"?{tbr:1,preloadN:o}:{tbr:A1(Eh(Dh(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 ti(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 S1=4;function Lh(e,t){let r=0;for(let a of e)r=Math.max(r,ti(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,ti(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 ni(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=dh(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=Jl(b=>zn(e,b)+zn(t,c-b),l.lo,l.hi),f=[{m1:l.c1,m2:l.c2}];for(let b=1;b<=S1&&m!==l.y1;b++){let g=l.y1+(m-l.y1)*b/S1;f.push({m1:e.cap(g),m2:t.cap(c-g)})}let p=Lh(f,pa),d=Lh(f,nu);if(!(d>p))return u;let h=(Lh(f,{tbr:s,preloadN:i})-p)/(d-p);return Math.min(a,u+(a-u)*Math.min(1,Math.max(0,h)))}function F1(e,t,r,n,o,a){return Ih(e,o,ni(t,r,n,o,a))}function Ih(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 _h(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 w1(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 T1(e,s,c,d,h,b,n,l,a);s=d,c=b}return null}function C1(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 T1(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 T1(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 au(e,t){return Math.abs(e.fx-e.x)>t?e.x:e.fx}var kD=(e,t)=>{let r=e.brakes?.hydraulic?.[t];return!!r&&r.location==="inboard"&&r.discs===1};function $t(e,t,r){let n=e.driveline?.[t];if(n)return r>=0?n.drive:kD(e,t)?n.coast:n.hubs}var P1=e=>e.tbr>1||e.preloadN>0;var MD=9.81,L1=["FL","FR","RL","RR"],Nh=e=>e==="FL"||e==="FR",su=e=>Nh(e)?"front":"rear",D1={front:["FL","FR"],rear:["RL","RR"]},si=()=>({peak:new Map,freeBrake:new Map}),ai=25;function oi(e,t){let r=Math.max(0,e)/ai,n=Math.floor(r),o=r-n,a=t(n);return o>0?a+o*(t(n+1)-a):a}var pn=1e-4,SD=.05;function _r(e,t,r,n=si(),o=!1){let a=r,s=e.massTotal,i=n.peak,c=(S,A)=>{let P=`${S}:${A}`,L=i.get(P);return L||(L=xl(ge(t,S),Math.max(1,A*ai)),i.set(P,L)),L},l=(S,A)=>({aPeak:oi(A,P=>c(S,P).aPeak),fyPeak:oi(A,P=>c(S,P).fyPeak)}),u=n.freeBrake,m=(S,A)=>{let P=`${S}:${A}`,L=u.get(P);if(L===void 0){let D=Math.max(1,A*ai);L=St(ge(t,S),D,0,!0,c(S,A)),u.set(P,L)}return L},f=(S,A)=>A>0?oi(A,P=>m(S,P)):0,p=Ir(e),d=ir(e),h=S=>d.regen&&d.regenPerWheel?.[S]?Tr(d.regen.v,d.regen[S],a)/2:0,b=h("front"),g=h("rear"),y=(S,A,P)=>{let L=Math.max(0,A[S]),D=l(su(S),L);return St(ge(t,su(S)),L,P[S]*D.fyPeak,!0,D)},R=(S,A,P,L,D=!0)=>{let E=te=>{let fe=Math.max(0,A[te]),W=ge(t,S),J=l(S,fe);return{Fz:fe,a:Math.abs(f(S,fe)),b:J.fyPeak,slide:fe>0?Math.abs(W.forces({Fz:fe,kappa:-1,alpha:0}).Fx):0,cap:re=>Math.abs(St(W,fe,re,!0,J))}},V=te=>Math.abs(P[te])*l(su(te),Math.max(0,A[te])).fyPeak,[N,z]=D1[S],I=E(N),_=E(z),B=V(N)+V(z),O=fh(I,_,B,L,S==="front"?b:g),G=D?O:{...O,xLock:0},K=$t(e,S,-1),Y=K&&P1(K)?K:void 0;if(!Y)return{axle:S,eq:G,cap:G};let j=Number.isFinite(L)?L:I.cap(V(N))+_.cap(V(z)),Z=F1(G,I,_,B,Y,j);return{axle:S,eq:G,cap:Z,law:Y,strong:()=>I.cap(V(N))>=_.cap(V(z))?N:z}},k=(S,A,P,L)=>R(S,A,P,L).cap,v=(S,A,P)=>{let L=S.demand,D=p.shares?la(A,L.front):ca(A,(L.front-L.regenFront)/2,L.regenFront),E=p.shares?la(P,L.rear):ca(P,(L.rear-L.regenRear)/2,L.regenRear);return{front:Number.isFinite(D)?D:0,rear:Number.isFinite(E)?E:0}},x=S=>({muX:A=>A>0?Math.abs(f(S,A))/A:0,muY:A=>A>0?l(S,A).fyPeak/A: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},C=(S,A,P,L,D)=>{let E=L.cap,V=D.cap,N=qs(p,E,V,a),z={arms:F,halfTrack:w,ayDir:Math.sign(S)};for(let I=0;I<2;I++){let _=v(N,E,V),B={};for(let G of L1){let K=Math.max(0,A[G]);B[G]={Fz:K,Fy:Math.abs(P[G])*l(su(G),K).fyPeak,Fx:-(Nh(G)?_.front:_.rear)/2}}let O=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 Ih(G.eq,G.law,$l(K,B,M,z))};E=O(L),V=O(D),N=qs(p,E,V,a)}return{limit:N,front:E,rear:V}};return{peakAt:l,axle:k,ceiling:(S,A,P)=>{let[L,D]=D1[S];return Math.abs(y(L,A,P)+y(D,A,P))},limitAt:(S,A,P,L=0)=>{let D={FL:0,FR:0,RL:0,RR:0},E=Ce(e,S,0,a,0,A),V,N=fe=>(V?.ax!==fe&&(V={ax:fe,loads:Ce(e,S,(fe+L)/MD,a,0,A)}),V.loads),z=Rl(fe=>ea(P,N(fe),E,l).short,-L,-1),I=P,_={front:0,rear:0},B,O,G=(fe,W=!0)=>{let J=z.at(fe);D=N(J),I=ea(P,D,E,l).util;let re=0,pe=0,de=0;for(let ie of L1){let oe=y(ie,D,I);re+=oe,Nh(ie)?pe+=oe:de+=oe}if(_={front:Math.abs(pe),rear:Math.abs(de)},p.mode!=="tyre"){let ie=R("front",D,I,Math.abs(pe),W),oe=R("rear",D,I,Math.abs(de),W);if(o&&(ie.law||oe.law)){let ue=C(S,D,I,ie,oe);B=ue.limit,O={front:ue.front,rear:ue.rear}}else B=qs(p,ie.cap,oe.cap,a),O={front:ie.cap,rear:oe.cap};re=-B.force}return re/s},K=_h(G,0,pn),Y=au(K,pn),j=Y;if(B?.lockFront||B?.lockRear){let fe=_h(J=>G(J,!1),0,pn);j=au(fe,pn);let W=w1(G,fe.x,K.x,pn,SD);W||G(K.x),Y=au(W??K,pn)}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:O};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 cu=9.81;function AD(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 _1=(e,t)=>t.mode==="hydraulic"&&!!ir(e).regen;function fa(e,t,r=0,n,o=0){if(!e.brakes&&e.brakeBalanceFront==null)return e.frontMassFrac;let a=Ir(e);if(a.shares&&a.mode!=="tyre")return a.shares.front;let s=n&&_1(e,a)?N1(e,n):void 0,i=s?.shares??E1.get(e);i||E1.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=O1(c,l,u),f=i.get(m);if(f===void 0){let p=-c*.005,d=l*.25,h=e.massTotal*Math.abs(p)*cu;if(s){let b=B1(a,V1(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"?AD(e,p,d):uh(a,h,d);i.size>5e4&&i.clear(),i.set(m,f)}return f}var E1=new WeakMap;function lu(e,t,r,n,o=0){let a=Ir(e);if(!_1(e,a))return;let s=Math.round(Math.max(0,r)/(e.massTotal*cu)/.005),i=Math.round(Math.max(0,n)/.25);return B1(a,V1(e,N1(e,t),s,i,Math.round(o/.01)),Math.max(0,r),n)}var I1=new WeakMap;function N1(e,t){let r=I1.get(e);r||I1.set(e,r=new WeakMap);let n=r.get(t);return n||r.set(t,n={ev:t,tyres:si(),shares:new Map,rooms:new Map,speeds:new Map}),n}var O1=(e,t,r)=>(r*1001+e)*100003+t;function V1(e,t,r,n,o){let a=O1(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:_r(e,t.ev,i,t.tyres),dragG:-Math.max(0,ss(e,i).drag)/(e.massTotal*cu)},t.speeds.set(n,l));let{cap:u}=l,m=Ce(e,c,-r*.005+l.dragG,i),f=Math.abs(c)*e.massTotal*cu,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 iu(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 B1(e,t,r,n){if(!(r>0))return iu(e,t,1,n);let o=c=>c.front+c.rear,a=e.controlFor(r,n),s=iu(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=iu(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=iu(e,t,l,n);o(u)<r?a=l:(i=l,s=u)}return s}var ha={rel:.003,abs:2,kappa:1e-5,iters:12},Oh={rel:1e-6,abs:.001,kappa:1e-12,iters:40};function Yn(e,t,r,n=ha){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=CD(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 $1=1e-6,FD=40,wD=(3-Math.sqrt(5))/2;function CD(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-$1),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<FD;g++){let y=$1*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),C=(o-u)*w-(o-l)*F;w=2*(w-F),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 S=o+b;(S-r<2*y||c-S<2*y)&&(b=R>=o?y:-y),k=!1}}k&&(h=o>=R?r-o:c-o,b=wD*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 uu=e=>Math.max(2,.003*Math.abs(e)),TD=(e,t)=>Math.max(t.abs,t.rel*Math.abs(e)),Vh=.5,PD=.03;function LD(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=TD(r,o),c=Math.max(-Vh,Math.min(Vh,n)),l=s(c);if(Math.abs(c)>PD){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)>Vh)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 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 G1(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 Bh(e,t,r,n,o,a=ha){let s=LD(e,t,r,o,a),i=s.fr.Fx-s.fl.Fx,c=da(n,r);if(Math.abs(i)<=c){let R=r-(s.fl.Fx+s.fr.Fx),k=Math.max(0,Math.abs(R)-uu(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=Yn(e.at,u,e.seed||s.kl,a),p=Yn(t.at,m,t.seed||s.kr,a),d=Math.abs(u-f.forces.Fx)>uu(u),h=Math.abs(m-p.forces.Fx)>uu(m),b=Math.max(0,n.preloadN),g=ou(n.tbr);d&&!h?p=Yn(t.at,G1(f.forces.Fx,l,b,g),p.kappa,a):h&&!d&&(f=Yn(e.at,G1(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)-uu(k))});return{left:y(f,u),right:y(p,m),locked:!1,spoolKappa:s.kappaM}}var DD={front:["FL","FR"],rear:["RL","RR"]},ED=Object.freeze({Fx:0,Fy:0,Mz:0});function mu(e,t,r,n){let o=r;for(let a of["front","rear"]){let[s,i]=DD[a],c=r[s]+r[i],l=$t(e,a,c);if(!l||!(da(l,c)>0))continue;let u=ge(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}):()=>ED,vx:Math.max(.05,1-b*n.curvature),seed:0}},d=Bh(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,ID=8,_D=1e-6,fn=["FL","FR","RL","RR"],jt=e=>e==="FL"||e==="FR",dn=e=>jt(e)?"front":"rear";function ci(e,t){let r=ge(e,"front"),n=ge(e,"rear");return r===n?jn(r,t):{front:jn(r,t),rear:jn(n,t)}}function jn(e,t){return Lf(e,Math.min(t,Wt(e)))}var du=e=>e==="FL"||e==="RL";function ga(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,fa(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 Wh(e,t,r,n){return Math.abs(Un(e,t,r,n!==void 0?{steerMaxDeg:n}:{}).peak.steerDeg)}function jh(e,t,r,n){let o=e.tv;if(!o?.enabled)return 0;let a=ck(o)(t,Math.abs(r),n);return r<0?-a:a}function Uh(e,t,r=0,n,o=0,a=0,s){let i=ga(e,{axG:t,driveFrontFrac:a},r,n,o),c=i?i.fx:{FL:0,FR:0,RL:0,RR:0};return i&&s&&n?mu(e,n,c,s):c}var li=e=>du(e)?-1:1,Xh=(e,t,r,n,o)=>t*e.Fy(t*r,n,t*o);function zh(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 ND(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?qo(o,n/se,u?r.FL:r.FR,u?r.FR:r.FL):Qo(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 Xn(e,t,r){let n=(e.toeFrontDeg??0)*se,o=(e.toeRearDeg??0)*se,a=ND(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 qh(e,t,r){if(r.Fz<=0)return 0;let n=ut(ge(e,dn(t))),o=li(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 K1(e,t,r,n){if(!$n(e))return null;let o=ut(ge(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:qh(o,s,i)}}return Vs(e,r/se,a,sn(o.model),{FL:n.FL.travelMm,FR:n.FR.travelMm})}var H1=()=>({totalNm:[],aligningNm:[],lateralNm:[],longitudinalNm:[],jackingNm:[]});function z1(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 OD=Object.freeze({Fx:0,Fy:0,Mz:0});function Y1(e,t,r){let n=t==="front"?(r?.FL??0)+(r?.FR??0):(r?.RL??0)+(r?.RR??0),o=$t(e,t,n);return o&&da(o,n)>0?{F:n,law:o}:null}function wt(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}=zh(e),h=Y1(e,"front",l),b=Y1(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=ut(ge(t,"front")),v=ut(ge(t,"rear")),x=e.trackFront/2e3,M=e.trackRear/2e3,F=!!(e.kinFront&&e.kinRear),w=F&&y===null?ln(e,e.kinFront,e.kinRear,r):null,C=NaN,T=null,S=W=>{if(!F)return null;if(y===null)return w;let J=R(W);return J!==C&&(C=J,T=ln(e,e.kinFront,e.kinRear,J)),T},A={},P={FL:0,FR:0,RL:0,RR:0},L=e.kinFront?.compliance,D=e.kinRear?.compliance,E=!!(L||D),V=!!(L?.toePerMz||D?.toePerMz),N=W=>jt(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}},I=!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=S(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,Be=gl(e,W/Me,u,ie,n/se,o/se,ue,oe?.steeringJacking),Ae=Be.loads;I=Be.overturned;let le=Xn(e,o,ue),Re=le.steer,Te=0,ze=be=>{let Fe=Math.max(0,Ae[be]),xe=li(be),me=jt(be)?k:v,Le=N(be),Se=0,Ye=0;if(Le){let Pn=z[be];Se=Le.toePerFy*Pn.fy+Le.toePerFx*Pn.fx+Le.toePerMz*Pn.mz,Ye=Le.camberPerFy*Pn.fy+Le.camberPerFx*Pn.fx}let Ue=Re[be]+(oe?xe*oe[be].bumpToe*se:0)+xe*Se*se,zt=Ue-(jt(be)?re:pe),Tn=(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:zt,camberRad:Tn}},je=(be,Fe)=>{let xe=y===null?J/r:1/y,me=jt(be)?f:-p,Le=(du(be)?1:-1)*(jt(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}):()=>OD,vx:Math.max(.05,Se),seed:P[be]}};for(let be=0;be<(E?ID:1);be++){Te=0;let Fe=0,xe={};for(let me of fn){let Le=jt(me)?h:b;if(Le&&!xe[me]){let[Eo,Et]=jt(me)?["FL","FR"]:["RL","RR"],Kc=ze(Eo),Uy=ze(Et),Xy=dn(me),Wp=Bh(je(Eo,Kc),je(Et,Uy),Le.F,Le.law,g[Xy],Oh);g[Xy]=Wp.spoolKappa,xe[Eo]={w:Kc,share:Wp.left},xe[Et]={w:Uy,share:Wp.right}}let Se=xe[me]?.w??ze(me),{Fz:Ye,mir:Ue,t:zt,gains:Tn,complianceToe:Pn,steerK:Kp,slip:Hp,camberRad:zp}=Se,rs=l?.[me]??0,Po,Lo=0,Yp=0,Gc=0,Do=xe[me]?.share;if(Do)P[me]=Do.kappa,Yp=Do.kappa,Lo=Do.forces.Fx,Gc=Do.short,Po=Ue*Do.forces.Fy;else if(rs===0||Ye<=0)Po=Xh(zt,Ue,Hp,Ye,zp),Gc=Ye<=0?Math.abs(rs):0;else{let Et=Yn(Kc=>zt.forces({Fz:Ye,kappa:Kc,alpha:Ue*Hp,gamma:Ue*zp}),rs,P[me],Oh);P[me]=Et.kappa,Yp=Et.kappa,Lo=Et.forces.Fx,Gc=Math.max(0,Math.abs(rs-Lo)-Math.max(ha.abs,ha.rel*Math.abs(rs))),Po=Ue*Et.forces.Fy}if(A[me]={Fz:Ye,travelMm:oe?.[me].travel??0,steerRad:Kp,slipRad:Hp,camberRad:zp,Fy:Po,Fx:Lo,kappa:Yp,fxShort:Gc,lifted:Be.lifted[me]},Tn){let Eo=V&&Tn.toePerMz?qh(zt,me,A[me]):0;z[me]={fy:-Ue*Po,fx:Lo,mz:-Ue*Eo*1e3};let Et=z[me];Fe=Math.max(Fe,Math.abs(Tn.toePerFy*Et.fy+Tn.toePerFx*Et.fx+Tn.toePerMz*Et.mz-Pn))}Te+=Po*Math.cos(Kp)+Lo*Math.sin(Kp)}if(Fe<_D)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},O=Math.max(20,3.5*B(r)/d);if(y!==null){O=4*Me;for(let W=0;W<8;W++){let J=Math.min(40*Me,3.5*B(R(O))/d);if(J<=O)break;O=J}O=Math.max(20,O)}let G=W=>_(W)-W,K=Math.max(.001,O*1e-4),Y=(W,J,re,pe)=>{let de=W,ie=re,oe=J,ue=pe,Be=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(Be=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 Be},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),O);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 Be=pe?O/24:Math.max(O/24,Math.abs(ue-W)/4);for(let Ae=1;Ae<=24;Ae++){let le=ie+re*Be;if(Math.abs(le)>O)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)<=O){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||(A.RL.Fy+A.RR.Fy)*W<0){let J={...A},re=I,pe=W*Math.max(Z*W+K,n*W*r*r/p),de=null;if(pe*W<O){let ie=G(pe);if(ie*W>0)de=j(pe,ie,W).root;else{let oe=pe+W*O/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(A,J),I=re)}}let fe=f*(A.FL.Fy*Math.cos(A.FL.steerRad)+A.FR.Fy*Math.cos(A.FR.steerRad))-p*(A.RL.Fy+A.RR.Fy);if(s||h||b){let W=J=>(du(J)?1:-1)*(jt(J)?x:M);for(let J of fn){let re=A[J],pe=jt(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:A,overturned:I,res:NaN}:{ay:Z/Me,cn:fe/(d*Me*m),wheels:A,overturned:I,res:te-Z}}function VD(e,t,r,n,o,a,s,i=0){let c=20*se,l=.001,u=(h,b)=>{let g=wt(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 C of[v.pos,v.neg]){let T=C===v.pos?1:-1,S=h+T*b[w];if(Math.abs(S)>c)continue;let A=u(S,C.ay);if(Math.abs(A.cn)<F&&m(A.ay)&&(F=Math.abs(A.cn),M=S),A.cn===0&&m(A.ay))return{beta:S,trimmed:!0};if(A.cn<0!=C.cn<0){let P={lo:C.b,hi:S,ayLo:C.ay},L=W1(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=S,C.cn=A.cn,y!==void 0&&(C.ay=A.ay)}return x?{beta:W1(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=BD(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 W1(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 BD(e,t,r,n,o,a,s){let i=(f,p)=>{let d=wt(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<$D;f++){let p=i(c+$h,l),d=i(c,l+Gh),h=(p.r-u.r)/$h,b=(d.r-u.r)/Gh,g=(p.c-u.c)/$h,y=(d.c-u.c)/Gh,R=h*y-b*g;if(!Number.isFinite(R)||R===0||Math.abs(R)<zD*(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,GD/Math.max(Math.abs(k),1e-300),KD/Math.max(Math.abs(v),1e-300));if(c+=x*k,l+=x*v,Math.abs(c-o)>HD||Math.abs(c)>s||l*a<0)return null;u=i(c,l)}return null}var $D=8,$h=1e-5,Gh=.001,GD=1*se,KD=2,HD=5*se,zD=.5;function J1(e,t,r,n,o,a,s,i){let c=wt(e,t,r,n,o,a,s,void 0,i),l=c.ay*Me/r,u={},m=0;for(let d of fn){let h=c.wheels[d],b=ge(t,dn(d)),g=Wt(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:qh(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=Vs(e,o/se,u,sn(ge(t,"front").model),{FL:c.wheels.FL.travelMm,FR:c.wheels.FR.travelMm}),p=Xn(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 Or(e,t,r,n,o,a,s=0){let i=Math.max(8,r),c=Wn(e,t,i,n,o,a,s);return n!==0&&o?.driving===void 0&&(c.driving=aE(e,t,i,c,a,s)),c}function Wn(e,t,r,n,o,a,s){let i=n*se,c=ga(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}=VD(e,t,r,i,u,l,c,s),d=J1(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)<=YD,h}var YD=3;function Un(e,t,r,n={}){let o=Math.max(8,r),a=n.direction??1,s=n.yawDemandCn??0,i=n.steerMaxDeg??WD,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=Kh.get(e)?.get(t)?.get(l);if(x)return x}let u=(x,M)=>M.trimmed&&Math.abs(M.beta-x.beta)<=fu&&Math.abs(M.ay-x.ay)*Me<=hu,m=!1,f=(x,M)=>{let F=Wn(e,t,o,a*x,M,c(a*x),s);return u(M,F)?(F.driving=!0,F):(m=F.overturned,null)},p=[Wn(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=C=>x.sb*(C.beta-x.state.beta)>0||a*C.steerDeg>=a*x.state.steerDeg||F&&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),d=Math.abs(x.state.steerDeg)},y=(x,M=!1)=>M||rE(p[p.length-1],x)?nE(e,t,o,a,p,x,c,s):null,R=p[0].trimmed?p[0]:null;if(!R){let x=0;for(let M=j1;M<=i&&!R;M+=j1){let F=Wn(e,t,o,a*M,void 0,c(a*M),s);if(F.trimmed){let w=M;R=F;for(let C=0;C<6;C++){let T=.5*(x+w),S=Wn(e,t,o,a*T,void 0,c(a*T),s);S.trimmed?(w=T,R=S):x=T}}else x=M}R&&(R.driving=!0,p.push(R))}if(R){let x=Math.abs(R.steerDeg),M=Math.min(Hh,100/(o*o)),F=R;for(;x<i;){let w=Math.min(i,x+M),C=f(w,F);if(C){let L=y(C);if(L){g(L);break}if(p.push(C),w>=i||ik(e,a*w))break;Math.abs(C.beta-F.beta)<.5*fu&&Math.abs(C.ay-F.ay)*Me<.5*hu&&(M=Math.min(Hh,1.5*M)),x=w,F=C;continue}if(M>jD){M*=.5;continue}let T=m,S=!1,A=null;for(let L of UD){let D=Math.min(i,x+L);if(D<=x)continue;let E=f(D,F);if(E){if(A=y(E,!0),A)break;p.push(E),x=D,F=E,M=Math.min(Hh,100/(o*o)),S=!0;break}}if(S)continue;if(A){g(A);break}d=x,h=T;let P=T?null:tE(e,t,o,a,p,c,s);P&&g(P);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=Kh.get(e);x||(x=new WeakMap,Kh.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 Kh=new WeakMap,WD=90,fu=1.5,hu=2.5,Hh=5,jD=.002,UD=[.5,1],j1=2.5,ek=.01,Nr=.001,XD=.05,qD=.25,QD=5,ZD=2,U1=1e-8,JD=1e-7,eE=1e-6;function tk(e,t,r,n,o,a,s){let i=n*se,c=o.ay*Me,l=b=>{let g=wt(e,t,r,i,b*se,c,ga(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)<U1;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)>ZD)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)>U1;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>hu?null:{steerDeg:h.x,ay:h.ay}}function ii(e,t,r,n,o){let a=J1(e,t,r,n.beta*se,n.steerDeg*se,n.ay*Me,ga(e,o(n.steerDeg),r,t));return{...a,trimmed:!a.overturned,driving:!a.overturned}}function tE(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=ek;Math.abs(g.beta-c.beta)<=fu;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=nk(f,n,b,g,R);if(!k)return null;let v=ii(e,t,r,k,a);return!v.trimmed||Math.abs(v.beta-c.beta)>fu||Math.abs(v.ay-c.ay)*Me>hu?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=tk(e,t,r,s,i,n,o);if(!c)return null;let l={beta:s,...c};return a.push(l),l}}function rE(e,t){let r=Math.abs(t.beta-e.beta);return r>qD&&r>QD*Math.abs(t.steerDeg-e.steerDeg)}function nE(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=ek;f*(a.beta-g.beta)>0;R=Math.min(XD,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=nk(p,n,...y);if(!x)return null;let M=ii(e,t,r,x,s);return M.trimmed?{state:M,sb:f}:null}b=g,g=k}return null}function nk(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*Nr-.5*(i-s))break;let h=!0;if(Math.abs(m)>Nr){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*Nr||i-v<2*Nr)&&(f=d>=c.beta?Nr:-Nr),h=!1}}h&&(m=c.beta>=d?s-c.beta:i-c.beta,f=ak*m);let b=e(Math.abs(f)>=Nr?c.beta+f:c.beta+(f>=0?Nr:-Nr));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 Qh(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 ii(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=tk(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?JD:eE))break;v<0?(m=k,p=v,d*=.5):(f=k,d=v,p*=.5)}return ii(e,t,r,h,i)}function oE(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 Qh(e,t,r,n.fold,a,{steerDeg:o});let u=typeof a.op=="function"?a.op(o):a.op,m=Wn(e,t,r,o,l,u,a.yawDemandCn??0);return m.driving?m:null}function aE(e,t,r,n,o,a){if(!n.trimmed)return!1;let s=n.steerDeg<0?-1:1,{states:i}=Un(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 hn(e,t,r,n,o){let a=Math.max(8,r),s=n>=0?1:-1,i=Math.abs(n),c=(b,g)=>Or(e,t,a,s*b,g,o),l=Un(e,t,a,{direction:s,op:o}),{fold:u}=l;if(u&&Math.abs(u.state.steerDeg)<=ba){if(i>Math.abs(u.state.ay))return q1(e,t,a,s,i,o);if(i>Math.abs(u.stall.ay)){let b=Qh(e,t,a,u,{direction:s,op:o},{ayG:i});if(b)return b}}let m=l.states.filter(b=>Math.abs(b.steerDeg)<=ba),f=m[m.length-1],p=l.states.length>m.length;p&&Math.abs(f.steerDeg)<ba&&m.push(c(ba,f));let d=m.findIndex(b=>Math.abs(b.ay)>=i);if(d===0)return Or(e,t,a,0,void 0,o);if(d>0)return X1(m[d-1],m[d],i,c);let h=ok(m,c,void 0,p||l.foldDeg===null);return h.ay>=i?X1(h.below,h.state,i,c):l.foldDeg!==null&&l.foldDeg<ba?q1(e,t,a,s,i,o):h.state}var ba=20;function X1(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)<=sE||a.steer-o.steer<=iE)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 sE=1e-9,iE=1e-7;function ok(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=cE/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 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,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-lE,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 S=(u-f)*(m-h),A=(u-d)*(m-p),P=(u-d)*A-(u-f)*S;A=2*(A-S),A>0&&(P=-P),A=Math.abs(A);let L=y;if(y=R,Math.abs(P)<Math.abs(.5*A*L)&&P>A*(c-u)&&P<A*(l-u)){R=P/A;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=ak*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,d=f,h=p,f=u,p=m,u=w,m=T,b=C):(w<u?c=w:l=w,T<=p||f===u?(d=f,h=p,f=w,p=T):(T<=h||d===u||d===f)&&(d=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 cE=.001,lE=.01,ak=(3-Math.sqrt(5))/2;function q1(e,t,r,n,o,a){let s=l=>Math.abs(Or(e,t,r,n*l,void 0,a).ay),i=0,c=ba;if(s(c)<o)return Or(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 Or(e,t,r,n*.5*(i+c),void 0,a)}function Zh(e,t,r,n,o){let a=hn(e,t,r,n,o);return a.steering?Math.abs(a.steering.totalNm):NaN}function Jh(e,t,r,n,o){if(!$n(e))return NaN;let a=n<0?-1:1,s=Math.abs(n),i=hn(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=Or(e,t,r,a*u,void 0,o),p=Or(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 Yh(e,t,r,n,o,a){let s=Math.max(8,r),i=wt(e,t,s,n*se,o*se,void 0,ga(e,a,s,t));return{ay:i.ay,cn:i.cn}}function eb(e,t,r,n,o){let a=Math.max(8,r),s=hn(e,t,a,n,o),i=.5,c=Yh(e,t,a,s.beta+i,s.steerDeg,o).cn,l=Yh(e,t,a,s.beta-i,s.steerDeg,o).cn;return(c-l)/(2*i*se)*e.massTotal*Me*(e.wheelbase/1e3)}function tb(e,t,r,n){let o=Math.max(8,r),{branch:a,opts:s}=uE(e,t,o,n);return sk(e,t,o,a,s)}function uE(e,t,r,n){if(!e.tv?.enabled){let s=n?{op:n}:{};return{branch:Un(e,t,r,s),opts:s}}let o=Wh(e,t,r),a={op:s=>{let i=jh(e,r,s,o);return i===0?n:{axG:n?.axG??0,driveFrontFrac:n?.driveFrontFrac,tvRearDiffN:i}}};return{branch:Un(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 ii(e,t,r,n.peak,a);let i=(l,u)=>Wn(e,t,r,l,u,a(l),s),c=n.states[0].driving||!n.peak.driving?n.states:n.states.slice(1);return ok(c,i,c.indexOf(n.peak),n.foldDeg===null).state}function rb(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}=zh(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&&$n(e),R=y?sn(ge(t,"front").model):void 0,k=(I,_,B,O)=>B===1?I:I+(_-I)*O/(B-1),v=e.tv?.enabled?Wh(e,t,a):0,x=I=>{let _=jh(e,a,I/se,v);return!n.axG&&_===0?null:ga(e,{axG:n.axG??0,driveFrontFrac:n.driveFrontFrac,tvRearDiffN:_},a,t)},{lf:M,lr:F}=zh(e),w=n.reserves?ci(t,e.massTotal*Me*1.2):null,C=I=>w?Sr(w,{FL:I.FL,FR:I.FR,RL:I.RL,RR:I.RR},{lf:M,lr:F}):null,T=[],S={ay:[],cn:[]},A=0;for(let I=0;I<b;I++){let _=k(u,m,b,I),B=x(_),O=[],G=[],K=[],Y=[],j=w?{stabil:[],agil:[]}:void 0,Z=y?H1():void 0,ne;for(let W=0;W<g;W++){let J=k(c,l,g,W),re=wt(e,t,a,J,_,ne,B,o);if(ne=Number.isFinite(re.ay)?re.ay*Me:void 0,O.push(re.ay),G.push(re.cn),K.push(J/se),Y.push(_/se),j){let pe=C(re.wheels);j.stabil.push(pe.stabil),j.agil.push(pe.agil)}Z&&z1(Z,K1(e,t,_,re.wheels)),Math.abs(re.ay)>A&&(A=Math.abs(re.ay))}T.push({label:`\u03B4 ${(_/se).toFixed(0)}\xB0`,ay:O,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=O[W-1]+J*(O[W]-O[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&&(S.ay.push(te),S.cn.push(0))}let P=[];for(let I=0;I<b;I++){let _=k(c,l,b,I),B=[],O=[],G=[],K=[],Y=w?{stabil:[],agil:[]}:void 0,j=y?H1():void 0,Z;for(let ne=0;ne<g;ne++){let te=k(u,m,g,ne),fe=wt(e,t,a,_,te,Z,x(te),o);if(Z=Number.isFinite(fe.ay)?fe.ay*Me:void 0,B.push(fe.ay),O.push(fe.cn),G.push(_/se),K.push(te/se),Y){let W=C(fe.wheels);Y.stabil.push(W.stabil),Y.agil.push(W.agil)}j&&z1(j,K1(e,t,te,fe.wheels))}P.push({label:`\u03B2 ${(_/se).toFixed(0)}\xB0`,ay:B,cn:O,betaDeg:G,deltaDeg:K,reserve:Y,steering:j})}let L=.5*se,D=x(h),E,V;if(o===void 0)E=(wt(e,t,a,d+L,h,void 0,D,o).cn-wt(e,t,a,d-L,h,void 0,D,o).cn)/(2*L),V=(wt(e,t,a,d,h+L,void 0,x(h+L),o).cn-wt(e,t,a,d,h-L,void 0,x(h-L),o).cn)/(2*L);else{let I=(O,G)=>wt(e,t,a,O,G,void 0,x(G),o).cn,_=(O,G,K)=>Number.isFinite(O)?(-3*O+4*G-K)/(2*L):(K-G)/L,B=I(d,h);E=-_(B,I(d-L,h),I(d-2*L,h)),V=_(B,I(d,h+L),I(d,h+2*L))}let N=0;if(D&&D.axG){let I=wt(e,t,a,d,h,void 0,D,o),_=0;for(let B of fn)_+=I.wheels[B].fxShort;N=_/Math.abs(e.massTotal*D.axG*Me)}let z=S.ay.reduce((I,_)=>Math.max(I,Math.abs(_)),0);return{isoBeta:P,isoDelta:T,trim:S,maxAy:A,stability:E,control:V,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 ik(e,t){return Xn(e,t*se).atLock}function mE(e,t,r,n,o=_r(e,t,r)){let a=r,s=e.massTotal,i=fn.filter(g=>jt(g)?n.drivenFront:n.drivenRear),c=o.peakAt,l={front:n.drivenFront?$t(e,"front",1):void 0,rear:n.drivenRear?$t(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*ai);k=St(ge(t,g),v,0,!1,c(g,v)),u.set(R,k)}return k},f=(g,y)=>y>0?oi(y,R=>m(g,R)):0,p=(g,y,R,k)=>{let v=ge(t,g),x=D=>{let E=Math.max(0,R[D]),V=c(g,E);return{Fz:E,a:f(g,E),b:V.fyPeak,slide:0,cap:N=>E>0?St(v,E,N,!1,V):0}},[M,F]=g==="front"?["FL","FR"]:["RL","RR"],w=x(M),C=x(F),T=k[M]*w.b,S=k[F]*C.b,A=w.cap(T)+C.cap(S),P=ni(w,C,T+S,y,A);return{l:M,r:F,full:P,asHeld:()=>({axle:g,strong:w.cap(T)>=C.cap(S)?M:F,full:P,open:ni(w,C,T+S,pa,A),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=P=>(M?.ax!==P&&(M={ax:P,loads:Ce(e,g,(P+k)/Me,a,0,y)}),M.loads),w=Rl(P=>ea(R,F(P),x,c).short,-k,1),C=R,T=P=>{let L=w.at(P);v=F(L),C=ea(R,v,x,c).util;let D=0,E=n.diffYaw?{fx:{FL:0,FR:0,RL:0,RR:0},axles:[]}:null;for(let V of i){let N=l[dn(V)];if(N){if(du(V)){let B=p(dn(V),N,v,C);D+=B.full,E&&(E.fx[B.l]=E.fx[B.r]=B.full/2,E.axles.push(B.asHeld()))}continue}let z=Math.max(0,v[V]),I=c(dn(V),z),_=St(ge(t,dn(V)),z,C[V]*I.fyPeak,!1,I);D+=_,E&&(E.fx[V]=_)}if(E){let V={};for(let N of fn){let z=Math.max(0,v[N]);V[N]={Fz:z,Fy:C[N]*c(dn(N),z).fyPeak,Fx:E.fx[N]}}for(let N of E.axles)D+=$l(N,V,h,b(g))-N.full}return D/s},S=C1(T,-k,pn).fx,A=w.edge();return A!==void 0&&S>A&&(S=A,T(S)),{ax:S,loads:v}}}}var pu=.05,Q1=.001,Z1=16,bu=8;function nb(e,t,r,n){let o=Math.max(bu,r),a=n.nSteer??7,s=e.tv?.enabled?Wh(e,t,o,n.steerMaxDeg):0,i=I=>{let _=jh(e,o,I,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=Un(e,t,o,l),m=I=>{let _={},B={};for(let O of fn)_[O]=I.wheels[O].slipDeg*se,B[O]=Math.min(1,I.wheels[O].gripUtil);return{steerDeg:I.steerDeg,ayMs:Math.max(0,I.ay*Me),ayG:I.ay,slip:_,util:B,scrub:I.ay>0?pE(I,e.massTotal):0}},f=null,p=I=>{if(f&&I===f.steerDeg)return m(f);let _=oE(e,t,o,u,I,l);if(_)return m(_);let B=u.states[0];for(let O of u.states)O.steerDeg<=I&&(B=O);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(I=>I.steerDeg<d.steerDeg),d]:u.states,g=d?b.findIndex(I=>I.ay*Me>=.995*h):0,y=b[g].steerDeg,{fold:R}=u;if(d&&R&&u.peak===R.state){let I=.995*h/Me,_=u.states.indexOf(R.stall),B=_-1;for(;B>0&&u.states[B].beta===R.stall.beta;)B--;let O=Math.sign(R.stall.beta-u.states[B].beta),G=_;for(;G>0&&u.states[G].ay>=I&&Math.sign(u.states[G].beta-u.states[G-1].beta)!==-O;)G--;u.states[G].ay<I&&(f=Qh(e,t,o,R,l,{ayG:I},u.states.slice(G,_+1)))}if(f)y=f.steerDeg;else if(g>0){let I=b[g-1].steerDeg,_=y;for(let B=0;B<8&&_-I>.001;B++){let O=.5*(I+_);p(O).ayMs>=.995*h?_=O:I=O}y=_}let k=[];for(let I=0;I<(h>0?a:1);I++){let _=I/(a-1);k.push(p(y*(_+Math.sin(Math.PI/2*_))/2))}k[0].ayMs=0;let v=[],x=[],M=[],F=[],w=_r(e,t,o,void 0,n.diffYaw===!0),C=mE(e,t,o,n,w),T=n.axDrag??0,S=I=>{let _=w.limitAt(I.ayMs/Me,I.steerDeg,I.util,T+I.scrub);return{axD:_.edge!==void 0&&_.edge>0?_.edge:_.ax,locked:_.axUnlocked-_.ax>pu}},A=I=>C.limitAt(I.ayMs/Me,I.steerDeg,I.util,T+I.scrub).ax,P=k.map(I=>({p:I,axA:A(I),...S(I)})),L=[];for(let I=0;I+1<P.length;I++){let _=P[I],B=P[I+1],O=[];_.locked!==B.locked?O.push({read:S,past:G=>G.locked===B.locked,braking:!0}):(B.axA>_.axA+pu&&O.push({read:G=>({axA:A(G)}),past:G=>(G.axA??-1/0)>_.axA}),-B.axD>-_.axD+pu&&O.push({read:S,past:G=>-(G.axD??0)>-_.axD}));for(let{read:G,past:K,braking:Y}of O){let j=_.p.steerDeg,Z=B.p.steerDeg,ne=null,te=_.axD,fe=B.axD;for(let W=0;W<Z1&&Z-j>Q1&&!(Y&&Math.abs(fe-te)<=pu);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}:S(W);L.push({p:W,axA:J.axA??A(W),...re})}}}P.push(...L),P.sort((I,_)=>I.p.steerDeg-_.p.steerDeg);let D=I=>I.axA+T+I.p.scrub,E=.001*Math.max(1,k[k.length-1].ayMs),V=[];for(let I=0;I+1<P.length;I++){let _=P[I],B=P[I+1];if(!(D(_)>=0&&D(B)<0))continue;let O=_.p.steerDeg,G=B.p.steerDeg,K=null,Y=null;for(let Z=0;Z<Z1&&G-O>Q1;Z++){let ne=.5*(O+G),te=p(ne);D({p:te,axA:A(te)})>=0?(O=ne,K=te):(G=ne,Y=te)}let j=K??Y;j&&j.ayMs>_.p.ayMs&&j.ayMs<B.p.ayMs&&V.push({p:j,axA:-(T+j.scrub),steady:!0,...S(j)})}P.push(...V),P.sort((I,_)=>I.p.steerDeg-_.p.steerDeg);let N=!1;for(let{p:I,axA:_,axD:B,steady:O}of P){let G=v.length-1,K=G>=0&&(O||N?!(I.ayMs>v[G]):I.ayMs-v[G]<E);N=O===!0&&!K,K?(x[G]=Math.max(x[G],_),M[G]=Math.min(M[G],B)):(v.push(I.ayMs),x.push(_),M.push(B),F.push(I.scrub))}for(let I=v.length-2;I>=0;I--)x[I]=Math.max(x[I],x[I+1]),M[I]=Math.min(M[I],M[I+1]);return{ayMax:v[v.length-1],ay:v,axAccel:x,axDecel:M,axScrub:F,rollover:u.rollover,atLock:d!==null&&ik(e,d.steerDeg)}}function pE(e,t){let r=e.beta*se,n=0;for(let o of fn){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 pU=Math.PI/180,dU={speeds:Array.from({length:23},(e,t)=>8+t),steerMaxDeg:14,steerSteps:29};function lk(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 ya={enabled:!1,kp:3e3,ffLow:150,ffHigh:300,vLow:18,vHigh:25},ck=e=>lk(e.ffLow,e.ffHigh,e.vLow,e.vHigh);var cr={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"}},dE=["k_yaw","k_roll","k_pitch"];function ui(e){for(let t of dE)delete e[t];for(let t of Object.keys(cr)){let r=e[t];if(!r){e[t]={...cr[t]};continue}e[t]={...r,label:cr[t].label,unit:cr[t].unit}}return e}function Q(e,t){return e[t]?.value??cr[t].value}function gu(e){let t=(r,n)=>e[r]?.value??n;return{enabled:t("tv_enabled",0)>=.5,kp:t("tv_kp",ya.kp),ffLow:t("tv_ff_low",ya.ffLow),ffHigh:t("tv_ff_high",ya.ffHigh),vLow:t("tv_v_low",ya.vLow),vHigh:t("tv_v_high",ya.vHigh)}}var uk=[10,25,50,100,200,300];function ob(e,t,r,n,o){let s=uk.map(i=>Math.round(i<=25?r*i:r*25+n*(i-25)));return{id:e,label:t,speedMmS:[...uk],reboundN:s,bumpN:s.map(i=>Math.round(i*o))}}var yu={name:"Generic FS damper",curves:[ob("c1","Soft",1.6,1,.65),ob("c2","Medium",3,1.6,.65),ob("c3","Firm",8,2.4,.65)]};function xu(e){let t=e.curves.length;return t>0?e.curves[Math.floor((t-1)/2)].id:""}var bn=25;function xa(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 mk(e,t){return t>=0?xa(e.rebound,t):-xa(e.bump,-t)}function pk(e,t,r){return t*mk(e,t*r)}var ab=(e,t)=>e.curves.find(r=>r.id===t);function mi(e,t){let r=ab(e,xu(e)),n=(t&&ab(e,t.bump))??r,o=(t&&ab(e,t.rebound))??r;return{bump:{speedMmS:n?.speedMmS??[],forceN:n?.bumpN??[]},rebound:{speedMmS:o?.speedMmS??[],forceN:o?.reboundN??[]}}}var Ru=5e3;function pi(e,t){let r=t>0?t:1,n=[],o=[],a=e.bump.speedMmS.map(c=>c/r).filter(c=>c<Ru),s=e.rebound.speedMmS.map(c=>c/r).filter(c=>c<Ru),i=c=>{n.push(c),o.push(pk(e,r,c))};i(-Ru);for(let c=a.length-1;c>=0;c--)i(-a[c]);i(0);for(let c of s)i(c);return i(Ru),{kind:"map",input:"velocity",x:n,y:o}}var sb=64;function di(e,t,r){let n=t>0?t:1,o=Math.max(r,1e-6),a=0;for(let s=0;s<sb;s++){let i=Math.sin((s+.5)*Math.PI/sb),c=n*o*i;a+=n*(xa(e.rebound,c)+xa(e.bump,c))*i}return a*(Math.PI/sb)/(Math.PI*o)}function qn(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:pi(m,u),rate:di(m,u,bn)}},s=a(e,t?.front,r),i=a(o??e,t?.rear,n);return!s&&!i?null:{...s?{front:s}:{},...i?{rear:i}:{}}}var dk=(e,t)=>({...e,y:e.y.map(r=>r*t)}),fE=e=>({...e,x:e.x.map(t=>-t).reverse(),y:e.y.map(t=>-t).reverse()});function ib(e,t,r){let n=Math.abs(r)>0?Math.abs(r):1,o=mi(e,t);return{law:o,curve:dk(pi(o,n),.5),rate:di(o,n,bn)/2,mr:n,ratio:n,share:.5}}function cb(e,t,r,n,o){let a=n*(Math.abs(r)>0?Math.abs(r):1),s=mi(e,t),i=dk(pi(s,a),1/n);return{law:s,curve:o?fE(i):i,rate:di(s,a,bn)/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 vu=["front","rear","heaveFront","heaveRear","rollFront","rollRear"];function hi(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 Vr(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 gi(e){return e.kind==="coil"?2:1}function bi(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 hk(e){return bi(e)/2}function bk(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 fk(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 hE(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 yi(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*bi(e.section)/e.barLength,a=2*o/(n*n),s=hk(e.armSection??e.section),i=3*e.E*s/n**3,c=e.dropLinkRate??1/0;return{rateAtLink:fk([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*bi(e.section)/e.barLength,a=2*o/(n*n),s=3*e.E*bk(e.blade)/n**3,i=e.dropLinkRate??1/0;return{rateAtLink:fk([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*bi(e.section)/e.length,a=2*o/(n*n);return{rateAtLink:a,contributions:{barTwist:a},torsional:o}}case"coil":{let n=Vr(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=hE(e.linkTravel,e.force,t);return{rateAtLink:Math.max(0,n),contributions:{},torsional:0}}}}function ku(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?zd(t,r):1,o=t?Yd(t,r):0,a=yi(e,o).rateAtLink;return{wheelRate:Math.max(0,a*n*n),motionRatio:n,rateAtLink:a}}function xi(e,t){let r=e.damper??0;return!r||e.design.kind==="none"?0:gi(e.design)*r*t*t}var bE=150;function gE(e){return X(e,[0,-.5,1])<-1e-9?U(e,-1):e}function gk(e){let t=e.hardpoints,r=H(t.rockerPivotB,t.rockerPivotA),n=ee(t.rockerPivotA,U(H(t.rockerToDamper,t.rockerPivotA),.6)),o=gE(q(ae(r,H(t.rockerToDamper,t.rockerPivotA))));return{outer:n,inner:ee(n,U(o,bE)),attach:"rocker"}}function Ct(e,t){let r={};for(let o of er)r[o]=tt(Ge(e,o));let n={vehicle:e,ctx:r};return t&&(n.kc=fl(n,t)),n}var Mu=.5;function yE(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 yk=e=>[(e[2][1]-e[1][2])/2,(e[0][2]-e[2][0])/2,(e[1][0]-e[0][1])/2];function Su(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:ye(o,r.travel,r.steer,void 0,a),i=r.state??at(s),c=ye(o,r.travel+Mu,r.steer,void 0,a),l=ye(o,r.travel-Mu,r.steer,void 0,a),u=(s?s.ok:r.converged)&&c.ok&&l.ok,m=at(c),f=at(l),p=(C,T)=>Ot(C.points[T],n),d=o.inv.strut?"pushrodOuter":"uprightUpper",h=p(i,d),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=>yE(R,[p(C,d),p(C,"uprightLower"),p(C,y)]),v=k(m),x=k(f),M=yk(v.rot),F=yk(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*Mu)):w,omega:u?U(H(M,F),1/(2*Mu)):w}}function lb(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 xk(e,t,r){let n=Su(e,t,gt(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 Rk(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 vk(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 xE(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 RE=.1*Math.PI/180;function kk(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]))*RE<=o*n}function Au(e,t){return!e.valid||!e.cpLeft||!e.cpRight?!1:kk([e.lateral,e.height],e.cpLeft,e.cpRight,e.sinAngle,t)}function Ri(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 vE=1;function Mk(e){let t=Ri(e);if(!t||!e.cpLeft||!e.cpRight||Math.abs(t.left-t.right)>vE)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 Ra(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 lr(e,t,r){let n=r==="front"?"FL":"RL",o=r==="front"?"FR":"RR",a=xk(e,n,t),s=xk(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=Rk(a),c=Rk(s),l=vk(a,i),u=vk(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=lb(a.cp,f,s.cp,p)??xE(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,C=(g[0]-M)*v+(g[1]-F)*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 Br(e,t){return{front:lr(e,t,"front"),rear:lr(e,t,"rear")}}function Fu(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 kE(e,t){return{camber:Fu(e.travel,e.camber,t),toe:Fu(e.travel,e.toe,t),motionRatio:Fu(e.travel,e.motionRatio,t),damperLen:e.damperLen?Fu(e.travel,e.damperLen,t):0}}var Sk=e=>kE(e,0).motionRatio;function ub(e,t){if(e.kind!=="coil")return null;let r=t??e.motionRatio,n=Vr(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 wu(e,t){if(e.kind==="none")return 0;if(e.kind==="tabulated"){let n=a=>ME(e,a);return(n(.5)-n(-.5))/(2*.5)/2}if((e.gap??0)>0)return 0;let r=t??e.motionRatio;return Vr(e.rate,0)*r*r/2}function vi(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 ME(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 mb={kind:"coil",rate:120,motionRatio:.7,gap:5,bothWays:!1};var Ak=new WeakMap;function Tu(e,t){let r=Ak.get(e);r||(r=new Map,Ak.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=En(e,t);return r.set(n,a),a}var SE=32,ki=new Map,Fk=new WeakMap,AE=1;function FE(e){let t=Fk.get(e);return t===void 0&&(t=AE++,Fk.set(e,t)),t}function pb(e,t){if(!t.linkage)return null;let r=an(e,t.linkage,t.design.kind),n=`${FE(e)}|${r?"unit":"bar"}|${JSON.stringify(t.linkage)}`,o=ki.get(n);if(o)return o;let a=jo(e,t.linkage,{kind:t.design.kind});return ki.size>=SE&&ki.delete(ki.keys().next().value),ki.set(n,a),a}function Zn(e,t,r=0){let n=(o,a)=>{if(!(!o||o.design.kind==="none"))return ku(o.design,pb(a,o),r).wheelRate};return{front:n(t.arbFrontDesign,e.front),rear:n(t.arbRearDesign,e.rear)}}function va(e,t){let r=(n,o)=>{if(!n||n.design.kind==="none")return;let a=n.linkage?Tu(o,n.linkage).atDesign:void 0;return wu(n.design,a)};return{front:r(t.heaveFrontDesign,e.front),rear:r(t.heaveRearDesign,e.rear)}}function Lk(e,t){let r=(a,s)=>{if(!a||a.design.kind!=="coil")return;let i=a.linkage?Tu(s,a.linkage).atDesign:void 0;return ub(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 Pu(e,t){let r=(o,a)=>o?vi(o,db(o,a)):0,n=(o,a)=>o?xi(o,fb(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 db=(e,t)=>e.linkage?Tu(t,e.linkage).atDesign:void 0,fb=(e,t)=>ku(e.design,pb(t,e),0).motionRatio;function Dk(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=db(f,p);if(vi(f,h)>0)return ib(n,r?.[d],h??(f.design.kind==="coil"?f.design.motionRatio:1))},s=(f,p,d)=>{if(!f||!o?.curves.length)return;let h=fb(f,p);if(!(xi(f,h)>0))return;let b=pb(p,f)!==null;return cb(o,r?.[d],h,gi(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 Lu(e,t){let r=t.heaveDamperModel??t.damperModel,n=t.rollDamperModel??t.damperModel,o=(i,c)=>Qn(i)?{source:"none"}:hi(i.config.coilover,c),a=(i,c)=>{if(!i)return{source:"none"};let l=vi(i,db(i,c))>0;return hi(i.coilover,l?r:void 0)},s=(i,c)=>{if(!i||i.design.kind!=="coil")return{source:"none"};let l=xi(i,fb(i,c))>0;return hi(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 Ek(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 Qn=e=>e.config.actuation==="decoupled",Jn="a decoupled axle damps in its heave and roll elements, set below";function Ik(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}=Zn(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?Tu(f,m.linkage).atDesign:void 0;o(p,wu(m.design,d))}let i=CE(e,t,r),c=wE(e,i);n.kinFront=c.kinFront,n.kinRear=c.kinRear;let l=LE(e,i);n.steerFront=c.steerFront,Number.isFinite(l.ackermannPct)&&o("ackermann_pct",l.ackermannPct);let u=m=>Qn(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"]])Qn(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"]])Qn(m)&&(o(f,0),n.readouts={...n.readouts,[f]:Jn});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 wE(e,t){return{kinFront:Ck(e.front),kinRear:Ck(e.rear),steerFront:e.front.measured?void 0:Du(e.front,t)}}var wk=new WeakMap;function Ck(e){let t=wk.get(e);return t||wk.set(e,t=oa(e)),t}function CE(e,t,r={}){return TE(e,t,r.front,r.rear)}function TE(e,t,r,n){let o=e.front.config.loadedRadius;if(!((ar(r??t.tireModel)??0)>0))return o;let a={...t,surveyedRadiusFront:o,surveyedRadiusRear:e.rear.config.loadedRadius};return Eu(a,r,n).front??o}var Tk=new WeakMap;function Du(e,t=e.config.loadedRadius){let r=Tk.get(e);r||(r=new Map,Tk.set(e,r));let n=r.get(t);if(n)return n;let o=t===e.config.loadedRadius?void 0:{loadedRadius:t},a=mf(e,Vt(e.config),void 0,void 0,void 0,void 0,o);return r.size>=4&&r.clear(),r.set(t,a),a}var Pk=new WeakMap;function PE(e){return Ke(e,{travelMin:-1,travelMax:1,steps:3}).samples[1].metrics.motionRatio??1}var Cu=e=>e.measured?Sk(e.measured):PE(e);function LE(e,t=e.front.config.loadedRadius){let r=()=>e.front.measured?void 0:Du(e.front,t);return{...DE(e),get steerFront(){return r()},get ackermannPct(){let n=r();return n?pf(n,bt(e.front),e.config.wheelbase):Number.NaN}}}function DE(e){let t=Pk.get(e);if(t)return t;let r=e.front.measured,n=e.rear.measured,a=!r||!n?Br(Ct(e),{heave:0,pitch:0,roll:0,steer:0}):null,s={wheelbase:e.config.wheelbase,trackFront:r?r.track:bt(e.front),trackRear:n?n.track:bt(e.rear),mrFront:Cu(e.front),mrRear:Cu(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:Ra(a.front),rcGainRear:n||!a?0:Ra(a.rear),rcFrontValid:r?!0:!!a?.front.valid,rcRearValid:n?!0:!!a?.rear.valid};return Pk.set(e,s),s}var xt={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}},Ok=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),ur=(e,t,r,n=1/0)=>typeof e=="number"&&Number.isFinite(e)?Math.min(n,Math.max(r,e)):t;function eo(e){if(Ok(e))switch(e.kind){case"open":case"spool":return{kind:e.kind};case"clutch":{let t=xt.clutch;return{kind:"clutch",preloadNm:ur(e.preloadNm,t.preloadNm,0),rampDriveDeg:ur(e.rampDriveDeg,t.rampDriveDeg,1,90),rampCoastDeg:ur(e.rampCoastDeg,t.rampCoastDeg,1,90),faces:Math.round(ur(e.faces,t.faces,0)),muClutch:ur(e.muClutch,t.muClutch,0,1),rFrictionMm:ur(e.rFrictionMm,t.rFrictionMm,1),rRampMm:ur(e.rRampMm,t.rRampMm,1)}}case"torsen":{let t=xt.torsen,r=ur(e.preloadNm,0,0);return{kind:"torsen",tbrDrive:ur(e.tbrDrive,t.tbrDrive,1),tbrCoast:ur(e.tbrCoast,t.tbrCoast,1),...r>0?{preloadNm:r}:{}}}default:return}}function Iu(e){if(!Ok(e))return;let t=eo(e.front),r=eo(e.rear);return t||r?{...t?{front:t}:{},...r?{rear:r}:{}}:void 0}function Mi(e){let t=mn(e),r=n=>n>=2?"independent":n===1?"diff":"none";return{front:r(t.front),rear:r(t.rear)}}function Si(e){if(!e.driveline)return;let t=Mi(e),r=e.r_dyn.value,n=s=>{if(t[s]!=="diff")return;let i=eo(e.driveline?.[s]);if(!(!i||i.kind==="independent"))return{kind:i.kind,drive:ri(i,"drive",r),coast:ri(i,"coast",r),hubs:ri(i,"hubs",r)}},o=n("front"),a=n("rear");return o||a?{...o?{front:o}:{},...a?{rear:a}:{}}:void 0}var EE={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"}},_k=e=>{let t=e==="front"?"Front":"Rear";return Object.fromEntries(Object.entries(EE).map(([r,n])=>[`${e}.${r}`,{section:t,...n}]))},_u={..._k("front"),..._k("rear")},Nk=e=>e.motorModel?.kind==="ice"?e.motorPlacement==="front"?"front":"rear":null;function Vk(e,t){let r=Nk(t);if(!(!r||Nk(e)===r||t.driveline?.[r]))return{...t.driveline,[r]:{...xt.clutch}}}function Gt(e,t,r,n){return e>0?!(r>0)||!Number.isFinite(r)?e:Math.max(1,e-t/r):n}function Nu(e,t,r){let n=Math.max(0,Math.min(1,r)),o=Gt(e.freeRadius,e.staticLoad,e.tyreRate,e.surveyed),a=Gt(t.freeRadius,t.staticLoad,t.tyreRate,t.surveyed);return n*o+(1-n)*a}function ka(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 $r(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 Ai(e,t){if(!e)return _E(t);let r=t-cn(e,0).camber;return r?{...e,camber:e.camber.map(n=>n+r)}:e}function IE(e){return{kinFront:Ai(e.kinFront,Q(e,"camber_front_deg")),kinRear:Ai(e.kinRear,Q(e,"camber_rear_deg"))}}function _E(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 Bk=9.81,$k=e=>e>1?e/100:e;function Ma(e,t,r){let n=t??e.tireModel??Gs(),o=r??e.tireModelRear??n,a={grip:Q(e,"grip_scale"),stiffness:Q(e,"stiffness_scale")},s=Gl(n,a);return{front:s,rear:o===n?s:Gl(o,a)}}function mr(e,t,r){let n=Ma(e,t,r),o=Pe(n.front);return ut(n.rear===n.front?o:Ll(o,Pe(n.rear)))}function hb(e,t,r){let n=$k(e.front_mass_diss.value),o=Ma(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*Bk*n/2,u=e.m.value*Bk*(1-n)/2,m=(i?a.verticalStiffness():0)||Q(e,"tire_vertical_rate"),f=(c?s.verticalStiffness():0)||Q(e,"tire_vertical_rate"),p=ar(i)??0,d=ar(c)??0,h=e.surveyedRadiusFront&&e.surveyedRadiusRear?Nu({freeRadius:p,staticLoad:l,tyreRate:m,surveyed:e.surveyedRadiusFront},{freeRadius:d,staticLoad:u,tyreRate:f,surveyed:e.surveyedRadiusRear},n):void 0,b=e.surveyedRadiusFront?Gt(p,l,m,e.surveyedRadiusFront):void 0,g=e.surveyedRadiusRear?Gt(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 Eu(e,t,r){let n=hb(e,t,r);return{front:n.standingFront,rear:n.standingRear}}function Gk(e,t,r){return hb(e,t,r).cgStandingRadius}function dt(e,t,r){let n=$k(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}=hb(e,t,r),g=ei(e),y=Si(e),R=qn(e.damperModel,e.damperSetup,o,a,e.damperModelRear??e.damperModel),k=e.readouts?.damper_front===Jn,v=e.readouts?.damper_rear===Jn,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:gu(e),cgHeight:ka(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:NE(e,{Wf:c,Wr:l,tireRate:u,tireRateRear:m,tyreFreeRadius:f,tyreFreeRadiusRear:p,standingFront:h,standingRear:b}),tyreFreeRadius:f,...p!==f?{tyreFreeRadiusRear:p}:{},rcHeightFront:$r(Q(e,"rc_front"),e.rcRoad?.gainFront,e.rcRoad?.radiusFront,h),rcHeightRear:$r(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,...IE(e)}}function NE(e,t){let r=(a,s,i,c)=>a??(s>0?Gt(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 Ou={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 Kk(e,t=e.batteryModel){if(!t)return e;let r=xr(t),n=(o,a)=>({...o,value:a});return{...e,capacity:n(e.capacity,r.capacityAh),ocv:n(e.ocv,r.voltageAtFull)}}var zk={damper_front:`the damper part sets it: its front curve at ${bn} mm/s`,damper_rear:`the damper part sets it (the rear's own, where the car names one): its rear curve at ${bn} mm/s`};function Vu(e){let t=!!(e.damperModelId||e.damperModel),r=t||!!(e.damperModelIdRear||e.damperModelRear);return{...t?{damper_front:zk.damper_front}:{},...r?{damper_rear:zk.damper_rear}:{}}}function Yk(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=qn(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!==Jn&&(i.damper_front=s(e.damper_front,"damper front",a.front.rate/(n*n))),a.rear&&e.readouts?.damper_rear!==Jn&&(i.damper_rear=s(e.damper_rear,"damper rear",a.rear.rate/(o*o))),i}var Wk={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 Gr(e){return!!e&&typeof e=="object"&&"value"in e&&"label"in e}var $E={Batteriekapazit\u00E4t:"pack capacity",Rollwiderstandsbeiwert:"rolling-resistance coefficient"},Uk=e=>$E[e]??e;function Bu(e){let t=[];for(let r of Object.keys(e)){if(r==="motor"||r==="name")continue;let n=e[r];Gr(n)&&t.push({key:r,label:Uk(n.label),value:n.value,unit:n.unit})}return t}var GE=[{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"]}],KE=.5,jk=e=>e==="infinite"?1/0:typeof e=="number"?e:null,HE=e=>/front/.test(e)?e.replace("front","rear"):/rear/.test(e)?e.replace("rear","front"):null,zX=(()=>{let e=Wk.rows,t=o=>{let a=HE(o),s=jk(e[o]?.score),i=a&&e[a]?jk(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>=KE&&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 bb={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 Xk(e){let t=new Map;for(let a of Bu(e))t.set(a.key,a);let r=new Set,n=[];for(let a of GE){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=Bu(e).filter(a=>!r.has(a.key));return o.length&&n.push({title:"Other",rows:o}),n}var gb={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"},yb={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"},qk=e=>!!(e.aeroModelId||e.aeroModel);function zE(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 YE=e=>!!(e.batteryModelId||e.batteryModel);function WE(e,t){let r={};return t.geometry&&Object.assign(r,bb,zE(e)),qk(e)&&Object.assign(r,gb),YE(e)&&Object.assign(r,Ou),Object.assign(r,Vu(e)),e.readouts&&Object.assign(r,e.readouts),r}function Qk(e,t){let r=WE(e,t);return qk(e)||Object.assign(r,yb),r}function xb(e){let t=e.cop_long;return Gr(t)?1-t.value:.5}function jE(e,t){let r=e.front_aero_diss,n=e.cop_long;!Gr(r)||!Gr(n)||(t===r.label?n.value=1-r.value:t===n.label&&(r.value=1-n.value))}function UE(e,t){jE(e,t);let r=e.c_l,n=e.c_w,o=e.l_to_d_ratio;!Gr(r)||!Gr(n)||(t===r.label||t===n.label?Gr(o)&&n.value!==0&&(o.value=r.value/n.value):Gr(o)&&t===o.label&&o.value!==0&&(n.value=r.value/o.value))}function $u(e,t,r){let n=!1;for(let o of Object.keys(e)){if(o==="motor"||o==="name")continue;let a=e[o];if(Gr(a)&&Uk(a.label)===t){a.value=r,n=!0;break}}return n&&UE(e,t),n}function Gu(e,t,r=0,n,o){let a=()=>({cl:e.c_l.value,cw:e.c_w.value,frontShare:xb(e),A:e.A.value,platform:null});if(!e.aeroModel)return a();let s=vr(n??dt(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:xb(e),A:s.area,platform:s}}var Zk=e=>typeof e=="object"&&e!==null&&typeof e.value=="number"&&typeof e.label=="string";function Jk(e,t=e.aeroModel){if(!t)return e;let r=Zr(t,{wheelbase:Q(e,"wheelbase")}).at(Q(e,"ride_height_front"),Q(e,"ride_height_rear")),{cl:n,balanceFront:o}=pd(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(Zk(e.cop_long)?e.cop_long:void 0,cr.cop_long,1-o)};return Zk(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 Fi={dsTarget:.25,accelStep:.25,vTol:.002,scanSteps:24,seamIters:8,fitSpacing:1},XE=32;function eM(e,t,r){let n=Math.round(e/t);return Math.max(1,Math.min(Number.isFinite(n)?n:1,Math.floor(r/XE)||1))}function st(e){let t=Fi,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 tM=Math.PI/180,Ku=.02,rM=new WeakMap;function wi(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)*tM,l=(e.bank?.[i]??0)*tM,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 Hu(e,t,r){return e.n0[t]+e.k[t]*r*r}function nM(e,t){return e.k[t]<0?Math.sqrt(Math.max(0,e.n0[t])/-e.k[t]):1/0}function oM(e,t){if(!e)return null;let r=1/0,n=-1/0;for(let o=0;o<e.n0.length;o++){let a=Hu(e,o,t[o]??0);a<r&&(r=a),a>n&&(n=a)}return r>=1-Ku&&n<=1+Ku?null:{lo:r,hi:n}}var Sa=[.1,.25,.5,.75,1,1.25,1.5,2,2.5];function aM(e){let t=e.lo>=1-Ku?1:1-1.25*(1-e.lo)-.05,r=e.hi<=1+Ku?1:1+1.25*(e.hi-1)+.05,n=[...Sa].reverse().find(a=>a<=t)??Sa[0],o=Sa.find(a=>a>=r)??Sa[Sa.length-1];return Sa.filter(a=>a>=n&&a<=o)}function Rb(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):Rb(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 zu(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}=qE(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:C,tau:T,target:S}=F;d=0,h=0,b=0;for(let A=0;A<s;A++){let P=i(A),L=e[P];for(let V=0;T<=0&&V<n.count;V++){let N=C;if(w<L-1e-9?n.best(w)>C&&(n.rpm(w,C)>=n.limitRpm||c[A]>=w*k)?N=C+1:C>0&&w<n.vIdle(C)&&(N=C-1):L<w-1e-9&&C>0&&n.best(l[A])<C&&n.rpm(w,C-1)<=n.limitRpm&&(N=C-1),N===C)break;S=N,N>C?d++:h++,T=N>C?y:R,T<=0&&(C=S)}u[A]=w,m[A]=C+1,f[A]=n.rpm(w,C);let D=T>0;p[A]=D?1:0;let E=L;if(!D)w<L&&(E=Math.min(L,Math.sqrt(Math.max(0,w*w+2*o(A,w,n.share(w,C))*t[A]))));else if(w<L){let V=o(A,w,g>0?g*n.share(w,C):0),N=Math.min(L,Math.sqrt(Math.max(0,w*w+2*V*t[A]))),z=w+N>0?2*t[A]/(w+N):1/0;if(z<=T)E=N,b+=z,T-=z;else{let I=Math.min(L,Math.max(0,w+V*T)),_=Math.max(0,t[A]-(w+I)*.5*T);b+=T,T=0,C=S,E=Math.min(L,Math.sqrt(Math.max(0,I*I+2*o(A,I,n.share(I,C))*_)))}}else{let V=w+E>0?2*t[A]/(w+E):0;b+=Math.min(V,T),T-=V,T<=0&&(C=S)}w=E}return{v:w,gear:C,tau:T,target:S}},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),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 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 qE(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 vb=.001,kb=9.81,Ci=(e,t)=>Yu(e?.gradient?.[t]??0);function Yu(e){return e===0?0:-kb*Math.sin(e*Math.PI/180)}function yn(e,t){let r=new Array(t);for(let n=0;n<t;n++)r[n]=Yu(e?.[n]??0);return r}var gn=(e,t)=>{let r=e?.mu?.[t];return r!=null&&r>0?r:1},to=(e,t)=>e?.bank?.[t]??0;function QE(e,t,r,n,o,a){let s=e.ay(t,r,gn(o,a)),i=to(o,a);if(!i)return s;let c=i*Math.PI/180,l=n===0?0:-Math.sign(n)*kb*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)+kb*Math.sin(r)}function Mb(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 ro=(e,t,r)=>t?t(r):e,ZE=1e-4;function Aa(e,t,r,n,o,a,s){let i=st(r),c=[];for(let l=0;l<t.length;l++){let u=t[l],m=Math.abs(u),f=ro(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:Mb(b=>b*b*m-QE(f,b,0,u,n,l),vb,d,i.scanSteps,Math.min(i.vTol,ZE));c.push({v:h,ax:0,ay:h*h*u})}return c}function JE(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=Mb(p=>u(p)-t.v,vb,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 eI(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 iM(e,t,r,n,o,a){let s=st(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,JE(ro(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],s,gn(r,m),Ci(r,m),to(r,m),a?p=>a(m,p):void 0))}if(u<=s.vTol)break}return c}function cM(e,t,r,n,o,a){let s=st(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,eI(ro(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],gn(r,m),Ci(r,m),to(r,m),a?a[m]:1))}if(u<=s.vTol)break}return c}function tI(e,t,r){let n=r.load?wi(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=>nM(n,a%o),n:(a,s)=>Hu(n,a,s)}}function lM(e,t,r,n,o,a,s){return zu(n,r.ds,o,a,(i,c,l)=>{let u=c*c*r.curvature[i];return ro(e,t,i).axAccel(c,Math.abs(He(u,to(r,i))),gn(r,i),s?l*s[i]:l)+Ci(r,i)})}function uM(e,t){return{gear:e.gear.slice(0,t),engineRpm:e.rpm.slice(0,t),shifting:e.shifting.slice(0,t)}}function mM(e,t,r,n){if(!e.scrub)return{};let o=!1,a=n.map((s,i)=>{let c=ro(e,t,i),l=He(s*s*r.curvature[i],to(r,i)),u=c.scrub?c.scrub(s,Math.abs(l),gn(r,i)):0;return u!==0&&(o=!0),u});return o?{axScrub:a}:{}}function Rt(e,t,r,n={}){let o=st(r),a=t.npts,s=t.closed&&!n.standingStart,{pick:i,cap:c,n:l}=tI(e,t,n),u=n.driveDerate,m=n.brakeFade;if(!s)return rI(e,t,o,n.standingStart===!0,i,u,n.vCeiling,m,c,l,n.shifts);let f=Aa(e,t.curvature,o,t,i,n.vCeiling,c),p=iM(e,f,t,o,i,m),d=cM(e,f,t,o,i,u),h=n.shifts?lM(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))}:{},...mM(e,i,t,b),...h?uM(h,a):{}}}function rI(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=Aa(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=ro(e,o,R),M=w=>{let C=He(w*w*t.curvature[R],to(t,R)),T=(i?x.axDecel(w,Math.abs(C),gn(t,R),i(R,w)):x.axDecel(w,Math.abs(C),gn(t,R)))+Ci(t,R);return Math.sqrt(Math.max(0,w*w+2*T*t.ds[R]))},F=n&&R===0?k.v:vb;k.v=Mb(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,to(t,R));k.ax=ro(e,o,R).axAccel(k.v,Math.abs(x),gn(t,R),a?a[R]:1)+Ci(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?lM(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))}:{},...mM(e,o,t,y.map(R=>R.v)),...b?uM(b,m):{}}}var pM=(e,t)=>{let r=e[t]?.value;return Number.isFinite(r)&&r>0?r:0};function no(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 oo(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 Ti=36e5,bM=Math.PI*2,Sb=e=>Math.max(0,Math.min(1,e));function Ab(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=Wc(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/bM),l=Math.max(0,i*o/(n*a)),u=r.efficiency(c,l);return u>.01?u:.5}}var dM=new WeakMap;function Fa(e){if(e.batteryModel)return e.batteryModel;let t=e.capacity.value,r=e.ocv.value,n=dM.get(e);if(n&&n.capacityAh===t&&n.ocv===r)return n.model;let o=td(t,r);return dM.set(e,{capacityAh:t,ocv:r,model:o}),o}function Fb(e){let t=e.params,r=Fh(t,ru(e));if(ft(t.motorModel)||pt(t).mode!=="hydraulic")return r;let n;return(o,a,s,i=0)=>{if(!(o>0))return 0;n??=nI(e);let c=lu(n.inp,n.ev,o,a,i);return c?Math.min(o,c.regenFront+c.regenRear):r(o,a,s)}}var fM=new WeakMap;function nI(e){let t=e.params,r=fM.get(t);if(!r){let n=Dr(t);r={inp:dt(n.regen?t:{...t,energy:{...n,regen:!0}}),ev:mr(t)},fM.set(t,r)}return r}var Pi=e=>e.airTempC??At;function Wu(e,t){return e.thermal?e.thermal.startC??t:_o}function hM(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 gM=()=>({windingC:[],derate:[],lossW:[],torqueNm:[],ampsRms:[]});function oI(e){let t=e.motorModel;if(!t?.thermal)return;let r=rd(t.thermal),n=Wc(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/bM),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 aI(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 sI(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 iI(e){let{drivenFront:t,drivenRear:r}=oo(e);return no(e.params,t,r)}function wa(e,t,r,n,o=Lr,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?dt(m):void 0,g=Ab(m),y=xr(Fa(m)),R=y.chargeC,k=Sb(a??m.soc.value),v=Pi(m),x=s??Wu(y,v),M=x,F=0,w=0,C=0,T=0,S=-1,A=-1,P=-1,L=oI(m),D=L?L.th.startC:0,E=D,V=0,N=1,z=-1,I=0,_=0,B=Fb(e),O=m.motorModel?.kind==="ice",G=u?.scrub,K=G?d/iI(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}=Gu(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],Be=j+1<r.length?r[j+1]:Z,Ae=.5*(Z+Be),le=Ae>0?t[j]/Ae:0,Re=0,Te=k,ze=x,je=0,be=0,Fe=le;if(O){oe>0&&(be=ue/g(Z,oe),F+=be/Ti),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=aI(y,xe,le,k,x);me.short&&S<0&&(S=j),me.cutoff&&A<0&&(A=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),F+=me.energyJ*Ye/Ti,be=me.energyJ*Ye,Fe=me.seconds,C+=me.lossJ*Ye,T+=Se,le>0&&(je=Se/me.seconds),k=Sb(k-Se/R),x=hM(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=sI(y,Le,le,k,x),Ye=(1-k)*R,Ue=Math.min(Se.dq,Ye),zt=Se.dq>0?Ue/Se.dq:1;w+=Se.energyJ*zt/Ti,be=-Se.energyJ*zt,C+=Se.lossJ*zt,T-=Ue,le>0&&(je=-Ue/le),k=Sb(k+Ue/R),x=hM(y,x,Ue>0&&le>0?-Ue/le:0,Se.lossJ*zt,le,v),x>M&&(M=x),Re=-me*zt}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(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<N&&(N=me),me<1&&z<0&&(z=j),_+=le,me<1&&(I+=le);let Le=L.torque(Re,xe,me),Se=L.th.lossW(xe,Le,D);V+=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>E&&(E=D)}}return{drive:F,regen:w,net:F-w,chargeAh:T/3600,loss:C/Ti,socEnd:k,shortAt:S,cutoffAt:A,emptyAt:P,tempEndC:x,tempMaxC:M,...L?{motorTempEndC:D,motorTempMaxC:E,motorLossKwh:V/Ti,motorDerateMin:N,motorDerateAt:z,motorDerateTimeFrac:_>0?I/_:0}:{}}}var cI=.5,lI=.02,uI=6;function yM(e,t,r,n,o,a,s,i){let c=n(),l=1,u=d=>{let h=gM(),b=wa(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<lI){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]+cI*((g[R]??1)-f[R]);f=y}return{lap:c,derate:f,solves:l,converged:p,peakWindingC:m.peak,derateTimeFrac:m.frac}}var mI=.1;function xM(e){let t=e.power_limit_kw?.value??0;return t>0?t*1e3:0}function wb(e,t,r){return e.motorModel?.kind==="ice"?1/0:xr(Fa(e)).maxPower(t??e.soc.value,r,xM(e)).watts}function ju(e,t,r,n){let o=wb(e,r,n);if(!Number.isFinite(o))return 1/0;if(o<=0)return 0;let a=Math.max(mI,t),s=Ab(e),i=o*(e.effi_pgb?.value??.9)/a;return o*s(t,i)/a}var pI=180/Math.PI;function Uu(e,t,r,n){let o=e*t,a=e*(1-t);return o/r-a/n}var Xu=e=>e*9.81*pI;var T7=Math.PI/180;function qu(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?Uu(e.massTotal,e.frontMassFrac,2*i,2*c):0,u=Xu(l),m=u>.15?"understeer":u<-.15?"oversteer":"neutral";return{gradient:u,balance:m,cAlphaFront:i,cAlphaRear:c}}var O7=Math.PI/180,V7=180/Math.PI;var RM=2220446049250313e-31;function hI(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 bI(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 gI(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])<=RM*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<=RM*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 vM(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 hI(r),bI(r),gI(r)}function kM(e){let t=[],r=new Array(e.length).fill(!1),n=vM(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 Cb(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 yI(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 Cb(r,n)}function Qu(e,t=r=>yI(e,r)){return kM(e).map(r=>({...r,vector:t(r.eigenvalue)}))}function Ca(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 MM(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 Ca(Qu(i),c,0)}function SM(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=MM({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 Zu(e,t,r){let n=we(e);return{front:SM(e,n,"front",t??n.rideDampingFront),rear:SM(e,n,"rear",r??n.rideDampingRear)}}var Q7=180/Math.PI;var Tb=["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},Ta=20,AM=[ce.zFL,ce.zFR,ce.zRL,ce.zRR],FM=[ce.vzFL,ce.vzFR,ce.vzRL,ce.vzRR],Kr={fzFL:0,fzFR:1,fzRL:2,fzRR:3,fzBody:4,myBody:5,mxBody:6,fx:7,fy:8,mz:9},Pb=10;function Ju(e){let t=Array.from({length:Ta},()=>new Array(Ta).fill(0)),r=Array.from({length:Ta},()=>new Array(Pb).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[AM[i]]-=c,s[FM[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(Ta).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=AM[s],x=FM[s];for(let M=0;M<Ta;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][Kr.fzFL+s]=1/y}return r[ce.vzBody][Kr.fzBody]=1/e.bodyMass,r[ce.pitchRate][Kr.myBody]=1/n.yy,r[ce.rollRate][Kr.mxBody]=1/n.xx,r[ce.vx][Kr.fx]=1/e.totalMass,r[ce.vy][Kr.fy]=1/e.totalMass,r[ce.yawRate][Kr.mz]=1/n.zz,{A:t,B:r,params:e}}function Lb(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=Xe(e,"front")*1e3,p=Xe(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 wM=ce.rollRate+1;function CM(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,wM).map(i=>i.slice(0,wM));if(!n.every(i=>i.every(Number.isFinite)))return{};let a=Qu(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 Cb(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:Ca(a,s,1),pitch:Ca(a,s,2),roll:Ca(a,s,3)}}function TM(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 em(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=CM(Ju(Lb(e)));return{roll:TM(m.roll,a,s),pitch:TM(m.pitch,l,u)}}var tm=9.81,Hr=Math.PI/180;function PM(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 Pa(e,t,r,n,o){let{wb:a,lf:s,lr:i,m:c}=PM(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/tm,0,r),F=Math.max(0,M.FL+M.FR),w=Math.max(0,M.RL+M.RR),C=t(v,F),T=t(x,w),S=(C*Math.cos(o)+T)/c;if(l=.5*(l+S),Math.abs(S-l)<1e-4)break}let u=l/r,m=o-n-s*u/r,f=-n+i*u/r,p=Ce(e,l/tm,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/tm,cn:y/(c*tm*a)}}function Db(e,t,r,n={}){let o=Math.max(8,r),a=(n.betaMaxDeg??10)*Hr,s=(n.deltaMaxDeg??10)*Hr,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=Pa(e,t,o,F,y);R.push(w.ay),k.push(w.cn),v.push(F/Hr),x.push(y/Hr),Math.abs(w.ay)>f&&(f=Math.abs(w.ay))}u.push({label:`\u03B4 ${(y/Hr).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=Pa(e,t,o,y,F);R.push(w.ay),k.push(w.cn),v.push(y/Hr),x.push(F/Hr)}p.push({label:`\u03B2 ${(y/Hr).toFixed(0)}\xB0`,ay:R,cn:k,betaDeg:v,deltaDeg:x})}let d=.5*Hr,h=(Pa(e,t,o,d,0).cn-Pa(e,t,o,-d,0).cn)/(2*d),b=(Pa(e,t,o,0,d).cn-Pa(e,t,o,0,-d).cn)/(2*d);return{isoBeta:p,isoDelta:u,trim:m,maxAy:f,stability:h,control:b,speed:o}}function xI(e){return!e.corneringStiffnessFront||!e.corneringStiffnessRear?null:{Cf:2*e.corneringStiffnessFront,Cr:2*e.corneringStiffnessRear}}function Li(e,t){let r=xI(e);if(!r)return null;let{Cf:n,Cr:o}=r,{wb:a,lf:s,lr:i,m:c}=PM(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 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=Uu(c,e.frontMassFrac,n,o),M=Xu(x),F=M>.15?"understeer":M<-.15?"oversteer":"neutral",w=s*n-i*o,C=P=>P*3.6,T=null,S=null;w>1e-6?S=C(Math.sqrt(n*o*a*a/(c*w))):w<-1e-6&&(T=C(Math.sqrt(n*o*a*a/(c*-w))));let A=u/(a+x*u*u);return{stable:v,yawFreq:R/(2*Math.PI),dampingRatio:k,eigReal:y,understeerGradient:M,balance:F,characteristicSpeed:T,criticalSpeed:S,yawRateGain:A}}var LM=Math.PI/180;function IM(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 DM(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 _M(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 NM(e,t,r){let n=e.isoDelta[0],o=(n.betaDeg[1]-n.betaDeg[0])*LM||1,a=e.isoDelta.length>1?(e.isoDelta[1].deltaDeg[0]-e.isoDelta[0].deltaDeg[0])*LM:1,s=x=>_M(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)=>DM(x.cn,M,o)),f=s((x,M,F)=>DM(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(`${IM(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 EM=1e-4;function Eb(e){let t=null,r=f=>{if(!t)return!0;let p=Math.abs(f),d=Math.abs(t.ay);return p>d*(1+EM)?!0:p<d*(1-EM)?!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=NM(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 RI=["tv_kp"];function OM(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"},...RI.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 vI=OM(0);function VM(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 kI=VM(0);var MI=9.81;function SI(e){let t=e.wheelbase/1e3;return{lf:t*(1-e.frontMassFrac),lr:t*e.frontMassFrac}}function Di(e,t,r,n){let o=t.tire;if(!o)return null;let s=(r==="limit"?tb(e,o,t.speed):hn(e,o,t.speed,t.ayG)).wheels;return Sr(n??jn(o,e.massTotal*MI*1.2),{FL:s.FL,FR:s.FR,RL:s.RL,RR:s.RR},SI(e))}function AI(e){if(!e.tire)return e.cornerStiffness;let t=ge(e.tire,"front"),r=ge(e.tire,"rear");return{front:n=>t.corneringStiffness(n),rear:n=>r.corneringStiffness(n)}}var BM=[{key:"understeer",label:"Understeer gradient",unit:"\xB0/g",compute:(e,t)=>qu(e,t.ayG,AI(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*ff(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=>em(e).roll.freq},{key:"pitchFreq",label:"Pitch-mode freq",unit:"Hz",compute:e=>em(e).pitch.freq},{key:"zetaFront",label:"Damping \u03B6 front",unit:"-",compute:e=>Zu(e).front.dampingRatio},{key:"zetaRear",label:"Damping \u03B6 rear",unit:"-",compute:e=>Zu(e).rear.dampingRatio},{key:"yawFreq",label:"Yaw natural freq",unit:"Hz",compute:(e,t)=>Li(e,t.speed)?.yawFreq??NaN},{key:"yawZeta",label:"Yaw damping \u03B6",unit:"-",compute:(e,t)=>Li(e,t.speed)?.dampingRatio??NaN},{key:"stabilitySpeed",label:"Char./critical speed",unit:"km/h",compute:(e,t)=>{let r=Li(e,t.speed);return r?r.criticalSpeed??r.characteristicSpeed??NaN:NaN}},{key:"maxAy",label:"Max lateral accel",unit:"g",compute:(e,t)=>t.fyAxle?Db(e,t.fyAxle,t.speed,{betaMaxDeg:12,deltaMaxDeg:12}).maxAy:NaN},{key:"yawReserveRear",label:"Yaw stability reserve",unit:"N\xB7m",compute:(e,t)=>Di(e,t,"operating")?.stabil??NaN},{key:"yawReserveFront",label:"Yaw agility reserve",unit:"N\xB7m",compute:(e,t)=>Di(e,t,"operating")?.agil??NaN},{key:"limitBalance",label:"Limit balance (+US / \u2212OS)",unit:"-",compute:(e,t)=>Di(e,t,"limit")?.rel??NaN},{key:"yawStiffness",label:"Yaw stiffness N_\u03B2",unit:"N\xB7m/rad",compute:(e,t)=>t.tire?eb(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorque",label:"Steering holding torque",unit:"N\xB7m",compute:(e,t)=>t.tire?Zh(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorqueGradient",label:"Steering feedback gradient",unit:"N\xB7m/g",compute:(e,t)=>t.tire?Jh(e,t.tire,t.speed,t.ayG):NaN}],Ib=Object.fromEntries(BM.map(e=>[e.key,e]));var zr=9.81;function FI(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 wI={front:!1,rear:!0};function La(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 $M(e,t,r,n,o,a){let s=e[t]+e[r];if(!(s>0))return;let i=La(n,o[t],a[t]),c=La(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 GM(e,t,r,n,o,a={},s="open"){if(!e.rear)return 1;if(!e.front)return 0;let i=(f,p,d)=>d?ti(f,p,d):s==="own"?f+p:2*Math.min(f,p),c=i(La(n,t.FL,r.FL),La(n,t.FR,r.FR),a.front),l=i(La(o,t.RL,r.RL),La(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 _b(e,t,r,n){return{car:t?zM(t,r.loadFactor[n]):e,ayTyre:He(r.ay[n],r.bank?.[n]??0),axCar:r.ax[n]-(r.axGrade?.[n]??0)}}function KM(e,t){if(!e.aero?.model)return 0;let r=Math.min(t.v.length,t.ax.length,t.ay.length),n=t.loadFactor?nm(e):void 0,o=0,a=0;for(let s=0;s<r;s++){let i=t.ds?.[s]??1,c=_b(e,n,t,s);o+=i,df(c.car,t.v[s],c.axCar/zr,c.ayTyre/zr)&&(a+=i)}return o>0?a/o:0}function HM(e,t,r){let n=Wt(ge(t,"front")),o=Wt(ge(t,"rear")),a=Math.min(r.v.length,r.ax.length,r.ay.length),s=r.loadFactor?nm(e):void 0,i=0,c=0;for(let l=0;l<a;l++){let u=r.ds?.[l]??1,m=_b(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 rm(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=ci(t,e.massTotal*zr*1.2),l=aa(c,"front"),u=aa(c,"rear"),m=ut(ge(t,"front")),f=ut(ge(t,"rear")),p=n.perWheel?yf(m,l):null,d=n.perWheel?f===m?p:yf(f,u):null,h=n.driven??wI,b={front:$t(e,"front",1),rear:$t(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=Wt(m),w=Wt(f),C=0,T=0,S=0,A=0,P=0,L=0,D=["FL","FR","RL","RR"],E=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,V=r.loadFactor?nm(e):void 0;for(let N=0;N<o;N++){let z=_b(e,V,r,N),{ayTyre:I,axCar:_}=z,B=I/zr,O=Ce(z.car,B,_/zr,r.v[N]),G=e.massTotal*I,K=G*i/a,Y=G*s/a,j=_s(m,K,O.FL,O.FR,P),Z=_s(f,Y,O.RL,O.RR,L);P=j,L=Z;let ne={FL:Math.abs(m.Fy(j,O.FL,0)),FR:Math.abs(m.Fy(j,O.FR,0)),RL:Math.abs(f.Fy(Z,O.RL,0)),RR:Math.abs(f.Fy(Z,O.RR,0))},te=(_-(r.axDrag?.[N]??0)-(r.axScrub?.[N]??0))/zr,fe=te>0&&h.front?GM(h,O,ne,l,u,b,"own"):0,W=r.v[N]*r.v[N],J=e.driveline?{Fz:O,alpha:{front:j,rear:Z},curvature:W>1?r.ay[N]/W:0,seed:g}:void 0,re={...Uh(e,te,r.v[N],t,B,fe,J)};te>0&&(b.front||$M(re,"FL","FR",l,O,ne),b.rear||$M(re,"RL","RR",u,O,ne));let pe=!1,de=!1;for(let ue of["FL","FR","RL","RR"]){let Be=(ue==="FL"||ue==="FR"?l:u).muX(O[ue])*O[ue];Math.abs(re[ue])>Be&&(pe=!0),O[ue]>(ue==="FL"||ue==="FR"?F:w)&&(de=!0)}de&&(M+=r.ds?.[N]??1);let ie=Sr(c,{FL:{Fz:O.FL,Fy:ne.FL,Fx:re.FL},FR:{Fz:O.FR,Fy:ne.FR,Fx:re.FR},RL:{Fz:O.RL,Fy:ne.RL,Fx:re.RL},RR:{Fz:O.RR,Fy:ne.RR,Fx:re.RR}},{lf:s,lr:i});if(y[N]=ie.stabil,R[N]=ie.agil,k[N]=ie.rel,E){let ue=.5*(O.FL+O.FR),Be=.5*(O.RL+O.RR),Ae=l.muX(ue)*ue,le=u.muX(Be)*Be;for(let Re of D){let Te=O[Re],ze=Re==="FL"||Re==="FR",je=ze?l:u,be=je.muY(Te)*Te,Fe=je.muX(Te)*Te,xe=E[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=FI(re[Re],Fe,ze?Ae:le),Ye=ze?p:d,Ue=Ye&&Te>0?Ye.reach(Te,Math.sign(re[Re])*Se,Le):1;xe.used[N]=Math.hypot(Le,Se)/Ue}}ie.stabil<v&&(v=ie.stabil,x=N);let oe=r.ds?.[N]??1;A+=oe,ie.diff>0&&(C+=oe),pe&&(T+=oe),df(z.car,r.v[N],_/zr,B)&&(S+=oe)}return{stabil:y,agil:R,rel:k,minStabil:Number.isFinite(v)?v:0,minStabilAt:x,pastTurnoverFrac:A>0?M/A:0,understeerFrac:A>0?C/A:0,beyondFrac:A>0?T/A:0,aeroOutsideFrac:A>0?S/A:0,wheels:E}}function nm(e){return Object.create(e,{loadFactor:{value:1,writable:!0,enumerable:!0}})}function zM(e,t){return e.loadFactor=t,e}var Nb=9.81;function Ob(e,t,r,n={}){let o=r.v.length,a=e.massTotal,s=Ir(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)/Nb,h=Math.min(.99,Math.max(.01,fa(e,f/Nb,u,t,d)));c.front[l]=p*h,c.rear[l]=p*(1-h);let b=i?lu(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/Nb)),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 iQ=Math.PI/180;var cQ=Tb.map(li);var lQ=[ce.zFL,ce.zFR,ce.zRL,ce.zRR];var uQ=Array.from({length:ce.rollRate+1},(e,t)=>t);var $I=9.81,GI=.001,KI=.6,HI=2,UM=4;function XM(e,t,r,n=UM){let o=Math.min(e.v.length,t.npts),{ds:a,closed:s}=t,i=r.massTotal*$I*r.wheelbase,c=zI(e.ay.slice(0,o).map((m,f)=>m/Math.max(GI,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 zI(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 qM(e,t,r,n,o={}){let a=o.maxIter??20,s=o.tol??.001,i=Math.min(1,Math.max(.001,o.relax??KI)),c=o.smoothM??UM,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=Rt(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=XM(d,t,r,c);f=v.demand.map((F,w)=>f[w]+i*(F-f[w])),p=v.rdot;let x=Rt(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>=HI){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 xQ=Math.PI/180;var QQ=180/Math.PI;function Da(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 ZM(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=>Da(p.vs,h,d)),axDecelN:p.decel.map(h=>Da(p.vs,h,d)),axScrubN:p.scrub.map(h=>Da(p.vs,h,d))});if(!o){let p=a(e);return d=>({ayMax:Da(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/Da(i.vs,i.radius,p),f=p=>p>=u||c.vs.length<2?Da(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 i2(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 JM(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=ZM(s,t),c=[],l=a,u=(f,p)=>{let d=.5*(f+p),h=e(d);l++;let b=i2(i(d),h);s.splice(s.findIndex(g=>g.v>d),0,h),i=ZM(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 c2=2,l2=.5,Ei=Math.PI/180,eS=21,u2={nCoarse:11,nSteer:13,nNorm:41,nAngle:45},m2={nCoarse:11,nSteer:13,nNorm:41,nAngle:61},p2=.005,d2=.05,Vb=e=>e<0?0:e>1?1:e;function f2(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*Ei,u=0,m=(b,g,y)=>{for(let R=b;R<=g;R+=y){let k=Math.abs(t.Fy(R*Ei,c,0));k>u&&(u=k,l=R*Ei)}};m(1,45,1),m(Math.max(.1,l/Ei-1),l/Ei+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*St(t,c,R,!1)/o),d.push(4*St(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 pr(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?m2:u2),{nCoarse:c,nSteer:l,nAngle:u}=i,m=Er(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=dt(f);s!==1&&(R.loadFactor=s);let k=mr(f),v=m1(0,n?.vRes??(e.engine?l2:c2),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}=oo(e),C=no(f,F,w),T=(B,O)=>{let G=M?mt(M.vVehicle,B,O):NaN;return Number.isFinite(G)?G:1/0},S=B=>{let O=B*B,{cl:G,cw:K,A:Y}=Gu(f,B,0,R),j=.5*d*-K*Y*O,Z=.5*d*-G*Y*O,ne=h*(-Z+y);return j+ne},A=B=>{let O=S(B)/p*C.powerFactor,G=S(B)/p*C.tractionFactor,K;if(e.engine){let j=S(B);K=ma(e.engine,B,C.effective,j,g).accel-O}else if(M){let j=0;F&&(j+=T(M.fFront,B)),w&&(j+=T(M.fRear,B)),K=g*j/p*C.powerFactor}else{let j=mt(e.vVehicle,x,B),Z=g*j/p*C.powerFactor;K=Number.isFinite(Z)?Z:1/0}let Y=ju(f,B,o)/p*C.powerFactor;return{axDrag:O,axDragTyre:G,axDrive:K,axPackCap:Y,axPower:Math.min(K,Y)}},P=v.map(A),L=e.vMax;for(let B=1;B<v.length;B++){let O=P[B].axDrive+P[B].axDrag;if(O>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-O):v[B-1];break}let D=Math.min(e.vMax,(1+d2)*L),E=r==="fast"?f2:nb,V=B=>{let O=E(R,k,B,{drivenFront:F,drivenRear:w,nSteer:l,yawDemandCn:a,axDrag:S(B)/p,...f.diffYaw?{diffYaw:!0}:{}}),G=O.ay[0],K=O.ay[O.ay.length-1],Y=te=>Math.min(Math.max(te*O.ayMax,G),K),j=m.map(te=>eu(O.ay,O.axAccel,Y(te))*C.tractionFactor),Z=m.map(te=>eu(O.ay,O.axDecel,Y(te))),ne=m.map(te=>eu(O.ay,O.axScrub,Y(te))*C.tractionFactor);return{v:B,ayMax:O.ayMax,axAccelN:j,axDecelN:Z,axScrubN:ne,atLock:O.atLock===!0}},N=r==="fast"?0:Math.min(bu,D),z=JM(V,N,D,c,i.anchorTol??p2),I=[],_=[];for(let B=0;B<v.length;B++){let O=v[B],{axDrag:G,axDragTyre:K,axDrive:Y,axPackCap:j,axPower:Z}=P[B],{ayMax:ne,axAccelN:te,axDecelN:fe,axScrubN:W}=z.at(O);I.push({v:O,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=Vb(Math.abs(Math.cos(ie)));J.push({ax:Math.min(mt(m,te,ue)+K,Z+G)+mt(m,W,ue),ay:oe,v:O})}for(let de=u-1;de>=0;de--){let ie=Math.PI*de/(u-1),oe=ne*Math.cos(ie),ue=Vb(Math.abs(Math.cos(ie)));re.push({ax:mt(m,fe,ue)+G+mt(m,W,ue),ay:oe,v:O})}let pe=(de,ie,oe)=>Array.from({length:eS},(ue,Be)=>({ax:ie+(oe-ie)*(Be+1)/(eS+1),ay:de,v:O}));_.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(I,m),rows:I,norm:m,surf:_}}function Ea(e,t){return e?.length?t.map(r=>am(e,r)):t.map(()=>0)}function am(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?mt(t,h,g):a(d,mt(t,h,g),mt(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?Vb(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,C=E=>k[E]+b*(v[E]-k[E]),T=E=>x[E]+b*(M[E]-x[E]),S=E=>F?y*(F[E]+b*(w[E]-F[E])):0,A=a(b,d.ayMax,h.ayMax),P=a(b,d.axDrag,h.axDrag),L=a(b,l(d),l(h)),D=a(b,d.axPower,h.axPower);for(let E=R;E>=0;E--){let V=Math.min(y*C(E)+L,D+P)+S(E),N=y*T(E)+P+S(E);if(!(g<=V+1e-6&&g>=N-1e-6))continue;if(E===R)return t[E]*y*A;let z=(O,G,K)=>{if(K(G))return 1;let Y=(O-g)/(O-G);return Y>0?Math.min(Y,1):0},I=O=>g<=O+1e-6,_=O=>g>=O-1e-6,B=Math.min(z(y*C(E)+L+S(E),y*C(E+1)+L+S(E+1),I),z(D+P+S(E),D+P+S(E+1),I),z(y*T(E)+P+S(E),y*T(E+1)+P+S(E+1),_));return(t[E]+B*(t[E+1]-t[E]))*y*A}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 h2(e,t,r){let n=e.params,o=n.m.value,{drivenFront:a,drivenRear:s}=oo(e),i=no(n,a,s);return c=>ju(n,c,t,r)/o*i.powerFactor}function Ii(e,t,r,n){let o=h2(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 b2=[-.2,-.08,0,.06,.12,.2,.3];function nS(e,t=!1,r="twoTrack",n,o,a=b2){let s=[...new Set([...a,0])].sort((d,h)=>d-h),i=s.map(d=>pr(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=>Ii(y,d,h,b));return{anchors:s,steady:g[s.indexOf(0)],clamps:p,at:f(g)}}}}function oS(e,t,r,n="twoTrack",o){let a=[...new Set([...t,1])].sort((i,c)=>i-c),s=a.map(i=>i===1?r:pr(e,!1,n,o,void 0,0,i));return{...tS(a,s),atSoc:(i,c,l)=>tS(a,s.map(u=>Ii(u,i,c,l)))}}function tS(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):Rb(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 aS=new WeakMap;function Bb(e,t){let r=aS.get(e);if(!r){let n=Dr(e).regen?Fb(t??Ft(e)):void 0;r={inp:dt(e),ev:mr(e),...n?{regen:n}:{}},aS.set(e,r)}return r}function $b(e,t,r){let n=Bb(e,r);return Ob(n.inp,n.ev,t,n.regen?{regen:n.regen}:{})}function Gb(e){let t=pt(e);if(t.mode!=="hydraulic")return null;let r=a=>a.heat?{heat:rh(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 g2(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 Kb(e,t,r,n,o,a=At){if(!e)return null;let s=g2(t);return{...e.front?{front:Xl(e.front.heat,e.front.discs,s.front,r,n,o.front,a)}:{},...e.rear?{rear:Xl(e.rear.heat,e.rear.discs,s.rear,r,n,o.rear,a)}:{}}}var y2=.5,x2=.02,R2=6,sm=9,sS=1e-9,v2={FL:0,FR:0,RL:0,RR:0};function Hb(e){return e?[...new Set([...e.padCurve.factor,1])].sort((t,r)=>t-r):[1]}function k2(e,t,r){let n=ir(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 iS(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 cS(e,t,r,n,o=()=>0){let a=Array.from({length:sm},(m,f)=>r*f/(sm-1)),s=si(),{front:i,rear:c}=n,l=a.map(m=>{let f=o(m),p=h=>_r(h,t,m,s).limitAt(0,0,v2,f).ax,d=p(e);return i.map(h=>c.map(b=>{if(h===1&&b===1)return 1;let g=d<0?p(k2(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(sm-2,Math.max(0,Math.floor(m/u))):0,h=u>0?Math.min(1,Math.max(0,(m-a[d])/u)):0,b=iS(i,f),g=iS(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(sm-1,d+1))-y(d));return Math.abs(R-1)<sS?1:R}}}function M2(e,t){let{front:r,rear:n}=t;return(o,a)=>e.share(a,r?.[o]??1,n?.[o]??1)}var S2=e=>(e.front??[]).every(t=>t===1)&&(e.rear??[]).every(t=>t===1);function lS(e,t,r){let n=e(),o=1,a=t(n);if(S2(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<R2;c++){let l=e(M2(r,s));o++;let u=Math.abs(l.laptime-n.laptime);if(n=l,u<x2){i=!0;break}a=t(n);let m=(d,h)=>d&&h?d.map((b,g)=>b+y2*((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 xn(e,t){let r=e.engine;if(!r||r.gears.length===0||t.length===0)return;let n=e.params,{drivenFront:o,drivenRear:a}=oo(e),s=no(n,o,a).effective,i=n.power_scale.value,{up:c,down:l}=gh(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:yh(r.engine.gearbox),limitRpm:r.engine.limitRpm,best:f=>ma(r,f,s,am(t,f)*s,i).gear,share:(f,p)=>{let d=am(t,f),h=d*s,b=ma(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 uS=new WeakMap;function Yb(e){let t=uS.get(e.ggv);return t===void 0&&(t=xn(e.vehicle,e.ggv.rows)??null,uS.set(e.ggv,t)),t??void 0}function A2(e){return e.gear&&e.engineRpm&&e.shifting?{gear:e.gear,rpm:e.engineRpm,shifting:e.shifting}:{}}var cm=class extends Error{constructor(t){super(t),this.name="EventError"}};function F2(e,t){let{ggv:r}=t,n=st(t.numerics),o=n.accelStep,a=Math.max(1,Math.round(e.distance/o)),s=Aa(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=Yb(t),c=i?zu(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:xS(t,f,[...u,s[a].v],m,1)}}function w2(e,t){let r=Math.max(1,Math.round(e.laps??1)),[n]=Aa(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=xS(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 lm(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 C2(e,t){let r=e.distance!=null?t.v_limit_endurance?.value??0:0;return r>0?r/3.6:void 0}function T2(e,t){if(e.distance==null||ft(t.motorModel))return 0;let r=t.endurance_reserve?.value??0;return r>0?Math.min(r,95)/100:0}var mS=1;function bS(e,t,r,n){return{v:r.v,ax:r.ax,ay:r.ay,ds:t.ds,axDrag:Ea(e.ggv.rows,r.v),...r.axScrub?{axScrub:r.axScrub}:{},axGrade:n,...t.bank?{bank:t.bank}:{}}}var pS=new WeakMap;function gS(e){let t=e.vehicle.params;if(!t.brakeFade)return null;let r=pS.get(t);if(r===void 0){let n=Gb(t),o=n?pt(t):null;if(!n||!o||o.mode!=="hydraulic")r=null;else{let a=Bb(t,e.vehicle),s=e.ggv.rows,i=cS(a.inp,a.ev,e.vehicle.vMax,{front:Hb(o.hydraulic.front.heat),rear:Hb(o.hydraulic.rear.heat)},c=>Ea(s,[c])[0]);r={discs:n,table:i}}pS.set(t,r)}return r}function P2(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=Yb(e),u=(g,y)=>e.yaw?qM(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}:{}}):Rt(Ii(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=yn(t.gradient,t.npts),f=g=>n.motorThermal?yM(e.vehicle,t.ds,e.energyOpts??Lr,y=>u(y,g),o,a,m,t.bank).lap:u(void 0,g),p=gS(e);if(!p)return f();let d=Pi(n),h=r.discC??{front:d,rear:d};return lS(f,g=>{let y=Kb(p.discs,$b(n,bS(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 L2(e,t){let r=C2(e,t.vehicle.params),n=T2(e,t.vehicle.params);return n>0?I2(e,t,n,r):_i(e,t,r)}function im(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 dS=5,D2=.1,E2=.005,fS=12;function I2(e,t,r,n){let o=_i(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=im(o,r);if(i>=0)return s(o,n,!0);let c=Math.min(n??1/0,t.ggv.vMax),l=c/2,u=_i(e,t,l);a++;let m=im(u,r);for(;m<0&&l>dS&&a<fS;)c=l,i=m,l=Math.max(dS,l/2),u=_i(e,t,l),a++,m=im(u,r);if(m<0)return s(u,l,!1);let f=l,p=0;for(;a<fS&&c-l>D2&&m>E2;){let d=c-l,h=Math.min(c-.05*d,Math.max(l+.05*d,l+m*d/(m-i))),b=_i(e,t,h);a++;let g=im(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 yS(e,t,r){return r===0?e:e&&!t}function _i(e,t,r){let n=t.track;if(!n)throw new cm(`Event "${e.id}" needs a track.`);let o=lm(e,n),a=e.standingStart??t.standingStart??!1,s=K=>yS(a,n.closed,K),i=t.vehicle.params,c=xr(Fa(i)),l=c.capacityAh,u=i.soc.value,m=Pi(i),f=Wu(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,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,F+=(K.motorDerateTimeFrac??0)*Y,v+=(K.motorLossKwh??0)/j,w+=(K.motorLossKwh??0)/j)},S=null,A,P=Gb(i),L={front:m,rear:m},D=null,E=gS(t)!==null,V=(K,Y)=>E&&(Math.abs(K.front-Y.front)>mS||Math.abs(K.rear-Y.rear)>mS),N=(K,Y,j)=>{let Z=wb(i,K,Y);if(D&&D.launch===j&&!O2(Z,D.pw)&&!V(L,D.discC))return D.lap;let ne=P2(t,n,{soc:K,packTempC:Y,launched:j,...r?{vCeiling:r}:{},...E?{discC:L}:{}});return D={pw:Z,launch:j,discC:L,lap:ne},ne},z=yn(n.gradient,n.npts),I=(K,Y,j)=>wa(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=$b(i,bS(t,n,K,z),t.vehicle),_.set(K,j)),Kb(P,j,K.v,n.ds,Y,m)},O=(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){A={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,C=-1/0;let ne=N(u,f,Y),te=I(ne,u,f);if(te.emptyAt>=0){A=O(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,Be=1;if(W<=zb)J=ne.laptime,re=te.net,pe=te.loss,de=te.chargeAh,ie=te.tempEndC,T(te,J),Be=1;else{let le=Math.min(_2,Math.max(2,Math.ceil(W/(2*zb))));Be=le;let Re=u,Te=f;J=0,re=0,pe=0,de=0;for(let ze=0;ze<le;ze++){let je=N(Re,Te,Y),be=I(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){A=O(K,ue,oe);break}u=Re}p+=J,d+=re,h+=pe,b+=de,W<=zb&&(u=te.socEnd),f=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:f,packTempMaxC:Number.isFinite(C)?C:Z,energyKwh:re,lossKwh:pe,chargeAh:de,launched:Y,substeps:Be,...r?{vCeiling:r}:{},...x?{motor:{peakWindingC:M,derateTimeFrac:J>0?F/J:0,lossKwh:w}}:{},...Ae?{brakes:{...Ae.front?{front:hS(Ae.front)}:{},...Ae.rear?{rear:hS(Ae.rear)}:{}}}:{}}),S=ne}if(!S){let K=Yb(t);S=Rt(Ii(t.ggv,t.vehicle,u),n,t.numerics,{standingStart:a,...t.load?{load:t.load.atSoc(t.vehicle,u)}:{},...K?{shifts:K}:{}}),A=A??{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:S.laptime,trace:{v:S.v,ax:S.ax,ay:S.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}:{},...S.loadFactor?{loadFactor:S.loadFactor}:{},...S.axScrub?{axScrub:S.axScrub}:{},...A2(S)},energy:{consumed:d,loss:h,...ft(i.motorModel)?{}:{native:{value:b,unit:"Ah"}},remainingFraction:ft(i.motorModel)?1:u,...y?{motor:{peakWindingC:R,derateTimeFrac:p>0?k/p:0,lossKwh:v}}:{}},lapLog:g,...A?{incomplete:A}:{}}}var zb=.05;function hS(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 _2=4,N2=.001;function O2(e,t){return e===t?!1:!Number.isFinite(e)||!Number.isFinite(t)?!0:Math.abs(e-t)>N2*Math.max(1,Math.abs(t))}function xS(e,t,r,n,o,a){return V2(e,t,o,()=>({v:r,ax:n,...a?{lateral:a}:{}}))}function V2(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=wa(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 ft(e.vehicle.params.motorModel)?{consumed:s,loss:i,remainingFraction:1}:{consumed:s,loss:i,native:{value:c,unit:"Ah"},remainingFraction:a}}function RS(e,t){switch(e.kind){case"straightLineAccel":return F2(e,t);case"constantRadius":return w2(e,t);case"trackLap":return L2(e,t)}}function Wb(e,t){let r={};for(let n of e)r[n.id]=RS(n,t);return r}function vS(e,t){if(e.kind!=="trackLap")return e;let{distance:r,...n}=e;return{...n,laps:Math.max(1,Math.round(t))}}function ao(e,t,r,n,o="twoTrack",a){let s=1/0,i=-1/0;for(let f of r){let p=wi(f);if(!p)continue;let d=oM(p,Rt(t,f,n).v);d&&(s=Math.min(s,d.lo),i=Math.max(i,d.hi))}if(!(i>=s))return;let c=aM({lo:s,hi:i}),l=c.join(","),u=a?.get(l);if(u)return u;let m=oS(e,c,t,o);return a?.set(l,m),m}var Ni=e=>e.distance/Math.max(1,e.laps);function Oi(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 B2=e=>e.v.map(t=>t*3.6),$2=e=>e.ax.map(t=>t/9.81),G2=e=>e.ay.map(t=>t/9.81),K2=e=>e.ay.map((t,r)=>e.v[r]>1e-6?t/(e.v[r]*e.v[r]):0),um=(e,t,r)=>e?.slice()??new Array(t.s.length).fill(r),H2=e=>um(e.z,e,0),z2=e=>e.gradient?e.gradient.map(t=>100*Math.tan(t*Math.PI/180)):um(void 0,e,0),Y2=e=>um(e.bank,e,0),W2=e=>um(e.mu,e,1);function j2(e){let t=e.s.length,r=Oi(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 jb=[{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 kS(e){let t=Oi(e);return{ds:t,vars:{s:e.s,ds:t,t:j2(e),v:e.v,speed:B2(e),ax:e.ax,ay:e.ay,axg:$2(e),ayg:G2(e),curv:K2(e),z:H2(e),grade:z2(e),bank:Y2(e),grip:W2(e)}}}function MS(e,t){return{v:e.v,ax:e.ax,ay:e.ay,ds:Oi({s:e.s,length:t}),axGrade:yn(e.gradient,e.v.length),...e.bank?{bank:e.bank}:{},...e.loadFactor?{loadFactor:e.loadFactor}:{}}}function SS(e,t){let r=dt(e);return{pastTurnover:HM(r,mr(e),t),...e.aeroModel?{aeroOutside:KM(r,t)}:{}}}var mm="Flying lap";function Ub(e,t){return e.kind!=="trackLap"||e.label!==mm?e.label:e.standingStart??t?"Run":e.label}function U2(e){let t=dt(e);return{yawInertia:t.yawInertia??0,massTotal:t.massTotal,wheelbase:t.wheelbase/1e3}}function X2(e,t,r){let n=e.params,o=n.ggvMode??"twoTrack",a=n.quasiTransient?nS(e,!1,o):null,s=a?a.steady:pr(e,!1,o),i=t?ao(e,s,[t],r,o):void 0;return{ggv:s,...a?{yaw:{family:a,car:U2(n)}}:{},...i?{load:i}:{}}}function q2(e,t){let r=t.lapCounts,n=t.standingStart??!1,o=!1,a=e.events.map(s=>{let i=r?.[s.id]!=null?vS(s,r[s.id]):s,c=Ub(i,n),l=c===i.label?i:{...i,label:c};return l!==s&&(o=!0),l});return o?a:e.events}function Q2(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=lm(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 Z2(e,t){for(let[r,n]of Object.entries(e))n.trace&&(e[r]={...n,...SS(t,MS(n.trace,Ni(n)))})}function Vi(e,t,r={}){let n=Ft(e),o=X2(n,r.track,r.numerics),{ggv:a}=o,s=Wb(q2(t,r),{vehicle:n,...o,track:r.track,energyOpts:Dr(e,r.energyOpts),numerics:r.numerics,standingStart:r.standingStart});return Q2(s,t,r),Z2(s,n.params),{name:e.name,rulesetId:t.id,events:s,ggv:a}}function Xb(e){return{...e,ggv:{rows:e.ggv.rows,vMax:e.ggv.vMax,surf:e.ggv.surf}}}var qb=["<","<=",">",">=","==","!="],Ne=class extends Error{at;constructor(t,r){super(t),this.name="ExprError",this.at=r}},Bi=e=>e>="0"&&e<="9",AS=e=>/[A-Za-z_]/.test(e),J2=e=>/[A-Za-z0-9_]/.test(e);function e_(e){let t=[],r=0;for(;r<e.length;){let n=e[r];if(n===" "||n===" "||n===`
|
|
224
|
+
`||n==="\r"){r++;continue}if(Bi(n)||n==="."&&Bi(e[r+1]??"")){let o=r;for(;r<e.length&&(Bi(e[r])||e[r]===".");)r++;if(e[r]==="e"||e[r]==="E"){let i=r;if(r++,(e[r]==="+"||e[r]==="-")&&r++,Bi(e[r]??""))for(;r<e.length&&Bi(e[r]);)r++;else r=i}let a=e.slice(o,r),s=Number(a);if(!Number.isFinite(s))throw new Ne(`"${a}" is not a number`,o);t.push({t:"num",value:s,at:o});continue}if(AS(n)){let o=r;for(;;){for(;r<e.length&&J2(e[r]);)r++;if(e[r]==="."&&AS(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(qb.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 Ne(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 Ne(`"${n}" is not something this expression can contain`,r)}return t.push({t:"end",at:e.length}),t}function Qb(e){let t=e_(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 Ne(`Expected ${b} here`,n().at)};function i(){let h=c(),b=n();if(b.t!=="op"||!qb.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"&&qb.includes(y.value))throw new Ne("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 Ne("The expression ends before it is finished",h.at):new Ne(`"${h.value}" cannot start a value`,h.at)}let p=i(),d=n();if(d.t!=="end")throw new Ne(`"${d.value}" is left over \u2014 check for a missing operator`,d.at);return p}function Zb(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 $i=(e,t)=>typeof e=="number"?new Array(t).fill(e):e;function t_(e){let t=1;for(let r of e)Array.isArray(r)&&(t=Math.max(t,r.length));return t}function Tt(e,t){if(e.every(a=>typeof a=="number"))return t(...e);let r=t_(e),n=e.map(a=>$i(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 Oe=(e,t)=>({arity:e,call:r=>Tt(r,t)}),so=e=>e!==0&&!Number.isNaN(e),dr=e=>e?1:0;function FS(e,t,r){let n=wS(t,r,"integrate"),o=n.length,a=$i(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 wS(e,t,r){if(!e.ds||e.ds.length===0)throw new Ne(`${r}() needs to know the sample spacing, and this context has none`,t);return e.ds}var pm={abs:Oe(1,Math.abs),sqrt:Oe(1,Math.sqrt),sign:Oe(1,Math.sign),floor:Oe(1,Math.floor),ceil:Oe(1,Math.ceil),round:Oe(1,Math.round),exp:Oe(1,Math.exp),log:Oe(1,Math.log),sin:Oe(1,Math.sin),cos:Oe(1,Math.cos),tan:Oe(1,Math.tan),atan:Oe(1,Math.atan),atan2:Oe(2,Math.atan2),hypot:Oe(2,Math.hypot),min:Oe(2,Math.min),max:Oe(2,Math.max),clamp:Oe(3,(e,t,r)=>Math.min(r,Math.max(t,e))),if:Oe(3,(e,t,r)=>so(e)?t:r),and:Oe(2,(e,t)=>dr(so(e)&&so(t))),or:Oe(2,(e,t)=>dr(so(e)||so(t))),not:Oe(1,e=>dr(!so(e))),finite:Oe(1,e=>dr(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=FS(e,t,0),n=t.ds,o=$i(e,n.length),a=n.length-1;return r[a]+(o[a]+o[0])/2*n[a]}},integrate:{arity:1,call:([e],t)=>FS(e,t,0)},cum:{arity:1,call:([e],t)=>{let r=t.ds?.length??(Array.isArray(e)?e.length:1),n=$i(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=wS(t,0,"deriv"),n=r.length,o=$i(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}}},Ia={g:9.81,pi:Math.PI,e:Math.E,nan:NaN,inf:1/0},Gi={fleetmin:"min",fleetmax:"max"};function io(e){switch(e.kind){case"call":return Object.hasOwn(Gi,e.name)||e.args.some(io);case"unary":return io(e.arg);case"binary":return io(e.left)||io(e.right);default:return!1}}var r_=e=>typeof e=="number"?`${e}`:`between ${e[0]} and ${e[1]}`;function n_(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 o_(e,t){let r=t.map(c=>({k:c,d:n_(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 fr(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(Ia,e.name))return Ia[e.name];let r=[...Object.keys(t.vars),...Object.keys(Ia)].sort();throw new Ne(o_(e.name,r),e.at)}case"unary":return Tt([fr(e.arg,t)],r=>-r);case"binary":{let r=fr(e.left,t),n=fr(e.right,t);switch(e.op){case"+":return Tt([r,n],(o,a)=>o+a);case"-":return Tt([r,n],(o,a)=>o-a);case"*":return Tt([r,n],(o,a)=>o*a);case"/":return Tt([r,n],(o,a)=>a===0?0:o/a);case"^":return Tt([r,n],(o,a)=>o**a);case"<":return Tt([r,n],(o,a)=>dr(o<a));case"<=":return Tt([r,n],(o,a)=>dr(o<=a));case">":return Tt([r,n],(o,a)=>dr(o>a));case">=":return Tt([r,n],(o,a)=>dr(o>=a));case"==":return Tt([r,n],(o,a)=>dr(o===a));case"!=":return Tt([r,n],(o,a)=>dr(o!==a))}break}case"call":{let r=Object.hasOwn(Gi,e.name)?Gi[e.name]:void 0;if(r){if(!t.fleet)throw new Ne(`${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 Ne(`${e.name}() takes 1 argument, not ${e.args.length}`,e.at);return t.fleet(e.args[0],r,e.at)}let n=Object.hasOwn(pm,e.name)?pm[e.name]:void 0;if(!n){let s=[...Object.keys(pm),...t.fleet?Object.keys(Gi):[]];throw new Ne(`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 Ne(`${e.name}() takes ${r_(n.arity)} argument${o===1&&a===1?"":"s"}, not ${e.args.length}`,e.at);return n.call(e.args.map(s=>fr(s,t)),t)}}throw new Ne("Unreachable node",0)}var _a=e=>Number.isFinite(e)?e:NaN,Jb=[{name:"time",unit:"s",what:"the whole event, every lap",read:e=>_a(e?.time)},{name:"lapTime",unit:"s",what:"one lap \u2014 the last one completed",read:e=>_a(e?.lapTime)},{name:"distance",unit:"m",what:"distance covered",read:e=>_a(e?.distance)},{name:"laps",unit:"-",what:"laps completed",read:e=>_a(e?.laps)},{name:"energy",unit:"kWh",what:"energy drawn over the event",read:e=>_a(e?.energy?.consumed)},{name:"remaining",unit:"-",what:"share of the pack or tank left afterwards",read:e=>_a(e?.energy?.remainingFraction)},{name:"finished",unit:"-",what:"1 when the car ran the whole event, else 0",read:e=>e&&!e.incomplete?1:0}],CS=/^[A-Za-z_][A-Za-z0-9_]*$/,a_=new Set([...Object.keys(Ia),...jb.map(e=>e.name)]);function dm(e,t,r=[]){let n=[],o=new Set(r),a=t.map(b=>b.id),s=new Set;for(let b of a)CS.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(!CS.test(b.key)){n.push({key:b.key,message:`"${b.key}" must be one word \u2014 letters, digits and _`});continue}if(a_.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,Qb(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,[...Zb(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=s_(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 Ne("fleetmin() and fleetmax() cannot sit inside one another",y)},p=new Set,d={};for(let b of a)for(let g of Jb)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 jb)h[b.name]=[1,1];for(let b of m){let g=i.get(b),y=c.get(b);(io(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=fr(x,{vars:R,ds:k,fleet:f});if(Array.isArray(w))throw new Ne("fleetmin() and fleetmax() compare one number per car \u2014 reduce the channel first, e.g. peak(v)",F);return w};try{let x=fr(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 s_(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 i_(e,t,r={}){let n={...r};for(let o of e.eventIds){let a=t.events[o];for(let s of Jb)n[`${o}.${s.name}`]=s.read(a)}return{vars:n,laps:new Map,events:t.events}}function TS(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?kS({...n.trace,length:Ni(n)}):null,e.laps.set(t.over,r)}return r?{vars:{...e.vars,...r.vars},ds:r.ds}:null}var PS=e=>Array.isArray(e)?NaN:e;function LS(e,t,r,n={}){let o=Object.keys(t),a=o.map(i=>i_(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=TS(b,i);if(!g)continue;let y=PS(fr(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=TS(f,i);f.vars[i.key]=p?PS(fr(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 Ki(e,t,r){return LS(e,t,!0,r)}function eg(e,t,r){return LS(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:
|
|
225
225
|
`+r.map(n=>` ${n.key?`${n.key}: `:""}${n.message}`).join(`
|
|
226
|
-
`)),this.name="RulesetDefError",this.problems=r}},Ni=e=>typeof e=="number"&&Number.isFinite(e),_i=e=>Ni(e)&&e>0,Pt=(e,t)=>e===void 0||t(e);function I2(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":_i(a.distance)||r(`${s} needs a distance above zero, in metres`),Pt(a.vStart,i=>Ni(i)&&i>=0)||r(`${s}'s entry speed must be zero or more`);break;case"constantRadius":_i(a.radius)||r(`${s} needs a radius above zero, in metres`),Pt(a.laps,i=>Ni(i)&&i>=1)||r(`${s} runs at least one lap`);break;case"trackLap":Pt(a.laps,i=>Ni(i)&&i>=1)||r(`${s} runs at least one lap`),Pt(a.distance,_i)||r(`${s}'s distance must be above zero, in metres`),Pt(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),Pt(a.unit,i=>typeof i=="string")||r("Its unit is text",s),Pt(a.over,i=>typeof i=="string")||r("Names its event by id",s),Pt(a.format,i=>i==="time"||i==="points")||r("Is shown as a time, as points, or as a number",s),Pt(a.max,Ni)||r("Its maximum is a number",s),Pt(a.lowerBetter,i=>typeof i=="boolean")||r("Lower is better, or it is not",s),Pt(a.hidden,i=>typeof i=="boolean")||r("Is hidden, or it is not",s)}Pt(e.track?.minTurnRadius,_i)||r("The tightest turn the rules allow is a radius above zero");let n=e.battery;for(let o of["packVoltageMax","segmentVoltageMax","powerLimitKw"])Pt(n?.[o],_i)||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 dS(e){let t=I2(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}=om(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 sm(e){return dS(e).problems}var Kb=e=>Number.isFinite(e)?e:NaN;function _2(e){return e.unit&&e.format!=="time"?`${e.label} (${e.unit})`:e.label}function hn(e){let t=structuredClone(e),{plan:r,problems:n}=dS(t);if(!r)throw new am(t.id,n);let o=new WeakMap,a=p=>{let d=o.get(p);return d||(d=Gb(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 Kb(b);let g=h,y=i.get(p);return y!==void 0?Kb(g.parts?.[y]):p===t.score?.total?Kb(g.total):NaN},l=t.kpis.filter(p=>!p.hidden).map(p=>{let d=r.field.has(p.key);return{key:p.key,label:_2(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=Ii(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=Ii(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 Wt={accel:"accel",skidpad:"skidpad",autocross:"autocross",endurance:"endurance"},fS=[{kind:"straightLineAccel",id:Wt.accel,label:"Acceleration (75 m)",distance:75},{kind:"constantRadius",id:Wt.skidpad,label:"Skidpad",radius:8.375},{kind:"trackLap",id:Wt.autocross,label:"Autocross (1 lap)",laps:1},{kind:"trackLap",id:Wt.endurance,label:"Endurance (22 km)",distance:22e3}],hS=[{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"}],bS={total:"overall",parts:{[Wt.accel]:"accelPts",[Wt.skidpad]:"skidpadPts",[Wt.autocross]:"autocrossPts",[Wt.endurance]:"endurancePts",efficiency:"efficiencyPts"}},gS={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:fS,kpis:hS,score:bS,track:{minTurnRadius:4.5},battery:Ly,traceEventId:Wt.autocross},yS={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:fS,kpis:hS,score:bS,track:{minTurnRadius:4.5},traceEventId:Wt.autocross},Oi=hn(gS),Hb=hn(yS);var zb="lap",N2=[{kind:"trackLap",id:zb,label:rm,laps:1}],xS={id:"trackday",label:"Track day",description:"One flying lap of the selected track. Times and traces only \u2014 no scoring.",events:N2,kpis:[{key:"lap",label:"Lap time",format:"time",lowerBetter:!0,expr:"lap.time"},{key:"topSpeed",label:"Top speed",unit:"km/h",over:zb,expr:"peak(speed)"},{key:"energy",label:"Energy / lap",unit:"kWh",lowerBetter:!0,expr:"lap.energy"}],traceEventId:zb},Yb=hn(xS);function bn(e){if(e===null||typeof e!="object")return JSON.stringify(e)??"null";if(Array.isArray(e))return`[${e.map(bn).join(",")}]`;let t=e,r=Object.keys(t).sort(),n=[];for(let o of r)t[o]!==void 0&&n.push(`${JSON.stringify(o)}:${bn(t[o])}`);return`{${n.join(",")}}`}function ro(e){let t=bn(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 Da=[Oi,Hb,Yb],no=Oi.id,Ea=e=>Da.some(t=>t.id===e),RS=new WeakMap,Vi=new Map,O2=64;function im(e){let t=RS.get(e);if(t!==void 0)return t;let r=bn(e),n=Vi.get(r);return n===void 0&&(n=sm(e).length?null:hn(e),Vi.size>=O2&&Vi.delete(Vi.keys().next().value),Vi.set(r,n)),RS.set(e,n),n}function cm(e,t=[]){if(e==null)return;if(typeof e!="string")return im(e)??void 0;let r=Da.find(o=>o.id===e);if(r)return r;let n=t.find(o=>o.id===e);return n?im(n)??void 0:void 0}function oo(e,t=[]){return cm(e,t)??Oi}function Wb(e=[]){let t=e.filter(r=>!Ea(r.id)).map(r=>im(r)).filter(r=>r!==null);return[...Da,...t]}var Bi=e=>e.definition??e.id;function lm(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=V2(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 Ub(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=jb(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 V2(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=jb(e,c,r,n),u=new Array(o).fill(0);u[0]=i,u[o-1]=s;let m=jb(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 jb(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 $i(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 vS(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 kS(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 MS(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=>vS(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=kS([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 B2(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=vS(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 $2(e,t,r){let{j:n,t:o}=B2(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=kS([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 Xb(e,t){return t>0?e.z.map((r,n)=>{let o=$2(e,n,t/2);return o?o.value.reduce((a,s,i)=>a+s*e.z[o.j[i]],0):r}):[...e.z]}function G2(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 um(e){let t=$i(e);if(!t)return 0;let r=MS(t);return r>1e-6?Math.max(10,G2(r,K2(t))):0}function K2(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 mr(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 pm(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 SS(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 mm(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 H2(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 qb(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=SS(r,(y,R)=>mr(e,y,R));if(!b)return null;let g=mm(b,t);return g.every(Number.isFinite)?g:null}let n=r-2,a=SS(n,(b,g)=>mr(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]=mr(e,b,r-2),i[b]=mr(e,b,r-1);let c=mm(a,t.slice(0,n)),l=mm(a,s),u=mm(a,i),m=(b,g)=>{let y=0;for(let R=0;R<b.length;R++)y+=b[R]*g[R];return y},f=[[mr(e,r-2,r-2)-m(s,l),mr(e,r-2,r-1)-m(s,u)],[mr(e,r-1,r-2)-m(i,l),mr(e,r-1,r-1)-m(i,u)]],p=[t[r-2]-m(s,c),t[r-1]-m(i,c)],d=H2(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 AS(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=qb(i,t);if(c){let l=pm(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 FS=4,z2=8,Qb=.001;function Y2(e,t,r){let n=[];for(let c=1;c<e.length;c++){let l=e[c]-e[c-1];l>=Qb&&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/_k(r,s,i)))}function W2(e,t){let r=e.closed!==!1,n=[],o=[],a=(F,w)=>{let C=n.length-1;C>=0&&Math.hypot(F-n[C],w-o[C])<Qb||(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:Y2(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 C=c[p+1]-c[p],T=C>0?(w-c[p])/C:0,S=(p+1)%s;a(e.x[p]+T*(e.x[S]-e.x[p]),e.y[p]+T*(e.y[S]-e.y[p]))}if(r)for(;n.length>2&&Math.hypot(n[n.length-1]-n[0],o[o.length-1]-o[0])<Qb;)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,C=n[w]-n[F-1],T=o[w]-o[F-1],S=Math.sqrt(Math.hypot(C,T))||1e-9;b[F]=b[F-1]+S}let g=r?lm(b.slice(0,d),n,b[d]):Ub(b,n),y=r?lm(b.slice(0,d),o,b[d]):Ub(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]/FS;for(let C=0;C<FS;C++){let T=C*w;M+=rh(S=>Math.hypot(g.d1(F,S),y.d1(F,S)),T,T+w),k.push(M),v.push(F),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 Gi(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 j2=.01,U2=3,wS=10;function X2(e,t,r,n=wS){let o={step:0,uncertainty:1/0},a=e.length;if(a<8||!(r>0))return o;let s=Math.max(wS,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=Qt(d,h),g=Qt(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 q2(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 Q2(e,t,r){let{pos:n,loop:o}=q2(e.length,t),{step:a,uncertainty:s}=X2(e,n,o,r);return Math.abs(a)>Math.max(j2,U2*s)?{z:e.map((i,c)=>i+a*n[c]/o),drift:-a}:{z:e,drift:0}}function Z2(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+rh(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 J2=3,Zb=5;function e_(e,t,r,n=Zb){return fm(e,t,r,n)}function fm(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 qb({n:a,diag:i,off1:c,off2:l,closed:r},u)??[...e]}function it(e,t){let r=st(t),n=W2(e,r.fitSpacing),o=n.length,a=Math.max(z2,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 C=0;C<s;C++){let T=C*i,{seg:S,du:A}=Z2(n,T);c[C]=n.sx.eval(S,A),l[C]=n.sy.eval(S,A),u[C]=T;let P=n.sx.d1(S,A),L=n.sy.d1(S,A),D=n.sx.d2(S,A),E=n.sy.d2(S,A),V=Math.hypot(P,L),N=Math.pow(P*P+L*L,1.5);f[C]=N>0?(P*E-L*D)/N:0,p[C]=V>0?-L/V:0,d[C]=V>0?P/V: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?Q2(e.z,n.rawCum,g):null,R=y?y.z:e.z,k=g>0?$i(e):null,v=k?Xb({...k,z:R},g):R,x=Gi(v,0,h,n),M=new Array(s).fill(0);if(b){for(let T=0;T<s;T++){let S=n.closed?(T+1)%s:Math.min(T+1,s-1),A=n.closed?(T-1+s)%s:Math.max(T-1,0),P=n.closed?2:S-A,L=x[S]-x[A];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 S=n.closed?(T+1)%s:T+1,A=x[S]-x[T];m[T]=Math.hypot(i,A)}let C=0;for(let T=0;T<s;T++)u[T]=C,C+=m[T]}let F=b?m.reduce((C,T)=>C+T,0):o,w;if(b){w=new Array(s).fill(0);let C=Math.max(J2,e.zReach??um(e)),T=Math.max(2,Math.round(C/i));if(n.closed?s>2*T:s>2*T+1){let S=0,A=0;for(let D=-T;D<=T;D++)S+=D*D,A+=D*D*D*D;let P=2*T+1,L=A-S*S/P;for(let D=0;D<s;D++){let E=n.closed?D:Math.min(Math.max(D,T),s-1-T),V=0,N=0;for(let _=-T;_<=T;_++){let B=x[n.closed?(E+_+s)%s:E+_];V+=(_*_-S/P)*B,N+=_*B}let z=2*V/L/(i*i),I=N/S/i;w[D]=z/Math.pow(1+I*I,1.5)}}}return{name:e.name,closed:n.closed,x:c,y:l,s:u,ds:m,curvature:e.turnReach?e_(f,i,n.closed,e.turnReach):f,npts:s,length:F,nx:p,ny:d,z:x,gradient:M,...w?{verticalCurvature:w}:{},widthLeft:Gi(e.widthLeft,1.5,h,n),widthRight:Gi(e.widthRight,1.5,h,n),bank:Gi(e.bank,0,h,n),mu:Gi(e.mu,1,h,n),...y?.drift?{elevationDrift:y.drift}:{}}}function CS(e,t,r){let n=pm(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 t_(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]-=mr(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 AS(c,i)}var r_=1e-4;function TS(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=CS(e,t,u),f=new Array(a).fill("free"),p=!1;for(let d=0;d<s;d++){let h=pm(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=t_(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 C=F+R*(g[w]-F),T=l(C,w);return T!==C&&(k=!0),T}),x=CS(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+r_*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 Jb={lineStep:2,carHalfWidth:.75,margin:.1,foldMargin:.25,referenceReach:5,passes:40,iterations:400},n_=[1,.5,.25,.125,.0625,.03125,.015625,.0078125,.00390625,.001953125,.0009765625],o_=e=>Math.sqrt(e.reduce((t,r)=>t+r*r,0)/(e.length||1));function Ki(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 a_=Math.PI/180,PS=20;function s_(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?PS:Math.min(PS,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 i_(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?s_(t,r):t.z;return{...n||o?{z:s.map((i,c)=>i+r[c]*Math.tan(t.bank[c]*a_))}:{},...n?{zReach:e.zReach??um(e)}:{},...o?{bank:[...t.bank]}:{},...a?{mu:[...t.mu]}:{}}}function LS(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 c_(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,C=(b*r[u]+g*n[u])/k,T=(f*r[l]+p*n[l])/y,S=(d*r[l]+h*n[l])/R,A=(d*r[m]+h*n[m])/R,P=(b*r[m]+g*n[m])/k,L=-2*c(r[u],n[u],d,h)/v+x*(w/y+C/k),D=2*c(r[l],n[l],b,g)/v-x*(T/y-S/R),E=2*c(f,p,r[m],n[m])/v-x*(A/R+P/k);s[l]=x*M,i.l[l]=M*L-F*.5*w,i.d[l]=M*D+F*.5*(T-S),i.r[l]=M*E+F*.5*A}return{res:s,jac:i}}function l_(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 u_(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=fm(e.x,s,n,t,!0),c=fm(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=Ki(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 m_=6;function p_(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(m_/(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 eg(e,t={}){let r={...Jb,...t},n=it(e,{dsTarget:r.lineStep}),o=u_(n,r.referenceReach),a=o.npts,s=T=>({x:o.x.map((S,A)=>S+o.nx[A]*T[A]),y:o.y.map((S,A)=>S+o.ny[A]*T[A])}),i=T=>{let S=Ki(T.x,T.y,o.closed),A=LS(T.x,T.y,o.closed),P=0;for(let L=0;L<S.length;L++)P+=S[L]*S[L]*A[L];return P},c=o_(n.curvature),l=LS(n.x,n.y,n.closed).reduce((T,S)=>T+S,0),u=new Array(a).fill(0),m=r.carHalfWidth+r.margin,f=new Array(a),p=new Array(a),d=0;for(let T=0;T<a;T++){let S=o.widthLeft[T]-m,A=-(o.widthRight[T]-m);if(S<A){d++;let P=(o.widthLeft[T]-o.widthRight[T])/2;f[T]=P,p[T]=P}else f[T]=S,p[T]=A}let h=[...f],b=[...p];p_(o,f,p,r.foldMargin);let g=T=>{let S=s(T),A=i_(e,o,T),P={name:`${e.name} \u2014 racing line`,x:S.x,y:S.y,closed:o.closed,widthLeft:h.map((I,_)=>Math.max(0,I-T[_])),widthRight:b.map((I,_)=>Math.max(0,T[_]-I)),...A,fit:"interpolate",turnReach:Zb},L=1e-6,D=T.filter((I,_)=>I>=f[_]-L||I<=p[_]+L).length,E=Ki(S.x,S.y,o.closed),V=I=>1/Math.max(...I.map(Math.abs),1e-9),N=0,z=o.closed?S.x.length:S.x.length-1;for(let I=0;I<z;I++){let _=(I+1)%S.x.length,B=S.x[_]-S.x[I],O=S.y[_]-S.y[I];N+=A.z?Math.hypot(B,O,A.z[_]-A.z[I]):Math.hypot(B,O)}return{offset:T,s:[...o.s],asset:P,curvatureRms:{centreLine:c,racingLine:Math.sqrt(i(S)/(l||1))},infeasibleSamples:d,atBoundary:a?D/a:0,length:{centreLine:n.length,racingLine:N},worstRadius:{centreLine:V(n.curvature),racingLine:V(E)}}},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]=f[y+T];if(!o.closed&&k>0){let T=(S,A)=>{if(v[S]=Math.max(v[S],p[A]),x[S]=Math.min(x[S],f[A]),v[S]>x[S]){let P=.5*(v[S]+x[S]);v[S]=P,x[S]=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 S=s(T),P=[...Ki(S.x,S.y,o.closed).map(Math.abs)].sort((L,D)=>L-D);return{integral:i(S),tail:P[Math.floor(.99*(P.length-1))]}},F=[...u],w=M(u),C;for(let T=0;T<r.passes;T++){let S=s(F),{res:A,jac:P}=c_(S.x,S.y,o.nx,o.ny,o.closed),{M:L,b:D}=l_(P,A,y,R,o.closed),E=TS(L,D,v.map((z,I)=>z-F[y+I]),x.map((z,I)=>z-F[y+I]),{maxIter:r.iterations,bounds:C});C=E.bounds;let V=new Array(a).fill(0);for(let z=0;z<k;z++)V[y+z]=E.x[z];o.closed||(V[0]=V[1],V[a-1]=V[a-2]);let N=!1;for(let z of n_){let I=F.map((B,O)=>B+z*V[O]),_=M(I);if(_.integral<w.integral*(1-1e-6)){F=I,w=_,N=!0;break}}if(!N)break}return g(F)}function tg(e){let t=Math.max(Q(e,"track_front"),Q(e,"track_rear"));return(t>0?t/2e3:.6)+.1}function hm(e,t,r={}){if(!r.racingLine)return{asset:e,numerics:t,line:null};let n=r.params?tg(r.params):void 0,o=eg(e,{...r.line,...n?{carHalfWidth:n}:{}});return{asset:o.asset,numerics:{...t,fitSpacing:0},line:o}}function Hi(e,t,r={}){let n=hm(e,t,r);return{track:it(n.asset,n.numerics),line:n.line}}function rg(e=4,t=Hi){let r=new WeakMap;return(n,o,a={})=>{let s=a.racingLine===!0,i=s?[a.params?tg(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 DS={racingLine:!1,standingStart:!1},bm=256;function zi(e,t,r,n,o=DS,a=Hi){let s=oo(n),{racingLine:i,standingStart:c,lapCounts:l}=o;return e.map(u=>{let{track:m}=a(t,r,{racingLine:i,params:u});return Nb(Pi(u,s,{track:m,numerics:r,standingStart:c,lapCounts:l}))})}function ng(e,t){let r=oo(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 og(e,t,r){let n={};for(let o of oo(e).metrics)n[o.key]=o.value(t,r);return n}var gm=36;var ig=287.05287,f_=461.495,ym=9.80665/(ig*.0065),h_=101325/(ig*288.15),b_=273.15,g_=-500,y_=6e3,x_=400,R_=1100,xm={source:"car",altitudeM:0,pressure:{kind:"standard"},humidityPct:0};function v_(e){return 101325*Math.pow(1-.0065*e/288.15,ym)}function k_(e){return 288.15/.0065*(1-Math.pow(e/h_,1/(ym-1)))}function M_(e){return 288.15/.0065*(1-Math.pow(e/101325,1/ym))}function S_(e,t){return e*Math.pow(1-.0065*t/288.15,ym)}function A_(e){return 611.21*Math.exp((18.678-e/234.5)*(e/(257.14+e)))}function F_(e,t){switch(e.kind){case"standard":return v_(t);case"qnh":return S_(e.hPa*100,t);case"station":return e.hPa*100}}function Yi(e,t,r=0,n=M_(e)){let o=t+b_,a=Math.min(.5*e,Math.max(0,Math.min(100,r))/100*A_(t)),s=e-a,i=s/(ig*o)+a/(f_*o);return{altitudeM:n,p:e,pDry:s,T:o,rho:i,densityAltitudeM:k_(i)}}function ES(e,t){return Yi(F_(e.pressure,e.altitudeM),t,e.humidityPct,e.altitudeM)}var ag=(e,t,r)=>Math.min(r,Math.max(t,e)),sg=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function Rm(e){if(!e||typeof e!="object")return structuredClone(xm);let t=e,r=t.pressure??{},n=ag(sg(r.hPa,1013.25),x_,R_),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:ag(sg(t.altitudeM,0),g_,y_),pressure:o,humidityPct:ag(sg(t.humidityPct,0),0,100)}}var Wi=e=>e?.source==="venue";var w_=Math.PI/180;function C_(){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 T_(){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 cg(e){let t=-e*w_;return q([0,Math.cos(t),Math.sin(t)])}function vm(){let e={rodType:"push",pushrodAttach:"lowerArm",steerMode:"rack",spinAxis:cg(-1),loadedRadius:230,springRate:35,rackAxis:[0,1,0]};return{hardpoints:C_(),config:e}}function ji(){let e={rodType:"pull",pushrodAttach:"lowerArm",steerMode:"fixed",spinAxis:cg(-1.5),loadedRadius:232,springRate:40,rackAxis:[0,1,0]};return{hardpoints:T_(),config:e}}function km(){let e=[-25,635,460],t=[-40,600,710],r={layout:"mcpherson",actuation:"direct",rodType:"push",pushrodAttach:"upright",steerMode:"rack",spinAxis:cg(-.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 lg(){return{front:vm(),rear:ji(),config:{wheelbase:1600,trackFront:1200,trackRear:1220,frontAxleX:800}}}var P_=Math.PI/180;function IS(e){let t=-e*P_;return q([0,Math.cos(t),Math.sin(t)])}function ug(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:IS(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]=L_(o[l]);return{hardpoints:o,config:c}}function L_(e){return e.map(t=>Math.round(t*10)/10+0)}function so(e){return{name:e.name,front:ug(vm(),e.front),rear:ug(ji(),e.rear),config:{wheelbase:e.wheelbase,trackFront:e.trackFront,trackRear:e.trackRear,frontAxleX:e.wheelbase/2}}}function Ia(e,t,r){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:t}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:r}}}}var _a=600,io=610,Na=230,co=232;function lo(){let e=lg();return{...e,name:"Formula Student",front:{...e.front,config:{...e.front.config,actuation:"rocker"}},rear:{...e.rear,config:{...e.rear.config,actuation:"rocker"}}}}function mg(){return so({name:"Formula 1",wheelbase:3600,trackFront:1600,trackRear:1600,front:{kx:1.3,ky:800/_a,kz:355/Na,lowerInnerDz:-5,upperInnerDz:0,camberDeg:-3,loadedRadius:355,springRate:200},rear:{kx:1.3,ky:800/io,kz:355/co,lowerInnerDz:35,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:220}})}function Ui(){return Ia(so({name:"GT car",wheelbase:2700,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/_a,kz:325/Na,lowerInnerDz:18,upperInnerDz:5,camberDeg:-3.5,loadedRadius:325,springRate:110,actuation:"direct"},rear:{kx:1.2,ky:825/io,kz:325/co,lowerInnerDz:36,upperInnerDz:15,camberDeg:-2,loadedRadius:325,springRate:120,actuation:"direct"}}),318.6,318.6)}function Xi(){return Ia(so({name:"Sports car",wheelbase:2750,trackFront:1550,trackRear:1550,front:{kx:1.15,ky:775/_a,kz:320/Na,lowerInnerDz:36,upperInnerDz:15,camberDeg:-.5,loadedRadius:320,springRate:55,actuation:"direct"},rear:{kx:1.15,ky:775/io,kz:320/co,lowerInnerDz:57,upperInnerDz:25,camberDeg:-1,loadedRadius:320,springRate:60,actuation:"direct"}}),305.4,309)}function D_(e,t,r,n,o,a){let s=km(),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:IS(n),springRate:o,rackTravel:a}}}function _S(){return Ia({name:"Cup car",front:D_(55,-25,-23,-3.5,150,55),rear:ug(ji(),{kx:1.15,ky:820/io,kz:320/co,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 NS(){return{...Ia(so({name:"Stock car",wheelbase:2794,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/_a,kz:355/Na,lowerInnerDz:20,upperInnerDz:5,camberDeg:-2.5,loadedRadius:355,springRate:175,actuation:"direct"},rear:{kx:1.2,ky:825/io,kz:355/co,lowerInnerDz:40,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:150,actuation:"direct"}}),343.8,345.3),chassis:{boxes:[],body:"nascar"}}}function OS(){let e=Ia(so({name:"Hill-climb prototype",wheelbase:2550,trackFront:1580,trackRear:1540,front:{kx:1.1,ky:790/_a,kz:300/Na,lowerInnerDz:10,upperInnerDz:5,camberDeg:-2.5,loadedRadius:300,springRate:90},rear:{kx:1.1,ky:770/io,kz:300/co,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 VS(){let e=Ia(so({name:"Race truck",wheelbase:3700,trackFront:2050,trackRear:1950,front:{kx:1.5,ky:1025/_a,kz:506/Na,lowerInnerDz:40,upperInnerDz:10,camberDeg:-.5,loadedRadius:506,springRate:200,actuation:"direct"},rear:{kx:1.5,ky:975/io,kz:506/co,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}),BS=(e,t)=>({...or[e],value:t});function $S(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 uo(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 Gr(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:BS("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]=BS(r,n);return t}var Oa={name:"Formula Student",m:300,A:1,cl:3,cw:1.3,frontMass:.47,frontAero:.45,rDyn:.222,drivenWheels:2,gearRatio:11.5,motor:$S(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}},dg={name:"Formula 1",m:798,A:1.5,cl:3,cw:.9,frontMass:.46,frontAero:.44,rDyn:.35,drivenWheels:2,gearRatio:4.9,motor:uo(735,2e3,12500,2500,2),motorCount:1,driveline:{rear:xt.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}},Mm={name:"GT car",m:1300,A:2,cl:1.4,cw:.42,frontMass:.5,frontAero:.42,rDyn:.33,drivenWheels:2,gearRatio:3.43,motor:uo(410,2e3,8e3,2e3,2),motorCount:1,driveline:{rear:xt.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}},Sm={name:"Sports car",m:1600,A:2.2,cl:-.1,cw:.3,frontMass:.55,frontAero:.5,rDyn:.32,drivenWheels:2,gearRatio:3.14,motor:uo(220,1500,6500,1400,2),motorCount:1,driveline:{rear:xt.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}},fg={name:"Cup car",m:1265,A:2.1,cl:.45,cw:.4,frontMass:.62,frontAero:.45,rDyn:.31,drivenWheels:2,gearRatio:3.5,motor:uo(250,2e3,7e3,1190,2),motorCount:1,motorPlacement:"front",driveline:{front:xt.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}},hg={name:"Stock car",m:1620,A:2.2,cl:.6,cw:.45,frontMass:.53,frontAero:.45,rDyn:.35,drivenWheels:2,gearRatio:4.1,motor:uo(500,2500,9e3,1680,2),motorCount:1,driveline:{rear:xt.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}},bg={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:uo(330,3e3,8500,1240,2),motorCount:1,driveline:{rear:xt.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}},gg={name:"Race truck",m:5300,A:6.2,cl:-.1,cw:.65,frontMass:.6,frontAero:.6,rDyn:.502,drivenWheels:2,gearRatio:3.55,motor:uo(880,100,3e3,88e3,2),motorCount:1,driveline:{rear:xt.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 pg(e,t,r){return Gr(r({...structuredClone(e),name:t}))}var Am={[Oa.name]:Gr(Oa),"Formula Student +15% downforce":pg(Oa,"Formula Student +15% downforce",e=>({...e,cl:e.cl*1.15,cw:e.cw*1.08})),"Formula Student -15 kg":pg(Oa,"Formula Student -15 kg",e=>({...e,m:e.m-15})),"Formula Student +15% power":pg(Oa,"Formula Student +15% power",e=>({...e,motor:$S(25*1.15,15e3,2e4),powerLimitKw:80*1.15})),[dg.name]:Gr(dg),[Mm.name]:Gr(Mm),[Sm.name]:Gr(Sm),[fg.name]:Gr(fg),[hg.name]:Gr(hg),[bg.name]:Gr(bg),[gg.name]:Gr(gg)},GS=Object.keys(Am),yg=GS.slice(0,4),xg=[Oa.name,dg.name,Mm.name,Sm.name,fg.name,hg.name,bg.name,gg.name];var ire={"Touring car":Mm.name,"Street car":Sm.name};var E_={bg:"#0e1116",panel:"#161b22",panel2:"#1c232d",border:"#2a323d",borderBright:"#39424e",sunken:"#11161c",ink:"#06090d"},I_={normal:"#d6dde6",dim:"#8b96a3",bright:"#e7ecf3",white:"#ffffff"},__={label:"#c8d2dc",grid:"#39424e",gridFaint:"#232b35",empty:"#1a2028"},N_={accent:"#4aa3ff",accentInk:"#04121f",warn:"#ffb454",good:"#4ec9a0",bad:"#ff6b6b",badSoft:"#ff8f8f"},O_=["#f0e442","#7b68ee","#f7a8b8","#d55e00","#d8b4fe","#b5e48c"],Fm={front:"#a6e22e",rear:"#00b4d8"},KS=["#5b4bd6","#4aa3ff","#4ec9a0","#f0e442"],Rg={power:"#ffb454",traction:"#f0845c",front:Fm.front,rear:Fm.rear,grip:"#73c9b3",braking:"#b48aff",crest:"#e88fd0",below:"rgba(214, 221, 230, 0.32)"},V_={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"},B_={x:"#ff6b6b",y:"#57c75a",z:"#4aa3ff"},$_={line:"#b4bfcb"},G_={compression:"#b48aff",tension:"#ff6b6b"},K_={fz:"#e7ecf3",fx:"#7ad7f0",fy:"#ff54c8"},H_={drivenLine:"#4d7cff",axis:"#eef3fa",slip:"#ffe81a",drive:Rg.power,brake:Rg.braking},z_={ground:"#101920",grid:"#1a2630",gridMajor:"#26343f",horizon:"#1d2833",bridge:"#6f7a86",coneLeft:"#2f63c9",coneRight:"#d9b51f",coneStart:"#ee7a2c"},Y_={chassis:"#435160",volume:"#303b47",tyre:"#435160",tyreLine:"#39424e",tyreFace:"#1c232d"},W_={centreLine:"#4aa3ff",corridorFill:"rgba(74,163,255,0.10)",boundary:"#3d4956",racingLine:"#ffb454",start:"#e7ecf3",finish:"#ff6b6b",direction:"#8b96a3"},j_={SURFACE:E_,TEXT:I_,CHART:__,ROLE:N_,SERIES:O_,AXLE:Fm,LAP_SPEED:KS,LIMITER:Rg,RIG:V_,AXIS:B_,CONSTRUCTION:$_,FORCE:G_,TYRE_FORCE:K_,REPLAY:H_,SCENERY:z_,BODY:Y_,TRACK:W_},HS=e=>Object.fromEntries(Object.entries(e).map(([t,r])=>[t,Array.isArray(r)?Object.freeze([...r]):Object.freeze({...r})])),wm=HS(j_),vt=wm.SERIES,zS=(()=>{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 HS({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 YS=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},lre=(()=>{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=wm[r],o=zS[r];for(let a of Object.keys(n)){let s=YS(n[a]);s&&!e.has(s)&&e.set(s,o[a])}}return e})();var WS=(e,t)=>new Set(t.flatMap(r=>{let n=e[r];return Array.isArray(n)?[...n]:Object.values(n)}).map(YS).filter(r=>r!==null)),ure=WS(zS,["SERIES","AXLE","LAP_SPEED","LIMITER","ROLE","RIG","FORCE","TYRE_FORCE","REPLAY","AXIS","TRACK","CONSTRUCTION"]),mre=WS(wm,Object.keys(wm).filter(e=>e!=="SURFACE"));function vg(){return{kind:"simple",name:"Simple motor",rpm:[0,16e3,2e4],torque:[21,21,14],efficiency:.95}}function kg(){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 Mg(){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 Sg(){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 Ag(){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 jS(){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 US(){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 XS(){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 qS(){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 QS(){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 ZS(){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 JS(e){return ro(U_(e))}function U_(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 qi(e,t){return{...t,fingerprint:JS(e)}}var eA="CC-BY-4.0",X_={title:"PaceDynamics built-in library",url:"https://pacedyn.dev/",licence:eA},tA={fidelity:"generic",licence:eA,sources:[X_]};var Cm=e=>qi(e,tA);var rA=["raw.githubusercontent.com"],nA=["tum-csv"],Q_=/^[0-9a-f]{64}$/;function Zi(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"||!Q_.test(r)||!nA.includes(n))return!1;try{let o=new URL(t);return o.protocol==="https:"&&rA.includes(o.hostname)&&!o.username&&!o.password&&!o.port}catch{return!1}}var Tm=e=>new URL(e.url).hostname;async function oA(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 Z_(e){let t=new URL(e).pathname.split("/").pop()??"";return decodeURIComponent(t).replace(/\.[^.]*$/,"")||"Linked track"}function J_(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 eN={"tum-csv":J_};function aA(e,t){return eN[t.format](e,Z_(t.url))}async function Fg(e,t,r){let n=await oA(e);if(n!==t.sha256)throw new Error(`${Tm(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=aA(new TextDecoder().decode(e),t),a=await Pm(o);if(a!==r)throw new Error(`Linked track ${r} does not convert to its name (it is ${a}).`);return o}var wg=20,rN=new RegExp(`^[0-9a-f]{${wg}}$`),Ji=e=>typeof e=="string"&&rN.test(e);async function Pm(e){let t=new TextEncoder().encode(bn(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,wg)}var Cg=e=>`tracks/${e}.json`;var nN=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function Tg(e){return{model:{name:e.name,source:e.source},...e.provenance?{provenance:e.provenance}:{}}}async function Pg(e,t){if(!nN(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 Pm(e);if(r!==t)throw new Error(`Catalogue track ${t} does not match its name (it is ${r}).`);return e}var mo=(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}),gn=[mo("suspensions","suspensionId","suspension"),mo("tires","tireModelId","tyre",[{key:"tiresRear",ref:"tireModelIdRear",label:"rear tyre"}]),mo("motors","motorModelId","motor"),mo("aeros","aeroModelId","aero map"),mo("batteries","batteryModelId","battery"),mo("brakes","brakeModelId","brakes"),mo("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 Lm(e){let t={...e};for(let r of gn)for(let n of r.refs)delete t[n];return t}var Dm=vt,ec=Dm,Lg=Dm,yn=[...vt.slice(3),...vt.slice(0,3)],Ig=[...vt.slice(1),vt[0]],Dg=[...vt.slice(2),...vt.slice(0,2)],Eg=[...vt.slice(4),...vt.slice(0,4)],_g=[...vt.slice(5),...vt.slice(0,5)],tc=[...vt.slice(2),...vt.slice(0,2)];function Ng(){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 Og(e,t,r){let n=Am[e];if(!n)throw new Error(`no preset vehicle named "${e}"`);return{id:t,params:{...ri(structuredClone(n)),energy:{...wr},suspensionId:"sus1"},visible:!0,color:ec[r%ec.length]}}function sN(){return yg.map((e,t)=>Og(e,`v${t+1}`,t))}function iN(){return[Es(),Rf(),vf(),kf(),Mf(),Sf(),Af(),Ff(),wf(),Cf()].map((t,r)=>({id:`t${r+1}`,color:Lg[r%Lg.length],model:t}))}function cN(){return[td(),rd(),nd(),od(),ad(),sd(),id(),cd()].map((t,r)=>({id:`a${r+1}`,color:Dg[r%Dg.length],model:t}))}function lN(){return[$p(),Gp(),Kp()].map((t,r)=>({id:`b${r+1}`,color:Eg[r%Eg.length],model:t}))}function uN(){return[{id:"brk1",color:_g[0],model:structuredClone(jf)}]}function mN(){return[{id:"dmp1",color:tc[0],model:structuredClone(mu)}]}function pN(){return[vg(),kg()].map((t,r)=>({id:`m${r+1}`,color:yn[r%yn.length],model:t}))}function Vg(e){let t=r=>({...r,provenance:Cm(r.model)});return{...e,suspensions:e.suspensions.map(t),vehicles:e.vehicles.map(r=>({...r,provenance:Cm(Lm(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 rc(e="Untitled project"){let t=new Date().toISOString(),r=sN();return Vg({schemaVersion:gm,meta:{id:Ng(),name:e,domain:"racecar",rulesetId:no,createdAt:t,updatedAt:t},suspensions:[{id:"sus1",color:Ig[0],model:lo()}],activeSuspensionId:"sus1",vehicles:r,activeVehicleId:r[0]?.id??null,tires:iN(),motors:pN(),aeros:cN(),batteries:lN(),brakes:uN(),dampers:mN(),tracks:[],activeTrackId:null,mathChannels:[],rulesets:[],studies:[],activeStudyId:null,loadCases:[],reportLayouts:[],tyreSheets:[],kinSheets:[],plans:[],results:[],settings:{numerics:{...yi},ggvMode:"twoTrack",quasiTransient:!1,motorThermal:!1,brakeFade:!1,airTempC:At,air:structuredClone(xm),diffYaw:!1,lapCounts:{},pathPlanId:null,useRacingLine:!0,standingStart:!1}})}var dN=["front","rear"],Bg=9.81,fN=Math.PI/180;var Kr="*",$g=40,sA=.8;function Gg(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 iA(e,t,r){let n=t.rows.map(c=>c.v),o=c=>mt(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/Bg*100)/100+0,axG:Math.round(u/Bg*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($g/3.6,o($g/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(sA*s,o(sA*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 Kg(e,t,r){let n=!1,o=e.map(a=>{if(!a.follows)return a;let s=iA(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 Hg(e,t){let r=e.speedKmh/3.6,n=e.ayG*Bg;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)/fN}var cA=e=>e.ayG<0?"L":"R";function zg(e,t=dN){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 Yg=(e,t)=>e.travelMin===t.travelMin&&e.travelMax===t.travelMax&&e.rollMaxDeg===t.rollMaxDeg&&e.rollAtLimitDeg===t.rollAtLimitDeg;var Hr=Math.PI/180,hN=9.81,nc=.1,Wg=20,lA=6,dA=50;function uA(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 jg(e,t,r,n,o){let a=o*Hr;if(t==="side")return uA(i=>r*e.Fy(r*i*Hr,n,a),1,45);let s=t==="drive"?1:-1;return uA(i=>s*e.Fx(s*i,n,a),.02,.6)}function Im(e){let t=e?Ll(e)?.gamma:void 0,r=[t?.min,t?.max].filter(o=>o!==void 0&&Number.isFinite(o));if(!r.length)return{lo:-lA,hi:lA,stated:!1};let n=Math.max(...r.map(Math.abs))/Hr;return{lo:-n,hi:n,stated:!0}}function bN(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 mA=250,pA=new WeakMap;function gN(e,t,r,n,o,a,s){let i=pA.get(e);i||pA.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*mA);h=bN(g=>jg(r,n,o,b,g).force,s.lo,s.hi),l.set(d,h)}return h},m=Math.max(0,a)/mA,f=Math.floor(m),p=m-f;return p<1e-9?u(f):u(f)*(1-p)+u(f+1)*p}function Va(e,t){return t==="front"?e.tireModel:e.tireModelRear??e.tireModel}var yN=new WeakMap,xN=new WeakMap,RN=new WeakMap,Ug=(e,t,r)=>{let n=e.get(t);return n===void 0&&e.set(t,n=r()),n};function Xg(e,t){let r=Va(e,t);return r?Ug(yN,r,()=>Fs(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 qg(e,t){let r=Va(e,t);return r?Ug(RN,r,()=>Dl(r).none)?"This tyre file has no drive or brake grip.":Ug(xN,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*Hr);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 po(e,t){return e==="side"||e==="ackermann"?Math.abs(t.ayG)>=nc?e==="ackermann"&&!(fA(t)<=Wg)?`is a corner wider than ${Wg} m`:null:"does not corner":(e==="drive"?t.axG:-t.axG)>=nc?null:e==="drive"?"does not drive":"does not brake"}var vN=e=>e.axG>=nc?"drive":e.axG<=-nc?"brake":null;function fA(e){let t=e.speedKmh/3.6,r=Math.abs(e.ayG)*hN;return r>1e-9?t*t/r:1/0}var Em=(e,t)=>`${e==="front"?"F":"R"}${t}`,kN=e=>e==="L"?"R":"L",MN=(e,t,r)=>Math.min(r,Math.max(t,e));function Qg({ev:e,params:t,input:r,state:n,pose:o}){let a=`${Q(t,"grip_scale")}|${Q(t,"stiffness_scale")}`,s=fA(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=ge(e,k),C=Va(t,k),T=Math.max(0,o.loads[v]),S=o.camber[v],A=MN(S,F.lo,F.hi),P=jg(w,x,M,T,A),L=T<dA,D=C&&!L?gN(C,a,w,x,M,T,F):A,E=L?P.force:jg(w,x,M,T,D).force,V=.05;return{corner:v,Fz:T,lifted:L,camber:S,read:A,outside:A!==S,wants:D,atEdge:!L&&(D-F.lo<V||F.hi-D<V),peak:P.force,slip:P.at,best:E}},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(!po("side",n)){let x=Im(Va(t,k));v=[m(k,Em(k,o.outer),"side",1,x),m(k,Em(k,kN(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*Hr;return Math.atan2(M+s*Math.sin(w),s*Math.cos(w)-F)/Hr},R=k=>(n.ayG<0?-1:1)*o.steer[k];return{side(k){if(h.has(k))return h.get(k)??null;let v=Xg(t,k)?null:d(k),x=v?f("side",v,Im(Va(t,k))):null;return h.set(k,x),x},long(k){if(b.has(k))return b.get(k)??null;let v=vN(n),x=null;if(v&&!qg(t,k)){let M=Im(Va(t,k));x=f(v,[m(k,Em(k,"L"),v,1,M),m(k,Em(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=ge(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)}],S=E=>T.reduce((V,N)=>{let z=N.steer-y(k,N.inner,E);return V+N.dt*F.Fy(N.dt*z*Hr,N.g.Fz,N.g.read*Hr)},0),A=T.map(E=>E.steer-E.g.slip-y(k,E.inner,0)),P=Math.min(...A)-2,L=Math.max(...A)+2,D=SN(S,P,L,.25);M=Math.max(0,1-D/(w.peak+C.peak))}return g.set(k,M),M},ackermann(){if(po("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)))/Hr;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 SN(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 AN=9.81,hA=Math.PI/180,oc={speed:20,ayG:1.2};function Zg(e,t={}){let r=t.operating??oc,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=ir(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 C={cornerStiffness:T=>w.corneringStiffness(T),ayG:x.ayG,speed:x.speed,fyAxle:(T,S)=>2*w.Fy(T,S/2),tire:w};return i.set(M,C),C},b=()=>{if(s!==void 0)return s;let v=p(),x=d();if(!v||!x)return s=null;try{s=Gn(x,v.massTotal*AN*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(),C=d(),T=null;if(w&&C)try{T=Hh(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 F=null,w=p();try{let C=w?.kinFront,T=w?.kinRear;if(w&&C&&T){let S=Hg(v,w.wheelbase),A=v.speedKmh/3.6,P=nn(w,C,T,A)(v.ayG,v.axG,0,S),L={FL:P.FL.travel,FR:P.FR.travel},D=Hn(w,S*hA,L),E=S?D.camber:null,V={},N={};for(let I of["FL","FR","RL","RR"]){let _=I[1]==="R"?P[I].camberRoad:0-P[I].camberRoad;V[I]=_+(E?.[I]??0),N[I]=D.steer[I]/hA+(I[1]==="R"?1:-1)*P[I].bumpToe}let z=we(w,v.ayG,v.axG,A,0,S,L,P.steeringJacking);F={corners:P,rollDeg:P.FL.camberRoad-P.FL.camber,steerDeg:S,camber:V,outer:cA(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(),C=d(),T=F&&w&&C?Qg({ev:C,params:e.params,input:w,state:v,pose:F}):null;return R.set(x,T),T},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?Rb(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 C=p(),T=h(x),S=null;if(C&&T)try{S=Si(C,T,v,b()??void 0)}catch{S=null}return u.set(F,S),S}}}var bA=["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 Jg(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 Nm(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 bA){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 Om(e,t,r){if(!t.length)return e;let n=ac(e),o=n.length,a={widthLeft:_m(e.widthLeft,r.widthLeft),widthRight:_m(e.widthRight,r.widthRight),bank:_m(e.bank,r.bank),mu:_m(e.mu,r.mu)},s={};for(let c of bA){let l=e[c];Array.isArray(l)&&l.length===o&&(s[c]=l)}let i=Nm(t,n,a,s);return{...e,...i}}function _m(e,t){return typeof e=="number"?e:t}var xA=1,gA=4,Bm=Math.PI/180,e0=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)*Bm:e.length}function Vm(e,t){return e.kind==="straight"?0:e.kind==="arc"?e0(e.radius):t}function yA(e){return e.kind==="straight"?0:e.kind==="arc"?e0(e.radius):e0(e.endRadius)}var sc=(e,t,r,n,o)=>e+t*o+(n>0?(r-t)*o*o/(2*n):0);function ic(e,t={}){let r=Math.max(.05,t.spacing??xA),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((S,A)=>S+t0(A),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*Bm,b=e.length?Vm(e[0],0):0,g=0,y=f,R=(S,A,P)=>{s.push(S),i.push(A),c.push(P)};R(p,d,0);let k=(S,A,P,L,D)=>{let E=D-L;if(E<=0)return;if(Math.abs(A-S)<1e-12){let N=sc(h,S,S,P,L);if(Math.abs(S)<1e-12)p+=E*Math.cos(N),d+=E*Math.sin(N);else{let z=N+S*E;p+=(Math.sin(z)-Math.sin(N))/S,d+=-(Math.cos(z)-Math.cos(N))/S}return}let V=E/gA;for(let N=0;N<gA;N++){let z=L+N*V,I=sc(h,S,A,P,z),_=sc(h,S,A,P,z+V/2),B=sc(h,S,A,P,z+V);p+=V/6*(Math.cos(I)+4*Math.cos(_)+Math.cos(B)),d+=V/6*(Math.sin(I)+4*Math.sin(_)+Math.sin(B))}};for(let S of e){let A=t0(S),P=Vm(S,b),L=yA(S);if(l.push({from:g,to:g+A,...S.widthLeft!==void 0?{widthLeft:S.widthLeft}:{},...S.widthRight!==void 0?{widthRight:S.widthRight}:{},...S.bank!==void 0?{bank:S.bank}:{},...S.mu!==void 0?{mu:S.mu}:{},...S.ramp!==void 0?{ramp:S.ramp}:{}}),A<=0){b=L;continue}let D=0;for(;y<=g+A+1e-9;){let E=Math.min(A,y-g);k(P,L,A,D,E),D=E,R(p,d,g+E),y+=f}k(P,L,A,D,A),h=sc(h,P,L,A,A),b=L,g+=A}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?Vm(e[0],b):0,F={gap:v,headingError:FN((h-o.heading*Bm)/Bm),curvatureError:b-M},w=[];for(let S=0;S<e.length;S++){let A=yA(e[S]),P=S+1<e.length?e[S+1]:n?e[0]:null;if(!P)continue;let L=Vm(P,A);w.push({index:S,before:A,after:L,jump:Math.abs(L-A)})}let C=Nm(l,c,a);return{asset:{name:t.name??"Track",x:s,y:i,fit:"interpolate",...n?{}:{closed:!1},...C},sections:l,joints:w,closure:F,length:x}}function FN(e){let t=e%360;return t>180&&(t-=360),t<-180&&(t+=360),t}var wN={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 ${vA(e).toFixed(0)} m`}}}function vA(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 kA=e=>e.kind==="skidpad"||e.kind==="curves"&&e.closed===!0,MA=e=>e.kind==="acceleration",SA=1.5,AA=3;function CN(e,t){let r=e.offsetM,n=e.pitchM,o=Math.max(1,e.gates)*n,a=Math.max(0,e.leadInM),s=SA*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*(AA*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 TN(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 r0(e,t={}){let r={...wN,...t},n=MA(e),o=TN(e);if(!o){let u=CN(e,r);return{asset:u,peakCurvature:RA(u),worstJoint:0,standingStart:n}}let a=kA(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*(AA*Math.PI/180))):r.spacingM,c=ic(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:RA(c.asset),worstJoint:l.reduce((u,m)=>Math.max(u,m.jump),0),standingStart:n}}function RA(e){try{return Math.max(...it(e).curvature.map(Math.abs))}catch{return NaN}}var Gm={courses:[{id:"c1",course:{kind:"manoeuvre",spec:{kind:"skidpad",radiusM:8.375}}}],ggvMode:"twoTrack"};function n0(e){return e.course.kind==="project"?"the project\u2019s track":e.course.kind==="track"?e.course.name:cc(e.course.spec)}var FA=new WeakMap,$m=new Map;function wA(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=$m.get(n);if(o)return{...o,numerics:r};let a=r0(e.spec),s={asset:a.asset,standingStart:a.standingStart};return $m.size>64&&$m.clear(),$m.set(n,s),{...s,numerics:r}}function o0(e,t,r={}){let n=r.lap??Gm,o=r.simParams,a=r.numerics??{},s=n.courses.length?n.courses:Gm.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=wA(v.course,r,a),F=null;if(M)try{let w=JSON.stringify(M.numerics),C=FA.get(M.asset);C||(C=new Map,FA.set(M.asset,C));let T=C.get(w);T||(T=it(M.asset,M.numerics),C.set(w,T)),F={id:v.id,track:T,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=Ft(k),c=cr(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?Jn(l,M,[v.track],v.numerics,n.ggvMode,u):void 0,C=l?fn(l,M.rows):void 0;F=Rt(M,v.track,v.numerics,{standingStart:v.standingStart,...w?{load:w}:{},...C?{shifts:C}:{}})}catch{F=null}return f.set(v.id,F),F};return{lapSettings:n,get lapAvailable(){return!!o&&s.some(k=>!!wA(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(),C=null;if(M&&F&&w)try{let T=h();C=ju(F,w,{v:M.v,ax:M.ax,ay:M.ay,ds:v.track.ds,axDrag:Ta(g()?.rows,M.v),...M.axScrub?{axScrub:M.axScrub}:{},axGrade:dn(v.track.gradient,M.v.length),bank:v.track.bank,...M.loadFactor?{loadFactor:M.loadFactor}:{}},T?{driven:ch(T)}:{})}catch{C=null}return p.set(v.id,C),C}}}var CA=180/Math.PI,a0={rise:0,sinPitch:0,sinRoll:0};function TA(e){let t=e.kc;return t?PA(e.vehicle,r=>t.ground0[r]):a0}function PA(e,t){let r=e.config,n=Vo(r),o=0,a=0,s=0,i=0,c=0,l=0,u=0,m=0,f=0;for(let g of Oo){let y=Ze(g,r),R=y.axleX-n,k=y.sideSign*Qr(e,y.isFront)/2,v=t(g);if(!Number.isFinite(v))return a0;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 lc(e,t){let r=e.kc,n=PA(e.vehicle,o=>(r?r.ground0[o]:0)+t[o]);return q([-n.sinPitch,n.sinRoll,1])}function s0(e,t,r,n){let o=q(Zr(e,Ze(t,r)));return-Math.asin(Math.max(-1,Math.min(1,X(o,n))))*CA}function Km(e,t,r,n,o){let a=q(Zr(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=os({uprightUpper:c(u.uprightUpper),uprightLower:c(u.uprightLower),wheelCenter:c(u.wheelCenter),spinAxis:m,tieOuter:c(u.tieOuter),loadedRadius:o.loadedRadius,patchShift:o.patchShift&&PN(o.patchShift,e.metrics.toe/CA,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 PN(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 LA(e,t){let r=TA(t);if(r===a0)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 i0(e,t,r){let n=LA({heave:0,pitch:0,roll:0,steer:0},r);return e-kd(n,[t,0,0],Vo(r.vehicle.config))}var LN=180/Math.PI;function c0(e,t){return!e.valid||!e.ic?!1:Math.hypot(e.ic[0]-e.cp[0],e.ic[1]-e.cp[1])<=t}function Hm(e,t,r){let n=Ze(t,e.vehicle.config),o=gt(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=A=>{let P=a.velocity(A);return[P[0],P[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=lc(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=A=>{let P=A[0]*g[0]+A[1]*g[1];return Math.abs(P)>1e-9?-(A[0]*y[0]+A[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,F=x?(A=>{let P=[s[0]-A[0],s[2]-A[1]],L=[i[0]-A[0],i[2]-A[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:d,road:y,swingArmAngleDeg:0,tanTheta:0,tanThetaHub:0,valid:!1,sinAngle:F};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,S=R(m);return{ic:x,line:T,cp:p,wc:d,road:y,swingArmAngleDeg:Math.atan(S)*LN,tanTheta:S,tanThetaHub:R(f),valid:!0,sinAngle:F}}function DA(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 EN=180/Math.PI,IN=Math.PI/180,l0=.5,zm=2,u0=.25,_N={heave:0,pitch:0,roll:0,steer:0},NN={FL:"FR",FR:"FL",RL:"RR",RR:"RL"},Ym=e=>e.ok?e.state:{...e.nearest,converged:!1};function m0(e,t,r){return t.state?t.solved===!1?{...t.state,converged:!1}:t.state:Ym(ye(e,t.travel,t.steer,void 0,r))}var EA=new WeakMap;function IA(e,t){let r=e.ctx[t],n=$e(e.vehicle,t).config.loadedRadius,o=Zt(n,e.kc,t),a=EA.get(r);a||(a=new Map,EA.set(r,a));let s=a.get(o);if(!s){let i=Jr(t,e.vehicle.config,_N,e.vehicle);s=Ym(ye(r,i.travel,i.steer,void 0,o===n?void 0:{loadedRadius:o})),a.set(o,s)}return s}var pr=(e,t)=>!e||!e.lo.converged||!e.hi.converged?NaN:(t(e.hi)-t(e.lo))/(2*e.step),_A=(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 OA(e,t,r,n,o){let a=e.vehicle.config,s=No(r),i=$e(e.vehicle,r),c=Ze(r,a),l=e.ctx[r],u=gt(e,t),m=u[r],f={travel:m.travel,steer:m.steer},p=m.rigid?void 0:{loadedRadius:m.loadedRadius},d=m0(l,m,p),h=IA(e,r),b={lo:Ym(ye(l,f.travel-l0,f.steer,void 0,p)),hi:Ym(ye(l,f.travel+l0,f.steer,void 0,p)),step:l0},g=c.isFront?{lo:Ie(l,d.beta,f.steer-zm,void 0,p),hi:Ie(l,d.beta,f.steer+zm,void 0,p),step:zm}:null,y=Y=>{let j=gt(e,{...t,roll:t.roll+Y*IN})[r];return m0(l,j,j.rigid?void 0:{loadedRadius:j.loadedRadius})},R={lo:y(-u0),hi:y(u0),step:u0},k=VN(e,t,r,c.isFront,u,g),v=Nt(d.points.contactPatch,c),x=Nt(h.points.contactPatch,c),M=Math.abs(v[1])-Math.abs(x[1]),F=NN[r],w=u[F],C=m0(e.ctx[F],w,w.rigid?void 0:{loadedRadius:w.loadedRadius}),T=C.converged?M+Math.abs(C.points.contactPatch[1])-Math.abs(IA(e,F).points.contactPatch[1]):NaN,S=o??ar(e,t,s),A=gu(S,bt(i)),P=A?null:nk(S),L=c.sideSign>0?S.icRight:S.icLeft,D=L?Math.hypot(L[0]-v[1],L[1]-v[2]):1/0,E=Hm(e,r,t),V=E.ic?Math.hypot(E.ic[0]-E.cp[0],E.ic[1]-E.cp[1]):1/0,N=DA(E,s,a.wheelbase,n),z=-pr(b,Y=>Y.points.damperLength),I=i.config.springRate,_=pr(R,Y=>Y.metrics.camber),B=lc(e,{FL:u.FL.ground,FR:u.FR.ground,RL:u.RL.ground,RR:u.RR.ground}),O=e.kc?.loadCase,G=Y=>O?Km(Y,r,a,B,{loadedRadius:m.loadedRadius,patchShift:O.patchShift[r]}):Y.metrics,K=G(d);return{id:r,converged:d.converged,travel:d.travel,camber:d.metrics.camber,camberRoad:s0(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:pr(b,Y=>Y.metrics.camber),bumpSteer:pr(b,Y=>Y.metrics.toe),trackScrubRate:pr(b,Y=>Math.abs(Nt(Y.points.contactPatch,c)[1])),casterGain:pr(b,Y=>G(Y).caster),kpiGain:pr(b,Y=>G(Y).kpi),scrubGain:pr(b,Y=>G(Y).scrubRadius),trailGain:pr(b,Y=>G(Y).mechanicalTrail),...c.isFront?{camberPerSteer:_A(g,Y=>Y.metrics.camber,Y=>Y.metrics.toe),steerJacking:-_A(g,Y=>Y.points.contactPatch[2],Y=>Y.metrics.toe),...k!==void 0?{steerLoad:k}:{}}:{},rollCamber:_,camberRecovery:-100*c.sideSign*_,rollSteer:c.sideSign*pr(R,Y=>Y.metrics.toe),halfTrackChange:M,trackChange:T,longitudinal:v[0]-x[0],rollCentreHeight:P?P.heightAboveGround:S.heightAboveGround,rollCentreHeightChassis:(P?P.height:S.height)-i0(0,c.axleX,e),rollCentreLateral:S.lateralAlongGround,rollCentreValid:S.valid,rollCentreUsable:A,rollCentreHeightUsable:A||P!==null,rollCentreSinAngle:S.sinAngle,fvsaLength:D,svsaLength:V,swingArmAngle:E.swingArmAngleDeg,svsaUsable:c0(E,a.wheelbase),svsaSinAngle:E.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:I,motionRatio:z,wheelRate:I*z*z,damperLength:d.points.damperLength,damperTravel:h.points.damperLength-d.points.damperLength,...ON(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)*EN,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 ON(e,t,r,n){if(e.config.actuation==="decoupled")return{};let o=n?{droop:n.droopStated?n.droop:null,bump:n.bump}:$o(t,e.config.coilover),a=t-r;return{...o.droop!==null?{damperToExtended:a-o.droop}:{},...o.bump!==null?{damperToClosed:o.bump-a}:{}}}function VN(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)*zm,M=g.state?{q:[...g.state.pose.t,...g.state.pose.omega],phi:g.state.points.rockerAngle}:void 0,F=ht(ye(y,g.travel,g.steer-x,M,R)),w=ht(ye(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]=gr(i.curve[b],g.travel,w.points.damperLength)-gr(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=fs(p,h,[m.hi[0],m.hi[1]]),g=fs(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 uc(e,t,r,n,o){return OA(e,t,r==="front"?"FL":"RL",n,o)}function p0(e,t,r,n){let o=uc(e,t,"front",r,n?.front),a=uc(e,t,"rear",r,n?.rear);return{front:o,rear:a,wheelbaseChange:o.longitudinal-a.longitudinal}}var Wm=Math.PI/180,mc={travelSteps:9,heaveSteps:5,rollSteps:4,rackSteps:6},jm={travelMin:-25,travelMax:25,rollMaxDeg:3,rollAtLimitDeg:2.5};function BN(e){let t=e.params;return{cgHeight:t.cg_height?dt({...t,surveyedRadiusFront:e.vehicle.front.config.loadedRadius,surveyedRadiusRear:e.vehicle.rear.config.loadedRadius}).cgHeight:300,...ph(t),drive:lh(t)}}function VA(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 d0(e,t=mc,r=jm,n){let o=null,a=(S,A)=>(o||(o={violation:S,reason:A}),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=Ct(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=Ct(s)},m=S=>S==="front"?"FL":"RL",f=S=>{let A=u();if(!A.kc)return;let P=i(S).config.loadedRadius,L=Zt(P,A.kc,m(S));return L===P?void 0:{loadedRadius:L}},p=(S,A)=>-hs(u(),m(S),A),d=new Map,h=new Map,b=new Map,g=new Map,y=new Map,R=new Map,k=new Map,v=null,x=()=>{if(v)return v;u();let S=BN(e);return v=l!==null&&Number.isFinite(l)?{...S,cgHeight:l}:S},M,F,w=()=>{if(F!==void 0)return F;let S=fl(u().ctx.FL,Ot(s.front.config));return F=S?hl(S):null,F},C=(S,A,P)=>{if(S.has(A))return S.get(A)??null;let L=P();return S.set(A,L),L};return{car:e,density:t,envelope:r,get failure(){return o},axisLength:(S,A)=>{let P=i(S),L=P.hardpoints;return A==="uca"&&P.config.layout==="mcpherson"?NaN:A==="uca"?ve(L.ucaFront,L.ucaRear):ve(L.lcaFront,L.lcaRear)},linkLength:S=>{let A=i(S).hardpoints;return ve(A.tieInner,A.tieOuter)},compliance:S=>C(h,S,()=>ff(i(S))??null),sweep:S=>C(d,S,()=>{let A;try{A=Ge(i(S),{travelMin:r.travelMin,travelMax:r.travelMax,steps:t.travelSteps})}catch{return a(500,`the ${S} travel sweep threw`)}if(!A.covered){let L=A.samples.map(V=>V.travel),D=Math.max(...L)-Math.min(...L),E=r.travelMax-r.travelMin;return a(Math.max(0,E-D),`the ${S} linkage reaches only ${D.toFixed(0)} mm of the ${E.toFixed(0)} mm travel range`)}if(A.fold)return a(200,`the ${S} travel(beta) folds \u2014 the suspension goes over centre in range`);let P=A.samples.filter(L=>!L.converged).length;if(P>0)return a(100+10*P,`${P} of ${A.samples.length} ${S} travel solves did not converge`);if(S==="front"&&i("front").config.steerMode==="rack"){let L=w();if(L)return a(L.violation,L.reason)}return A}),rcHeave:S=>C(b,S,()=>{let A=[],P=[],L=Math.max(2,t.heaveSteps);try{for(let E=0;E<L;E++){let V=r.travelMin+(r.travelMax-r.travelMin)*E/(L-1);A.push(V),P.push(ar(u(),{heave:p(S,V),pitch:0,roll:0,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in heave`)}let D=VA(P,E=>Math.abs(A[E]-A[E-1]));return D>0?a(300,`the ${S} roll-centre construction lands on another branch at ${A[D].toFixed(0)} mm of travel`):{at:A,rc:P}}),rcRoll:S=>C(g,S,()=>{let A=[],P=[],L=Math.max(2,t.rollSteps);try{for(let E=0;E<L;E++){let V=r.rollMaxDeg*E/(L-1);A.push(V),P.push(ar(u(),{heave:0,pitch:0,roll:V*Wm,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in roll`)}let D=VA(P,E=>Math.abs(P[E].cpLeft?.[0]??0)*Math.abs(A[E]-A[E-1])*Wm);return D>0?a(300,`the ${S} roll-centre construction lands on another branch at ${A[D].toFixed(1)}\xB0 of roll`):{at:A,rc:P}}),steer:()=>{if(M!==void 0)return M;try{M=Ud(u(),{steerMax:Ot(s.front.config),steps:t.rackSteps})}catch{M=a(500,"the steering sweep threw")}let S=M?.filter(A=>!A.converged).length??0;if(M&&S>0){let A=w();M=A?a(A.violation,A.reason):a(100+10*S,`${S} of ${M.length} steering solves did not converge`)}return M??null},solveAt:(S,A,P=0)=>C(y,`${S}:${A}:${P}`,()=>{try{let L=ye(u().ctx[m(S)],A,P,void 0,f(S));return L.ok?L.state:L.why==="unconverged"?a(100,`the ${S} corner did not solve at ${A.toFixed(0)} mm of travel`):a(100+Math.abs(L.travelMiss),`the ${S} corner reaches only ${(A+L.travelMiss).toFixed(0)} of ${A.toFixed(0)} mm of travel`)}catch{return a(150,`the ${S} corner solve threw at ${A.toFixed(0)} mm of travel`)}}),readout:S=>C(R,`${S.heave}:${S.pitch}:${S.roll}:${S.steer}`,()=>{try{return p0(u(),S,x())}catch{return a(500,"the derived readout threw")}}),readoutAtTravel:(S,A)=>C(k,`${S}:${A}`,()=>{try{return uc(u(),{heave:p(S,A),pitch:0,roll:0,steer:0},S,x())}catch{return a(500,`the ${S} readout threw at ${A.toFixed(0)} mm of travel`)}}),travelAtRoll:(S,A)=>{let P=i(S).hardpoints.wheelCenter[1]*Math.sin(A*Wm),L=u();if(!L.kc)return P;try{let D=gt(L,{heave:0,pitch:0,roll:A*Wm,steer:0}),E=S==="front"?Math.max(D.FL.travel,D.FR.travel):Math.max(D.RL.travel,D.RR.travel);return Number.isFinite(E)?E:P}catch{return a(500,`the ${S} axle could not be rolled on its tyre`),P}},onTyre:()=>!!u().kc}}var $N=rg();function f0(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=cm(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?zi([c],a.track,a.numerics,Bi(s),a.settings,$N)[0]:Pi(c,s,{numerics:a.numerics,standingStart:l,lapCounts:u});o={};for(let f of s.metrics)Ic(f)&&(o[f.key]=f.value(m,void 0))}}catch{o=null}return r.set(n,o),o}}}var Um=Math.PI/180,Xm=1e-6;function $A(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 $A(t.travel,t.camber);let r=q(e.config.spinAxis);return-Math.asin(Math.max(-1,Math.min(1,r[2])))/Um}function dc(e){let t=e.measured;if(t)return $A(t.travel,t.toe);let[r,n]=e.config.spinAxis;return Math.atan2(r,n)/Um}function h0(e,t){let r=Math.abs(t.camber)>=Xm,n=Math.abs(t.toe)>=Xm;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)*Um,l=(dc(e)+t.toe)*Um,[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 qm(e){let t=e&&typeof e=="object"?e.value:void 0;return typeof t=="number"&&Number.isFinite(t)?t:void 0}function GN(e,t){let r=t;return{front:qm(r.camber_front_deg)??pc(e.front),rear:qm(r.camber_rear_deg)??pc(e.rear)}}function KN(e,t){let r=t;return{front:qm(r.toe_front_deg)??dc(e.front),rear:qm(r.toe_rear_deg)??dc(e.rear)}}function HN(e){return{camber:{front:pc(e.front),rear:pc(e.rear)},toe:{front:dc(e.front),rear:dc(e.rear)}}}var BA=new WeakMap;function zN(e,t){let r=HN(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)<Xm&&Math.abs(u.toe)<Xm;if(o(n.front)&&o(n.rear))return e;let a=`${t.camber.front}|${t.camber.rear}|${t.toe.front}|${t.toe.rear}`,s=BA.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&&h0(m,n[No(u)])])):void 0,l={...e,front:h0(e.front,n.front),rear:h0(e.rear,n.rear),...c?{corners:c}:{}};return s||BA.set(e,s=new Map),s.size>=16&&s.clear(),s.set(a,l),l}function Ba(e,t){return t?zN(e,{camber:GN(e,t),toe:KN(e,t)}):e}var YN=9.81;function $a(e){let t=Pn(e),r=Math.max(0,e.unsprungPerCorner)*YN,n=a=>{let s=a==="FL"||a==="FR",i=s?"front":"rear",c=Xe(e,i),l=c>0?c:1/0,u=Yp(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:$t(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 GA=new WeakMap;function WN(e){let t=Ba(e.vehicle,e.params);if(t===e.vehicle)return e;let r=GA.get(e);return(!r||r.vehicle!==t)&&GA.set(e,r={...e,vehicle:t}),r}function xn(e,t={}){let r=WN(e),n=Zg(r,t),o=t.assemble?()=>{let l=n.dynInput();if(!l)throw new Error("the car did not assemble");return{kc:$a(l),cgHeight:l.cgHeight}}:void 0,a=d0(r,t.density,t.envelope,o),s=o0(r,n,t),i=f0(r,t),c=t.states??[];return{...a,...n,...s,...i,get failure(){return a.failure},values:new Map,states:c,stateOf:l=>l===void 0?c[0]??null:c.find(u=>u.id===l)??null}}var jN=["x","y","z"],UN=/^(line|plane)\((-?\d+),(-?\d+)\)([uv]?)$/,KA=Math.PI/18e3,HA=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],zA=(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]],XN=e=>Math.hypot(e[0],e[1],e[2]),b0=(e,t)=>[e[0]*t,e[1]*t,e[2]*t];function g0(e){let t=XN(e);return t>1e-9?b0(e,1/t):null}function qN(e,t){let r=e*KA,n=t*KA;return[Math.cos(n)*Math.cos(r),Math.cos(n)*Math.sin(r),Math.sin(n)]}function dr(e){let t=e.lastIndexOf(".");if(t<0)return null;let r=UN.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:qN(Number(r[2]),Number(r[3]))},coord:n==="line"?"along":r[4]}}function YA(e){let t=g0(zA([0,0,1],e))??[1,0,0];(t[0]<-1e-9||Math.abs(t[0])<=1e-9&&t[1]<0)&&(t=b0(t,-1));let r=g0(zA(e,t))??[0,1,0];return(r[2]<-1e-9||Math.abs(r[2])<=1e-9&&r[1]<0)&&(r=b0(r,-1)),[t,r]}function y0(e){if(e.coord==="along")return e.shape.dir;let[t,r]=YA(e.shape.dir);return e.coord==="u"?t:r}function WA(e,t){let r=dr(t);if(!r)return;let n=jN.map(u=>e[`${r.point}.${u}`]);if(n.some(u=>!u))return;let o=y0(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=>HA(s(u),o),write:(u,m)=>{let f=s(u),p=m-HA(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 Qm=["x","y","z"];var QN=/^(?:hp\.(?:front|rear)\.\w+|(?:heave|roll)\.(?:front|rear)\.(?:outer|inner|anchor))$/;function fc(e){let t=e.lastIndexOf("."),r=e.slice(0,t);if(t<0||!QN.test(r))return null;let n=e.slice(t+1);if(n==="x"||n==="y"||n==="z")return{point:r,axis:n};let o=dr(e);return o?{point:r,axis:o.coord}:null}var hc="*";function x0(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 R0=e=>e?.reads==="speed"||e?.reads==="operating",v0=e=>e?.reads==="lateral"||e?.reads==="operating";function fo(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 Zm(e,t){return e?.appliesAt?t.find(r=>!e.appliesAt(r)):t[0]}function Jm(e,t,r){let n=r?.stateId?e.stateOf(r.stateId):Zm(t,e.states)??null;return n&&!t.appliesAt?.(n)?n:null}function Lt(e,t,r){let n=`${t.id}@${fo(r)}`,o=e.values.get(n);if(o!==void 0)return o;let a;try{a=r?.courseId===hc&&t.reads==="course"?ZN(e,t,r):r?.stateId===Kr&&t.reads==="state"?JN(e,t,r):t.read(e,r)}catch{a=NaN}return e.values.set(n,a),a}function ZN(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:Lt(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 JN(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:Lt(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));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 k0(e){let t={mean:"weighted mean",max:"highest",min:"lowest"};return e?.acrossStates?`every state, ${t[e.acrossStates]}`:"every state"}function et(e){return`${e.quantity??e.groupShort??e.group} \xB7 ${e.label}`}var eO={front:"Front",rear:"Rear"},bc={heave:0,pitch:0,roll:0,steer:0};function jA(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 tO(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 gc=e=>e.length?Math.max(...e)-Math.min(...e):NaN;function UA(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 XA(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 Ga(e,t,r){let n=e.stateOf(t?.stateId),o=n?e.poseAt(n):null;return o?r(o):NaN}var yc=(e,t)=>`${e==="front"?"F":"R"}${t}`,qA=e=>e==="L"?"R":"L";function QA(e){let t=eO[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?Id(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=Ld(o(x.car),F.linkage,F.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(bc)?.[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?tO(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?gc(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?gc(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?jA(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?jA(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=>gc(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=>gc(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)=>Ga(x,M,F=>F.camber[yc(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)=>Ga(x,M,F=>F.camber[yc(e,qA(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)=>Ga(x,M,F=>F.corners[yc(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?XA(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(C=>C.metrics.motionRatio??NaN).filter(Number.isFinite);if(!F.length)return NaN;let w=F.reduce((C,T)=>C+T,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?XA(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=>UA(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:ga(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=>UA(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:Wn(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(bc)?.[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)=>Ga(x,M,F=>F.corners[yc(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)=>Ga(x,M,F=>F.corners[yc(e,qA(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:gc(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(bc)?.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(bc)?.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(bc)?.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 ZA(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 rO=[{id:"kin.front.ackermannCentre",group:"Steering",label:"Ackermann near centre",unit:"%",scale:25,scope:"front",cost:"cheap",read:e=>ZA(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=>ZA(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}}],nO=[{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)=>Ga(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}}],M0=[...QA("front"),...QA("rear"),...rO,...nO];var nF={front:"Front",rear:"Rear"},JA=e=>po("side",e),oO=e=>po("drive",e)&&po("brake",e)?"neither brakes nor drives":null;function aO(e,t,r,n){let o=Jm(e,t,r),a=o?e.tyreAt(o):null;return a?n(a):NaN}function Ka(e,t){let r={...e,read:(n,o)=>aO(n,r,o,t)};return r}var eF=e=>e?100*e.lossCamber:NaN,tF=e=>e&&!e.lifted?e.camber-e.wants:NaN;function rF(e){let t=nF[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:JA,unavailable:s=>Xg(s.params,e)},a=[Ka({...o,id:r("camberErrorOuter"),label:"camber error at the outer wheel",unit:"\xB0",scale:.5},s=>tF(s.side(e)?.wheels[0])),Ka({...o,id:r("camberErrorInner"),label:"camber error at the inner wheel",unit:"\xB0",scale:.5},s=>tF(s.side(e)?.wheels[1])),Ka({...o,id:r("sideLossCamber"),label:"side grip lost to camber",unit:"%",scale:1},s=>eF(s.side(e))),Ka({...n,appliesAt:JA,id:r("sideLossToe"),label:"side grip lost to the toe split",unit:"%",scale:1},s=>100*s.toeLoss(e)),Ka({...n,appliesAt:oO,unavailable:s=>qg(s.params,e),id:r("longLossCamber"),label:"drive and brake grip lost to camber",unit:"%",scale:1},s=>eF(s.long(e)))];return e==="front"&&a.push(Ka({...n,appliesAt:s=>po("ackermann",s),id:r("ackermannError"),label:"Ackermann against the tyre",unit:"%",scale:25},s=>s.ackermann())),a}var S0=[...rF("front"),...rF("rear")],sO=/^tyre\.(front|rear)\.(camberErrorOuter|camberErrorInner|sideLossCamber|longLossCamber)$/;function A0(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=sO.exec(a.id);if(!i)continue;let c=i[1],l=i[2]==="longLossCamber",u=s?.stateId==="*"?e.states.filter(m=>!a.appliesAt?.(m)):[Jm(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 ${nF[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 F0(e,t){let r=e.appliesAt?.(t);return r?`is read at ${t.name}, which ${r}`:null}var oF={understeer:"operating",yawFreq:"speed",yawZeta:"speed",yawStiffness:"operating",steeringTorque:"operating",steeringTorqueGradient:"operating"};function nt(e,t,r,n="cheap"){let o=vb[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,...oF[e]?{reads:oF[e]}:{},read:(a,s)=>{let i=a.dynInput(),c=a.dynCtx(s);return i&&c?o.compute(i,c):NaN}}}var iO=[nt("understeer","Handling \u2014 balance",.1),nt("tlltdFront","Handling \u2014 balance",5),nt("rollStiffFront","Handling \u2014 balance",5)],cO=[nt("yawFreq","Handling \u2014 response",.5),nt("yawZeta","Handling \u2014 response",.2),nt("stabilitySpeed","Handling \u2014 response",50),nt("yawStiffness","Handling \u2014 response",2e4,"trim")],lO=[nt("steeringTorque","Steering feel",1,"trim"),nt("steeringTorqueGradient","Steering feel",2,"trim")],uO=[nt("rollGradient","Ride & body",.5),nt("pitchGradient","Ride & body",.5),nt("rideFreqFront","Ride & body",.5),nt("rideFreqRear","Ride & body",.5),nt("rollFreq","Ride & body",.5),nt("pitchFreq","Ride & body",.5),nt("zetaFront","Ride & body",.2),nt("zetaRear","Ride & body",.2)],mO=[{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}],pO=[{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}],w0=[...iO,...cO,...lO,...uO,...mO,...pO];function dO(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 C0=[{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)=>dO(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 fO(e,t){let r=/^(.*?)\s*\(([^)]+)\)\s*$/.exec(e);return r?{label:r[1],unit:r[2]}:{label:e,unit:t?"s":""}}function hO(e){return e==="s"||e==="kWh"?.1:e==="km/h"?2:1}var aF=new WeakMap;function ep(e){let t=aF.get(e);return t||(t=e.metrics.filter(Ic).map(r=>{let{label:n,unit:o}=fO(r.label,r.format==="time");return{id:`event.${e.id}.${r.key}`,group:`Events \xB7 ${e.label}`,groupShort:"Events",label:n,unit:o,scale:hO(o),scope:"car",cost:"session",read:a=>a.session(e.id)?.[r.key]??NaN}}),aF.set(e,t),t)}var T0=Da.flatMap(ep);var tp=[...M0,...S0,...w0,...C0,...T0],Ha=Object.fromEntries(tp.map(e=>[e.id,e]));var sF={all:tp,byId:Ha},iF=new WeakMap;function zr(e=[]){if(e.length===0)return sF;let t=iF.get(e);if(t)return t;let r=Wb(e).filter(n=>!Ea(n.id)).flatMap(ep);return t=r.length?{all:[...tp,...r],byId:{...Ha,...Object.fromEntries(r.map(n=>[n.id,n]))}}:sF,iF.set(e,t),t}var xc=180/Math.PI,za=Math.PI/180,gO=.2;function rp(e,t){let r=H(t,e);return q(r[0]<0?dd(r):r)}var np=e=>({side:Math.atan2(e[2],e[0])*xc,plan:Math.atan2(e[1],e[0])*xc}),op=(e,t)=>q([1,Math.tan(t*za),Math.tan(e*za)]),Rc=e=>Math.abs(e[0])>=gO,ap=(e,t)=>Math.atan(t/Math.max(e,1))*xc,sp=(e,t)=>Math.tan(t*za)*Math.max(e,1);var Rn=["side","plan","clock","len"],jt={uca:{fore:"ucaFront",aft:"ucaRear",ball:"uprightUpper"},lca:{fore:"lcaFront",aft:"lcaRear",ball:"uprightLower"}},vc={uca:"upper arm",lca:"lower arm"},yO=1,cF=(e,t)=>rp(e[jt[t].fore],e[jt[t].aft]);function lF(e){let t=q(H(pd,U(e,X(pd,e))));return{e1:t,e2:ae(e,t)}}function P0(e,t){let r=cF(e,t);if(!Rc(r))return`the ${vc[t]}'s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it`;let n=jt[t],o=qr(e[n.ball],e[n.fore],r);return Math.hypot(...H(o,e[n.ball]))>=yO?null:`the ${vc[t]}'s ball joint sits on its own pivot axis, so the arm has no length to swing on`}function Yr(e,t){let r=jt[t],n=e[r.ball],o=cF(e,t),a=qr(n,e[r.fore],o),s=H(a,n),i=Math.hypot(s[0],s[1],s[2]),{e1:c,e2:l}=lF(o),u=i>0?U(s,1/i):c;return{...np(o),clock:Math.atan2(X(u,l),X(u,c))*xc,len:i,sFront:X(H(e[r.fore],a),o),sRear:X(H(e[r.aft],a),o)}}function L0(e,t){let r=op(e.side,e.plan),{e1:n,e2:o}=lF(r),a=ee(U(n,Math.cos(e.clock*za)),U(o,Math.sin(e.clock*za))),s=ee(t,U(a,e.len));return{fore:ee(s,U(r,e.sFront)),aft:ee(s,U(r,e.sRear))}}function uF(e,t,r,n){let o=jt[t],a={...Yr(e,t),[r]:n},{fore:s,aft:i}=L0(a,e[o.ball]);return{...e,[o.fore]:s,[o.aft]:i}}function mF(e,t){return t==="clock"?e.len:Math.abs(e.sFront-e.sRear)/2}function ip(e,t,r){return t==="len"?r:ap(mF(e,t),r)}function D0(e,t,r){return t==="len"?r:sp(mF(e,t),r)}var ho=["side","plan","atY","atZ"],bo={fore:"rockerPivotA",aft:"rockerPivotB"},xO=5,pF=e=>rp(e.rockerPivotA,e.rockerPivotB);function Ya(e){return Math.hypot(...H(e.rockerPivotB,e.rockerPivotA))<xO?"the rocker\u2019s two pivots are the same point, so there is no axis to describe":Rc(pF(e))?null:"the rocker\u2019s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it"}function vn(e){let t=pF(e),r=Rc(t)?t:[1,0,0],n=e.rockerPivotA,o=ee(n,U(r,-n[0]/r[0]));return{...np(r),atY:o[1],atZ:o[2],sA:X(H(n,o),r),sB:X(H(e.rockerPivotB,o),r)}}function E0(e){let t=op(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 dF(e,t,r){if(Ya(e))return e;let{a:n,b:o}=E0({...vn(e),[t]:r});return{...e,rockerPivotA:n,rockerPivotB:o}}var fF=e=>Math.abs(e.sA-e.sB)/2;function I0(e,t,r){return t==="side"||t==="plan"?ap(fF(e),r):r}function _0(e,t,r){return t==="side"||t==="plan"?sp(fF(e),r):r}var Xt={front:"Front",rear:"Rear"},Ut=["x","y","z"],Oe=(e,t)=>t==="front"?e.front:e.rear,kc=(e,t,r)=>t==="front"?{...e,front:r}:{...e,rear:r},hF=[{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"}]}],bF={damperChassis:"strut top mount",pushrodOuter:"strut lower mount"},go=30;function RO(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).config.layout==="mcpherson";for(let o of hF)for(let{key:a,label:s}of o.keys){let i=n&&bF[a]||s;for(let c=0;c<3;c++)t.push({id:`hp.${r}.${a}.${Ut[c]}`,group:`${Xt[r]} hardpoints \u2014 ${o.kind}`,label:`${i} ${Ut[c]}`,scope:Xt[r],unit:"mm",defaultSpan:go,read:l=>Oe(l.vehicle,r).hardpoints[a][c],write:(l,u)=>{let m=Oe(l.vehicle,r),f=[...m.hardpoints[a]];f[c]=u;let p={...m.hardpoints,[a]:f};return{...l,vehicle:kc(l.vehicle,r,{...m,hardpoints:p})}}})}}return t}var vO={side:"axis side-view angle",plan:"axis plan-view angle",clock:"arm clock angle",len:"effective arm length"},kO={side:"\xB0",plan:"\xB0",clock:"\xB0",len:"mm"};function MO(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).config.layout==="mcpherson";for(let o of["uca","lca"]){let a=Oe(e.vehicle,r).hardpoints,s=P0(a,o)?null:Yr(a,o);for(let i of Rn)t.push({id:`arm.${r}.${o}.${i}`,group:`${Xt[r]} ${n?"arm axes":"wishbone axes"}`,label:`${vc[o]} \u2014 ${vO[i]}`,scope:Xt[r],unit:kO[i],defaultSpan:s?ip(s,i,go):go,read:c=>Yr(Oe(c.vehicle,r).hardpoints,o)[i],write:(c,l)=>{let u=Oe(c.vehicle,r),m=uF(u.hardpoints,o,i,l);return{...c,vehicle:kc(c.vehicle,r,{...u,hardpoints:m})}}})}}return t}var SO={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"},AO={side:"\xB0",plan:"\xB0",atY:"mm",atZ:"mm"};function FO(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).hardpoints,o=Ya(n)?null:vn(n);for(let a of ho)t.push({id:`rocker.${r}.${a}`,group:`${Xt[r]} rocker axis`,label:`rocker \u2014 ${SO[a]}`,scope:Xt[r],unit:AO[a],defaultSpan:o?I0(o,a,go):go,read:s=>vn(Oe(s.vehicle,r).hardpoints)[a],write:(s,i)=>{let c=Oe(s.vehicle,r),l=dF(c.hardpoints,a,i);return{...s,vehicle:kc(s.vehicle,r,{...c,hardpoints:l})}}})}return t}var cp={front:"heaveFrontDesign",rear:"heaveRearDesign"},N0={front:"arbFrontDesign",rear:"arbRearDesign"};function wO(e,t){return{heave:e.config.actuation==="decoupled"?"heave element":"third spring",roll:t?.design.kind==="coil"?"roll shock":"anti-roll bar"}}var lp=e=>/^(heave|roll)\.(front|rear)\.(outer|inner|anchor)\.[xyz]$/.test(e);function CO(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r),o=e.params[cp[r]],a=e.params[N0[r]],s=wO(n,a),i=d=>d.params[cp[r]],c=d=>d.params[N0[r]],l=(d,h)=>({...d,params:{...d.params,[cp[r]]:h}}),u=(d,h)=>({...d,params:{...d.params,[N0[r]]:h}}),m={group:`${Xt[r]} heave & roll elements`,scope:Xt[r]},f=(d,h,b,g,y)=>{for(let R of b)t.push({...m,id:`${d}.${Ut[R]}`,label:`${h} ${Ut[R]}`,unit:"mm",defaultSpan:go,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=en(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 TO=[{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 PO(e){let t=[];for(let r of["front","rear"]){let n=Oe(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:Xt[r],unit:"N/mm",defaultSpan:Math.max(500,l*.4),read:u=>i(Oe(u.vehicle,r).compliance??{})??l,write:(u,m)=>{let f=Oe(u.vehicle,r),p={...f,compliance:c(f.compliance??{},Math.max(1,m))};return{...u,vehicle:kc(u.vehicle,r,p)}}})};for(let a of["ucaFront","ucaRear","lcaFront","lcaRear","tieRod","pushRod"])o(`link.${a}`,`${LO[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}`,`${DO[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 LO={ucaFront:"UCA front leg",ucaRear:"UCA rear leg",lcaFront:"LCA front leg",lcaRear:"LCA rear leg",tieRod:"tie rod",pushRod:"push/pull rod"},DO={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 EO(){return TO.map(e=>({id:`cfg.${e.axle}.${e.field}`,group:e.group,label:e.label,scope:Xt[e.axle],unit:e.unit,defaultSpan:e.span(e.fallback),read:t=>Oe(t.vehicle,e.axle).config[e.field]??e.fallback,write:(t,r)=>{let n=Oe(t.vehicle,e.axle),o={...n,config:{...n.config,[e.field]:r}};return{...t,vehicle:kc(t.vehicle,e.axle,o)}}}))}function IO(e){let t=En(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=>En(c.params.steeringSystem)[n],write:(c,l)=>({...c,params:{...c.params,steeringSystem:En({...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 _O(e){let t=hi(e.params),r=[];for(let n of["front","rear"]){if(t[n]!=="diff")continue;let o=Un(e.params.driveline?.[n]);if(o?.kind!=="clutch"&&o?.kind!=="torsen")continue;let a=(s,i)=>{let c=Fu[`${n}.${s}`];return{id:`driveline.${n}.${s}`,group:"Differential",label:c.label.charAt(0).toLowerCase()+c.label.slice(1),scope:Xt[n],unit:c.unit===": 1"?"":c.unit??"",defaultSpan:i,read:l=>Un(l.params.driveline?.[n])?.[s],write:(l,u)=>({...l,params:{...l.params,driveline:Au({...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 NO(e){if(Ul(e.params)!=="hydraulic")return[];let t=[{id:"brakeSetup.barFront",group:"Brakes",label:`${gh("barFront").toLowerCase()}, front share`,unit:"-",defaultSpan:.05,read:a=>Fr(a.params.brakeSetup).barFront,write:(a,s)=>({...a,params:{...a.params,brakeSetup:Fr({...Fr(a.params.brakeSetup),barFront:s})}})}];if(!e.params.brakeModel)return t;let r=rr(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:bh(a.circuit?`${a.circuit}.${String(a.key)}`:a.key),unit:s,defaultSpan:i,read:c=>n(rr(c.params.brakeModel),a),write:(c,l)=>{let u=rr(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:rr(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 gF=e=>!!e&&typeof e=="object"&&"value"in e&&"label"in e;function yF(e){let t={...e};for(let r of Object.keys(t)){let n=t[r];gF(n)&&(t[r]={...n})}return t}function OO(e){let t=[];for(let r of Pk(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 gF(s)?s.value:NaN},write:(a,s)=>{let i=yF(a.params);return Lu(i,n.label,s),{...a,params:i}}})}return t}function xF(e){let t={};for(let s of["front","rear"]){if(!Oe(e.vehicle,s).measured)continue;let c="this axle is described by measured curves, so its linkage is not solved";for(let l of hF)for(let{key:u}of l.keys)for(let m of Ut)t[`hp.${s}.${u}.${m}`]={why:c};for(let l of["uca","lca"])for(let u of Rn)t[`arm.${s}.${l}.${u}`]={why:c};for(let l of ho)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 Ut)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(Oe(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 Ut)t[`hp.${s}.${c}.${l}`]={why:i};for(let c of ho)t[`rocker.${s}.${c}`]={why:i}}for(let s of["front","rear"]){let i=Oe(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 Ut)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=Oe(e.vehicle,s),c=e.params[cp[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.${Ut[f]}`]={why:`the rocker shaft runs along ${Ut[f]} \u2014 this only slides the eye along it`})}for(let s of["front","rear"]){let i=Oe(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 Ut)t[`hp.${s}.${l}.${u}`]={why:c,useInstead:`hp.${s}.damperChassis.${u}`};for(let l of Rn)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=Oe(e.vehicle,s);if(i.measured)continue;for(let l of["uca","lca"]){if(l==="uca"&&i.config.layout==="mcpherson")continue;let u=P0(i.hardpoints,l);if(u)for(let m of Rn)t[`arm.${s}.${l}.${m}`]={why:u,useInstead:`hp.${s}.${jt[l].fore}.z`}}let c=Ya(i.hardpoints);if(c&&i.config.actuation!=="direct")for(let l of ho)t[`rocker.${s}.${l}`]={why:c,useInstead:`hp.${s}.${bo.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?ob:ab;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(Cu))t[`param.${s}`]={why:i};for(let[s,i]of Object.entries(Tu(e.params)))t[`param.${s}`]={why:i};let a=Ul(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 RF(e){let t={...BO,...xF(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[...RO(e),...MO(e),...FO(e),...CO(e),...EO(),...IO(e),...NO(e),..._O(e),...PO(e),...OO(e.params)].map(r)}var VO={spring_front:"cfg.front.springRate",spring_rear:"cfg.rear.springRate"},BO=Object.fromEntries(Object.entries(nb).map(([e,t])=>[`param.${e}`,{why:t,useInstead:VO[e]}])),ct=e=>e.scope?`${e.scope} \xB7 ${e.label}`:e.label;function Gt(e){let t={};for(let n of RF(e))t[n.id]=n;let r=(n,o)=>{if(typeof o!="string")return;let a=WA(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 O0=e=>e.step!==void 0&&Number.isFinite(e.step)&&e.step>0?e.step:0,V0=e=>O0(e)>0||(e.values?.length??0)>0,B0=e=>e.some(V0),vF=e=>1e-9*Math.max(1,Math.abs(e.lo),Math.abs(e.hi));function kF(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=O0(e);if(!r||!Number.isFinite(e.start))return t;let n=vF(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 MF=(e,t)=>t.map((r,n)=>e[n]&&V0(e[n])?kF(e[n],r):r);function $0(e,t=1e3){if(e.values?.length)return e.values.length;let r=O0(e);if(!r||!Number.isFinite(e.start))return 1/0;let n=vF(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 G0(e,t,r){let n=MF(e.variables,t),o=n.every((a,s)=>a===t[s]);return{x:n,score:o?r:kr(e,n)}}function z0(e,t){if(!e.variables.some(AF))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(FF(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 AF=e=>!!(e.fixed||e.around||e.follows)||FF(e),FF=e=>!!e.values?.length&&(e.lo!==Math.min(...e.values)||e.hi!==Math.max(...e.values));function Dt(e,t){if(!t.variables.some(AF))return t;let r=Gt(e);return z0(t,n=>{let o=r[n];if(!o)return NaN;try{return o.read(e)}catch{return NaN}})}function qt(e){return[...e.objectives,...e.constraints,...e.watches??[]]}var mp=e=>(e.metrics??zr()).byId;function Y0(e,t){t=Dt(e,t);let r=Gt(e),n=[];for(let o of t.variables){let a=r[o.id];a&&n.push({id:a.id,name:ct(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 pp(e,t,r){t=Dt(e,t);let n=Gt(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]))}),U0(e,o,t.followers,n)}function W0(e,t,r={}){let n=t.states??[],o=n.some(c=>c.follows);if(!o&&!t.envelopeFollows)return t;let a=xn(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=Kg(n,c,KO(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=mp(r),u=j0(t,l),m=qt(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=xn(e,{density:t.density,envelope:h,assemble:r.assemble,numerics:r.numerics});return m.every(({r:g,m:y})=>Number.isFinite(Lt(b,y,g.at)))},p=c.length===s.length?GO(e,zg(c,u),u):null,d=p&&m.length?$O(p,f):p;d&&!Yg(d,t.envelope)&&(i=d)}return s===n&&i===t.envelope?t:{...t,states:s,envelope:i}}var up=3;function $O(e,t){let r=(c,l)=>t({...e,travelMin:c,travelMax:l}),n=e.travelMin-up,o=e.travelMax+up;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+up)),i=Math.max(1,Math.min(e.travelMax,o-up));return s===e.travelMin&&i===e.travelMax?e:{...e,travelMin:s,travelMax:i}}function j0(e,t){let r=new Set;for(let n of qt(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 GO(e,t,r){if(!t)return null;let n=Ba(e.vehicle,e.params),{travelMin:o,travelMax:a}=t;for(let s of r.map(i=>n[i]))try{let i=Ge(s,{travelMin:o,travelMax:a,steps:mc.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 KO(e){let t=e.projectTrack?.();if(!t)return null;try{return Gg(it(t.asset,t.numerics))}catch{return null}}function U0(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 Mc(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 wF=(e,t="")=>t&&t!=="-"?`${e} ${t}`:`${e}`;function CF(e,t,r){let n=t??Ha[e.metricId],o=(n?et(n):e.metricId)+Sc(e.at,n,r),a=s=>wF(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 Sc(e,t,r){if(!e&&t?.reads!=="state")return"";e??={};let n=[];if(t?.reads==="state")if(e.stateId===Kr)n.push(k0(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&&R0(t)&&n.push(`${(e.speed*3.6).toFixed(0)} km/h`),e.ayG!==void 0&&v0(t)&&n.push(`${e.ayG.toFixed(2)} g`),e.courseId===hc&&t?.reads==="course")n.push(x0(t));else if(e.courseId&&t?.reads==="course"){let o=r?.lap.courses.find(a=>a.id===e.courseId);o&&n.push(n0(o))}return n.length?` @ ${n.join(", ")}`:""}function TF(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 PF=5e-4;function LF(e,t){return e.cost!=="lap"&&e.cost!=="session"?0:Number.isFinite(t)?PF*Math.abs(t):0}function dp(e,t,r={}){t=Dt(e,t);let n=Y0(e,t),o=Gt(e),a=mp(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=Lt(f,b,h.at);if(!Number.isFinite(g))return{ok:!1,violation:f.failure?.violation??400,reason:f.failure?.reason??`${et(b)} could not be computed`};let y=Mc(h,g);y>0&&(p+=y/b.scale,d.push(`${CF(h,b,t)} (${wF(g.toFixed(3),b.unit)})`))}return d.length===0?Is:{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=U0(e,f,t.followers,o),{car:f,ev:xn(f,{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 f=u(i,m);if(!f.ok)return f;for(let{spec:p,metric:d}of c)Lt(m,d,p.at);for(let{spec:p,metric:d}of l)Lt(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=Lt(m,p,f.at);return{name:et(p)+Sc(f.at,p,t),raw:d,unit:p.unit,weight:f.weight,contribution:TF(f,p,d),resolution:Math.abs(f.weight)*LF(p,d)/p.scale}})}}function K0(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 DF(e,t){if(e.variables.some(o=>o.id===t))return!0;let r=fc(t);if(!r||!Qm.includes(r.axis))return!1;if(e.variables.some(o=>dr(o.id)?.point===r.point))return!0;let n=K0(t);return!!n&&e.variables.some(o=>/^(arm|rocker)\./.test(o.id)&&K0(o.id)===n)}function HO(e,t){let r=e.followers??[],n=new Map(r.map(i=>[i.id,i.follows])),o=i=>{let c=t[i],l=fc(i);return c&&l&&Qm.includes(l.axis)?{name:ct({...c,label:c.label.replace(/ [xyz]$/,"")}),axis:l.axis}:{name:c?ct(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 DF(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 X0(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=Dt(e,t);let a=Gt(e),s=[],i=mp(r),c=qt(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=qt(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(`${et(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(`${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!==Kr?y.find(F=>F.id===k.at.stateId):void 0,M=x?F0(v,x):null;M?s.push(`${et(v)} ${M}. Point it at a state that does.`):!x&&!Zm(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 f=new Set([...t.lap.courses.map(y=>y.id),hc]);for(let y of qt(t))if(y.at?.courseId&&!f.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(`${ct(R)}: list two values or more, or fix it where it is.`):y.hi>y.lo?y.step!==void 0&&$0({...y,start:R.read(e)})<2&&s.push(`${ct(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(`${ct(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?ct(v):void 0;s.push(`${ct(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(`${ct(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=K0(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]?ct(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=fc(y);if(!R)continue;let k=dr(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`],F=M?ct({...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(...HO(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 qt(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 qt(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 EF=.1,IF=2e3,H0=3;function q0(e,t,r={},n=IF){t=Dt(e,t);let o=dp(e,t,r),a=mp(r),s=Gt(e),i=o.variables.map(S=>S.start),c=S=>{let A=o.build(S);return o.feasible(A).ok&&o.terms(A),A},l=c(i),u=o.feasible(l),m=[...t.objectives,...t.constraints],f=(S,A=m)=>{let P={};for(let L of A){let D=a[L.metricId];D&&(P[`${L.metricId}@${fo(L.at)}`]=Lt(S.ev,D,L.at))}return P},p=S=>m.map(A=>S[`${A.metricId}@${fo(A.at)}`]).map(A=>Number.isFinite(A)?A.toFixed(9):"x").join("|"),d=f(l,qt(t)),h=p(d),b=[],g=[],y={},R=[],k=0;t.variables.forEach((S,A)=>{let P=s[S.id];if(!P)return;if(R.length>=H0&&k>n){g.push(P);return}let L=[...i];L[A]=i[A]+(S.hi-i[A])*.25||S.hi;let D=performance.now(),E=c(L),V=performance.now()-D;k+=V,R.push(V);let N=f(E);y[P.id]=N,p(N)===h&&b.push(P)});let v=t.variables[0],x=v?t.variables.indexOf(v):-1;for(let S=0;v&&R.length>0&&R.length<H0;S++){let A=[...i];A[x]=i[x]+(v.hi-i[x])*(.4+.15*S)||v.hi;let P=performance.now();c(A),R.push(performance.now()-P)}let M=[...R].sort((S,A)=>S-A),F=M.length?M[M.length>>1]:0,w=[],C=qt(t).map(S=>S.metricId);if(C.some(S=>S.startsWith("dyn.trim")||S==="dyn.ymdMaxAy")){let S=l.ev.ymdLimit();S?.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."),!S&&l.ev.dynAvailable&&w.push("The yaw-moment diagram found no trim point, so anything read off the limit is unavailable.")}if(C.some(S=>S==="dyn.steeringTorque"||S==="dyn.steeringTorqueGradient")){let S=l.ev.tyre()?.model,A=S?tn(S):null;A==="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."):A==="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(S=>T.includes(S))){let A=l.ev.lapReserve()?.beyondFrac;if(A!==void 0&&Number.isFinite(A)){let P=(A*100).toFixed(0);A>=EF?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.`):A>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(...A0(l.ev,qt(t).map(S=>({m:a[S.metricId],at:S.at})).filter(S=>!!S.m))),{msPerEval:F,values:d,samples:R.length,times:R,dead:b,moves:y,unprobed:g,warnings:w,beyondFrac:C.some(S=>T.includes(S))?l.ev.lapReserve()?.beyondFrac:void 0,startFeasible:u.ok,startReason:u.reason}}var YO=[{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:WO.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 WO=["setup:m","characteristics:peak_power","characteristics:power_to_weight","characteristics:cla","characteristics:cda","characteristics:pack_energy","characteristics:maxAy","characteristics:top_speed"];var Tse=new Set(YO.map(e=>e.kind));var _F={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 Q0=["FL","FR","RL","RR"],kt=(e,t,r)=>({input:e,from:r?r[0]:_F[e].from,to:r?r[1]:_F[e].to,n:t}),Ese=[{id:"sides",name:"Inside and outside",cards:[{id:"camber-roll",form:"curves",title:"Camber to the road through roll",sweep:kt("roll",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"toe-rack",form:"curves",title:"Wheel angle against the rack",sweep:kt("steer",25),wheels:["FL","FR"],y:["toe"]},{id:"camber-rack",form:"curves",title:"Camber to the road through the steer",sweep:kt("steer",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"load-roll",form:"curves",title:"Wheel loads through roll",sweep:kt("roll",25),wheels:Q0,y:["wheelLoad"]},{id:"travel-roll",form:"curves",title:"Wheel travel through roll",sweep:kt("roll",25),wheels:Q0,y:["travel"]},{id:"toe-roll",form:"curves",title:"Roll steer, all four",sweep:kt("roll",25),wheels:Q0,y:["toe"]}]},{id:"maps",name:"Travel and steer together",cards:[{id:"camber-map",form:"surface",title:"Camber over travel and rack",sweep:kt("travel",17),second:kt("steer",13),wheels:["FL"],y:["camber"]},{id:"bump-steer-map",form:"map",title:"Bump steer over travel and rack",sweep:kt("travel",17),second:kt("steer",13),wheels:["FL"],y:["bumpSteer"]},{id:"bump-steer-family",form:"curves",title:"Bump steer through travel, at five rack positions",sweep:kt("travel",25),second:kt("steer",5,[-20,20]),wheels:["FL"],y:["bumpSteer"]},{id:"scrub-map",form:"surface",title:"Scrub radius over travel and rack",sweep:kt("travel",17),second:kt("steer",13),wheels:["FL"],y:["scrubRadius"]}]}];function Z0(e){let t=Number(e);return Number.isFinite(t)?Math.min($f,Math.max(Bf,t)):At}var OF=6e4;var wie=[{within:60*6e4,every:OF},{within:1440*6e4,every:60*6e4},{within:720*60*6e4,every:1440*6e4},{within:1/0,every:10080*6e4}];var oV=new Set(["color","visible","source","origin"]),Vie=["id",...oV];var $F=.18/1.18,GF={induction:{kind:"natural"}},KF=e=>e.breathing??GF;function fp(e){switch(e?.kind){case"sae-j1349":return Yi(99e3,25);case"measured":return Yi(e.hPa*100,e.tempC);default:return Yi(101325,20)}}var sV=fp(void 0);function HF(e,t){let r=fp(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 zF(e,t){let r=e.induction;if(r.kind==="table"){let o=s=>Be(r.densityAltitudeM,r.powerPct,s),a=o(fp(e.rated).densityAltitudeM);return a>0?Math.max(0,o(t.densityAltitudeM)/a):0}let n=e.frictionShare??$F;return Math.max(0,(HF(e,t)-n)/(1-n))}var BF=new WeakMap;function ey(e,t){let r=e.asRated??e,n=`${t.p}|${t.pDry}|${t.T}`,o=BF.get(r);o||BF.set(r,o=new Map);let a=o.get(n);if(a)return a;let s=zF(KF(r),t),i={...r,torque:r.torque.map(c=>c*s),asRated:r};return o.set(n,i),i}function uV(e){return JSON.parse(ty(ry(e,"public/laptime/index.json"),"utf8")).tracks}var mV=async e=>{let t=await fetch(e.url);if(!t.ok)throw new Error(`The track could not be read from ${Tm(e)} (${t.status}).`);return new Uint8Array(await t.arrayBuffer())};function YF(e,t=new Map,r=mV){let n=uV(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(!Ji(o.address))throw new Error(`"${o.address}" is not a catalogue address`);if(!Zi(o.link))throw new Error("This track is linked to a source this version does not read from.");i=await Fg(await r(o.link),o.link,o.address)}else if(o.kind==="catalogue"){if(!Ji(o.address))throw new Error(`"${o.address}" is not a catalogue address`);let c=JSON.parse(ty(ry(e,"public/catalogue",Cg(o.address)),"utf8"));i=await Pg(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(ty(ry(e,"public/laptime",c),"utf8"))}return t.set(a,i),structuredClone(i)}}var pV=9.81;function WF(e,t=e.tireModel,r=e.tireModelRear){if(!t)return e;let n=e.m.value*pV/4,o=xa(e,t,r),a=Pe(o.front).rollingRadius(n),s=o.rear===o.front?a:Pe(o.rear).rollingRadius(n),i=dV(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 dV(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 fV=1e-6;function jF(e,t,r){let n=e.cgReference;if(!n||!e.cg_height)return e;let o=kk(e,t,r);if(o===void 0||Math.abs(o-n.standingRadius)<fV)return e;let a=n.typed??e.cg_height.value;return{...e,cg_height:{...e.cg_height,value:ya(e.cg_height.value,n.standingRadius,o)},cgReference:{...n,standingRadius:o,typed:a}}}function UF(e,t,r){let n=e.rcRoad,o=e.rc_front,a=e.rc_rear;if(!n||!o||!a)return e;let s=Su(e,t,r),i=Nr(o.value,n.gainFront,n.radiusFront,s.front),c=Nr(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 XF=e=>({brakeFade:e.brakeFade,airTempC:e.airTempC,diffYaw:e.diffYaw,...Wi(e.air)?{air:e.air}:{}});var yo=(e,t)=>t?e.find(r=>r.id===t)?.model:void 0;function xo(e){return{tire:t=>yo(e.tires,t),motor:t=>yo(e.motors,t),aero:t=>yo(e.aeros,t),battery:t=>yo(e.batteries,t),brake:t=>yo(e.brakes??[],t),damper:t=>yo(e.dampers??[],t),suspensionOf:t=>Ba(ny(e,t),t)}}function ny(e,t){let r=yo(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 Ro(e,t,r){let n={front:t.tire(e.tireModelId),rear:t.tire(e.tireModelIdRear)};return oy(hk(t.suspensionOf(e),e,n),t,r)}function hV(e){return Wi(e.air)?ES(e.air,e.airTempC??At):void 0}var bV="the air the session states, at its venue";function gV(e,t){return t?{...e,rho:{...e.rho,value:t.rho},readouts:{...e.readouts,rho:bV}}:e}function yV(e,t,r){if(!r)return{rho:e.rho,motorModel:t,readouts:e.readouts};let{rho:n,readouts:o}=gV(e,r);return{rho:n,motorModel:t&&ft(t)?ey(t,r):t,air:r,readouts:o}}function oy(e,t,r){let n=t.tire(e.tireModelId),o=t.tire(e.tireModelIdRear),a=UF(jF(WF(Fk(Mk(Ik(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}=yV(a,t.motor(e.motorModelId),hV(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),...si(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 kV=e=>e!==!1,MV=(e,t,r)=>r&&t>0?(e%t+t)%t:Math.min(Math.max(e,0),t);function SV(e,t,r){let n=e.points.filter(o=>Number.isFinite(o.at)&&Number.isFinite(o.z)).map(o=>({...o,at:MV(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 AV(e,t,r){let n=SV(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 FV(e,t,r,n){let o=t-e.at;return n&&r>0?o-r*Math.round(o/r):o}function wV(e,t,r,n){for(let s of e){let i=FV(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 qF(e,t,r,n){let o=kV(n),a=AV(e,r,o);return a.length?t.map(s=>wV(a,s,r,o)):t.map(()=>0)}function Ac(e,t){if(!t?.points.length)return e;let r=ac(e),{zSmoothing:n,...o}=e;return{...o,z:qF(t,r,Jg(e),e.closed)}}var hp={widthLeft:1.5,widthRight:1.5,bank:0,mu:1};function QF(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 Fc(e,t){let r=QF(e.source);return ZF(e,r?await t(r):void 0)}function ZF(e,t){let{source:r}=e;if(r.kind==="segments"){let{segments:i,closed:c,spacing:l}=r,{asset:u}=ic(i,{name:e.name,closed:c,spacing:l,base:hp});return Ac(u,r.profile)}let n=r.sections??[];if(r.kind==="inline")return Ac(Om(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 Ac(Om({...t,...o!==void 0?{widthLeft:o}:{},...a!==void 0?{widthRight:a}:{},...s!==void 0?{closed:s}:{}},n,hp),r.profile)}var due=1/500;var fue=5*Math.PI/180;var Mue=1/3;var LV=[4,2,1,.5,.25,.125];function JF(e,t,r={}){let n=[...r.steps??LV].sort((g,y)=>y-g),o=st(r.numerics),a=r.tolPct??.5,s=Ft(e),i=e.ggvMode??"twoTrack",c=cr(s,!1,i),l={...o,dsTarget:n[0]??o.dsTarget},u=n.length?Jn(s,c,[it(t,l)],l,i):void 0,m=fn(s,c.rows),f=n.map((g,y)=>{let R={...o,dsTarget:g},k=Date.now(),v=it(t,R),x=Rt(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 Wa(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:Z0(t.airTempC??r.airTempC),...Wi(Rm(t.air??r.air))?{air:Rm(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:st(r.numerics)}}async function bp(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 Fc(r,t)}}function IV(e,t){let r=structuredClone(e);for(let[n,o]of Object.entries(t))if(!Lu(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 ay=(e,t)=>{let r=e?.name;return typeof r=="string"&&r?r:t};function _V(e,t){let r={};for(let n of gn){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:ay(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:ay(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:ay(i.model,i.id),byFallback:!0}:null;continue}r[n.doc]=null}return r}function NV(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 ew(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 tw=e=>e.length<2?e[0]??"":`${e.slice(0,-1).join(", ")} and ${e[e.length-1]}`;async function gp(e,t,r={}){let n=Wa(e,r.settings),{entry:o,asset:a}=await bp(e,t),s=xo(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]?IV(d.params,r.overrides[d.id]):d.params;return Ro(structuredClone(h),s,n)}),l=Bi(oo(e.meta.rulesetId,e.rulesets)),u=zi(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}=ng(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:NV(u[h]),metrics:og(l,u[h],p?.[d.id]),fitted:_V(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 rw(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=Wa(e),{asset:a}=await bp(e,t),s=Ro(structuredClone(n.params),xo(e),o);return JF(s,a,{...r.steps?{steps:r.steps}:{},numerics:o.numerics,...r.tolPct!==void 0?{tolPct:r.tolPct}:{},...r.onStep?{onStep:r.onStep}:{}})}var OV=(e,t)=>e[t]??[],VV=(e,t,r)=>r<=1?[e]:Array.from({length:r},(n,o)=>e+(t-e)*o/(r-1));function yp(e){return e.kind==="param"?VV(e.start,e.end,Math.max(1,Math.round(e.steps))):e.kind==="part"?[...e.partIds]:[...e.values]}var nw=e=>e.kind==="param"?e.label:e.kind==="part"?`${e.part} model`:e.setting;function BV(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=Ro(structuredClone(r.params),xo(e),Wa(e)),o=Dk(n,{geometry:!0}),a=Pu(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=gn.find(l=>l.doc===i.part);if(!c)throw new Error(`"${i.part}" is not a library \u2014 it is one of ${gn.map(l=>l.doc).join(", ")}`);for(let l of i.partIds)if(!OV(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*yp(c).length,1);if(s>bm)throw new Error(`that grid is ${s} runs, over the ${bm} cap \u2014 a run is a whole session. Drop an axis or use fewer steps.`)}var $V=e=>e.map(t=>String(typeof t=="number"?Number(t.toPrecision(4)):t)).join(" \xD7 ");function GV(e,t){let r=[...new Set(e.flatMap(o=>(o.didNotFinish??[]).map(a=>a.label)))],n=e.map(o=>({name:$V(o.at),events:r.map(a=>({label:a,incomplete:o.didNotFinish?.find(s=>s.label===a)}))}));return ew(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`:tw(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 KV(e){let t=[[]];for(let r of e){let n=yp(r),o=[];for(let a of n)for(let s of t)o.push([...s,a]);t=o}return t}async function ow(e,t,r,n){BV(e,r);let o=KV(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=gn.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 gp(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(yp(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(nw(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(...GV(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:nw(u),values:yp(u)})),runs:a,metricKeys:i,fleetScored:s,flat:c,caveats:l}}var Tpe=Math.PI/180;function sy(e){if(!e.chassis)return e;let{chassis:t,...r}=e;return r}var $be=180/Math.PI;var O5={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:no,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 h0e=O5.id;var wc=.02;function gw(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 B5=(e,t)=>({od:t,id:Math.min(e.id,t-.5)}),$5=(e,t)=>e/(2*t*t);function bw(e,t){switch(e.kind){case"ubar":case"blade":case"torsionTube":return{...e,section:B5(e.section,t)};default:return e}}function yw(e,t,r){let n=Math.max(wc,Math.abs(r));if(e?.kind==="coil"){let l=$5(t,n),u=e.rate;if(typeof u=="number")return{...e,rate:l};let m=Ir(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=>ui(bw(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 bw(a,c)}function xw(e,t,r,n){let o=e?.design,a=yw(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 G5=Math.PI/180,xp=1e-6;function K5(e){return!(ve(e.rockerPivotA,e.rockerPivotB)<xp||ve(e.rockerToPushrod,e.rockerPivotA)<xp||ve(e.rockerToDamper,e.rockerPivotA)<xp||ve(e.rockerToDamper,e.damperChassis)<xp)}function Mw(e){if(!K5(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=ye(r,n,0);if(!o.ok||!Number.isFinite(o.state.metrics.damperLength))return!1}return!0}catch{return!1}}function Sw(e){if(e.config.actuation!=="direct"||Mw(e))return;let{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}=z5(e);return{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}}var Rw=40;function Rp(e,t={}){let r=e.hardpoints,n=r.pushrodOuter,o=r.damperChassis,a=ve(n,o),s=ee(n,U(H(o,n),H5)),i=t.armRod??Math.max(25,.15*a),c=t.armDamper??i,l=[s[0]-Rw,s[1],s[2]],u=[s[0]+Rw,s[1],s[2]],m=q(H(u,l)),f=H(n,s),p=q(H(f,U(m,vw(f,m)))),d=It(p,m,(t.armAngleDeg??60)*G5),h=ee(s,U(d,i)),b=H(o,s),g=q(H(b,U(m,vw(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 H5=.72,vw=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2];function kw(e){let t=Ge(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 z5(e,t={}){let r=t.target??kw(e),n=t.armAngleDeg,o=Rp(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=Rp(e,{armRod:s,armAngleDeg:n,damperSide:p}),h={...e,config:{...e.config,actuation:"rocker"},hardpoints:d};try{let b=tt(h),g=ye(b,15,0),y=ye(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 kw({...e,config:{...e.config,actuation:"rocker"},hardpoints:Rp(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 Rp(e,{armRod:u,armAngleDeg:n,armDamper:m,damperSide:i})}var T0e=Array.from({length:19},(e,t)=>-45+5*t);var P0e=Math.PI/180;function Y5(e){let t=e.hardpoints,r=q(H(t.rockerPivotB,t.rockerPivotA)),n=qr(t.rockerToDamper,t.rockerPivotA,r),o=.6*Xr(H(t.rockerToDamper,n)),a=ae(r,ux),s=Xr(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 W5=(e,t)=>({...e,config:{...e.config,actuation:t}});function ly(e,t,r,n){let o=r==="front"?e.front:e.rear,a=Ru(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=Wn(e,t)[r]??Q(t,r==="front"?"arb_front":"arb_rear"),u=ga(e,t)[r]??Q(t,r==="front"?"heave_spring_front":"heave_spring_rear"),m=Sw(o),f=W5(m?{...o,hardpoints:{...o.hardpoints,...m}}:o,"decoupled"),p=r==="front"?t.heaveFrontDesign:t.heaveRearDesign,d=n?.heave??Aw(p?.linkage,w=>wn(f,w).atDesign)??Nd(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??Aw(h?g:c?.linkage,w=>Ho(f,w,{kind:b}).atDesign)??(h?Y5(f):Q1(f)),R=wn(f,d).atDesign,k=Ho(f,y,{kind:b}).atDesign,v=ku(e,t),x=gw({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=xw({design:p?.design??{kind:"none"},linkage:d,damper:p?.damper},M,x,k);return m?{...F,crank:m}:F}function Aw(e,t){return e&&Math.abs(t(e))>=wc?e:void 0}var vp=[{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"]}],uy=()=>({arbFront:void 0,arbRear:void 0,heaveFront:void 0,heaveRear:void 0}),j5={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]}},U5={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]}},X5=()=>({outer:[0,189,486],attach:"rocker",mount:{kind:"chassis",anchor:[-225,0,486]}}),q5={rate:60,motionRatio:1},Q5={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]}},Z5=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]}},J5={kind:"coil",rate:1560,motionRatio:1,gap:0,bothWays:!0},e3=40,t3={rockerPivotA:[50,130,440],rockerPivotB:[-50,130,440],rockerToPushrod:[10,170,460],rockerToDamper:[-20,64,440],damperChassis:[-20,64,215]},Fw=()=>({outer:[-50,130,480],attach:"rocker",shaftStation:-50}),ww=()=>({outer:[50,130,400],inner:[50,130,480],attach:"rocker",shaftStationOuter:50,shaftStationInner:50}),r3=e=>[e[0],e[1],e[2]];function n3(e){let t=r=>({...r,hardpoints:{...r.hardpoints,...Tw(t3)},config:{...r.config,actuation:"decoupled"}});return{...e,front:t(e.front),rear:t(e.rear)}}function Tw(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,r3(r)]))}function Pw(e,t=lo(),r=e==="pull"?U5:j5){let n=(o,a)=>({...o,hardpoints:{...o.hardpoints,...Tw(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 kp(e,t){let r=my(e),n=ja(e);if(e==="heave")return{meta:r,vehicle:n,components:{...uy(),heaveFront:{design:{...Zh,...q5},linkage:X5()}}};if(e!=="decoupled")return{meta:r,vehicle:n,components:uy()};let o=ly(n,t,"front",{heave:Fw(),roll:ww()}),a=ly(n,t,"rear",{heave:Fw(),roll:ww()});return{meta:r,vehicle:n,components:{arbFront:o.arb,arbRear:a.arb,heaveFront:o.heave,heaveRear:a.heave}}}function ja(e){let{name:t}=my(e);if(e==="direct")return{...Ui(),name:t};if(e==="mcpherson"){let n=Xi(),o=km();return{...n,front:{...o,config:{...o.config,loadedRadius:n.front.config.loadedRadius}},name:t}}let r=o3(Pw(e==="pullrod"?"pull":"push"));return{...e==="decoupled"?n3(r):r,name:t}}var Cw={front:221.7,rear:220.9};function o3(e){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:Cw.front}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:Cw.rear}}}}function my(e){let t=vp.find(r=>r.id===e);if(!t)throw new Error(`Unknown suspension template: ${e}`);return t}function Mp(){let e=t=>({design:{...J5},linkage:Z5(t),damper:e3});return{meta:my("heave"),vehicle:Pw("push",mg(),Q5),components:{...uy(),heaveFront:e("front"),heaveRear:e("rear")}}}var Lw=[10,25,50,100,200,300],a3=[{id:"c1",label:"Soft",scale:.7},{id:"c2",label:"Medium",scale:1},{id:"c3",label:"Firm",scale:1.4}],Dw=e=>Math.round(e*100)/100;function s3(e,t,r){let n=Lw.map(o=>Dw(r*o));return{id:e,label:t,speedMmS:[...Lw],bumpN:n,reboundN:[...n]}}function i3(e){return{name:e.name,body:{...e.body},curves:a3.map(t=>s3(t.id,t.label,Dw(e.coefficient*t.scale)))}}function Cc(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 fr(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:tc[e.dampers.length%tc.length],model:i3(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 lt=e=>`${e} (typical)`,py={car:{name:lt("Formula Student damper"),coefficient:2.5,body:{extended:249,stroke:55}}},Sp={car:py.car,heave:{name:lt("Formula Student heave damper"),coefficient:3.4,body:{extended:270,stroke:47}},roll:{name:lt("Formula Student roll damper"),coefficient:3.7,body:{extended:322,stroke:100}}},Ap={car:{name:lt("Formula 1 damper"),coefficient:6,body:{extended:240,stroke:40}},heave:{name:lt("Formula 1 heave damper"),coefficient:40,body:{extended:240,stroke:40}}},Ew={car:{name:lt("GT damper"),coefficient:4.5,body:{extended:510,stroke:80}}},dy={car:{name:lt("Sports car damper"),coefficient:2.4,body:{extended:515,stroke:110}}},Iw={car:{name:lt("Sports car strut"),coefficient:2.4,body:{extended:310,stroke:120}},rear:dy.car},_w={car:{name:lt("Cup car strut"),coefficient:4,body:{extended:285,stroke:75}},rear:{name:lt("Cup car rear damper"),coefficient:3.5,body:{extended:505,stroke:80}}},Nw={car:{name:lt("Stock car front damper"),coefficient:7.5,body:{extended:555,stroke:110}},rear:{name:lt("Stock car rear damper"),coefficient:6.75,body:{extended:555,stroke:110}}},Ow={car:{name:lt("Hill-climb front damper"),coefficient:3,body:{extended:285,stroke:65}},rear:{name:lt("Hill-climb rear damper"),coefficient:3.5,body:{extended:285,stroke:65}}},Vw={car:{name:lt("Race truck front damper"),coefficient:12,body:{extended:780,stroke:160}},rear:{name:lt("Race truck rear damper"),coefficient:8.5,body:{extended:780,stroke:160}}};function Xa(e){return e.vehicles=e.vehicles.slice(0,1),e.activeVehicleId=e.vehicles[0]?.id??null,e}function kn(e,t){let r=rc(e);return r.meta.rulesetId=t,r}function vo(e,t,r,n){let o=kn(e,t);return o.suspensions=[{...o.suspensions[0],model:n()}],o.vehicles=[Og(r,"v1",0)],o.activeVehicleId="v1",o}var[,c3,l3,u3,m3,p3,d3,f3]=xg;function fy(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 Bw(){return{...ja("decoupled"),name:lo().name}}var h3=[{label:"Formula Student (decoupled)",vehicle:Bw,components:e=>Cc(kp("decoupled",e).components,Sp)},{label:"Formula 1 (third springs)",vehicle:()=>Mp().vehicle,components:()=>Cc(Mp().components,Ap)}],hy={"direct-coilover":"direct",pushrod:"pushrod",pullrod:"pullrod","third-spring":"heave","mcpherson-strut":"mcpherson"},b3=[...h3.map(e=>e.vehicle),...Object.values(hy).map(e=>()=>ja(e))];function Ua(e){let t=Cc(kp("decoupled",e.vehicles[0].params).components,Sp);e.suspensions=[{...e.suspensions[0],model:Bw()}];for(let r of e.vehicles)fy(r.params,t);return fr(e,Sp),e}var ko={title:"OpenStreetMap",url:"https://www.openstreetmap.org/copyright",licence:"ODbL-1.0",credit:"\xA9 OpenStreetMap contributors"},Fp={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"},$w={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]"},Gw={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"},g3={id:"cota",name:"Circuit of the Americas, Austin",address:"e0c6ea889d708cf15f9c",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ko,Fp,Gw]}},y3={id:"laguna-seca",name:"Laguna Seca, Monterey",address:"185b5811b9c423ef44ef",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ko,Fp,Gw]}},x3={id:"nordschleife",name:"Nordschleife, N\xFCrburg",address:"74c49603c7b2f15985c6",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ko,$w]}},R3={id:"brands-hatch",name:"Brands Hatch, Kent",address:"c4953e3c25eaba4a5b7e",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ko,{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."}]}},v3={id:"bristol",name:"Bristol, Tennessee",address:"f0e23953669a414ad600",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ko,Fp]}},k3={id:"pikes-peak",name:"Pikes Peak, Colorado",address:"3de137fe33b5c2875036",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ko,Fp]},standingStart:!0},M3={source:"venue",altitudeM:3580,pressure:{kind:"standard"},humidityPct:0},S3=10,A3={id:"nurburg-sprint",name:"Sprintstrecke, N\xFCrburg",address:"1875636cdbb615aa2756",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ko,$w]}};function Mo(e,t){let{id:r,name:n,address:o,provenance:a,standingStart:s}=t,i={kind:"catalogue",id:r,address:o},c=qi(Tg({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 Mn(e,t,r){let n=e.vehicles[0].params,o=`m${e.motors.length+1}`;e.motors=[...e.motors,{id:o,color:yn[e.motors.length%yn.length],model:t}];let a=xk({},{...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 F3=3.8,wp={hubPlanetary:14.5,inboardChain:4,engineChain:3.4},w3="Hub motor, 35 kW (example)";function by(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 Kw(e){let t=e.motors.find(r=>r.id==="m1");return t.model={...t.model,name:w3},t.id}function Cp(e,t,r){let n=Xa(Ua(kn(e,r)));return n.vehicles[0].params.name=t,n}function C3(){let e=Cp("Formula Student combustion car","Formula Student combustion","fs-cv");Mn(e,Sg(),wp.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 T3(){let e=Cp("Formula Student AWD car","Formula Student AWD","fs-ev");return by(e,Kw(e),4,"awd",wp.hubPlanetary,"hub"),e}function P3(){let e=Cp("Formula Student RWD hub-motor car","Formula Student RWD hub motors","fs-ev");return by(e,Kw(e),2,"rear",wp.hubPlanetary,"hub"),e}function L3(){let e=Cp("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:yn[e.motors.length%yn.length],model:Mg()}],by(e,t,1,"rear",wp.inboardChain),e.vehicles[0].params.driveline={rear:structuredClone(xt.clutch)},e}function D3(){let e=Xa(Ua(kn("Formula Student endurance energy","fs-ev"))),t=e.vehicles[0],r=structuredClone(t);if(r.id="v2",r.color=ec[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 E3(){let e=Mp(),t=vo("Formula 1 car","trackday",c3,()=>e.vehicle);return fy(t.vehicles[0].params,Cc(e.components,Ap)),fr(t,Ap),Mn(t,Ag(),F3),Mo(t,g3)}function Hw(e="GT car",t=Ui){let r=vo(e,"trackday",l3,t);return fr(r,Ew),Mn(r,jS(),r.vehicles[0].params.gear_ratio.value),Mo(r,y3)}function zw(e="Sports car",t=Xi,r=dy){let n=vo(e,"trackday",u3,t);return fr(n,r),Mn(n,US(),n.vehicles[0].params.gear_ratio.value),Mo(n,x3)}function I3(){let e=vo("Cup car","trackday",m3,_S);return fr(e,_w),Mn(e,XS(),e.vehicles[0].params.gear_ratio.value),Mo(e,R3)}function _3(){let e=vo("Stock car","trackday",p3,NS);return fr(e,Nw),Mn(e,qS(),e.vehicles[0].params.gear_ratio.value),Mo(e,v3)}function N3(){let e=vo("Hill-climb prototype","trackday",d3,OS);return fr(e,Ow),Mn(e,QS(),e.vehicles[0].params.gear_ratio.value),e.settings.air=structuredClone(M3),e.settings.airTempC=S3,Mo(e,k3)}function O3(){let e=vo("Race truck","trackday",f3,VS);return fr(e,Vw),Mn(e,ZS(),e.vehicles[0].params.gear_ratio.value),Mo(e,A3)}function V3(e){let t=vp.find(o=>o.id===e);if(e==="direct")return Hw(t.name,()=>ja(e));if(e==="mcpherson")return zw(t.name,()=>ja(e),Iw);let r=Xa(kn(t.name,"trackday")),n=kp(e,r.vehicles[0].params);return r.suspensions=[{...r.suspensions[0],model:n.vehicle}],fy(r.vehicles[0].params,n.components),fr(r,py),r}function Tc(e,t,r){let n=hy[e],o=vp.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:()=>V3(n)}}var B3=[{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:()=>Ua(kn("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:D3},{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:()=>Xa(Ua(kn("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:C3},{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:T3},{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:P3},{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:L3},{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:E3},{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:Hw},{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:zw},{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:I3},{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:_3},{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:N3},{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:O3},{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:()=>Xa(Ua(kn("Suspension study","trackday")))},Tc("direct-coilover","The GT car\u2019s wishbones driving coilovers straight into the towers, at Laguna Seca.","On the GT car, at Laguna Seca."),Tc("pushrod","The FS car on pushrods: a rod from each lower wishbone works a rocker.","On the Formula Student car, at FSG."),Tc("pullrod","The FS car on pullrods: a rod from each upper wishbone pulls a low rocker.","On the Formula Student car, at FSG."),Tc("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."),Tc("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:()=>Xa(Ua(kn("Tyre study","fs-ev")))}],Yw=B3.map(e=>({...e,load:()=>Vg(e.load())}));var Ww={width:320,height:200},fye=[.6*Ww.width-9,.6*Ww.height-9];var jw=new WeakMap,Uw=new WeakMap,gy=e=>JSON.stringify(e,(t,r)=>r===1/0?"Infinity":r);function Xw(e,t){if(!t){let a=jw.get(e);return a||(a=Ct(e),jw.set(e,a)),a}let r=Uw.get(e);r||(r=new Map,Uw.set(e,r));let n=gy(t),o=r.get(n);return o||(r.size>=4&&r.clear(),o=Ct(e,t),r.set(n,o)),o}var K3=Math.PI/180,H3=e=>e>1?e/100:e;function Pc(e){let t=null;return()=>(t??={v:e()}).v}function qw(e){let t=Ge(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 Qw=new WeakMap,yy={heave:0,pitch:0,roll:0,steer:0},Zw=[0,1,2,3,4],Jw=[-20,-10,0,10,20];function tC(e,t){let r=_r(e,yy),n=["front","rear"],o=c=>{let l=pi(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 Zw){let l=c===0?null:_r(e,{...yy,roll:c*K3});n.forEach((u,m)=>{let f=l?pi(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 Jw){let l=c===0?null:_r(e,{...yy,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:Zw,rcFront:s[0].rc,rcRear:s[1].rc,rcSplitFront:s[0].split,rcSplitRear:s[1].split},heave:{drop:Jw,rcFront:i[0],rcRear:i[1]}}}var eC=new WeakMap;function z3(e,t,r,n){let o=eC.get(e);o||(o=new Map,eC.set(e,o));let a=`${gy(r)}|${n[0]}|${n[1]}`,s=o.get(a);if(!s){o.size>=4&&o.clear();try{s=tC(Xw(e,r),n)}catch{s=t.rigidMigration(n)}o.set(a,s)}return s}function Y3(e){let t=Qw.get(e);if(t)return t;let r=Ct(e),n=_r(r,{heave:0,pitch:0,roll:0,steer:0}),o=qw(e.front),a=qw(e.rear),s={wheelbase:e.config.wheelbase,trackFront:bt(e.front),trackRear:bt(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:ba(n.front),rcGainRear:ba(n.rear),rigidMigration:i=>tC(r,i),kinFront:Pc(()=>ea(e.front)),kinRear:Pc(()=>ea(e.rear))};return Qw.set(e,s),s}function rC(e,t,r,n){let o=Y3(e),a=Wn(e,t),s=ga(e,t),i=mk(e,t),c=ku(e,t),l=pk(e,t),u=fk(t),m=dk(e,t),f=Yn(e.front),p=Yn(e.rear),d=zn(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=H3(t.front_mass_diss.value),y=xa(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),C=(r?R.verticalStiffness():0)||Q(t,"tire_vertical_rate"),T=(v?k.verticalStiffness():0)||Q(t,"tire_vertical_rate"),S=tr(r)??0,A=tr(v)??0,P=wu({freeRadius:S,staticLoad:x,tyreRate:C,surveyed:e.front.config.loadedRadius},{freeRadius:A,staticLoad:M,tyreRate:T,surveyed:e.rear.config.loadedRadius},g),L=$t(S,x,C,e.front.config.loadedRadius),D=$t(A,M,T,e.rear.config.loadedRadius),E=[Nr(o.rcHeightFront,o.rcGainFront,e.front.config.loadedRadius,L),Nr(o.rcHeightRear,o.rcGainRear,e.rear.config.loadedRadius,D)],V=Pc(()=>gi(o.kinFront(),Q(t,"camber_front_deg"))),N=Pc(()=>gi(o.kinRear(),Q(t,"camber_rear_deg"))),z=Pc(()=>z3(e,o,$a(B),E)),I=Ws({...t,wheelbase:{...t.wheelbase,value:o.wheelbase}}),_=bi(t),B={massTotal:t.m.value,frontMassFrac:g,steeringSystem:t.steeringSystem,tv:uu(t),cgHeight:ya(Q(t,"cg_height"),t.cgReference?.standingRadius,P),cgStandingRadius:P,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: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:I.balanceFront,brakes:I,..._?{driveline:_}:{},heaveSpringFront:s.front??Q(t,"heave_spring_front"),heaveSpringRear:s.rear??Q(t,"heave_spring_rear"),unsprungPerCorner:Q(t,"unsprung_mass"),unsprungCgHeight:$t(S,x,C,o.unsprungCgHeight),tyreFreeRadius:S,...A!==S?{tyreFreeRadiusRear:A}:{},rcHeightFront:E[0],rcHeightRear:E[1],corneringStiffnessFront:F,corneringStiffnessRear:w,get kinFront(){return V()},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 Mu(e.front,L)},ackermannPct:Q(t,"ackermann_pct"),toeFrontDeg:Q(t,"toe_front_deg"),toeRearDeg:Q(t,"toe_rear_deg")};return B}var oC=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}),Ry={ggvMode:"twoTrack"},nC=new WeakMap;function vy(e,t=Ry){let r=nC.get(e.vehicle);r||nC.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={...oC(e.params),suspensionOf:()=>e.vehicle};n.set(o,a=Ro(e.params,s,t))}return a}var aC=(e=Ry)=>t=>vy(t,e),sC=(e=Ry)=>t=>rC(t.vehicle,oy(t.params,oC(t.params),e),t.params.tireModel,t.params.tireModelRear);function W3(e,t){return vy(e,t.switches)}var ky=e=>zr(e?.rulesets);function iC(e,t,r,n,o={},a=()=>r.standingStart){let s=vy(n,r.switches),i=(l,u)=>{let m=hm(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 cC=e=>[...new Set(e.lap.courses.flatMap(t=>t.course.kind==="track"?[t.course.trackId]:[]))],lC=e=>{let t=e?.session;return t?{sessionParams:r=>W3(r,t),session:()=>t}:{}},Tp=e=>({metrics:ky(e),assemble:sC(e?.switches),simParams:aC(e?.switches),projectTrack:()=>e?.course??null,libraryTrack:t=>e?.tracks?.[t]??null,numerics:e?.numerics,...lC(e)}),j3=(e,t)=>({density:e.density,envelope:e.envelope,states:e.states,operating:e.operating,lap:e.lap,assemble:sC(t?.switches),simParams:aC(t?.switches),projectTrack:()=>t?.course??null,libraryTrack:r=>t?.tracks?.[r]??null,numerics:t?.numerics,...lC(t)}),uC="nelder-mead",mC=600,Lc=[0,.15,.15];function pC(e,t,r,n=Lc.length){let o=Ay(t);return Lc.slice(0,Math.max(1,n)).map((a,s)=>({...e,seed:s+1,startJitter:a,car:o,...r?{lap:r}:{}}))}function dC(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 fC(e,t,r,n,o=.01){let a=ky(n).byId;return U3(e,t,r,n).filter(s=>s.excess>-o*(a[s.metricId]?.scale??1))}function U3(e,t,r,n){let o;try{o=xn(pp(e,t,r),j3(t,n))}catch{return[]}return X3(o,t,ky(n))}function X3(e,t,r){let n=[];for(let o of t.constraints){let a=r.byId[o.metricId];if(!a)continue;let s=Lt(e,a,o.at);if(!Number.isFinite(s))continue;let i=`${et(a)}${Sc(o.at,a)}`;n.push({key:o.key,metricId:o.metricId,label:i,unit:a.unit==="-"?"":a.unit,value:s,excess:Mc(o,s)})}return n}var q3=.05;function Q3(e,t){if(t.id.startsWith("hp.")||lp(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 _0(vn(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 D0(Yr(o.hardpoints,n[2]),n[3],1)}function hC(e,t,r){let n=r.filter(f=>f.score.feasible);if(n.length<2)return null;let o=t.map(f=>Q3(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(q3,m),unit:a}}var Z3={steeringSystem:!0,brakeSetup:!0,driveline:!0,heaveFrontDesign:!0,heaveRearDesign:!0,arbFrontDesign:!0,arbRearDesign:!0},bC=e=>Object.hasOwn(Z3,e);function xy(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 J3(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":bC(t)||xy(e)?"block":null}function My(e,t){t=Dt(e,t);let r=Gt(e);return[...t.variables,...t.followers??[]].filter(n=>r[n.id]&&!r[n.id].supersededBy&&!J3(n.id)).map(n=>ct(r[n.id]))}function gC(e,t,r){t=Dt(e,t);let n=Gt(e),o=pp(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[bo.fore,bo.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=jt[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"&&dr(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:ct(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(bC(m)||xy(c.id)){let h=xy(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 Sy(e){let t=performance.now(),r=Tp(e.lap),n=e.follow?W0(e.car,e.spec,r):e.spec,{dead:o,unprobed:a,...s}=q0(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 Ay=e=>e.vehicle.chassis?{...e,vehicle:sy(e.vehicle)}:e;function yC(e,t){try{let r=Fy(e.car,e.spec,e.lap),n=na.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:Mr(r.variables),score:kr(r,Mr(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&&B0(r.variables)?G0(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 Fy=(e,t,r)=>dp(e,t,Tp(r));function xC(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),...si(e,t.damper)}}function RC(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 vC=e=>({ggvMode:e.ggvMode,quasiTransient:e.quasiTransient===!0&&e.ggvMode!=="fast",motorThermal:e.motorThermal===!0,...XF({brakeFade:e.brakeFade===!0,airTempC:e.airTempC,diffYaw:e.diffYaw===!0,...e.air?{air:e.air}:{}})});function eB(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 kC(e,t){let r=t.plannedPath!==void 0,n=eB(t);return{...iC(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 wy(e,t){let r=e.vehicles.find(o=>o.id===t);if(!r)throw new Error(`this project holds no vehicle "${t}"`);let n=xo(e);return RC(structuredClone(ny(e,r.params)),structuredClone(r.params),xC(r.params,n))}var tB="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 Cy(e,t,r,n){if(e.settings.pathPlanId)throw new Error(tB);let o=Wa(e),a=e.tracks.length?(await bp(e,t)).asset:null,s={};for(let i of n?cC(n):[]){let c=e.tracks.find(l=>l.id===i);c&&(s[i]=await Fc(c,t))}return kC(r,{track:a,numerics:o.numerics,racingLine:o.racingLine,standingStart:o.standingStart,lapCounts:o.lapCounts??{},switches:vC(o),rulesets:e.rulesets??[],library:s,standingOf:i=>e.tracks.find(c=>c.id===i)?.standingStart===!0})}async function MC(e,t,r,n){let o=wy(e,r),a=Dt(o,n),s=await Cy(e,t,o,a);return Sy({id:0,car:o,spec:a,lap:s})}async function SC(e,t,r,n){let o=wy(e,r),a=Dt(o,n),s=My(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 Cy(e,t,o,a)}catch(l){return{problems:[l instanceof Error?l.message:String(l)]}}let c=X0(o,a,{...Tp(i),metrics:zr(e.rulesets)});return c.length?{problems:c}:{problems:[],msPerEval:Sy({id:0,car:o,spec:a,lap:i}).msPerEval,carFingerprint:ro(Ay(o))}}async function rB(e,t,r,n,o,a=[]){let s=pC(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(yC(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 AC(e,t,r,n){let o=wy(e,r.vehicleId),a=Dt(o,r.spec),s=My(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 Cy(e,t,o,a),c=r.method??uC;if(!na.some(b=>b.name===c))throw new Error(`unknown method "${c}" \u2014 it is one of ${na.map(b=>b.name).join(", ")}`);let l=r.budget??mC,u=Math.max(1,Math.min(r.seeds??Lc.length,Lc.length)),m=await rB(o,{spec:a,method:c,budget:l},i,u,n),f=Fy(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:dC(f.variables,b.x),constraints:fC(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}}:{}})),d=m.runs.reduce((b,g)=>_s(g.score,b.score)?g:b),h=d.snapped?.score.feasible?d.snapped:null;return{method:c,budget:l,seeds:p,spread:m.runs.length>1?hC(o,f.variables,m.runs.map(b=>({x:b.x,score:b.score}))):null,writes:gC(o,a,h?h.x:d.x),...d.snapped?{adopts:h?"on its steps":`as found: on its steps it breaks a hold (${d.snapped.score.reason??"not legal"})`}:{}}}function wC(){if(typeof process.threadCpuUsage!="function")return performance.now();let e=process.threadCpuUsage();return(e.user+e.system)/1e3}async function oB(e,t){let r=YF(e.root);switch(e.kind){case"sweep":return ow(e.doc,r,e.req,t);case"convergence":return rw(e.doc,r,{vehicleId:e.vehicleId,...e.steps?{steps:e.steps}:{},...e.tolPct!==void 0?{tolPct:e.tolPct}:{},onStep:t});case"study":return AC(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 gp(e.doc,r,{...e.vehicleIds?{vehicleIds:e.vehicleIds}:{},...e.settings?{settings:e.settings}:{},...e.overrides?{overrides:e.overrides}:{}});case"probe":return MC(e.doc,r,e.vehicleId,e.spec);case"quote":return SC(e.doc,r,e.vehicleId,e.spec)}}if(FC){let e=FC,t=r=>e.postMessage(r);(async()=>{try{let r=await oB(nB,(n,o)=>t({type:"progress",done:n,total:o}));t({type:"done",result:r,cpuMs:wC()})}catch(r){t({type:"failed",message:r instanceof Error?r.message:String(r),cpuMs:wC()})}})()}export{oB as runJob,wC as threadCpuMs};
|
|
226
|
+
`)),this.name="RulesetDefError",this.problems=r}},zi=e=>typeof e=="number"&&Number.isFinite(e),Hi=e=>zi(e)&&e>0,Pt=(e,t)=>e===void 0||t(e);function c_(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":Hi(a.distance)||r(`${s} needs a distance above zero, in metres`),Pt(a.vStart,i=>zi(i)&&i>=0)||r(`${s}'s entry speed must be zero or more`);break;case"constantRadius":Hi(a.radius)||r(`${s} needs a radius above zero, in metres`),Pt(a.laps,i=>zi(i)&&i>=1)||r(`${s} runs at least one lap`);break;case"trackLap":Pt(a.laps,i=>zi(i)&&i>=1)||r(`${s} runs at least one lap`),Pt(a.distance,Hi)||r(`${s}'s distance must be above zero, in metres`),Pt(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),Pt(a.unit,i=>typeof i=="string")||r("Its unit is text",s),Pt(a.over,i=>typeof i=="string")||r("Names its event by id",s),Pt(a.format,i=>i==="time"||i==="points")||r("Is shown as a time, as points, or as a number",s),Pt(a.max,zi)||r("Its maximum is a number",s),Pt(a.lowerBetter,i=>typeof i=="boolean")||r("Lower is better, or it is not",s),Pt(a.hidden,i=>typeof i=="boolean")||r("Is hidden, or it is not",s)}Pt(e.track?.minTurnRadius,Hi)||r("The tightest turn the rules allow is a radius above zero");let n=e.battery;for(let o of["packVoltageMax","segmentVoltageMax","powerLimitKw"])Pt(n?.[o],Hi)||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 DS(e){let t=c_(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}=dm(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 hm(e){return DS(e).problems}var tg=e=>Number.isFinite(e)?e:NaN;function l_(e){return e.unit&&e.format!=="time"?`${e.label} (${e.unit})`:e.label}function Rn(e){let t=structuredClone(e),{plan:r,problems:n}=DS(t);if(!r)throw new fm(t.id,n);let o=new WeakMap,a=p=>{let d=o.get(p);return d||(d=eg(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 tg(b);let g=h,y=i.get(p);return y!==void 0?tg(g.parts?.[y]):p===t.score?.total?tg(g.total):NaN},l=t.kpis.filter(p=>!p.hidden).map(p=>{let d=r.field.has(p.key);return{key:p.key,label:l_(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=Ki(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=Ki(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 Ut={accel:"accel",skidpad:"skidpad",autocross:"autocross",endurance:"endurance"},ES=[{kind:"straightLineAccel",id:Ut.accel,label:"Acceleration (75 m)",distance:75},{kind:"constantRadius",id:Ut.skidpad,label:"Skidpad",radius:8.375},{kind:"trackLap",id:Ut.autocross,label:"Autocross (1 lap)",laps:1},{kind:"trackLap",id:Ut.endurance,label:"Endurance (22 km)",distance:22e3}],IS=[{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"}],_S={total:"overall",parts:{[Ut.accel]:"accelPts",[Ut.skidpad]:"skidpadPts",[Ut.autocross]:"autocrossPts",[Ut.endurance]:"endurancePts",efficiency:"efficiencyPts"}},NS={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:ES,kpis:IS,score:_S,track:{minTurnRadius:4.5},battery:qy,traceEventId:Ut.autocross},OS={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:ES,kpis:IS,score:_S,track:{minTurnRadius:4.5},traceEventId:Ut.autocross},Yi=Rn(NS),rg=Rn(OS);var ng="lap",u_=[{kind:"trackLap",id:ng,label:mm,laps:1}],VS={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:ng,expr:"peak(speed)"},{key:"energy",label:"Energy / lap",unit:"kWh",lowerBetter:!0,expr:"lap.energy"}],traceEventId:ng},og=Rn(VS);function vn(e){if(e===null||typeof e!="object")return JSON.stringify(e)??"null";if(Array.isArray(e))return`[${e.map(vn).join(",")}]`;let t=e,r=Object.keys(t).sort(),n=[];for(let o of r)t[o]!==void 0&&n.push(`${JSON.stringify(o)}:${vn(t[o])}`);return`{${n.join(",")}}`}function co(e){let t=vn(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 Na=[Yi,rg,og],lo=Yi.id,Oa=e=>Na.some(t=>t.id===e),BS=new WeakMap,Wi=new Map,m_=64;function bm(e){let t=BS.get(e);if(t!==void 0)return t;let r=vn(e),n=Wi.get(r);return n===void 0&&(n=hm(e).length?null:Rn(e),Wi.size>=m_&&Wi.delete(Wi.keys().next().value),Wi.set(r,n)),BS.set(e,n),n}function gm(e,t=[]){if(e==null)return;if(typeof e!="string")return bm(e)??void 0;let r=Na.find(o=>o.id===e);if(r)return r;let n=t.find(o=>o.id===e);return n?bm(n)??void 0:void 0}function uo(e,t=[]){return gm(e,t)??Yi}function ag(e=[]){let t=e.filter(r=>!Oa(r.id)).map(r=>bm(r)).filter(r=>r!==null);return[...Na,...t]}var ji=e=>e.definition??e.id;function ym(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=p_(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 ig(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=sg(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 p_(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=sg(e,c,r,n),u=new Array(o).fill(0);u[0]=i,u[o-1]=s;let m=sg(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 sg(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 Ui(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 $S(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 GS(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 KS(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=>$S(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=GS([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 d_(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=$S(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 f_(e,t,r){let{j:n,t:o}=d_(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=GS([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 cg(e,t){return t>0?e.z.map((r,n)=>{let o=f_(e,n,t/2);return o?o.value.reduce((a,s,i)=>a+s*e.z[o.j[i]],0):r}):[...e.z]}function h_(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 xm(e){let t=Ui(e);if(!t)return 0;let r=KS(t);return r>1e-6?Math.max(10,h_(r,b_(t))):0}function b_(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 hr(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 vm(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 HS(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 Rm(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 g_(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 lg(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=HS(r,(y,R)=>hr(e,y,R));if(!b)return null;let g=Rm(b,t);return g.every(Number.isFinite)?g:null}let n=r-2,a=HS(n,(b,g)=>hr(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]=hr(e,b,r-2),i[b]=hr(e,b,r-1);let c=Rm(a,t.slice(0,n)),l=Rm(a,s),u=Rm(a,i),m=(b,g)=>{let y=0;for(let R=0;R<b.length;R++)y+=b[R]*g[R];return y},f=[[hr(e,r-2,r-2)-m(s,l),hr(e,r-2,r-1)-m(s,u)],[hr(e,r-1,r-2)-m(i,l),hr(e,r-1,r-1)-m(i,u)]],p=[t[r-2]-m(s,c),t[r-1]-m(i,c)],d=g_(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 zS(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=lg(i,t);if(c){let l=vm(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 YS=4,y_=8,ug=.001;function x_(e,t,r){let n=[];for(let c=1;c<e.length;c++){let l=e[c]-e[c-1];l>=ug&&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/eM(r,s,i)))}function R_(e,t){let r=e.closed!==!1,n=[],o=[],a=(F,w)=>{let C=n.length-1;C>=0&&Math.hypot(F-n[C],w-o[C])<ug||(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:x_(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 C=c[p+1]-c[p],T=C>0?(w-c[p])/C:0,S=(p+1)%s;a(e.x[p]+T*(e.x[S]-e.x[p]),e.y[p]+T*(e.y[S]-e.y[p]))}if(r)for(;n.length>2&&Math.hypot(n[n.length-1]-n[0],o[o.length-1]-o[0])<ug;)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,C=n[w]-n[F-1],T=o[w]-o[F-1],S=Math.sqrt(Math.hypot(C,T))||1e-9;b[F]=b[F-1]+S}let g=r?ym(b.slice(0,d),n,b[d]):ig(b,n),y=r?ym(b.slice(0,d),o,b[d]):ig(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]/YS;for(let C=0;C<YS;C++){let T=C*w;M+=hh(S=>Math.hypot(g.d1(F,S),y.d1(F,S)),T,T+w),k.push(M),v.push(F),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 Xi(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 v_=.01,k_=3,WS=10;function M_(e,t,r,n=WS){let o={step:0,uncertainty:1/0},a=e.length;if(a<8||!(r>0))return o;let s=Math.max(WS,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=Jt(d,h),g=Jt(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 S_(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 A_(e,t,r){let{pos:n,loop:o}=S_(e.length,t),{step:a,uncertainty:s}=M_(e,n,o,r);return Math.abs(a)>Math.max(v_,k_*s)?{z:e.map((i,c)=>i+a*n[c]/o),drift:-a}:{z:e,drift:0}}function F_(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+hh(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 w_=3,mg=5;function C_(e,t,r,n=mg){return Mm(e,t,r,n)}function Mm(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 lg({n:a,diag:i,off1:c,off2:l,closed:r},u)??[...e]}function it(e,t){let r=st(t),n=R_(e,r.fitSpacing),o=n.length,a=Math.max(y_,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 C=0;C<s;C++){let T=C*i,{seg:S,du:A}=F_(n,T);c[C]=n.sx.eval(S,A),l[C]=n.sy.eval(S,A),u[C]=T;let P=n.sx.d1(S,A),L=n.sy.d1(S,A),D=n.sx.d2(S,A),E=n.sy.d2(S,A),V=Math.hypot(P,L),N=Math.pow(P*P+L*L,1.5);f[C]=N>0?(P*E-L*D)/N:0,p[C]=V>0?-L/V:0,d[C]=V>0?P/V: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?A_(e.z,n.rawCum,g):null,R=y?y.z:e.z,k=g>0?Ui(e):null,v=k?cg({...k,z:R},g):R,x=Xi(v,0,h,n),M=new Array(s).fill(0);if(b){for(let T=0;T<s;T++){let S=n.closed?(T+1)%s:Math.min(T+1,s-1),A=n.closed?(T-1+s)%s:Math.max(T-1,0),P=n.closed?2:S-A,L=x[S]-x[A];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 S=n.closed?(T+1)%s:T+1,A=x[S]-x[T];m[T]=Math.hypot(i,A)}let C=0;for(let T=0;T<s;T++)u[T]=C,C+=m[T]}let F=b?m.reduce((C,T)=>C+T,0):o,w;if(b){w=new Array(s).fill(0);let C=Math.max(w_,e.zReach??xm(e)),T=Math.max(2,Math.round(C/i));if(n.closed?s>2*T:s>2*T+1){let S=0,A=0;for(let D=-T;D<=T;D++)S+=D*D,A+=D*D*D*D;let P=2*T+1,L=A-S*S/P;for(let D=0;D<s;D++){let E=n.closed?D:Math.min(Math.max(D,T),s-1-T),V=0,N=0;for(let _=-T;_<=T;_++){let B=x[n.closed?(E+_+s)%s:E+_];V+=(_*_-S/P)*B,N+=_*B}let z=2*V/L/(i*i),I=N/S/i;w[D]=z/Math.pow(1+I*I,1.5)}}}return{name:e.name,closed:n.closed,x:c,y:l,s:u,ds:m,curvature:e.turnReach?C_(f,i,n.closed,e.turnReach):f,npts:s,length:F,nx:p,ny:d,z:x,gradient:M,...w?{verticalCurvature:w}:{},widthLeft:Xi(e.widthLeft,1.5,h,n),widthRight:Xi(e.widthRight,1.5,h,n),bank:Xi(e.bank,0,h,n),mu:Xi(e.mu,1,h,n),...y?.drift?{elevationDrift:y.drift}:{}}}function jS(e,t,r){let n=vm(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 T_(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]-=hr(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 zS(c,i)}var P_=1e-4;function US(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=jS(e,t,u),f=new Array(a).fill("free"),p=!1;for(let d=0;d<s;d++){let h=vm(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=T_(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 C=F+R*(g[w]-F),T=l(C,w);return T!==C&&(k=!0),T}),x=jS(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+P_*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 pg={lineStep:2,carHalfWidth:.75,margin:.1,foldMargin:.25,referenceReach:5,passes:40,iterations:400},L_=[1,.5,.25,.125,.0625,.03125,.015625,.0078125,.00390625,.001953125,.0009765625],D_=e=>Math.sqrt(e.reduce((t,r)=>t+r*r,0)/(e.length||1));function qi(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 E_=Math.PI/180,XS=20;function I_(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?XS:Math.min(XS,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 __(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?I_(t,r):t.z;return{...n||o?{z:s.map((i,c)=>i+r[c]*Math.tan(t.bank[c]*E_))}:{},...n?{zReach:e.zReach??xm(e)}:{},...o?{bank:[...t.bank]}:{},...a?{mu:[...t.mu]}:{}}}function qS(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 N_(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,C=(b*r[u]+g*n[u])/k,T=(f*r[l]+p*n[l])/y,S=(d*r[l]+h*n[l])/R,A=(d*r[m]+h*n[m])/R,P=(b*r[m]+g*n[m])/k,L=-2*c(r[u],n[u],d,h)/v+x*(w/y+C/k),D=2*c(r[l],n[l],b,g)/v-x*(T/y-S/R),E=2*c(f,p,r[m],n[m])/v-x*(A/R+P/k);s[l]=x*M,i.l[l]=M*L-F*.5*w,i.d[l]=M*D+F*.5*(T-S),i.r[l]=M*E+F*.5*A}return{res:s,jac:i}}function O_(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 V_(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=Mm(e.x,s,n,t,!0),c=Mm(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=qi(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 B_=6;function $_(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(B_/(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 dg(e,t={}){let r={...pg,...t},n=it(e,{dsTarget:r.lineStep}),o=V_(n,r.referenceReach),a=o.npts,s=T=>({x:o.x.map((S,A)=>S+o.nx[A]*T[A]),y:o.y.map((S,A)=>S+o.ny[A]*T[A])}),i=T=>{let S=qi(T.x,T.y,o.closed),A=qS(T.x,T.y,o.closed),P=0;for(let L=0;L<S.length;L++)P+=S[L]*S[L]*A[L];return P},c=D_(n.curvature),l=qS(n.x,n.y,n.closed).reduce((T,S)=>T+S,0),u=new Array(a).fill(0),m=r.carHalfWidth+r.margin,f=new Array(a),p=new Array(a),d=0;for(let T=0;T<a;T++){let S=o.widthLeft[T]-m,A=-(o.widthRight[T]-m);if(S<A){d++;let P=(o.widthLeft[T]-o.widthRight[T])/2;f[T]=P,p[T]=P}else f[T]=S,p[T]=A}let h=[...f],b=[...p];$_(o,f,p,r.foldMargin);let g=T=>{let S=s(T),A=__(e,o,T),P={name:`${e.name} \u2014 racing line`,x:S.x,y:S.y,closed:o.closed,widthLeft:h.map((I,_)=>Math.max(0,I-T[_])),widthRight:b.map((I,_)=>Math.max(0,T[_]-I)),...A,fit:"interpolate",turnReach:mg},L=1e-6,D=T.filter((I,_)=>I>=f[_]-L||I<=p[_]+L).length,E=qi(S.x,S.y,o.closed),V=I=>1/Math.max(...I.map(Math.abs),1e-9),N=0,z=o.closed?S.x.length:S.x.length-1;for(let I=0;I<z;I++){let _=(I+1)%S.x.length,B=S.x[_]-S.x[I],O=S.y[_]-S.y[I];N+=A.z?Math.hypot(B,O,A.z[_]-A.z[I]):Math.hypot(B,O)}return{offset:T,s:[...o.s],asset:P,curvatureRms:{centreLine:c,racingLine:Math.sqrt(i(S)/(l||1))},infeasibleSamples:d,atBoundary:a?D/a:0,length:{centreLine:n.length,racingLine:N},worstRadius:{centreLine:V(n.curvature),racingLine:V(E)}}},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]=f[y+T];if(!o.closed&&k>0){let T=(S,A)=>{if(v[S]=Math.max(v[S],p[A]),x[S]=Math.min(x[S],f[A]),v[S]>x[S]){let P=.5*(v[S]+x[S]);v[S]=P,x[S]=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 S=s(T),P=[...qi(S.x,S.y,o.closed).map(Math.abs)].sort((L,D)=>L-D);return{integral:i(S),tail:P[Math.floor(.99*(P.length-1))]}},F=[...u],w=M(u),C;for(let T=0;T<r.passes;T++){let S=s(F),{res:A,jac:P}=N_(S.x,S.y,o.nx,o.ny,o.closed),{M:L,b:D}=O_(P,A,y,R,o.closed),E=US(L,D,v.map((z,I)=>z-F[y+I]),x.map((z,I)=>z-F[y+I]),{maxIter:r.iterations,bounds:C});C=E.bounds;let V=new Array(a).fill(0);for(let z=0;z<k;z++)V[y+z]=E.x[z];o.closed||(V[0]=V[1],V[a-1]=V[a-2]);let N=!1;for(let z of L_){let I=F.map((B,O)=>B+z*V[O]),_=M(I);if(_.integral<w.integral*(1-1e-6)){F=I,w=_,N=!0;break}}if(!N)break}return g(F)}function fg(e){let t=Math.max(Q(e,"track_front"),Q(e,"track_rear"));return(t>0?t/2e3:.6)+.1}function Sm(e,t,r={}){if(!r.racingLine)return{asset:e,numerics:t,line:null};let n=r.params?fg(r.params):void 0,o=dg(e,{...r.line,...n?{carHalfWidth:n}:{}});return{asset:o.asset,numerics:{...t,fitSpacing:0},line:o}}function Qi(e,t,r={}){let n=Sm(e,t,r);return{track:it(n.asset,n.numerics),line:n.line}}function hg(e=4,t=Qi){let r=new WeakMap;return(n,o,a={})=>{let s=a.racingLine===!0,i=s?[a.params?fg(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 QS={racingLine:!1,standingStart:!1},Am=256;function Zi(e,t,r,n,o=QS,a=Qi){let s=uo(n),{racingLine:i,standingStart:c,lapCounts:l}=o;return e.map(u=>{let{track:m}=a(t,r,{racingLine:i,params:u});return Xb(Vi(u,s,{track:m,numerics:r,standingStart:c,lapCounts:l}))})}function bg(e,t){let r=uo(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 gg(e,t,r){let n={};for(let o of uo(e).metrics)n[o.key]=o.value(t,r);return n}var Fm=36;var Rg=287.05287,K_=461.495,wm=9.80665/(Rg*.0065),H_=101325/(Rg*288.15),z_=273.15,Y_=-500,W_=6e3,j_=400,U_=1100,Cm={source:"car",altitudeM:0,pressure:{kind:"standard"},humidityPct:0};function X_(e){return 101325*Math.pow(1-.0065*e/288.15,wm)}function q_(e){return 288.15/.0065*(1-Math.pow(e/H_,1/(wm-1)))}function Q_(e){return 288.15/.0065*(1-Math.pow(e/101325,1/wm))}function Z_(e,t){return e*Math.pow(1-.0065*t/288.15,wm)}function J_(e){return 611.21*Math.exp((18.678-e/234.5)*(e/(257.14+e)))}function eN(e,t){switch(e.kind){case"standard":return X_(t);case"qnh":return Z_(e.hPa*100,t);case"station":return e.hPa*100}}function Ji(e,t,r=0,n=Q_(e)){let o=t+z_,a=Math.min(.5*e,Math.max(0,Math.min(100,r))/100*J_(t)),s=e-a,i=s/(Rg*o)+a/(K_*o);return{altitudeM:n,p:e,pDry:s,T:o,rho:i,densityAltitudeM:q_(i)}}function ZS(e,t){return Ji(eN(e.pressure,e.altitudeM),t,e.humidityPct,e.altitudeM)}var yg=(e,t,r)=>Math.min(r,Math.max(t,e)),xg=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function Tm(e){if(!e||typeof e!="object")return structuredClone(Cm);let t=e,r=t.pressure??{},n=yg(xg(r.hPa,1013.25),j_,U_),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:yg(xg(t.altitudeM,0),Y_,W_),pressure:o,humidityPct:yg(xg(t.humidityPct,0),0,100)}}var ec=e=>e?.source==="venue";var tN=Math.PI/180;function rN(){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 nN(){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 vg(e){let t=-e*tN;return q([0,Math.cos(t),Math.sin(t)])}function Pm(){let e={rodType:"push",pushrodAttach:"lowerArm",steerMode:"rack",spinAxis:vg(-1),loadedRadius:230,springRate:35,rackAxis:[0,1,0]};return{hardpoints:rN(),config:e}}function tc(){let e={rodType:"pull",pushrodAttach:"lowerArm",steerMode:"fixed",spinAxis:vg(-1.5),loadedRadius:232,springRate:40,rackAxis:[0,1,0]};return{hardpoints:nN(),config:e}}function Lm(){let e=[-25,635,460],t=[-40,600,710],r={layout:"mcpherson",actuation:"direct",rodType:"push",pushrodAttach:"upright",steerMode:"rack",spinAxis:vg(-.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 kg(){return{front:Pm(),rear:tc(),config:{wheelbase:1600,trackFront:1200,trackRear:1220,frontAxleX:800}}}var oN=Math.PI/180;function JS(e){let t=-e*oN;return q([0,Math.cos(t),Math.sin(t)])}function Mg(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:JS(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]=aN(o[l]);return{hardpoints:o,config:c}}function aN(e){return e.map(t=>Math.round(t*10)/10+0)}function po(e){return{name:e.name,front:Mg(Pm(),e.front),rear:Mg(tc(),e.rear),config:{wheelbase:e.wheelbase,trackFront:e.trackFront,trackRear:e.trackRear,frontAxleX:e.wheelbase/2}}}function Va(e,t,r){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:t}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:r}}}}var Ba=600,fo=610,$a=230,ho=232;function bo(){let e=kg();return{...e,name:"Formula Student",front:{...e.front,config:{...e.front.config,actuation:"rocker"}},rear:{...e.rear,config:{...e.rear.config,actuation:"rocker"}}}}function Sg(){return po({name:"Formula 1",wheelbase:3600,trackFront:1600,trackRear:1600,front:{kx:1.3,ky:800/Ba,kz:355/$a,lowerInnerDz:-5,upperInnerDz:0,camberDeg:-3,loadedRadius:355,springRate:200},rear:{kx:1.3,ky:800/fo,kz:355/ho,lowerInnerDz:35,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:220}})}function rc(){return Va(po({name:"GT car",wheelbase:2700,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/Ba,kz:325/$a,lowerInnerDz:18,upperInnerDz:5,camberDeg:-3.5,loadedRadius:325,springRate:110,actuation:"direct"},rear:{kx:1.2,ky:825/fo,kz:325/ho,lowerInnerDz:36,upperInnerDz:15,camberDeg:-2,loadedRadius:325,springRate:120,actuation:"direct"}}),318.6,318.6)}function nc(){return Va(po({name:"Sports car",wheelbase:2750,trackFront:1550,trackRear:1550,front:{kx:1.15,ky:775/Ba,kz:320/$a,lowerInnerDz:36,upperInnerDz:15,camberDeg:-.5,loadedRadius:320,springRate:55,actuation:"direct"},rear:{kx:1.15,ky:775/fo,kz:320/ho,lowerInnerDz:57,upperInnerDz:25,camberDeg:-1,loadedRadius:320,springRate:60,actuation:"direct"}}),305.4,309)}function sN(e,t,r,n,o,a){let s=Lm(),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:JS(n),springRate:o,rackTravel:a}}}function eA(){return Va({name:"Cup car",front:sN(55,-25,-23,-3.5,150,55),rear:Mg(tc(),{kx:1.15,ky:820/fo,kz:320/ho,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 tA(){return{...Va(po({name:"Stock car",wheelbase:2794,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/Ba,kz:355/$a,lowerInnerDz:20,upperInnerDz:5,camberDeg:-2.5,loadedRadius:355,springRate:175,actuation:"direct"},rear:{kx:1.2,ky:825/fo,kz:355/ho,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=Va(po({name:"Hill-climb prototype",wheelbase:2550,trackFront:1580,trackRear:1540,front:{kx:1.1,ky:790/Ba,kz:300/$a,lowerInnerDz:10,upperInnerDz:5,camberDeg:-2.5,loadedRadius:300,springRate:90},rear:{kx:1.1,ky:770/fo,kz:300/ho,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 nA(){let e=Va(po({name:"Race truck",wheelbase:3700,trackFront:2050,trackRear:1950,front:{kx:1.5,ky:1025/Ba,kz:506/$a,lowerInnerDz:40,upperInnerDz:10,camberDeg:-.5,loadedRadius:506,springRate:200,actuation:"direct"},rear:{kx:1.5,ky:975/fo,kz:506/ho,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}),oA=(e,t)=>({...cr[e],value:t});function aA(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 go(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 Yr(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:oA("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]=oA(r,n);return t}var Ga={name:"Formula Student",m:300,A:1,cl:3,cw:1.3,frontMass:.47,frontAero:.45,rDyn:.222,drivenWheels:2,gearRatio:11.5,motor:aA(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}},Fg={name:"Formula 1",m:798,A:1.5,cl:3,cw:.9,frontMass:.46,frontAero:.44,rDyn:.35,drivenWheels:2,gearRatio:4.9,motor:go(735,2e3,12500,2500,2),motorCount:1,driveline:{rear:xt.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}},Dm={name:"GT car",m:1300,A:2,cl:1.4,cw:.42,frontMass:.5,frontAero:.42,rDyn:.33,drivenWheels:2,gearRatio:3.43,motor:go(410,2e3,8e3,2e3,2),motorCount:1,driveline:{rear:xt.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}},Em={name:"Sports car",m:1600,A:2.2,cl:-.1,cw:.3,frontMass:.55,frontAero:.5,rDyn:.32,drivenWheels:2,gearRatio:3.14,motor:go(220,1500,6500,1400,2),motorCount:1,driveline:{rear:xt.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}},wg={name:"Cup car",m:1265,A:2.1,cl:.45,cw:.4,frontMass:.62,frontAero:.45,rDyn:.31,drivenWheels:2,gearRatio:3.5,motor:go(250,2e3,7e3,1190,2),motorCount:1,motorPlacement:"front",driveline:{front:xt.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}},Cg={name:"Stock car",m:1620,A:2.2,cl:.6,cw:.45,frontMass:.53,frontAero:.45,rDyn:.35,drivenWheels:2,gearRatio:4.1,motor:go(500,2500,9e3,1680,2),motorCount:1,driveline:{rear:xt.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}},Tg={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:go(330,3e3,8500,1240,2),motorCount:1,driveline:{rear:xt.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}},Pg={name:"Race truck",m:5300,A:6.2,cl:-.1,cw:.65,frontMass:.6,frontAero:.6,rDyn:.502,drivenWheels:2,gearRatio:3.55,motor:go(880,100,3e3,88e3,2),motorCount:1,driveline:{rear:xt.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 Ag(e,t,r){return Yr(r({...structuredClone(e),name:t}))}var Im={[Ga.name]:Yr(Ga),"Formula Student +15% downforce":Ag(Ga,"Formula Student +15% downforce",e=>({...e,cl:e.cl*1.15,cw:e.cw*1.08})),"Formula Student -15 kg":Ag(Ga,"Formula Student -15 kg",e=>({...e,m:e.m-15})),"Formula Student +15% power":Ag(Ga,"Formula Student +15% power",e=>({...e,motor:aA(25*1.15,15e3,2e4),powerLimitKw:80*1.15})),[Fg.name]:Yr(Fg),[Dm.name]:Yr(Dm),[Em.name]:Yr(Em),[wg.name]:Yr(wg),[Cg.name]:Yr(Cg),[Tg.name]:Yr(Tg),[Pg.name]:Yr(Pg)},sA=Object.keys(Im),Lg=sA.slice(0,4),Dg=[Ga.name,Fg.name,Dm.name,Em.name,wg.name,Cg.name,Tg.name,Pg.name];var Yre={"Touring car":Dm.name,"Street car":Em.name};var iN={bg:"#0e1116",panel:"#161b22",panel2:"#1c232d",border:"#2a323d",borderBright:"#39424e",sunken:"#11161c",ink:"#06090d"},cN={normal:"#d6dde6",dim:"#8b96a3",bright:"#e7ecf3",white:"#ffffff"},lN={label:"#c8d2dc",grid:"#39424e",gridFaint:"#232b35",empty:"#1a2028"},uN={accent:"#4aa3ff",accentInk:"#04121f",warn:"#ffb454",good:"#4ec9a0",bad:"#ff6b6b",badSoft:"#ff8f8f"},mN=["#f0e442","#7b68ee","#f7a8b8","#d55e00","#d8b4fe","#b5e48c"],_m={front:"#a6e22e",rear:"#00b4d8"},iA=["#5b4bd6","#4aa3ff","#4ec9a0","#f0e442"],Eg={power:"#ffb454",traction:"#f0845c",front:_m.front,rear:_m.rear,grip:"#73c9b3",braking:"#b48aff",crest:"#e88fd0",below:"rgba(214, 221, 230, 0.32)"},pN={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"},dN={x:"#ff6b6b",y:"#57c75a",z:"#4aa3ff"},fN={line:"#b4bfcb"},hN={compression:"#b48aff",tension:"#ff6b6b"},bN={fz:"#e7ecf3",fx:"#7ad7f0",fy:"#ff54c8"},gN={drivenLine:"#4d7cff",axis:"#eef3fa",slip:"#ffe81a",drive:Eg.power,brake:Eg.braking},yN={ground:"#101920",grid:"#1a2630",gridMajor:"#26343f",horizon:"#1d2833",bridge:"#6f7a86",coneLeft:"#2f63c9",coneRight:"#d9b51f",coneStart:"#ee7a2c"},xN={chassis:"#435160",volume:"#303b47",tyre:"#435160",tyreLine:"#39424e",tyreFace:"#1c232d"},RN={centreLine:"#4aa3ff",corridorFill:"rgba(74,163,255,0.10)",boundary:"#3d4956",racingLine:"#ffb454",start:"#e7ecf3",finish:"#ff6b6b",direction:"#8b96a3"},vN={SURFACE:iN,TEXT:cN,CHART:lN,ROLE:uN,SERIES:mN,AXLE:_m,LAP_SPEED:iA,LIMITER:Eg,RIG:pN,AXIS:dN,CONSTRUCTION:fN,FORCE:hN,TYRE_FORCE:bN,REPLAY:gN,SCENERY:yN,BODY:xN,TRACK:RN},cA=e=>Object.fromEntries(Object.entries(e).map(([t,r])=>[t,Array.isArray(r)?Object.freeze([...r]):Object.freeze({...r})])),Nm=cA(vN),vt=Nm.SERIES,lA=(()=>{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 cA({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 uA=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},jre=(()=>{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=Nm[r],o=lA[r];for(let a of Object.keys(n)){let s=uA(n[a]);s&&!e.has(s)&&e.set(s,o[a])}}return e})();var mA=(e,t)=>new Set(t.flatMap(r=>{let n=e[r];return Array.isArray(n)?[...n]:Object.values(n)}).map(uA).filter(r=>r!==null)),Ure=mA(lA,["SERIES","AXLE","LAP_SPEED","LIMITER","ROLE","RIG","FORCE","TYRE_FORCE","REPLAY","AXIS","TRACK","CONSTRUCTION"]),Xre=mA(Nm,Object.keys(Nm).filter(e=>e!=="SURFACE"));function Ig(){return{kind:"simple",name:"Simple motor",rpm:[0,16e3,2e4],torque:[21,21,14],efficiency:.95}}function _g(){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 Ng(){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 Og(){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 Vg(){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 dA(){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 fA(){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 hA(){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 bA(){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 gA(){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 yA(e){return co(kN(e))}function kN(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 oc(e,t){return{...t,fingerprint:yA(e)}}var xA="CC-BY-4.0",MN={title:"PaceDynamics built-in library",url:"https://pacedyn.dev/",licence:xA},RA={fidelity:"generic",licence:xA,sources:[MN]};var Om=e=>oc(e,RA);var vA=["raw.githubusercontent.com"],kA=["tum-csv"],AN=/^[0-9a-f]{64}$/;function sc(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"||!AN.test(r)||!kA.includes(n))return!1;try{let o=new URL(t);return o.protocol==="https:"&&vA.includes(o.hostname)&&!o.username&&!o.password&&!o.port}catch{return!1}}var Vm=e=>new URL(e.url).hostname;async function MA(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 FN(e){let t=new URL(e).pathname.split("/").pop()??"";return decodeURIComponent(t).replace(/\.[^.]*$/,"")||"Linked track"}function wN(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 CN={"tum-csv":wN};function SA(e,t){return CN[t.format](e,FN(t.url))}async function Bg(e,t,r){let n=await MA(e);if(n!==t.sha256)throw new Error(`${Vm(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=SA(new TextDecoder().decode(e),t),a=await Bm(o);if(a!==r)throw new Error(`Linked track ${r} does not convert to its name (it is ${a}).`);return o}var $g=20,PN=new RegExp(`^[0-9a-f]{${$g}}$`),ic=e=>typeof e=="string"&&PN.test(e);async function Bm(e){let t=new TextEncoder().encode(vn(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,$g)}var Gg=e=>`tracks/${e}.json`;var LN=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function Kg(e){return{model:{name:e.name,source:e.source},...e.provenance?{provenance:e.provenance}:{}}}async function Hg(e,t){if(!LN(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 Bm(e);if(r!==t)throw new Error(`Catalogue track ${t} does not match its name (it is ${r}).`);return e}var yo=(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}),kn=[yo("suspensions","suspensionId","suspension"),yo("tires","tireModelId","tyre",[{key:"tiresRear",ref:"tireModelIdRear",label:"rear tyre"}]),yo("motors","motorModelId","motor"),yo("aeros","aeroModelId","aero map"),yo("batteries","batteryModelId","battery"),yo("brakes","brakeModelId","brakes"),yo("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 $m(e){let t={...e};for(let r of kn)for(let n of r.refs)delete t[n];return t}var Gm=vt,cc=Gm,zg=Gm,Mn=[...vt.slice(3),...vt.slice(0,3)],jg=[...vt.slice(1),vt[0]],Yg=[...vt.slice(2),...vt.slice(0,2)],Wg=[...vt.slice(4),...vt.slice(0,4)],Ug=[...vt.slice(5),...vt.slice(0,5)],lc=[...vt.slice(2),...vt.slice(0,2)];function Xg(){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 qg(e,t,r){let n=Im[e];if(!n)throw new Error(`no preset vehicle named "${e}"`);return{id:t,params:{...ui(structuredClone(n)),energy:{...Lr},suspensionId:"sus1"},visible:!0,color:cc[r%cc.length]}}function IN(){return Lg.map((e,t)=>qg(e,`v${t+1}`,t))}function _N(){return[Gs(),Ef(),If(),_f(),Nf(),Of(),Vf(),Bf(),$f(),Gf()].map((t,r)=>({id:`t${r+1}`,color:zg[r%zg.length],model:t}))}function NN(){return[dd(),fd(),hd(),bd(),gd(),yd(),xd(),Rd()].map((t,r)=>({id:`a${r+1}`,color:Yg[r%Yg.length],model:t}))}function ON(){return[Zp(),Jp(),ed()].map((t,r)=>({id:`b${r+1}`,color:Wg[r%Wg.length],model:t}))}function VN(){return[{id:"brk1",color:Ug[0],model:structuredClone(sh)}]}function BN(){return[{id:"dmp1",color:lc[0],model:structuredClone(yu)}]}function $N(){return[Ig(),_g()].map((t,r)=>({id:`m${r+1}`,color:Mn[r%Mn.length],model:t}))}function Qg(e){let t=r=>({...r,provenance:Om(r.model)});return{...e,suspensions:e.suspensions.map(t),vehicles:e.vehicles.map(r=>({...r,provenance:Om($m(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 uc(e="Untitled project"){let t=new Date().toISOString(),r=IN();return Qg({schemaVersion:Fm,meta:{id:Xg(),name:e,domain:"racecar",rulesetId:lo,createdAt:t,updatedAt:t},suspensions:[{id:"sus1",color:jg[0],model:bo()}],activeSuspensionId:"sus1",vehicles:r,activeVehicleId:r[0]?.id??null,tires:_N(),motors:$N(),aeros:NN(),batteries:ON(),brakes:VN(),dampers:BN(),tracks:[],activeTrackId:null,mathChannels:[],rulesets:[],studies:[],activeStudyId:null,loadCases:[],reportLayouts:[],tyreSheets:[],kinSheets:[],plans:[],results:[],settings:{numerics:{...Fi},ggvMode:"twoTrack",quasiTransient:!1,motorThermal:!1,brakeFade:!1,airTempC:At,air:structuredClone(Cm),diffYaw:!1,lapCounts:{},pathPlanId:null,useRacingLine:!0,standingStart:!1}})}var GN=["front","rear"],Zg=9.81,KN=Math.PI/180;var Wr="*",Jg=40,AA=.8;function e0(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 FA(e,t,r){let n=t.rows.map(c=>c.v),o=c=>mt(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/Zg*100)/100+0,axG:Math.round(u/Zg*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(Jg/3.6,o(Jg/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(AA*s,o(AA*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 t0(e,t,r){let n=!1,o=e.map(a=>{if(!a.follows)return a;let s=FA(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 r0(e,t){let r=e.speedKmh/3.6,n=e.ayG*Zg;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)/KN}var wA=e=>e.ayG<0?"L":"R";function n0(e,t=GN){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 o0=(e,t)=>e.travelMin===t.travelMin&&e.travelMax===t.travelMax&&e.rollMaxDeg===t.rollMaxDeg&&e.rollAtLimitDeg===t.rollAtLimitDeg;var jr=Math.PI/180,HN=9.81,mc=.1,a0=20,CA=6,DA=50;function TA(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 s0(e,t,r,n,o){let a=o*jr;if(t==="side")return TA(i=>r*e.Fy(r*i*jr,n,a),1,45);let s=t==="drive"?1:-1;return TA(i=>s*e.Fx(s*i,n,a),.02,.6)}function Hm(e){let t=e?Vl(e)?.gamma:void 0,r=[t?.min,t?.max].filter(o=>o!==void 0&&Number.isFinite(o));if(!r.length)return{lo:-CA,hi:CA,stated:!1};let n=Math.max(...r.map(Math.abs))/jr;return{lo:-n,hi:n,stated:!0}}function zN(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 PA=250,LA=new WeakMap;function YN(e,t,r,n,o,a,s){let i=LA.get(e);i||LA.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*PA);h=zN(g=>s0(r,n,o,b,g).force,s.lo,s.hi),l.set(d,h)}return h},m=Math.max(0,a)/PA,f=Math.floor(m),p=m-f;return p<1e-9?u(f):u(f)*(1-p)+u(f+1)*p}function Ka(e,t){return t==="front"?e.tireModel:e.tireModelRear??e.tireModel}var WN=new WeakMap,jN=new WeakMap,UN=new WeakMap,i0=(e,t,r)=>{let n=e.get(t);return n===void 0&&e.set(t,n=r()),n};function c0(e,t){let r=Ka(e,t);return r?i0(WN,r,()=>Is(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 l0(e,t){let r=Ka(e,t);return r?i0(UN,r,()=>Bl(r).none)?"This tyre file has no drive or brake grip.":i0(jN,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*jr);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 xo(e,t){return e==="side"||e==="ackermann"?Math.abs(t.ayG)>=mc?e==="ackermann"&&!(EA(t)<=a0)?`is a corner wider than ${a0} m`:null:"does not corner":(e==="drive"?t.axG:-t.axG)>=mc?null:e==="drive"?"does not drive":"does not brake"}var XN=e=>e.axG>=mc?"drive":e.axG<=-mc?"brake":null;function EA(e){let t=e.speedKmh/3.6,r=Math.abs(e.ayG)*HN;return r>1e-9?t*t/r:1/0}var Km=(e,t)=>`${e==="front"?"F":"R"}${t}`,qN=e=>e==="L"?"R":"L",QN=(e,t,r)=>Math.min(r,Math.max(t,e));function u0({ev:e,params:t,input:r,state:n,pose:o}){let a=`${Q(t,"grip_scale")}|${Q(t,"stiffness_scale")}`,s=EA(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=ge(e,k),C=Ka(t,k),T=Math.max(0,o.loads[v]),S=o.camber[v],A=QN(S,F.lo,F.hi),P=s0(w,x,M,T,A),L=T<DA,D=C&&!L?YN(C,a,w,x,M,T,F):A,E=L?P.force:s0(w,x,M,T,D).force,V=.05;return{corner:v,Fz:T,lifted:L,camber:S,read:A,outside:A!==S,wants:D,atEdge:!L&&(D-F.lo<V||F.hi-D<V),peak:P.force,slip:P.at,best:E}},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(!xo("side",n)){let x=Hm(Ka(t,k));v=[m(k,Km(k,o.outer),"side",1,x),m(k,Km(k,qN(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*jr;return Math.atan2(M+s*Math.sin(w),s*Math.cos(w)-F)/jr},R=k=>(n.ayG<0?-1:1)*o.steer[k];return{side(k){if(h.has(k))return h.get(k)??null;let v=c0(t,k)?null:d(k),x=v?f("side",v,Hm(Ka(t,k))):null;return h.set(k,x),x},long(k){if(b.has(k))return b.get(k)??null;let v=XN(n),x=null;if(v&&!l0(t,k)){let M=Hm(Ka(t,k));x=f(v,[m(k,Km(k,"L"),v,1,M),m(k,Km(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=ge(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)}],S=E=>T.reduce((V,N)=>{let z=N.steer-y(k,N.inner,E);return V+N.dt*F.Fy(N.dt*z*jr,N.g.Fz,N.g.read*jr)},0),A=T.map(E=>E.steer-E.g.slip-y(k,E.inner,0)),P=Math.min(...A)-2,L=Math.max(...A)+2,D=ZN(S,P,L,.25);M=Math.max(0,1-D/(w.peak+C.peak))}return g.set(k,M),M},ackermann(){if(xo("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)))/jr;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 ZN(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 JN=9.81,IA=Math.PI/180,pc={speed:20,ayG:1.2};function m0(e,t={}){let r=t.operating??pc,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=mr(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 C={cornerStiffness:T=>w.corneringStiffness(T),ayG:x.ayG,speed:x.speed,fyAxle:(T,S)=>2*w.Fy(T,S/2),tire:w};return i.set(M,C),C},b=()=>{if(s!==void 0)return s;let v=p(),x=d();if(!v||!x)return s=null;try{s=jn(x,v.massTotal*JN*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(),C=d(),T=null;if(w&&C)try{T=rb(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 F=null,w=p();try{let C=w?.kinFront,T=w?.kinRear;if(w&&C&&T){let S=r0(v,w.wheelbase),A=v.speedKmh/3.6,P=ln(w,C,T,A)(v.ayG,v.axG,0,S),L={FL:P.FL.travel,FR:P.FR.travel},D=Xn(w,S*IA,L),E=S?D.camber:null,V={},N={};for(let I of["FL","FR","RL","RR"]){let _=I[1]==="R"?P[I].camberRoad:0-P[I].camberRoad;V[I]=_+(E?.[I]??0),N[I]=D.steer[I]/IA+(I[1]==="R"?1:-1)*P[I].bumpToe}let z=Ce(w,v.ayG,v.axG,A,0,S,L,P.steeringJacking);F={corners:P,rollDeg:P.FL.camberRoad-P.FL.camber,steerDeg:S,camber:V,outer:wA(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(),C=d(),T=F&&w&&C?u0({ev:C,params:e.params,input:w,state:v,pose:F}):null;return R.set(x,T),T},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?Eb(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 C=p(),T=h(x),S=null;if(C&&T)try{S=Di(C,T,v,b()??void 0)}catch{S=null}return u.set(F,S),S}}}var _A=["widthLeft","widthRight","bank","mu"];function dc(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 p0(e){let t=dc(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 Ym(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 _A){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 Wm(e,t,r){if(!t.length)return e;let n=dc(e),o=n.length,a={widthLeft:zm(e.widthLeft,r.widthLeft),widthRight:zm(e.widthRight,r.widthRight),bank:zm(e.bank,r.bank),mu:zm(e.mu,r.mu)},s={};for(let c of _A){let l=e[c];Array.isArray(l)&&l.length===o&&(s[c]=l)}let i=Ym(t,n,a,s);return{...e,...i}}function zm(e,t){return typeof e=="number"?e:t}var VA=1,NA=4,Um=Math.PI/180,d0=e=>e===null||!Number.isFinite(e)||e===0?0:1/e;function f0(e){return e.kind==="arc"?Math.abs(e.radius)*Math.abs(e.angle)*Um:e.length}function jm(e,t){return e.kind==="straight"?0:e.kind==="arc"?d0(e.radius):t}function OA(e){return e.kind==="straight"?0:e.kind==="arc"?d0(e.radius):d0(e.endRadius)}var fc=(e,t,r,n,o)=>e+t*o+(n>0?(r-t)*o*o/(2*n):0);function hc(e,t={}){let r=Math.max(.05,t.spacing??VA),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((S,A)=>S+f0(A),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*Um,b=e.length?jm(e[0],0):0,g=0,y=f,R=(S,A,P)=>{s.push(S),i.push(A),c.push(P)};R(p,d,0);let k=(S,A,P,L,D)=>{let E=D-L;if(E<=0)return;if(Math.abs(A-S)<1e-12){let N=fc(h,S,S,P,L);if(Math.abs(S)<1e-12)p+=E*Math.cos(N),d+=E*Math.sin(N);else{let z=N+S*E;p+=(Math.sin(z)-Math.sin(N))/S,d+=-(Math.cos(z)-Math.cos(N))/S}return}let V=E/NA;for(let N=0;N<NA;N++){let z=L+N*V,I=fc(h,S,A,P,z),_=fc(h,S,A,P,z+V/2),B=fc(h,S,A,P,z+V);p+=V/6*(Math.cos(I)+4*Math.cos(_)+Math.cos(B)),d+=V/6*(Math.sin(I)+4*Math.sin(_)+Math.sin(B))}};for(let S of e){let A=f0(S),P=jm(S,b),L=OA(S);if(l.push({from:g,to:g+A,...S.widthLeft!==void 0?{widthLeft:S.widthLeft}:{},...S.widthRight!==void 0?{widthRight:S.widthRight}:{},...S.bank!==void 0?{bank:S.bank}:{},...S.mu!==void 0?{mu:S.mu}:{},...S.ramp!==void 0?{ramp:S.ramp}:{}}),A<=0){b=L;continue}let D=0;for(;y<=g+A+1e-9;){let E=Math.min(A,y-g);k(P,L,A,D,E),D=E,R(p,d,g+E),y+=f}k(P,L,A,D,A),h=fc(h,P,L,A,A),b=L,g+=A}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?jm(e[0],b):0,F={gap:v,headingError:eO((h-o.heading*Um)/Um),curvatureError:b-M},w=[];for(let S=0;S<e.length;S++){let A=OA(e[S]),P=S+1<e.length?e[S+1]:n?e[0]:null;if(!P)continue;let L=jm(P,A);w.push({index:S,before:A,after:L,jump:Math.abs(L-A)})}let C=Ym(l,c,a);return{asset:{name:t.name??"Track",x:s,y:i,fit:"interpolate",...n?{}:{closed:!1},...C},sections:l,joints:w,closure:F,length:x}}function eO(e){let t=e%360;return t>180&&(t-=360),t<-180&&(t+=360),t}var tO={halfWidthM:1.5,spacingM:.5};function bc(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 ${$A(e).toFixed(0)} m`}}}function $A(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 GA=e=>e.kind==="skidpad"||e.kind==="curves"&&e.closed===!0,KA=e=>e.kind==="acceleration",HA=1.5,zA=3;function rO(e,t){let r=e.offsetM,n=e.pitchM,o=Math.max(1,e.gates)*n,a=Math.max(0,e.leadInM),s=HA*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*(zA*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:bc(e),x:m,y:f,closed:!1,widthLeft:t.halfWidthM,widthRight:t.halfWidthM,fit:"interpolate"}}function nO(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 h0(e,t={}){let r={...tO,...t},n=KA(e),o=nO(e);if(!o){let u=rO(e,r);return{asset:u,peakCurvature:BA(u),worstJoint:0,standingStart:n}}let a=GA(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*(zA*Math.PI/180))):r.spacingM,c=hc(o,{name:bc(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:BA(c.asset),worstJoint:l.reduce((u,m)=>Math.max(u,m.jump),0),standingStart:n}}function BA(e){try{return Math.max(...it(e).curvature.map(Math.abs))}catch{return NaN}}var qm={courses:[{id:"c1",course:{kind:"manoeuvre",spec:{kind:"skidpad",radiusM:8.375}}}],ggvMode:"twoTrack"};function b0(e){return e.course.kind==="project"?"the project\u2019s track":e.course.kind==="track"?e.course.name:bc(e.course.spec)}var YA=new WeakMap,Xm=new Map;function WA(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=Xm.get(n);if(o)return{...o,numerics:r};let a=h0(e.spec),s={asset:a.asset,standingStart:a.standingStart};return Xm.size>64&&Xm.clear(),Xm.set(n,s),{...s,numerics:r}}function g0(e,t,r={}){let n=r.lap??qm,o=r.simParams,a=r.numerics??{},s=n.courses.length?n.courses:qm.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=WA(v.course,r,a),F=null;if(M)try{let w=JSON.stringify(M.numerics),C=YA.get(M.asset);C||(C=new Map,YA.set(M.asset,C));let T=C.get(w);T||(T=it(M.asset,M.numerics),C.set(w,T)),F={id:v.id,track:T,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=Ft(k),c=pr(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?ao(l,M,[v.track],v.numerics,n.ggvMode,u):void 0,C=l?xn(l,M.rows):void 0;F=Rt(M,v.track,v.numerics,{standingStart:v.standingStart,...w?{load:w}:{},...C?{shifts:C}:{}})}catch{F=null}return f.set(v.id,F),F};return{lapSettings:n,get lapAvailable(){return!!o&&s.some(k=>!!WA(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(),C=null;if(M&&F&&w)try{let T=h();C=rm(F,w,{v:M.v,ax:M.ax,ay:M.ay,ds:v.track.ds,axDrag:Ea(g()?.rows,M.v),...M.axScrub?{axScrub:M.axScrub}:{},axGrade:yn(v.track.gradient,M.v.length),bank:v.track.bank,...M.loadFactor?{loadFactor:M.loadFactor}:{}},T?{driven:vh(T)}:{})}catch{C=null}return p.set(v.id,C),C}}}var jA=180/Math.PI,y0={rise:0,sinPitch:0,sinRoll:0};function UA(e){let t=e.kc;return t?XA(e.vehicle,r=>t.ground0[r]):y0}function XA(e,t){let r=e.config,n=nn(r),o=0,a=0,s=0,i=0,c=0,l=0,u=0,m=0,f=0;for(let g of er){let y=Ze(g,r),R=y.axleX-n,k=y.sideSign*Nt(e,y.isFront)/2,v=t(g);if(!Number.isFinite(v))return y0;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 gc(e,t){let r=e.kc,n=XA(e.vehicle,o=>(r?r.ground0[o]:0)+t[o]);return q([-n.sinPitch,n.sinRoll,1])}function x0(e,t,r,n){let o=q(rn(e,Ze(t,r)));return-Math.asin(Math.max(-1,Math.min(1,X(o,n))))*jA}function Qm(e,t,r,n,o){let a=q(rn(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&&oO(o.patchShift,e.metrics.toe/jA,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 oO(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 Zm(e,t){let r=UA(t);if(r===y0)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 Ha(e,t,r){let n=Zm({heave:0,pitch:0,roll:0,steer:0},r);return e-Id(n,[t,0,0],nn(r.vehicle.config))}var aO=180/Math.PI;function R0(e,t){return!e.valid||!e.ic?!1:Math.hypot(e.ic[0]-e.cp[0],e.ic[1]-e.cp[1])<=t}function Jm(e,t,r){let n=Ze(t,e.vehicle.config),o=gt(e,r),a=Su(e,t,o[t]),s=a.at("uprightUpper"),i=a.at("uprightLower"),c=a.at("contactPatch"),l=a.at("wheelCenter"),u=A=>{let P=a.velocity(A);return[P[0],P[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=gc(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=A=>{let P=A[0]*g[0]+A[1]*g[1];return Math.abs(P)>1e-9?-(A[0]*y[0]+A[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,F=x?(A=>{let P=[s[0]-A[0],s[2]-A[1]],L=[i[0]-A[0],i[2]-A[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:d,road:y,swingArmAngleDeg:0,tanTheta:0,tanThetaHub:0,valid:!1,sinAngle:F};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,S=R(m);return{ic:x,line:T,cp:p,wc:d,road:y,swingArmAngleDeg:Math.atan(S)*aO,tanTheta:S,tanThetaHub:R(f),valid:!0,sinAngle:F}}function qA(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 iO=180/Math.PI,cO=Math.PI/180,v0=.5,ep=2,k0=.25,lO={heave:0,pitch:0,roll:0,steer:0},uO={FL:"FR",FR:"FL",RL:"RR",RR:"RL"},tp=e=>e.ok?e.state:{...e.nearest,converged:!1};function M0(e,t,r){return t.state?t.solved===!1?{...t.state,converged:!1}:t.state:tp(ye(e,t.travel,t.steer,void 0,r))}var QA=new WeakMap;function ZA(e,t){let r=e.ctx[t],n=Ge(e.vehicle,t).config.loadedRadius,o=rr(n,e.kc,t),a=QA.get(r);a||(a=new Map,QA.set(r,a));let s=a.get(o);if(!s){let i=on(t,e.vehicle.config,lO,e.vehicle);s=tp(ye(r,i.travel,i.steer,void 0,o===n?void 0:{loadedRadius:o})),a.set(o,s)}return s}var br=(e,t)=>!e||!e.lo.converged||!e.hi.converged?NaN:(t(e.hi)-t(e.lo))/(2*e.step),JA=(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 tF(e,t,r,n,o){let a=e.vehicle.config,s=Ko(r),i=Ge(e.vehicle,r),c=Ze(r,a),l=e.ctx[r],u=gt(e,t),m=u[r],f={travel:m.travel,steer:m.steer},p=m.rigid?void 0:{loadedRadius:m.loadedRadius},d=M0(l,m,p),h=ZA(e,r),b={lo:tp(ye(l,f.travel-v0,f.steer,void 0,p)),hi:tp(ye(l,f.travel+v0,f.steer,void 0,p)),step:v0},g=c.isFront?{lo:Ie(l,d.beta,f.steer-ep,void 0,p),hi:Ie(l,d.beta,f.steer+ep,void 0,p),step:ep}:null,y=Y=>{let j=gt(e,{...t,roll:t.roll+Y*cO})[r];return M0(l,j,j.rigid?void 0:{loadedRadius:j.loadedRadius})},R={lo:y(-k0),hi:y(k0),step:k0},k=pO(e,t,r,c.isFront,u,g),v=Ot(d.points.contactPatch,c),x=Ot(h.points.contactPatch,c),M=Math.abs(v[1])-Math.abs(x[1]),F=uO[r],w=u[F],C=M0(e.ctx[F],w,w.rigid?void 0:{loadedRadius:w.loadedRadius}),T=C.converged?M+Math.abs(C.points.contactPatch[1])-Math.abs(ZA(e,F).points.contactPatch[1]):NaN,S=o??lr(e,t,s),A=Au(S,bt(i)),P=A?null:Mk(S),L=c.sideSign>0?S.icRight:S.icLeft,D=L?Math.hypot(L[0]-v[1],L[1]-v[2]):1/0,E=Jm(e,r,t),V=E.ic?Math.hypot(E.ic[0]-E.cp[0],E.ic[1]-E.cp[1]):1/0,N=qA(E,s,a.wheelbase,n),z=-br(b,Y=>Y.points.damperLength),I=i.config.springRate,_=br(R,Y=>Y.metrics.camber),B=gc(e,{FL:u.FL.ground,FR:u.FR.ground,RL:u.RL.ground,RR:u.RR.ground}),O=e.kc?.loadCase,G=Y=>O?Qm(Y,r,a,B,{loadedRadius:m.loadedRadius,patchShift:O.patchShift[r]}):Y.metrics,K=G(d);return{id:r,converged:d.converged,travel:d.travel,camber:d.metrics.camber,camberRoad:x0(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:br(b,Y=>Y.metrics.camber),bumpSteer:br(b,Y=>Y.metrics.toe),trackScrubRate:br(b,Y=>Math.abs(Ot(Y.points.contactPatch,c)[1])),casterGain:br(b,Y=>G(Y).caster),kpiGain:br(b,Y=>G(Y).kpi),scrubGain:br(b,Y=>G(Y).scrubRadius),trailGain:br(b,Y=>G(Y).mechanicalTrail),...c.isFront?{camberPerSteer:JA(g,Y=>Y.metrics.camber,Y=>Y.metrics.toe),steerJacking:-JA(g,Y=>Y.points.contactPatch[2],Y=>Y.metrics.toe),...k!==void 0?{steerLoad:k}:{}}:{},rollCamber:_,camberRecovery:-100*c.sideSign*_,rollSteer:c.sideSign*br(R,Y=>Y.metrics.toe),halfTrackChange:M,trackChange:T,longitudinal:v[0]-x[0],rollCentreHeight:P?P.heightAboveGround:S.heightAboveGround,rollCentreHeightChassis:(P?P.height:S.height)-Ha(0,c.axleX,e),rollCentreLateral:S.lateralAlongGround,rollCentreValid:S.valid,rollCentreUsable:A,rollCentreHeightUsable:A||P!==null,rollCentreSinAngle:S.sinAngle,fvsaLength:D,svsaLength:V,swingArmAngle:E.swingArmAngleDeg,svsaUsable:R0(E,a.wheelbase),svsaSinAngle:E.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:I,motionRatio:z,wheelRate:I*z*z,damperLength:d.points.damperLength,damperTravel:h.points.damperLength-d.points.damperLength,...mO(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)*iO,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 mO(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 pO(e,t,r,n,o,a){if(!a||!n)return;let s=hl(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)*ep,M=g.state?{q:[...g.state.pose.t,...g.state.pose.omega],phi:g.state.points.rockerAngle}:void 0,F=ht(ye(y,g.travel,g.steer-x,M,R)),w=ht(ye(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]=kr(i.curve[b],g.travel,w.points.damperLength)-kr(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=ks(p,h,[m.hi[0],m.hi[1]]),g=ks(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 yc(e,t,r,n,o){return tF(e,t,r==="front"?"FL":"RL",n,o)}function S0(e,t,r,n){let o=yc(e,t,"front",r,n?.front),a=yc(e,t,"rear",r,n?.rear);return{front:o,rear:a,wheelbaseChange:o.longitudinal-a.longitudinal}}var rp=Math.PI/180,xc={travelSteps:9,heaveSteps:5,rollSteps:4,rackSteps:6},np={travelMin:-25,travelMax:25,rollMaxDeg:3,rollAtLimitDeg:2.5};function dO(e){let t=e.params;return{cgHeight:t.cg_height?dt({...t,surveyedRadiusFront:e.vehicle.front.config.loadedRadius,surveyedRadiusRear:e.vehicle.rear.config.loadedRadius}).cgHeight:300,...Ah(t),drive:kh(t)}}function rF(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 A0(e,t=xc,r=np,n){let o=null,a=(S,A)=>(o||(o={violation:S,reason:A}),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=Ct(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=Ct(s)},m=S=>S==="front"?"FL":"RL",f=S=>{let A=u();if(!A.kc)return;let P=i(S).config.loadedRadius,L=rr(P,A.kc,m(S));return L===P?void 0:{loadedRadius:L}},p=(S,A)=>-Ms(u(),m(S),A),d=new Map,h=new Map,b=new Map,g=new Map,y=new Map,R=new Map,k=new Map,v=null,x=()=>{if(v)return v;u();let S=dO(e);return v=l!==null&&Number.isFinite(l)?{...S,cgHeight:l}:S},M,F,w=()=>{if(F!==void 0)return F;let S=vl(u().ctx.FL,Vt(s.front.config));return F=S?kl(S):null,F},C=(S,A,P)=>{if(S.has(A))return S.get(A)??null;let L=P();return S.set(A,L),L};return{car:e,density:t,envelope:r,get failure(){return o},axisLength:(S,A)=>{let P=i(S),L=P.hardpoints;return A==="uca"&&P.config.layout==="mcpherson"?NaN:A==="uca"?ve(L.ucaFront,L.ucaRear):ve(L.lcaFront,L.lcaRear)},linkLength:S=>{let A=i(S).hardpoints;return ve(A.tieInner,A.tieOuter)},compliance:S=>C(h,S,()=>wf(i(S))??null),sweep:S=>C(d,S,()=>{let A;try{A=Ke(i(S),{travelMin:r.travelMin,travelMax:r.travelMax,steps:t.travelSteps})}catch{return a(500,`the ${S} travel sweep threw`)}if(!A.covered){let L=A.samples.map(V=>V.travel),D=Math.max(...L)-Math.min(...L),E=r.travelMax-r.travelMin;return a(Math.max(0,E-D),`the ${S} linkage reaches only ${D.toFixed(0)} mm of the ${E.toFixed(0)} mm travel range`)}if(A.fold)return a(200,`the ${S} travel(beta) folds \u2014 the suspension goes over centre in range`);let P=A.samples.filter(L=>!L.converged).length;if(P>0)return a(100+10*P,`${P} of ${A.samples.length} ${S} travel solves did not converge`);if(S==="front"&&i("front").config.steerMode==="rack"){let L=w();if(L)return a(L.violation,L.reason)}return A}),rcHeave:S=>C(b,S,()=>{let A=[],P=[],L=Math.max(2,t.heaveSteps);try{for(let E=0;E<L;E++){let V=r.travelMin+(r.travelMax-r.travelMin)*E/(L-1);A.push(V),P.push(lr(u(),{heave:p(S,V),pitch:0,roll:0,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in heave`)}let D=rF(P,E=>Math.abs(A[E]-A[E-1]));return D>0?a(300,`the ${S} roll-centre construction lands on another branch at ${A[D].toFixed(0)} mm of travel`):{at:A,rc:P}}),rcRoll:S=>C(g,S,()=>{let A=[],P=[],L=Math.max(2,t.rollSteps);try{for(let E=0;E<L;E++){let V=r.rollMaxDeg*E/(L-1);A.push(V),P.push(lr(u(),{heave:0,pitch:0,roll:V*rp,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in roll`)}let D=rF(P,E=>Math.abs(P[E].cpLeft?.[0]??0)*Math.abs(A[E]-A[E-1])*rp);return D>0?a(300,`the ${S} roll-centre construction lands on another branch at ${A[D].toFixed(1)}\xB0 of roll`):{at:A,rc:P}}),steer:()=>{if(M!==void 0)return M;try{M=cf(u(),{steerMax:Vt(s.front.config),steps:t.rackSteps})}catch{M=a(500,"the steering sweep threw")}let S=M?.filter(A=>!A.converged).length??0;if(M&&S>0){let A=w();M=A?a(A.violation,A.reason):a(100+10*S,`${S} of ${M.length} steering solves did not converge`)}return M??null},solveAt:(S,A,P=0)=>C(y,`${S}:${A}:${P}`,()=>{try{let L=ye(u().ctx[m(S)],A,P,void 0,f(S));return L.ok?L.state:L.why==="unconverged"?a(100,`the ${S} corner did not solve at ${A.toFixed(0)} mm of travel`):a(100+Math.abs(L.travelMiss),`the ${S} corner reaches only ${(A+L.travelMiss).toFixed(0)} of ${A.toFixed(0)} mm of travel`)}catch{return a(150,`the ${S} corner solve threw at ${A.toFixed(0)} mm of travel`)}}),readout:S=>C(R,`${S.heave}:${S.pitch}:${S.roll}:${S.steer}`,()=>{try{return S0(u(),S,x())}catch{return a(500,"the derived readout threw")}}),readoutAtTravel:(S,A)=>C(k,`${S}:${A}`,()=>{try{return yc(u(),{heave:p(S,A),pitch:0,roll:0,steer:0},S,x())}catch{return a(500,`the ${S} readout threw at ${A.toFixed(0)} mm of travel`)}}),travelAtRoll:(S,A)=>{let P=i(S).hardpoints.wheelCenter[1]*Math.sin(A*rp),L=u();if(!L.kc)return P;try{let D=gt(L,{heave:0,pitch:0,roll:A*rp,steer:0}),E=S==="front"?Math.max(D.FL.travel,D.FR.travel):Math.max(D.RL.travel,D.RR.travel);return Number.isFinite(E)?E:P}catch{return a(500,`the ${S} axle could not be rolled on its tyre`),P}},onTyre:()=>!!u().kc,contexts:u}}var fO=hg();function F0(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=gm(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?Zi([c],a.track,a.numerics,ji(s),a.settings,fO)[0]:Vi(c,s,{numerics:a.numerics,standingStart:l,lapCounts:u});o={};for(let f of s.metrics)Hc(f)&&(o[f.key]=f.value(m,void 0))}}catch{o=null}return r.set(n,o),o}}}var op=.01;function hO(e,t){return t.bump!==null&&e>t.bump-op?{at:"closed",past:Math.max(0,e-t.bump)}:t.droopStated&&e<t.droop+op?{at:"toppedOut",past:Math.max(0,t.droop-e)}:t.seat!==null&&e<t.seat+op?{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}),bO=[["front","FL","FR"],["rear","RL","RR"]];function C0(e,t){let r=[];for(let[n,o,a]of bO){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=Gd(f,t[m]);d===null||!Number.isFinite(d)||r.push(w0(m,n,n,d,f.spring.length0-d,nF(p),!0))}let i=e.elements?.[n];if(!i)continue;let c=i.heave?.law;if(c){let m=gR(i,s),f=i.read.heave?.span0,p=n==="front"?"heaveFront":"heaveRear";r.push(w0(p,p,n,m,f!==void 0?f-m:null,nF(c),i.carriesLoad))}let l=i.rollStop,u=l?yR(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(w0(f,f,n,m,u,p,i.carriesLoad))}}return r}function w0(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,...hO(n,a),bumpStated:a.bump!==null,bounds:s}}function oF(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),Ha(Math.min(n.zMin,n.zMax),i,t)],max:[s,Math.max(n.yMin,n.yMax),Ha(Math.max(n.zMin,n.zMax),i,t)]}})}var gO=(e,t)=>[e[0]+t[0],e[1]+t[1],e[2]+t[2]],yO=(e,t)=>[e[0]*t,e[1]*t,e[2]*t];var xO=(e,t,r)=>e.z0+e.dzdx*t+e.dzdy*r;function RO(e,t){let r=Math.sin(e.pitch);return{z0:-e.heave+t*r,dzdx:-r,dzdy:Math.sin(e.roll)}}function aF(e){return RO(Zm({heave:0,pitch:0,roll:0,steer:0},e),nn(e.vehicle.config))}function vO(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:yO(a.reduce((c,l)=>gO(c,l),[0,0,0]),1/a.length)}}function sF(e,t){return{...vO(e,r=>r[2]-xO(t,r[0],r[1])),road:t}}function iF(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]}var uF=Math.PI/180;function T0(e,t,r,n){let o=t.speedKmh/3.6,a=Md(e,o,t.axG,Jr(e,t.ayG,0));if(!a||!e.aero)return null;let s=e.wheelbase,i=$o(e.aero,s),c=(h,b)=>Math.atan((b-h)/s)/uF,l={},u={};for(let h of er)l[h]=r.corners[h].travel,u[h]=r.corners[h].ground;let m=n.kc?C0(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:mF(f,s,a.hFront,a.hRear)}:null;return{front:{height:a.hFront,...cF(m,"front")},rear:{height:a.hRear,...cF(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:kO(n,u)}}function cF(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 mF(e,t,r,n){let o=(a,[s,i])=>Math.min(a-s,i-a);if(ux(e)){let{x:a,y:s}=No(e),i=[a[0],a[a.length-1]],c=[s[0],s[s.length-1]];return Qr(e)?lF(e.frame,t,i,c,r,n):Math.min(o(r,i),o(n,c))}return Xc(e)?lF(e.frame,t,e.range.h,e.range.pitch,r,n):Math.min(o(r,e.range.hFront),o(n,e.range.hRear))}function lF(e,t,r,n,o,a){let s=Oo(e,t,o,a),i=l=>t*Math.tan(l*uF),c=a-o;return Math.min(s.h-r[0],r[1]-s.h,c-i(n[0]),i(n[1])-c)}function kO(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=Nt(e.vehicle,!0)/2,c=Nt(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 er){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=iF(u,m);if(!f)return null;let p=aF(n),d={z0:p.z0+f[0],dzdx:p.dzdx+f[1],dzdy:p.dzdy+f[2]},h=null;for(let b of oF(r,n)){let g=sF(b,d);(!h||g.height<h.height)&&(h={height:g.height,volume:b.name})}return h}function P0(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 MO={front:"front",rear:"rear",heaveFront:"front",heaveRear:"rear",rollFront:"front",rollRear:"rear"};function ap(e,t,r,n){let o=Lu(e,t);return vu.some(s=>{if(MO[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 L0(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 sp=Math.PI/180,ip=1e-6;function dF(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 Rc(e){let t=e.measured;if(t)return dF(t.travel,t.camber);let r=q(e.config.spinAxis);return-Math.asin(Math.max(-1,Math.min(1,r[2])))/sp}function vc(e){let t=e.measured;if(t)return dF(t.travel,t.toe);let[r,n]=e.config.spinAxis;return Math.atan2(r,n)/sp}function D0(e,t){let r=Math.abs(t.camber)>=ip,n=Math.abs(t.toe)>=ip;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=(Rc(e)+t.camber)*sp,l=(vc(e)+t.toe)*sp,[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 cp(e){let t=e&&typeof e=="object"?e.value:void 0;return typeof t=="number"&&Number.isFinite(t)?t:void 0}function SO(e,t){let r=t;return{front:cp(r.camber_front_deg)??Rc(e.front),rear:cp(r.camber_rear_deg)??Rc(e.rear)}}function AO(e,t){let r=t;return{front:cp(r.toe_front_deg)??vc(e.front),rear:cp(r.toe_rear_deg)??vc(e.rear)}}function FO(e){return{camber:{front:Rc(e.front),rear:Rc(e.rear)},toe:{front:vc(e.front),rear:vc(e.rear)}}}var pF=new WeakMap;function wO(e,t){let r=FO(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)<ip&&Math.abs(u.toe)<ip;if(o(n.front)&&o(n.rear))return e;let a=`${t.camber.front}|${t.camber.rear}|${t.toe.front}|${t.toe.rear}`,s=pF.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&&D0(m,n[Ko(u)])])):void 0,l={...e,front:D0(e.front,n.front),rear:D0(e.rear,n.rear),...c?{corners:c}:{}};return s||pF.set(e,s=new Map),s.size>=16&&s.clear(),s.set(a,l),l}function za(e,t){return t?wO(e,{camber:SO(e,t),toe:AO(e,t)}):e}var CO=9.81;function Ya(e){let t=Nn(e),r=Math.max(0,e.unsprungPerCorner)*CO,n=a=>{let s=a==="FL"||a==="FR",i=s?"front":"rear",c=Xe(e,i),l=c>0?c:1/0,u=nd(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:Gt(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 fF=new WeakMap;function TO(e){let t=za(e.vehicle,e.params);if(t===e.vehicle)return e;let r=fF.get(e);return(!r||r.vehicle!==t)&&fF.set(e,r={...e,vehicle:t}),r}function Sn(e,t={}){let r=TO(e),n=m0(r,t),o=t.assemble?()=>{let m=n.dynInput();if(!m)throw new Error("the car did not assemble");return{kc:Ya(m),cgHeight:m.cgHeight}}:void 0,a=A0(r,t.density,t.envelope,o),s=g0(r,n,t),i=F0(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=T0(h,m,d,a.contexts())}catch{b=null}return l.set(f,b),b}}}var PO=["x","y","z"],LO=/^(line|plane)\((-?\d+),(-?\d+)\)([uv]?)$/,hF=Math.PI/18e3,bF=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],gF=(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]],DO=e=>Math.hypot(e[0],e[1],e[2]),E0=(e,t)=>[e[0]*t,e[1]*t,e[2]*t];function I0(e){let t=DO(e);return t>1e-9?E0(e,1/t):null}function EO(e,t){let r=e*hF,n=t*hF;return[Math.cos(n)*Math.cos(r),Math.cos(n)*Math.sin(r),Math.sin(n)]}function gr(e){let t=e.lastIndexOf(".");if(t<0)return null;let r=LO.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:EO(Number(r[2]),Number(r[3]))},coord:n==="line"?"along":r[4]}}function yF(e){let t=I0(gF([0,0,1],e))??[1,0,0];(t[0]<-1e-9||Math.abs(t[0])<=1e-9&&t[1]<0)&&(t=E0(t,-1));let r=I0(gF(e,t))??[0,1,0];return(r[2]<-1e-9||Math.abs(r[2])<=1e-9&&r[1]<0)&&(r=E0(r,-1)),[t,r]}function _0(e){if(e.coord==="along")return e.shape.dir;let[t,r]=yF(e.shape.dir);return e.coord==="u"?t:r}function xF(e,t){let r=gr(t);if(!r)return;let n=PO.map(u=>e[`${r.point}.${u}`]);if(n.some(u=>!u))return;let o=_0(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=>bF(s(u),o),write:(u,m)=>{let f=s(u),p=m-bF(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 lp=["x","y","z"];var IO=/^(?:hp\.(?:front|rear)\.\w+|(?:heave|roll)\.(?:front|rear)\.(?:outer|inner|anchor))$/;function kc(e){let t=e.lastIndexOf("."),r=e.slice(0,t);if(t<0||!IO.test(r))return null;let n=e.slice(t+1);if(n==="x"||n==="y"||n==="z")return{point:r,axis:n};let o=gr(e);return o?{point:r,axis:o.coord}:null}var Mc="*";function N0(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 O0=e=>e?.reads==="speed"||e?.reads==="operating",V0=e=>e?.reads==="lateral"||e?.reads==="operating";function Ro(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 up(e,t){return e?.appliesAt?t.find(r=>!e.appliesAt(r)):t[0]}function Wa(e,t,r){let n=r?.stateId?e.stateOf(r.stateId):up(t,e.states)??null;return n&&!t.appliesAt?.(n)?n:null}function Lt(e,t,r){let n=`${t.id}@${Ro(r)}`,o=e.values.get(n);if(o!==void 0)return o;let a;try{a=r?.courseId===Mc&&t.reads==="course"?_O(e,t,r):r?.stateId===Wr&&t.reads==="state"?NO(e,t,r):t.read(e,r)}catch{a=NaN}return e.values.set(n,a),a}function _O(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:Lt(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 NO(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:Lt(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 B0(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 OO={front:"Front",rear:"Rear"},Sc={heave:0,pitch:0,roll:0,steer:0};function RF(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 VO(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 Ac=e=>e.length?Math.max(...e)-Math.min(...e):NaN;function vF(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 kF(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 ja(e,t,r){let n=e.stateOf(t?.stateId),o=n?e.poseAt(n):null;return o?r(o):NaN}var Fc=(e,t)=>`${e==="front"?"F":"R"}${t}`,MF=e=>e==="L"?"R":"L";function SF(e){let t=OO[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?Wd(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=Hd(o(x.car),F.linkage,F.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(Sc)?.[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?VO(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?Ac(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?Ac(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?RF(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?RF(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=>Ac(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=>Ac(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)=>ja(x,M,F=>F.camber[Fc(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)=>ja(x,M,F=>F.camber[Fc(e,MF(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)=>ja(x,M,F=>F.corners[Fc(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?kF(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(C=>C.metrics.motionRatio??NaN).filter(Number.isFinite);if(!F.length)return NaN;let w=F.reduce((C,T)=>C+T,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?kF(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=>vF(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:va(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=>vF(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:Zn(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(Sc)?.[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)=>ja(x,M,F=>F.corners[Fc(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)=>ja(x,M,F=>F.corners[Fc(e,MF(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:Ac(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(Sc)?.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(Sc)?.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(Sc)?.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 AF(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 BO=[{id:"kin.front.ackermannCentre",group:"Steering",label:"Ackermann near centre",unit:"%",scale:25,scope:"front",cost:"cheap",read:e=>AF(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=>AF(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}}],$O=[{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)=>ja(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}}],$0=[...SF("front"),...SF("rear"),...BO,...$O];var PF={front:"Front",rear:"Rear"},FF=e=>xo("side",e),GO=e=>xo("drive",e)&&xo("brake",e)?"neither brakes nor drives":null;function KO(e,t,r,n){let o=Wa(e,t,r),a=o?e.tyreAt(o):null;return a?n(a):NaN}function Ua(e,t){let r={...e,read:(n,o)=>KO(n,r,o,t)};return r}var wF=e=>e?100*e.lossCamber:NaN,CF=e=>e&&!e.lifted?e.camber-e.wants:NaN;function TF(e){let t=PF[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:FF,unavailable:s=>c0(s.params,e)},a=[Ua({...o,id:r("camberErrorOuter"),label:"camber error at the outer wheel",unit:"\xB0",scale:.5},s=>CF(s.side(e)?.wheels[0])),Ua({...o,id:r("camberErrorInner"),label:"camber error at the inner wheel",unit:"\xB0",scale:.5},s=>CF(s.side(e)?.wheels[1])),Ua({...o,id:r("sideLossCamber"),label:"side grip lost to camber",unit:"%",scale:1},s=>wF(s.side(e))),Ua({...n,appliesAt:FF,id:r("sideLossToe"),label:"side grip lost to the toe split",unit:"%",scale:1},s=>100*s.toeLoss(e)),Ua({...n,appliesAt:GO,unavailable:s=>l0(s.params,e),id:r("longLossCamber"),label:"drive and brake grip lost to camber",unit:"%",scale:1},s=>wF(s.long(e)))];return e==="front"&&a.push(Ua({...n,appliesAt:s=>xo("ackermann",s),id:r("ackermannError"),label:"Ackermann against the tyre",unit:"%",scale:25},s=>s.ackermann())),a}var G0=[...TF("front"),...TF("rear")],HO=/^tyre\.(front|rear)\.(camberErrorOuter|camberErrorInner|sideLossCamber|longLossCamber)$/;function K0(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=HO.exec(a.id);if(!i)continue;let c=i[1],l=i[2]==="longLossCamber",u=s?.stateId==="*"?e.states.filter(m=>!a.appliesAt?.(m)):[Wa(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 ${PF[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 H0(e,t){let r=e.appliesAt?.(t);return r?`is read at ${t.name}, which ${r}`:null}var zO={front:"Front",rear:"Rear"};function YO(e,t,r,n){let o=Wa(e,t,r),a=o?e.platformAt(o):null;return(a?n(a):null)??NaN}function Kt(e,t){let r={...e,read:(n,o)=>YO(n,r,o,t)};return r}var z0={cost:"cheap",reads:"state"},WO={unavailable:e=>P0(e.params)};function LF(e){let t=zO[e],r=o=>`platform.${e}.${o}`,n={...z0,group:`${t} platform`,quantity:`${t} \xB7 Platform`,scope:e};return[Kt({...n,id:r("rideHeight"),label:"ride height at a state",unit:"mm",scale:5,acrossStates:"min"},o=>o[e].height),Kt({...n,id:r("toBumpStop"),label:"travel left to the bump stop",unit:"mm",scale:5,acrossStates:"min",unavailable:o=>ap(o.vehicle,o.params,e,"bump")},o=>o[e].toBump),Kt({...n,id:r("toDroopStop"),label:"travel left to the droop stop",unit:"mm",scale:5,acrossStates:"min",unavailable:o=>ap(o.vehicle,o.params,e,"droop")},o=>o[e].toDroop)]}var mp={...z0,group:"Platform",scope:"car"},wc={...z0,...WO,group:"Aero platform",groupShort:"Aero",scope:"car"},Y0=[...LF("front"),...LF("rear"),Kt({...mp,id:"platform.rake",label:"rake at a state",unit:"\xB0",scale:.2,acrossStates:"span"},e=>e.rakeDeg),Kt({...mp,id:"platform.pitch",label:"pitch at a state",unit:"\xB0",scale:.2,acrossStates:"max"},e=>e.pitchDeg),Kt({...mp,id:"platform.roll",label:"body roll at a state",unit:"\xB0",scale:.2,acrossStates:"max"},e=>e.rollDeg),Kt({...mp,id:"platform.groundClearance",label:"ground clearance at a state",unit:"mm",scale:5,acrossStates:"min",unavailable:e=>L0(e.vehicle)},e=>e.clearance?.height),Kt({...wc,id:"platform.balance",label:"balance at a state",unit:"%",scale:1,acrossStates:"span"},e=>e.aero?.balance),Kt({...wc,id:"platform.clA",label:"downforce Cl\xB7A at a state",unit:"m\xB2",scale:.1,acrossStates:"mean"},e=>e.aero?.clA),Kt({...wc,id:"platform.cdA",label:"drag Cd\xB7A at a state",unit:"m\xB2",scale:.05,acrossStates:"mean"},e=>e.aero?.cdA),Kt({...wc,id:"platform.dataMargin",label:"margin to the model\u2019s data",unit:"mm",scale:5,acrossStates:"min"},e=>e.aero?.dataMargin),Kt({...wc,id:"platform.loopMargin",label:"aero-elastic margin, 1 \u2212 loop gain",unit:"-",scale:.1,acrossStates:"min"},e=>e.aero?.loopMargin)];var DF={understeer:"operating",yawFreq:"speed",yawZeta:"speed",yawStiffness:"operating",steeringTorque:"operating",steeringTorqueGradient:"operating"};function nt(e,t,r,n="cheap"){let o=Ib[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,...DF[e]?{reads:DF[e]}:{},read:(a,s)=>{let i=a.dynInput(),c=a.dynCtx(s);return i&&c?o.compute(i,c):NaN}}}var jO=[nt("understeer","Handling \u2014 balance",.1),nt("tlltdFront","Handling \u2014 balance",5),nt("rollStiffFront","Handling \u2014 balance",5)],UO=[nt("yawFreq","Handling \u2014 response",.5),nt("yawZeta","Handling \u2014 response",.2),nt("stabilitySpeed","Handling \u2014 response",50),nt("yawStiffness","Handling \u2014 response",2e4,"trim")],XO=[nt("steeringTorque","Steering feel",1,"trim"),nt("steeringTorqueGradient","Steering feel",2,"trim")],qO=[nt("rollGradient","Ride & body",.5),nt("pitchGradient","Ride & body",.5),nt("rideFreqFront","Ride & body",.5),nt("rideFreqRear","Ride & body",.5),nt("rollFreq","Ride & body",.5),nt("pitchFreq","Ride & body",.5),nt("zetaFront","Ride & body",.2),nt("zetaRear","Ride & body",.2)],QO=[{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}],ZO=[{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}],W0=[...jO,...UO,...XO,...qO,...QO,...ZO];function JO(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 j0=[{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)=>JO(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 eV(e,t){let r=/^(.*?)\s*\(([^)]+)\)\s*$/.exec(e);return r?{label:r[1],unit:r[2]}:{label:e,unit:t?"s":""}}function tV(e){return e==="s"||e==="kWh"?.1:e==="km/h"?2:1}var EF=new WeakMap;function pp(e){let t=EF.get(e);return t||(t=e.metrics.filter(Hc).map(r=>{let{label:n,unit:o}=eV(r.label,r.format==="time");return{id:`event.${e.id}.${r.key}`,group:`Events \xB7 ${e.label}`,groupShort:"Events",label:n,unit:o,scale:tV(o),scope:"car",cost:"session",read:a=>a.session(e.id)?.[r.key]??NaN}}),EF.set(e,t),t)}var U0=Na.flatMap(pp);var dp=[...$0,...G0,...Y0,...W0,...j0,...U0],Xa=Object.fromEntries(dp.map(e=>[e.id,e]));var IF={all:dp,byId:Xa},_F=new WeakMap;function Ur(e=[]){if(e.length===0)return IF;let t=_F.get(e);if(t)return t;let r=ag(e).filter(n=>!Oa(n.id)).flatMap(pp);return t=r.length?{all:[...dp,...r],byId:{...Xa,...Object.fromEntries(r.map(n=>[n.id,n]))}}:IF,_F.set(e,t),t}var Cc=180/Math.PI,qa=Math.PI/180,nV=.2;function fp(e,t){let r=H(t,e);return q(r[0]<0?Ad(r):r)}var hp=e=>({side:Math.atan2(e[2],e[0])*Cc,plan:Math.atan2(e[1],e[0])*Cc}),bp=(e,t)=>q([1,Math.tan(t*qa),Math.tan(e*qa)]),Tc=e=>Math.abs(e[0])>=nV,gp=(e,t)=>Math.atan(t/Math.max(e,1))*Cc,yp=(e,t)=>Math.tan(t*qa)*Math.max(e,1);var An=["side","plan","clock","len"],Xt={uca:{fore:"ucaFront",aft:"ucaRear",ball:"uprightUpper"},lca:{fore:"lcaFront",aft:"lcaRear",ball:"uprightLower"}},Pc={uca:"upper arm",lca:"lower arm"},oV=1,NF=(e,t)=>fp(e[Xt[t].fore],e[Xt[t].aft]);function OF(e){let t=q(H(Sd,U(e,X(Sd,e))));return{e1:t,e2:ae(e,t)}}function X0(e,t){let r=NF(e,t);if(!Tc(r))return`the ${Pc[t]}'s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it`;let n=Xt[t],o=tn(e[n.ball],e[n.fore],r);return Math.hypot(...H(o,e[n.ball]))>=oV?null:`the ${Pc[t]}'s ball joint sits on its own pivot axis, so the arm has no length to swing on`}function Xr(e,t){let r=Xt[t],n=e[r.ball],o=NF(e,t),a=tn(n,e[r.fore],o),s=H(a,n),i=Math.hypot(s[0],s[1],s[2]),{e1:c,e2:l}=OF(o),u=i>0?U(s,1/i):c;return{...hp(o),clock:Math.atan2(X(u,l),X(u,c))*Cc,len:i,sFront:X(H(e[r.fore],a),o),sRear:X(H(e[r.aft],a),o)}}function q0(e,t){let r=bp(e.side,e.plan),{e1:n,e2:o}=OF(r),a=ee(U(n,Math.cos(e.clock*qa)),U(o,Math.sin(e.clock*qa))),s=ee(t,U(a,e.len));return{fore:ee(s,U(r,e.sFront)),aft:ee(s,U(r,e.sRear))}}function VF(e,t,r,n){let o=Xt[t],a={...Xr(e,t),[r]:n},{fore:s,aft:i}=q0(a,e[o.ball]);return{...e,[o.fore]:s,[o.aft]:i}}function BF(e,t){return t==="clock"?e.len:Math.abs(e.sFront-e.sRear)/2}function xp(e,t,r){return t==="len"?r:gp(BF(e,t),r)}function Q0(e,t,r){return t==="len"?r:yp(BF(e,t),r)}var vo=["side","plan","atY","atZ"],ko={fore:"rockerPivotA",aft:"rockerPivotB"},aV=5,$F=e=>fp(e.rockerPivotA,e.rockerPivotB);function Qa(e){return Math.hypot(...H(e.rockerPivotB,e.rockerPivotA))<aV?"the rocker\u2019s two pivots are the same point, so there is no axis to describe":Tc($F(e))?null:"the rocker\u2019s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it"}function Fn(e){let t=$F(e),r=Tc(t)?t:[1,0,0],n=e.rockerPivotA,o=ee(n,U(r,-n[0]/r[0]));return{...hp(r),atY:o[1],atZ:o[2],sA:X(H(n,o),r),sB:X(H(e.rockerPivotB,o),r)}}function Z0(e){let t=bp(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 GF(e,t,r){if(Qa(e))return e;let{a:n,b:o}=Z0({...Fn(e),[t]:r});return{...e,rockerPivotA:n,rockerPivotB:o}}var KF=e=>Math.abs(e.sA-e.sB)/2;function J0(e,t,r){return t==="side"||t==="plan"?gp(KF(e),r):r}function ey(e,t,r){return t==="side"||t==="plan"?yp(KF(e),r):r}var Qt={front:"Front",rear:"Rear"},qt=["x","y","z"],Ve=(e,t)=>t==="front"?e.front:e.rear,Lc=(e,t,r)=>t==="front"?{...e,front:r}:{...e,rear:r},HF=[{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"}]}],zF={damperChassis:"strut top mount",pushrodOuter:"strut lower mount"},Mo=30;function sV(e){let t=[];for(let r of["front","rear"]){let n=Ve(e.vehicle,r).config.layout==="mcpherson";for(let o of HF)for(let{key:a,label:s}of o.keys){let i=n&&zF[a]||s;for(let c=0;c<3;c++)t.push({id:`hp.${r}.${a}.${qt[c]}`,group:`${Qt[r]} hardpoints \u2014 ${o.kind}`,label:`${i} ${qt[c]}`,scope:Qt[r],unit:"mm",defaultSpan:Mo,read:l=>Ve(l.vehicle,r).hardpoints[a][c],write:(l,u)=>{let m=Ve(l.vehicle,r),f=[...m.hardpoints[a]];f[c]=u;let p={...m.hardpoints,[a]:f};return{...l,vehicle:Lc(l.vehicle,r,{...m,hardpoints:p})}}})}}return t}var iV={side:"axis side-view angle",plan:"axis plan-view angle",clock:"arm clock angle",len:"effective arm length"},cV={side:"\xB0",plan:"\xB0",clock:"\xB0",len:"mm"};function lV(e){let t=[];for(let r of["front","rear"]){let n=Ve(e.vehicle,r).config.layout==="mcpherson";for(let o of["uca","lca"]){let a=Ve(e.vehicle,r).hardpoints,s=X0(a,o)?null:Xr(a,o);for(let i of An)t.push({id:`arm.${r}.${o}.${i}`,group:`${Qt[r]} ${n?"arm axes":"wishbone axes"}`,label:`${Pc[o]} \u2014 ${iV[i]}`,scope:Qt[r],unit:cV[i],defaultSpan:s?xp(s,i,Mo):Mo,read:c=>Xr(Ve(c.vehicle,r).hardpoints,o)[i],write:(c,l)=>{let u=Ve(c.vehicle,r),m=VF(u.hardpoints,o,i,l);return{...c,vehicle:Lc(c.vehicle,r,{...u,hardpoints:m})}}})}}return t}var uV={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"},mV={side:"\xB0",plan:"\xB0",atY:"mm",atZ:"mm"};function pV(e){let t=[];for(let r of["front","rear"]){let n=Ve(e.vehicle,r).hardpoints,o=Qa(n)?null:Fn(n);for(let a of vo)t.push({id:`rocker.${r}.${a}`,group:`${Qt[r]} rocker axis`,label:`rocker \u2014 ${uV[a]}`,scope:Qt[r],unit:mV[a],defaultSpan:o?J0(o,a,Mo):Mo,read:s=>Fn(Ve(s.vehicle,r).hardpoints)[a],write:(s,i)=>{let c=Ve(s.vehicle,r),l=GF(c.hardpoints,a,i);return{...s,vehicle:Lc(s.vehicle,r,{...c,hardpoints:l})}}})}return t}var Rp={front:"heaveFrontDesign",rear:"heaveRearDesign"},ty={front:"arbFrontDesign",rear:"arbRearDesign"};function dV(e,t){return{heave:e.config.actuation==="decoupled"?"heave element":"third spring",roll:t?.design.kind==="coil"?"roll shock":"anti-roll bar"}}var vp=e=>/^(heave|roll)\.(front|rear)\.(outer|inner|anchor)\.[xyz]$/.test(e);function fV(e){let t=[];for(let r of["front","rear"]){let n=Ve(e.vehicle,r),o=e.params[Rp[r]],a=e.params[ty[r]],s=dV(n,a),i=d=>d.params[Rp[r]],c=d=>d.params[ty[r]],l=(d,h)=>({...d,params:{...d.params,[Rp[r]]:h}}),u=(d,h)=>({...d,params:{...d.params,[ty[r]]:h}}),m={group:`${Qt[r]} heave & roll elements`,scope:Qt[r]},f=(d,h,b,g,y)=>{for(let R of b)t.push({...m,id:`${d}.${qt[R]}`,label:`${h} ${qt[R]}`,unit:"mm",defaultSpan:Mo,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=an(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 hV=[{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 bV(e){let t=[];for(let r of["front","rear"]){let n=Ve(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:Qt[r],unit:"N/mm",defaultSpan:Math.max(500,l*.4),read:u=>i(Ve(u.vehicle,r).compliance??{})??l,write:(u,m)=>{let f=Ve(u.vehicle,r),p={...f,compliance:c(f.compliance??{},Math.max(1,m))};return{...u,vehicle:Lc(u.vehicle,r,p)}}})};for(let a of["ucaFront","ucaRear","lcaFront","lcaRear","tieRod","pushRod"])o(`link.${a}`,`${gV[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}`,`${yV[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 gV={ucaFront:"UCA front leg",ucaRear:"UCA rear leg",lcaFront:"LCA front leg",lcaRear:"LCA rear leg",tieRod:"tie rod",pushRod:"push/pull rod"},yV={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 xV(){return hV.map(e=>({id:`cfg.${e.axle}.${e.field}`,group:e.group,label:e.label,scope:Qt[e.axle],unit:e.unit,defaultSpan:e.span(e.fallback),read:t=>Ve(t.vehicle,e.axle).config[e.field]??e.fallback,write:(t,r)=>{let n=Ve(t.vehicle,e.axle),o={...n,config:{...n.config,[e.field]:r}};return{...t,vehicle:Lc(t.vehicle,e.axle,o)}}}))}function RV(e){let t=Bn(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=>Bn(c.params.steeringSystem)[n],write:(c,l)=>({...c,params:{...c.params,steeringSystem:Bn({...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 vV(e){let t=Mi(e.params),r=[];for(let n of["front","rear"]){if(t[n]!=="diff")continue;let o=eo(e.params.driveline?.[n]);if(o?.kind!=="clutch"&&o?.kind!=="torsen")continue;let a=(s,i)=>{let c=_u[`${n}.${s}`];return{id:`driveline.${n}.${s}`,group:"Differential",label:c.label.charAt(0).toLowerCase()+c.label.slice(1),scope:Qt[n],unit:c.unit===": 1"?"":c.unit??"",defaultSpan:i,read:l=>eo(l.params.driveline?.[n])?.[s],write:(l,u)=>({...l,params:{...l.params,driveline:Iu({...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 kV(e){if(tu(e.params)!=="hydraulic")return[];let t=[{id:"brakeSetup.barFront",group:"Brakes",label:`${Ph("barFront").toLowerCase()}, front share`,unit:"-",defaultSpan:.05,read:a=>Pr(a.params.brakeSetup).barFront,write:(a,s)=>({...a,params:{...a.params,brakeSetup:Pr({...Pr(a.params.brakeSetup),barFront:s})}})}];if(!e.params.brakeModel)return t;let r=sr(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:Th(a.circuit?`${a.circuit}.${String(a.key)}`:a.key),unit:s,defaultSpan:i,read:c=>n(sr(c.params.brakeModel),a),write:(c,l)=>{let u=sr(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:sr(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 YF=e=>!!e&&typeof e=="object"&&"value"in e&&"label"in e;function WF(e){let t={...e};for(let r of Object.keys(t)){let n=t[r];YF(n)&&(t[r]={...n})}return t}function MV(e){let t=[];for(let r of Xk(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 YF(s)?s.value:NaN},write:(a,s)=>{let i=WF(a.params);return $u(i,n.label,s),{...a,params:i}}})}return t}function jF(e){let t={};for(let s of["front","rear"]){if(!Ve(e.vehicle,s).measured)continue;let c="this axle is described by measured curves, so its linkage is not solved";for(let l of HF)for(let{key:u}of l.keys)for(let m of qt)t[`hp.${s}.${u}.${m}`]={why:c};for(let l of["uca","lca"])for(let u of An)t[`arm.${s}.${l}.${u}`]={why:c};for(let l of vo)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 qt)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(Ve(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 qt)t[`hp.${s}.${c}.${l}`]={why:i};for(let c of vo)t[`rocker.${s}.${c}`]={why:i}}for(let s of["front","rear"]){let i=Ve(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 qt)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=Ve(e.vehicle,s),c=e.params[Rp[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.${qt[f]}`]={why:`the rocker shaft runs along ${qt[f]} \u2014 this only slides the eye along it`})}for(let s of["front","rear"]){let i=Ve(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 qt)t[`hp.${s}.${l}.${u}`]={why:c,useInstead:`hp.${s}.damperChassis.${u}`};for(let l of An)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=Ve(e.vehicle,s);if(i.measured)continue;for(let l of["uca","lca"]){if(l==="uca"&&i.config.layout==="mcpherson")continue;let u=X0(i.hardpoints,l);if(u)for(let m of An)t[`arm.${s}.${l}.${m}`]={why:u,useInstead:`hp.${s}.${Xt[l].fore}.z`}}let c=Qa(i.hardpoints);if(c&&i.config.actuation!=="direct")for(let l of vo)t[`rocker.${s}.${l}`]={why:c,useInstead:`hp.${s}.${ko.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?gb:yb;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(Ou))t[`param.${s}`]={why:i};for(let[s,i]of Object.entries(Vu(e.params)))t[`param.${s}`]={why:i};let a=tu(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 UF(e){let t={...AV,...jF(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[...sV(e),...lV(e),...pV(e),...fV(e),...xV(),...RV(e),...kV(e),...vV(e),...bV(e),...MV(e.params)].map(r)}var SV={spring_front:"cfg.front.springRate",spring_rear:"cfg.rear.springRate"},AV=Object.fromEntries(Object.entries(bb).map(([e,t])=>[`param.${e}`,{why:t,useInstead:SV[e]}])),ct=e=>e.scope?`${e.scope} \xB7 ${e.label}`:e.label;function Ht(e){let t={};for(let n of UF(e))t[n.id]=n;let r=(n,o)=>{if(typeof o!="string")return;let a=xF(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 ry=e=>e.step!==void 0&&Number.isFinite(e.step)&&e.step>0?e.step:0,ny=e=>ry(e)>0||(e.values?.length??0)>0,oy=e=>e.some(ny),XF=e=>1e-9*Math.max(1,Math.abs(e.lo),Math.abs(e.hi));function qF(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=ry(e);if(!r||!Number.isFinite(e.start))return t;let n=XF(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 QF=(e,t)=>t.map((r,n)=>e[n]&&ny(e[n])?qF(e[n],r):r);function ay(e,t=1e3){if(e.values?.length)return e.values.length;let r=ry(e);if(!r||!Number.isFinite(e.start))return 1/0;let n=XF(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 sy(e,t,r){let n=QF(e.variables,t),o=n.every((a,s)=>a===t[s]);return{x:n,score:o?r:Fr(e,n)}}function ly(e,t){if(!e.variables.some(JF))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(ew(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 JF=e=>!!(e.fixed||e.around||e.follows)||ew(e),ew=e=>!!e.values?.length&&(e.lo!==Math.min(...e.values)||e.hi!==Math.max(...e.values));function Dt(e,t){if(!t.variables.some(JF))return t;let r=Ht(e);return ly(t,n=>{let o=r[n];if(!o)return NaN;try{return o.read(e)}catch{return NaN}})}function Zt(e){return[...e.objectives,...e.constraints,...e.watches??[]]}var Mp=e=>(e.metrics??Ur()).byId;function uy(e,t){t=Dt(e,t);let r=Ht(e),n=[];for(let o of t.variables){let a=r[o.id];a&&n.push({id:a.id,name:ct(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 Sp(e,t,r){t=Dt(e,t);let n=Ht(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]))}),dy(e,o,t.followers,n)}function my(e,t,r={}){let n=t.states??[],o=n.some(c=>c.follows);if(!o&&!t.envelopeFollows)return t;let a=Sn(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=t0(n,c,CV(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=Mp(r),u=py(t,l),m=Zt(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=Sn(e,{density:t.density,envelope:h,assemble:r.assemble,numerics:r.numerics});return m.every(({r:g,m:y})=>Number.isFinite(Lt(b,y,g.at)))},p=c.length===s.length?wV(e,n0(c,u),u):null,d=p&&m.length?FV(p,f):p;d&&!o0(d,t.envelope)&&(i=d)}return s===n&&i===t.envelope?t:{...t,states:s,envelope:i}}var kp=3;function FV(e,t){let r=(c,l)=>t({...e,travelMin:c,travelMax:l}),n=e.travelMin-kp,o=e.travelMax+kp;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+kp)),i=Math.max(1,Math.min(e.travelMax,o-kp));return s===e.travelMin&&i===e.travelMax?e:{...e,travelMin:s,travelMax:i}}function py(e,t){let r=new Set;for(let n of Zt(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 wV(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:xc.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 CV(e){let t=e.projectTrack?.();if(!t)return null;try{return e0(it(t.asset,t.numerics))}catch{return null}}function dy(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 Dc(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 tw=(e,t="")=>t&&t!=="-"?`${e} ${t}`:`${e}`;function rw(e,t,r){let n=t??Xa[e.metricId],o=(n?et(n):e.metricId)+Ec(e.at,n,r),a=s=>tw(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 Ec(e,t,r){if(!e&&t?.reads!=="state")return"";e??={};let n=[];if(t?.reads==="state")if(e.stateId===Wr)n.push(B0(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&&O0(t)&&n.push(`${(e.speed*3.6).toFixed(0)} km/h`),e.ayG!==void 0&&V0(t)&&n.push(`${e.ayG.toFixed(2)} g`),e.courseId===Mc&&t?.reads==="course")n.push(N0(t));else if(e.courseId&&t?.reads==="course"){let o=r?.lap.courses.find(a=>a.id===e.courseId);o&&n.push(b0(o))}return n.length?` @ ${n.join(", ")}`:""}function nw(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 ow=5e-4;function aw(e,t){return e.cost!=="lap"&&e.cost!=="session"?0:Number.isFinite(t)?ow*Math.abs(t):0}function Ap(e,t,r={}){t=Dt(e,t);let n=uy(e,t),o=Ht(e),a=Mp(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=Lt(f,b,h.at);if(!Number.isFinite(g))return{ok:!1,violation:f.failure?.violation??400,reason:f.failure?.reason??`${et(b)} could not be computed`};let y=Dc(h,g);y>0&&(p+=y/b.scale,d.push(`${rw(h,b,t)} (${tw(g.toFixed(3),b.unit)})`))}return d.length===0?Ks:{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=dy(e,f,t.followers,o),{car:f,ev:Sn(f,{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 f=u(i,m);if(!f.ok)return f;for(let{spec:p,metric:d}of c)Lt(m,d,p.at);for(let{spec:p,metric:d}of l)Lt(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=Lt(m,p,f.at);return{name:et(p)+Ec(f.at,p,t),raw:d,unit:p.unit,weight:f.weight,contribution:nw(f,p,d),resolution:Math.abs(f.weight)*aw(p,d)/p.scale}})}}function iy(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 sw(e,t){if(e.variables.some(o=>o.id===t))return!0;let r=kc(t);if(!r||!lp.includes(r.axis))return!1;if(e.variables.some(o=>gr(o.id)?.point===r.point))return!0;let n=iy(t);return!!n&&e.variables.some(o=>/^(arm|rocker)\./.test(o.id)&&iy(o.id)===n)}function TV(e,t){let r=e.followers??[],n=new Map(r.map(i=>[i.id,i.follows])),o=i=>{let c=t[i],l=kc(i);return c&&l&&lp.includes(l.axis)?{name:ct({...c,label:c.label.replace(/ [xyz]$/,"")}),axis:l.axis}:{name:c?ct(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 sw(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 fy(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=Dt(e,t);let a=Ht(e),s=[],i=Mp(r),c=Zt(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=Zt(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),Wr]);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===Wr&&!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!==Wr?y.find(F=>F.id===k.at.stateId):void 0,M=x?H0(v,x):null;M?s.push(`${et(v)} ${M}. Point it at a state that does.`):!x&&!up(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 f=new Set([...t.lap.courses.map(y=>y.id),Mc]);for(let y of Zt(t))if(y.at?.courseId&&!f.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(`${ct(R)}: list two values or more, or fix it where it is.`):y.hi>y.lo?y.step!==void 0&&ay({...y,start:R.read(e)})<2&&s.push(`${ct(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(`${ct(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?ct(v):void 0;s.push(`${ct(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(`${ct(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=iy(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]?ct(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=kc(y);if(!R)continue;let k=gr(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`],F=M?ct({...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(...TV(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 Zt(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 Zt(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 iw=.1,cw=2e3,cy=3;function hy(e,t,r={},n=cw){t=Dt(e,t);let o=Ap(e,t,r),a=Mp(r),s=Ht(e),i=o.variables.map(S=>S.start),c=S=>{let A=o.build(S);return o.feasible(A).ok&&o.terms(A),A},l=c(i),u=o.feasible(l),m=[...t.objectives,...t.constraints],f=(S,A=m)=>{let P={};for(let L of A){let D=a[L.metricId];D&&(P[`${L.metricId}@${Ro(L.at)}`]=Lt(S.ev,D,L.at))}return P},p=S=>m.map(A=>S[`${A.metricId}@${Ro(A.at)}`]).map(A=>Number.isFinite(A)?A.toFixed(9):"x").join("|"),d=f(l,Zt(t)),h=p(d),b=[],g=[],y={},R=[],k=0;t.variables.forEach((S,A)=>{let P=s[S.id];if(!P)return;if(R.length>=cy&&k>n){g.push(P);return}let L=[...i];L[A]=i[A]+(S.hi-i[A])*.25||S.hi;let D=performance.now(),E=c(L),V=performance.now()-D;k+=V,R.push(V);let N=f(E);y[P.id]=N,p(N)===h&&b.push(P)});let v=t.variables[0],x=v?t.variables.indexOf(v):-1;for(let S=0;v&&R.length>0&&R.length<cy;S++){let A=[...i];A[x]=i[x]+(v.hi-i[x])*(.4+.15*S)||v.hi;let P=performance.now();c(A),R.push(performance.now()-P)}let M=[...R].sort((S,A)=>S-A),F=M.length?M[M.length>>1]:0,w=[],C=Zt(t).map(S=>S.metricId);if(C.some(S=>S.startsWith("dyn.trim")||S==="dyn.ymdMaxAy")){let S=l.ev.ymdLimit();S?.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."),!S&&l.ev.dynAvailable&&w.push("The yaw-moment diagram found no trim point, so anything read off the limit is unavailable.")}if(C.some(S=>S==="dyn.steeringTorque"||S==="dyn.steeringTorqueGradient")){let S=l.ev.tyre()?.model,A=S?sn(S):null;A==="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."):A==="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(S=>T.includes(S))){let A=l.ev.lapReserve()?.beyondFrac;if(A!==void 0&&Number.isFinite(A)){let P=(A*100).toFixed(0);A>=iw?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.`):A>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(...K0(l.ev,Zt(t).map(S=>({m:a[S.metricId],at:S.at})).filter(S=>!!S.m))),{msPerEval:F,values:d,samples:R.length,times:R,dead:b,moves:y,unprobed:g,warnings:w,beyondFrac:C.some(S=>T.includes(S))?l.ev.lapReserve()?.beyondFrac:void 0,startFeasible:u.ok,startReason:u.reason}}var LV=[{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:DV.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 DV=["setup:m","characteristics:peak_power","characteristics:power_to_weight","characteristics:cla","characteristics:cda","characteristics:pack_energy","characteristics:maxAy","characteristics:top_speed"];var Iie=new Set(LV.map(e=>e.kind));var lw={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 by=["FL","FR","RL","RR"],kt=(e,t,r)=>({input:e,from:r?r[0]:lw[e].from,to:r?r[1]:lw[e].to,n:t}),Vie=[{id:"sides",name:"Inside and outside",cards:[{id:"camber-roll",form:"curves",title:"Camber to the road through roll",sweep:kt("roll",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"toe-rack",form:"curves",title:"Wheel angle against the rack",sweep:kt("steer",25),wheels:["FL","FR"],y:["toe"]},{id:"camber-rack",form:"curves",title:"Camber to the road through the steer",sweep:kt("steer",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"load-roll",form:"curves",title:"Wheel loads through roll",sweep:kt("roll",25),wheels:by,y:["wheelLoad"]},{id:"travel-roll",form:"curves",title:"Wheel travel through roll",sweep:kt("roll",25),wheels:by,y:["travel"]},{id:"toe-roll",form:"curves",title:"Roll steer, all four",sweep:kt("roll",25),wheels:by,y:["toe"]}]},{id:"maps",name:"Travel and steer together",cards:[{id:"camber-map",form:"surface",title:"Camber over travel and rack",sweep:kt("travel",17),second:kt("steer",13),wheels:["FL"],y:["camber"]},{id:"bump-steer-map",form:"map",title:"Bump steer over travel and rack",sweep:kt("travel",17),second:kt("steer",13),wheels:["FL"],y:["bumpSteer"]},{id:"bump-steer-family",form:"curves",title:"Bump steer through travel, at five rack positions",sweep:kt("travel",25),second:kt("steer",5,[-20,20]),wheels:["FL"],y:["bumpSteer"]},{id:"scrub-map",form:"surface",title:"Scrub radius over travel and rack",sweep:kt("travel",17),second:kt("steer",13),wheels:["FL"],y:["scrubRadius"]}]}];function gy(e){let t=Number(e);return Number.isFinite(t)?Math.min(Jf,Math.max(Zf,t)):At}var mw=6e4;var Dce=[{within:60*6e4,every:mw},{within:1440*6e4,every:60*6e4},{within:720*60*6e4,every:1440*6e4},{within:1/0,every:10080*6e4}];var zV=new Set(["color","visible","source","origin"]),Hce=["id",...zV];var fw=.18/1.18,hw={induction:{kind:"natural"}},bw=e=>e.breathing??hw;function Fp(e){switch(e?.kind){case"sae-j1349":return Ji(99e3,25);case"measured":return Ji(e.hPa*100,e.tempC);default:return Ji(101325,20)}}var WV=Fp(void 0);function gw(e,t){let r=Fp(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 yw(e,t){let r=e.induction;if(r.kind==="table"){let o=s=>$e(r.densityAltitudeM,r.powerPct,s),a=o(Fp(e.rated).densityAltitudeM);return a>0?Math.max(0,o(t.densityAltitudeM)/a):0}let n=e.frictionShare??fw;return Math.max(0,(gw(e,t)-n)/(1-n))}var dw=new WeakMap;function xy(e,t){let r=e.asRated??e,n=`${t.p}|${t.pDry}|${t.T}`,o=dw.get(r);o||dw.set(r,o=new Map);let a=o.get(n);if(a)return a;let s=yw(bw(r),t),i={...r,torque:r.torque.map(c=>c*s),asRated:r};return o.set(n,i),i}function qV(e){return JSON.parse(Ry(vy(e,"public/laptime/index.json"),"utf8")).tracks}var QV=async e=>{let t=await fetch(e.url);if(!t.ok)throw new Error(`The track could not be read from ${Vm(e)} (${t.status}).`);return new Uint8Array(await t.arrayBuffer())};function xw(e,t=new Map,r=QV){let n=qV(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(!ic(o.address))throw new Error(`"${o.address}" is not a catalogue address`);if(!sc(o.link))throw new Error("This track is linked to a source this version does not read from.");i=await Bg(await r(o.link),o.link,o.address)}else if(o.kind==="catalogue"){if(!ic(o.address))throw new Error(`"${o.address}" is not a catalogue address`);let c=JSON.parse(Ry(vy(e,"public/catalogue",Gg(o.address)),"utf8"));i=await Hg(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(Ry(vy(e,"public/laptime",c),"utf8"))}return t.set(a,i),structuredClone(i)}}var ZV=9.81;function Rw(e,t=e.tireModel,r=e.tireModelRear){if(!t)return e;let n=e.m.value*ZV/4,o=Ma(e,t,r),a=Pe(o.front).rollingRadius(n),s=o.rear===o.front?a:Pe(o.rear).rollingRadius(n),i=JV(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 JV(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 e5=1e-6;function vw(e,t,r){let n=e.cgReference;if(!n||!e.cg_height)return e;let o=Gk(e,t,r);if(o===void 0||Math.abs(o-n.standingRadius)<e5)return e;let a=n.typed??e.cg_height.value;return{...e,cg_height:{...e.cg_height,value:ka(e.cg_height.value,n.standingRadius,o)},cgReference:{...n,standingRadius:o,typed:a}}}function kw(e,t,r){let n=e.rcRoad,o=e.rc_front,a=e.rc_rear;if(!n||!o||!a)return e;let s=Eu(e,t,r),i=$r(o.value,n.gainFront,n.radiusFront,s.front),c=$r(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 Mw=e=>({brakeFade:e.brakeFade,airTempC:e.airTempC,diffYaw:e.diffYaw,...ec(e.air)?{air:e.air}:{}});var So=(e,t)=>t?e.find(r=>r.id===t)?.model:void 0;function Ao(e){return{tire:t=>So(e.tires,t),motor:t=>So(e.motors,t),aero:t=>So(e.aeros,t),battery:t=>So(e.batteries,t),brake:t=>So(e.brakes??[],t),damper:t=>So(e.dampers??[],t),suspensionOf:t=>za(ky(e,t),t)}}function ky(e,t){let r=So(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 Fo(e,t,r){let n={front:t.tire(e.tireModelId),rear:t.tire(e.tireModelIdRear)};return My(Ik(t.suspensionOf(e),e,n),t,r)}function t5(e){return ec(e.air)?ZS(e.air,e.airTempC??At):void 0}var r5="the air the session states, at its venue";function n5(e,t){return t?{...e,rho:{...e.rho,value:t.rho},readouts:{...e.readouts,rho:r5}}:e}function o5(e,t,r){if(!r)return{rho:e.rho,motorModel:t,readouts:e.readouts};let{rho:n,readouts:o}=n5(e,r);return{rho:n,motorModel:t&&ft(t)?xy(t,r):t,air:r,readouts:o}}function My(e,t,r){let n=t.tire(e.tireModelId),o=t.tire(e.tireModelIdRear),a=kw(vw(Rw(Yk(Kk(Jk(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}=o5(a,t.motor(e.motorModelId),t5(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 c5=e=>e!==!1,l5=(e,t,r)=>r&&t>0?(e%t+t)%t:Math.min(Math.max(e,0),t);function u5(e,t,r){let n=e.points.filter(o=>Number.isFinite(o.at)&&Number.isFinite(o.z)).map(o=>({...o,at:l5(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 m5(e,t,r){let n=u5(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 p5(e,t,r,n){let o=t-e.at;return n&&r>0?o-r*Math.round(o/r):o}function d5(e,t,r,n){for(let s of e){let i=p5(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 Sw(e,t,r,n){let o=c5(n),a=m5(e,r,o);return a.length?t.map(s=>d5(a,s,r,o)):t.map(()=>0)}function Ic(e,t){if(!t?.points.length)return e;let r=dc(e),{zSmoothing:n,...o}=e;return{...o,z:Sw(t,r,p0(e),e.closed)}}var wp={widthLeft:1.5,widthRight:1.5,bank:0,mu:1};function Aw(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 _c(e,t){let r=Aw(e.source);return Fw(e,r?await t(r):void 0)}function Fw(e,t){let{source:r}=e;if(r.kind==="segments"){let{segments:i,closed:c,spacing:l}=r,{asset:u}=hc(i,{name:e.name,closed:c,spacing:l,base:wp});return Ic(u,r.profile)}let n=r.sections??[];if(r.kind==="inline")return Ic(Wm(r.asset,n,wp),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 Ic(Wm({...t,...o!==void 0?{widthLeft:o}:{},...a!==void 0?{widthRight:a}:{},...s!==void 0?{closed:s}:{}},n,wp),r.profile)}var yme=1/500;var xme=5*Math.PI/180;var Cme=1/3;var g5=[4,2,1,.5,.25,.125];function ww(e,t,r={}){let n=[...r.steps??g5].sort((g,y)=>y-g),o=st(r.numerics),a=r.tolPct??.5,s=Ft(e),i=e.ggvMode??"twoTrack",c=pr(s,!1,i),l={...o,dsTarget:n[0]??o.dsTarget},u=n.length?ao(s,c,[it(t,l)],l,i):void 0,m=xn(s,c.rows),f=n.map((g,y)=>{let R={...o,dsTarget:g},k=Date.now(),v=it(t,R),x=Rt(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 Za(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:gy(t.airTempC??r.airTempC),...ec(Tm(t.air??r.air))?{air:Tm(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:st(r.numerics)}}async function Cp(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 _c(r,t)}}function R5(e,t){let r=structuredClone(e);for(let[n,o]of Object.entries(t))if(!$u(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 Sy=(e,t)=>{let r=e?.name;return typeof r=="string"&&r?r:t};function v5(e,t){let r={};for(let n of kn){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:Sy(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:Sy(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:Sy(i.model,i.id),byFallback:!0}:null;continue}r[n.doc]=null}return r}function k5(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 Cw(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 Tw=e=>e.length<2?e[0]??"":`${e.slice(0,-1).join(", ")} and ${e[e.length-1]}`;async function Tp(e,t,r={}){let n=Za(e,r.settings),{entry:o,asset:a}=await Cp(e,t),s=Ao(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]?R5(d.params,r.overrides[d.id]):d.params;return Fo(structuredClone(h),s,n)}),l=ji(uo(e.meta.rulesetId,e.rulesets)),u=Zi(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}=bg(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:k5(u[h]),metrics:gg(l,u[h],p?.[d.id]),fitted:v5(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 Pw(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=Za(e),{asset:a}=await Cp(e,t),s=Fo(structuredClone(n.params),Ao(e),o);return ww(s,a,{...r.steps?{steps:r.steps}:{},numerics:o.numerics,...r.tolPct!==void 0?{tolPct:r.tolPct}:{},...r.onStep?{onStep:r.onStep}:{}})}var M5=(e,t)=>e[t]??[],S5=(e,t,r)=>r<=1?[e]:Array.from({length:r},(n,o)=>e+(t-e)*o/(r-1));function Pp(e){return e.kind==="param"?S5(e.start,e.end,Math.max(1,Math.round(e.steps))):e.kind==="part"?[...e.partIds]:[...e.values]}var Lw=e=>e.kind==="param"?e.label:e.kind==="part"?`${e.part} model`:e.setting;function A5(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=Fo(structuredClone(r.params),Ao(e),Za(e)),o=Qk(n,{geometry:!0}),a=Bu(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=kn.find(l=>l.doc===i.part);if(!c)throw new Error(`"${i.part}" is not a library \u2014 it is one of ${kn.map(l=>l.doc).join(", ")}`);for(let l of i.partIds)if(!M5(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*Pp(c).length,1);if(s>Am)throw new Error(`that grid is ${s} runs, over the ${Am} cap \u2014 a run is a whole session. Drop an axis or use fewer steps.`)}var F5=e=>e.map(t=>String(typeof t=="number"?Number(t.toPrecision(4)):t)).join(" \xD7 ");function w5(e,t){let r=[...new Set(e.flatMap(o=>(o.didNotFinish??[]).map(a=>a.label)))],n=e.map(o=>({name:F5(o.at),events:r.map(a=>({label:a,incomplete:o.didNotFinish?.find(s=>s.label===a)}))}));return Cw(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`:Tw(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 C5(e){let t=[[]];for(let r of e){let n=Pp(r),o=[];for(let a of n)for(let s of t)o.push([...s,a]);t=o}return t}async function Dw(e,t,r,n){A5(e,r);let o=C5(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=kn.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 Tp(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(Pp(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(Lw(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(...w5(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:Lw(u),values:Pp(u)})),runs:a,metricKeys:i,fleetScored:s,flat:c,caveats:l}}var Ide=Math.PI/180;function Ay(e){if(!e.chassis)return e;let{chassis:t,...r}=e;return r}var Kge=180/Math.PI;var k3={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:lo,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 hye=k3.id;var Nc=.02;function Yw(e){let t=Math.max(Nc,Math.abs(e.heaveMotionRatio)),r=Math.max(Nc,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 S3=(e,t)=>({od:t,id:Math.min(e.id,t-.5)}),A3=(e,t)=>e/(2*t*t);function zw(e,t){switch(e.kind){case"ubar":case"blade":case"torsionTube":return{...e,section:S3(e.section,t)};default:return e}}function Ww(e,t,r){let n=Math.max(Nc,Math.abs(r));if(e?.kind==="coil"){let l=A3(t,n),u=e.rate;if(typeof u=="number")return{...e,rate:l};let m=Vr(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=>yi(zw(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 zw(a,c)}function jw(e,t,r,n){let o=e?.design,a=Ww(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 F3=Math.PI/180,Lp=1e-6;function w3(e){return!(ve(e.rockerPivotA,e.rockerPivotB)<Lp||ve(e.rockerToPushrod,e.rockerPivotA)<Lp||ve(e.rockerToDamper,e.rockerPivotA)<Lp||ve(e.rockerToDamper,e.damperChassis)<Lp)}function Qw(e){if(!w3(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=ye(r,n,0);if(!o.ok||!Number.isFinite(o.state.metrics.damperLength))return!1}return!0}catch{return!1}}function Zw(e){if(e.config.actuation!=="direct"||Qw(e))return;let{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}=T3(e);return{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}}var Uw=40;function Dp(e,t={}){let r=e.hardpoints,n=r.pushrodOuter,o=r.damperChassis,a=ve(n,o),s=ee(n,U(H(o,n),C3)),i=t.armRod??Math.max(25,.15*a),c=t.armDamper??i,l=[s[0]-Uw,s[1],s[2]],u=[s[0]+Uw,s[1],s[2]],m=q(H(u,l)),f=H(n,s),p=q(H(f,U(m,Xw(f,m)))),d=It(p,m,(t.armAngleDeg??60)*F3),h=ee(s,U(d,i)),b=H(o,s),g=q(H(b,U(m,Xw(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 C3=.72,Xw=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2];function qw(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 T3(e,t={}){let r=t.target??qw(e),n=t.armAngleDeg,o=Dp(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=Dp(e,{armRod:s,armAngleDeg:n,damperSide:p}),h={...e,config:{...e.config,actuation:"rocker"},hardpoints:d};try{let b=tt(h),g=ye(b,15,0),y=ye(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 qw({...e,config:{...e.config,actuation:"rocker"},hardpoints:Dp(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 Dp(e,{armRod:u,armAngleDeg:n,armDamper:m,damperSide:i})}var Tye=Array.from({length:19},(e,t)=>-45+5*t);var Pye=Math.PI/180;function P3(e){let t=e.hardpoints,r=q(H(t.rockerPivotB,t.rockerPivotA)),n=tn(t.rockerToDamper,t.rockerPivotA,r),o=.6*en(H(t.rockerToDamper,n)),a=ae(r,Tx),s=en(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 L3=(e,t)=>({...e,config:{...e.config,actuation:t}});function Cy(e,t,r,n){let o=r==="front"?e.front:e.rear,a=Cu(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=Zn(e,t)[r]??Q(t,r==="front"?"arb_front":"arb_rear"),u=va(e,t)[r]??Q(t,r==="front"?"heave_spring_front":"heave_spring_rear"),m=Zw(o),f=L3(m?{...o,hardpoints:{...o.hardpoints,...m}}:o,"decoupled"),p=r==="front"?t.heaveFrontDesign:t.heaveRearDesign,d=n?.heave??Jw(p?.linkage,w=>En(f,w).atDesign)??Ud(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??Jw(h?g:c?.linkage,w=>jo(f,w,{kind:b}).atDesign)??(h?P3(f):gk(f)),R=En(f,d).atDesign,k=jo(f,y,{kind:b}).atDesign,v=Pu(e,t),x=Yw({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=jw({design:p?.design??{kind:"none"},linkage:d,damper:p?.damper},M,x,k);return m?{...F,crank:m}:F}function Jw(e,t){return e&&Math.abs(t(e))>=Nc?e:void 0}var Ep=[{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"]}],Ty=()=>({arbFront:void 0,arbRear:void 0,heaveFront:void 0,heaveRear:void 0}),D3={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]}},E3={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]}},I3=()=>({outer:[0,189,486],attach:"rocker",mount:{kind:"chassis",anchor:[-225,0,486]}}),_3={rate:60,motionRatio:1},N3={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]}},O3=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]}},V3={kind:"coil",rate:1560,motionRatio:1,gap:0,bothWays:!0},B3=40,$3={rockerPivotA:[50,130,440],rockerPivotB:[-50,130,440],rockerToPushrod:[10,170,460],rockerToDamper:[-20,64,440],damperChassis:[-20,64,215]},eC=()=>({outer:[-50,130,480],attach:"rocker",shaftStation:-50}),tC=()=>({outer:[50,130,400],inner:[50,130,480],attach:"rocker",shaftStationOuter:50,shaftStationInner:50}),G3=e=>[e[0],e[1],e[2]];function K3(e){let t=r=>({...r,hardpoints:{...r.hardpoints,...nC($3)},config:{...r.config,actuation:"decoupled"}});return{...e,front:t(e.front),rear:t(e.rear)}}function nC(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,G3(r)]))}function oC(e,t=bo(),r=e==="pull"?E3:D3){let n=(o,a)=>({...o,hardpoints:{...o.hardpoints,...nC(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 Ip(e,t){let r=Py(e),n=Ja(e);if(e==="heave")return{meta:r,vehicle:n,components:{...Ty(),heaveFront:{design:{...mb,..._3},linkage:I3()}}};if(e!=="decoupled")return{meta:r,vehicle:n,components:Ty()};let o=Cy(n,t,"front",{heave:eC(),roll:tC()}),a=Cy(n,t,"rear",{heave:eC(),roll:tC()});return{meta:r,vehicle:n,components:{arbFront:o.arb,arbRear:a.arb,heaveFront:o.heave,heaveRear:a.heave}}}function Ja(e){let{name:t}=Py(e);if(e==="direct")return{...rc(),name:t};if(e==="mcpherson"){let n=nc(),o=Lm();return{...n,front:{...o,config:{...o.config,loadedRadius:n.front.config.loadedRadius}},name:t}}let r=H3(oC(e==="pullrod"?"pull":"push"));return{...e==="decoupled"?K3(r):r,name:t}}var rC={front:221.7,rear:220.9};function H3(e){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:rC.front}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:rC.rear}}}}function Py(e){let t=Ep.find(r=>r.id===e);if(!t)throw new Error(`Unknown suspension template: ${e}`);return t}function _p(){let e=t=>({design:{...V3},linkage:O3(t),damper:B3});return{meta:Py("heave"),vehicle:oC("push",Sg(),N3),components:{...Ty(),heaveFront:e("front"),heaveRear:e("rear")}}}var aC=[10,25,50,100,200,300],z3=[{id:"c1",label:"Soft",scale:.7},{id:"c2",label:"Medium",scale:1},{id:"c3",label:"Firm",scale:1.4}],sC=e=>Math.round(e*100)/100;function Y3(e,t,r){let n=aC.map(o=>sC(r*o));return{id:e,label:t,speedMmS:[...aC],bumpN:n,reboundN:[...n]}}function W3(e){return{name:e.name,body:{...e.body},curves:z3.map(t=>Y3(t.id,t.label,sC(e.coefficient*t.scale)))}}function Oc(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 yr(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:lc[e.dampers.length%lc.length],model:W3(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 lt=e=>`${e} (typical)`,Ly={car:{name:lt("Formula Student damper"),coefficient:2.5,body:{extended:249,stroke:55}}},Np={car:Ly.car,heave:{name:lt("Formula Student heave damper"),coefficient:3.4,body:{extended:270,stroke:47}},roll:{name:lt("Formula Student roll damper"),coefficient:3.7,body:{extended:322,stroke:100}}},Op={car:{name:lt("Formula 1 damper"),coefficient:6,body:{extended:240,stroke:40}},heave:{name:lt("Formula 1 heave damper"),coefficient:40,body:{extended:240,stroke:40}}},iC={car:{name:lt("GT damper"),coefficient:4.5,body:{extended:510,stroke:80}}},Dy={car:{name:lt("Sports car damper"),coefficient:2.4,body:{extended:515,stroke:110}}},cC={car:{name:lt("Sports car strut"),coefficient:2.4,body:{extended:310,stroke:120}},rear:Dy.car},lC={car:{name:lt("Cup car strut"),coefficient:4,body:{extended:285,stroke:75}},rear:{name:lt("Cup car rear damper"),coefficient:3.5,body:{extended:505,stroke:80}}},uC={car:{name:lt("Stock car front damper"),coefficient:7.5,body:{extended:555,stroke:110}},rear:{name:lt("Stock car rear damper"),coefficient:6.75,body:{extended:555,stroke:110}}},mC={car:{name:lt("Hill-climb front damper"),coefficient:3,body:{extended:285,stroke:65}},rear:{name:lt("Hill-climb rear damper"),coefficient:3.5,body:{extended:285,stroke:65}}},pC={car:{name:lt("Race truck front damper"),coefficient:12,body:{extended:780,stroke:160}},rear:{name:lt("Race truck rear damper"),coefficient:8.5,body:{extended:780,stroke:160}}};function ts(e){return e.vehicles=e.vehicles.slice(0,1),e.activeVehicleId=e.vehicles[0]?.id??null,e}function wn(e,t){let r=uc(e);return r.meta.rulesetId=t,r}function wo(e,t,r,n){let o=wn(e,t);return o.suspensions=[{...o.suspensions[0],model:n()}],o.vehicles=[qg(r,"v1",0)],o.activeVehicleId="v1",o}var[,j3,U3,X3,q3,Q3,Z3,J3]=Dg;function Ey(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 dC(){return{...Ja("decoupled"),name:bo().name}}var eB=[{label:"Formula Student (decoupled)",vehicle:dC,components:e=>Oc(Ip("decoupled",e).components,Np)},{label:"Formula 1 (third springs)",vehicle:()=>_p().vehicle,components:()=>Oc(_p().components,Op)}],Iy={"direct-coilover":"direct",pushrod:"pushrod",pullrod:"pullrod","third-spring":"heave","mcpherson-strut":"mcpherson"},tB=[...eB.map(e=>e.vehicle),...Object.values(Iy).map(e=>()=>Ja(e))];function es(e){let t=Oc(Ip("decoupled",e.vehicles[0].params).components,Np);e.suspensions=[{...e.suspensions[0],model:dC()}];for(let r of e.vehicles)Ey(r.params,t);return yr(e,Np),e}var Co={title:"OpenStreetMap",url:"https://www.openstreetmap.org/copyright",licence:"ODbL-1.0",credit:"\xA9 OpenStreetMap contributors"},Vp={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"},fC={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]"},hC={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"},rB={id:"cota",name:"Circuit of the Americas, Austin",address:"e0c6ea889d708cf15f9c",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,Vp,hC]}},nB={id:"laguna-seca",name:"Laguna Seca, Monterey",address:"185b5811b9c423ef44ef",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,Vp,hC]}},oB={id:"nordschleife",name:"Nordschleife, N\xFCrburg",address:"74c49603c7b2f15985c6",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,fC]}},aB={id:"brands-hatch",name:"Brands Hatch, Kent",address:"c4953e3c25eaba4a5b7e",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,{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."}]}},sB={id:"bristol",name:"Bristol, Tennessee",address:"f0e23953669a414ad600",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,Vp]}},iB={id:"pikes-peak",name:"Pikes Peak, Colorado",address:"3de137fe33b5c2875036",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,Vp]},standingStart:!0},cB={source:"venue",altitudeM:3580,pressure:{kind:"standard"},humidityPct:0},lB=10,uB={id:"nurburg-sprint",name:"Sprintstrecke, N\xFCrburg",address:"1875636cdbb615aa2756",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,fC]}};function To(e,t){let{id:r,name:n,address:o,provenance:a,standingStart:s}=t,i={kind:"catalogue",id:r,address:o},c=oc(Kg({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 Cn(e,t,r){let n=e.vehicles[0].params,o=`m${e.motors.length+1}`;e.motors=[...e.motors,{id:o,color:Mn[e.motors.length%Mn.length],model:t}];let a=Vk({},{...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 mB=3.8,Bp={hubPlanetary:14.5,inboardChain:4,engineChain:3.4},pB="Hub motor, 35 kW (example)";function _y(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 bC(e){let t=e.motors.find(r=>r.id==="m1");return t.model={...t.model,name:pB},t.id}function $p(e,t,r){let n=ts(es(wn(e,r)));return n.vehicles[0].params.name=t,n}function dB(){let e=$p("Formula Student combustion car","Formula Student combustion","fs-cv");Cn(e,Og(),Bp.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 fB(){let e=$p("Formula Student AWD car","Formula Student AWD","fs-ev");return _y(e,bC(e),4,"awd",Bp.hubPlanetary,"hub"),e}function hB(){let e=$p("Formula Student RWD hub-motor car","Formula Student RWD hub motors","fs-ev");return _y(e,bC(e),2,"rear",Bp.hubPlanetary,"hub"),e}function bB(){let e=$p("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:Mn[e.motors.length%Mn.length],model:Ng()}],_y(e,t,1,"rear",Bp.inboardChain),e.vehicles[0].params.driveline={rear:structuredClone(xt.clutch)},e}function gB(){let e=ts(es(wn("Formula Student endurance energy","fs-ev"))),t=e.vehicles[0],r=structuredClone(t);if(r.id="v2",r.color=cc[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 yB(){let e=_p(),t=wo("Formula 1 car","trackday",j3,()=>e.vehicle);return Ey(t.vehicles[0].params,Oc(e.components,Op)),yr(t,Op),Cn(t,Vg(),mB),To(t,rB)}function gC(e="GT car",t=rc){let r=wo(e,"trackday",U3,t);return yr(r,iC),Cn(r,pA(),r.vehicles[0].params.gear_ratio.value),To(r,nB)}function yC(e="Sports car",t=nc,r=Dy){let n=wo(e,"trackday",X3,t);return yr(n,r),Cn(n,dA(),n.vehicles[0].params.gear_ratio.value),To(n,oB)}function xB(){let e=wo("Cup car","trackday",q3,eA);return yr(e,lC),Cn(e,fA(),e.vehicles[0].params.gear_ratio.value),To(e,aB)}function RB(){let e=wo("Stock car","trackday",Q3,tA);return yr(e,uC),Cn(e,hA(),e.vehicles[0].params.gear_ratio.value),To(e,sB)}function vB(){let e=wo("Hill-climb prototype","trackday",Z3,rA);return yr(e,mC),Cn(e,bA(),e.vehicles[0].params.gear_ratio.value),e.settings.air=structuredClone(cB),e.settings.airTempC=lB,To(e,iB)}function kB(){let e=wo("Race truck","trackday",J3,nA);return yr(e,pC),Cn(e,gA(),e.vehicles[0].params.gear_ratio.value),To(e,uB)}function MB(e){let t=Ep.find(o=>o.id===e);if(e==="direct")return gC(t.name,()=>Ja(e));if(e==="mcpherson")return yC(t.name,()=>Ja(e),cC);let r=ts(wn(t.name,"trackday")),n=Ip(e,r.vehicles[0].params);return r.suspensions=[{...r.suspensions[0],model:n.vehicle}],Ey(r.vehicles[0].params,n.components),yr(r,Ly),r}function Vc(e,t,r){let n=Iy[e],o=Ep.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:()=>MB(n)}}var SB=[{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:()=>es(wn("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:gB},{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:()=>ts(es(wn("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:dB},{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:fB},{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:hB},{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:bB},{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:yB},{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:gC},{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:yC},{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:xB},{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:RB},{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:vB},{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:kB},{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:()=>ts(es(wn("Suspension study","trackday")))},Vc("direct-coilover","The GT car\u2019s wishbones driving coilovers straight into the towers, at Laguna Seca.","On the GT car, at Laguna Seca."),Vc("pushrod","The FS car on pushrods: a rod from each lower wishbone works a rocker.","On the Formula Student car, at FSG."),Vc("pullrod","The FS car on pullrods: a rod from each upper wishbone pulls a low rocker.","On the Formula Student car, at FSG."),Vc("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."),Vc("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:()=>ts(es(wn("Tyre study","fs-ev")))}],xC=SB.map(e=>({...e,load:()=>Qg(e.load())}));var RC={width:320,height:200},fxe=[.6*RC.width-9,.6*RC.height-9];var vC=new WeakMap,kC=new WeakMap,Ny=e=>JSON.stringify(e,(t,r)=>r===1/0?"Infinity":r);function MC(e,t){if(!t){let a=vC.get(e);return a||(a=Ct(e),vC.set(e,a)),a}let r=kC.get(e);r||(r=new Map,kC.set(e,r));let n=Ny(t),o=r.get(n);return o||(r.size>=4&&r.clear(),o=Ct(e,t),r.set(n,o)),o}var wB=Math.PI/180,CB=e=>e>1?e/100:e;function Bc(e){let t=null;return()=>(t??={v:e()}).v}function SC(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 AC=new WeakMap,Oy={heave:0,pitch:0,roll:0,steer:0},FC=[0,1,2,3,4],wC=[-20,-10,0,10,20];function TC(e,t){let r=Br(e,Oy),n=["front","rear"],o=c=>{let l=Ri(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 FC){let l=c===0?null:Br(e,{...Oy,roll:c*wB});n.forEach((u,m)=>{let f=l?Ri(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 wC){let l=c===0?null:Br(e,{...Oy,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:FC,rcFront:s[0].rc,rcRear:s[1].rc,rcSplitFront:s[0].split,rcSplitRear:s[1].split},heave:{drop:wC,rcFront:i[0],rcRear:i[1]}}}var CC=new WeakMap;function TB(e,t,r,n){let o=CC.get(e);o||(o=new Map,CC.set(e,o));let a=`${Ny(r)}|${n[0]}|${n[1]}`,s=o.get(a);if(!s){o.size>=4&&o.clear();try{s=TC(MC(e,r),n)}catch{s=t.rigidMigration(n)}o.set(a,s)}return s}function PB(e){let t=AC.get(e);if(t)return t;let r=Ct(e),n=Br(r,{heave:0,pitch:0,roll:0,steer:0}),o=SC(e.front),a=SC(e.rear),s={wheelbase:e.config.wheelbase,trackFront:bt(e.front),trackRear:bt(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:Ra(n.front),rcGainRear:Ra(n.rear),rigidMigration:i=>TC(r,i),kinFront:Bc(()=>oa(e.front)),kinRear:Bc(()=>oa(e.rear))};return AC.set(e,s),s}function PC(e,t,r,n){let o=PB(e),a=Zn(e,t),s=va(e,t),i=Lk(e,t),c=Pu(e,t),l=Dk(e,t),u=Ek(t),m=Lu(e,t),f=Qn(e.front),p=Qn(e.rear),d=qn(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=CB(t.front_mass_diss.value),y=Ma(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),C=(r?R.verticalStiffness():0)||Q(t,"tire_vertical_rate"),T=(v?k.verticalStiffness():0)||Q(t,"tire_vertical_rate"),S=ar(r)??0,A=ar(v)??0,P=Nu({freeRadius:S,staticLoad:x,tyreRate:C,surveyed:e.front.config.loadedRadius},{freeRadius:A,staticLoad:M,tyreRate:T,surveyed:e.rear.config.loadedRadius},g),L=Gt(S,x,C,e.front.config.loadedRadius),D=Gt(A,M,T,e.rear.config.loadedRadius),E=[$r(o.rcHeightFront,o.rcGainFront,e.front.config.loadedRadius,L),$r(o.rcHeightRear,o.rcGainRear,e.rear.config.loadedRadius,D)],V=Bc(()=>Ai(o.kinFront(),Q(t,"camber_front_deg"))),N=Bc(()=>Ai(o.kinRear(),Q(t,"camber_rear_deg"))),z=Bc(()=>TB(e,o,Ya(B),E)),I=ei({...t,wheelbase:{...t.wheelbase,value:o.wheelbase}}),_=Si(t),B={massTotal:t.m.value,frontMassFrac:g,steeringSystem:t.steeringSystem,tv:gu(t),cgHeight:ka(Q(t,"cg_height"),t.cgReference?.standingRadius,P),cgStandingRadius:P,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: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:I.balanceFront,brakes:I,..._?{driveline:_}:{},heaveSpringFront:s.front??Q(t,"heave_spring_front"),heaveSpringRear:s.rear??Q(t,"heave_spring_rear"),unsprungPerCorner:Q(t,"unsprung_mass"),unsprungCgHeight:Gt(S,x,C,o.unsprungCgHeight),tyreFreeRadius:S,...A!==S?{tyreFreeRadiusRear:A}:{},rcHeightFront:E[0],rcHeightRear:E[1],corneringStiffnessFront:F,corneringStiffnessRear:w,get kinFront(){return V()},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 Du(e.front,L)},ackermannPct:Q(t,"ackermann_pct"),toeFrontDeg:Q(t,"toe_front_deg"),toeRearDeg:Q(t,"toe_rear_deg")};return B}var DC=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}),By={ggvMode:"twoTrack"},LC=new WeakMap;function $y(e,t=By){let r=LC.get(e.vehicle);r||LC.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={...DC(e.params),suspensionOf:()=>e.vehicle};n.set(o,a=Fo(e.params,s,t))}return a}var EC=(e=By)=>t=>$y(t,e),IC=(e=By)=>t=>PC(t.vehicle,My(t.params,DC(t.params),e),t.params.tireModel,t.params.tireModelRear);function LB(e,t){return $y(e,t.switches)}var Gy=e=>Ur(e?.rulesets);function _C(e,t,r,n,o={},a=()=>r.standingStart){let s=$y(n,r.switches),i=(l,u)=>{let m=Sm(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 NC=e=>[...new Set(e.lap.courses.flatMap(t=>t.course.kind==="track"?[t.course.trackId]:[]))],OC=e=>{let t=e?.session;return t?{sessionParams:r=>LB(r,t),session:()=>t}:{}},Gp=e=>({metrics:Gy(e),assemble:IC(e?.switches),simParams:EC(e?.switches),projectTrack:()=>e?.course??null,libraryTrack:t=>e?.tracks?.[t]??null,numerics:e?.numerics,...OC(e)}),DB=(e,t)=>({density:e.density,envelope:e.envelope,states:e.states,operating:e.operating,lap:e.lap,assemble:IC(t?.switches),simParams:EC(t?.switches),projectTrack:()=>t?.course??null,libraryTrack:r=>t?.tracks?.[r]??null,numerics:t?.numerics,...OC(t)}),VC="nelder-mead",BC=600,$c=[0,.15,.15];function $C(e,t,r,n=$c.length){let o=zy(t);return $c.slice(0,Math.max(1,n)).map((a,s)=>({...e,seed:s+1,startJitter:a,car:o,...r?{lap:r}:{}}))}function GC(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 KC(e,t,r,n,o=.01){let a=Gy(n).byId;return EB(e,t,r,n).filter(s=>s.excess>-o*(a[s.metricId]?.scale??1))}function EB(e,t,r,n){let o;try{o=Sn(Sp(e,t,r),DB(t,n))}catch{return[]}return IB(o,t,Gy(n))}function IB(e,t,r){let n=[];for(let o of t.constraints){let a=r.byId[o.metricId];if(!a)continue;let s=Lt(e,a,o.at);if(!Number.isFinite(s))continue;let i=`${et(a)}${Ec(o.at,a)}`;n.push({key:o.key,metricId:o.metricId,label:i,unit:a.unit==="-"?"":a.unit,value:s,excess:Dc(o,s)})}return n}var _B=.05;function NB(e,t){if(t.id.startsWith("hp.")||vp(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 ey(Fn(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 Q0(Xr(o.hardpoints,n[2]),n[3],1)}function HC(e,t,r){let n=r.filter(f=>f.score.feasible);if(n.length<2)return null;let o=t.map(f=>NB(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(_B,m),unit:a}}var OB={steeringSystem:!0,brakeSetup:!0,driveline:!0,heaveFrontDesign:!0,heaveRearDesign:!0,arbFrontDesign:!0,arbRearDesign:!0},zC=e=>Object.hasOwn(OB,e);function Vy(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 VB(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":zC(t)||Vy(e)?"block":null}function Ky(e,t){t=Dt(e,t);let r=Ht(e);return[...t.variables,...t.followers??[]].filter(n=>r[n.id]&&!r[n.id].supersededBy&&!VB(n.id)).map(n=>ct(r[n.id]))}function YC(e,t,r){t=Dt(e,t);let n=Ht(e),o=Sp(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[ko.fore,ko.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=Xt[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"&&gr(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:ct(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(zC(m)||Vy(c.id)){let h=Vy(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 Hy(e){let t=performance.now(),r=Gp(e.lap),n=e.follow?my(e.car,e.spec,r):e.spec,{dead:o,unprobed:a,...s}=hy(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 zy=e=>e.vehicle.chassis?{...e,vehicle:Ay(e.vehicle)}:e;function WC(e,t){try{let r=Yy(e.car,e.spec,e.lap),n=ia.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:wr(r.variables),score:Fr(r,wr(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&&oy(r.variables)?sy(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 Yy=(e,t,r)=>Ap(e,t,Gp(r));function jC(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 UC(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 XC=e=>({ggvMode:e.ggvMode,quasiTransient:e.quasiTransient===!0&&e.ggvMode!=="fast",motorThermal:e.motorThermal===!0,...Mw({brakeFade:e.brakeFade===!0,airTempC:e.airTempC,diffYaw:e.diffYaw===!0,...e.air?{air:e.air}:{}})});function BB(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 qC(e,t){let r=t.plannedPath!==void 0,n=BB(t);return{..._C(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 Wy(e,t){let r=e.vehicles.find(o=>o.id===t);if(!r)throw new Error(`this project holds no vehicle "${t}"`);let n=Ao(e);return UC(structuredClone(ky(e,r.params)),structuredClone(r.params),jC(r.params,n))}var $B="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 jy(e,t,r,n){if(e.settings.pathPlanId)throw new Error($B);let o=Za(e),a=e.tracks.length?(await Cp(e,t)).asset:null,s={};for(let i of n?NC(n):[]){let c=e.tracks.find(l=>l.id===i);c&&(s[i]=await _c(c,t))}return qC(r,{track:a,numerics:o.numerics,racingLine:o.racingLine,standingStart:o.standingStart,lapCounts:o.lapCounts??{},switches:XC(o),rulesets:e.rulesets??[],library:s,standingOf:i=>e.tracks.find(c=>c.id===i)?.standingStart===!0})}async function QC(e,t,r,n){let o=Wy(e,r),a=Dt(o,n),s=await jy(e,t,o,a);return Hy({id:0,car:o,spec:a,lap:s})}async function ZC(e,t,r,n){let o=Wy(e,r),a=Dt(o,n),s=Ky(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 jy(e,t,o,a)}catch(l){return{problems:[l instanceof Error?l.message:String(l)]}}let c=fy(o,a,{...Gp(i),metrics:Ur(e.rulesets)});return c.length?{problems:c}:{problems:[],msPerEval:Hy({id:0,car:o,spec:a,lap:i}).msPerEval,carFingerprint:co(zy(o))}}async function GB(e,t,r,n,o,a=[]){let s=$C(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(WC(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 JC(e,t,r,n){let o=Wy(e,r.vehicleId),a=Dt(o,r.spec),s=Ky(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 jy(e,t,o,a),c=r.method??VC;if(!ia.some(b=>b.name===c))throw new Error(`unknown method "${c}" \u2014 it is one of ${ia.map(b=>b.name).join(", ")}`);let l=r.budget??BC,u=Math.max(1,Math.min(r.seeds??$c.length,$c.length)),m=await GB(o,{spec:a,method:c,budget:l},i,u,n),f=Yy(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:GC(f.variables,b.x),constraints:KC(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}}:{}})),d=m.runs.reduce((b,g)=>Hs(g.score,b.score)?g:b),h=d.snapped?.score.feasible?d.snapped:null;return{method:c,budget:l,seeds:p,spread:m.runs.length>1?HC(o,f.variables,m.runs.map(b=>({x:b.x,score:b.score}))):null,writes:YC(o,a,h?h.x:d.x),...d.snapped?{adopts:h?"on its steps":`as found: on its steps it breaks a hold (${d.snapped.score.reason??"not legal"})`}:{}}}function tT(){if(typeof process.threadCpuUsage!="function")return performance.now();let e=process.threadCpuUsage();return(e.user+e.system)/1e3}async function HB(e,t){let r=xw(e.root);switch(e.kind){case"sweep":return Dw(e.doc,r,e.req,t);case"convergence":return Pw(e.doc,r,{vehicleId:e.vehicleId,...e.steps?{steps:e.steps}:{},...e.tolPct!==void 0?{tolPct:e.tolPct}:{},onStep:t});case"study":return JC(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 Tp(e.doc,r,{...e.vehicleIds?{vehicleIds:e.vehicleIds}:{},...e.settings?{settings:e.settings}:{},...e.overrides?{overrides:e.overrides}:{}});case"probe":return QC(e.doc,r,e.vehicleId,e.spec);case"quote":return ZC(e.doc,r,e.vehicleId,e.spec)}}if(eT){let e=eT,t=r=>e.postMessage(r);(async()=>{try{let r=await HB(KB,(n,o)=>t({type:"progress",done:n,total:o}));t({type:"done",result:r,cpuMs:tT()})}catch(r){t({type:"failed",message:r instanceof Error?r.message:String(r),cpuMs:tT()})}})()}export{HB as runJob,tT as threadCpuMs};
|