@pacedyn/mcp 0.392.0 → 0.393.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +59 -59
- package/dist/worker.js +5 -5
- 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 tB}from"node:worker_threads";import{readFileSync as ty}from"node:fs";import{join as ry}from"node:path";var Dc=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 Ec(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 Ic(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],Ip={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 _p(e){return Be(_y,Ny,e)}var Oy=.5;function Np(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=Ip[t]??Ip.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 Op(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=Ec(e);if(r)throw new Error(r);let{cell:n,pack:o}=e,a=n.curve.kind==="table"?n.curve:Np(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?Ic(a.soc,l,u,F,w):Be(a.soc,a.r0,F)*_p(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*Op(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 Vp(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 Bp(){return{name:"Formula Student accumulator",cell:Vp(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 $p(){return{name:"LFP pack",cell:Vp($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 Gp(){return{name:"Road car pack",cell:Vp(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 Kp(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 _c(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)=>Ic(e.effRpm,e.effTorque,e.effGrid,n,o);return{model:e,maxTorque:t,efficiency:r}}function Hp(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 zp(e,t){let r=e.tyreFreeRadiusRear;return(t==="rear"&&r!==void 0?r:e.tyreFreeRadius)??0}var Nc=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 Oc(e,t,r){if(!(r>0))return 1;let n=e*Nc*t*(Math.PI/180)/r;return 1/(1-Math.min(Hy,n))}function Yp(e,t,r){return r>0?e*Nc*t/(r*r):0}function zy(e,t,r,n,o){if(!(n>0)||!(o>0))return 1;let a=Yp(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*Nc*v,M=Oc(r,v,y),F=y>0?x/y*M:0,w=e.massTotal*Nc*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 Yr=["clFront","clRear","cd"],Po=e=>e.frame?.kind==="pitch";function Vc(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 Bc=45,Qe=e=>typeof e=="number"&&Number.isFinite(e);function $c(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 Yr){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=$c("front ride-height",e.axes?.hFront);if(i)return i;let c=$c("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=$c("ride-height",e.axes?.h);if(i)return i;let c=$c("pitch",e.axes?.pitch,"\xB0","pitch");if(c)return c;let l=e.axes.pitch.find(u=>Math.abs(u)>=Bc);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 Yr){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 Yr){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])>=Bc||Math.abs(i[1])>=Bc))return`A pitch range reaching ${Math.abs(i[0])>=Bc?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 Gc(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 GB=180/Math.PI,PC=["hFront","hRear"],LC=["h","pitch"],Up=e=>e?.kind==="pitch"?LC:PC,Mt=(e,t)=>e[t],Kc=(e,t)=>e[t],Wp=(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 Xp(e){let t=Up(e.frame),r=e.balanceFront,n=e.cl*r,o=e.cl*(1-r),a=Wp(t,c=>Mt(e.dCl,c)*r+e.cl*Mt(e.dBalance,c)),s=Wp(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:Wp(t,c=>Mt(e.dCd,c))},range:{[t[0]]:[...Kc(e.range,t[0])],[t[1]]:[...Kc(e.range,t[1])]},provenance:{...e.provenance},...i?{attitude:i}:{}}}function Hc(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 jp(e,t,r=11){let n=Array.from({length:r},(a,s)=>t.maxDeg*s/(r-1)),o=n.map(a=>Hc(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:jp(e.at,e.attitude.yaw)}:{},...e.attitude.roll?{roll:jp(e.at,e.attitude.roll)}:{}}}function qy(e,t,r,n=0,o=0){let[a,s]=Up(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?Hc(e.at,e.attitude.yaw,n):{clFront:1,clRear:1,cd:1},m=e.attitude?.roll?Hc(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]=Up(e.frame),n=[...Kc(e.range,t)],o=[...Kc(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 Qp=180/Math.PI,Qy=new WeakMap,Zy=new WeakMap,Zp=new WeakMap;function Wr(e,t){let r=Zy.get(e);if(r)return r;let n=t?.wheelbase,o=n!==void 0?Zp.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=Zp.get(e);return c||(c=new Map,Zp.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}=Vc(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 Yr){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 Yr)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)*Qp,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)*Qp,m,f,p),b=Qp/(n*(1+d*d)),g={};for(let y of Yr)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=Gc(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 Jp(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 Xp({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 ed=()=>br(Jy),td=()=>br(ex),rd=()=>br(tx),nd=()=>br(rx),od=()=>br(nx),ad=()=>br(ox),sd=()=>br(ax),id=()=>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 zc(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 Yc(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 cd(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(Yp(t.sprungMass,r,e.wheelbase),.5*n*o/(n+o))}function Wc(e,t,r,n,o){let a=e.cgHeight,s=cd(e,r);if(n===0&&o===0&&s===0)return{height:a,forward:0,noseLoad:0,dropFront:0,dropRear:0};let i=zc(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=Yc(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 ld={yawDeg:0,rollDeg:0},ix=1e-4,NC=40,cx=50;function Io(e,t,r=0){let n=e.aero?.model;if(!(!n||!Wr(n,e).hasAttitude))return{yawDeg:r,rollDeg:Te(e).rollGradient*t}}function ud(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}=Vc(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 jr(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&&Wr(o.model,e).hasAttitude?n:ld,i=s===ld?`${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=Wr(t.model,e),s=Te(e),i=2*s.rideRateFront,c=2*s.rideRateRear,l=ud(t,e.wheelbase),u=.5*t.rho*r*r,m=a.area,f=e.wheelbase>0?t.copHeight/e.wheelbase:0,p=zc(e,s),d=cd(e,n),h=(C,T)=>Yc(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=jr(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 jc(e,t=0,r=0,n,o){if(e.aero&&t>0){if(e.aero.model){let i=jr(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 Wc(e,o??Te(e),r,a.downFront-s,a.downRear+s)}return r===0?{height:e.cgHeight,forward:0,noseLoad:0}:Wc(e,o??Te(e),r,0,0)}var ux=[0,1,0],md=[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],pd=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),Ur=e=>Math.sqrt(X(e,e)),es=(e,t)=>BC(H(e,t)),ve=(e,t)=>Ur(H(e,t)),q=e=>{let t=Ur(e);return t<1e-12?[0,0,0]:[e[0]/t,e[1]/t,e[2]/t]};var Xr=(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,Xr(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 dd(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 fd(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 hd(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 bd(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 gd(e,t,r,n){let o=_t(e,t,e.lbj0),a=bd(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]),Uc=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))),yd=e=>Uc(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?Uc(a):yd(r),i=ae(r,s),c=H(e.ubj0,e.lbj0),l=X(c,c);if(!(l>1e-18))return"free";let u=H(n,t),m=X(u,u),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=Uc(c),d=(h,b)=>{let g=ee(n,ee(U(s,o*h),U(i,o*b))),y=Uc(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):yd(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=yd(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:dd(fd(R,y,ae(R,y)),gx(fd(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:dd(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=bd(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)),xd=(e,t)=>ee(e.pivotA,It(e.rdmRel0,e.axis,t));function ns(e,t){return{pushrod:qC(e,t),damper:xd(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(xd(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(xd(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 Xc=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))*Xc,o=Math.atan2(t[0],t[1])*Xc,a=Math.atan2(-r[0],r[2])*Xc,s=Math.atan2(-r[1],r[2])*Xc,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:hd(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=>gd(e,o,t,r),n,{scales:ZC,tol:1e-10,maxIter:40})}var eT=.01,qc=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,Rd(s),o).travel-s.travel)/.02;(!Number.isFinite(c)||Math.abs(c)<1e-6)&&(c=1);let l=f=>Math.max(-qc,Math.min(qc,f)),u=l((t-s.travel)/c),m=Ie(e,u,r,Rd(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,Rd(s),o)}return Lx(m,t,Math.abs(u)===qc)}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 Rd(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 Qr(e,t){return[e[0],t.sideSign*e[1],e[2]]}function Vo(e){return e.frontAxleX-e.wheelbase/2}function vd(e,t,r){return t[2]+e.heave+(t[0]-r)*Math.sin(e.pitch)-t[1]*Math.sin(e.roll)}function Zr(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 kd(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=kd(n,r,s),c=kd(o,r,s),l=-kd(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 Qc=e=>e!==void 0&&Number.isFinite(e)&&e>0;function iT(e){return e&&Qc(e.helperRate)&&Qc(e.helperTravel)?{rate:e.helperRate,travel:e.helperTravel}:null}function Md(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=-Md(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=Qc(t?.extended)&&t.extended>e?t.extended:null,n=r!==null&&Qc(t?.stroke)?r-t.stroke:null;return{droop:r!==null?e-r:null,bump:n!==null&&n<e?e-n:null}}function Sd(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=Md(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=Md(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 Ad(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 Fd(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 Zc={min:-60,max:60,steps:61},wd=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=Zc,n=e.corner.config.coilover){let o=e.corner.config;if(o.actuation==="decoupled")return wd(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 wd(r);let c=fT(i,0);if(!(Math.abs(c.mr)>1e-6))return wd(r);let l=t/c.mr,u=ss(s,l,c.L,n),m=u?mT(i,Fd(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?Fd(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 Cd(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=Cd(e,0),c=a-r;return(s?Go(s,c):o+n*c)*Cd(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 Jr(e,t,r){return e.config.actuation==="decoupled"&&t.attach==="rocker"&&r==="coil"}function Td(e,t,r){return Jr(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 Pd(e,t,r.kind,Ge(e,{travelMin:n,travelMax:o,steps:a}).samples)}function Pd(e,t,r,n){let o=q(H(t.outer,Td(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 Ld(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 Dd(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 el(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 Ed(e,t,Ge(e,{travelMin:n,travelMax:o,steps:a}).samples)}function Ed(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(el(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 Id(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 _d(e,t){let r=e.hardpoints,n=r.rockerPivotA,o=Bx(Jc(r.rockerPivotB,r.rockerPivotA)),a=Math.max(30,.6*Gx(Jc(r.rockerToDamper,n))),s=Jc(r.rockerToDamper,n),i=Bx(Jc(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:Id(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 Jc=(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 Nd=.001,RT=e=>({outer:e.outer,inner:e.outer,attach:e.attach}),Xx=(e,t,r)=>(el(e.at0,t)-el(r,t))/2,vT=(e,t)=>X(H(t,e.pickup.at0),e.axis);function Od(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=>Od(e,t.map(o=>o[n])));return t.map((n,o)=>[r[0][o],r[1][o],r[2][o]])}function Vd(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:Vd([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,Td(o,h,t.rollKind??"coil")))}}let i=t.roll&&Jr(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:Vd([n.min,n.max]),pickups:{}};let d={travel:l,heave:u,heaveRatio:Od(l,u),roll:m,rollRatio:Od(l,m)};return i&&(d.eyes={near:f,nearRatio:Kx(l,f),far:p,farRatio:Kx(l,p)}),{side:d,pickups:s}}function tl(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 ze(e,t){return{h:tl(e.travel,e.heave,t),dh:tl(e.travel,e.heaveRatio,t),ddh:zx(e.travel,e.heaveRatio,t),r:tl(e.travel,e.roll,t),dr:tl(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 Bd=(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 rl(e,t){let r=Vd(e.travel);return t==="heave"?{...e,heave:r.heave,heaveRatio:r.heaveRatio}:{...e,roll:r.roll,rollRatio:r.rollRatio}}var nl=(e,t)=>e?e.law?Go(e.law,t):e.preload+e.rate*t:0,Wx=(e,t)=>e?e.law?Ad(e.law,t):e.rate:0;function ps(e,t,r,n,o){let a=nl(e.heave,n),s=nl(e.roll,o);return[a*t.dh+s*t.dr,a*r.dh-s*r.dr]}var jx=(e,t)=>ze(e[0],t).h+ze(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=ze(r[0],a).r-ze(r[1],-a).r-(ze(r[0],-a).r-ze(r[1],a).r),l=i/c;return Number.isFinite(s)&&s>0&&Number.isFinite(l)&&Math.abs(l)>Nd?{length0:s,scale:l}:null}function Zx(e,t,r,n=Zc){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=>ze(A,0));c&&!(Math.abs(p[0].dh+p[1].dh)>Nd)&&(i=[rl(i[0],"heave"),rl(i[1],"heave")],c=!1),l&&!(Math.abs(p[0].dr+p[1].dr)>Nd)&&(i=[rl(i[0],"roll"),rl(i[1],"roll")],l=!1),p=i.map(A=>ze(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?Sd(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&&Jr(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=ze(e.side[0],t[0]),o=ze(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 $d(e,t,r){let n=ze(e.side[0],t[0]),o=ze(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=nl(e.heave,a),u=nl(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 Gd(e,t,r){let n=$d(e,t);return n[r][0]+n[r][1]}function AT(e,t,r){let n=e.read.heave;if(!n)return ze(e.side[0],t[0]).h+ze(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 ze(e.side[0],t[0]).r-ze(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 Bd(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=ze(e.side[0],t[0]),o=ze(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 Kd(e,t,r,n){let o=ze(e.side[0],r),a=ze(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?Bd(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 Hd(e,t,r,n){let o=Ko(e,r[n]);return t?.carriesLoad?o+Gd(t,r,n):o}var zd=e=>e==="FR"||e==="RR"?1:0,ol=(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=$d(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 Yd=["FL","FR","RL","RR"],oR={front:["FL","FR"],rear:["RL","RR"]},LT=512,DT=5e-4,ET=8;function al(e,t){let r={},n={},o=new Map;for(let s of Yd){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=`${Yd.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 Wd(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=>Zr(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:[Wd(e,o[0],s[0]),Wd(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:Hd(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 Yd)r[n]=Wd(e,n,Zr(n,e.vehicle.config,t,e.vehicle));return r}return sR(e,t).corners}function sl(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=Zr(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=ol(o,t),p=gr(o.curve[t],r,m.points.damperLength)+(f?Kd(f,zd(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=Qr(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 jd(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,Ud=e=>e.rackRatio&&e.rackRatio>0?e.rackRatio:pR;var Xd=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=Xd(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,Xd(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=Xd(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:Ud(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 il(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=il(e.rackMm,e.rows[r.lo][t].jacobian,n);if(r.lo===r.hi)return o;let a=il(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:il(e.meanDeg,e.innerJacobian,t),outerJacobian:il(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 Qd(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?jr(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 Zd(e,t,r=0,n=0,o=0){if(!e.aero?.model||t<=0)return!1;let a=jr(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*Oc(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 Jd(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 cl(e,t,r,n,o,a,s,i).loads}function cl(e,t,r,n=0,o=0,a=0,s,i){let c=Pn(e),l=Te(e),u=jc(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 ef=Math.PI/180;function ul(e,t){let r=8*ef,n=0,o=0;for(let a=1;a<=90;a++){let s=a*.5,i=Math.abs(e.Fy(s*ef,t,0));if(i>n&&(n=i,r=s*ef,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??ul(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 nf(e,t){return e.model?.kind==="simple"?null:MR(e,t)}var vR=new WeakMap,tf=100,kR=1.35,rf=18,er=41,ll=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<ll;C++){let T=Math.sin(.5*Math.PI*C/(ll-1));M.push(T),F.push(C===0?1:C===ll-1?0:Math.min(F[C-1],h(T*g)/b))}let w=ll-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:rf},(p,d)=>tf*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>tf?Math.log(p/tf)/n:0;if(d>=rf-1)return[rf-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 ml(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 pl(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 of=40;function dl(e){return{violation:Math.max(0,e.lock-e.reached),reason:`the steering reaches only ${e.reached.toFixed(0)} mm of the ${e.lock.toFixed(0)} mm rack travel${e.side<0?" (other side)":""}`}}var 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 fl(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 af(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{...fl(e,r,n),armResidual:0};if(t==="upright")return{...fl(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 fK=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"],hl=["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=hl.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 bl(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(hl),e.axisSystem&&e.side==="left"&&r(nP(e.version)),t.size?oP(e.coeffs,t):e.coeffs}var bK=Math.PI/180;var $=(e,t)=>Number.isFinite(e)?e:t;function DR(e){let t=bl(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 gl(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 yl(e,t,r=0,n){let o=gl(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 xl(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*xl(e,t)}function sf(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 Rl(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 cf(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 en(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=yl(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=gl(r,v,x,M),u=v,m=x,f=M),l),d=v=>e.kind==="magic"?Rl(c(v.Fz,v.gamma??0,v.p),v.kappa,v.alpha):cf(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"?xl(c(x,M,F),v):VR(n,x,v),g=(v,x,M=0,F)=>e.kind==="magic"?sf(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 kl(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:kl(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 Ml=25*(Math.PI/180);function cP(e){let t=.6180339887,r=0,n=Ml,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=Ml;if(s(Ml)<=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(Ml,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 lf={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 uf(e,t,r){let n=r.shaft?af(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},Sl={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 mf(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 pf(e,t,r){let n=uf(e,r.force,r.extras??lf),o=r.alignMoment?ee(n.moment,[0,0,r.alignMoment]):n.moment;return xs(e,t,n.force,o)}function Fl(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:pf(Cs(e,i),e.corner.config.pushrodAttach,n),deflection:Sl,rigid:i,iterations:0,converged:!0,bypassed:!0};let u=i,m=e,f=e.corner.config.pushrodAttach,p=pf(Cs(e,i),f,n),d=Sl,h=!1,b=0;for(;b<uP;b++){let g=Cs(m,u);if(p=pf(g,f,n),p.singular)break;d=mf(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 Al=1e3,YR=1e5;function WR(e,t,r,n,o){let a=Fl(e,t,r,n,void 0,o);return{toe:a.state.metrics.toe,camber:a.state.metrics.camber,patch:a.state.points.contactPatch,converged:a.converged,bypassed:a.bypassed}}function wl(e,t,r,n,o){let a={force:[0,0,n]},s=(b,g=0)=>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,Al,n]),l=s([0,-Al,n]),u=s([Al,0,n]),m=s([-Al,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 df(e,t=dP){if(!Dn(e.compliance)||!Ln(e))return;let r=tt(e),n=Ie(r,0,0),o=wl(r,n.beta,0,t);if(!o.bypassed)return{toePerFy:o.toePerLateral/1e3,camberPerFy:o.camberPerLateral/1e3,toePerFx:o.toePerLongitudinal/1e3,camberPerFx:o.camberPerLongitudinal/1e3,toePerMz:o.toePerAligning/1e5}}function ea(e,t=-of,r=of,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=df(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 Cl(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 tn(e,t){return{motionRatio:Cl(e.travel,e.motionRatio,t),camber:Cl(e.travel,e.camber,t),toe:Cl(e.travel,e.toe,t),damperLen:Cl(e.travel,e.damperLen,t)}}var jR=Math.PI/180,fP=9.81;function rn(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=tn(t,0),u=tn(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=tn(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 ff=(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,ff(e?.roadFeedbackGain,1))),turnInFrictionNm:Math.max(0,ff(e?.turnInFrictionNm,0)),columnStiffnessNmPerRad:Math.max(0,ff(e?.columnStiffnessNmPerRad,0))}}function hf(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=hf(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 gf(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 bf(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=bf(e,t),o=bf(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 Tl(e){if(e.kind==="magic")return e.range??yP(e.coeffs)}function yf(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*yf(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=yf(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 Pl(e,t=yf(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 Ll(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}))),x4=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 w4=Math.PI/180;var D4=Math.PI/180,E4=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 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)
|
|
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 Rf(){return Ds(sv,"Example MF6.2")}var BP=Math.PI/180,iv=2,cv=2;function lv(e){let t=Math.sin(cv*Math.atan(1/iv)),r=-e.corneringStiffness/(e.Fz0*t),n=e.camberStiffness/BP/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]
|
|
@@ -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},Rf=()=>vr(uv),vf=()=>vr(mv),kf=()=>vr(pv),Mf=()=>vr(dv),Sf=()=>vr(fv),Af=()=>vr(hv),Ff=()=>vr(bv),wf=()=>vr(gv);var yv=e=>Number.isFinite(e)&&e>0;function Dl(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 Cf(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 El(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 Tf(e,t){let{budget:r}=t,n=Math.max(1,Math.floor(t.progressEvery??1)),o=e.variables,a=p=>Cf(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 Pf=(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=Tf(e,t),n=El(t.seed??1),o=e.variables.length;for(r.evaluate(Pf(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=Tf(e,t),n=e.variables.length,o=El(t.seed??1),a=1,s=2,i=.5,c=.5,l=Pf(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=Tf(e,t),n=e.variables.length,o=El(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=Pf(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 q4=Math.PI/180;var Il=Math.PI/180;var eH={Fz:100,alpha:.25*Il,kappa:.005,gamma:.5*Il,p:6900},vv={Fz:100,alpha:1*Il,kappa:.02,gamma:.5*Il,p:6900};var kv=Math.PI/180,sH={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 mH=Math.PI/180;var ZP=Math.PI/180;var yH=3*ZP;var MH=Math.PI/180;var _H=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 WH=Math.PI/180;var pL=Math.PI/180,_l=[{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"}],i6=new Map(_l.map(e=>[e.id,e]));var c6=.01*pL;var Ye=Math.PI/180;var Cv=new Set(_l.filter(e=>e.group!=="inputs"&&(e.unit==="N"||e.unit==="N\xB7m"||e.unit==="N/rad")).map(e=>e.id)),Tv={alpha:{from:-15*Ye,to:15*Ye,n:61},kappa:{from:-.25,to:.25,n:61},gamma:{from:-6*Ye,to:6*Ye,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}},_f={alpha:{from:0,to:12*Ye,n:7},kappa:{from:-.2,to:.2,n:9},gamma:{from:-4*Ye,to:4*Ye,n:5},Fz:{from:400,to:1600,n:5},p:{from:6e4,to:12e4,n:4},V:{from:5,to:35,n:4}};var Nf={alpha:{from:0,to:12*Ye,n:25},kappa:{from:-.2,to:.2,n:25},gamma:{from:-4*Ye,to:4*Ye,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}),Nl=(e,[t,r],n,o,a={})=>({id:e,form:"carpet",sweep:[{input:t,..._f[t]},{input:r,..._f[r]}],x:n,y:[o],...a}),Sr=(e,t)=>({id:e,fixed:t}),Vt={input:"Fz",values:"car"},If={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}),Nl("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*Ye,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*Ye,n:49}),ke("mzr","alpha",["Mzr"],{title:"Residual aligning moment",series:Vt,hold:yt},{from:0,to:12*Ye,n:49}),Nl("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*Ye,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:If}),ke("kappa-peak","Fz",["kappaPeak"],{title:"Slip ratio at the peak over load"})]},{id:"combined",name:"Combined",cards:[Nl("carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Nl("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*Ye,4*Ye,8*Ye]}}),ke("fx-kappa","kappa",["Fx"],{title:"Driving force while cornering",series:{input:"alpha",values:[0,4*Ye,8*Ye]}}),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*Ye)},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",...Nf.gamma},{input:"Fz",...Nf.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:If}),ke("radius","Fz",["R0","Rl","Re"],{title:"Radius over load"},{from:0}),ke("p-roll","V",["Proll"],{title:"Rolling power",series:Vt,hold:If})]},{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,Of=273.15,Dv=.95,Ev=60,Ol=10,ML=.55,At=25,Vf=-20,Bf=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]}},Vl={...Vs,discMassKg:.4,discOuterMm:200,padCurve:{tempC:[...Os.tempC],factor:[...Os.factor]}};function $f(e,t){let r=t==="front"?Vs:Vl,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 Gf(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,Ol,5e3,t.coolingWPerM2K),padCurve:AL(e?.padCurve,t.padCurve)}}function Bl(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 Kf(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=>Ol+(e.coolingWPerM2K-Ol)*Math.pow(Math.max(0,m)*t/a,ML),c=(m,f,p)=>{let d=m+Of,h=p+Of;return i(f)*o*(m-p)+s*(d**4-h**4)},l=(m,f)=>i(f)*o+4*s*Math.max(0,m+Of)**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=>Bl(e.padCurve,m),window:Iv(e.padCurve)}}function $l(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])&&Bl(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 Hf=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},Yf={fullAtBar:10,maxPowerKw:0,fadeBelowKmh:0,distribution:"equal"};var Wf=$v(Kl(Nn,"Formula Student brakes")),jf=40,Bv={ideal:!1,barFront:Nn.barFront,pedalForceMaxN:0,testSpeedKmh:jf,regen:Yf};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:$f(r,n)};return{...e,front:t(e.front,"front"),rear:t(e.rear,"rear")}}function Kl(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 Uf(e,t){return Gv({...e,barFront:t.barFront,pedalForceMaxN:t.pedalForceMaxN})}function Xf(e,t){let r=Fr(t),n=e?rr(e):void 0;return{mode:r.ideal?"tyre":n?"hydraulic":"balance",hydraulic:n?Uf(n,r):Nn,regen:r.regen}}var FL=["none","proportioning","limiter"],Gl=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},Je=(e,t,r,n)=>Math.min(r,Math.max(t,Gl(e,n))),wL=(e,t)=>{let r=Gl(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(Gl(e?.discs,n==="inboard"?1:t.discs)))),pistonsPerSide:Math.max(1,Math.min(6,Math.round(Gl(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:Gf(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,Vl),adjusterPitchMm:wL(e?.adjusterPitchMm,t.adjusterPitchMm),barLengthMm:Je(e?.barLengthMm,0,500,t.barLengthMm)}}function CL(e){let t=Yf;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 Kl(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,jf),regen:CL(e?.regen)}}var TL="Formula Student brakes";var zf=e=>Math.PI/4*(e*Vv)**2;function nn(e,t){let r=e.pistonsPerSide*zf(e.pistonDiaMm)*Hf;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/zf(e.masterFrontMm)/Hf,o=(1-e.barFront)*r/zf(e.masterRearMm)/Hf;return{front:n,rearIn:o,rear:Kv(e,o)}}function PL(e,t){let r=Bs(e,1);return{front:nn(e.front,t)*r.front,rear:nn(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=nn(t.front,e.tyreRadiusM),n=nn(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 Hl=ys,EL=.1,Vn=(e,t)=>e.a*Math.sqrt(Math.max(0,1-(t/Math.max(1e-9,e.b))**2));function zl(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 Jf(e,t,r){let n=Math.max(0,r-Hl*t.b),o=Math.min(r,Hl*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 eh(e,t,r,n,o=0){let a=Math.max(0,r),s=Jf(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<Hl*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=zl(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=>Hl*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=zl(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 Qf=e=>Math.max(e.xNoLock,e.xLock),Zf=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=Zf(r),s=Zf(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=Qf(t),a=Qf(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 Yl(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 th(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 rh(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 nh(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 oh(e){let t=e.driveKept;return t===void 0||!Number.isFinite(t)?Xv:Math.max(0,Math.min(1,t))}function ah(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 sh(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=ah(e.motorModel,l,u);let v=Tr(0,k.vMax,Math.max(2,Math.ceil(k.vMax/p)+1)),x=v.map(w=>sh(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=rh(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 on=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=on(e);return t.front>=2||t.rear>=2}function Jv(e){return Zv(e)?e.motorMount??"hub":"chassis"}function ih(e){if(!e.motorModel)return{front:!1,rear:!0};let t=on(e);return{front:t.front>0,rear:t.rear>0}}function ch(e){let t=on(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 Xf(e.brakeModel,e.brakeSetup)}function Wl(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(jl(Ft(e)),t??pt(e).regen)}function jl(e){return e.fAxle??{vVehicle:e.vVehicle,fFront:e.vVehicle.map(()=>0),fRear:e.fRad.map(t=>t*e.params.driven_wheels.value)}}function lh(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 uh(e,t=pt(e)){return{front:t.hydraulic.front.location==="inboard",rear:t.hydraulic.rear.location==="inboard"}}function mh(e){let t=pt(e);return{brakeBalanceFront:lh(e,t),brakeInboard:uh(e,t)}}function t1(e,t=pt(e)){if(t.mode==="tyre"||t.regen.distribution!=="wheel"||ft(e.motorModel))return;let r=on(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=uh(e,t),o=lh(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 ph(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 dh={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")},fh={ideal:{label:"Ideal brakes"},barFront:{label:"Balance bar"},pedalForceMaxN:{label:"Pedal force",unit:"N"},testSpeedKmh:{section:"Brake test",label:"Speed",unit:"km/h"},"regen.maxPowerKw":{section:"Regen",label:"Power ceiling",unit:"kW"},"regen.fadeBelowKmh":{section:"Regen",label:"Fades out below",unit:"km/h"},"regen.fullAtBar":{section:"Regen",label:"Full at",unit:"bar"},"regen.distribution":{section:"Regen",label:"Wheel by wheel"}};function hh(e){let t=dh[e];return`${t.label}, ${t.section}`.toLowerCase()}function bh(e){let t=fh[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}),Ul=Object.freeze({tbr:1/0,preloadN:0}),yh=e=>e.faces*e.muClutch*e.rFrictionMm/e.rRampMm;function xh(e,t){if(!(e>0)||Number.isNaN(t))return 0;let r=Math.tan(Math.min(90,t)*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 Xl(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)+Xl(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 Ul;case"independent":return t==="hubs"?ca:Ul;case"clutch":{let o=n(e.preloadNm);return t==="hubs"?{tbr:1,preloadN:o}:{tbr:a1(xh(yh(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 gh(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=Jf(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=zl(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=gh(f,ca),d=gh(f,Ul);if(!(d>p))return u;let h=(gh(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 Rh(e,o,Xs(t,r,n,o,a))}function Rh(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 vh(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 ql(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"],kh=e=>e==="FL"||e==="FR",Ql=e=>kh(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 an=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=ul(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(Ql(S),L);return St(ge(t,Ql(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(Ql(te),Math.max(0,A[te])).fyPeak,[N,z]=p1[S],I=E(N),_=E(z),B=V(N)+V(z),O=eh(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(Ql(G),K).fyPeak,Fx:-(kh(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 Rh(G.eq,G.law,Ll(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=ml(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,kh(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=vh(G,0,an),Y=ql(K,an),j=Y;if(B?.lockFront||B?.lockRear){let fe=vh(J=>G(J,!1),0,an);j=ql(fe,an);let W=i1(G,fe.x,K.x,an,XL);W||G(K.x),Y=ql(W??K,an)}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 Jl=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)*Jl;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 eu(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*Jl)/.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*Jl)},t.speeds.set(n,l));let{cap:u}=l,m=we(e,c,-r*.005+l.dragG,i),f=Math.abs(c)*e.massTotal*Jl,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 Zl(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 Zl(e,t,1,n);let o=c=>c.front+c.rear,a=e.controlFor(r,n),s=Zl(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=Zl(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=Zl(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},Mh={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 tu=e=>Math.max(2,.003*Math.abs(e)),eD=(e,t)=>Math.max(t.abs,t.rel*Math.abs(e)),Sh=.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(-Sh,Math.min(Sh,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)>Sh)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 Ah(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)-tu(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)>tu(u),h=Math.abs(m-p.forces.Fx)>tu(m),b=Math.max(0,n.preloadN),g=Xl(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)-tu(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 ru(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=Ah(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,cn=["FL","FR","RL","RR"],Yt=e=>e==="FL"||e==="FR",sn=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 gf(e,Math.min(t,zt(e)))}var ou=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 Dh(e,t,r,n){return Math.abs(Kn(e,t,r,n!==void 0?{steerMaxDeg:n}:{}).peak.steerDeg)}function Eh(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 Ih(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?ru(e,n,c,s):c}var ti=e=>ou(e)?-1:1,_h=(e,t,r,n,o)=>t*e.Fy(t*r,n,t*o);function Ph(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 Nh(e,t,r){if(r.Fz<=0)return 0;let n=ut(ge(e,sn(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:Nh(o,s,i)}}return Ps(e,r/se,a,en(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}=Ph(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?rn(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=rn(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=cl(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,Ke=be=>{let Fe=Math.max(0,Ae[be]),xe=ti(be),me=Yt(be)?k:v,Le=N(be),Se=0,He=0;if(Le){let An=z[be];Se=Le.toePerFy*An.fy+Le.toePerFx*An.fx+Le.toePerMz*An.mz,He=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]+He)*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=(ou(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?He=>Fe.t.forces({Fz:Fe.Fz,kappa:He,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 cn){let Le=Yt(me)?h:b;if(Le&&!xe[me]){let[wo,Et]=Yt(me)?["FL","FR"]:["RL","RR"],Lc=Ke(wo),Ty=Ke(Et),Py=sn(me),Ep=Ah(je(wo,Lc),je(Et,Ty),Le.F,Le.law,g[Py],Mh);g[Py]=Ep.spoolKappa,xe[wo]={w:Lc,share:Ep.left},xe[Et]={w:Ty,share:Ep.right}}let Se=xe[me]?.w??Ke(me),{Fz:He,mir:Ue,t:Kt,gains:Sn,complianceToe:An,steerK:Tp,slip:Pp,camberRad:Lp}=Se,qa=l?.[me]??0,So,Ao=0,Dp=0,Pc=0,Fo=xe[me]?.share;if(Fo)P[me]=Fo.kappa,Dp=Fo.kappa,Ao=Fo.forces.Fx,Pc=Fo.short,So=Ue*Fo.forces.Fy;else if(qa===0||He<=0)So=_h(Kt,Ue,Pp,He,Lp),Pc=He<=0?Math.abs(qa):0;else{let Et=Bn(Lc=>Kt.forces({Fz:He,kappa:Lc,alpha:Ue*Pp,gamma:Ue*Lp}),qa,P[me],Mh);P[me]=Et.kappa,Dp=Et.kappa,Ao=Et.forces.Fx,Pc=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:He,travelMm:oe?.[me].travel??0,steerRad:Tp,slipRad:Pp,camberRad:Lp,Fy:So,Fx:Ao,kappa:Dp,fxShort:Pc,lifted:Ve.lifted[me]},Sn){let wo=V&&Sn.toePerMz?Nh(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(Tp)+Ao*Math.sin(Tp)}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),Ke=Math.max(de,ie);Re>Ce&&Re<Ke||(Re=.5*(de+ie));let je=G(Re);if(Ve=Re,Math.abs(je)<1e-4||Ke-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=>(ou(J)?1:-1)*(Yt(J)?x:M);for(let J of cn){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+Fh,l),d=i(c,l+wh),h=(p.r-u.r)/Fh,b=(d.r-u.r)/wh,g=(p.c-u.c)/Fh,y=(d.c-u.c)/wh,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,Fh=1e-5,wh=.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 cn){let h=c.wheels[d],b=ge(t,sn(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:Nh(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,en(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=Ch.get(e)?.get(t)?.get(l);if(x)return x}let u=(x,M)=>M.trimmed&&Math.abs(M.beta-x.beta)<=au&&Math.abs(M.ay-x.ay)*Me<=su,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(Th,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*au&&Math.abs(C.ay-F.ay)*Me<.5*su&&(M=Math.min(Th,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(Th,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=Ch.get(e);x||(x=new WeakMap,Ch.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 Ch=new WeakMap,gD=90,au=1.5,su=2.5,Th=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>su?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)<=au;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)>au||Math.abs(v.ay-c.ay)*Me>su?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 Oh(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 Oh(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 ln(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=Oh(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 Vh(e,t,r,n,o){let a=ln(e,t,r,n,o);return a.steering?Math.abs(a.steering.totalNm):NaN}function Bh(e,t,r,n,o){if(!In(e))return NaN;let a=n<0?-1:1,s=Math.abs(n),i=ln(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 Lh(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 $h(e,t,r,n,o){let a=Math.max(8,r),s=ln(e,t,a,n,o),i=.5,c=Lh(e,t,a,s.beta+i,s.steerDeg,o).cn,l=Lh(e,t,a,s.beta-i,s.steerDeg,o).cn;return(c-l)/(2*i*se)*e.massTotal*Me*(e.wheelbase/1e3)}function Gh(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=Dh(e,t,r),a={op:s=>{let i=Eh(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 Kh(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}=Ph(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?en(ge(t,"front").model):void 0,k=(I,_,B,O)=>B===1?I:I+(_-I)*O/(B-1),v=e.tv?.enabled?Dh(e,t,a):0,x=I=>{let _=Eh(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}=Ph(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 cn)_+=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=cn.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=ml(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[sn(V)];if(N){if(ou(V)){let B=p(sn(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(sn(V),z),_=St(ge(t,sn(V)),z,C[V]*I.fyPeak,!1,I);D+=_,E&&(E.fx[V]=_)}if(E){let V={};for(let N of cn){let z=Math.max(0,v[N]);V[N]={Fz:z,Fy:C[N]*c(sn(N),z).fyPeak,Fx:E.fx[N]}}for(let N of E.axles)D+=Ll(N,V,h,b(g))-N.full}return D/s},S=c1(T,-k,an).fx,A=w.edge();return A!==void 0&&S>A&&(S=A,T(S)),{ax:S,loads:v}}}}var nu=.05,L1=.001,D1=16,iu=8;function Hh(e,t,r,n){let o=Math.max(iu,r),a=n.nSteer??7,s=e.tv?.enabled?Dh(e,t,o,n.steerMaxDeg):0,i=I=>{let _=Eh(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 cn)_[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=Oh(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>nu}},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+nu&&O.push({read:G=>({axA:A(G)}),past:G=>(G.axA??-1/0)>_.axA}),-B.axD>-_.axD+nu&&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)<=nu);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 cn){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 Aj=Math.PI/180,Fj={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 cu(e){let t=(r,n)=>e[r]?.value??n;return{enabled:t("tv_enabled",0)>=.5,kp:t("tv_kp",fa.kp),ffLow:t("tv_ff_low",fa.ffLow),ffHigh:t("tv_ff_high",fa.ffHigh),vLow:t("tv_v_low",fa.vLow),vHigh:t("tv_v_high",fa.vHigh)}}var z1=[10,25,50,100,200,300];function zh(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 lu={name:"Generic FS damper",curves:[zh("c1","Soft",1.6,1,.65),zh("c2","Medium",3,1.6,.65),zh("c3","Firm",8,2.4,.65)]};function uu(e){let t=e.curves.length;return t>0?e.curves[Math.floor((t-1)/2)].id:""}var un=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 Yh=(e,t)=>e.curves.find(r=>r.id===t);function ni(e,t){let r=Yh(e,uu(e)),n=(t&&Yh(e,t.bump))??r,o=(t&&Yh(e,t.rebound))??r;return{bump:{speedMmS:n?.speedMmS??[],forceN:n?.bumpN??[]},rebound:{speedMmS:o?.speedMmS??[],forceN:o?.reboundN??[]}}}var mu=5e3;function oi(e,t){let r=t>0?t:1,n=[],o=[],a=e.bump.speedMmS.map(c=>c/r).filter(c=>c<mu),s=e.rebound.speedMmS.map(c=>c/r).filter(c=>c<mu),i=c=>{n.push(c),o.push(W1(e,r,c))};i(-mu);for(let c=a.length-1;c>=0;c--)i(-a[c]);i(0);for(let c of s)i(c);return i(mu),{kind:"map",input:"velocity",x:n,y:o}}var Wh=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<Wh;s++){let i=Math.sin((s+.5)*Math.PI/Wh),c=n*o*i;a+=n*(ha(e.rebound,c)+ha(e.bump,c))*i}return a*(Math.PI/Wh)/(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,un)}},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 jh(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,un)/2,mr:n,ratio:n,share:.5}}function Uh(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,un)/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 pu(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?Ld(t,r):1,o=t?Dd(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=al(n,t)),n}var du=.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 fu(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+du,r.steer,void 0,a),l=ye(o,r.travel-du,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*du)):w,omega:u?U(H(M,F),1/(2*du)):w}}function Xh(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=fu(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 hu(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=Xh(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 bu(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:bu(e.travel,e.camber,t),toe:bu(e.travel,e.toe,t),motionRatio:bu(e.travel,e.motionRatio,t),damperLen:e.damperLen?bu(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 gu(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 Qh={kind:"coil",rate:120,motionRatio:.7,gap:5,bothWays:!1};var ak=new WeakMap;function xu(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 Zh(e,t){if(!t.linkage)return null;let r=Jr(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 pu(o.design,Zh(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?xu(o,n.linkage).atDesign:void 0;return gu(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?xu(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 Ru(e,t){let r=(o,a)=>o?di(o,Jh(o,a)):0,n=(o,a)=>o?mi(o,eb(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 Jh=(e,t)=>e.linkage?xu(t,e.linkage).atDesign:void 0,eb=(e,t)=>pu(e.design,Zh(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=Jh(f,p);if(di(f,h)>0)return jh(n,r?.[d],h??(f.design.kind==="coil"?f.design.motionRatio:1))},s=(f,p,d)=>{if(!f||!o?.curves.length)return;let h=eb(f,p);if(!(mi(f,h)>0))return;let b=Zh(p,f)!==null;return Uh(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,Jh(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,eb(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?xu(f,m.linkage).atDesign:void 0;o(p,gu(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:vu(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 ku(a,r,n).front??o}var lk=new WeakMap;function vu(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 yu=e=>e.measured?ok(e.measured):tE(e);function rE(e,t=e.front.config.loadedRadius){let r=()=>e.front.measured?void 0:vu(e.front,t);return{...nE(e),get steerFront(){return r()},get ackermannPct(){let n=r();return n?Qd(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:yu(e.front),mrRear:yu(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 Mu(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=on(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}]))},Su={...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 Au(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-tn(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=Dl(n,a);return{front:s,rear:o===n?s:Dl(o,a)}}function ir(e,t,r){let n=xa(e,t,r),o=Pe(n.front);return ut(n.rear===n.front?o:kl(o,Pe(n.rear)))}function tb(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?Au({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 ku(e,t,r){let n=tb(e,t,r);return{front:n.standingFront,rear:n.standingRear}}function kk(e,t,r){return tb(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}=tb(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:cu(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 Fu={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 ${un} mm/s`,damper_rear:`the damper part sets it (the rear's own, where the car names one): its rear curve at ${un} mm/s`};function wu(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 Cu(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,nX=(()=>{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 rb={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 Cu(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=Cu(e).filter(a=>!r.has(a.key));return o.length&&n.push({title:"Other",rows:o}),n}var nb={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"},ob={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,rb,bE(e)),Lk(e)&&Object.assign(r,nb),gE(e)&&Object.assign(r,Fu),Object.assign(r,wu(e)),e.readouts&&Object.assign(r,e.readouts),r}function Dk(e,t){let r=yE(e,t);return Lk(e)||Object.assign(r,ob),r}function ab(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 Tu(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 Pu(e,t,r=0,n,o){let a=()=>({cl:e.c_l.value,cw:e.c_w.value,frontShare:ab(e),A:e.A.value,platform:null});if(!e.aeroModel)return a();let s=jr(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:ab(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=Wr(t,{wheelbase:Q(e,"wheelbase")}).at(Q(e,"ride_height_front"),Q(e,"ride_height_rear")),{cl:n,balanceFront:o}=Jp(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,Lu=.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 Du(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=Du(e,o,t[o]??0);a<r&&(r=a),a>n&&(n=a)}return r>=1-Lu&&n<=1+Lu?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-Lu?1:1-1.25*(1-e.lo)-.05,r=e.hi<=1+Lu?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 sb(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):sb(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 Eu(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 ib=.001,cb=9.81,Ri=(e,t)=>lb(e?.gradient?.[t]??0);function lb(e){return e===0?0:-cb*Math.sin(e*Math.PI/180)}function pn(e,t){let r=new Array(t);for(let n=0;n<t;n++)r[n]=lb(e?.[n]??0);return r}var mn=(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,mn(o,a)),i=Xn(o,a);if(!i)return s;let c=i*Math.PI/180,l=n===0?0:-Math.sign(n)*cb*Math.sin(c);return Math.max(0,(s+l)/Math.cos(c))}function We(e,t){if(!t)return e;let r=t*Math.PI/180;return e*Math.cos(r)+cb*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),ib,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=We(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,ib,r.v,a.scanSteps,a.vTol),r.ay=r.v*r.v*n;let f=Math.abs(We(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(We(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,mn(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],mn(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)=>Du(n,a,s)}}function zk(e,t,r,n,o,a,s){return Eu(n,r.ds,o,a,(i,c,l)=>{let u=c*c*r.curvature[i];return qn(e,t,i).axAccel(c,Math.abs(We(u,Xn(r,i))),mn(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=We(s*s*r.curvature[i],Xn(r,i)),u=c.scrub?c.scrub(s,Math.abs(l),mn(r,i)):0;return u!==0&&(o=!0),u});return o?{axScrub:a}:{}}function 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=We(w*w*t.curvature[R],Xn(t,R)),T=(i?x.axDecel(w,Math.abs(C),mn(t,R),i(R,w)):x.axDecel(w,Math.abs(C),mn(t,R)))+Ri(t,R);return Math.sqrt(Math.max(0,w*w+2*T*t.ds[R]))},F=n&&R===0?k.v:ib;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=We(k.ay,Xn(t,R));k.ax=qn(e,o,R).axAccel(k.v,Math.abs(x),mn(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=_c(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=Kp(t,r);return Uk.set(e,{capacityAh:t,ocv:r,model:o}),o}function db(e){let t=e.params,r=ph(t,jl(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=eu(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 Iu(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=Hp(t.thermal),n=_c(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??Iu(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}=Pu(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,Ke=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),He=me.dq>0?Se/me.dq:1;Se>=Le&&P<0&&(P=j),F+=me.energyJ*He/vi,be=me.energyJ*He,Fe=me.seconds,C+=me.lossJ*He,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*He,le,v),x>M&&(M=x),Re=oe}else if(o.regen){let xe=u?We(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),He=(1-k)*R,Ue=Math.min(Se.dq,He),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,Ke)),xe.cellC.push(Ke)}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 _u(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 Nu(e,t,r,n){let o=e*t,a=e*(1-t);return o/r-a/n}var Ou=e=>e*9.81*VE;var KX=Math.PI/180;function Vu(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?Nu(e.massTotal,e.frontMassFrac,2*i,2*c):0,u=Ou(l),m=u>.15?"understeer":u<-.15?"oversteer":"neutral";return{gradient:u,balance:m,cAlphaFront:i,cAlphaRear:c}}var qX=Math.PI/180,QX=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 Bu(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(Bu(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 $u(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 u7=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 Gu(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=Bu(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 Ku(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(Gu(yb(e)));return{roll:uM(m.roll,a,s),pitch:uM(m.pitch,l,u)}}var Hu=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/Hu,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/Hu,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/Hu,cn:y/(c*Hu*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=Nu(c,e.frontMassFrac,n,o),M=Ou(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"?Gh(e,o,t.speed):ln(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)=>Vu(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*Jd(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=>Ku(e).roll.freq},{key:"pitchFreq",label:"Pitch-mode freq",unit:"Hz",compute:e=>Ku(e).pitch.freq},{key:"zetaFront",label:"Damping \u03B6 front",unit:"-",compute:e=>$u(e).front.dampingRatio},{key:"zetaRear",label:"Damping \u03B6 rear",unit:"-",compute:e=>$u(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?$h(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorque",label:"Steering holding torque",unit:"N\xB7m",compute:(e,t)=>t.tire?Vh(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorqueGradient",label:"Steering feedback gradient",unit:"N\xB7m/g",compute:(e,t)=>t.tire?Bh(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:We(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?Yu(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,Zd(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?Yu(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 zu(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?nf(m,l):null,d=n.perWheel?f===m?p:nf(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?Yu(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={...Ih(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],Ke=Re==="FL"||Re==="FR",je=Ke?l:u,be=je.muY(Ce)*Ce,Fe=je.muX(Ce)*Ce,xe=E[Re],me=Ke?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?(Ke?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,Ke?Ae:le),He=Ke?p:d,Ue=He&&Ce>0?He.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),Zd(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 Yu(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=We(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?eu(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 Rq=Math.PI/180;var vq=bb.map(ti);var kq=[ce.zFL,ce.zFR,ce.zRL,ce.zRR];var Mq=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 Dq=Math.PI/180;var uQ=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}=Pu(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=_u(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:Hh,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=>Yl(O.ay,O.axAccel,Y(te))*C.tractionFactor),Z=m.map(te=>Yl(O.ay,O.axDecel,Y(te))),ne=m.map(te=>Yl(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(iu,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=>ju(e,r)):t.map(()=>0)}function ju(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=>_u(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):sb(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:Kf(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:$l(e.front.heat,e.front.discs,s.front,r,n,o.front,a)}:{},...e.rear?{rear:$l(e.rear.heat,e.rear.discs,s.rear,r,n,o.rear,a)}:{}}}var zI=.5,YI=.02,WI=6,Uu=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:Uu},(m,f)=>r*f/(Uu-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(Uu-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(Uu-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 dn(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}=nh(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:oh(r.engine.gearbox),limitRpm:r.engine.limitRpm,best:f=>ia(r,f,s,ju(t,f)*s,i).gear,share:(f,p)=>{let d=ju(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=dn(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 qu=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?Eu(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 Qu(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=pn(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 Xu(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=Xu(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=Xu(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=Xu(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=Xu(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 qu(`Event "${e.id}" needs a track.`);let o=Qu(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=Iu(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=pn(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 Ke=0;Ke<le;Ke++){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*(Ke/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*(Ke+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 Zu=e=>e.distance/Math.max(1,e.laps);function Ju(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),em=(e,t,r)=>e?.slice()??new Array(t.s.length).fill(r),h2=e=>em(e.z,e,0),b2=e=>e.gradient?e.gradient.map(t=>100*Math.tan(t*Math.PI/180)):em(void 0,e,0),g2=e=>em(e.bank,e,0),y2=e=>em(e.mu,e,1);function x2(e){let t=e.s.length,r=Ju(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=Ju(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:Ju({s:e.s,length:t}),axGrade:pn(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 tm="Flying lap";function _b(e,t){return e.kind!=="trackLap"||e.label!==tm?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=Qu(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,Zu(n)))})}function Ci(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}},Ti=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(Ti(n)||n==="."&&Ti(e[r+1]??"")){let o=r;for(;r<e.length&&(Ti(e[r])||e[r]===".");)r++;if(e[r]==="e"||e[r]==="E"){let i=r;if(r++,(e[r]==="+"||e[r]==="-")&&r++,Ti(e[r]??""))for(;r<e.length&&Ti(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 Pi=(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=>Pi(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=Pi(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 rm={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=Pi(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=Pi(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=Pi(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},Li={fleetmin:"min",fleetmax:"max"};function to(e){switch(e.kind){case"call":return Object.hasOwn(Li,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(Li,e.name)?Li[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(rm,e.name)?rm[e.name]:void 0;if(!n){let s=[...Object.keys(rm),...t.fleet?Object.keys(Li):[]];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 nm(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:Zu(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 Di(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 om=class extends Error{problems;constructor(t,r){super(`Ruleset "${t}" does not compile:
|
|
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:
|
|
225
225
|
`+r.map(n=>` ${n.key?`${n.key}: `:""}${n.message}`).join(`
|
|
226
|
-
`)),this.name="RulesetDefError",this.problems=r}},Ii=e=>typeof e=="number"&&Number.isFinite(e),Ei=e=>Ii(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":Ei(a.distance)||r(`${s} needs a distance above zero, in metres`),Pt(a.vStart,i=>Ii(i)&&i>=0)||r(`${s}'s entry speed must be zero or more`);break;case"constantRadius":Ei(a.radius)||r(`${s} needs a radius above zero, in metres`),Pt(a.laps,i=>Ii(i)&&i>=1)||r(`${s} runs at least one lap`);break;case"trackLap":Pt(a.laps,i=>Ii(i)&&i>=1)||r(`${s} runs at least one lap`),Pt(a.distance,Ei)||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,Ii)||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,Ei)||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],Ei)||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}=nm(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 am(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 fn(e){let t=structuredClone(e),{plan:r,problems:n}=dS(t);if(!r)throw new om(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=Di(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=Di(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},_i=fn(gS),Hb=fn(yS);var zb="lap",N2=[{kind:"trackLap",id:zb,label:tm,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=fn(xS);function hn(e){if(e===null||typeof e!="object")return JSON.stringify(e)??"null";if(Array.isArray(e))return`[${e.map(hn).join(",")}]`;let t=e,r=Object.keys(t).sort(),n=[];for(let o of r)t[o]!==void 0&&n.push(`${JSON.stringify(o)}:${hn(t[o])}`);return`{${n.join(",")}}`}function ro(e){let t=hn(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=[_i,Hb,Yb],no=_i.id,Ea=e=>Da.some(t=>t.id===e),RS=new WeakMap,Ni=new Map,O2=64;function sm(e){let t=RS.get(e);if(t!==void 0)return t;let r=hn(e),n=Ni.get(r);return n===void 0&&(n=am(e).length?null:fn(e),Ni.size>=O2&&Ni.delete(Ni.keys().next().value),Ni.set(r,n)),RS.set(e,n),n}function im(e,t=[]){if(e==null)return;if(typeof e!="string")return sm(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?sm(n)??void 0:void 0}function oo(e,t=[]){return im(e,t)??_i}function Wb(e=[]){let t=e.filter(r=>!Ea(r.id)).map(r=>sm(r)).filter(r=>r!==null);return[...Da,...t]}var Oi=e=>e.definition??e.id;function cm(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 Vi(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 lm(e){let t=Vi(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 mm(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 um(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=um(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=um(a,t.slice(0,n)),l=um(a,s),u=um(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=mm(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?cm(b.slice(0,d),n,b[d]):Ub(b,n),y=r?cm(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+=th(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 Bi(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+th(v=>Math.hypot(s.d1(p,v),i.d1(p,v)),h,g),k=Math.hypot(s.d1(p,g),i.d1(p,g));if(k<1e-12)break;g-=(R-t)/k}return{seg:p,du:Math.min(Math.max(g,0),a[p])}}var J2=3,Zb=5;function e_(e,t,r,n=Zb){return dm(e,t,r,n)}function dm(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?Vi(e):null,v=k?Xb({...k,z:R},g):R,x=Bi(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??lm(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:Bi(e.widthLeft,1.5,h,n),widthRight:Bi(e.widthRight,1.5,h,n),bank:Bi(e.bank,0,h,n),mu:Bi(e.mu,1,h,n),...y?.drift?{elevationDrift:y.drift}:{}}}function CS(e,t,r){let n=mm(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=mm(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 $i(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??lm(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=dm(e.x,s,n,t,!0),c=dm(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=$i(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=$i(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=$i(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=[...$i(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 fm(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 Gi(e,t,r={}){let n=fm(e,t,r);return{track:it(n.asset,n.numerics),line:n.line}}function rg(e=4,t=Gi){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},hm=256;function Ki(e,t,r,n,o=DS,a=Gi){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(Ci(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 bm=36;var ig=287.05287,f_=461.495,gm=9.80665/(ig*.0065),h_=101325/(ig*288.15),b_=273.15,g_=-500,y_=6e3,x_=400,R_=1100,ym={source:"car",altitudeM:0,pressure:{kind:"standard"},humidityPct:0};function v_(e){return 101325*Math.pow(1-.0065*e/288.15,gm)}function k_(e){return 288.15/.0065*(1-Math.pow(e/h_,1/(gm-1)))}function M_(e){return 288.15/.0065*(1-Math.pow(e/101325,1/gm))}function S_(e,t){return e*Math.pow(1-.0065*t/288.15,gm)}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 Hi(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 Hi(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 xm(e){if(!e||typeof e!="object")return structuredClone(ym);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 zi=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 Rm(){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 Yi(){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 vm(){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:Rm(),rear:Yi(),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(Rm(),e.front),rear:ug(Yi(),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 Wi(){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 ji(){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=vm(),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(Yi(),{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}},km={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}},Mm={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 Sm={[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),[km.name]:Gr(km),[Mm.name]:Gr(Mm),[fg.name]:Gr(fg),[hg.name]:Gr(hg),[bg.name]:Gr(bg),[gg.name]:Gr(gg)},GS=Object.keys(Sm),yg=GS.slice(0,4),xg=[Oa.name,dg.name,km.name,Mm.name,fg.name,hg.name,bg.name,gg.name];var are={"Touring car":km.name,"Street car":Mm.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"],Am={front:"#a6e22e",rear:"#00b4d8"},KS=["#5b4bd6","#4aa3ff","#4ec9a0","#f0e442"],Rg={power:"#ffb454",traction:"#f0845c",front:Am.front,rear:Am.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:Am,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})])),Fm=HS(j_),vt=Fm.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},ire=(()=>{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=Fm[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)),cre=WS(zS,["SERIES","AXLE","LAP_SPEED","LIMITER","ROLE","RIG","FORCE","TYRE_FORCE","REPLAY","AXIS","TRACK","CONSTRUCTION"]),lre=WS(Fm,Object.keys(Fm).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 Ui(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 wm=e=>Ui(e,tA);var rA=["raw.githubusercontent.com"],nA=["tum-csv"],Q_=/^[0-9a-f]{64}$/;function qi(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 Cm=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(`${Cm(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 Tm(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}}$`),Qi=e=>typeof e=="string"&&rN.test(e);async function Tm(e){let t=new TextEncoder().encode(hn(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 Tm(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}),bn=[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 Pm(e){let t={...e};for(let r of bn)for(let n of r.refs)delete t[n];return t}var Lm=vt,Zi=Lm,Lg=Lm,gn=[...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)],Ji=[...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=Sm[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:Zi[r%Zi.length]}}function sN(){return yg.map((e,t)=>Og(e,`v${t+1}`,t))}function iN(){return[Es(),xf(),Rf(),vf(),kf(),Mf(),Sf(),Af(),Ff(),wf()].map((t,r)=>({id:`t${r+1}`,color:Lg[r%Lg.length],model:t}))}function cN(){return[ed(),td(),rd(),nd(),od(),ad(),sd(),id()].map((t,r)=>({id:`a${r+1}`,color:Dg[r%Dg.length],model:t}))}function lN(){return[Bp(),$p(),Gp()].map((t,r)=>({id:`b${r+1}`,color:Eg[r%Eg.length],model:t}))}function uN(){return[{id:"brk1",color:_g[0],model:structuredClone(Wf)}]}function mN(){return[{id:"dmp1",color:Ji[0],model:structuredClone(lu)}]}function pN(){return[vg(),kg()].map((t,r)=>({id:`m${r+1}`,color:gn[r%gn.length],model:t}))}function Vg(e){let t=r=>({...r,provenance:wm(r.model)});return{...e,suspensions:e.suspensions.map(t),vehicles:e.vehicles.map(r=>({...r,provenance:wm(Pm(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 ec(e="Untitled project"){let t=new Date().toISOString(),r=sN();return Vg({schemaVersion:bm,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(ym),diffYaw:!1,lapCounts:{},pathPlanId:null,useRacingLine:!0,standingStart:!1}})}var dN=["front","rear"],Bg=9.81,fN=Math.PI/180;var yn="*",$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 Kr=Math.PI/180,hN=9.81,tc=.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*Kr;if(t==="side")return uA(i=>r*e.Fy(r*i*Kr,n,a),1,45);let s=t==="drive"?1:-1;return uA(i=>s*e.Fx(s*i,n,a),.02,.6)}function Em(e){let t=e?Tl(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))/Kr;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,()=>Pl(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*Kr);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)>=tc?e==="ackermann"&&!(fA(t)<=Wg)?`is a corner wider than ${Wg} m`:null:"does not corner":(e==="drive"?t.axG:-t.axG)>=tc?null:e==="drive"?"does not drive":"does not brake"}var vN=e=>e.axG>=tc?"drive":e.axG<=-tc?"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 Dm=(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=Em(Va(t,k));v=[m(k,Dm(k,o.outer),"side",1,x),m(k,Dm(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*Kr;return Math.atan2(M+s*Math.sin(w),s*Math.cos(w)-F)/Kr},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,Em(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=Em(Va(t,k));x=f(v,[m(k,Dm(k,"L"),v,1,M),m(k,Dm(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*Kr,N.g.Fz,N.g.read*Kr)},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)))/Kr;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,rc={speed:20,ayG:1.2};function Zg(e,t={}){let r=t.operating??rc,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=Kh(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=rn(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 nc(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=nc(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 _m(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 Nm(e,t,r){if(!t.length)return e;let n=nc(e),o=n.length,a={widthLeft:Im(e.widthLeft,r.widthLeft),widthRight:Im(e.widthRight,r.widthRight),bank:Im(e.bank,r.bank),mu:Im(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=_m(t,n,a,s);return{...e,...i}}function Im(e,t){return typeof e=="number"?e:t}var xA=1,gA=4,Vm=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)*Vm:e.length}function Om(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 oc=(e,t,r,n,o)=>e+t*o+(n>0?(r-t)*o*o/(2*n):0);function ac(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*Vm,b=e.length?Om(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=oc(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=oc(h,S,A,P,z),_=oc(h,S,A,P,z+V/2),B=oc(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=Om(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=oc(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?Om(e[0],b):0,F={gap:v,headingError:FN((h-o.heading*Vm)/Vm),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=Om(P,A);w.push({index:S,before:A,after:L,jump:Math.abs(L-A)})}let C=_m(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 sc(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:sc(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=ac(o,{name:sc(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 $m={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:sc(e.course.spec)}var FA=new WeakMap,Bm=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=Bm.get(n);if(o)return{...o,numerics:r};let a=r0(e.spec),s={asset:a.asset,standingStart:a.standingStart};return Bm.size>64&&Bm.clear(),Bm.set(n,s),{...s,numerics:r}}function o0(e,t,r={}){let n=r.lap??$m,o=r.simParams,a=r.numerics??{},s=n.courses.length?n.courses:$m.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?dn(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=zu(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:pn(v.track.gradient,M.v.length),bank:v.track.bank,...M.loadFactor?{loadFactor:M.loadFactor}:{}},T?{driven:ih(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 ic(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(Qr(e,Ze(t,r)));return-Math.asin(Math.max(-1,Math.min(1,X(o,n))))*CA}function Gm(e,t,r,n,o){let a=q(Qr(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-vd(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 Km(e,t,r){let n=Ze(t,e.vehicle.config),o=gt(e,r),a=fu(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=ic(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,Hm=2,u0=.25,_N={heave:0,pitch:0,roll:0,steer:0},NN={FL:"FR",FR:"FL",RL:"RR",RR:"RL"},zm=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:zm(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=Zr(t,e.vehicle.config,_N,e.vehicle);s=zm(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:zm(ye(l,f.travel-l0,f.steer,void 0,p)),hi:zm(ye(l,f.travel+l0,f.steer,void 0,p)),step:l0},g=c.isFront?{lo:Ie(l,d.beta,f.steer-Hm,void 0,p),hi:Ie(l,d.beta,f.steer+Hm,void 0,p),step:Hm}: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=hu(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=Km(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=ic(e,{FL:u.FL.ground,FR:u.FR.ground,RL:u.RL.ground,RR:u.RR.ground}),O=e.kc?.loadCase,G=Y=>O?Gm(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=sl(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)*Hm,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 cc(e,t,r,n,o){return OA(e,t,r==="front"?"FL":"RL",n,o)}function p0(e,t,r,n){let o=cc(e,t,"front",r,n?.front),a=cc(e,t,"rear",r,n?.rear);return{front:o,rear:a,wheelbaseChange:o.longitudinal-a.longitudinal}}var Ym=Math.PI/180,lc={travelSteps:9,heaveSteps:5,rollSteps:4,rackSteps:6},Wm={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,...mh(t),drive:ch(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=lc,r=Wm,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=pl(u().ctx.FL,Ot(s.front.config));return F=S?dl(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,()=>df(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*Ym,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])*Ym);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=jd(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 cc(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*Ym),L=u();if(!L.kc)return P;try{let D=gt(L,{heave:0,pitch:0,roll:A*Ym,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=im(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?Ki([c],a.track,a.numerics,Oi(s),a.settings,$N)[0]:Ci(c,s,{numerics:a.numerics,standingStart:l,lapCounts:u});o={};for(let f of s.metrics)Dc(f)&&(o[f.key]=f.value(m,void 0))}}catch{o=null}return r.set(n,o),o}}}var jm=Math.PI/180,Um=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 uc(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])))/jm}function mc(e){let t=e.measured;if(t)return $A(t.travel,t.toe);let[r,n]=e.config.spinAxis;return Math.atan2(r,n)/jm}function h0(e,t){let r=Math.abs(t.camber)>=Um,n=Math.abs(t.toe)>=Um;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=(uc(e)+t.camber)*jm,l=(mc(e)+t.toe)*jm,[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 Xm(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:Xm(r.camber_front_deg)??uc(e.front),rear:Xm(r.camber_rear_deg)??uc(e.rear)}}function KN(e,t){let r=t;return{front:Xm(r.toe_front_deg)??mc(e.front),rear:Xm(r.toe_rear_deg)??mc(e.rear)}}function HN(e){return{camber:{front:uc(e.front),rear:uc(e.rear)},toe:{front:mc(e.front),rear:mc(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)<Um&&Math.abs(u.toe)<Um;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=zp(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 pc(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 dc="*";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 Qm(e,t){return e?.appliesAt?t.find(r=>!e.appliesAt(r)):t[0]}function Zm(e,t,r){let n=r?.stateId?e.stateOf(r.stateId):Qm(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===dc&&t.reads==="course"?ZN(e,t,r):r?.stateId===yn&&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"},fc={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 hc=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 bc=(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?Ed(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=Pd(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(fc)?.[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?hc(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?hc(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=>hc(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=>hc(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[bc(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[bc(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[bc(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(fc)?.[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[bc(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[bc(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:hc(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(fc)?.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(fc)?.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(fc)?.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=Zm(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)):[Zm(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 Jm(e){let t=aF.get(e);return t||(t=e.metrics.filter(Dc).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(Jm);var ep=[...M0,...S0,...w0,...C0,...T0],Ha=Object.fromEntries(ep.map(e=>[e.id,e]));var sF={all:ep,byId:Ha},iF=new WeakMap;function Hr(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(Jm);return t=r.length?{all:[...ep,...r],byId:{...Ha,...Object.fromEntries(r.map(n=>[n.id,n]))}}:sF,iF.set(e,t),t}var gc=180/Math.PI,za=Math.PI/180,gO=.2;function tp(e,t){let r=H(t,e);return q(r[0]<0?pd(r):r)}var rp=e=>({side:Math.atan2(e[2],e[0])*gc,plan:Math.atan2(e[1],e[0])*gc}),np=(e,t)=>q([1,Math.tan(t*za),Math.tan(e*za)]),yc=e=>Math.abs(e[0])>=gO,op=(e,t)=>Math.atan(t/Math.max(e,1))*gc,ap=(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"}},xc={uca:"upper arm",lca:"lower arm"},yO=1,cF=(e,t)=>tp(e[jt[t].fore],e[jt[t].aft]);function lF(e){let t=q(H(md,U(e,X(md,e))));return{e1:t,e2:ae(e,t)}}function P0(e,t){let r=cF(e,t);if(!yc(r))return`the ${xc[t]}'s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it`;let n=jt[t],o=Xr(e[n.ball],e[n.fore],r);return Math.hypot(...H(o,e[n.ball]))>=yO?null:`the ${xc[t]}'s ball joint sits on its own pivot axis, so the arm has no length to swing on`}function zr(e,t){let r=jt[t],n=e[r.ball],o=cF(e,t),a=Xr(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{...rp(o),clock:Math.atan2(X(u,l),X(u,c))*gc,len:i,sFront:X(H(e[r.fore],a),o),sRear:X(H(e[r.aft],a),o)}}function L0(e,t){let r=np(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={...zr(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 sp(e,t,r){return t==="len"?r:op(mF(e,t),r)}function D0(e,t,r){return t==="len"?r:ap(mF(e,t),r)}var ho=["side","plan","atY","atZ"],bo={fore:"rockerPivotA",aft:"rockerPivotB"},xO=5,pF=e=>tp(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":yc(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=yc(t)?t:[1,0,0],n=e.rockerPivotA,o=ee(n,U(r,-n[0]/r[0]));return{...rp(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=np(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"?op(fF(e),r):r}function _0(e,t,r){return t==="side"||t==="plan"?ap(fF(e),r):r}var Xt={front:"Front",rear:"Rear"},Ut=["x","y","z"],Oe=(e,t)=>t==="front"?e.front:e.rear,Rc=(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:Rc(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:zr(a,o);for(let i of Rn)t.push({id:`arm.${r}.${o}.${i}`,group:`${Xt[r]} ${n?"arm axes":"wishbone axes"}`,label:`${xc[o]} \u2014 ${vO[i]}`,scope:Xt[r],unit:kO[i],defaultSpan:s?sp(s,i,go):go,read:c=>zr(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:Rc(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:Rc(s.vehicle,r,{...c,hardpoints:l})}}})}return t}var ip={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 cp=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[ip[r]],a=e.params[N0[r]],s=wO(n,a),i=d=>d.params[ip[r]],c=d=>d.params[N0[r]],l=(d,h)=>({...d,params:{...d.params,[ip[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=Jr(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:Rc(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:Rc(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=Su[`${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:Mu({...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(Wl(e.params)!=="hydraulic")return[];let t=[{id:"brakeSetup.barFront",group:"Brakes",label:`${bh("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:hh(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 Tu(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[ip[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?nb:ob;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(Fu))t[`param.${s}`]={why:i};for(let[s,i]of Object.entries(wu(e.params)))t[`param.${s}`]={why:i};let a=Wl(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(rb).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 up=e=>(e.metrics??Hr()).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 mp(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=up(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 lp=3;function $O(e,t){let r=(c,l)=>t({...e,travelMin:c,travelMax:l}),n=e.travelMin-lp,o=e.travelMax+lp;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+lp)),i=Math.max(1,Math.min(e.travelMax,o-lp));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:lc.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 vc(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)+kc(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 kc(e,t,r){if(!e&&t?.reads!=="state")return"";e??={};let n=[];if(t?.reads==="state")if(e.stateId===yn)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===dc&&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 pp(e,t,r={}){t=Dt(e,t);let n=Y0(e,t),o=Gt(e),a=up(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=vc(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)+kc(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=pc(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=pc(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=up(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),yn]);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===yn&&!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!==yn?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&&!Qm(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),dc]);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=pc(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=pp(e,t,r),a=up(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?en(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 wse=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}),Lse=[{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(Bf,Math.max(Vf,t)):At}var OF=6e4;var Aie=[{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"]),Nie=["id",...oV];var $F=.18/1.18,GF={induction:{kind:"natural"}},KF=e=>e.breathing??GF;function dp(e){switch(e?.kind){case"sae-j1349":return Hi(99e3,25);case"measured":return Hi(e.hPa*100,e.tempC);default:return Hi(101325,20)}}var sV=dp(void 0);function HF(e,t){let r=dp(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(dp(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 ${Cm(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(!Qi(o.address))throw new Error(`"${o.address}" is not a catalogue address`);if(!qi(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(!Qi(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=ku(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,...zi(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 zi(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 Mc(e,t){if(!t?.points.length)return e;let r=nc(e),{zSmoothing:n,...o}=e;return{...o,z:qF(t,r,Jg(e),e.closed)}}var fp={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 Sc(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}=ac(i,{name:e.name,closed:c,spacing:l,base:fp});return Mc(u,r.profile)}let n=r.sections??[];if(r.kind==="inline")return Mc(Nm(r.asset,n,fp),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 Mc(Nm({...t,...o!==void 0?{widthLeft:o}:{},...a!==void 0?{widthRight:a}:{},...s!==void 0?{closed:s}:{}},n,fp),r.profile)}var mue=1/500;var pue=5*Math.PI/180;var vue=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=dn(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),...zi(xm(t.air??r.air))?{air:xm(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 hp(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 Sc(r,t)}}function IV(e,t){let r=structuredClone(e);for(let[n,o]of Object.entries(t))if(!Tu(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 bn){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 bp(e,t,r={}){let n=Wa(e,r.settings),{entry:o,asset:a}=await hp(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=Oi(oo(e.meta.rulesetId,e.rulesets)),u=Ki(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 hp(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 gp(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=Cu(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=bn.find(l=>l.doc===i.part);if(!c)throw new Error(`"${i.part}" is not a library \u2014 it is one of ${bn.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*gp(c).length,1);if(s>hm)throw new Error(`that grid is ${s} runs, over the ${hm} 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=gp(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=bn.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 bp(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(gp(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:gp(u)})),runs:a,metricKeys:i,fleetScored:s,flat:c,caveats:l}}var wpe=Math.PI/180;function sy(e){if(!e.chassis)return e;let{chassis:t,...r}=e;return r}var kbe=180/Math.PI;var _5={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 Qge=_5.id;var Ac=.02;function gw(e){let t=Math.max(Ac,Math.abs(e.heaveMotionRatio)),r=Math.max(Ac,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 O5=(e,t)=>({od:t,id:Math.min(e.id,t-.5)}),V5=(e,t)=>e/(2*t*t);function bw(e,t){switch(e.kind){case"ubar":case"blade":case"torsionTube":return{...e,section:O5(e.section,t)};default:return e}}function yw(e,t,r){let n=Math.max(Ac,Math.abs(r));if(e?.kind==="coil"){let l=V5(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 B5=Math.PI/180,yp=1e-6;function $5(e){return!(ve(e.rockerPivotA,e.rockerPivotB)<yp||ve(e.rockerToPushrod,e.rockerPivotA)<yp||ve(e.rockerToDamper,e.rockerPivotA)<yp||ve(e.rockerToDamper,e.damperChassis)<yp)}function Mw(e){if(!$5(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}=K5(e);return{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}}var Rw=40;function xp(e,t={}){let r=e.hardpoints,n=r.pushrodOuter,o=r.damperChassis,a=ve(n,o),s=ee(n,U(H(o,n),G5)),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)*B5),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 G5=.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 K5(e,t={}){let r=t.target??kw(e),n=t.armAngleDeg,o=xp(e,{armAngleDeg:n});if(!(r>0))return o;let a=ve(e.hardpoints.pushrodOuter,e.hardpoints.damperChassis),s=Math.max(25,.15*a),i=(()=>{for(let p of[1,-1]){let d=xp(e,{armRod:s,armAngleDeg:n,damperSide:p}),h={...e,config:{...e.config,actuation:"rocker"},hardpoints:d};try{let b=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:xp(e,{armRod:p,armAngleDeg:n,armDamper:d,damperSide:i})})}catch{return Number.NaN}},l=[1,.6,.35,.2,1.7,2.6].map(p=>Math.max(12,s*p)),u=s,m=s,f=1/0;for(let p of l){let d=.25*p,h=6*p,b=p;for(let y=0;y<24;y++){let R=(d+h)/2,k=c(p,R);if(!Number.isFinite(k))break;b=R,k<r?d=R:h=R}let g=Math.abs(c(p,b)-r);if(Number.isFinite(g)&&g<f&&(f=g,u=p,m=b),f<1e-4*Math.max(1,r))break}return xp(e,{armRod:u,armAngleDeg:n,armDamper:m,damperSide:i})}var m0e=Array.from({length:19},(e,t)=>-45+5*t);var p0e=Math.PI/180;function H5(e){let t=e.hardpoints,r=q(H(t.rockerPivotB,t.rockerPivotA)),n=Xr(t.rockerToDamper,t.rockerPivotA,r),o=.6*Ur(H(t.rockerToDamper,n)),a=ae(r,ux),s=Ur(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 z5=(e,t)=>({...e,config:{...e.config,actuation:t}});function ly(e,t,r,n){let o=r==="front"?e.front:e.rear,a=yu(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=z5(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)??_d(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?H5(f):Q1(f)),R=wn(f,d).atDesign,k=Ho(f,y,{kind:b}).atDesign,v=Ru(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))>=Ac?e:void 0}var Rp=[{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}),Y5={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]}},W5={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]}},j5=()=>({outer:[0,189,486],attach:"rocker",mount:{kind:"chassis",anchor:[-225,0,486]}}),U5={rate:60,motionRatio:1},X5={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]}},q5=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]}},Q5={kind:"coil",rate:1560,motionRatio:1,gap:0,bothWays:!0},Z5=40,J5={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}),e3=e=>[e[0],e[1],e[2]];function t3(e){let t=r=>({...r,hardpoints:{...r.hardpoints,...Tw(J5)},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,e3(r)]))}function Pw(e,t=lo(),r=e==="pull"?W5:Y5){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 vp(e,t){let r=my(e),n=ja(e);if(e==="heave")return{meta:r,vehicle:n,components:{...uy(),heaveFront:{design:{...Qh,...U5},linkage:j5()}}};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{...Wi(),name:t};if(e==="mcpherson"){let n=ji(),o=vm();return{...n,front:{...o,config:{...o.config,loadedRadius:n.front.config.loadedRadius}},name:t}}let r=r3(Pw(e==="pullrod"?"pull":"push"));return{...e==="decoupled"?t3(r):r,name:t}}var Cw={front:221.7,rear:220.9};function r3(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=Rp.find(r=>r.id===e);if(!t)throw new Error(`Unknown suspension template: ${e}`);return t}function kp(){let e=t=>({design:{...Q5},linkage:q5(t),damper:Z5});return{meta:my("heave"),vehicle:Pw("push",mg(),X5),components:{...uy(),heaveFront:e("front"),heaveRear:e("rear")}}}var Lw=[10,25,50,100,200,300],n3=[{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 o3(e,t,r){let n=Lw.map(o=>Dw(r*o));return{id:e,label:t,speedMmS:[...Lw],bumpN:n,reboundN:[...n]}}function a3(e){return{name:e.name,body:{...e.body},curves:n3.map(t=>o3(t.id,t.label,Dw(e.coefficient*t.scale)))}}function Fc(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:Ji[e.dampers.length%Ji.length],model:a3(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}}},Mp={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}}},Sp={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=ec(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[,s3,i3,c3,l3,u3,m3,p3]=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 d3=[{label:"Formula Student (decoupled)",vehicle:Bw,components:e=>Fc(vp("decoupled",e).components,Mp)},{label:"Formula 1 (third springs)",vehicle:()=>kp().vehicle,components:()=>Fc(kp().components,Sp)}],hy={"direct-coilover":"direct",pushrod:"pushrod",pullrod:"pullrod","third-spring":"heave","mcpherson-strut":"mcpherson"},f3=[...d3.map(e=>e.vehicle),...Object.values(hy).map(e=>()=>ja(e))];function Ua(e){let t=Fc(vp("decoupled",e.vehicles[0].params).components,Mp);e.suspensions=[{...e.suspensions[0],model:Bw()}];for(let r of e.vehicles)fy(r.params,t);return fr(e,Mp),e}var ko={title:"OpenStreetMap",url:"https://www.openstreetmap.org/copyright",licence:"ODbL-1.0",credit:"\xA9 OpenStreetMap contributors"},Ap={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"},h3={id:"cota",name:"Circuit of the Americas, Austin",address:"e0c6ea889d708cf15f9c",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ko,Ap,Gw]}},b3={id:"laguna-seca",name:"Laguna Seca, Monterey",address:"185b5811b9c423ef44ef",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ko,Ap,Gw]}},g3={id:"nordschleife",name:"Nordschleife, N\xFCrburg",address:"74c49603c7b2f15985c6",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ko,$w]}},y3={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."}]}},x3={id:"bristol",name:"Bristol, Tennessee",address:"f0e23953669a414ad600",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ko,Ap]}},R3={id:"pikes-peak",name:"Pikes Peak, Colorado",address:"3de137fe33b5c2875036",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ko,Ap]},standingStart:!0},v3={source:"venue",altitudeM:3580,pressure:{kind:"standard"},humidityPct:0},k3=10,M3={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=Ui(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:gn[e.motors.length%gn.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 S3=3.8,Fp={hubPlanetary:14.5,inboardChain:4,engineChain:3.4},A3="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:A3},t.id}function wp(e,t,r){let n=Xa(Ua(kn(e,r)));return n.vehicles[0].params.name=t,n}function F3(){let e=wp("Formula Student combustion car","Formula Student combustion","fs-cv");Mn(e,Sg(),Fp.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 w3(){let e=wp("Formula Student AWD car","Formula Student AWD","fs-ev");return by(e,Kw(e),4,"awd",Fp.hubPlanetary,"hub"),e}function C3(){let e=wp("Formula Student RWD hub-motor car","Formula Student RWD hub motors","fs-ev");return by(e,Kw(e),2,"rear",Fp.hubPlanetary,"hub"),e}function T3(){let e=wp("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:gn[e.motors.length%gn.length],model:Mg()}],by(e,t,1,"rear",Fp.inboardChain),e.vehicles[0].params.driveline={rear:structuredClone(xt.clutch)},e}function P3(){let e=Xa(Ua(kn("Formula Student endurance energy","fs-ev"))),t=e.vehicles[0],r=structuredClone(t);if(r.id="v2",r.color=Zi[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 L3(){let e=kp(),t=vo("Formula 1 car","trackday",s3,()=>e.vehicle);return fy(t.vehicles[0].params,Fc(e.components,Sp)),fr(t,Sp),Mn(t,Ag(),S3),Mo(t,h3)}function Hw(e="GT car",t=Wi){let r=vo(e,"trackday",i3,t);return fr(r,Ew),Mn(r,jS(),r.vehicles[0].params.gear_ratio.value),Mo(r,b3)}function zw(e="Sports car",t=ji,r=dy){let n=vo(e,"trackday",c3,t);return fr(n,r),Mn(n,US(),n.vehicles[0].params.gear_ratio.value),Mo(n,g3)}function D3(){let e=vo("Cup car","trackday",l3,_S);return fr(e,_w),Mn(e,XS(),e.vehicles[0].params.gear_ratio.value),Mo(e,y3)}function E3(){let e=vo("Stock car","trackday",u3,NS);return fr(e,Nw),Mn(e,qS(),e.vehicles[0].params.gear_ratio.value),Mo(e,x3)}function I3(){let e=vo("Hill-climb prototype","trackday",m3,OS);return fr(e,Ow),Mn(e,QS(),e.vehicles[0].params.gear_ratio.value),e.settings.air=structuredClone(v3),e.settings.airTempC=k3,Mo(e,R3)}function _3(){let e=vo("Race truck","trackday",p3,VS);return fr(e,Vw),Mn(e,ZS(),e.vehicles[0].params.gear_ratio.value),Mo(e,M3)}function N3(e){let t=Rp.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=vp(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 wc(e,t,r){let n=hy[e],o=Rp.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:()=>N3(n)}}var O3=[{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:P3},{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:F3},{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:w3},{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:C3},{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:T3},{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:L3},{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:D3},{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:E3},{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:I3},{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:_3},{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")))},wc("direct-coilover","The GT car\u2019s wishbones driving coilovers straight into the towers, at Laguna Seca.","On the GT car, at Laguna Seca."),wc("pushrod","The FS car on pushrods: a rod from each lower wishbone works a rocker.","On the Formula Student car, at FSG."),wc("pullrod","The FS car on pullrods: a rod from each upper wishbone pulls a low rocker.","On the Formula Student car, at FSG."),wc("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."),wc("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=O3.map(e=>({...e,load:()=>Vg(e.load())}));var Ww={width:320,height:200},q0e=[.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 $3=Math.PI/180,G3=e=>e>1?e/100:e;function Cc(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*$3});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 K3(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 H3(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:Cc(()=>ea(e.front)),kinRear:Cc(()=>ea(e.rear))};return Qw.set(e,s),s}function rC(e,t,r,n){let o=H3(e),a=Wn(e,t),s=ga(e,t),i=mk(e,t),c=Ru(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=G3(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=Au({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=Cc(()=>gi(o.kinFront(),Q(t,"camber_front_deg"))),N=Cc(()=>gi(o.kinRear(),Q(t,"camber_rear_deg"))),z=Cc(()=>K3(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:cu(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 vu(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 z3(e,t){return vy(e,t.switches)}var ky=e=>Hr(e?.rulesets);function iC(e,t,r,n,o={},a=()=>r.standingStart){let s=vy(n,r.switches),i=(l,u)=>{let m=fm(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=>z3(r,t),session:()=>t}:{}},Cp=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)}),Y3=(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,Tc=[0,.15,.15];function pC(e,t,r,n=Tc.length){let o=Ay(t);return Tc.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 W3(e,t,r,n).filter(s=>s.excess>-o*(a[s.metricId]?.scale??1))}function W3(e,t,r,n){let o;try{o=xn(mp(e,t,r),Y3(t,n))}catch{return[]}return j3(o,t,ky(n))}function j3(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)}${kc(o.at,a)}`;n.push({key:o.key,metricId:o.metricId,label:i,unit:a.unit==="-"?"":a.unit,value:s,excess:vc(o,s)})}return n}var U3=.05;function X3(e,t){if(t.id.startsWith("hp.")||cp(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(zr(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=>X3(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(U3,m),unit:a}}var q3={steeringSystem:!0,brakeSetup:!0,driveline:!0,heaveFrontDesign:!0,heaveRearDesign:!0,arbFrontDesign:!0,arbRearDesign:!0},bC=e=>Object.hasOwn(q3,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 Q3(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&&!Q3(n.id)).map(n=>ct(r[n.id]))}function gC(e,t,r){t=Dt(e,t);let n=Gt(e),o=mp(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=Cp(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)=>pp(e,t,Cp(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 Z3(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=Z3(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 J3="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(J3);let o=Wa(e),a=e.tracks.length?(await hp(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 Sc(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,{...Cp(i),metrics:Hr(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 eB(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??Tc.length,Tc.length)),m=await eB(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 rB(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 bp(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 rB(tB,(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{rB as runJob,wC as threadCpuMs};
|
|
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};
|