@pacedyn/mcp 0.389.0 → 0.391.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 +7 -7
- package/package.json +1 -1
package/dist/worker.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{parentPort as jw,workerData as m3}from"node:worker_threads";import{readFileSync as E0}from"node:fs";import{join as I0}from"node:path";var Sc=e=>e.format!=="points"&&!e.field;var ft=e=>e?.kind==="ice";var ly={packVoltageMax:600,segmentVoltageMax:120,powerLimitKw:80};var De=e=>typeof e=="number"&&Number.isFinite(e);function Xw(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(De))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(De))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(De))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(De))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(De))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 Qw(e){return!e||typeof e!="object"?"The cell has no curve.":e.kind==="table"?Xw(e):e.kind==="analytic"?!De(e.vCut)||!De(e.vNom)||!De(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?!De(e.r0)||e.r0<0?"The cell resistance must be a number and cannot be negative.":e.socAtNom!==void 0&&(!De(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 Ac(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(!De(t.capacityAh)||t.capacityAh<=0)return"The cell capacity must be a positive number of amp-hours.";if(!De(t.vMin)||t.vMin<0)return"The cut-off voltage must be a number and cannot be negative.";if(!De(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(!De(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&&(!De(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&&(!De(t.massKg)||t.massKg<0))return"The cell mass must be a number and cannot be negative.";let r=Qw(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(!De(o.heatCapacityJPerK)||o.heatCapacityJPerK<=0)return"The cell heat capacity must be a positive number of joules per kelvin.";if(!De(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&&!De(o.startC))return"The starting temperature must be a number.";if(o.entropicVPerK!==void 0&&!De(o.entropicVPerK))return"The entropic coefficient must be a number.";if(o.derateFromC!==void 0){if(!De(o.derateFromC))return"The temperature the derate starts at must be a number.";if(o.derateToC!==void 0){if(!De(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(!De(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 Sn(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 Fc(e,t,r,n,o){let a=e.length,s=t.length;if(a===0||s===0)return 0;let i=Sn(e,n),c=Sn(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 Fo=[0,.05,.1,.2,.3,.4,.5,.6,.7,.8,.9,1],kp={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]},uy=[0,.05,.1,.2,.5,.8,1],my=[2.2,1.55,1.3,1.12,1,.97,.98];function py(e){return Be(uy,my,e)}var dy=[-20,-10,0,10,25,40,60],fy=[4,2.8,2,1.4,1,.82,.75];function Mp(e){return Be(dy,fy,e)}var hy=.5;function Sp(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=kp[t]??kp.other,l=e.socAtNom??hy,u=Fo.includes(l)?[...Fo]:[...Fo,l].sort((h,b)=>h-b),m=Be(Fo,c,l),f=m>0&&m<1?Math.log(i)/Math.log(m):1,p=[],d=[];for(let h of u){let b=Be(Fo,c,h);p.push(o+s*Math.pow(b,f)),d.push(e.constantResistance?a:a*py(h))}return{kind:"table",soc:u,ocv:p,r0:d}}function Ap(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 wo=25,by=new WeakMap;function hr(e){let t=by.get(e);if(t)return t;let r=Ac(e);if(r)throw new Error(r);let{cell:n,pack:o}=e,a=n.curve.kind==="table"?n.curve:Sp(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=wo)=>{let C=l&&u?Fc(a.soc,l,u,F,w):Be(a.soc,a.r0,F)*Mp(w);return c*C+o.busResistance},y=(F,w,C)=>b(F)-w*g(F,C),x=(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))},M=(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)},R=(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,$=Number.isFinite(p)?P(p):1/0,O=S>0?T*T/(4*S):1/0,W=[["rules",D],["voltage-floor",E],["current",$],["matched-load",O]],I=W[0][0],_=W[0][1];for(let[G,K]of W)K<_&&(_=K,I=G);let V=v(w??wo);V<1&&(_=Number.isFinite(_)?_*V:_,I="temperature");let N=Number.isFinite(_)?x(_,F,w):1/0;return{watts:_,binding:I,rules:D,voltageFloor:E,current:$,matchedLoad:O,derate:V,amps:N,volts:Number.isFinite(N)?T-N*S:T}},k={model:e,table:a,capacityAh:m,chargeC:m*3600,energyKwh:m*(s*Ap(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:x,chargeCurrentFor:M,maxPower:R};return by.set(e,k),k}function Fp(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 gy={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},yy={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},xy={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 wp(){return{name:"Formula Student accumulator",cell:Fp(gy),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 Cp(){return{name:"LFP pack",cell:Fp(yy),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 Tp(){return{name:"Road car pack",cell:Fp(xy),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 Pp(e,t,r="Constant pack"){return{name:r,cell:{name:"Constant cell",chemistry:"other",capacityAh:e,curve:{kind:"table",soc:[0,1],ocv:[t,t],r0:[0,0]},iMaxA:0,vMin:0,vMax:t},pack:{series:1,parallel:1,busResistance:0},provenance:{source:"assumed",note:"The constant pack: one open-circuit voltage, no internal resistance and no current limit \u2014 what a car carried before the battery was a model. It cannot sag, so its power never fades."}}}function wc(e){if(e.kind==="ice"){let n=e.gearbox.efficiency;return{model:e,maxTorque:o=>o>e.limitRpm?0: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)=>Fc(e.effRpm,e.effTorque,e.effGrid,n,o);return{model:e,maxTorque:t,efficiency:r}}function Lp(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,x=d;for(let M=0;M<g;M++)x+=(h-e.coolingWPerK*(x-e.coolantC))*y/e.heatCapacityJPerK;return x},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 Dp(e,t){let r=e.tyreFreeRadiusRear;return(t==="rear"&&r!==void 0?r:e.tyreFreeRadius)??0}var Cc=9.81,Ry=(e,t)=>e*(t*t)/2*(Math.PI/180)/1e3,Wa=(e,t)=>e+t>0?e*t/(e+t):0,vy=.5;function Tc(e,t,r){if(!(r>0))return 1;let n=e*Cc*t*(Math.PI/180)/r;return 1/(1-Math.min(vy,n))}function Ep(e,t,r){return r>0?e*Cc*t/(r*r):0}function ky(e,t,r,n,o){if(!(n>0)||!(o>0))return 1;let a=Ep(e,t,r)*(1/n+1/o);return 1/(1-Math.min(vy,a))}function Ce(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=Wa(i,a),u=Wa(c,s),m=($,O)=>{let W=O/2;return W>0?1/(2*Math.PI)*Math.sqrt($*1e3/W):0},f=m(l,n),p=m(u,o),d=Wa(e.wheelRateFront+e.arbFront,a),h=Wa(e.wheelRateRear+e.arbRear,s),b=Ry(d,e.trackFront),g=Ry(h,e.trackRear),y=b+g,x=y>0?b/y:.5,M=e.rcHeightFront+(e.rcHeightRear-e.rcHeightFront)*(1-e.frontMassFrac),v=(e.cgHeight-M)/1e3,R=r*Cc*v,k=Tc(r,v,y),F=y>0?R/y*k:0,w=e.massTotal*Cc*e.cgHeight/e.wheelbase,C=2*l,T=2*u,S=ky(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*Wa(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:x,rollGradient:F,pitchGradient:P,pitchRate:L,cgRollGain:k,cgPitchGain:S,rideDampingFront:D+(e.heaveDamperFront??0),rideDampingRear:E+(e.heaveDamperRear??0),rollDampingFront:D+(e.rollDamperFront??0),rollDampingRear:E+(e.rollDamperRear??0)}}var zr=["clFront","clRear","cd"],Co=e=>e.frame?.kind==="pitch";function Pc(e){return Co(e)?{x:e.axes.h,y:e.axes.pitch}:{x:e.axes.hFront,y:e.axes.hRear}}var My=e=>e.frame?.kind==="pitch";var Lc=45,qe=e=>typeof e=="number"&&Number.isFinite(e);function Dc(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 Sy(e,t){if(t===void 0)return null;for(let r of zr){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 Ay(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 ja(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=Dc("front ride-height",e.axes?.hFront);if(i)return i;let c=Dc("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=Dc("ride-height",e.axes?.h);if(i)return i;let c=Dc("pitch",e.axes?.pitch,"\xB0","pitch");if(c)return c;let l=e.axes.pitch.find(u=>Math.abs(u)>=Lc);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 zr){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 Sy("yaw",e.attitude?.yaw)??Sy("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 zr){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])>=Lc||Math.abs(i[1])>=Lc))return`A pitch range reaching ${Math.abs(i[0])>=Lc?i[0]:i[1]}\xB0 is not a car's attitude. Pitch is in degrees.`}return Ay("yaw",e.attitude?.yaw)??Ay("roll",e.attitude?.roll)}return`Unknown aero model kind "${e.kind}".`}var Fy=180/Math.PI;function Ec(e,t,r,n){let o=(n-r)/t;return{h:r+e.refX*o,pitch:Math.atan(o)*Fy}}function To(e,t,r,n){let o=Math.tan(n/Fy);return{hFront:r-e.refX*o,hRear:r+(t-e.refX)*o}}var q3=180/Math.PI,qw=["hFront","hRear"],Zw=["h","pitch"],Np=e=>e?.kind==="pitch"?Zw:qw,Mt=(e,t)=>e[t],Ic=(e,t)=>e[t],Ip=(e,t)=>({[e[0]]:t(e[0]),[e[1]]:t(e[1])});function Jw(e){if(!(!e.yaw&&!e.roll))return{...e.yaw?{yaw:{...e.yaw}}:{},...e.roll?{roll:{...e.roll}}:{}}}function Op(e){let t=Np(e.frame),r=e.balanceFront,n=e.cl*r,o=e.cl*(1-r),a=Ip(t,c=>Mt(e.dCl,c)*r+e.cl*Mt(e.dBalance,c)),s=Ip(t,c=>Mt(e.dCl,c)*(1-r)-e.cl*Mt(e.dBalance,c)),i=Jw(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:Ip(t,c=>Mt(e.dCd,c))},range:{[t[0]]:[...Ic(e.range,t[0])],[t[1]]:[...Ic(e.range,t[1])]},provenance:{...e.provenance},...i?{attitude:i}:{}}}function _c(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 _p(e,t,r=11){let n=Array.from({length:r},(a,s)=>t.maxDeg*s/(r-1)),o=n.map(a=>_c(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 wy(e){if(!(!e.attitude?.yaw&&!e.attitude?.roll))return{...e.attitude.yaw?{yaw:_p(e.at,e.attitude.yaw)}:{},...e.attitude.roll?{roll:_p(e.at,e.attitude.roll)}:{}}}function Cy(e,t,r,n=0,o=0){let[a,s]=Np(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?_c(e.at,e.attitude.yaw,n):{clFront:1,clRear:1,cd:1},m=e.attitude?.roll?_c(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 Vp(e){let[t,r]=Np(e.frame),n=[...Ic(e.range,t)],o=[...Ic(e.range,r)],a=i=>o.map(c=>n.map(l=>i(Cy(e,l,c)))),s=wy(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 Bp=180/Math.PI,Ty=new WeakMap,Py=new WeakMap,$p=new WeakMap;function Yr(e,t){let r=Py.get(e);if(r)return r;let n=t?.wheelbase,o=n!==void 0?$p.get(e)?.get(n):void 0;if(o)return o;let a=eC(e),s=a.map;if(!Co(s)){let l=tC(e,a);return Py.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=rC(e,a,s.frame,n),c=$p.get(e);return c||(c=new Map,$p.set(e,c)),c.set(n,i),i}function eC(e){let t=Ty.get(e);if(t)return t;let r=ja(e);if(r)throw new Error(r);let n=e.kind==="map"?e:Vp(e),{x:o,y:a}=Pc(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,x)=>{let M=Math.abs(x),v=y.clFront.deg[y.clFront.deg.length-1];return{clFront:Be(y.clFront.deg,y.clFront.factor,M),clRear:Be(y.clRear.deg,y.clRear.factor,M),cd:Be(y.cd.deg,y.cd.factor,M),clamped:M>v}},p=(y,x)=>{if(!u)return m;let M=c?f(c,y):m,v=l?f(l,x):m;return{clFront:M.clFront*v.clFront,clRear:M.clRear*v.clRear,cd:M.cd*v.cd,clamped:M.clamped||v.clamped}},d=(y,x,M=0,v=0)=>{let R=Sn(o,y),k=Sn(a,x),F=Math.min(R.i+1,s-1),w=Math.min(k.i+1,i-1),C=S=>{let A=S[k.i][R.i],P=S[k.i][F],L=S[w][R.i],D=S[w][F],E=A+R.t*(P-A),$=L+R.t*(D-L);return E+k.t*($-E)},T=p(M,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:R.clamped||k.clamped,clampedAttitude:T.clamped}},h={x:[o[0],o[s-1]],y:[a[0],a[i-1]]},b=(y,x,M=!1,v=0,R=0)=>{let k=p(v,R),F=Sn(o,M?Math.min(Math.max(y,h.x[0]),h.x[1]):y),w=Sn(a,M?Math.min(Math.max(x,h.y[0]),h.y[1]):x),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 zr){let D=n[L],E=D[w.i][F.i],$=D[w.i][C],O=D[T][F.i],W=D[T][C],I=F.clamped||S===0?0:(($-E)*(1-w.t)+(W-O)*w.t)/S,_=w.clamped||A===0?0:((O-E)*(1-F.t)+(W-$)*F.t)/A;P[L]=u?{x:I*k[L],y:_*k[L]}:{x:I,y:_}}return P},g={map:n,x:h.x,y:h.y,hasAttitude:u,factors:p,at:d,slopes:b};return Ty.set(e,g),g}function tC(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 zr)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 rC(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)*Bp,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)*Bp,m,f,p),b=Bp/(n*(1+d*d)),g={};for(let y of zr)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)=>To(r,n,l,u),fromAxles:(l,u)=>{let m=Ec(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 Gp(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,Ly={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."},Dy={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."},Ey={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."},Iy={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."},_y={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."},Ny={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."},Oy={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."},Vy={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 Op({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 Kp=()=>br(Ly),Hp=()=>br(Dy),zp=()=>br(Ey),Yp=()=>br(Iy),Wp=()=>br(_y),jp=()=>br(Ny),Up=()=>br(Oy),Xp=()=>br(Vy);function Po(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 Nc(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 Oc(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 Qp(e,t){return e.wheelbase>0?e.massTotal*t*9.81/e.wheelbase:0}function Lo(e,t,r){let n=2*t.rideRateFront,o=2*t.rideRateRear;return!(n>0)||!(o>0)?0:Math.min(Ep(t.sprungMass,r,e.wheelbase),.5*n*o/(n+o))}function Vc(e,t,r,n,o){let a=e.cgHeight,s=Qp(e,r);if(n===0&&o===0&&s===0)return{height:a,forward:0,noseLoad:0,dropFront:0,dropRear:0};let i=Nc(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=Lo(e,t,u);let b=n-s*u,g=o+s*u;if(p>0){let M=c*l-p*(c+l);m=(b*(l-p)-p*g)/M,f=(g*(c-p)-p*b)/M}else m=c>0?b/c:0,f=l>0?g/l:0;let y=Oc(a,i,m,f),x=Math.abs(y-u);if(u=y,x<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 qp={yawDeg:0,rollDeg:0},By=1e-4,nC=40,$y=50;function Do(e,t,r=0){let n=e.aero?.model;if(!(!n||!Yr(n,e).hasAttitude))return{yawDeg:r,rollDeg:Ce(e).rollGradient*t}}function Zp(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 To(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=My(r)?n(r.frame,r.ref.h,r.ref.pitch):r.ref;else if(r){let{x:a,y:s}=Pc(r),i=(a[0]+a[a.length-1])/2,c=(s[0]+s[s.length-1])/2;o=Co(r)?n(r.frame,i,c):{hFront:i,hRear:c}}return{hFront:e.rideHeightFront??o.hFront,hRear:e.rideHeightRear??o.hRear}}var Gy=new WeakMap;function Wr(e,t,r=0,n){let o=e.aero;if(!o?.model)return null;let a=Gy.get(e);a||(a=new Map,Gy.set(e,a));let s=n&&Yr(o.model,e).hasAttitude?n:qp,i=s===qp?`${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=Yr(t.model,e),s=Ce(e),i=2*s.rideRateFront,c=2*s.rideRateRear,l=Zp(t,e.wheelbase),u=.5*t.rho*r*r,m=a.area,f=e.wheelbase>0?t.copHeight/e.wheelbase:0,p=Nc(e,s),d=Qp(e,n),h=(C,T)=>Oc(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),$=d*E,O=Lo(e,s,E)*b(C,T),W=A-$-D+O,I=P+$+D-O,_=C-l.hFront+(i>0?W/i:0),V=T-l.hRear+(c>0?I/c:0);return{c:S,downFront:A,downRear:P,drag:L,rF:_,rR:V,norm:Math.hypot(_,V)}},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)]]},x=l.hFront,M=l.hRear,v=g(x,M),R=0;for(;v.norm>=By&&R<nC;){R++;let C=y(x,M),T=i>0?d/i:0,S=c>0?d/c:0,A=Lo(e,s,h(x,M)),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,$=C[1][0]+S*p.front+L,O=1+C[1][1]+S*p.rear-L,W=D*O-E*$,I,_;Math.abs(W)>1e-9?(I=-(O*v.rF-E*v.rR)/W,_=-(-$*v.rF+D*v.rR)/W):(I=-.5*v.rF,_=-.5*v.rR);let V=Math.max(1,Math.abs(I)/$y,Math.abs(_)/$y);I/=V,_/=V;let N=1;for(let G=0;G<6;G++){let K=g(x+N*I,M+N*_);if(K.norm<=v.norm||G===5){x+=N*I,M+=N*_,v=K;break}N*=.5}}let k=y(x,M,!0),F=2+k[0][0]+k[1][1],w=(1+k[0][0])*(1+k[1][1])-k[0][1]*k[1][0];return{v:r,axG:n,hFront:x,hRear:M,cgHeight:h(x,M),cgForward:e.wheelbase>0?h(x,M)*b(x,M)/e.wheelbase:0,cgNoseLoad:Lo(e,s,h(x,M))*b(x,M),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:aC(k),stable:w>0&&F>0,converged:v.norm<By,iterations:R,clampedRide:v.c.clampedRide,yawDeg:o.yawDeg,rollDeg:o.rollDeg,clampedAttitude:v.c.clampedAttitude}}function aC(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 Ua(e,t,r=0,n){let o=Wr(e,t,r,n);return o?{downforce:o.downforce,drag:o.drag,downFront:o.downFront,downRear:o.downRear}:e.aero?Po(e.aero,t):{downforce:0,drag:0,downFront:0,downRear:0}}function Bc(e,t=0,r=0,n,o){if(e.aero&&t>0){if(e.aero.model){let i=Wr(e,t,r,n);return{height:i.cgHeight,forward:i.cgForward,noseLoad:i.cgNoseLoad}}let a=Po(e.aero,t),s=e.wheelbase>0?a.drag*e.aero.copHeight/e.wheelbase:0;return Vc(e,o??Ce(e),r,a.downFront-s,a.downRear+s)}return r===0?{height:e.cgHeight,forward:0,noseLoad:0}:Vc(e,o??Ce(e),r,0,0)}var Ky=[0,1,0],Jp=[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],ed=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]],sC=e=>X(e,e),jr=e=>Math.sqrt(X(e,e)),Xa=(e,t)=>sC(H(e,t)),ve=(e,t)=>jr(H(e,t)),Q=e=>{let t=jr(e);return t<1e-12?[0,0,0]:[e[0]/t,e[1]/t,e[2]/t]};var Ur=(e,t,r)=>{let n=Q(r),o=H(e,t);return ee(t,U(n,X(o,n)))},Hy=(e,t,r)=>ve(e,Ur(e,t,r));var cC=1e-6;function lC(e){if(e<cC){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 nt(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]=lC(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 nt(U(o,r),e)}function Qt(e,t){let r=t.length,n=e.map(a=>a.slice()),o=t.slice();return Yy(n,o,r,new Array(r).fill(0))}function zy(e,t,r){return Yy(e,t,t.length,r)}function Yy(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 Wy=e=>{let t=0;for(let r of e)t=Math.max(t,Math.abs(r));return t},jy=e=>{let t=0;for(let r of e)t+=r*r;return t},uC=Math.sqrt(Number.EPSILON);function Uy(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=Wy(c),u=jy(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),x=new Array(a).fill(0),M=new Array(a).fill(0),v=new Array(a).fill(0);for(let R=0;R<n;R++){if(l<o)return{x:i,residualNorm:l,iterations:R,converged:!0,condProxy:f};for(let C=0;C<a;C++){let T=uC*Math.max(Math.abs(i[C]),s[C]);for(let A=0;A<a;A++)M[A]=i[A];M[C]+=T;let S=e(M);for(let A=0;A<p;A++)d[A][C]=(S[A]-c[A])/T}let k=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,k=Math.max(k,h[C][C])}let F=Math.max(k,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=zy(b,y,x);if(f=Math.max(f,S.condProxy),!S.singular){for(let L=0;L<a;L++)v[L]=i[L]+x[L];let A=e(v),P=jy(A);if(P<u){for(let L=0;L<a;L++)i[L]=v[L];c=A,u=P,l=Wy(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 Qa(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 td(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 Xy=e=>[e[0],-e[1],-e[2],-e[3]];function Qy(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 qy(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 Zy(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 rd(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 Jy(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 ex(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 mC(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 pC(e){let t=e.hardpoints,r=Q(H(t.damperChassis,t.pushrodOuter)),[n,o]=mC(r);return{top:t.damperChassis,lower0:t.pushrodOuter,axis0:r,e1:n,e2:o}}function nd(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=Xa(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:pC(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(nt(n,a),e.c0),o)}function od(e,t){return ee(e.lcaFront,It(e.lbjRel0,e.lcaDir,t))}function Eo(e,t){return e.steerMovesRack?ee(e.tieInner0,U(e.rackAxis,t)):e.tieInner0}function ad(e,t,r,n){let o=_t(e,t,e.lbj0),a=od(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,nt(h,d.e1)),u=X(b,nt(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=Eo(e,n),p=(Xa(m,f)-e.tieLen2)/e.tieLenRef;return[s,i,c,l,u,p]}var qa=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]),$c=e=>{let t=qa(e);return[e[0]/t,e[1]/t,e[2]/t]},dC=(e,t)=>H(e,U(t,X(e,t))),sd=e=>$c(ae(e,Math.abs(e[0])<.6?[1,0,0]:[0,1,0]));function fC(e,t){let r=e.ucaDir,n=ee(e.ucaFront,U(r,e.ubjAxial0)),o=Math.sqrt(e.ubjRadius2),a=dC(H(e.ubj0,e.ucaFront),r),s=qa(a)>1e-9?$c(a):sd(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=Qa(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=$c(c),d=(h,b)=>{let g=ee(n,ee(U(s,o*h),U(i,o*b))),y=$c(H(g,t));return{q1:qy(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 hC(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=qa(a),i=s>1e-9?U(a,1/s):sd(n),c=H(t.top,r),l=qa(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=sd(u),h=b=>{let g=b*p,y=ee(U(u,g),U(d,Math.min(m,1))),x=H(U(u,Math.min(m,1)),U(d,g));return{q1:td(rd(x,y,ae(x,y)),Xy(rd(i,n,ae(i,n)))),k:u,margin:f,ok:f>=0}};return f>0?[h(1),h(-1)]:[h(1)]}function bC(e,t,r,n){let{k:o}=n,a=Qy(n.q1,H(e.tro0,e.lbj0)),s=X(a,o),i=H(a,U(o,s)),c=qa(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=Qa(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:td(Zy(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 tx(e,t,r,n=[0,0,0,0,0,0]){let o=od(e,t),a=Eo(e,r),s=Jy([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?hC(e,e.strut,o):fC(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=bC(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:x}of b.roots){let M=i(x);y&&(!l||M>l.near)&&(l={q:x,margin:g,near:M}),!y&&(!u||M>u.near)&&(u={q:x,margin:g,near:M})}}let{q:m,margin:f}=l??u,p=ex(m),d=H(H(o,e.c0),nt(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 nx(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:Xa(e.pushrodOuter,e.rockerToPushrod),damperLen0:ve(e.rockerToDamper,e.damperChassis)}}var gC=(e,t)=>ee(e.pivotA,It(e.rprRel0,e.axis,t)),id=(e,t)=>ee(e.pivotA,It(e.rdmRel0,e.axis,t));function Za(e,t){return{pushrod:gC(e,t),damper:id(e,t)}}function ox(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=Qa(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(id(e,r),e.damperChassis),converged:p,margin:0}}let u=rx(Math.atan2(l.s1,l.c1),r),m=rx(Math.atan2(l.s2,l.c2),r),f=Math.abs(m-r)<Math.abs(u-r)?m:u;return{phi:f,damperLength:ve(id(e,f),e.damperChassis),converged:l.ok,margin:l.margin}}function rx(e,t){let r=2*Math.PI;return e+r*Math.round((t-e)/r)}function ax(e,t,r,n){return ee(t,nt(U(Q(r),n),H(e,t)))}function sx(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 ix(e,t,r,n){return ee(t,nt(U(Q(r),n),H(e,t)))}var Gc=180/Math.PI,yC=(e,t,r)=>Math.max(t,Math.min(r,e)),cx=[NaN,NaN,NaN];function Ja(e){let t=Q(e.spinAxis),r=Q(H(e.uprightUpper,e.uprightLower)),n=-Math.asin(yC(t[2],-1,1))*Gc,o=Math.atan2(t[0],t[1])*Gc,a=Math.atan2(-r[0],r[2])*Gc,s=Math.atan2(-r[1],r[2])*Gc,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]):cx,d=m?f(e.wheelCenter[2]):cx,h=l[1]-p[1],b=p[0]-l[0],g=Q(ae(t,[0,0,1])),y=ae([0,0,1],g),x=H(l,p),M=X(x,y),v=-X(x,g),R=e.wheelCenter[1]-d[1],k=d[0]-e.wheelCenter[0],F=Hy(e.tieOuter,u,r);return{camber:n,toe:o,caster:a,kpi:s,scrubRadius:h,mechanicalTrail:b,scrubAtWheel:M,trailAtWheel:v,kingpinOffset:R,casterOffset:k,steeringArm:F,contactPatch:l,kingpinGround:p,kingpinAtHub:d}}function et(e){return{corner:e,inv:nd(e),rocker:nx(e.hardpoints)}}var xC=[20,20,20,.2,.2,.2];function ux(e,t,r,n=[0,0,0,0,0,0]){let o=tx(e,t,r,n);if(!o.free)return o;let a=RC(e,t,r,n);return{x:a.x,converged:a.converged,margin:0}}function RC(e,t,r,n=[0,0,0,0,0,0]){return Uy(o=>ad(e,o,t,r),n,{scales:xC,tol:1e-10,maxIter:40})}var vC=.01,Kc=1.2,ht=e=>e.ok?e.state:null,ot=e=>e.ok?e.state:e.nearest;function ge(e,t,r,n,o){let a=0,s=Ee(e,a,r,n,o);if(Math.abs(s.travel-t)<1e-4)return lx(s,t,!1);let c=(Ee(e,.02,r,cd(s),o).travel-s.travel)/.02;(!Number.isFinite(c)||Math.abs(c)<1e-6)&&(c=1);let l=f=>Math.max(-Kc,Math.min(Kc,f)),u=l((t-s.travel)/c),m=Ee(e,u,r,cd(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=Ee(e,u,r,cd(s),o)}return lx(m,t,Math.abs(u)===Kc)}function lx(e,t,r){let n=e.travel-t,o=Math.abs(n)<=vC,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 cd(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 kC(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=sx(t.ubj0,a,t.ucaFront,t.ucaDir);return ix(o.pushrodOuter,t.ucaFront,t.ucaDir,s)}default:return ax(o.pushrodOuter,t.lcaFront,t.lcaDir,n)}}function Ee(e,t,r,n,o){let{inv:a,corner:s}=e,i=n?.q??[0,0,0,0,0,0],c=ux(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),x=Q(nt(u,p.spinAxis)),M=kC(d?"upright":p.pushrodAttach,a,l,t,f),v=d?d.top:f.damperChassis,R=d||p.actuation==="direct"?{phi:0,damperLength:ve(M,v),converged:!0,margin:1}:ox(e.rocker,M,n?.phi??0),k=Ja({uprightUpper:h,uprightLower:b,wheelCenter:y,spinAxis:x,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:M,spinAxis:x,contactPatch:k.contactPatch,kingpinGround:k.kingpinGround,kingpinAtHub:k.kingpinAtHub,rockerAngle:R.phi,damperLength:R.damperLength},metrics:{camber:k.camber,toe:k.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:k.steeringArm,damperLength:R.damperLength},converged:c.converged&&R.converged,margin:Math.min(c.margin,R.margin)}}var Io=e=>e==="FL"||e==="FR"?"front":"rear",px=e=>e==="FL"||e==="RL"?"left":"right";function $e(e,t){return e.corners?.[t]??MC(e[Io(t)],px(t))}function dx(e){let t=e.config.springSplit;return e.config.actuation==="decoupled"||t===void 0||!Number.isFinite(t)||Math.abs(t)>=1?0:t}var mx=new WeakMap;function MC(e,t){let r=dx(e);if(r===0)return e;let n=mx.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)},mx.set(e,n)}return n[t]}var _o=["FL","FR","RL","RR"],bt=e=>2*e.hardpoints.wheelCenter[1],Xr=(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 No(e){return e.frontAxleX-e.wheelbase/2}function ld(e,t,r){return t[2]+e.heave+(t[0]-r)*Math.sin(e.pitch)-t[1]*Math.sin(e.roll)}function qr(e,t,r,n){let o=Ze(e,t),a=(n?Xr(n,o.isFront):o.isFront?t.trackFront:t.trackRear)/2,s=o.sideSign*a,i=o.axleX-No(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 SC={travelMin:-40,travelMax:40,steps:41,steer:0};function es(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={...SC,...t},n=et(e);return Oo(n,r)}function Oo(e,t){let r=t.steer,n=.01,o=Ee(e,n,r),a=Ee(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=Ee(e,0,r);u.push({beta:0,travel:m.travel,warm:es(m),converged:m.converged});let f=es(m);for(let x=1;x<=l;x++){let M=c*x/l,v=Ee(e,M,r,f);f=es(v),u.push({beta:M,travel:v.travel,warm:f,converged:v.converged})}f=es(m);for(let x=1;x<=l;x++){let M=-c*x/l,v=Ee(e,M,r,f);f=es(v),u.push({beta:M,travel:v.travel,warm:f,converged:v.converged})}u.sort((x,M)=>x.beta-M.beta);let p=u[u.length-1].travel>=u[0].travel,d=!1;for(let x=1;x<u.length;x++){let M=u[x].travel-u[x-1].travel;(p&&M<-1e-6||!p&&M>1e-6)&&(d=!0)}let h=u.filter(x=>x.converged).map(x=>x.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 x=0;x<t.steps;x++){let M=t.steps===1?t.travelMin:t.travelMin+(t.travelMax-t.travelMin)*x/(t.steps-1),v=AC(u,M,p),R=FC(u,v);y.push(Ee(e,v,r,R))}return wC(y,e.corner.config.actuation==="decoupled"?0:e.corner.config.springRate),{samples:y,covered:g,reach:b,fold:d,unconverged:y.filter(x=>!x.converged).length}}function AC(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 FC(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 ud(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 wC(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=ud(n,r,s),c=ud(o,r,s),l=-ud(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 Hc=e=>e!==void 0&&Number.isFinite(e)&&e>0;function CC(e){return e&&Hc(e.helperRate)&&Hc(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 ts(e,t,r,n){if(!(e>0)||!Number.isFinite(e)||!(t>0)||!Number.isFinite(t))return null;let o=CC(n),a=-md(e,t,o),s=Vo(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 Vo(e,t){if(!Number.isFinite(e))return{droop:null,bump:null};let r=Hc(t?.extended)&&t.extended>e?t.extended:null,n=r!==null&&Hc(t?.stroke)?r-t.stroke:null;return{droop:r!==null?e-r:null,bump:n!==null&&n<e?e-n:null}}function pd(e,t){if(!(e>0)||!Number.isFinite(e))return null;let r=Vo(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 TC(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 PC(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 Bo(e,t){let r=TC(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 dd(e,t){let r=PC(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},hd=e=>({travel:[e.min,e.max],force:[0,0],motionRatio:[0,0],spring:null}),fx=new WeakMap;function LC(e,t){let r=fx.get(e.corner);r||fx.set(e.corner,r=new Map);let n=`${t.min}|${t.max}|${t.steps}`,o=r.get(n);return o||r.set(n,o=Oo(e,{travelMin:t.min,travelMax:t.max,steps:t.steps,steer:0})),o}function rs(e,t,r=zc,n=e.corner.config.coilover){let o=e.corner.config;if(o.actuation==="decoupled")return hd(r);let a=LC(e,r),s=EC(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 hd(r);let c=_C(i,0);if(!(Math.abs(c.mr)>1e-6))return hd(r);let l=t/c.mr,u=ts(s,l,c.L,n),m=u?DC(i,fd(u).map(h=>c.L-h)):i,f=m.map(h=>(u?Bo(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 DC(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 EC(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:IC(e,n,r);return!(o>0)||!Number.isFinite(o)?t:t*o/(t+o)}function IC(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=Za(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 bd(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=bd(e,0),c=a-r;return(s?Bo(s,c):o+n*c)*bd(e,t)-o*i}function _C(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 $o(e,t){let r=e.travel.length;if(r<3)return ns(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 ns(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 Pe(e,t,r){let n=e.hardpoints;switch(t.attach){case"upright":{let o=H(t.outer,n.wheelCenter);return ee(ee(nt(r.pose.omega,o),n.wheelCenter),r.pose.t)}case"lowerArm":{let o=Q(H(n.lcaRear,n.lcaFront));return ee(n.lcaFront,nt(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 Zr(e,t,r){return e.config.actuation==="decoupled"&&t.attach==="rocker"&&r==="coil"}function gd(e,t,r){return Zr(e,t,r)?[t.inner[0],-t.inner[1],t.inner[2]]:t.inner}function Go(e,t,r){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return yd(e,t,r.kind,Ge(e,{travelMin:n,travelMax:o,steps:a}).samples)}function yd(e,t,r,n){let o=Q(H(t.outer,gd(e,t,r))),a=[],s=[],i=t.outer;for(let p of n)a.push(p.travel),s.push(X(H(Pe(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 xd(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 Rd(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 os=e=>e.mount??{kind:"rockerToRocker"},yx=e=>[e[0],0,e[2]],NC=e=>2*Math.abs(e[1]),OC=(e,t)=>Math.hypot(e[0]-t[0],e[2]-t[2]);function Wc(e,t){return t.kind==="chassis"?OC(e,t.anchor):NC(e)}function as(e,t,r){if(r.kind==="chassis"){let s=[(e[0]+t[0])/2,(e[1]-t[1])/2,(e[2]+t[2])/2];return Math.hypot(s[0]-r.anchor[0],s[1],s[2]-r.anchor[2])}let n=e[0]-t[0],o=e[1]+t[1],a=e[2]-t[2];return Math.hypot(n,o,a)}function An(e,t,r={}){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return vd(e,t,Ge(e,{travelMin:n,travelMax:o,steps:a}).samples)}function vd(e,t,r){let n=os(t),o=d=>Pe(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(Wc(o(d),n));let c=bx(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=hx(a,20),f=hx(a,-20),p=as(o(m),o(f),n);return{travel:a,ratio:u,springTravel:s,atDesign:bx(a,u,0),installedLength:c,rollSensitivity:c-p}}function hx(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 bx(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 kd(e,t,r){let n={outer:t.outer,attach:t.attach},o=Ge(e,{travelMin:-5,travelMax:5,steps:3}),a=d=>yx(Pe(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 Md(e,t){let r=e.hardpoints,n=r.rockerPivotA,o=gx(Yc(r.rockerPivotB,r.rockerPivotA)),a=Math.max(30,.6*xx(Yc(r.rockerToDamper,n))),s=Yc(r.rockerToDamper,n),i=gx(Yc(s,VC(o,BC(s,o)))),c=$C(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:kd(e,d)}}:d,b;try{b=An(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 Yc=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],VC=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],BC=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],xx=e=>Math.hypot(e[0],e[1],e[2]),gx=e=>{let t=xx(e)||1;return[e[0]/t,e[1]/t,e[2]/t]},$C=(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 Sd=.001,GC=e=>({outer:e.outer,inner:e.outer,attach:e.attach}),wx=(e,t,r)=>(Wc(e.at0,t)-Wc(r,t))/2,KC=(e,t)=>X(H(t,e.pickup.at0),e.axis);function Ad(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 Rx(e,t){let r=[0,1,2].map(n=>Ad(e,t.map(o=>o[n])));return t.map((n,o)=>[r[0][o],r[1][o],r[2][o]])}function Fd(e){return{travel:e,heave:e.map(t=>t/2),heaveRatio:e.map(()=>.5),roll:[...e],rollRatio:e.map(()=>1)}}function vx(e,t,r,n){let o=e.corner;if(!t.heave&&!t.roll)return{side:Fd([n.min,n.max]),pickups:{}};let a=ot(ge(e,0,0)),s={};if(t.heave&&r){let h=GC(t.heave);s.heave={corner:o,link:h,at0:Pe(o,h,a)}}if(t.roll){let h=t.roll;s.roll={pickup:{corner:o,link:h,at0:Pe(o,h,a)},axis:Q(H(h.outer,gd(o,h,t.rollKind??"coil")))}}let i=t.roll&&Zr(o,t.roll,t.rollKind??"coil")?{near:t.roll,far:{...t.roll,outer:t.roll.inner}}:null,c=Oo(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?wx(s.heave,r,Pe(o,s.heave.link,h)):h.travel/2),m.push(s.roll?KC(s.roll,Pe(o,s.roll.pickup.link,h)):h.travel),i&&(f.push(Pe(o,i.near,h)),p.push(Pe(o,i.far,h))));if(l.length<2)return{side:Fd([n.min,n.max]),pickups:{}};let d={travel:l,heave:u,heaveRatio:Ad(l,u),roll:m,rollRatio:Ad(l,m)};return i&&(d.eyes={near:f,nearRatio:Rx(l,f),far:p,farRatio:Rx(l,p)}),{side:d,pickups:s}}function jc(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 kx(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:jc(e.travel,e.heave,t),dh:jc(e.travel,e.heaveRatio,t),ddh:kx(e.travel,e.heaveRatio,t),r:jc(e.travel,e.roll,t),dr:jc(e.travel,e.rollRatio,t),ddr:kx(e.travel,e.rollRatio,t)}}function Mx(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 wd=(e,t)=>Math.hypot(e[0]-t[0],e[1]+t[1],e[2]-t[2]);function Cx(e,t){let r=e.side[0].eyes,n=e.side[1].eyes;if(!r||!n)return null;let o=Mx(e.side[0].travel,r.near,r.nearRatio,t[0]),a=Mx(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 Tx=(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,HC=(e,t)=>e.bump!==null&&t>e.bump||e.droop!==null&&t<e.droop?e.rate:0;function ss(e,t,r,n,o=0){let a=e.rollStop;if(!a)return r;let s=Cx(e,t);if(!s)return r;let i=Tx(a,a.length0-(n??s.L+o));return i===0?r:[r[0]-i*s.dL[0],r[1]-i*s.dL[1]]}function Uc(e,t){let r=Fd(e.travel);return t==="heave"?{...e,heave:r.heave,heaveRatio:r.heaveRatio}:{...e,roll:r.roll,rollRatio:r.rollRatio}}var Xc=(e,t)=>e?e.law?Bo(e.law,t):e.preload+e.rate*t:0,Sx=(e,t)=>e?e.law?dd(e.law,t):e.rate:0;function is(e,t,r,n,o){let a=Xc(e.heave,n),s=Xc(e.roll,o);return[a*t.dh+s*t.dr,a*r.dh-s*r.dr]}var Ax=(e,t)=>ze(e[0],t).h+ze(e[1],t).h;function zC(e,t){let r=e.gap>0?Ax(t,e.gap):0;return e.bothWays?{free:r,pull:e.gap>0?Ax(t,-e.gap):0}:{free:r,pull:null}}function YC(e,t,r){let n={...t,outer:t.inner},o=(u,m)=>{let f=ht(ge(e[0],u,0)),p=ht(ge(e[1],m,0));if(!f||!p)return NaN;let d=Pe(e[0].corner,t,f),h=Pe(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)>Sd?{length0:s,scale:l}:null}function Px(e,t,r,n=zc){let o=r.heave?os(r.heave):void 0,a=vx(e[0],r,o,n),s=e[1].corner===e[0].corner?a:vx(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)>Sd)&&(i=[Uc(i[0],"heave"),Uc(i[1],"heave")],c=!1),l&&!(Math.abs(p[0].dr+p[1].dr)>Sd)&&(i=[Uc(i[0],"roll"),Uc(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,x=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,x=(p[0].dh*A[1]-p[1].dh*A[0])/P)}else b>0?y=(A[0]+A[1])/d:g>0&&(x=(A[0]-A[1])/h)}let M={};if(c&&o){let A=[a.pickups.heave,s.pickups.heave];M.heave={pickups:A,mount:o,span0:as(A[0].at0,A[1].at0,o)}}let v=M.heave?M.heave.span0:NaN,R=M.heave?r.coilover:void 0,k=r.carriesLoad?ts(b,y,v,R):u?pd(b,{...zC(u,i),length0:v,coilover:R}):null,F=b>0?{rate:b,preload:y,...k?{law:k}:{}}:null;if(l&&(M.roll={pickups:[a.pickups.roll.pickup,s.pickups.roll.pickup],axes:[a.pickups.roll.axis,s.pickups.roll.axis]},r.roll&&Zr(e[0].corner,r.roll,r.rollKind??"coil"))){let A=YC(e,r.roll,i);A&&(M.roll.unit=A)}let w=g>0?{rate:g,preload:x}:null,C={side:i,heave:F,roll:w,force0:[0,0],carriesLoad:r.carriesLoad,read:M},T=M.roll?.unit,S=T&&g>0&&i[0].eyes&&i[1].eyes?Vo(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=ss(C,[0,0],is(C,p[0],p[1],p[0].h+p[1].h,p[0].r-p[1].r)),C}function cs(e,t,r){let n=ze(e.side[0],t[0]),o=ze(e.side[1],t[1]),a=r?ss(e,t,is(e,n,o,n.h+o.h+r.heave,n.r-o.r+r.roll),void 0,r.unit):ss(e,t,is(e,n,o,n.h+o.h,n.r-o.r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function Cd(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=Sx(e.heave,a),c=Sx(e.roll,s),l=Xc(e.heave,a),u=Xc(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?Cx(e,t):null;if(!p||!d)return f;let h=p.length0-(r?d.L+r.unit:d.L),b=HC(p,h);if(b===0)return f;let g=Tx(p,h),y=(M,v)=>b*d.dL[M]*d.dL[v]-g*d.ddL[M][v],x=m+y(0,1);return[[f[0][0]+y(0,0),x],[x,f[1][1]+y(1,1)]]}function Td(e,t,r){let n=Cd(e,t);return n[r][0]+n[r][1]}function WC(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-as(Pe(o.corner,o.link,r[0]),Pe(a.corner,a.link,r[1]),n.mount)}function jC(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(Pe(n.pickups[a].corner,n.pickups[a].link,r[a]),n.pickups[a].at0),n.axes[a]);return o(0)-o(1)}function UC(e,t){let r=e.read.roll;if(!e.rollStop||!r)return;let[n,o]=r.pickups;return wd(Pe(n.corner,n.link,t[0]),Pe(o.corner,{...o.link,outer:o.link.inner},t[1]))}function ls(e,t,r){let n=ze(e.side[0],t[0]),o=ze(e.side[1],t[1]),a=ss(e,t,is(e,n,o,WC(e,t,r),jC(e,t,r)),UC(e,r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function Pd(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*wx(i,s.mount,Pe(i.corner,i.link,n)):o.h+a.h,l=e.rollStop&&n?e.read.roll?.pickups[t]:void 0,u=l&&n?wd(Pe(l.corner,l.link,n),Pe(l.corner,{...l.link,outer:l.link.inner},n)):void 0;return ss(e,[r,r],is(e,o,a,c,n?0:o.r-a.r),u)[t]-e.force0[t]}function Ld(e,t,r,n){let o=$o(e,r[n]);return t?.carriesLoad?o+Td(t,r,n):o}var Dd=e=>e==="FR"||e==="RR"?1:0,Qc=(e,t)=>e.elements?.[t==="FL"||t==="FR"?"front":"rear"]??null;var Lx=e=>Number.isFinite(e)&&e>0?1/e:0;var Dx=(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},XC=(e,t)=>[e[0][0]*t[0]+e[0][1]*t[1],e[1][0]*t[0]+e[1][1]*t[1]],Ex=1e-8,QC=40;function qC(e,t,r,n){return{force:(s,i)=>{if(r){let u=cs(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=ns)=>{if(r){let c=Cd(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 Ko(e,t,r,n,o,a=[0,0],s=[0,0],i=null,c){let l=[Lx(r[0].tyreRate),Lx(r[1].tyreRate)],u=[r[0].staticLoad,r[1].staticLoad],m=qC(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],$=[P[0]+t[0]*L+E[0]*l[0]-e[0]*L,P[1]+t[1]*L+E[1]*l[1]-e[1]*L],O=[d[0]*(u[0]+E[0]),d[1]*(u[1]+E[1])],W=[O[0]<$[0],O[1]<$[1]];return{f:E,on:$,off:O,lifted:W,r:[Math.min($[0],O[0]),Math.min($[1],O[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),$=!1,O=0;for(;O<QC;O++){if(g(E.r)<Ex){$=!0;break}let W=Dx(b(m.stiffness(D),E.lifted),[-E.r[0],-E.r[1]]);if(!W)break;let I=1,_=[D[0]+W[0],D[1]+W[1]],V=h(_,L);for(let N=0;N<8&&g(V.r)>g(E.r);N++)I/=2,_=[D[0]+I*W[0],D[1]+I*W[1]],V=h(_,L);D=_,E=V}return!$&&g(E.r)<Ex&&($=!0),{t:D,b:E,converged:$,it:O}},x=y(o?[o[0],o[1]]:[e[0]-t[0],e[1]-t[1]],1),M=x.it;if(!x.converged){let P=0,L=[0,0],D=.25;for(;P<1&&D>=1/256;){let E=Math.min(1,P+D),$=y(L,E);M+=$.it,$.converged?(P=E,L=$.t,E===1&&(x=$)):D/=2}}let{t:v,b:R,converged:k}=x,F=R.lifted,w=[F[0]?-u[0]:R.f[0],F[1]?-u[1]:R.f[1]],C=[F[0]?Math.max(0,R.on[0]):0,F[1]?Math.max(0,R.on[1]):0],T=m.stiffness(v,$o),S=b(T,F);return{t:v,dF:w,lifted:F,clearance:C,converged:k,iterations:M,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]],$=Dx(S,E);if(!$)return[NaN,NaN];let O=XC(T,$);return[F[0]?0:O[0]+D[0],F[1]?0:O[1]+D[1]]}}}var Fn=e=>!(Number.isFinite(e.tyreRate)&&e.tyreRate>0);function qt(e,t,r){return t?.input.corners[r].staticLoadedRadius??e}var Ed=["FL","FR","RL","RR"],Nx={front:["FL","FR"],rear:["RL","RR"]},ZC=512,JC=5e-4,eT=8;function qc(e,t){let r={},n={},o=new Map;for(let s of Ed){let i=e.ctx[s],c=t.corners[s],l=c.staticLoadedRadius;n[s]=ot(ge(i,0,0,void 0,l===void 0?void 0:{loadedRadius:l})).points.contactPatch[2];let u=t.cornerCoilover?.[s==="FL"||s==="FR"?"front":"rear"],m=`${Ed.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?rs(i,c.springLoad,void 0,u):rs(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=Nx[s];a[s]=Px([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 Ox(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 tT=e=>`${e.heave}|${e.pitch}|${e.roll}|${e.steer}`;function Id(e,t,r){return{travel:r.travel,steer:r.steer,ground:r.travel,tyreDeflection:0,load:NaN,loadedRadius:qt($e(e.vehicle,t).config.loadedRadius,e.kc,t),lifted:!1,contactLength:0,converged:!0,rigid:!0,rideRate:NaN,wheelRateAtLoad:NaN}}var rT=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 Ix(e,t,r,n){let o=Nx[n],a=e.vehicle.config,s=o.map(w=>qr(w,a,r,e.vehicle)),i=[t.input.corners[o[0]],t.input.corners[o[1]]],c=t.loadCase;if(!c&&i.every(Fn))return{corners:[Id(e,o[0],s[0]),Id(e,o[1],s[1])],respond:null};let l=o.map(w=>t.curve[w]),u=t.elements?.[n]??null,m=o.map(w=>qt($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=Ko(f,h,i,l,void 0,void 0,p,u),x=[void 0,void 0],M=[!0,!0],v=[0,0],R=!1;for(let w=0;w<eT;w++){w>0&&(y=Ko(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=ge(e.ctx[o[A]],y.t[A],s[A].steer,rT(x[A]),{loadedRadius:m[A]-v[A],patchShift:d[A]}),L=ot(P);x[A]=L,M[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=ls(u,y.t,[x[0],x[1]]),P=cs(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<JC){R=!0;break}}let k=y.respond([1,1],[0,0]);return{corners:[0,1].map(w=>{let C=x[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:Ox(m[w]-v[w],i[w].staticLoad+y.dF[w],i[w].tyreRate),converged:y.converged&&R&&M[w],rigid:!1,state:C,solved:M[w],rideRate:k[w],wheelRateAtLoad:Ld(l[w],u,y.t,w)}}),respond:y.respond}}function Vx(e,t){let r=e.kc,n=tT(t),o=r.memo.get(n);if(o)return o;let a=Ix(e,r,t,"front"),s=Ix(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>=ZC&&r.memo.clear(),r.memo.set(n,i),i}function gt(e,t){if(!e.kc){let r={};for(let n of Ed)r[n]=Id(e,n,qr(n,e.vehicle.config,t,e.vehicle));return r}return Vx(e,t).corners}function Zc(e,t,r){return e.kc?Vx(e,t).respond[r]:null}function us(e,t,r,n=0){let o=e.kc;if(!o)return r;let a=o.input.corners[t];if(Fn(a))return r;let s=qr(t,e.vehicle.config,{heave:0,pitch:0,roll:0,steer:n},e.vehicle).steer,i=qt($e(e.vehicle,t).config.loadedRadius,o,t),c=o.loadCase,l=c?.linkLoad[t]??0,u=c?.patchShift[t],m=ot(ge(e.ctx[t],r,s,void 0,{loadedRadius:i,patchShift:u})),f=Qc(o,t),p=gr(o.curve[t],r,m.points.damperLength)+(f?Pd(f,Dd(t),r,m):a.heaveRate*r),h=Math.max(p+l,-a.staticLoad)/a.tyreRate;return(h===0?m:ot(ge(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 aT(e,t){let r=Qr(e,t),n=U(ae(oT,r),-t.sideSign);return-Math.atan2(n[1],n[0])*nT}var Bx=e=>1/Math.tan(e*Math.PI/180),$x=.05,Gx=.001;function Kx(e,t,r){if(!Number.isFinite(e)||!Number.isFinite(t))return NaN;if(!(Math.abs(e)<Gx&&Math.abs(t)<Gx))return e>0&&t>0?100*(Bx(t)-Bx(e))/r:NaN}function sT(e,t){let r=Xr(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=[$x,-$x].map(l=>{let{inner:u,outer:m}=a(t("FL",l).deg-n,t("FR",l).deg-o);return Kx(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=Kx(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 _d(e,t){let r=e.vehicle.config,n={FL:Ze("FL",r),FR:Ze("FR",r)},o=t.travel??0,a=sT(e,(i,c)=>{let l=ht(ge(e.ctx[i],o,n[i].sideSign*c));return{deg:l?aT(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 Hx=35,zx=55,Ot=e=>e.rackTravel&&e.rackTravel>0?e.rackTravel:Hx,Nd=e=>e.rackRatio&&e.rackRatio>0?e.rackRatio:zx;var Od=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 Yx(e,t,r,n,o){let a=ge(e,n,0,void 0,o),s=ot(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=Od(s);for(let b=1;b<=r;b++){let g=p*(t*b)/r,y=Ee(e,s.beta,g,h,o),x=ht(ge(e,n,g,Od(y),o));if(!x||!y.converged){i++,d.push({...d[d.length-1]});continue}d.push({steer:x.metrics.toe,camber:x.metrics.camber,lift:-(y.points.contactPatch[2]-c),contactPatch:y.points.contactPatch,spinAxis:y.points.spinAxis,yaw:-y.metrics.toe*Math.PI/180}),h=Od(y)}return d},m=u(1),f=u(-1);return{travelMm:n,unsolved:i,centre:l,positive:m,negative:f}}function iT(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 Wx(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:iT(o,t)});return{travelMm:e.travelMm,inner:n(r?e.positive:e.negative),outer:n(r?e.negative:e.positive)}}function cT(e){return e.positive[1].steer-e.centre.steer<0}function lT(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:Nd(e.config),innerJacobian:r.inner.jacobian,outerJacobian:r.outer.jacobian}}function Vd(e,t,r=13,n=-40,o=40,a=5,s){let i=et(e),c=Array.from({length:r+1},(b,g)=>t*g/r),l=Yx(i,t,r,0,s),u=cT(l),m=Wx(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=Yx(i,t,r,b,s);return d+=g.unsolved,Wx(g,c,u)});return{...lT(e,c,m),...jx(l.unsolved),travelSurface:{rackMm:c,rows:h,...jx(d)}}}var jx=e=>e>0?{unsolved:e}:{};function Zt(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 Jc(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 Ux(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 wn=(e,t,r)=>e+r*(t-e);function Ho(e,t,r,n,o){let a=Zt(e.rackMm,e.rows[n.lo][t][r],o);if(n.lo===n.hi)return a;let s=Zt(e.rackMm,e.rows[n.hi][t][r],o);return wn(a,s,n.t)}function Xx(e,t,r,n){let o=Jc(e.rackMm,e.rows[r.lo][t].jacobian,n);if(r.lo===r.hi)return o;let a=Jc(e.rackMm,e.rows[r.hi][t].jacobian,n);return{longitudinal:wn(o.longitudinal,a.longitudinal,r.t),lateral:wn(o.lateral,a.lateral,r.t),vertical:wn(o.vertical,a.vertical,r.t),yaw:wn(o.yaw,a.yaw,r.t)}}function zo(e,t,r,n){let o=e.travelSurface;if(!o||o.rackMm.length<2||o.rows.length===0)return Yo(e,t);let a=Ux(o,r),s=Ux(o,n),i=(p,d,h)=>{let b=o.rows[d.lo][p].steerDeg[h];return d.lo===d.hi?b:wn(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=wn(o.rackMm[d],o.rackMm[p],b)}return{innerDeg:Ho(o,"inner","steerDeg",a,m),outerDeg:Ho(o,"outer","steerDeg",s,m),innerCamber:Ho(o,"inner","camberDeg",a,m),outerCamber:Ho(o,"outer","camberDeg",s,m),innerLift:Ho(o,"inner","liftMm",a,m),outerLift:Ho(o,"outer","liftMm",s,m),innerJacobian:Xx(o,"inner",a,m),outerJacobian:Xx(o,"outer",s,m),atLock:f}}function Yo(e,t){let r=e.meanDeg.length-1;return{innerDeg:Zt(e.meanDeg,e.innerDeg,t),outerDeg:Zt(e.meanDeg,e.outerDeg,t),innerCamber:Zt(e.meanDeg,e.innerCamber,t),outerCamber:Zt(e.meanDeg,e.outerCamber,t),innerLift:e.innerLift?Zt(e.meanDeg,e.innerLift,t):0,outerLift:e.outerLift?Zt(e.meanDeg,e.outerLift,t):0,...e.innerJacobian&&e.outerJacobian?{innerJacobian:Jc(e.meanDeg,e.innerJacobian,t),outerJacobian:Jc(e.meanDeg,e.outerJacobian,t)}:{},atLock:r>=0&&t>e.meanDeg[r]}}var uT=()=>({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 Wo(e,t,r=Ce(e),n){let o=e.steerFront;if(!o?.innerLift||!o.outerLift||o.meanDeg.length<2||Math.abs(t)<1e-12)return uT();let a=Math.abs(t),s=t>0,i=n&&o.travelSurface?zo(o,a,s?n.FL:n.FR,s?n.FR:n.FL):null,c=i?.innerLift??Zt(o.meanDeg,o.innerLift,a),l=i?.outerLift??Zt(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,x={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:x,load:{FL:p*x.FL,FR:p*x.FR,RL:d*x.RL,RR:d*x.RR},rollDeg:y===0?0:-Math.atan(y)*180/Math.PI}}function Bd(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 ms=9.81;function jo(e,t,r=0,n=0,o=0){if(!e.aero||t<=0)return{FL:0,FR:0,RL:0,RR:0};let a=e.aero.model?Wr(e,t,r,Do(e,n,o)):Po(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 $d(e,t,r=0,n=0,o=0){if(!e.aero?.model||t<=0)return!1;let a=Wr(e,t,r,Do(e,n,o));return a!=null&&(a.clampedRide||a.clampedAttitude)}function Cn(e){let t=e.loadFactor===void 0?e.massTotal*ms:e.massTotal*ms*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 Qx(e,t=Ce(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*Tc(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 Gd(e){let{cf:t,cr:r}=Qx(e);return t+r>0?t/(t+r):.5}function qx(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 Le(e,t,r,n=0,o=0,a=0,s,i){return el(e,t,r,n,o,a,s,i).loads}function el(e,t,r,n=0,o=0,a=0,s,i){let c=Cn(e),l=Ce(e),u=Bc(e,n,r,Do(e,t,o),l),{cf:m,cr:f}=Qx(e,l,u.height),p=m*t*ms,d=f*t*ms,h=e.massTotal*(r*ms)*u.height/e.wheelbase-u.noseLoad,b=jo(e,n,r,t,o),g=(i??Wo(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 qx(y,e.trackFront,e.trackRear)}var Kd=Math.PI/180;function rl(e,t){let r=8*Kd,n=0,o=0;for(let a=1;a<=90;a++){let s=a*.5,i=Math.abs(e.Fy(s*Kd,t,0));if(i>n&&(n=i,r=s*Kd,o=a),a>o+12&&i<.995*n)break}return{aPeak:r,fyPeak:n}}function Zx(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 ds=.999;function St(e,t,r,n,o){if(t<=0)return 0;let{aPeak:a,fyPeak:s}=o??rl(e,t),i=Math.min(Math.abs(r),ds*s),c=n?-1:1,l=(v,R)=>Math.abs(e.forces({Fz:t,kappa:c*v,alpha:R}).Fy),u=.3,m=u,f=l(u,a);if(f<i){let v=0,R=u,k=NaN,F=f;for(let w=0;w<9;w++){let C=.5*(v+R),T=l(C,a);T>=i?(v=C,k=T):(R=C,F=T)}Number.isNaN(k)&&(k=l(0,a)),m=k<i?0:Zx(v,k,R,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 R=0,k=a,F=NaN,w=NaN;for(let C=0;C<5;C++){let T=.5*(R+k),S=l(v,T);S<i?(R=T,F=S):(k=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:Zx(R,F,k,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,x]=g===d?[d-1,d-2]:b[g-1]>=b[g+1]?[g-1,g+1]:[g+1,g-1],M=fT(p,h(g-1),h(Math.min(d,g+1)),h(g),b[g],h(y),b[y],h(x),b[x],mT);return c*Math.max(0,M)}var mT=.01,pT=20,dT=(3-Math.sqrt(5))/2;function fT(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<pT;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),x=(n-i)*(o-s),M=(n-i)*x-(n-a)*y;x=2*(x-y),x>0&&(M=-M),x=Math.abs(x);let v=u;if(u=m,Math.abs(M)<Math.abs(.5*x*v)&&M>x*(t-n)&&M<x*(r-n)){m=M/x;let R=n+m;(R-t<2*p||r-R<2*p)&&(m=d>=n?p:-p),h=!1}}h&&(u=n>=d?t-n:r-n,m=dT*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 Yd(e,t){return e.model?.kind==="simple"?null:tR(e,t)}var Jx=new WeakMap,Hd=100,eR=1.35,zd=18,Jt=41,tl=41,ps=65;function tR(e,t){let r=Jx.get(e);if(r)return r;let n=Math.log(eR),o=(p,d)=>{let h=k=>Math.abs(St(e,p,k,d)),b=h(0),g=t.muY(p)*p,y=new Float64Array(Jt),x=b>0&&g>0?Math.max(1,t.muX(p)*p/b):1;if(!(b>0)||!(g>0))y.fill(1);else{let k=[],F=[];for(let C=0;C<tl;C++){let T=Math.sin(.5*Math.PI*C/(tl-1));k.push(T),F.push(C===0?1:C===tl-1?0:Math.min(F[C-1],h(T*g)/b))}let w=tl-1;for(let C=0;C<Jt;C++){let T=C/(Jt-1);for(;w>0&&F[w-1]<T;)w--;let S=w>0?F[w-1]-F[w]:0;y[C]=w===0?k[0]:k[w]+(S>0?(T-F[w])/S:0)*(k[w-1]-k[w])}y[0]=1,y[Jt-1]=0}let M=new Float64Array(ps),v=k=>Math.atan2(y[k],k/(Jt-1)/x),R=Jt-2;for(let k=0;k<ps;k++){let F=.5*Math.PI*k/(ps-1),w=Math.cos(F),C=Math.sin(F);for(;R>0&&v(R)<F;)R--;let T=R/(Jt-1)/x,S=y[R],A=(R+1)/(Jt-1)/x,P=y[R+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);M[k]=D>0?D:Math.hypot(T,S)}return{room:y,scale:x,edge:M}},a=Array.from({length:zd},(p,d)=>Hd*eR**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)*(Jt-1),b=Math.min(Jt-2,Math.floor(h));return p.room[b]+(h-b)*(p.room[b+1]-p.room[b])},l=p=>{let d=p>Hd?Math.log(p/Hd)/n:0;if(d>=zd-1)return[zd-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),x=Math.atan2(Math.abs(h),Math.abs(d))/(.5*Math.PI)*(ps-1),M=Math.min(ps-2,Math.floor(x)),v=k=>k.edge[M]+(x-M)*(k.edge[M+1]-k.edge[M]),R=v(b[g]);return y>0?R+y*(v(b[g+1])-R):R},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 Jx.set(e,f),f}var hT=[["front","FL","FR"],["rear","RL","RR"]];function Uo(e,t,r,n){let o={...e},a=0,s=ds;for(let[i,c,l]of hT){let u=(M,v)=>n(i,Math.max(0,v[M])).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,x=f*g;y<=s?x<=s||(x=s,y=d>0?(p-s*h)/d:1/0):(y=s,x=h>0?(p-s*d)/h:1/0),(!(y<=s)||!(x<=s))&&(a+=Math.max(0,p-s*(d+h)),y=Math.min(s,y),x=Math.min(s,x)),o[c]=y,o[l]=x}return{util:o,short:a}}var rR=.001,bT=1e-5,nR=100;function gT(e,t,r,n){if(!(n>rR))return r;let o=t,a=Math.abs(r-t)<nR?t+Math.sign(r-t)*nR:r;for(let s=0;s<60&&Math.abs(a-o)>bT;s++){let i=.5*(o+a);e(i)>rR?a=i:o=i}return o}function nl(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=gT(e,t,o,e(o));return a!==o&&(n=a),a},edge:()=>n}}function ol(e,t){let r=n=>{try{return ge(e,0,n).ok}catch{return!1}};for(let n of[1,-1]){if(r(n*t))continue;let o=0;for(let a=1;a<=6;a++){let s=n*t*a/6;if(!r(s))break;o=Math.abs(s)}return{lock:t,reached:o,side:n}}return null}var Wd=40;function al(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 oR=[0,0,0];function yT(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 sl(e,t,r){if(e.mcpherson)return xT(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??oR,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]:yT(e,u[5]),condProxy:l.condProxy,singular:l.singular}}function xT(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??oR,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 jd(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 RT=[0,0,0];function fs(e,t,r,n){let o=e.direct?e.damperChassis:e.rockerToPushrod;if(e.mcpherson)return{...sl(e,r,n),armResidual:0};if(t==="upright")return{...sl(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 q=0;q<6;q++){let ne=f[q].dir,te=ae(H(f[q].at,c),ne);p[0][q]=ne[0],p[1][q]=ne[1],p[2][q]=ne[2],p[3][q]=te[0],p[4][q]=te[1],p[5][q]=te[2]}let d=ae(H(e.contactPatch,c),r),h=n??RT,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,x=g.x,M=x[0],v=x[1],R=x[2],k=[x[3],x[4],x[5]],F=Q(H(i.rear,i.front)),w=Q(H(o,e.pushrodOuter)),C=U(k,-1),T=(q,ne)=>X(F,ae(H(q,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)),$=X(D,D),O=X(D,E),W=X(E,E),I=X(D,L),_=X(E,L),V=$*W-O*O,N=NaN,G=NaN,K=NaN;if(Math.abs(V)>1e-12){N=(I*W-_*O)/V,G=($*_-O*I)/V;let q=ee(U(D,N),U(E,G)),ne=H(L,q);K=Math.hypot(ne[0],ne[1],ne[2])}let z=a?{f:M,r:v}:{f:N,r:G},j=a?{f:N,r:G}:{f:M,r:v};return{ucaFront:z.f,ucaRear:z.r,lcaFront:j.f,lcaRear:j.r,tieRod:R,pushRod:A,damper:y||!Number.isFinite(A)||e.decoupled?NaN:e.direct?A:vT(e,A),condProxy:g.condProxy,singular:y,armResidual:K}}function vT(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 SG=Math.PI/180;function hs(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 sR=["QSX3","QSX8","QSX13","QSX14"],kT=["QSX1"],il=["PHY1","PHY2","PHY3","PKY6","PKY7","PVY1","PVY2","PVY3","PVY4","PEY3","PEY4","QHZ1","QHZ2","QHZ3","QHZ4","QEZ4","QEZ5","QDZ6","QDZ7","QDZ8","QDZ9","QDZ10","QDZ11","SSZ1","SSZ3","SSZ4","RBY3","RHX1","RVY1","RVY2","RVY3",...sR];function MT(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 ST(e){let t=new Set(MT(e)),r=il.filter(n=>!sR.includes(n));return[...r.filter(n=>!t.has(n)),...[...t].filter(n=>!r.includes(n)),...kT]}function AT(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 iR(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 aR=.1;function cR(e){if(e.fitData)return"sae";let t=iR(e.coeffs,e.version);return t>aR?"sae":t<-aR?"iso":null}function bs(e){return e.axisSystem??cR(e)??"sae"}function cl(e){let t=new Set,r=n=>{for(let o of n)t.has(o)?t.delete(o):t.add(o)};return bs(e)==="iso"&&r(il),e.axisSystem&&e.side==="left"&&r(ST(e.version)),t.size?AT(e.coeffs,t):e.coeffs}var FG=Math.PI/180;var B=(e,t)=>Number.isFinite(e)?e:t;function uR(e){let t=cl(e);return{PCX1:B(t.PCX1,1.65),PDX1:B(t.PDX1,1),PDX2:B(t.PDX2,0),PDX3:B(t.PDX3,0),PEX1:B(t.PEX1,0),PEX2:B(t.PEX2,0),PEX3:B(t.PEX3,0),PEX4:B(t.PEX4,0),PHX1:B(t.PHX1,0),PHX2:B(t.PHX2,0),PKX1:B(t.PKX1,20),PKX2:B(t.PKX2,0),PKX3:B(t.PKX3,0),PPX1:B(t.PPX1,0),PPX2:B(t.PPX2,0),PPX3:B(t.PPX3,0),PPX4:B(t.PPX4,0),PVX1:B(t.PVX1,0),PVX2:B(t.PVX2,0),PCY1:B(t.PCY1,1.3),PDY1:B(t.PDY1,1),PDY2:B(t.PDY2,0),PDY3:B(t.PDY3,0),PEY1:B(t.PEY1,0),PEY2:B(t.PEY2,0),PEY3:B(t.PEY3,0),PEY4:B(t.PEY4,0),PEY5:B(t.PEY5,0),PHY1:B(t.PHY1,0),PHY2:B(t.PHY2,0),PHY3:B(t.PHY3,0),PKY1:B(t.PKY1,-15),PKY2:B(t.PKY2,2),PKY3:B(t.PKY3,0),PKY4:B(t.PKY4,2),PKY5:B(t.PKY5,0),PKY6:B(t.PKY6,0),PKY7:B(t.PKY7,0),PPY1:B(t.PPY1,0),PPY2:B(t.PPY2,0),PPY3:B(t.PPY3,0),PPY4:B(t.PPY4,0),PPY5:B(t.PPY5,0),PVY1:B(t.PVY1,0),PVY2:B(t.PVY2,0),PVY3:B(t.PVY3,0),PVY4:B(t.PVY4,0),RBX1:B(t.RBX1,0),RBX2:B(t.RBX2,0),RBX3:B(t.RBX3,0),RBY1:B(t.RBY1,0),RBY2:B(t.RBY2,0),RBY3:B(t.RBY3,0),RBY4:B(t.RBY4,0),RCX1:B(t.RCX1,1),RCY1:B(t.RCY1,1),REX1:B(t.REX1,0),REX2:B(t.REX2,0),REY1:B(t.REY1,0),REY2:B(t.REY2,0),RHX1:B(t.RHX1,0),RHY1:B(t.RHY1,0),RHY2:B(t.RHY2,0),RVY1:B(t.RVY1,0),RVY2:B(t.RVY2,0),RVY3:B(t.RVY3,0),RVY4:B(t.RVY4,0),RVY5:B(t.RVY5,1),RVY6:B(t.RVY6,0),PPZ1:B(t.PPZ1,0),PPZ2:B(t.PPZ2,0),QBZ1:B(t.QBZ1,8),QBZ2:B(t.QBZ2,0),QBZ3:B(t.QBZ3,0),QBZ4:B(t.QBZ4,0),QBZ5:B(t.QBZ5,0),QBZ6:B(t.QBZ6,0),QBZ9:B(t.QBZ9,0),QBZ10:B(t.QBZ10,0),QCZ1:B(t.QCZ1,1.1),QDZ1:B(t.QDZ1,.1),QDZ2:B(t.QDZ2,0),QDZ3:B(t.QDZ3,0),QDZ4:B(t.QDZ4,0),QDZ6:B(t.QDZ6,0),QDZ7:B(t.QDZ7,0),QDZ8:B(t.QDZ8,0),QDZ9:B(t.QDZ9,0),QDZ10:B(t.QDZ10,0),QDZ11:B(t.QDZ11,0),QEZ1:B(t.QEZ1,0),QEZ2:B(t.QEZ2,0),QEZ3:B(t.QEZ3,0),QEZ4:B(t.QEZ4,0),QEZ5:B(t.QEZ5,0),QHZ1:B(t.QHZ1,0),QHZ2:B(t.QHZ2,0),QHZ3:B(t.QHZ3,0),QHZ4:B(t.QHZ4,0),SSZ1:B(t.SSZ1,0),SSZ2:B(t.SSZ2,0),SSZ3:B(t.SSZ3,0),SSZ4:B(t.SSZ4,0),QSX1:B(t.QSX1,0),QSX2:B(t.QSX2,0),QSX3:B(t.QSX3,0),QSX4:B(t.QSX4,0),QSX5:B(t.QSX5,0),QSX6:B(t.QSX6,0),QSX7:B(t.QSX7,0),QSX8:B(t.QSX8,0),QSX9:B(t.QSX9,0),QSX10:B(t.QSX10,0),QSX11:B(t.QSX11,0),QSX12:B(t.QSX12,0),QSX13:B(t.QSX13,0),QSX14:B(t.QSX14,0),PPMX1:B(t.PPMX1,0),QSY1:B(t.QSY1,0),QSY2:B(t.QSY2,0),QSY3:B(t.QSY3,0),QSY4:B(t.QSY4,0),QSY5:B(t.QSY5,0),QSY6:B(t.QSY6,0),QSY7:B(t.QSY7,0),QSY8:B(t.QSY8,0),LONGVL:t.LONGVL!==void 0&&t.LONGVL>0?t.LONGVL:16.7,LCX:B(t.LCX,1),LCY:B(t.LCY,1),LEX:B(t.LEX,1),LEY:B(t.LEY,1),LFZO:B(t.LFZO,1),LHX:B(t.LHX,1),LHY:B(t.LHY,1),LKX:B(t.LKX,1),LKY:B(t.LKY,1),LKYC:B(t.LKYC,1),LKZC:B(t.LKZC,1),LMUX:B(t.LMUX,1),LMUY:B(t.LMUY,1),LMX:B(t.LMX,1),LMY:B(t.LMY,1),LVMX:B(t.LVMX,1),LRES:B(t.LRES,1),LS:B(t.LS,1),LTR:B(t.LTR,1),LVX:B(t.LVX,1),LVY:B(t.LVY,1),LVYKA:B(t.LVYKA,1),LXAL:B(t.LXAL,1),LYKA:B(t.LYKA,1)}}var lR=new WeakMap;function gs(e){let t=lR.get(e);return t===void 0&&(t=uR(e),lR.set(e,t)),t}var mR=e=>e>=0?1:-1;function ll(e,t,r=0,n){let o=gs(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),x=h?(o.PHY1+o.PHY2*c)*o.LHY+(b*s-g)/y:(o.PHY1+o.PHY2*c)*o.LHY+o.PHY3*s,M=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:x,SVy:M,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 ul(e,t,r=0,n){let o=ll(e,t,r,n),a=gs(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,x=(a.PHX1+a.PHX2*c)*a.LHX,M=(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,R=M*s,k=s*(a.PKX1+a.PKX2*c)*Math.exp(a.PKX3*c)*(1+a.PPX1*l+a.PPX2*l*l)*a.LKX,F=v*R!==0?k/(v*R):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:x,Cx:v,Dx:R,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:k/w*(k/w),sS0:m*(a.SSZ1+(a.SSZ3+a.SSZ4*c)*i)*a.LS,sS2:m*a.SSZ2*a.LS/u}}function ys(e,t){let r=t+e.SHy,n=e.EyA*(e.EyG-e.EyS*mR(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 ml(e,t){let r=t+e.SHx,n=e.ExA*(1-e.PEX4*mR(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 pR(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 FT(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=pR(e,o,r),i=e.Bt*s;return e.Dt*Math.cos(e.Ct*Math.atan(i-a*(i-Math.atan(i))))*n}function wT(e,t,r,n){return e.Dr*Math.cos(Math.atan(e.Br*pR(e,t+e.SHy+e.arOff,r)))*n}function dR(e,t,r,n,o,a){let s=Math.cos(t),i=FT(e,t,r,s),c=wT(e,t,r,s);return-i*(o-a)+c+(e.sS0+e.sS2*o)*n}function fR(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*ml(e,t)}function Ud(e,t){let r=e.sS0===0&&e.sS2===0?0:fR(e,0,t);return dR(e,t,0,r,ys(e,t),0)}function pl(e,t,r){let n=ys(e,r),o=fR(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:dR(e,r,t,o,m,u)}}var xs=(e,t)=>Math.max(.1,e.muY0+e.loadSensY*(t-e.nominalLoad)),Rs=(e,t)=>Math.max(.1,e.muX0+e.loadSensX*(t-e.nominalLoad)),hR=(e,t,r)=>xs(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cy*Math.atan(e.By*r)),bR=(e,t,r)=>Rs(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cx*Math.atan(e.Bx*r));function Xd(e,t){let r=Math.max(1,t.Fz),n=xs(e,r)*r,o=Rs(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 dl=Math.PI/180;function Jr(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 gR(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?hs(r,t):1,s=n?hs(n,t):1,i=o?hs(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 Xo(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 Ie(e){let t=gR(e),r=t,n=t,o=null,a=NaN,s=NaN,i=NaN,c=(v,R,k)=>(o!==null&&v===a&&R===s&&k===i||(o=ul(r,v,R,k),a=v,s=R,i=k),o),l=null,u=NaN,m=NaN,f=NaN,p=(v,R,k)=>(l!==null&&v===u&&R===m&&k===f||(l=ll(r,v,R,k),u=v,m=R,f=k),l),d=v=>e.kind==="magic"?pl(c(v.Fz,v.gamma??0,v.p),v.kappa,v.alpha):Xd(n,v),h=(v,R,k=0,F)=>e.kind==="magic"?ys(p(R,k,F),v):hR(n,R,v),b=(v,R,k=0,F)=>e.kind==="magic"?ml(c(R,k,F),v):bR(n,R,v),g=(v,R,k=0,F)=>e.kind==="magic"?Ud(c(R,k,F),v):d({Fz:R,kappa:0,alpha:v,gamma:k,p:F}).Mz,y=v=>e.kind==="simple"?xs(n,v):Xo(R=>h(R*dl,v),45,1)/Math.max(1,v),x=v=>e.kind==="simple"?Rs(n,v):Xo(R=>b(R,v),.6,.02)/Math.max(1,v),M=v=>{let R=.1*dl;return Math.abs((h(R,v)-h(-R,v))/(2*R))};return{model:e,forces:d,Fx:b,Fy:h,Mz:g,muX:x,muY:y,corneringStiffness:M,verticalStiffness:()=>e.verticalStiffness,rollingRadius:v=>{if(e.kind==="magic"&&e.missing?.includes("UNLOADED_RADIUS"))return 0;let R=e.unloadedR0??0;if(!(R>0))return 0;let k=e.verticalStiffness*1e3;if(!(k>0))return R;let F=e.rollingFraction??.306;return R-F*Math.max(0,v)/k},relaxationLength:v=>{let R=e.relaxation;if(!R)return 0;let k=R.carcassStiffness??0;if(!(k>0))return R.sigma;let F=M(Math.max(0,v));return F>0?F/(k*1e3):R.sigma}}}function Qo(e){let t=Math.max(1,e.model.kind==="magic"?e.model.fnomin:e.model.nominalLoad);return e.Fy(2*dl,t,0)-e.Fy(-2*dl,t,0)>=0?1:-1}var CT=Math.PI/180;function xe(e,t){return e.axle?e.axle(t):e}function hl(e,t){if(e===t)return e;let r=Qo(e)*Qo(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=>Xo(u=>s(u,l),.6,.02)/Math.max(1,l),muY:l=>Xo(u=>i(u*CT,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(yR.has(e))return e;let t=xR.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:hl(a,s)}else Qo(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 yR.add(r),r!==e&&xR.set(e,r),r}var yR=new WeakSet,xR=new WeakMap;var bl=25*(Math.PI/180);function TT(e){let t=.6180339887,r=0,n=bl,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 vs(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=bl;if(s(bl)<=a){let u=TT(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(bl,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 Qd={shaft:!1,trail:0,hub:[0,0,0]};function vR(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 qd(e,t,r){let n=r.shaft?jd(e,t):[0,0,0];if(r.trail!==0){let a=vR(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 PT=(e,t)=>{let r=e!==void 0&&e>0?1/e:0,n=t!==void 0&&t>0?1/t:0;return r+n},gl={ucaFront:0,ucaRear:0,lcaFront:0,lcaRear:0,tieRod:0,pushRod:0,rack:0};function Tn(e){return!e.measured}function Pn(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 ks(e,t){let r=e.corner.hardpoints,n=Za(e.rocker,t.points.rockerAngle);return{ucaFront:r.ucaFront,ucaRear:r.ucaRear,lcaFront:r.lcaFront,lcaRear:r.lcaRear,tieInner:Eo(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 Zd(e,t,r=0){let n=t.links??{},o=t.bushings??{},a=(l,u,m)=>{let f=PT(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 kR(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 Ms(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=kR(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=kR(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 LT=8,DT=1e-5,ET=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 Jd(e,t,r){let n=qd(e,r.force,r.extras??Qd),o=r.alignMoment?ee(n.moment,[0,0,r.alignMoment]):n.moment;return fs(e,t,n.force,o)}function xl(e,t,r,n,o,a,s=0){let i=Ee(e,t,r,o,a),c=e.corner.compliance;if(!(Pn(c)&&Tn(e.corner)))return{state:i,forces:Jd(ks(e,i),e.corner.config.pushrodAttach,n),deflection:gl,rigid:i,iterations:0,converged:!0,bypassed:!0};let u=i,m=e,f=e.corner.config.pushrodAttach,p=Jd(ks(e,i),f,n),d=gl,h=!1,b=0;for(;b<LT;b++){let g=ks(m,u);if(p=Jd(g,f,n),p.singular)break;d=Zd(p,c,s),m=Ms(e,d);let y=Ee(m,t,r,ET(u),a),x=ve(y.points.wheelCenter,u.points.wheelCenter);if(u=y,x<DT){h=!0;break}}return{state:u,forces:p,deflection:d,rigid:i,iterations:b+1,converged:h&&u.converged,bypassed:!1}}var yl=1e3,MR=1e5;function SR(e,t,r,n,o){let a=xl(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 Rl(e,t,r,n,o){let a={force:[0,0,n]},s=(b,g=0)=>SR(e,t,r,{force:b,alignMoment:g},o),i=SR(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,yl,n]),l=s([0,-yl,n]),u=s([yl,0,n]),m=s([-yl,0,n]),f=s([0,0,n],MR),p=s([0,0,n],-MR),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 IT=1e3;function ef(e,t=IT){if(!Pn(e.compliance)||!Tn(e))return;let r=et(e),n=Ee(r,0,0),o=Rl(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 qo(e,t=-Wd,r=Wd,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=ef(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 vl(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 en(e,t){return{motionRatio:vl(e.travel,e.motionRatio,t),camber:vl(e.travel,e.camber,t),toe:vl(e.travel,e.toe,t),damperLen:vl(e.travel,e.damperLen,t)}}var AR=Math.PI/180,_T=9.81;function tn(e,t,r,n=0){let o=Ce(e),a=e.wheelbase*(1-e.frontMassFrac),s=e.wheelbase*e.frontMassFrac,i=jo(e,n),c=e.aero?.model?(M,v,R)=>jo(e,n,v,M,R):()=>i,l=en(t,0),u=en(r,0),m=e.loadFactor,f=m!==void 0&&m!==1?(m-1)*e.massTotal*_T:0,p=f*e.frontMassFrac/2,d=f*(1-e.frontMassFrac)/2,h=(M,v)=>v>0&&Number.isFinite(v)&&M+v>0?v/(M+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)},x={F:h(e.wheelRateFront+e.arbFront,b),R:h(e.wheelRateRear+e.arbRear,g)};return(M,v,R=0,k=0)=>{let F=c(M,v,R),w=o.rollGradient*M,C=w*AR,T=o.pitchGradient*v*AR,S=($,O)=>{let W=O==="F"?e.trackFront:e.trackRear,I=O==="F"?o.rideRateFront:o.rideRateRear,_=($==="R"?1:-1)*(W/2)*Math.tan(C),V=(O==="R"?s:-a)*Math.tan(T),N=`${O}${$}`,G=f?F[N]+(O==="F"?p:d):F[N],K=I>0?G/I:0;return{anti:_,sym:V+K}},A={FL:S("L","F"),FR:S("R","F"),RL:S("L","R"),RR:S("R","R")},P=$=>{let O=$[0];return A[$].sym*y[O]+A[$].anti*x[O]},L=Wo(e,k,o,{FL:P("FL"),FR:P("FR")}),D=w+L.rollDeg,E=($,O)=>{let W=O==="F"?t:r,I=O==="F"?l:u,_=`${O==="F"?"F":"R"}${$}`,V=A[_].sym+A[_].anti+L.travel[_],N=P(_)+L.travel[_]*x[O],G=V-N,K=en(W,N),z=($==="R"?1:-1)*K.camber;return{travel:N,tyre:G,ground:V,camber:z,camberRoad:z+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 tf=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function Ln(e){return{enabled:e?.enabled===!0,roadFeedbackGain:Math.min(2,Math.max(0,tf(e?.roadFeedbackGain,1))),turnInFrictionNm:Math.max(0,tf(e?.turnInFrictionNm,0)),columnStiffnessNmPerRad:Math.max(0,tf(e?.columnStiffnessNmPerRad,0))}}function rf(e,t,r){let n=Ln(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 FR=()=>({totalNm:0,aligningNm:0,lateralNm:0,longitudinalNm:0,jackingNm:0});function Dn(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 Ss(e,t,r,n="model",o){let a=e.steerFront;if(!Dn(e)||!a)return null;let s=t<0?-1:1,c=a.rackRatioMmPerRev/(2*Math.PI)/1e3,l=t>=0,u=o&&a.travelSurface?zo(a,Math.abs(t),l?o.FL:o.FR,l?o.FR:o.FL):Yo(a,Math.abs(t));if(!u.innerJacobian||!u.outerJacobian)return null;let m=(b,g)=>{let y=r[b],x=b==="FL"?-1:1,M=-x*y.Fy,R={aligning:1e3*(-x*y.Mz)*g.yaw,lateral:M*g.lateral,longitudinal:y.Fx*g.longitudinal,jacking:y.Fz*g.vertical},k=FR();k.aligningNm=-s*R.aligning*c,k.lateralNm=-s*R.lateral*c,k.longitudinalNm=-s*R.longitudinal*c,k.jackingNm=-s*R.jacking*c,k.totalNm=k.aligningNm+k.lateralNm+k.longitudinalNm+k.jackingNm;let F=-s*(R.aligning+R.lateral+R.longitudinal+R.jacking);return{moment:k,rackN:F}},f=m("FL",l?u.innerJacobian:u.outerJacobian),p=m("FR",l?u.outerJacobian:u.innerJacobian),d=FR();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=rf(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 NT=e=>"front"in e&&"rear"in e;function Zo(e,t){return NT(e)?e[t]:e}function of(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 nf(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 wR(e,t,r){let n=nf(e,t),o=nf(e,r);return{left:n,right:o,fyRes:n.fyRes+o.fyRes}}function Rr(e,t,r){let n=wR(Zo(e,"front"),t.FL,t.FR),o=wR(Zo(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 kl=[{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"}],VT=kl.flatMap(e=>[e.min,e.max]);function PR(e){return Math.max(1,e.kind==="magic"?e.fnomin:e.nominalLoad)}function CR(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=TR.get(e);if(t!==void 0)return t;let r=10*PR(e.model),{turnover:n,collapse:o}=$T(e,r),a=n??o??r;return TR.set(e,a),a}var TR=new WeakMap;function $T(e,t){let r=PR(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=CR(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=CR(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 LR=["FL","FR","RL","RR"],GT=e=>e==="FL"||e==="RL",KT=e=>e==="FL"||e==="FR"?"front":"rear";function Ml(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 LR)a[l]={...t[l]};let s=l=>{let u=0;for(let f of LR)KT(f)===e.axle&&(a[f].Fx=e.sense*(f===e.strong?l-e.open/2:e.open/2),u-=(GT(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 HT=[["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]],zT=[["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]],YT=[["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]],WT=[["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]],jT=[["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]],ER=[["lateral",HT],["longitudinal",zT],["aligning",YT],["combined",WT],["scaling",jT]].flatMap(([e,t])=>t.map(([r,n,o])=>({key:r,section:e,text:n,fallback:o}))),T4=new Map(ER.map(e=>[e.key,e]));var UT=/^\$\s*EDITED\s+([A-Z][A-Z0-9_]*)\s+was\s+(absent|[-+0-9.eE]+)\s*$/;function IR(e){let t={};for(let r of e.split(/\r?\n/)){let n=r.trim().match(UT);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 QT=/^\s*\$\s*UNLOADED_RADIUS_STAND_IN\s*=\s*([0-9.eE+-]+)/,qT=/^\$-+ written by (?:PaceDynamics|PaceLab)\b/m,ZT=/^\$\s*AXIS_SYSTEM\s*=\s*(ISO-W|SAE)\b/m;function JT(e){let t=e.match(ZT);return t?{axisSystem:t[1]==="SAE"?"sae":"iso",trustSide:!0}:qT.test(e)?{axisSystem:"sae",trustSide:!1}:{axisSystem:"iso",trustSide:!0}}function eP(e){return e>=62?"6.2":e>=61?"6.1":"5.2"}var _R=new Map([["pa",1],["pascal",1],["kpa",1e3],["kilopascal",1e3],["mpa",1e6],["megapascal",1e6],["bar",1e5],["psi",6894.757293168]]);function tP(e,t,r){let n=r.PRESSURE?.trim().toLowerCase(),o=n===void 0?1:_R.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 rP=new Map([["radians",1],["radian",1],["rad",1],["degrees",Math.PI/180],["degree",Math.PI/180],["deg",Math.PI/180]]);function nP(e,t){let r=(s,i)=>s===void 0?1:i.get(s.trim().toLowerCase()),n=r(t.ANGLE,rP),o={fz:1,kappa:1,alpha:n,gamma:n,p:r(t.PRESSURE,_R)},a={};for(let s of kl){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 As(e,t="imported",r={}){let n=JT(e),o=r.axisSystem??n.axisSystem,a={},s={},i={},c="",l;for(let g of e.split(/\r?\n/)){let y=g.match(QT);y&&(l=parseFloat(y[1]));let x=g.replace(/[$!].*$/,"").trim();if(!x)continue;if(x.startsWith("[")){c=(x.match(/^\[([^\]]*)/)?.[1]??"").trim().toUpperCase();continue}let M=x.indexOf("=");if(M<0)continue;let v=x.slice(0,M).trim().toUpperCase(),R=x.slice(M+1).trim(),k=R.match(/^'([^']*)'|^"([^"]*)"/);if(k){s[v]=k[1]??k[2]??"",c==="UNITS"&&(i[v]=s[v]);continue}let F=parseFloat(R);Number.isFinite(F)&&(a[v]=F)}let u=eP(a.FITTYP??62),m=IR(e),f=m?Object.fromEntries(Object.entries(m).filter(([g])=>a[g]!==void 0)):void 0,p=a.VERTICAL_STIFFNESS??a.KZ??0,d=tP(a,s,i),h=nP(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 er(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 O4=Math.PI/180;var K4=Math.PI/180,H4=180/Math.PI;function Fs(){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 BR=`$ AXIS_SYSTEM = SAE (authored in the evaluation frame: y right)
|
|
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)
|
|
3
3
|
[MODEL]
|
|
4
4
|
FITTYP = 62
|
|
5
5
|
[DIMENSION]
|
|
@@ -108,7 +108,7 @@ QHZ1 = 0
|
|
|
108
108
|
QHZ2 = 0
|
|
109
109
|
QHZ3 = 0
|
|
110
110
|
QHZ4 = 0
|
|
111
|
-
`;function
|
|
111
|
+
`;function xf(){return 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]
|
|
@@ -170,9 +170,9 @@ PEY3 = 0.1
|
|
|
170
170
|
PEY4 = -4
|
|
171
171
|
PEY5 = 0
|
|
172
172
|
PKY1 = ${o(r)}
|
|
173
|
-
PKY2 = ${o(
|
|
173
|
+
PKY2 = ${o(iv)}
|
|
174
174
|
PKY3 = 0.8
|
|
175
|
-
PKY4 = ${o(
|
|
175
|
+
PKY4 = ${o(cv)}
|
|
176
176
|
PKY5 = 0
|
|
177
177
|
PKY6 = ${o(n)}
|
|
178
178
|
PKY7 = 0
|
|
@@ -220,7 +220,7 @@ QHZ1 = 0
|
|
|
220
220
|
QHZ2 = 0
|
|
221
221
|
QHZ3 = 0
|
|
222
222
|
QHZ4 = 0
|
|
223
|
-
`}function vr(e){let t=As(KR(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 HR={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},zR={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},YR={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},WR={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},jR={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},UR={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},XR={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},QR={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},sf=()=>vr(HR),cf=()=>vr(zR),lf=()=>vr(YR),uf=()=>vr(WR),mf=()=>vr(jR),pf=()=>vr(UR),df=()=>vr(XR),ff=()=>vr(QR);var qR=e=>Number.isFinite(e)&&e>0;function Sl(e,t){let r=qR(t.grip)?t.grip:1,n=qR(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 ws={ok:!0,violation:0},En=1e7;function kr(e,t){let r;try{r=e.build(t)}catch(s){return{total:En*2,feasible:!1,terms:[],reason:`build failed: ${String(s)}`}}let n=e.feasible(r);if(!n.ok)return{total:En+Math.max(0,n.violation),feasible:!1,terms:[],reason:n.reason};let o;try{o=e.terms(r)}catch(s){return{total:En*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:En*2,feasible:!1,terms:o,reason:"objective was not finite"}}var Cs=(e,t)=>!t||(e.feasible!==t.feasible?e.feasible:e.total<t.total);function hf(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 Al(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 iP(e){let t=0;for(;t===0;)t=e();return Math.sqrt(-2*Math.log(t))*Math.cos(2*Math.PI*e())}function bf(e,t){let{budget:r}=t,n=Math.max(1,Math.floor(t.progressEvery??1)),o=e.variables,a=p=>hf(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=Cs(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 gf=(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 ZR(e,t){let r=bf(e,t),n=Al(t.seed??1),o=e.variables.length;for(r.evaluate(gf(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 Jo(e,t){let r=bf(e,t),n=e.variables.length,o=Al(t.seed??1),a=1,s=2,i=.5,c=.5,l=gf(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,x)=>y+g*(y-f.u[x])),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 x=m[0],M=0;for(let v=1;v<=n;v++)for(let R=0;R<n;R++)M=Math.max(M,Math.abs(m[v].u[R]-x.u[R]));if(M<1e-4)break;for(let v=1;v<=n&&r.left()>0;v++){let R=m[v].u.map((k,F)=>x.u[F]+c*(k-x.u[F]));m[v]={u:R,f:r.evaluate(R)}}}}}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 JR(e,t){let r=bf(e,t),n=e.variables.length,o=Al(t.seed??1),a=4+Math.floor(3*Math.log(n)),s=Math.floor(a/2),i=[];for(let k=1;k<=s;k++)i.push(Math.log(s+.5)-Math.log(k));let c=i.reduce((k,F)=>k+F,0);for(let k=0;k<s;k++)i[k]/=c;let l=1/i.reduce((k,F)=>k+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=gf(e,t.warmStart!==!1,r,t.startJitter,o),y=.25,x=new Array(n).fill(1),M=new Array(n).fill(0),v=new Array(n).fill(0),R=0;for(;r.left()>0;){R++;let k=[];for(let S=0;S<a&&r.left()>0;S++){let A=[];for(let L=0;L<n;L++)A.push(iP(o));let P=g.map((L,D)=>L+y*x[D]*A[D]);k.push({z:A,u:P,f:r.evaluate(P)})}if(k.length<s)break;k.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]*k[S].u[A],w[A]+=i[S]*k[S].z[A];g=g.map(S=>Math.min(1,Math.max(0,S)));for(let S=0;S<n;S++)M[S]=(1-u)*M[S]+Math.sqrt(u*(2-u)*l)*w[S];let C=Math.sqrt(M.reduce((S,A)=>S+A*A,0)),T=C/Math.sqrt(1-(1-u)**(2*R))/b<1.4+2/(n+1)?1:0;for(let S=0;S<n;S++){let A=(g[S]-F[S])/(y*x[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]*k[D].z[S]*k[D].z[S];let P=x[S]*x[S],L=(1-d-h)*P+d*(v[S]*v[S]+(1-T)*f*(2-f)*P)+h*A*P;x[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 ea=[{name:"random",run:ZR},{name:"nelder-mead",run:Jo},{name:"sep-cma-es",run:JR}];var sK=Math.PI/180;var Fl=Math.PI/180;var uK={Fz:100,alpha:.25*Fl,kappa:.005,gamma:.5*Fl,p:6900},ev={Fz:100,alpha:1*Fl,kappa:.02,gamma:.5*Fl,p:6900};var tv=Math.PI/180,bK={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:tv},gamma:{rad:1,deg:tv},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 vK=Math.PI/180;var xP=Math.PI/180;var CK=3*xP;var EK=Math.PI/180;var YK=Math.PI/180;var wP={RCX1:1,RCY1:1,REX1:0,REY1:0,RBY3:0,RHX1:0,RHY1:0},ov={RBX1:15,RBX2:15,RBY1:18,RBY2:19,...wP};var rH=Math.PI/180;var EP=Math.PI/180,wl=[{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"}],gH=new Map(wl.map(e=>[e.id,e]));var yH=.01*EP;var Ye=Math.PI/180;var iv=new Set(wl.filter(e=>e.group!=="inputs"&&(e.unit==="N"||e.unit==="N\xB7m"||e.unit==="N/rad")).map(e=>e.id)),cv={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}},kf={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 Mf={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,...cv[t],...o}],x:t,y:r,...n}),Cl=(e,[t,r],n,o,a={})=>({id:e,form:"carpet",sweep:[{input:t,...kf[t]},{input:r,...kf[r]}],x:n,y:[o],...a}),Sr=(e,t)=>({id:e,fixed:t}),Vt={input:"Fz",values:"car"},vf={alpha:0,kappa:0},yt={kappa:0},av={alpha:0},NP={input:"Fz",values:[500,1e3,1500]},OP=[{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:av}),Cl("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}),Cl("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:av}),ke("mux-peak","Fz",["muXPeak"],{title:"Peak longitudinal \u03BC over load"}),ke("kx","Fz",["dFxdk"],{title:"Slip stiffness at zero slip over load",hold:vf}),ke("kappa-peak","Fz",["kappaPeak"],{title:"Slip ratio at the peak over load"})]},{id:"combined",name:"Combined",cards:[Cl("carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Cl("envelope-load",["kappa","alpha"],"Fy","Fx",{title:"Friction envelope per load",scale:{per:"Fz"},facet:NP}),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",...Mf.gamma},{input:"Fz",...Mf.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:vf}),ke("radius","Fz",["R0","Rl","Re"],{title:"Radius over load"},{from:0}),ke("p-roll","V",["Proll"],{title:"Rolling power",series:Vt,hold:vf})]},{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 zP=5670374e-14,Sf=273.15,mv=.95,pv=60,Tl=10,YP=.55,At=25,Af=-20,Ff=50,Ps={tempC:[20,100,200,550,650,750],factor:[.8,.92,1,1,.85,.65]},Ls={discMassKg:.5,discOuterMm:220,specificHeatJPerKgK:460,emissivity:.6,coolingWPerM2K:200,padCurve:{tempC:[...Ps.tempC],factor:[...Ps.factor]}},Pl={...Ls,discMassKg:.4,discOuterMm:200,padCurve:{tempC:[...Ps.tempC],factor:[...Ps.factor]}};function wf(e,t){let r=t==="front"?Ls:Pl,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 WP=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},Ts=(e,t,r,n)=>Math.min(r,Math.max(t,WP(e,n)));function jP(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 Cf(e,t){return{discMassKg:Ts(e?.discMassKg,.05,20,t.discMassKg),discOuterMm:Ts(e?.discOuterMm,50,600,t.discOuterMm),specificHeatJPerKgK:Ts(e?.specificHeatJPerKgK,100,3e3,t.specificHeatJPerKgK),emissivity:Ts(e?.emissivity,.02,1,t.emissivity),coolingWPerM2K:Ts(e?.coolingWPerM2K,Tl,5e3,t.coolingWPerM2K),padCurve:jP(e?.padCurve,t.padCurve)}}function Ll(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 Tf(e,t=1){let r=e.discMassKg*e.specificHeatJPerKgK,n=e.discOuterMm*.001/2,o=2*Math.PI*n*n,a=pv/3.6,s=e.emissivity*zP*o,i=m=>Tl+(e.coolingWPerM2K-Tl)*Math.pow(Math.max(0,m)*t/a,YP),c=(m,f,p)=>{let d=m+Sf,h=p+Sf;return i(f)*o*(m-p)+s*(d**4-h**4)},l=(m,f)=>i(f)*o+4*s*Math.max(0,m+Sf)**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,x=f/g;for(let M=0;M<g;M++)m+=(x-c(m,p,h)*y)/r;return m},padFactor:m=>Ll(e.padCurve,m),window:dv(e.padCurve)}}function Dl(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=mv/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 x=y*(o[g]??0);d+=x,f<e.window.fromC?h+=x:f>e.window.toC&&(b+=x);let M=g+1<i?n[g+1]:n[g],v=.5*(n[g]+M),R=v>0?(o[g]??0)/v:0;f=e.step(f,m*x,v,R,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 dv(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])&&Ll(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 Pf=1e5,gv=.001,In={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},Df={fullAtBar:10,maxPowerKw:0,fadeBelowKmh:0,distribution:"equal"};var Ef=xv(Il(In,"Formula Student brakes")),If=40,yv={ideal:!1,barFront:In.barFront,pedalForceMaxN:0,testSpeedKmh:If,regen:Df};function fv(e){let{heat:t,...r}=e;return t?{...r,heat:{...t,padCurve:{tempC:[...t.padCurve.tempC],factor:[...t.padCurve.factor]}}}:r}function xv(e){let t=(r,n)=>r.heat?r:{...r,heat:wf(r,n)};return{...e,front:t(e.front,"front"),rear:t(e.rear,"rear")}}function Il(e,t){return{name:t,pedalRatio:e.pedalRatio,masterFrontMm:e.masterFrontMm,masterRearMm:e.masterRearMm,valve:e.valve,valveKneeBar:e.valveKneeBar,valveSlope:e.valveSlope,front:fv(e.front),rear:fv(e.rear),adjusterPitchMm:e.adjusterPitchMm,barLengthMm:e.barLengthMm}}function _f(e,t){return Rv({...e,barFront:t.barFront,pedalForceMaxN:t.pedalForceMaxN})}function Nf(e,t){let r=Fr(t),n=e?tr(e):void 0;return{mode:r.ideal?"tyre":n?"hydraulic":"balance",hydraulic:n?_f(n,r):In,regen:r.regen}}var UP=["none","proportioning","limiter"],El=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},Je=(e,t,r,n)=>Math.min(r,Math.max(t,El(e,n))),XP=(e,t)=>{let r=El(e,t);return r>0?r:t};function hv(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(El(e?.discs,n==="inboard"?1:t.discs)))),pistonsPerSide:Math.max(1,Math.min(6,Math.round(El(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:Cf(e.heat,t.heat??r)}:{}}}function Rv(e){let t=In;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:UP.includes(e?.valve)?e?.valve:t.valve,valveKneeBar:Je(e?.valveKneeBar,0,200,t.valveKneeBar),valveSlope:Je(e?.valveSlope,0,1,t.valveSlope),front:hv(e?.front,t.front,Ls),rear:hv(e?.rear,t.rear,Pl),adjusterPitchMm:XP(e?.adjusterPitchMm,t.adjusterPitchMm),barLengthMm:Je(e?.barLengthMm,0,500,t.barLengthMm)}}function QP(e){let t=Df;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 tr(e){let t=Rv(e??void 0),r=typeof e?.name=="string"&&e.name.trim()?e.name:qP;return Il(t,r)}function Fr(e){return{ideal:e?.ideal===!0,barFront:Je(e?.barFront,.05,.95,In.barFront),pedalForceMaxN:Je(e?.pedalForceMaxN,0,5e3,0),testSpeedKmh:Je(e?.testSpeedKmh,5,150,If),regen:QP(e?.regen)}}var qP="Formula Student brakes";var Lf=e=>Math.PI/4*(e*gv)**2;function rn(e,t){let r=e.pistonsPerSide*Lf(e.pistonDiaMm)*Pf;return e.discs*2*e.padMu*r*e.effRadiusMm*gv*e.ratio/Math.max(.05,t)}function vv(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 Ds(e,t){let r=Math.max(0,t)*e.pedalRatio,n=e.barFront*r/Lf(e.masterFrontMm)/Pf,o=(1-e.barFront)*r/Lf(e.masterRearMm)/Pf;return{front:n,rearIn:o,rear:vv(e,o)}}function ZP(e,t){let r=Ds(e,1);return{front:rn(e.front,t)*r.front,rear:rn(e.rear,t)*r.rearIn}}function Es(e,t){let r=ZP(e,t);return r.front/Math.max(1e-12,r.front+r.rear)}function Is(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=kv(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 kv(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 bv=new WeakMap;function _n(e){let t=bv.get(e);return t||(t=e.mode==="hydraulic"&&e.hydraulic?eL(e,e.hydraulic):JP(e),bv.set(e,t)),t}function JP(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 eL(e,t){let r=rn(t.front,e.tyreRadiusM),n=rn(t.rear,e.tyreRadiusM),o=e.regen,a=(c,l)=>{let u=Ds(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 Of(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 _l=ds,tL=.1,Nn=(e,t)=>e.a*Math.sqrt(Math.max(0,1-(t/Math.max(1e-9,e.b))**2));function Nl(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 $f(e,t,r){let n=Math.max(0,r-_l*t.b),o=Math.min(r,_l*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 Gf(e,t,r,n,o=0){let a=Math.max(0,r),s=$f(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/tL)),d=p>0&&a<_l*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:x,hi:M}=s,v=Nl(T=>{let S=Nn(e,T),A=Nn(t,a-T);return Math.min(S+A,2*Math.min(S,A)+y)},x,M),R=e.cap(v),k=t.cap(a-v),F=Math.max(2*l,Math.min(R+k,2*Math.min(R,k)+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=>_l*E.b*Math.sqrt(Math.max(0,1-(T/Math.max(1e-9,E.a))**2)),P=Math.max(x,a-A(t)),L=Math.min(M,A(e));if(!(P<=L))return S;let D=Nl(E=>Math.min(y,Nn(e,E)-T)+Math.min(y,Nn(t,a-E)-T),P,L);return Math.max(S,w(e.cap(D),t.cap(a-D),T))}}}var Vf=e=>Math.max(e.xNoLock,e.xLock),Bf=e=>Math.max(e.mixedMax,2*e.xLock);function ta(e,t,r=0){let n=1e-9*Math.max(1,t),o=Math.max(0,r);if(t<=e.xNoLock+n)return Math.min(2*t+(o>0?Math.min(o,e.regenRoom(t)):0),e.ceiling);if(t<=e.xLock+n){let a=o>0?Math.min(e.regenWheel>0?Math.min(o,e.regenWheel):o/2,Math.max(0,e.xLock-t)):0;return Math.min(t+e.slide+a,e.ceiling)}return NaN}function ra(e,t){let r=t/2,n=1e-9*Math.max(1,r);return r<=e.mixedMax/2+n?Math.min(t,e.ceiling):r<=e.xLock+n?Math.min(r+e.slide,e.ceiling):NaN}function _s(e,t,r,n){return e.shares?rL(e,e.shares,t,r,n):nL(e,t,r,n)}function Mv(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 rL(e,t,r,n,o){let a=Bf(r),s=Bf(n),i=Math.min(t.front>0?a/t.front:1/0,t.rear>0?s/t.rear:1/0,e.uMax),c=Number.isFinite(e.uMax)&&i>=e.uMax,l=b=>{let g=ra(r,t.front*b),y=ra(n,t.rear*b);return Number.isFinite(g)&&Number.isFinite(y)?g+y:-1/0},u=a>0?t.front*i/a:1/0,m=s>0?t.rear*i/s:1/0,f=[{u:i,by:c?"pedal":u>=m?"front":"rear"}];if(r.xLock>r.xNoLock){let b=t.front>0?r.mixedMax/t.front:1/0;b<i&&f.push({u:b,by:"front"})}if(n.xLock>n.xNoLock){let b=t.rear>0?n.mixedMax/t.rear:1/0;b<i&&f.push({u:b,by:"rear"})}let{cand:p,force:d}=Mv(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 nL(e,t,r,n){let o=Vf(t),a=Vf(r),s=v=>(v.front-v.regenFront)/2,i=v=>(v.rear-v.regenRear)/2,c=v=>{let R=e.demand(v,n);return s(R)<=o*(1+1e-12)&&i(R)<=a*(1+1e-12)},l=(v,R)=>{if(v(e.demand(R,n)))return R;let k=0,F=R;for(let w=0;w<60;w++){let C=.5*(k+F);v(e.demand(C,n))?k=C:F=C}return k},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 R=e.demand(v,n),k=ta(t,s(R),R.regenFront),F=ta(r,i(R),R.regenRear);return Number.isFinite(k)&&Number.isFinite(F)?k+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(R=>s(R)<=t.xNoLock,m);v<m&&g.push({u:v,by:"front"})}if(r.xLock>r.xNoLock){let v=l(R=>i(R)<=r.xNoLock,m);v<m&&g.push({u:v,by:"rear"})}let{cand:y,force:x}=Mv(g,p),M=e.demand(y.u,n);return{force:Math.max(0,Number.isFinite(x)?x:0),control:y.u,demand:M,limitedBy:y.by,lockFront:s(M)>t.xNoLock*(1+1e-9),lockRear:i(M)>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 Sv(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 Ol(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,x]=d===0?[0,1]:[n-2,n-3],M=i(y)*(1+s(y)/(s(y)+s(x)))-i(x)*(s(y)/(s(y)+s(x)));return M*i(y)<=0?0:Math.abs(M)>2*Math.abs(i(y))?2*i(y):M}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 Ns(e,t,r){return r.map(n=>mt(e,t,n))}var Os=e=>e.reduce((t,r)=>r>t?r:t,-1/0),na=e=>e.reduce((t,r)=>r<t?r:t,1/0);var oL=[-.906179845938664,-.538469310105683,0,.538469310105683,.906179845938664],aL=[.236926885056189,.478628670499366,.568888888888889,.478628670499366,.236926885056189];function Kf(e,t,r){let n=.5*(r-t),o=.5*(t+r),a=0;for(let s=0;s<5;s++)a+=aL[s]*e(n*oL[s]+o);return n*a}var sL=Math.PI*2,iL=.5/3.6;function Vs(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 Hf(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*sL;c[g]=y*o/n,l[g]=s[g]*n/o}let u=Os(c),m=Tr(na(c),u,u/iL),f=Ns(c,l,m),{front:p,rear:d}=Vs(t,r),h=f.map(g=>g*p),b=f.map(g=>g*d);return{vVehicle:m,fFront:h,fRear:b,vMax:u}}var Av=60/(2*Math.PI),Fv=.1,wv=.08,Cv=0;function zf(e){let t=(r,n)=>r===void 0||!Number.isFinite(r)?n:Math.max(0,r);return{up:t(e.upshiftTime,Fv),down:t(e.downshiftTime,wv)}}function Yf(e){let t=e.driveKept;return t===void 0||!Number.isFinite(t)?Cv:Math.max(0,Math.min(1,t))}function Wf(e,t,r){let{primary:n,ratios:o,efficiency:a}=e.gearbox,s=t>0&&r>0&&n>0,i=(b,g)=>b/Av*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*Av: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 oa(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 jf(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 Tv=9.81,Pv=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]*(Pv/60),a[v]=t[v]/60*Pv,s[v]=a[v]*u/l,i[v]=r[v]*l,c[v]=i[v]/u;let m=Os(s),f=m,p=.5/3.6,d=Tr(na(s),m,m/p),h=Ns(s,c,d),b=Tr(na(t),Os(t),250),g=Ns(t,o,b).map(v=>v*e.power_scale.value),y,x=f,M;if(e.motorModel?.kind==="ice"){M=Wf(e.motorModel,l,u);let v=Tr(0,M.vMax,Math.max(2,Math.ceil(M.vMax/p)+1)),R=v.map(w=>jf(M,w)),k=v.map(()=>0),F=e.motorPlacement==="front";y={vVehicle:v,fFront:F?R:k,fRear:F?k:R,vMax:M.vMax},x=M.vMax}else e.motorModel&&(y=Hf(e.motorModel,Math.max(1,Math.round(e.motorCount??e.driven_wheels.value)),e.motorPlacement??"rear",l,u),x=y.vMax);return{params:e,g:Tv,FG:e.m.value*Tv,vMax:x,vVehicle:d,fRad:h,uMotor:b,pMotor:g,vRad:s,fAxle:y,...M?{engine:M}:{}}}var nn=e=>e.motorModel?.kind==="ice"?Vs(1,e.motorPlacement==="front"?"front":"rear"):Vs(Math.max(1,Math.round(e.motorCount??e.driven_wheels?.value??2)),e.motorPlacement??"rear");function Lv(e){let t=nn(e);return t.front>=2||t.rear>=2}function Dv(e){return Lv(e)?e.motorMount??"hub":"chassis"}function Uf(e){if(!e.motorModel)return{front:!1,rear:!0};let t=nn(e);return{front:t.front>0,rear:t.rear>0}}function Xf(e){let t=nn(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=Dv(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 Nf(e.brakeModel,e.brakeSetup)}function Vl(e){return Fr(e.brakeSetup).ideal?"tyre":e.brakeModel||e.brakeModelId?"hydraulic":"balance"}function Ev(e,t){if(!(ft(e.motorModel)||!Cr(e).regen))return Is(Bl(Ft(e)),t??pt(e).regen)}function Bl(e){return e.fAxle??{vVehicle:e.vVehicle,fFront:e.vVehicle.map(()=>0),fRear:e.fRad.map(t=>t*e.params.driven_wheels.value)}}function Qf(e,t=pt(e)){if(t.mode==="hydraulic")return Es(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+Z(e,"cg_height")/Math.max(1,Z(e,"wheelbase"))))}return Z(e,"brake_balance")}function qf(e,t=pt(e)){return{front:t.hydraulic.front.location==="inboard",rear:t.hydraulic.rear.location==="inboard"}}function Zf(e){let t=pt(e);return{brakeBalanceFront:Qf(e,t),brakeInboard:qf(e,t)}}function Iv(e,t=pt(e)){if(t.mode==="tyre"||t.regen.distribution!=="wheel"||ft(e.motorModel))return;let r=nn(e),n={front:r.front>=2,rear:r.rear>=2};return n.front||n.rear?n:void 0}function Bs(e){let t=pt(e),r=e.r_dyn.value,n=qf(e,t),o=Qf(e,t),a=Iv(e,t),s=t.mode==="hydraulic"||a?Ev(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 lL=9.81;function Jf(e,t){if(ft(e.motorModel))return()=>0;let r=pt(e),n=Is(t,r.regen);if(r.mode==="hydraulic"){let a=_n({mode:"hydraulic",balanceFront:Es(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"?uL(e):()=>Math.min(.99,Math.max(.01,Z(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 uL(e){let t=e.m.value*lL,r=e.front_mass_diss.value>1?e.front_mass_diss.value/100:e.front_mass_diss.value,n=Z(e,"cg_height")/Math.max(1,Z(e,"wheelbase")),o=1-Math.max(0,Math.min(1,Z(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 _v(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 eh={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"},..._v("front"),..._v("rear")},th={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 rh(e){let t=eh[e];return`${t.label}, ${t.section}`.toLowerCase()}function nh(e){let t=th[e];return t.section?`${t.section} ${t.label.charAt(0).toLowerCase()}${t.label.slice(1)}`:t.label}var Nv=new WeakMap;function rr(e){if(e.brakes)return e.brakes;let t=Nv.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},Nv.set(e,t)}return t}var Pr=e=>_n(rr(e));var fL=Math.PI/180,aa=Object.freeze({tbr:1,preloadN:0}),$l=Object.freeze({tbr:1/0,preloadN:0}),ah=e=>e.faces*e.muClutch*e.rFrictionMm/e.rRampMm;function sh(e,t){if(!(e>0)||Number.isNaN(t))return 0;let r=Math.tan(Math.min(90,t)*fL);return r>0?Math.min(1,e/r):1}function Vv(e){if(e>=1)return 1/0;let t=e>0?e:0;return(1+t)/(1-t)}function Gl(e){return e===1/0?1:e>1?(e-1)/(e+1):0}function sa(e,t){return e.tbr===1/0?1/0:(e.preloadN>0?e.preloadN:0)+Gl(e.tbr)*Math.abs(t)}function Gs(e,t,r){let n=o=>o!==void 0&&o>0&&r>0?o/r:0;switch(e.kind){case"open":return aa;case"spool":return $l;case"independent":return t==="hubs"?aa:$l;case"clutch":{let o=n(e.preloadNm);return t==="hubs"?{tbr:1,preloadN:o}:{tbr:Vv(sh(ah(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 $s(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 Ov=4;function oh(e,t){let r=0;for(let a of e)r=Math.max(r,$s(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,$s(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 Ks(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=$f(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=Nl(b=>Nn(e,b)+Nn(t,c-b),l.lo,l.hi),f=[{m1:l.c1,m2:l.c2}];for(let b=1;b<=Ov&&m!==l.y1;b++){let g=l.y1+(m-l.y1)*b/Ov;f.push({m1:e.cap(g),m2:t.cap(c-g)})}let p=oh(f,aa),d=oh(f,$l);if(!(d>p))return u;let h=(oh(f,{tbr:s,preloadN:i})-p)/(d-p);return Math.min(a,u+(a-u)*Math.min(1,Math.max(0,h)))}function Bv(e,t,r,n,o,a){return ih(e,o,Ks(t,r,n,o,a))}function ih(e,t,r){let n=Math.max(e.xNoLock,r/2),o=t.tbr===1/0||!(e.xLock>n)?0:e.xLock;return e.regenWheel>0?{...e,xNoLock:n,xLock:o,mixedMax:Math.max(e.mixedMax,2*n)}:{...e,xNoLock:n,xLock:o,mixedMax:2*n,regenRoom:a=>2*Math.max(0,n-a)}}function ch(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 $v(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 Kv(e,s,c,d,h,b,n,l,a);s=d,c=b}return null}function Gv(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 Kv(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 Kv(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 Kl(e,t){return Math.abs(e.fx-e.x)>t?e.x:e.fx}var hL=(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:hL(e,t)?n.coast:n.hubs}var Hv=e=>e.tbr>1||e.preloadN>0;var bL=9.81,zv=["FL","FR","RL","RR"],lh=e=>e==="FL"||e==="FR",Hl=e=>lh(e)?"front":"rear",Yv={front:["FL","FR"],rear:["RL","RR"]},Ys=()=>({peak:new Map,freeBrake:new Map}),zs=25;function Hs(e,t){let r=Math.max(0,e)/zs,n=Math.floor(r),o=r-n,a=t(n);return o>0?a+o*(t(n+1)-a):a}var on=1e-4,gL=.05;function Lr(e,t,r,n=Ys(),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=rl(xe(t,S),Math.max(1,A*zs)),i.set(P,L)),L},l=(S,A)=>({aPeak:Hs(A,P=>c(S,P).aPeak),fyPeak:Hs(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*zs);L=St(xe(t,S),D,0,!0,c(S,A)),u.set(P,L)}return L},f=(S,A)=>A>0?Hs(A,P=>m(S,P)):0,p=Pr(e),d=rr(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(Hl(S),L);return St(xe(t,Hl(S)),L,P[S]*D.fyPeak,!0,D)},x=(S,A,P,L,D=!0)=>{let E=te=>{let fe=Math.max(0,A[te]),Y=xe(t,S),J=l(S,fe);return{Fz:fe,a:Math.abs(f(S,fe)),b:J.fyPeak,slide:fe>0?Math.abs(Y.forces({Fz:fe,kappa:-1,alpha:0}).Fx):0,cap:re=>Math.abs(St(Y,fe,re,!0,J))}},$=te=>Math.abs(P[te])*l(Hl(te),Math.max(0,A[te])).fyPeak,[O,W]=Yv[S],I=E(O),_=E(W),V=$(O)+$(W),N=Gf(I,_,V,L,S==="front"?b:g),G=D?N:{...N,xLock:0},K=Bt(e,S,-1),z=K&&Hv(K)?K:void 0;if(!z)return{axle:S,eq:G,cap:G};let j=Number.isFinite(L)?L:I.cap($(O))+_.cap($(W)),q=Bv(G,I,_,V,z,j);return{axle:S,eq:G,cap:q,law:z,strong:()=>I.cap($(O))>=_.cap($(W))?O:W}},M=(S,A,P,L)=>x(S,A,P,L).cap,v=(S,A,P)=>{let L=S.demand,D=p.shares?ra(A,L.front):ta(A,(L.front-L.regenFront)/2,L.regenFront),E=p.shares?ra(P,L.rear):ta(P,(L.rear-L.regenRear)/2,L.regenRear);return{front:Number.isFinite(D)?D:0,rear:Number.isFinite(E)?E:0}},R=S=>({muX:A=>A>0?Math.abs(f(S,A))/A:0,muY:A=>A>0?l(S,A).fyPeak/A:0}),k={front:R("front"),rear:R("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,$=D.cap,O=_s(p,E,$,a),W={arms:F,halfTrack:w,ayDir:Math.sign(S)};for(let I=0;I<2;I++){let _=v(O,E,$),V={};for(let G of zv){let K=Math.max(0,A[G]);V[G]={Fz:K,Fy:Math.abs(P[G])*l(Hl(G),K).fyPeak,Fx:-(lh(G)?_.front:_.rear)/2}}let N=G=>{if(!G.law||!G.strong)return G.cap;let K={axle:G.axle,strong:G.strong(),full:2*G.cap.xNoLock,open:2*G.eq.xNoLock,sense:-1};return ih(G.eq,G.law,Ml(K,V,k,W))};E=N(L),$=N(D),O=_s(p,E,$,a)}return{limit:O,front:E,rear:$}};return{peakAt:l,axle:M,ceiling:(S,A,P)=>{let[L,D]=Yv[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=Le(e,S,0,a,0,A),$,O=fe=>($?.ax!==fe&&($={ax:fe,loads:Le(e,S,(fe+L)/bL,a,0,A)}),$.loads),W=nl(fe=>Uo(P,O(fe),E,l).short,-L,-1),I=P,_={front:0,rear:0},V,N,G=(fe,Y=!0)=>{let J=W.at(fe);D=O(J),I=Uo(P,D,E,l).util;let re=0,pe=0,de=0;for(let ie of zv){let oe=y(ie,D,I);re+=oe,lh(ie)?pe+=oe:de+=oe}if(_={front:Math.abs(pe),rear:Math.abs(de)},p.mode!=="tyre"){let ie=x("front",D,I,Math.abs(pe),Y),oe=x("rear",D,I,Math.abs(de),Y);if(o&&(ie.law||oe.law)){let ue=C(S,D,I,ie,oe);V=ue.limit,N={front:ue.front,rear:ue.rear}}else V=_s(p,ie.cap,oe.cap,a),N={front:ie.cap,rear:oe.cap};re=-V.force}return re/s},K=ch(G,0,on),z=Kl(K,on),j=z;if(V?.lockFront||V?.lockRear){let fe=ch(J=>G(J,!1),0,on);j=Kl(fe,on);let Y=$v(G,fe.x,K.x,on,gL);Y||G(K.x),z=Kl(Y??K,on)}let q=W.edge(),ne=q!==void 0&&z<q;ne&&(z=Math.min(0,q),G(z),j=Math.max(j,z));let te={loads:D,ceiling:_,limit:V,axles:N};return{ax:z,axUnlocked:j,...ne?{edge:q}:{},...te,split:()=>te.limit&&te.axles?v(te.limit,te.axles.front,te.axles.rear):{...te.ceiling}}}}}var Yl=9.81;function yL(e,t,r){let n=Le(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 Uv=(e,t)=>t.mode==="hydraulic"&&!!rr(e).regen;function ia(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&&Uv(e,a)?Xv(e,n):void 0,i=s?.shares??Wv.get(e);i||Wv.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=Qv(c,l,u),f=i.get(m);if(f===void 0){let p=-c*.005,d=l*.25,h=e.massTotal*Math.abs(p)*Yl;if(s){let b=Zv(a,qv(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"?yL(e,p,d):Of(a,h,d);i.size>5e4&&i.clear(),i.set(m,f)}return f}var Wv=new WeakMap;function Wl(e,t,r,n,o=0){let a=Pr(e);if(!Uv(e,a))return;let s=Math.round(Math.max(0,r)/(e.massTotal*Yl)/.005),i=Math.round(Math.max(0,n)/.25);return Zv(a,qv(e,Xv(e,t),s,i,Math.round(o/.01)),Math.max(0,r),n)}var jv=new WeakMap;function Xv(e,t){let r=jv.get(e);r||jv.set(e,r=new WeakMap);let n=r.get(t);return n||r.set(t,n={ev:t,tyres:Ys(),shares:new Map,rooms:new Map,speeds:new Map}),n}var Qv=(e,t,r)=>(r*1001+e)*100003+t;function qv(e,t,r,n,o){let a=Qv(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,Ua(e,i).drag)/(e.massTotal*Yl)},t.speeds.set(n,l));let{cap:u}=l,m=Le(e,c,-r*.005+l.dragG,i),f=Math.abs(c)*e.massTotal*Yl,p=b=>{let[g,y]=b==="front"?["FL","FR"]:["RL","RR"],x=f*(b==="front"?e.frontMassFrac:1-e.frontMassFrac),M=u.peakAt(b,Math.max(0,m[g])).fyPeak+u.peakAt(b,Math.max(0,m[y])).fyPeak,v=x>0&&M>0?Math.min(1,x/M):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 Zv(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 ca={rel:.003,abs:2,kappa:1e-5,iters:12},uh={rel:1e-6,abs:.001,kappa:1e-12,iters:40};function On(e,t,r,n=ca){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),x=Math.abs(y.Fx);if(x<Math.abs(f.Fx)){d={kappa:g,forces:y};break}c=m,l=f,u=p,m=g,f=y,p=x-a}if(p<0){let g=vL(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,x=Math.abs(y)>1e-12?(c*p-m*u)/y:.5*(c+m);x>c&&x<m||(x=.5*(c+m));let M=e(o*x),v=Math.abs(M.Fx)-a;if(h=M,b=o*x,Math.abs(v)<s)break;v<0?(c=x,u=v,p*=.5):(m=x,p=v,u*=.5)}return{kappa:b,forces:h}}var Jv=1e-6,xL=40,RL=(3-Math.sqrt(5))/2;function vL(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-Jv),y=e(t*g),x=-Math.abs(y.Fx);if(x>=m)return{kappa:o,forces:a};[l,f,u,p]=[o,m,r,d],o=g,m=x,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<xL;g++){let y=Jv*Math.abs(o)+1e-10,x=.5*(r+c);if(Math.abs(o-x)<=2*y-.5*(c-r))break;let M=!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=x>=o?y:-y),M=!1}}M&&(h=o>=x?r-o:c-o,b=RL*h);let v=Math.abs(b)>=y?o+b:o+(b>=0?y:-y),R=e(t*v),k=-Math.abs(R.Fx);k<=m?(v>=o?r=o:c=o,u=l,p=f,l=o,f=m,o=v,m=k,i=R):(v<o?r=v:c=v,k<=f||l===o?(u=l,p=f,l=v,f=k):(k<=p||u===o||u===l)&&(u=v,p=k))}return{kappa:o,forces:i}}var jl=e=>Math.max(2,.003*Math.abs(e)),kL=(e,t)=>Math.max(t.abs,t.rel*Math.abs(e)),mh=.5,ML=.03;function SL(e,t,r,n,o){let a=.5*(e.vx+t.vx),s=v=>{let R=(1+v)*a/e.vx-1,k=(1+v)*a/t.vx-1,F=e.at(R),w=t.at(k);return{kappaM:v,kl:R,kr:k,fl:F,fr:w,g:F.Fx+w.Fx-r}},i=kL(r,o),c=Math.max(-mh,Math.min(mh,n)),l=s(c);if(Math.abs(c)>ML){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 R=m.kappaM+u*p;if(Math.abs(R)>mh)break;let k=s(R);if(Math.abs(k.g)<i)return k;if(Math.abs(k.g)<Math.abs(d.g)&&(d=k),Math.sign(k.g)!==Math.sign(m.g)){f=k;break}if(u*(k.g-m.g)<=0)return d;m=k,p*=1.9}if(f===l)return d;let h=m,b=f,g=h.g,y=b.g,x=Math.abs(g)<Math.abs(y)?h:b,M=Math.min(1e-7,o.kappa);for(let v=0;v<30&&Math.abs(b.kappaM-h.kappaM)>M;v++){let R=y-g,k=Math.abs(R)>1e-12?(h.kappaM*y-b.kappaM*g)/R:.5*(h.kappaM+b.kappaM),F=Math.min(h.kappaM,b.kappaM),w=Math.max(h.kappaM,b.kappaM);k>F&&k<w||(k=.5*(F+w));let C=s(k);if(x=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 x}function e1(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 ph(e,t,r,n,o,a=ca){let s=SL(e,t,r,o,a),i=s.fr.Fx-s.fl.Fx,c=sa(n,r);if(Math.abs(i)<=c){let x=r-(s.fl.Fx+s.fr.Fx),M=Math.max(0,Math.abs(x)-jl(r))/2;return{left:{kappa:s.kl,forces:s.fl,want:s.fl.Fx+x/2,short:M},right:{kappa:s.kr,forces:s.fr,want:s.fr.Fx+x/2,short:M},locked:!0,spoolKappa:s.kappaM}}let l=Math.sign(i),u=r/2-l*c/2,m=r/2+l*c/2,f=On(e.at,u,e.seed||s.kl,a),p=On(t.at,m,t.seed||s.kr,a),d=Math.abs(u-f.forces.Fx)>jl(u),h=Math.abs(m-p.forces.Fx)>jl(m),b=Math.max(0,n.preloadN),g=Gl(n.tbr);d&&!h?p=On(t.at,e1(f.forces.Fx,l,b,g),p.kappa,a):h&&!d&&(f=On(e.at,e1(p.forces.Fx,-l,b,g),f.kappa,a));let y=(x,M)=>({kappa:x.kappa,forces:x.forces,want:M,short:Math.max(0,Math.abs(M-x.forces.Fx)-jl(M))});return{left:y(f,u),right:y(p,m),locked:!1,spoolKappa:s.kappaM}}var AL={front:["FL","FR"],rear:["RL","RR"]},FL=Object.freeze({Fx:0,Fy:0,Mz:0});function Ul(e,t,r,n){let o=r;for(let a of["front","rear"]){let[s,i]=AL[a],c=r[s]+r[i],l=Bt(e,a,c);if(!l||!(sa(l,c)>0))continue;let u=xe(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}):()=>FL,vx:Math.max(.05,1-b*n.curvature),seed:0}},d=ph(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,wL=8,CL=1e-6,sn=["FL","FR","RL","RR"],Yt=e=>e==="FL"||e==="FR",an=e=>Yt(e)?"front":"rear";function js(e,t){let r=xe(e,"front"),n=xe(e,"rear");return r===n?Bn(r,t):{front:Bn(r,t),rear:Bn(n,t)}}function Bn(e,t){return of(e,Math.min(t,zt(e)))}var Ql=e=>e==="FL"||e==="RL";function ua(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,ia(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 xh(e,t,r,n){return Math.abs($n(e,t,r,n!==void 0?{steerMaxDeg:n}:{}).peak.steerDeg)}function Rh(e,t,r,n){let o=e.tv;if(!o?.enabled)return 0;let a=v1(o)(t,Math.abs(r),n);return r<0?-a:a}function vh(e,t,r=0,n,o=0,a=0,s){let i=ua(e,{axG:t,driveFrontFrac:a},r,n,o),c=i?i.fx:{FL:0,FR:0,RL:0,RR:0};return i&&s&&n?Ul(e,n,c,s):c}var Us=e=>Ql(e)?-1:1,kh=(e,t,r,n,o)=>t*e.Fy(t*r,n,t*o);function gh(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 TL(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?zo(o,n/se,u?r.FL:r.FR,u?r.FR:r.FL):Yo(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 Gn(e,t,r){let n=(e.toeFrontDeg??0)*se,o=(e.toeRearDeg??0)*se,a=TL(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 Mh(e,t,r){if(r.Fz<=0)return 0;let n=ut(xe(e,an(t))),o=Us(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 t1(e,t,r,n){if(!Dn(e))return null;let o=ut(xe(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:Mh(o,s,i)}}return Ss(e,r/se,a,Jr(o.model),{FL:n.FL.travelMm,FR:n.FR.travelMm})}var r1=()=>({totalNm:[],aligningNm:[],lateralNm:[],longitudinalNm:[],jackingNm:[]});function n1(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 PL=Object.freeze({Fx:0,Fy:0,Mz:0});function o1(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&&sa(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}=gh(e),h=o1(e,"front",l),b=o1(e,"rear",l),g={front:0,rear:0},y=i!==void 0&&i>0&&Number.isFinite(i)?i:null,x=Y=>y===null?r:Math.sqrt(Math.max(0,Y)*y),M=ut(xe(t,"front")),v=ut(xe(t,"rear")),R=e.trackFront/2e3,k=e.trackRear/2e3,F=!!(e.kinFront&&e.kinRear),w=F&&y===null?tn(e,e.kinFront,e.kinRear,r):null,C=NaN,T=null,S=Y=>{if(!F)return null;if(y===null)return w;let J=x(Y);return J!==C&&(C=J,T=tn(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),$=!!(L?.toePerMz||D?.toePerMz),O=Y=>Yt(Y)?L:D,W={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,_=Y=>{let J=Y/r,re=y===null?n+f*J/r:n+f/y,pe=y===null?n-p*J/r:n-p/y,de=S(Y),ie=x(Y),oe=de?de(Y/Me,u,n/se,o/se):null,ue=oe?{FL:oe.FL.travel,FR:oe.FR.travel}:void 0,Ve=el(e,Y/Me,u,ie,n/se,o/se,ue,oe?.steeringJacking),Ae=Ve.loads;I=Ve.overturned;let le=Gn(e,o,ue),Re=le.steer,we=0,Ke=be=>{let Fe=Math.max(0,Ae[be]),ye=Us(be),me=Yt(be)?M:v,Te=O(be),Se=0,He=0;if(Te){let Mn=W[be];Se=Te.toePerFy*Mn.fy+Te.toePerFx*Mn.fx+Te.toePerMz*Mn.mz,He=Te.camberPerFy*Mn.fy+Te.camberPerFx*Mn.fx}let Ue=Re[be]+(oe?ye*oe[be].bumpToe*se:0)+ye*Se*se,Kt=Ue-(Yt(be)?re:pe),kn=(oe?oe[be].camberRoad:0)*se+ye*(le.camber[be]+He)*se;return{Fz:Fe,mir:ye,t:me,gains:Te,complianceToe:Se,steerK:Ue,slip:Kt,camberRad:kn}},je=(be,Fe)=>{let ye=y===null?J/r:1/y,me=Yt(be)?f:-p,Te=(Ql(be)?1:-1)*(Yt(be)?R:k),Se=(Math.cos(n)-Te*ye)*Math.cos(Fe.steerK)+(Math.sin(n)+me*ye)*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}):()=>PL,vx:Math.max(.05,Se),seed:P[be]}};for(let be=0;be<(E?wL:1);be++){we=0;let Fe=0,ye={};for(let me of sn){let Te=Yt(me)?h:b;if(Te&&!ye[me]){let[Ao,Et]=Yt(me)?["FL","FR"]:["RL","RR"],Mc=Ke(Ao),iy=Ke(Et),cy=an(me),vp=ph(je(Ao,Mc),je(Et,iy),Te.F,Te.law,g[cy],uh);g[cy]=vp.spoolKappa,ye[Ao]={w:Mc,share:vp.left},ye[Et]={w:iy,share:vp.right}}let Se=ye[me]?.w??Ke(me),{Fz:He,mir:Ue,t:Kt,gains:kn,complianceToe:Mn,steerK:gp,slip:yp,camberRad:xp}=Se,Ya=l?.[me]??0,ko,Mo=0,Rp=0,kc=0,So=ye[me]?.share;if(So)P[me]=So.kappa,Rp=So.kappa,Mo=So.forces.Fx,kc=So.short,ko=Ue*So.forces.Fy;else if(Ya===0||He<=0)ko=kh(Kt,Ue,yp,He,xp),kc=He<=0?Math.abs(Ya):0;else{let Et=On(Mc=>Kt.forces({Fz:He,kappa:Mc,alpha:Ue*yp,gamma:Ue*xp}),Ya,P[me],uh);P[me]=Et.kappa,Rp=Et.kappa,Mo=Et.forces.Fx,kc=Math.max(0,Math.abs(Ya-Mo)-Math.max(ca.abs,ca.rel*Math.abs(Ya))),ko=Ue*Et.forces.Fy}if(A[me]={Fz:He,travelMm:oe?.[me].travel??0,steerRad:gp,slipRad:yp,camberRad:xp,Fy:ko,Fx:Mo,kappa:Rp,fxShort:kc,lifted:Ve.lifted[me]},kn){let Ao=$&&kn.toePerMz?Mh(Kt,me,A[me]):0;W[me]={fy:-Ue*ko,fx:Mo,mz:-Ue*Ao*1e3};let Et=W[me];Fe=Math.max(Fe,Math.abs(kn.toePerFy*Et.fy+kn.toePerFx*Et.fx+kn.toePerMz*Et.mz-Mn))}we+=ko*Math.cos(gp)+Mo*Math.sin(gp)}if(Fe<CL)break}return we/d},V=Y=>{let J=Le(e,0,u,Y,0,o/se);return J.FL+J.FR+J.RL+J.RR},N=Math.max(20,3.5*V(r)/d);if(y!==null){N=4*Me;for(let Y=0;Y<8;Y++){let J=Math.min(40*Me,3.5*V(x(N))/d);if(J<=N)break;N=J}N=Math.max(20,N)}let G=Y=>_(Y)-Y,K=Math.max(.001,N*1e-4),z=(Y,J,re,pe)=>{let de=Y,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),we=Math.min(de,ie),Ke=Math.max(de,ie);Re>we&&Re<Ke||(Re=.5*(de+ie));let je=G(Re);if(Ve=Re,Math.abs(je)<1e-4||Ke-we<1e-6)break;je<0==oe<0?(de=Re,oe=je,ue*=.5):(ie=Re,ue=je,oe*=.5)}return Ve},j=(Y,J,re,pe=!1)=>{let de=(Ae,le)=>re>0?Ae>0&&le<0:le>0&&Ae<0,ie=Y,oe=J,ue=Y+re*Math.min(Math.abs(J),N);if(!pe&&Math.abs(ue-Y)>K){let Ae=G(ue);if(de(oe,Ae))return{root:z(ie,oe,ue,Ae),last:ie};ie=ue,oe=Ae}let Ve=pe?N/24:Math.max(N/24,Math.abs(ue-Y)/4);for(let Ae=1;Ae<=24;Ae++){let le=ie+re*Ve;if(Math.abs(le)>N)break;let Re=G(le);if(de(oe,Re))return{root:z(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}},q=c??null;if(c===void 0&&a!==void 0&&Number.isFinite(a)&&Math.abs(a)<=N){let Y=G(a);if(Math.abs(Y)<=1e-4)G(a+K)<0&&G(a-K)>0&&(q=a);else{let J=j(a,Y,Math.sign(Y)).root;q=J!==null&&(J===0||Math.sign(J)===Math.sign(a))?J:null}}let ne=q===null;if(q===null){let Y=G(0),J=G(K),re=Math.abs(Y)<=1e-4,pe=re?y!==null?1:o!==0?Math.sign(o):J>0?1:-1:Math.sign(Y),de=re?pe*K:0,ie=re?pe>0?J:G(-K):Y,oe=j(de,ie,pe);q=oe.root??(re?0:oe.last)}let te=_(q);if(ne&&o!==0&&y===null){let Y=Math.sign(o);if(q*Y<=0||(A.RL.Fy+A.RR.Fy)*Y<0){let J={...A},re=I,pe=Y*Math.max(q*Y+K,n*Y*r*r/p),de=null;if(pe*Y<N){let ie=G(pe);if(ie*Y>0)de=j(pe,ie,Y).root;else{let oe=pe+Y*N/24,ue=G(oe);(ue-ie)*Y>0&&(de=j(oe,ue,Y,ue*Y<=0).root)}}de!==null&&de*Y>0?(q=de,te=_(q)):(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 Y=J=>(Ql(J)?1:-1)*(Yt(J)?R:k);for(let J of sn){let re=A[J],pe=Yt(J)?f:-p;fe+=pe*re.Fx*Math.sin(re.steerRad)-Y(J)*re.Fx*Math.cos(re.steerRad)}}return y!==null&&q<-1e-6?{ay:NaN,cn:NaN,wheels:A,overturned:I,res:NaN}:{ay:q/Me,cn:fe/(d*Me*m),wheels:A,overturned:I,res:te-q}}function LL(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 x=u(h,y);if(Math.abs(x.cn)<1e-5)return{beta:h,trimmed:!0};let M=y===void 0?void 0:x.ay,v={pos:{b:h,cn:x.cn,ay:M},neg:{b:h,cn:x.cn,ay:M}},R=null,k=h,F=Math.abs(x.cn);for(let w=0;w<b.length&&!R;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),k=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=a1(u,P),D=u(L,C.ay);if(Math.abs(D.cn)<l&&m(D.ay))return R=P,{beta:L,trimmed:!0}}C.b=S,C.cn=A.cn,y!==void 0&&(C.ay=A.ay)}return R?{beta:a1(u,R),trimmed:!0}:g?{beta:k,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=DL(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 a1(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 DL(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<EL;f++){let p=i(c+dh,l),d=i(c,l+fh),h=(p.r-u.r)/dh,b=(d.r-u.r)/fh,g=(p.c-u.c)/dh,y=(d.c-u.c)/fh,x=h*y-b*g;if(!Number.isFinite(x)||x===0||Math.abs(x)<OL*(Math.abs(h*y)+Math.abs(b*g)))return null;if(f===0)m=Math.sign(x);else if(Math.sign(x)!==m)return null;if(Math.abs(u.r)<=1e-4&&Math.abs(u.c)<=1e-5)return{beta:c,ay:l};let M=(u.c*b-u.r*y)/x,v=(u.r*g-u.c*h)/x,R=Math.min(1,IL/Math.max(Math.abs(M),1e-300),_L/Math.max(Math.abs(v),1e-300));if(c+=R*M,l+=R*v,Math.abs(c-o)>NL||Math.abs(c)>s||l*a<0)return null;u=i(c,l)}return null}var EL=8,dh=1e-5,fh=.001,IL=1*se,_L=2,NL=5*se,OL=.5;function p1(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 sn){let h=c.wheels[d],b=xe(t,an(d)),g=zt(b),y=b.muY(Math.min(h.Fz,g)),x=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:Mh(b,d,h),gripUtil:y*h.Fz>0?Math.hypot(h.Fy/(y*h.Fz),x*h.Fz>0?h.Fx/(x*h.Fz):0):0,...h.Fz>g?{pastTurnover:!0}:{},lifted:h.lifted}}let f=Ss(e,o/se,u,Jr(xe(t,"front").model),{FL:c.wheels.FL.travelMm,FR:c.wheels.FR.travelMm}),p=Gn(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=Vn(e,t,i,n,o,a,s);return n!==0&&o?.driving===void 0&&(c.driving=ZL(e,t,i,c,a,s)),c}function Vn(e,t,r,n,o,a,s){let i=n*se,c=ua(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}=LL(e,t,r,i,u,l,c,s),d=p1(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)<=VL,h}var VL=3;function $n(e,t,r,n={}){let o=Math.max(8,r),a=n.direction??1,s=n.yawDemandCn??0,i=n.steerMaxDeg??BL,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 R=hh.get(e)?.get(t)?.get(l);if(R)return R}let u=(R,k)=>k.trimmed&&Math.abs(k.beta-R.beta)<=ql&&Math.abs(k.ay-R.ay)*Me<=Zl,m=!1,f=(R,k)=>{let F=Vn(e,t,o,a*R,k,c(a*R),s);return u(k,F)?(F.driving=!0,F):(m=F.overturned,null)},p=[Vn(e,t,o,0,void 0,c(0),s)],d=null,h=!1,b,g=R=>{let k=p.length-1;for(;k>1&&R.sb*(p[k].beta-p[k-1].beta)>=0;)k--;let F=a*(R.state.ay-p[k].ay)>0,w=C=>R.sb*(C.beta-R.state.beta)>0||a*C.steerDeg>=a*R.state.steerDeg||F&&a*C.ay>=a*R.state.ay;for(;p.length>Math.max(2,k)&&w(p[p.length-1]);)p.pop();b={state:R.state,stall:p[p.length-1]},p.push(R.state),d=Math.abs(R.state.steerDeg)},y=(R,k=!1)=>k||XL(p[p.length-1],R)?QL(e,t,o,a,p,R,c,s):null,x=p[0].trimmed?p[0]:null;if(!x){let R=0;for(let k=s1;k<=i&&!x;k+=s1){let F=Vn(e,t,o,a*k,void 0,c(a*k),s);if(F.trimmed){let w=k;x=F;for(let C=0;C<6;C++){let T=.5*(R+w),S=Vn(e,t,o,a*T,void 0,c(a*T),s);S.trimmed?(w=T,x=S):R=T}}else R=k}x&&(x.driving=!0,p.push(x))}if(x){let R=Math.abs(x.steerDeg),k=Math.min(bh,100/(o*o)),F=x;for(;R<i;){let w=Math.min(i,R+k),C=f(w,F);if(C){let L=y(C);if(L){g(L);break}if(p.push(C),w>=i||R1(e,a*w))break;Math.abs(C.beta-F.beta)<.5*ql&&Math.abs(C.ay-F.ay)*Me<.5*Zl&&(k=Math.min(bh,1.5*k)),R=w,F=C;continue}if(k>$L){k*=.5;continue}let T=m,S=!1,A=null;for(let L of GL){let D=Math.min(i,R+L);if(D<=R)continue;let E=f(D,F);if(E){if(A=y(E,!0),A)break;p.push(E),R=D,F=E,k=Math.min(bh,100/(o*o)),S=!0;break}}if(S)continue;if(A){g(A);break}d=R,h=T;let P=T?null:UL(e,t,o,a,p,c,s);P&&g(P);break}}else d=0;let M=p[0];for(let R of p)a*R.ay>a*M.ay&&(M=R);let v={states:p,foldDeg:d,rollover:h,peak:M,...b?{fold:b}:{}};if(l!==null){let R=hh.get(e);R||(R=new WeakMap,hh.set(e,R));let k=R.get(t);k||(k=new Map,R.set(t,k)),k.size>256&&k.clear(),k.set(l,v)}return v}var hh=new WeakMap,BL=90,ql=1.5,Zl=2.5,bh=5,$L=.002,GL=[.5,1],s1=2.5,d1=.01,Dr=.001,KL=.05,HL=.25,zL=5,YL=2,i1=1e-8,WL=1e-7,jL=1e-6;function f1(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,ua(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)<i1;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 x=2*Math.abs(f-u)+.001;if(y=f+Math.max(-x,Math.min(x,y-f)),u=f,m=p,f=y,p=l(f),Math.abs(f-o.steerDeg)>YL)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,x=p.g;for(let M=0;M<60&&x!==0&&Math.abs(y-b)>i1;M++){let v=(b*x-y*g)/(x-g),R=l(v);if(h={x:v,ay:R.ay},R.g===0)break;Math.sign(R.g)===Math.sign(g)?(b=v,g=R.g,x*=.5):(y=v,x=R.g,g*=.5)}}else if(!d())return null;return Math.abs(h.ay-o.ay)*Me>Zl?null:{steerDeg:h.x,ay:h.ay}}function Ws(e,t,r,n,o){let a=p1(e,t,r,n.beta*se,n.steerDeg*se,n.ay*Me,ua(e,o(n.steerDeg),r,t));return{...a,trimmed:!a.overturned,driving:!a.overturned}}function UL(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=h1(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,x=null;for(let R=d1;Math.abs(g.beta-c.beta)<=ql;R*=1.5){let k=f(g.beta+y*R);if(!k)return null;if(n*k.steerDeg<=n*g.steerDeg){x=k;break}b=g,g=k}if(!x)return null;let M=b1(f,n,b,g,x);if(!M)return null;let v=Ws(e,t,r,M,a);return!v.trimmed||Math.abs(v.beta-c.beta)>ql||Math.abs(v.ay-c.ay)*Me>Zl?null:{state:v,sb:m}}function h1(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=f1(e,t,r,s,i,n,o);if(!c)return null;let l={beta:s,...c};return a.push(l),l}}function XL(e,t){let r=Math.abs(t.beta-e.beta);return r>HL&&r>zL*Math.abs(t.steerDeg-e.steerDeg)}function QL(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=h1(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 x=d1;f*(a.beta-g.beta)>0;x=Math.min(KL,1.5*x)){let M=p(f*(a.beta-g.beta)>x?g.beta+f*x:a.beta);if(!M)return null;let v=n*M.steerDeg<=n*g.steerDeg;if(!y)v&&(y=[b,g,M]);else if(!v){let R=b1(p,n,...y);if(!R)return null;let k=Ws(e,t,r,R,s);return k.trimmed?{state:k,sb:f}:null}b=g,g=M}return null}function b1(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)),x=(c.beta-u.beta)*y-(c.beta-l.beta)*g;y=2*(y-g),y>0&&(x=-x),y=Math.abs(y);let M=m;if(m=f,Math.abs(x)<Math.abs(.5*y*M)&&x>y*(s-c.beta)&&x<y*(i-c.beta)){f=x/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=y1*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 Sh(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 Ws(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 R of u)Math.abs(R.beta-g)<Math.abs(y.beta-g)&&(y=R);let x=f1(e,t,r,g,y,i,c);if(!x)return null;let M={beta:g,...x};u.push(M),h=M;let v=l(M);if(Math.abs(v)<("steerDeg"in a?WL:jL))break;v<0?(m=M,p=v,d*=.5):(f=M,d=v,p*=.5)}return Ws(e,t,r,h,i)}function qL(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 Sh(e,t,r,n.fold,a,{steerDeg:o});let u=typeof a.op=="function"?a.op(o):a.op,m=Vn(e,t,r,o,l,u,a.yawDemandCn??0);return m.driving?m:null}function ZL(e,t,r,n,o,a){if(!n.trimmed)return!1;let s=n.steerDeg<0?-1:1,{states:i}=$n(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 cn(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=$n(e,t,a,{direction:s,op:o}),{fold:u}=l;if(u&&Math.abs(u.state.steerDeg)<=la){if(i>Math.abs(u.state.ay))return l1(e,t,a,s,i,o);if(i>Math.abs(u.stall.ay)){let b=Sh(e,t,a,u,{direction:s,op:o},{ayG:i});if(b)return b}}let m=l.states.filter(b=>Math.abs(b.steerDeg)<=la),f=m[m.length-1],p=l.states.length>m.length;p&&Math.abs(f.steerDeg)<la&&m.push(c(la,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 c1(m[d-1],m[d],i,c);let h=g1(m,c,void 0,p||l.foldDeg===null);return h.ay>=i?c1(h.below,h.state,i,c):l.foldDeg!==null&&l.foldDeg<la?l1(e,t,a,s,i,o):h.state}var la=20;function c1(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)<=JL||a.steer-o.steer<=eD)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 JL=1e-9,eD=1e-7;function g1(e,t,r,n=!1){let o=r??0;if(r===void 0)for(let R=1;R<e.length;R++)Math.abs(e[R].ay)>Math.abs(e[o].ay)&&(o=R);let a=e[Math.max(0,o-1)],s=Math.abs(e[o].steerDeg),i=tD/4,c,l,u,m,f,p,d,h,b=null,g;if(o>0&&o<e.length-1){let R=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(R.steerDeg),u=s,m=-Math.abs(e[o].ay);let[k,F]=Math.abs(a.ay)>=Math.abs(R.ay)?[a,R]:[R,a];f=Math.abs(k.steerDeg),p=-Math.abs(k.ay),d=Math.abs(F.steerDeg),h=-Math.abs(F.ay)}else{let R=Math.abs(e[o].lockDeg??e[o].steerDeg),k=R-rD,F=o>0&&n&&k>Math.abs(a.steerDeg)?t(k,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=R,u=k,m=-Math.abs(F.ay),b=F,f=R,p=-Math.abs(e[o].ay),d=c,h=-Math.abs(a.ay)}let y=l-c,x=0;for(let R=0;R<100;R++){let k=.5*(c+l);if(Math.abs(u-k)<=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=x,Math.abs(P)<Math.abs(.5*A*L)&&P>A*(c-u)&&P<A*(l-u)){x=P/A;let D=u+x;(D-c<2*i||l-D<2*i)&&(x=k>=u?i:-i),F=!1}}F&&(y=u>=k?c-u:l-u,x=y1*y);let w=Math.abs(x)>=i?u+x:u+(x>=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 M=b??t(s,a),v=Math.abs(M.steerDeg)>s?e[o]:a;return{state:M,below:v,ay:Math.abs(M.ay)}}var tD=.001,rD=.01,y1=(3-Math.sqrt(5))/2;function l1(e,t,r,n,o,a){let s=l=>Math.abs(Er(e,t,r,n*l,void 0,a).ay),i=0,c=la;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 Ah(e,t,r,n,o){let a=cn(e,t,r,n,o);return a.steering?Math.abs(a.steering.totalNm):NaN}function Fh(e,t,r,n,o){if(!Dn(e))return NaN;let a=n<0?-1:1,s=Math.abs(n),i=cn(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 yh(e,t,r,n,o,a){let s=Math.max(8,r),i=wt(e,t,s,n*se,o*se,void 0,ua(e,a,s,t));return{ay:i.ay,cn:i.cn}}function wh(e,t,r,n,o){let a=Math.max(8,r),s=cn(e,t,a,n,o),i=.5,c=yh(e,t,a,s.beta+i,s.steerDeg,o).cn,l=yh(e,t,a,s.beta-i,s.steerDeg,o).cn;return(c-l)/(2*i*se)*e.massTotal*Me*(e.wheelbase/1e3)}function Ch(e,t,r,n){let o=Math.max(8,r),{branch:a,opts:s}=nD(e,t,o,n);return x1(e,t,o,a,s)}function nD(e,t,r,n){if(!e.tv?.enabled){let s=n?{op:n}:{};return{branch:$n(e,t,r,s),opts:s}}let o=xh(e,t,r),a={op:s=>{let i=Rh(e,r,s,o);return i===0?n:{axG:n?.axG??0,driveFrontFrac:n?.driveFrontFrac,tvRearDiffN:i}}};return{branch:$n(e,t,r,a),opts:a}}function x1(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 Ws(e,t,r,n.peak,a);let i=(l,u)=>Vn(e,t,r,l,u,a(l),s),c=n.states[0].driving||!n.peak.driving?n.states:n.states.slice(1);return g1(c,i,c.indexOf(n.peak),n.foldDeg===null).state}function Th(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}=gh(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&&Dn(e),x=y?Jr(xe(t,"front").model):void 0,M=(I,_,V,N)=>V===1?I:I+(_-I)*N/(V-1),v=e.tv?.enabled?xh(e,t,a):0,R=I=>{let _=Rh(e,a,I/se,v);return!n.axG&&_===0?null:ua(e,{axG:n.axG??0,driveFrontFrac:n.driveFrontFrac,tvRearDiffN:_},a,t)},{lf:k,lr:F}=gh(e),w=n.reserves?js(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:k,lr:F}):null,T=[],S={ay:[],cn:[]},A=0;for(let I=0;I<b;I++){let _=M(u,m,b,I),V=R(_),N=[],G=[],K=[],z=[],j=w?{stabil:[],agil:[]}:void 0,q=y?r1():void 0,ne;for(let Y=0;Y<g;Y++){let J=M(c,l,g,Y),re=wt(e,t,a,J,_,ne,V,o);if(ne=Number.isFinite(re.ay)?re.ay*Me:void 0,N.push(re.ay),G.push(re.cn),K.push(J/se),z.push(_/se),j){let pe=C(re.wheels);j.stabil.push(pe.stabil),j.agil.push(pe.agil)}q&&n1(q,t1(e,t,_,re.wheels)),Math.abs(re.ay)>A&&(A=Math.abs(re.ay))}T.push({label:`\u03B4 ${(_/se).toFixed(0)}\xB0`,ay:N,cn:G,betaDeg:K,deltaDeg:z,reserve:j,steering:q});let te=null,fe=1/0;for(let Y=1;Y<G.length;Y++){if(!Number.isFinite(G[Y-1])||!Number.isFinite(G[Y])||G[Y-1]!==0&&G[Y-1]<0==G[Y]<0)continue;let J=G[Y-1]===G[Y]?0:G[Y-1]/(G[Y-1]-G[Y]),re=N[Y-1]+J*(N[Y]-N[Y-1]);if(o===void 0&&_!==0&&Math.abs(re)>=.05&&Math.sign(re)!==Math.sign(_))continue;let pe=Math.abs(K[Y-1]+J*(K[Y]-K[Y-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 _=M(c,l,b,I),V=[],N=[],G=[],K=[],z=w?{stabil:[],agil:[]}:void 0,j=y?r1():void 0,q;for(let ne=0;ne<g;ne++){let te=M(u,m,g,ne),fe=wt(e,t,a,_,te,q,R(te),o);if(q=Number.isFinite(fe.ay)?fe.ay*Me:void 0,V.push(fe.ay),N.push(fe.cn),G.push(_/se),K.push(te/se),z){let Y=C(fe.wheels);z.stabil.push(Y.stabil),z.agil.push(Y.agil)}j&&n1(j,t1(e,t,te,fe.wheels))}P.push({label:`\u03B2 ${(_/se).toFixed(0)}\xB0`,ay:V,cn:N,betaDeg:G,deltaDeg:K,reserve:z,steering:j})}let L=.5*se,D=R(h),E,$;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),$=(wt(e,t,a,d,h+L,void 0,R(h+L),o).cn-wt(e,t,a,d,h-L,void 0,R(h-L),o).cn)/(2*L);else{let I=(N,G)=>wt(e,t,a,N,G,void 0,R(G),o).cn,_=(N,G,K)=>Number.isFinite(N)?(-3*N+4*G-K)/(2*L):(K-G)/L,V=I(d,h);E=-_(V,I(d-L,h),I(d-2*L,h)),$=_(V,I(d,h+L),I(d,h+2*L))}let O=0;if(D&&D.axG){let I=wt(e,t,a,d,h,void 0,D,o),_=0;for(let V of sn)_+=I.wheels[V].fxShort;O=_/Math.abs(e.massTotal*D.axG*Me)}let W=S.ay.reduce((I,_)=>Math.max(I,Math.abs(_)),0);return{isoBeta:P,isoDelta:T,trim:S,maxAy:A,stability:E,control:$,speed:o===void 0?a:Math.sqrt(W*Me*o),...o!==void 0?{radius:o}:{},axG:D?.axG??0,axShortfall:O,...x?{steeringAligningSource:x}:{}}}function R1(e,t){return Gn(e,t*se).atLock}function oD(e,t,r,n,o=Lr(e,t,r)){let a=r,s=e.massTotal,i=sn.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 x=`${g}:${y}`,M=u.get(x);if(M===void 0){let v=Math.max(1,y*zs);M=St(xe(t,g),v,0,!1,c(g,v)),u.set(x,M)}return M},f=(g,y)=>y>0?Hs(y,x=>m(g,x)):0,p=(g,y,x,M)=>{let v=xe(t,g),R=D=>{let E=Math.max(0,x[D]),$=c(g,E);return{Fz:E,a:f(g,E),b:$.fyPeak,slide:0,cap:O=>E>0?St(v,E,O,!1,$):0}},[k,F]=g==="front"?["FL","FR"]:["RL","RR"],w=R(k),C=R(F),T=M[k]*w.b,S=M[F]*C.b,A=w.cap(T)+C.cap(S),P=Ks(w,C,T+S,y,A);return{l:k,r:F,full:P,asHeld:()=>({axle:g,strong:w.cap(T)>=C.cap(S)?k:F,full:P,open:Ks(w,C,T+S,aa,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,x,M=0)=>{let v={FL:0,FR:0,RL:0,RR:0},R=Le(e,g,0,a,0,y),k,F=P=>(k?.ax!==P&&(k={ax:P,loads:Le(e,g,(P+M)/Me,a,0,y)}),k.loads),w=nl(P=>Uo(x,F(P),R,c).short,-M,1),C=x,T=P=>{let L=w.at(P);v=F(L),C=Uo(x,v,R,c).util;let D=0,E=n.diffYaw?{fx:{FL:0,FR:0,RL:0,RR:0},axles:[]}:null;for(let $ of i){let O=l[an($)];if(O){if(Ql($)){let V=p(an($),O,v,C);D+=V.full,E&&(E.fx[V.l]=E.fx[V.r]=V.full/2,E.axles.push(V.asHeld()))}continue}let W=Math.max(0,v[$]),I=c(an($),W),_=St(xe(t,an($)),W,C[$]*I.fyPeak,!1,I);D+=_,E&&(E.fx[$]=_)}if(E){let $={};for(let O of sn){let W=Math.max(0,v[O]);$[O]={Fz:W,Fy:C[O]*c(an(O),W).fyPeak,Fx:E.fx[O]}}for(let O of E.axles)D+=Ml(O,$,h,b(g))-O.full}return D/s},S=Gv(T,-M,on).fx,A=w.edge();return A!==void 0&&S>A&&(S=A,T(S)),{ax:S,loads:v}}}}var Xl=.05,u1=.001,m1=16,Jl=8;function Ph(e,t,r,n){let o=Math.max(Jl,r),a=n.nSteer??7,s=e.tv?.enabled?xh(e,t,o,n.steerMaxDeg):0,i=I=>{let _=Rh(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=$n(e,t,o,l),m=I=>{let _={},V={};for(let N of sn)_[N]=I.wheels[N].slipDeg*se,V[N]=Math.min(1,I.wheels[N].gripUtil);return{steerDeg:I.steerDeg,ayMs:Math.max(0,I.ay*Me),ayG:I.ay,slip:_,util:V,scrub:I.ay>0?aD(I,e.massTotal):0}},f=null,p=I=>{if(f&&I===f.steerDeg)return m(f);let _=qL(e,t,o,u,I,l);if(_)return m(_);let V=u.states[0];for(let N of u.states)N.steerDeg<=I&&(V=N);return m(V)},d=u.peak.driving&&u.peak.ay>0?x1(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:x}=u;if(d&&x&&u.peak===x.state){let I=.995*h/Me,_=u.states.indexOf(x.stall),V=_-1;for(;V>0&&u.states[V].beta===x.stall.beta;)V--;let N=Math.sign(x.stall.beta-u.states[V].beta),G=_;for(;G>0&&u.states[G].ay>=I&&Math.sign(u.states[G].beta-u.states[G-1].beta)!==-N;)G--;u.states[G].ay<I&&(f=Sh(e,t,o,x,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 V=0;V<8&&_-I>.001;V++){let N=.5*(I+_);p(N).ayMs>=.995*h?_=N:I=N}y=_}let M=[];for(let I=0;I<(h>0?a:1);I++){let _=I/(a-1);M.push(p(y*(_+Math.sin(Math.PI/2*_))/2))}M[0].ayMs=0;let v=[],R=[],k=[],F=[],w=Lr(e,t,o,void 0,n.diffYaw===!0),C=oD(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>Xl}},A=I=>C.limitAt(I.ayMs/Me,I.steerDeg,I.util,T+I.scrub).ax,P=M.map(I=>({p:I,axA:A(I),...S(I)})),L=[];for(let I=0;I+1<P.length;I++){let _=P[I],V=P[I+1],N=[];_.locked!==V.locked?N.push({read:S,past:G=>G.locked===V.locked,braking:!0}):(V.axA>_.axA+Xl&&N.push({read:G=>({axA:A(G)}),past:G=>(G.axA??-1/0)>_.axA}),-V.axD>-_.axD+Xl&&N.push({read:S,past:G=>-(G.axD??0)>-_.axD}));for(let{read:G,past:K,braking:z}of N){let j=_.p.steerDeg,q=V.p.steerDeg,ne=null,te=_.axD,fe=V.axD;for(let Y=0;Y<m1&&q-j>u1&&!(z&&Math.abs(fe-te)<=Xl);Y++){let J=.5*(j+q),re=p(J),pe=G(re);K(pe)?(q=J,ne={p:re,r:pe},fe=pe.axD??fe):(j=J,te=pe.axD??te)}if(ne){let{p:Y,r:J}=ne,re=J.axD!==void 0&&J.locked!==void 0?{axD:J.axD,locked:J.locked}:S(Y);L.push({p:Y,axA:J.axA??A(Y),...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,M[M.length-1].ayMs),$=[];for(let I=0;I+1<P.length;I++){let _=P[I],V=P[I+1];if(!(D(_)>=0&&D(V)<0))continue;let N=_.p.steerDeg,G=V.p.steerDeg,K=null,z=null;for(let q=0;q<m1&&G-N>u1;q++){let ne=.5*(N+G),te=p(ne);D({p:te,axA:A(te)})>=0?(N=ne,K=te):(G=ne,z=te)}let j=K??z;j&&j.ayMs>_.p.ayMs&&j.ayMs<V.p.ayMs&&$.push({p:j,axA:-(T+j.scrub),steady:!0,...S(j)})}P.push(...$),P.sort((I,_)=>I.p.steerDeg-_.p.steerDeg);let O=!1;for(let{p:I,axA:_,axD:V,steady:N}of P){let G=v.length-1,K=G>=0&&(N||O?!(I.ayMs>v[G]):I.ayMs-v[G]<E);O=N===!0&&!K,K?(R[G]=Math.max(R[G],_),k[G]=Math.min(k[G],V)):(v.push(I.ayMs),R.push(_),k.push(V),F.push(I.scrub))}for(let I=v.length-2;I>=0;I--)R[I]=Math.max(R[I],R[I+1]),k[I]=Math.min(k[I],k[I+1]);return{ayMax:v[v.length-1],ay:v,axAccel:R,axDecel:k,axScrub:F,rollover:u.rollover,atLock:d!==null&&R1(e,d.steerDeg)}}function aD(e,t){let r=e.beta*se,n=0;for(let o of sn){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 NW=Math.PI/180,OW={speeds:Array.from({length:23},(e,t)=>8+t),steerMaxDeg:14,steerSteps:29};function k1(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 ma={enabled:!1,kp:3e3,ffLow:150,ffHigh:300,vLow:18,vHigh:25},v1=e=>k1(e.ffLow,e.ffHigh,e.vLow,e.vHigh);var nr={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"}},sD=["k_yaw","k_roll","k_pitch"];function Xs(e){for(let t of sD)delete e[t];for(let t of Object.keys(nr)){let r=e[t];if(!r){e[t]={...nr[t]};continue}e[t]={...r,label:nr[t].label,unit:nr[t].unit}}return e}function Z(e,t){return e[t]?.value??nr[t].value}function eu(e){let t=(r,n)=>e[r]?.value??n;return{enabled:t("tv_enabled",0)>=.5,kp:t("tv_kp",ma.kp),ffLow:t("tv_ff_low",ma.ffLow),ffHigh:t("tv_ff_high",ma.ffHigh),vLow:t("tv_v_low",ma.vLow),vHigh:t("tv_v_high",ma.vHigh)}}var M1=[10,25,50,100,200,300];function Lh(e,t,r,n,o){let s=M1.map(i=>Math.round(i<=25?r*i:r*25+n*(i-25)));return{id:e,label:t,speedMmS:[...M1],reboundN:s,bumpN:s.map(i=>Math.round(i*o))}}var tu={name:"Generic FS damper",curves:[Lh("c1","Soft",1.6,1,.65),Lh("c2","Medium",3,1.6,.65),Lh("c3","Firm",8,2.4,.65)]};function ru(e){let t=e.curves.length;return t>0?e.curves[Math.floor((t-1)/2)].id:""}var ln=25;function pa(e,t){let r=e.speedMmS,n=e.forceN,o=Math.min(r.length,n.length);if(o===0||!(t>0))return 0;let a=0,s=0;for(let i=0;i<o;i++){let c=r[i],l=n[i];if(t<=c)return s+(l-s)*(t-a)/(c-a);if(i===o-1)return l+Math.max(0,(l-s)/(c-a))*(t-c);a=c,s=l}return 0}function S1(e,t){return t>=0?pa(e.rebound,t):-pa(e.bump,-t)}function A1(e,t,r){return t*S1(e,t*r)}var Dh=(e,t)=>e.curves.find(r=>r.id===t);function Qs(e,t){let r=Dh(e,ru(e)),n=(t&&Dh(e,t.bump))??r,o=(t&&Dh(e,t.rebound))??r;return{bump:{speedMmS:n?.speedMmS??[],forceN:n?.bumpN??[]},rebound:{speedMmS:o?.speedMmS??[],forceN:o?.reboundN??[]}}}var nu=5e3;function qs(e,t){let r=t>0?t:1,n=[],o=[],a=e.bump.speedMmS.map(c=>c/r).filter(c=>c<nu),s=e.rebound.speedMmS.map(c=>c/r).filter(c=>c<nu),i=c=>{n.push(c),o.push(A1(e,r,c))};i(-nu);for(let c=a.length-1;c>=0;c--)i(-a[c]);i(0);for(let c of s)i(c);return i(nu),{kind:"map",input:"velocity",x:n,y:o}}var Eh=64;function Zs(e,t,r){let n=t>0?t:1,o=Math.max(r,1e-6),a=0;for(let s=0;s<Eh;s++){let i=Math.sin((s+.5)*Math.PI/Eh),c=n*o*i;a+=n*(pa(e.rebound,c)+pa(e.bump,c))*i}return a*(Math.PI/Eh)/(Math.PI*o)}function Kn(e,t,r,n,o=e){let a=(c,l,u)=>{if(!c||c.curves.length===0)return;let m=Qs(c,l);return{law:m,curve:qs(m,u),rate:Zs(m,u,ln)}},s=a(e,t?.front,r),i=a(o??e,t?.rear,n);return!s&&!i?null:{...s?{front:s}:{},...i?{rear:i}:{}}}var F1=(e,t)=>({...e,y:e.y.map(r=>r*t)}),iD=e=>({...e,x:e.x.map(t=>-t).reverse(),y:e.y.map(t=>-t).reverse()});function Ih(e,t,r){let n=Math.abs(r)>0?Math.abs(r):1,o=Qs(e,t);return{law:o,curve:F1(qs(o,n),.5),rate:Zs(o,n,ln)/2,mr:n,ratio:n,share:.5}}function _h(e,t,r,n,o){let a=n*(Math.abs(r)>0?Math.abs(r):1),s=Qs(e,t),i=F1(qs(s,a),1/n);return{law:s,curve:o?iD(i):i,rate:Zs(s,a,ln)/n,mr:a/n,ratio:a,share:1/n}}function Js(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 ei(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 ri(e){return e.kind==="coil"?2:1}function ti(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 C1(e){return ti(e)/2}function T1(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 w1(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 cD(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 ni(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*ti(e.section)/e.barLength,a=2*o/(n*n),s=C1(e.armSection??e.section),i=3*e.E*s/n**3,c=e.dropLinkRate??1/0;return{rateAtLink:w1([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*ti(e.section)/e.barLength,a=2*o/(n*n),s=3*e.E*T1(e.blade)/n**3,i=e.dropLinkRate??1/0;return{rateAtLink:w1([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*ti(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=cD(e.linkTravel,e.force,t);return{rateAtLink:Math.max(0,n),contributions:{},torsional:0}}}}function ou(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?xd(t,r):1,o=t?Rd(t,r):0,a=ni(e,o).rateAtLink;return{wheelRate:Math.max(0,a*n*n),motionRatio:n,rateAtLink:a}}function oi(e,t){let r=e.damper??0;return!r||e.design.kind==="none"?0:ri(e.design)*r*t*t}var lD=150;function uD(e){return X(e,[0,-.5,1])<-1e-9?U(e,-1):e}function P1(e){let t=e.hardpoints,r=H(t.rockerPivotB,t.rockerPivotA),n=ee(t.rockerPivotA,U(H(t.rockerToDamper,t.rockerPivotA),.6)),o=uD(Q(ae(r,H(t.rockerToDamper,t.rockerPivotA))));return{outer:n,inner:ee(n,U(o,lD)),attach:"rocker"}}function Ct(e,t){let r={};for(let o of _o)r[o]=et($e(e,o));let n={vehicle:e,ctx:r};return t&&(n.kc=qc(n,t)),n}var au=.5;function mD(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 L1=e=>[(e[2][1]-e[1][2])/2,(e[0][2]-e[2][0])/2,(e[1][0]-e[0][1])/2];function su(e,t,r){let n=Ze(t,e.vehicle.config),o=e.ctx[t],a=r.rigid?void 0:{loadedRadius:r.loadedRadius},s=r.state?null:ge(o,r.travel,r.steer,void 0,a),i=r.state??ot(s),c=ge(o,r.travel+au,r.steer,void 0,a),l=ge(o,r.travel-au,r.steer,void 0,a),u=(s?s.ok:r.converged)&&c.ok&&l.ok,m=ot(c),f=ot(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",x=[h,b,p(i,y)],M=C=>mD(x,[p(C,d),p(C,"uprightLower"),p(C,y)]),v=M(m),R=M(f),k=L1(v.rot),F=L1(R.rot),w=[NaN,NaN,NaN];return{solved:u,state:i,at:C=>p(i,C),velocity:C=>u?U(H(v.move(C),R.move(C)),1/(2*au)):w,omega:u?U(H(k,F),1/(2*au)):w}}function Nh(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 D1(e,t,r){let n=su(e,t,gt(e,r)[t]),o=n.at("contactPatch"),a=n.velocity(o);return{solved:n.solved,cp:[o[1],o[2]],vCp:[a[1],a[2]],wx:n.omega[0]}}function E1(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 I1(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 pD(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 dD=.1*Math.PI/180;function _1(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]))*dD<=o*n}function iu(e,t){return!e.valid||!e.cpLeft||!e.cpRight?!1:_1([e.lateral,e.height],e.cpLeft,e.cpRight,e.sinAngle,t)}function ai(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 fD=1;function N1(e){let t=ai(e);if(!t||!e.cpLeft||!e.cpRight||Math.abs(t.left-t.right)>fD)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 da(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 or(e,t,r){let n=r==="front"?"FL":"RL",o=r==="front"?"FR":"RR",a=D1(e,n,t),s=D1(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=E1(a),c=E1(s),l=I1(a,i),u=I1(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=Nh(a.cp,f,s.cp,p)??pD(a.cp,l,s.cp);if(!g)return{...m,sinAngle:b};let y=s.cp[0]-a.cp[0],x=s.cp[1]-a.cp[1],M=Math.hypot(y,x)||1,v=y/M,R=x/M,k=(a.cp[0]+s.cp[0])/2,F=(a.cp[1]+s.cp[1])/2,w=(g[0]-a.cp[0])*-R+(g[1]-a.cp[1])*v,C=(g[0]-k)*v+(g[1]-F)*R;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:or(e,t,"front"),rear:or(e,t,"rear")}}function cu(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 hD(e,t){return{camber:cu(e.travel,e.camber,t),toe:cu(e.travel,e.toe,t),motionRatio:cu(e.travel,e.motionRatio,t),damperLen:e.damperLen?cu(e.travel,e.damperLen,t):0}}var O1=e=>hD(e,0).motionRatio;function Oh(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 lu(e,t){if(e.kind==="none")return 0;if(e.kind==="tabulated"){let n=a=>bD(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 si(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 bD(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 Vh={kind:"coil",rate:120,motionRatio:.7,gap:5,bothWays:!1};var V1=new WeakMap;function mu(e,t){let r=V1.get(e);r||(r=new Map,V1.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=An(e,t);return r.set(n,a),a}var gD=32,ii=new Map,B1=new WeakMap,yD=1;function xD(e){let t=B1.get(e);return t===void 0&&(t=yD++,B1.set(e,t)),t}function Bh(e,t){if(!t.linkage)return null;let r=Zr(e,t.linkage,t.design.kind),n=`${xD(e)}|${r?"unit":"bar"}|${JSON.stringify(t.linkage)}`,o=ii.get(n);if(o)return o;let a=Go(e,t.linkage,{kind:t.design.kind});return ii.size>=gD&&ii.delete(ii.keys().next().value),ii.set(n,a),a}function zn(e,t,r=0){let n=(o,a)=>{if(!(!o||o.design.kind==="none"))return ou(o.design,Bh(a,o),r).wheelRate};return{front:n(t.arbFrontDesign,e.front),rear:n(t.arbRearDesign,e.rear)}}function fa(e,t){let r=(n,o)=>{if(!n||n.design.kind==="none")return;let a=n.linkage?mu(o,n.linkage).atDesign:void 0;return lu(n.design,a)};return{front:r(t.heaveFrontDesign,e.front),rear:r(t.heaveRearDesign,e.rear)}}function z1(e,t){let r=(a,s)=>{if(!a||a.design.kind!=="coil")return;let i=a.linkage?mu(s,a.linkage).atDesign:void 0;return Oh(a.design,i)??void 0},n=r(t.heaveFrontDesign,e.front),o=r(t.heaveRearDesign,e.rear);return{...n?{front:n}:{},...o?{rear:o}:{}}}function pu(e,t){let r=(o,a)=>o?si(o,$h(o,a)):0,n=(o,a)=>o?oi(o,Gh(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 $h=(e,t)=>e.linkage?mu(t,e.linkage).atDesign:void 0,Gh=(e,t)=>ou(e.design,Bh(t,e),0).motionRatio;function Y1(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=$h(f,p);if(si(f,h)>0)return Ih(n,r?.[d],h??(f.design.kind==="coil"?f.design.motionRatio:1))},s=(f,p,d)=>{if(!f||!o?.curves.length)return;let h=Gh(f,p);if(!(oi(f,h)>0))return;let b=Bh(p,f)!==null;return _h(o,r?.[d],h,ri(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 W1(e,t){let r=t.heaveDamperModel??t.damperModel,n=t.rollDamperModel??t.damperModel,o=(i,c)=>Hn(i)?{source:"none"}:ei(i.config.coilover,c),a=(i,c)=>{if(!i)return{source:"none"};let l=si(i,$h(i,c))>0;return ei(i.coilover,l?r:void 0)},s=(i,c)=>{if(!i||i.design.kind!=="coil")return{source:"none"};let l=oi(i,Gh(i,c))>0;return ei(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 j1(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 Hn=e=>e.config.actuation==="decoupled",Yn="a decoupled axle damps in its heave and roll elements, set below";function U1(e,t,r={}){let n={...t},o=(m,f)=>{let p=n[m];p&&typeof p=="object"&&"value"in p&&(n[m]={...p,value:f})},{front:a,rear:s}=zn(e,t);a!==void 0&&o("arb_front",a),s!==void 0&&o("arb_rear",s);for(let[m,f,p]of[[t.heaveFrontDesign,e.front,"heave_spring_front"],[t.heaveRearDesign,e.rear,"heave_spring_rear"]]){if(!m||m.design.kind==="none")continue;let d=m.linkage?mu(f,m.linkage).atDesign:void 0;o(p,lu(m.design,d))}let i=vD(e,t,r),c=RD(e,i);n.kinFront=c.kinFront,n.kinRear=c.kinRear;let l=SD(e,i);n.steerFront=c.steerFront,Number.isFinite(l.ackermannPct)&&o("ackermann_pct",l.ackermannPct);let u=m=>Hn(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"]])Hn(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"]])Hn(m)&&(o(f,0),n.readouts={...n.readouts,[f]:Yn});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 RD(e,t){return{kinFront:G1(e.front),kinRear:G1(e.rear),steerFront:e.front.measured?void 0:du(e.front,t)}}var $1=new WeakMap;function G1(e){let t=$1.get(e);return t||$1.set(e,t=qo(e)),t}function vD(e,t,r={}){return kD(e,t,r.front,r.rear)}function kD(e,t,r,n){let o=e.front.config.loadedRadius;if(!((er(r??t.tireModel)??0)>0))return o;let a={...t,surveyedRadiusFront:o,surveyedRadiusRear:e.rear.config.loadedRadius};return fu(a,r,n).front??o}var K1=new WeakMap;function du(e,t=e.config.loadedRadius){let r=K1.get(e);r||(r=new Map,K1.set(e,r));let n=r.get(t);if(n)return n;let o=t===e.config.loadedRadius?void 0:{loadedRadius:t},a=Vd(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 H1=new WeakMap;function MD(e){return Ge(e,{travelMin:-1,travelMax:1,steps:3}).samples[1].metrics.motionRatio??1}var uu=e=>e.measured?O1(e.measured):MD(e);function SD(e,t=e.front.config.loadedRadius){let r=()=>e.front.measured?void 0:du(e.front,t);return{...AD(e),get steerFront(){return r()},get ackermannPct(){let n=r();return n?Bd(n,bt(e.front),e.config.wheelbase):Number.NaN}}}function AD(e){let t=H1.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:uu(e.front),mrRear:uu(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:da(a.front),rcGainRear:n||!a?0:da(a.rear),rcFrontValid:r?!0:!!a?.front.valid,rcRearValid:n?!0:!!a?.rear.valid};return H1.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}},q1=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),ar=(e,t,r,n=1/0)=>typeof e=="number"&&Number.isFinite(e)?Math.min(n,Math.max(r,e)):t;function Wn(e){if(q1(e))switch(e.kind){case"open":case"spool":return{kind:e.kind};case"clutch":{let t=xt.clutch;return{kind:"clutch",preloadNm:ar(e.preloadNm,t.preloadNm,0),rampDriveDeg:ar(e.rampDriveDeg,t.rampDriveDeg,1,90),rampCoastDeg:ar(e.rampCoastDeg,t.rampCoastDeg,1,90),faces:Math.round(ar(e.faces,t.faces,0)),muClutch:ar(e.muClutch,t.muClutch,0,1),rFrictionMm:ar(e.rFrictionMm,t.rFrictionMm,1),rRampMm:ar(e.rRampMm,t.rRampMm,1)}}case"torsen":{let t=xt.torsen,r=ar(e.preloadNm,0,0);return{kind:"torsen",tbrDrive:ar(e.tbrDrive,t.tbrDrive,1),tbrCoast:ar(e.tbrCoast,t.tbrCoast,1),...r>0?{preloadNm:r}:{}}}default:return}}function hu(e){if(!q1(e))return;let t=Wn(e.front),r=Wn(e.rear);return t||r?{...t?{front:t}:{},...r?{rear:r}:{}}:void 0}function ci(e){let t=nn(e),r=n=>n>=2?"independent":n===1?"diff":"none";return{front:r(t.front),rear:r(t.rear)}}function li(e){if(!e.driveline)return;let t=ci(e),r=e.r_dyn.value,n=s=>{if(t[s]!=="diff")return;let i=Wn(e.driveline?.[s]);if(!(!i||i.kind==="independent"))return{kind:i.kind,drive:Gs(i,"drive",r),coast:Gs(i,"coast",r),hubs:Gs(i,"hubs",r)}},o=n("front"),a=n("rear");return o||a?{...o?{front:o}:{},...a?{rear:a}:{}}:void 0}var FD={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"}},X1=e=>{let t=e==="front"?"Front":"Rear";return Object.fromEntries(Object.entries(FD).map(([r,n])=>[`${e}.${r}`,{section:t,...n}]))},bu={...X1("front"),...X1("rear")},Q1=e=>e.motorModel?.kind==="ice"?e.motorPlacement==="front"?"front":"rear":null;function Z1(e,t){let r=Q1(t);if(!(!r||Q1(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 gu(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 ha(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 ui(e,t){if(!e)return CD(t);let r=t-en(e,0).camber;return r?{...e,camber:e.camber.map(n=>n+r)}:e}function wD(e){return{kinFront:ui(e.kinFront,Z(e,"camber_front_deg")),kinRear:ui(e.kinRear,Z(e,"camber_rear_deg"))}}function CD(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 J1=9.81,ek=e=>e>1?e/100:e;function ba(e,t,r){let n=t??e.tireModel??Fs(),o=r??e.tireModelRear??n,a={grip:Z(e,"grip_scale"),stiffness:Z(e,"stiffness_scale")},s=Sl(n,a);return{front:s,rear:o===n?s:Sl(o,a)}}function sr(e,t,r){let n=ba(e,t,r),o=Ie(n.front);return ut(n.rear===n.front?o:hl(o,Ie(n.rear)))}function Kh(e,t,r){let n=ek(e.front_mass_diss.value),o=ba(e,t,r),a=Ie(o.front),s=o.rear===o.front?a:Ie(o.rear),i=t??e.tireModel,c=r??e.tireModelRear??i,l=e.m.value*J1*n/2,u=e.m.value*J1*(1-n)/2,m=(i?a.verticalStiffness():0)||Z(e,"tire_vertical_rate"),f=(c?s.verticalStiffness():0)||Z(e,"tire_vertical_rate"),p=er(i)??0,d=er(c)??0,h=e.surveyedRadiusFront&&e.surveyedRadiusRear?gu({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 fu(e,t,r){let n=Kh(e,t,r);return{front:n.standingFront,rear:n.standingRear}}function tk(e,t,r){return Kh(e,t,r).cgStandingRadius}function dt(e,t,r){let n=ek(e.front_mass_diss.value),o=Z(e,"mr_front")||1,a=Z(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}=Kh(e,t,r),g=Bs(e),y=li(e),x=Kn(e.damperModel,e.damperSetup,o,a,e.damperModelRear??e.damperModel),M=e.readouts?.damper_front===Yn,v=e.readouts?.damper_rear===Yn,R={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,Z(e,"cop_long"))),copHeight:Z(e,"cop_height"),...e.aeroModel?{model:e.aeroModel}:{},rideHeightFront:Z(e,"ride_height_front"),rideHeightRear:Z(e,"ride_height_rear")};return{massTotal:e.m.value,frontMassFrac:n,steeringSystem:e.steeringSystem,tv:eu(e),cgHeight:ha(Z(e,"cg_height"),e.cgReference?.standingRadius,d),...d!==void 0?{cgStandingRadius:d}:{},wheelbase:Z(e,"wheelbase"),trackFront:Z(e,"track_front"),trackRear:Z(e,"track_rear"),wheelRateFront:Z(e,"spring_front")*o*o,wheelRateRear:Z(e,"spring_rear")*a*a,tireRate:u,...m!==u?{tireRateRear:m}:{},tireDamping:Z(e,"tire_vertical_damping"),arbFront:Z(e,"arb_front"),arbRear:Z(e,"arb_rear"),brakeBalanceFront:g.balanceFront,brakes:g,...y?{driveline:y}:{},heaveSpringFront:Z(e,"heave_spring_front"),heaveSpringRear:Z(e,"heave_spring_rear"),unsprungPerCorner:Z(e,"unsprung_mass"),unsprungCgHeight:TD(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(Z(e,"rc_front"),e.rcRoad?.gainFront,e.rcRoad?.radiusFront,h),rcHeightRear:Nr(Z(e,"rc_rear"),e.rcRoad?.gainRear,e.rcRoad?.radiusRear,b),corneringStiffnessFront:s.corneringStiffness(c),corneringStiffnessRear:i.corneringStiffness(l),damperFront:x?.front&&!M?x.front.rate:Z(e,"damper_front")*o*o,damperRear:x?.rear&&!v?x.rear.rate:Z(e,"damper_rear")*a*a,...x?.front&&!M?{damperCurveFront:x.front.curve}:{},...x?.rear&&!v?{damperCurveRear:x.rear.curve}:{},aero:R,ackermannPct:Z(e,"ackermann_pct"),toeFrontDeg:Z(e,"toe_front_deg"),toeRearDeg:Z(e,"toe_rear_deg"),yawInertia:Z(e,"I_yaw"),steerFront:e.steerFront,...wD(e)}}function TD(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 yu={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 rk(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 ok={damper_front:`the damper part sets it: its front curve at ${ln} mm/s`,damper_rear:`the damper part sets it (the rear's own, where the car names one): its rear curve at ${ln} mm/s`};function xu(e){let t=!!(e.damperModelId||e.damperModel),r=t||!!(e.damperModelIdRear||e.damperModelRear);return{...t?{damper_front:ok.damper_front}:{},...r?{damper_rear:ok.damper_rear}:{}}}function ak(e,t=e.damperModel,r=e.damperModelRear??t){if(!t&&!r)return e;let n=Z(e,"mr_front")||1,o=Z(e,"mr_rear")||1,a=Kn(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!==Yn&&(i.damper_front=s(e.damper_front,"damper front",a.front.rate/(n*n))),a.rear&&e.readouts?.damper_rear!==Yn&&(i.damper_rear=s(e.damper_rear,"damper rear",a.rear.rate/(o*o))),i}var sk={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 ID={Batteriekapazit\u00E4t:"pack capacity",Rollwiderstandsbeiwert:"rolling-resistance coefficient"},ck=e=>ID[e]??e;function Ru(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:ck(n.label),value:n.value,unit:n.unit})}return t}var _D=[{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"]}],ND=.5,ik=e=>e==="infinite"?1/0:typeof e=="number"?e:null,OD=e=>/front/.test(e)?e.replace("front","rear"):/rear/.test(e)?e.replace("rear","front"):null,f9=(()=>{let e=sk.rows,t=o=>{let a=OD(o),s=ik(e[o]?.score),i=a&&e[a]?ik(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>=ND&&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 Hh={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 lk(e){let t=new Map;for(let a of Ru(e))t.set(a.key,a);let r=new Set,n=[];for(let a of _D){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=Ru(e).filter(a=>!r.has(a.key));return o.length&&n.push({title:"Other",rows:o}),n}var zh={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"},Yh={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"},uk=e=>!!(e.aeroModelId||e.aeroModel);function VD(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 BD=e=>!!(e.batteryModelId||e.batteryModel);function $D(e,t){let r={};return t.geometry&&Object.assign(r,Hh,VD(e)),uk(e)&&Object.assign(r,zh),BD(e)&&Object.assign(r,yu),Object.assign(r,xu(e)),e.readouts&&Object.assign(r,e.readouts),r}function mk(e,t){let r=$D(e,t);return uk(e)||Object.assign(r,Yh),r}function Wh(e){let t=e.cop_long;return Or(t)?1-t.value:.5}function GD(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 KD(e,t){GD(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 vu(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)&&ck(a.label)===t){a.value=r,n=!0;break}}return n&&KD(e,t),n}function ku(e,t,r=0,n,o){let a=()=>({cl:e.c_l.value,cw:e.c_w.value,frontShare:Wh(e),A:e.A.value,platform:null});if(!e.aeroModel)return a();let s=Wr(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:Wh(e),A:s.area,platform:s}}var pk=e=>typeof e=="object"&&e!==null&&typeof e.value=="number"&&typeof e.label=="string";function dk(e,t=e.aeroModel){if(!t)return e;let r=Yr(t,{wheelbase:Z(e,"wheelbase")}).at(Z(e,"ride_height_front"),Z(e,"ride_height_rear")),{cl:n,balanceFront:o}=Gp(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(pk(e.cop_long)?e.cop_long:void 0,nr.cop_long,1-o)};return pk(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 mi={dsTarget:.25,accelStep:.25,vTol:.002,scanSteps:24,seamIters:8,fitSpacing:1},HD=32;function fk(e,t,r){let n=Math.round(e/t);return Math.max(1,Math.min(Number.isFinite(n)?n:1,Math.floor(r/HD)||1))}function at(e){let t=mi,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 hk=Math.PI/180,Mu=.02,bk=new WeakMap;function pi(e){let t=bk.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)*hk,l=(e.bank?.[i]??0)*hk,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 bk.set(e,s),s}function Su(e,t,r){return e.n0[t]+e.k[t]*r*r}function gk(e,t){return e.k[t]<0?Math.sqrt(Math.max(0,e.n0[t])/-e.k[t]):1/0}function yk(e,t){if(!e)return null;let r=1/0,n=-1/0;for(let o=0;o<e.n0.length;o++){let a=Su(e,o,t[o]??0);a<r&&(r=a),a>n&&(n=a)}return r>=1-Mu&&n<=1+Mu?null:{lo:r,hi:n}}var ga=[.1,.25,.5,.75,1,1.25,1.5,2,2.5];function xk(e){let t=e.lo>=1-Mu?1:1-1.25*(1-e.lo)-.05,r=e.hi<=1+Mu?1:1+1.25*(e.hi-1)+.05,n=[...ga].reverse().find(a=>a<=t)??ga[0],o=ga.find(a=>a>=r)??ga[ga.length-1];return ga.filter(a=>a>=n&&a<=o)}function jh(e,t,r){return r<1?Math.max(e,t):Math.min(e,t)}function Rk(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):jh(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 Au(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}=zD(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,x=g>=1?0:n.down,M=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 $=0;T<=0&&$<n.count;$++){let O=C;if(w<L-1e-9?n.best(w)>C&&(n.rpm(w,C)>=n.limitRpm||c[A]>=w*M)?O=C+1:C>0&&w<n.vIdle(C)&&(O=C-1):L<w-1e-9&&C>0&&n.best(l[A])<C&&n.rpm(w,C-1)<=n.limitRpm&&(O=C-1),O===C)break;S=O,O>C?d++:h++,T=O>C?y:x,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 $=o(A,w,g>0?g*n.share(w,C):0),O=Math.min(L,Math.sqrt(Math.max(0,w*w+2*$*t[A]))),W=w+O>0?2*t[A]/(w+O):1/0;if(W<=T)E=O,b+=W,T-=W;else{let I=Math.min(L,Math.max(0,w+$*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 $=w+E>0?2*t[A]/(w+E):0;b+=Math.min($,T),T-=$,T<=0&&(C=S)}w=E}return{v:w,gear:C,tau:T,target:S}},R=n.best(e[0]),k={v:e[0],gear:R,tau:0,target:R};if(r)for(let F=0;F<6;F++){let w=v(k),C=Math.abs(w.v-k.v)<=1e-9&&w.gear===k.gear&&w.target===k.target&&Math.abs(w.tau-k.tau)<=1e-12;if(k=w,C)break}else{let F=v(k);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 zD(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 Uh=.001,Xh=9.81,di=(e,t)=>Qh(e?.gradient?.[t]??0);function Qh(e){return e===0?0:-Xh*Math.sin(e*Math.PI/180)}function mn(e,t){let r=new Array(t);for(let n=0;n<t;n++)r[n]=Qh(e?.[n]??0);return r}var un=(e,t)=>{let r=e?.mu?.[t];return r!=null&&r>0?r:1},jn=(e,t)=>e?.bank?.[t]??0;function YD(e,t,r,n,o,a){let s=e.ay(t,r,un(o,a)),i=jn(o,a);if(!i)return s;let c=i*Math.PI/180,l=n===0?0:-Math.sign(n)*Xh*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)+Xh*Math.sin(r)}function qh(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 Un=(e,t,r)=>t?t(r):e,WD=1e-4;function ya(e,t,r,n,o,a,s){let i=at(r),c=[];for(let l=0;l<t.length;l++){let u=t[l],m=Math.abs(u),f=Un(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:qh(b=>b*b*m-YD(f,b,0,u,n,l),Uh,d,i.scanSteps,Math.min(i.vTol,WD));c.push({v:h,ax:0,ay:h*h*u})}return c}function jD(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=qh(p=>u(p)-t.v,Uh,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 UD(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 vk(e,t,r,n,o,a){let s=at(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,jD(Un(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],s,un(r,m),di(r,m),jn(r,m),a?p=>a(m,p):void 0))}if(u<=s.vTol)break}return c}function kk(e,t,r,n,o,a){let s=at(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,UD(Un(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],un(r,m),di(r,m),jn(r,m),a?a[m]:1))}if(u<=s.vTol)break}return c}function XD(e,t,r){let n=r.load?pi(t):null;if(!n||!r.load)return{pick:r.envelope};let o=t.npts;return{pick:Rk(n,r.load,e,r.envelope),cap:a=>gk(n,a%o),n:(a,s)=>Su(n,a,s)}}function Mk(e,t,r,n,o,a,s){return Au(n,r.ds,o,a,(i,c,l)=>{let u=c*c*r.curvature[i];return Un(e,t,i).axAccel(c,Math.abs(We(u,jn(r,i))),un(r,i),s?l*s[i]:l)+di(r,i)})}function Sk(e,t){return{gear:e.gear.slice(0,t),engineRpm:e.rpm.slice(0,t),shifting:e.shifting.slice(0,t)}}function Ak(e,t,r,n){if(!e.scrub)return{};let o=!1,a=n.map((s,i)=>{let c=Un(e,t,i),l=We(s*s*r.curvature[i],jn(r,i)),u=c.scrub?c.scrub(s,Math.abs(l),un(r,i)):0;return u!==0&&(o=!0),u});return o?{axScrub:a}:{}}function Rt(e,t,r,n={}){let o=at(r),a=t.npts,s=t.closed&&!n.standingStart,{pick:i,cap:c,n:l}=XD(e,t,n),u=n.driveDerate,m=n.brakeFade;if(!s)return QD(e,t,o,n.standingStart===!0,i,u,n.vCeiling,m,c,l,n.shifts);let f=ya(e,t.curvature,o,t,i,n.vCeiling,c),p=vk(e,f,t,o,i,m),d=kk(e,f,t,o,i,u),h=n.shifts?Mk(e,i,t,f.map(M=>M.v),!0,n.shifts,u):void 0;if(h)for(let M=0;M<a;M++)f[M].v=h.v[M];for(let M=0;M<a;M++){let v=f[M];v.ay=v.v*v.v*t.curvature[M];let R=f[(M+1)%a].v;v.ax=(R*R-v.v*v.v)/(2*t.ds[M])}let b=f.map(M=>M.v),g=f.map(M=>M.ax),y=f.map(M=>M.ay),x=0;for(let M=0;M<a;M++){let v=b[M]+b[(M+1)%a];v>0&&(x+=2*t.ds[M]/v)}return{states:f,v:b,ax:g,ay:y,laptime:x,sweeps:{backward:p,forward:d},...l?{loadFactor:b.map((M,v)=>l(v,M))}:{},...Ak(e,i,t,b),...h?Sk(h,a):{}}}function QD(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 x=0;x<p;x++)d[x]=t.curvature[x%m];let h=ya(e,d,r,t,o,s,c);n&&(h[0].v=0);for(let x=f-1;x>=0;x--){let M=h[x],v=h[x+1];if(M.v<=v.v)continue;let R=Un(e,o,x),k=w=>{let C=We(w*w*t.curvature[x],jn(t,x)),T=(i?R.axDecel(w,Math.abs(C),un(t,x),i(x,w)):R.axDecel(w,Math.abs(C),un(t,x)))+di(t,x);return Math.sqrt(Math.max(0,w*w+2*T*t.ds[x]))},F=n&&x===0?M.v:Uh;M.v=qh(w=>k(w)-v.v,F,M.v,r.scanSteps,r.vTol)}for(let x=0;x<f;x++){let M=h[x],v=h[x+1];M.ay=M.v*M.v*t.curvature[x];let R=We(M.ay,jn(t,x));M.ax=Un(e,o,x).axAccel(M.v,Math.abs(R),un(t,x),a?a[x]:1)+di(t,x),v.v=Math.min(v.v,Math.sqrt(Math.max(0,M.v*M.v+2*M.ax*t.ds[x])))}let b=u?Mk(e,o,t,h.map(x=>x.v),!1,u,a):void 0;if(b)for(let x=0;x<p;x++)h[x].v=b.v[x];let g=0;for(let x=0;x<f;x++){let M=h[x].v+h[x+1].v;M>0&&(g+=2*t.ds[x]/M)}let y=h.slice(0,m);for(let x=0;x<m;x++){let M=y[x];M.ay=M.v*M.v*t.curvature[x];let v=x<f?h[x+1].v:M.v;M.ax=t.ds[x]>0?(v*v-M.v*M.v)/(2*t.ds[x]):0}return{states:y,v:y.map(x=>x.v),ax:y.map(x=>x.ax),ay:y.map(x=>x.ay),laptime:g,sweeps:{backward:1,forward:1},...l?{loadFactor:y.map((x,M)=>l(M,x.v))}:{},...Ak(e,o,t,y.map(x=>x.v)),...b?Sk(b,m):{}}}var Fk=(e,t)=>{let r=e[t]?.value;return Number.isFinite(r)&&r>0?r:0};function Xn(e,t,r){let n=e.m.value,o=e.r_dyn?.value??0,a=Fk(e,"I_wheel"),s=e.motorModel?.kind==="ice"?0:Fk(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 Qn(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 fi=36e5,Pk=Math.PI*2,Zh=e=>Math.max(0,Math.min(1,e));function Jh(e){let t=e.motorModel;if(!t){let s=e.effi_pgb?.value??.9;return()=>s}if(t.kind==="simple"){let s=t.efficiency>.01?t.efficiency:.9;return()=>s}if(t.kind==="ice"){let s=t.gearbox.efficiency>.01?t.gearbox.efficiency:.9;return()=>s}let r=wc(t),n=e.gear_ratio.value,o=e.r_dyn.value,a=Math.max(1,Math.round(e.motorCount??e.driven_wheels.value));return(s,i)=>{let c=s*n/o*(60/Pk),l=Math.max(0,i*o/(n*a)),u=r.efficiency(c,l);return u>.01?u:.5}}var wk=new WeakMap;function xa(e){if(e.batteryModel)return e.batteryModel;let t=e.capacity.value,r=e.ocv.value,n=wk.get(e);if(n&&n.capacityAh===t&&n.ocv===r)return n.model;let o=Pp(t,r);return wk.set(e,{capacityAh:t,ocv:r,model:o}),o}function eb(e){let t=e.params,r=Jf(t,Bl(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??=qD(e);let c=Wl(n.inp,n.ev,o,a,i);return c?Math.min(o,c.regenFront+c.regenRear):r(o,a,s)}}var Ck=new WeakMap;function qD(e){let t=e.params,r=Ck.get(t);if(!r){let n=Cr(t);r={inp:dt(n.regen?t:{...t,energy:{...n,regen:!0}}),ev:sr(t)},Ck.set(t,r)}return r}var hi=e=>e.airTempC??At;function Fu(e,t){return e.thermal?e.thermal.startC??t:wo}function Tk(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 Lk=()=>({windingC:[],derate:[],lossW:[],torqueNm:[],ampsRms:[]});function ZD(e){let t=e.motorModel;if(!t?.thermal)return;let r=Lp(t.thermal),n=wc(t),o=e.gear_ratio.value,a=e.r_dyn.value,s=Math.max(1,Math.round(e.motorCount??e.driven_wheels.value));return{th:r,rpm:i=>i*o/a*(60/Pk),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 JD(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 eE(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 tE(e){let{drivenFront:t,drivenRear:r}=Qn(e);return Xn(e.params,t,r)}function Ra(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=Jh(m),y=hr(xa(m)),x=y.chargeC,M=Zh(a??m.soc.value),v=hi(m),R=s??Fu(y,v),k=R,F=0,w=0,C=0,T=0,S=-1,A=-1,P=-1,L=ZD(m),D=L?L.th.startC:0,E=D,$=0,O=1,W=-1,I=0,_=0,V=eb(e),N=m.motorModel?.kind==="ice",G=u?.scrub,K=G?d/tE(e).tractionFactor:0,z=Math.min(t.length,r.length);for(let j=0;j<z;j++){let q=r[j],ne=q*q,te=n[j]-(c?.[j]??0),{cl:fe,cw:Y,A:J}=ku(m,q,te/9.81,b),re=.5*f*fe*J*ne,pe=.5*f*Y*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]:q,Ae=.5*(q+Ve),le=Ae>0?t[j]/Ae:0,Re=0,we=M,Ke=R,je=0,be=0,Fe=le;if(N){oe>0&&(be=ue/g(q,oe),F+=be/fi),l?.netKwh.push(F-w),l?.powerKw?.push(le>0?be/le/1e3:0);continue}if(oe>0){let ye=ue/g(q,oe),me=JD(y,ye,le,M,R);me.short&&S<0&&(S=j),me.cutoff&&A<0&&(A=j);let Te=M*x,Se=Math.min(me.dq,Te),He=me.dq>0?Se/me.dq:1;Se>=Te&&P<0&&(P=j),F+=me.energyJ*He/fi,be=me.energyJ*He,Fe=me.seconds,C+=me.lossJ*He,T+=Se,le>0&&(je=Se/me.seconds),M=Zh(M-Se/x),R=Tk(y,R,me.dq>0&&le>0?Se/le:0,me.lossJ*He,le,v),R>k&&(k=R),Re=oe}else if(o.regen){let ye=u?We(u.ay[j],u.bank?.[j]??0)/9.81:0,me=V(-oe,q,te/9.81,ye),Te=o.regenEfficiency*me*t[j],Se=eE(y,Te,le,M,R),He=(1-M)*x,Ue=Math.min(Se.dq,He),Kt=Se.dq>0?Ue/Se.dq:1;w+=Se.energyJ*Kt/fi,be=-Se.energyJ*Kt,C+=Se.lossJ*Kt,T-=Ue,le>0&&(je=-Ue/le),M=Zh(M+Ue/x),R=Tk(y,R,Ue>0&&le>0?-Ue/le:0,Se.lossJ*Kt,le,v),R>k&&(k=R),Re=-me*Kt}if(l?.netKwh.push(F-w),l?.powerKw?.push(le>0?be/Fe/1e3:0),l?.pack){let ye=l.pack;ye.soc.push(we),ye.amps.push(je),ye.volts.push(y.ocv(we)-je*y.resistance(we,Ke)),ye.cellC.push(Ke)}if(L){let ye=L.rpm(q),me=L.th.derate(ye,D,L.peak(ye));me<O&&(O=me),me<1&&W<0&&(W=j),_+=le,me<1&&(I+=le);let Te=L.torque(Re,ye,me),Se=L.th.lossW(ye,Te,D);$+=Se*le,i&&(i.windingC.push(D),i.derate.push(me),i.lossW.push(Se),i.torqueNm.push(Te),i.ampsRms.push(L.amps(Te))),D=L.th.step(D,Se,le),D>E&&(E=D)}}return{drive:F,regen:w,net:F-w,chargeAh:T/3600,loss:C/fi,socEnd:M,shortAt:S,cutoffAt:A,emptyAt:P,tempEndC:R,tempMaxC:k,...L?{motorTempEndC:D,motorTempMaxC:E,motorLossKwh:$/fi,motorDerateMin:O,motorDerateAt:W,motorDerateTimeFrac:_>0?I/_:0}:{}}}var rE=.5,nE=.02,oE=6;function Dk(e,t,r,n,o,a,s,i){let c=n(),l=1,u=d=>{let h=Lk(),b=Ra(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<oE;d++){let h=n(f);l++;let b=Math.abs(h.laptime-c.laptime);if(c=h,m=u(c),b<nE){p=!0;break}let g=m.trace.derate,y=new Array(f.length);for(let x=0;x<f.length;x++)y[x]=f[x]+rE*((g[x]??1)-f[x]);f=y}return{lap:c,derate:f,solves:l,converged:p,peakWindingC:m.peak,derateTimeFrac:m.frac}}var aE=.1;function Ek(e){let t=e.power_limit_kw?.value??0;return t>0?t*1e3:0}function tb(e,t,r){return e.motorModel?.kind==="ice"?1/0:hr(xa(e)).maxPower(t??e.soc.value,r,Ek(e)).watts}function wu(e,t,r,n){let o=tb(e,r,n);if(!Number.isFinite(o))return 1/0;if(o<=0)return 0;let a=Math.max(aE,t),s=Jh(e),i=o*(e.effi_pgb?.value??.9)/a;return o*s(t,i)/a}var sE=180/Math.PI;function Cu(e,t,r,n){let o=e*t,a=e*(1-t);return o/r-a/n}var Tu=e=>e*9.81*sE;var J9=Math.PI/180;function Pu(e,t,r,n=0){let o=Le(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?Cu(e.massTotal,e.frontMassFrac,2*i,2*c):0,u=Tu(l),m=u>.15?"understeer":u<-.15?"oversteer":"neutral";return{gradient:u,balance:m,cAlphaFront:i,cAlphaRear:c}}var iX=Math.PI/180,cX=180/Math.PI;var Ik=2220446049250313e-31;function lE(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 uE(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 mE(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])<=Ik*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 x=Math.abs(p)+Math.abs(d)+Math.abs(h);if(p/=x,d/=x,h/=x,f===c)break;let M=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(M<=Ik*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 x=h/y;d/=p,h/=p;for(let v=b;v<=a;v++){let R=e[b][v]+d*e[b+1][v];b!==a-1&&(R+=h*e[b+2][v],e[b+2][v]-=R*x),e[b+1][v]-=R*u,e[b][v]-=R*l}let M=a<b+3?a:b+3;for(let v=c;v<=M;v++){let R=l*e[v][b]+u*e[v][b+1];b!==a-1&&(R+=x*e[v][b+2],e[v][b+2]-=R*h),e[v][b+1]-=R*d,e[v][b]-=R}}}}}}while(c<a-1&&a>=0)}return r.map((i,c)=>({re:i,im:n[c]}))}function _k(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 lE(r),uE(r),mE(r)}function Nk(e){let t=[],r=new Array(e.length).fill(!1),n=_k(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 rb(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 pE(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 rb(r,n)}function Lu(e,t=r=>pE(e,r)){return Nk(e).map(r=>({...r,vector:t(r.eigenvalue)}))}function va(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 Ok(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 va(Lu(i),c,0)}function Vk(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=Ok({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 Du(e,t,r){let n=Ce(e);return{front:Vk(e,n,"front",t??n.rideDampingFront),rear:Vk(e,n,"rear",r??n.rideDampingRear)}}var vX=180/Math.PI;var nb=["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},ka=20,Bk=[ce.zFL,ce.zFR,ce.zRL,ce.zRR],$k=[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},ob=10;function Eu(e){let t=Array.from({length:ka},()=>new Array(ka).fill(0)),r=Array.from({length:ka},()=>new Array(ob).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[Bk[i]]-=c,s[$k[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=k=>k?i?k.front:k.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(ka).fill(0);a(g,s,p,h),(d!==0||b!==0)&&a(g,o[s],d,b);let y=e.wheelMass[s],x=e.leverX[s],M=e.leverY[s],v=Bk[s],R=$k[s];for(let k=0;k<ka;k++){let F=g[k];F!==0&&(t[R][k]+=F/y,t[ce.vzBody][k]-=F/e.bodyMass,t[ce.pitchRate][k]+=x*F/n.yy,t[ce.rollRate][k]-=M*F/n.xx)}t[R][v]-=e.tyreRate[s]/y,t[R][R]-=e.tyreDamping[s]/y,r[R][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 ab(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 Gk=ce.rollRate+1;function Kk(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,Gk).map(i=>i.slice(0,Gk));if(!n.every(i=>i.every(Number.isFinite)))return{};let a=Lu(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 rb(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:va(a,s,1),pitch:va(a,s,2),roll:va(a,s,3)}}function Hk(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 Iu(e){let t=Ce(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=Kk(Eu(ab(e)));return{roll:Hk(m.roll,a,s),pitch:Hk(m.pitch,l,u)}}var _u=9.81,Br=Math.PI/180;function zk(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 Ma(e,t,r,n,o){let{wb:a,lf:s,lr:i,m:c}=zk(e),l=0;for(let x=0;x<16;x++){let M=l/r,v=o-n-s*M/r,R=-n+i*M/r,k=Le(e,l/_u,0,r),F=Math.max(0,k.FL+k.FR),w=Math.max(0,k.RL+k.RR),C=t(v,F),T=t(R,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=Le(e,l/_u,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/_u,cn:y/(c*_u*a)}}function sb(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,x,M)=>x===1?g:g+(y-g)*M/(x-1),u=[],m={ay:[],cn:[]},f=0;for(let g=0;g<i;g++){let y=l(-s,s,i,g),x=[],M=[],v=[],R=[];for(let k=0;k<c;k++){let F=l(-a,a,c,k),w=Ma(e,t,o,F,y);x.push(w.ay),M.push(w.cn),v.push(F/Br),R.push(y/Br),Math.abs(w.ay)>f&&(f=Math.abs(w.ay))}u.push({label:`\u03B4 ${(y/Br).toFixed(0)}\xB0`,ay:x,cn:M,betaDeg:v,deltaDeg:R});for(let k=1;k<M.length;k++)if(M[k-1]===0||M[k-1]<0!=M[k]<0){let F=M[k-1]===M[k]?0:M[k-1]/(M[k-1]-M[k]);m.ay.push(x[k-1]+F*(x[k]-x[k-1])),m.cn.push(0);break}}let p=[];for(let g=0;g<i;g++){let y=l(-a,a,i,g),x=[],M=[],v=[],R=[];for(let k=0;k<c;k++){let F=l(-s,s,c,k),w=Ma(e,t,o,y,F);x.push(w.ay),M.push(w.cn),v.push(y/Br),R.push(F/Br)}p.push({label:`\u03B2 ${(y/Br).toFixed(0)}\xB0`,ay:x,cn:M,betaDeg:v,deltaDeg:R})}let d=.5*Br,h=(Ma(e,t,o,d,0).cn-Ma(e,t,o,-d,0).cn)/(2*d),b=(Ma(e,t,o,0,d).cn-Ma(e,t,o,0,-d).cn)/(2*d);return{isoBeta:p,isoDelta:u,trim:m,maxAy:f,stability:h,control:b,speed:o}}function dE(e){return!e.corneringStiffnessFront||!e.corneringStiffnessRear?null:{Cf:2*e.corneringStiffnessFront,Cr:2*e.corneringStiffnessRear}}function bi(e,t){let r=dE(e);if(!r)return null;let{Cf:n,Cr:o}=r,{wb:a,lf:s,lr:i,m:c}=zk(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,x,M;if(g<0)y=h/2,x=Math.sqrt(Math.max(0,b)),M=x>0?-h/(2*x):1;else{let P=Math.sqrt(g);y=Math.max((h+P)/2,(h-P)/2),x=Math.sqrt(Math.abs(b)),M=x>0?-h/(2*x):1}let v=h<0&&b>0,R=Cu(c,e.frontMassFrac,n,o),k=Tu(R),F=k>.15?"understeer":k<-.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+R*u*u);return{stable:v,yawFreq:x/(2*Math.PI),dampingRatio:M,eigReal:y,understeerGradient:k,balance:F,characteristicSpeed:T,criticalSpeed:S,yawRateGain:A}}var Yk=Math.PI/180;function Uk(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 Wk(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 Xk(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 Qk(e,t,r){let n=e.isoDelta[0],o=(n.betaDeg[1]-n.betaDeg[0])*Yk||1,a=e.isoDelta.length>1?(e.isoDelta[1].deltaDeg[0]-e.isoDelta[0].deltaDeg[0])*Yk:1,s=R=>Xk(e,t,r,R),i=s((R,k)=>R.ay[k]),c=s((R,k)=>R.cn[k]),l=s((R,k)=>R.betaDeg[k]),u=s((R,k)=>R.deltaDeg[k]),m=s((R,k)=>Wk(R.cn,k,o)),f=s((R,k,F)=>Wk(e.isoDelta.map(w=>w.cn[k]),F,a||1)),p=Math.max(1e-6,e.maxAy),d=Math.abs(i)/p,h=Math.max(1e-6,...e.isoDelta.flatMap(R=>R.cn.filter(Number.isFinite).map(Math.abs))),b=Math.abs(c)/h,g=i===0?c:c*Math.sign(i),y=[];y.push(`${Uk(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 x=Math.abs(e.stability)>1e-9?m/e.stability:1;x<.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."):x<.85?y.push(`Yaw stiffness is down to about ${(100*x).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*x).toFixed(0)} %), so the car still opposes a change in body slip about as firmly as it does in a straight line.`);let M=Math.abs(e.control),v=M>1e-9?Math.abs(f)/M: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 jk=1e-4;function ib(e){let t=null,r=f=>{if(!t)return!0;let p=Math.abs(f),d=Math.abs(t.ay);return p>d*(1+jk)?!0:p<d*(1-jk)?!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=Qk(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 fE=["tv_kp"];function qk(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"},...fE.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 hE=qk(0);function Zk(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 bE=Zk(0);var gE=9.81;function yE(e){let t=e.wheelbase/1e3;return{lf:t*(1-e.frontMassFrac),lr:t*e.frontMassFrac}}function gi(e,t,r,n){let o=t.tire;if(!o)return null;let s=(r==="limit"?Ch(e,o,t.speed):cn(e,o,t.speed,t.ayG)).wheels;return Rr(n??Bn(o,e.massTotal*gE*1.2),{FL:s.FL,FR:s.FR,RL:s.RL,RR:s.RR},yE(e))}function xE(e){if(!e.tire)return e.cornerStiffness;let t=xe(e.tire,"front"),r=xe(e.tire,"rear");return{front:n=>t.corneringStiffness(n),rear:n=>r.corneringStiffness(n)}}var Jk=[{key:"understeer",label:"Understeer gradient",unit:"\xB0/g",compute:(e,t)=>Pu(e,t.ayG,xE(t),t.speed).gradient},{key:"rollGradient",label:"Roll gradient",unit:"\xB0/g",compute:e=>Ce(e).rollGradient},{key:"pitchGradient",label:"Pitch gradient",unit:"\xB0/g",compute:e=>Ce(e).pitchGradient},{key:"tlltdFront",label:"TLLTD front",unit:"%",compute:e=>100*Gd(e)},{key:"rollStiffFront",label:"Front roll-stiffness",unit:"%",compute:e=>100*Ce(e).frontRollStiffFrac},{key:"rideFreqFront",label:"Ride freq front",unit:"Hz",compute:e=>Ce(e).rideFreqFront},{key:"rideFreqRear",label:"Ride freq rear",unit:"Hz",compute:e=>Ce(e).rideFreqRear},{key:"rollFreq",label:"Roll-mode freq",unit:"Hz",compute:e=>Iu(e).roll.freq},{key:"pitchFreq",label:"Pitch-mode freq",unit:"Hz",compute:e=>Iu(e).pitch.freq},{key:"zetaFront",label:"Damping \u03B6 front",unit:"-",compute:e=>Du(e).front.dampingRatio},{key:"zetaRear",label:"Damping \u03B6 rear",unit:"-",compute:e=>Du(e).rear.dampingRatio},{key:"yawFreq",label:"Yaw natural freq",unit:"Hz",compute:(e,t)=>bi(e,t.speed)?.yawFreq??NaN},{key:"yawZeta",label:"Yaw damping \u03B6",unit:"-",compute:(e,t)=>bi(e,t.speed)?.dampingRatio??NaN},{key:"stabilitySpeed",label:"Char./critical speed",unit:"km/h",compute:(e,t)=>{let r=bi(e,t.speed);return r?r.criticalSpeed??r.characteristicSpeed??NaN:NaN}},{key:"maxAy",label:"Max lateral accel",unit:"g",compute:(e,t)=>t.fyAxle?sb(e,t.fyAxle,t.speed,{betaMaxDeg:12,deltaMaxDeg:12}).maxAy:NaN},{key:"yawReserveRear",label:"Yaw stability reserve",unit:"N\xB7m",compute:(e,t)=>gi(e,t,"operating")?.stabil??NaN},{key:"yawReserveFront",label:"Yaw agility reserve",unit:"N\xB7m",compute:(e,t)=>gi(e,t,"operating")?.agil??NaN},{key:"limitBalance",label:"Limit balance (+US / \u2212OS)",unit:"-",compute:(e,t)=>gi(e,t,"limit")?.rel??NaN},{key:"yawStiffness",label:"Yaw stiffness N_\u03B2",unit:"N\xB7m/rad",compute:(e,t)=>t.tire?wh(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorque",label:"Steering holding torque",unit:"N\xB7m",compute:(e,t)=>t.tire?Ah(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorqueGradient",label:"Steering feedback gradient",unit:"N\xB7m/g",compute:(e,t)=>t.tire?Fh(e,t.tire,t.speed,t.ayG):NaN}],cb=Object.fromEntries(Jk.map(e=>[e.key,e]));var $r=9.81;function RE(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 vE={front:!1,rear:!0};function Sa(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 eM(e,t,r,n,o,a){let s=e[t]+e[r];if(!(s>0))return;let i=Sa(n,o[t],a[t]),c=Sa(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 tM(e,t,r,n,o,a={},s="open"){if(!e.rear)return 1;if(!e.front)return 0;let i=(f,p,d)=>d?$s(f,p,d):s==="own"?f+p:2*Math.min(f,p),c=i(Sa(n,t.FL,r.FL),Sa(n,t.FR,r.FR),a.front),l=i(Sa(o,t.RL,r.RL),Sa(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 lb(e,t,r,n){return{car:t?oM(t,r.loadFactor[n]):e,ayTyre:We(r.ay[n],r.bank?.[n]??0),axCar:r.ax[n]-(r.axGrade?.[n]??0)}}function rM(e,t){if(!e.aero?.model)return 0;let r=Math.min(t.v.length,t.ax.length,t.ay.length),n=t.loadFactor?Ou(e):void 0,o=0,a=0;for(let s=0;s<r;s++){let i=t.ds?.[s]??1,c=lb(e,n,t,s);o+=i,$d(c.car,t.v[s],c.axCar/$r,c.ayTyre/$r)&&(a+=i)}return o>0?a/o:0}function nM(e,t,r){let n=zt(xe(t,"front")),o=zt(xe(t,"rear")),a=Math.min(r.v.length,r.ax.length,r.ay.length),s=r.loadFactor?Ou(e):void 0,i=0,c=0;for(let l=0;l<a;l++){let u=r.ds?.[l]??1,m=lb(e,s,r,l);i+=u;let f=Le(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 Nu(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=js(t,e.massTotal*$r*1.2),l=Zo(c,"front"),u=Zo(c,"rear"),m=ut(xe(t,"front")),f=ut(xe(t,"rear")),p=n.perWheel?Yd(m,l):null,d=n.perWheel?f===m?p:Yd(f,u):null,h=n.driven??vE,b={front:Bt(e,"front",1),rear:Bt(e,"rear",1)},g={front:0,rear:0},y=new Array(o),x=new Array(o),M=new Array(o),v=1/0,R=0,k=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(O=>[O,{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,$=r.loadFactor?Ou(e):void 0;for(let O=0;O<o;O++){let W=lb(e,$,r,O),{ayTyre:I,axCar:_}=W,V=I/$r,N=Le(W.car,V,_/$r,r.v[O]),G=e.massTotal*I,K=G*i/a,z=G*s/a,j=vs(m,K,N.FL,N.FR,P),q=vs(f,z,N.RL,N.RR,L);P=j,L=q;let ne={FL:Math.abs(m.Fy(j,N.FL,0)),FR:Math.abs(m.Fy(j,N.FR,0)),RL:Math.abs(f.Fy(q,N.RL,0)),RR:Math.abs(f.Fy(q,N.RR,0))},te=(_-(r.axDrag?.[O]??0)-(r.axScrub?.[O]??0))/$r,fe=te>0&&h.front?tM(h,N,ne,l,u,b,"own"):0,Y=r.v[O]*r.v[O],J=e.driveline?{Fz:N,alpha:{front:j,rear:q},curvature:Y>1?r.ay[O]/Y:0,seed:g}:void 0,re={...vh(e,te,r.v[O],t,V,fe,J)};te>0&&(b.front||eM(re,"FL","FR",l,N,ne),b.rear||eM(re,"RL","RR",u,N,ne));let pe=!1,de=!1;for(let ue of["FL","FR","RL","RR"]){let Ve=(ue==="FL"||ue==="FR"?l:u).muX(N[ue])*N[ue];Math.abs(re[ue])>Ve&&(pe=!0),N[ue]>(ue==="FL"||ue==="FR"?F:w)&&(de=!0)}de&&(k+=r.ds?.[O]??1);let ie=Rr(c,{FL:{Fz:N.FL,Fy:ne.FL,Fx:re.FL},FR:{Fz:N.FR,Fy:ne.FR,Fx:re.FR},RL:{Fz:N.RL,Fy:ne.RL,Fx:re.RL},RR:{Fz:N.RR,Fy:ne.RR,Fx:re.RR}},{lf:s,lr:i});if(y[O]=ie.stabil,x[O]=ie.agil,M[O]=ie.rel,E){let ue=.5*(N.FL+N.FR),Ve=.5*(N.RL+N.RR),Ae=l.muX(ue)*ue,le=u.muX(Ve)*Ve;for(let Re of D){let we=N[Re],Ke=Re==="FL"||Re==="FR",je=Ke?l:u,be=je.muY(we)*we,Fe=je.muX(we)*we,ye=E[Re],me=Ke?j:q;ye.Fz[O]=we,ye.alpha[O]=me,ye.Fy[O]=ne[Re],ye.Fx[O]=re[Re],ye.Mz[O]=we>0?(Ke?m:f).Mz(me,we,0):0,ye.FxCap[O]=Fe,ye.FyCap[O]=be;let Te=be>0?Math.min(1,Math.abs(ne[Re])/be):0,Se=RE(re[Re],Fe,Ke?Ae:le),He=Ke?p:d,Ue=He&&we>0?He.reach(we,Math.sign(re[Re])*Se,Te):1;ye.used[O]=Math.hypot(Te,Se)/Ue}}ie.stabil<v&&(v=ie.stabil,R=O);let oe=r.ds?.[O]??1;A+=oe,ie.diff>0&&(C+=oe),pe&&(T+=oe),$d(W.car,r.v[O],_/$r,V)&&(S+=oe)}return{stabil:y,agil:x,rel:M,minStabil:Number.isFinite(v)?v:0,minStabilAt:R,pastTurnoverFrac:A>0?k/A:0,understeerFrac:A>0?C/A:0,beyondFrac:A>0?T/A:0,aeroOutsideFrac:A>0?S/A:0,wheels:E}}function Ou(e){return Object.create(e,{loadFactor:{value:1,writable:!0,enumerable:!0}})}function oM(e,t){return e.loadFactor=t,e}var ub=9.81;function mb(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)/ub,h=Math.min(.99,Math.max(.01,ia(e,f/ub,u,t,d)));c.front[l]=p*h,c.rear[l]=p*(1-h);let b=i?Wl(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/ub)),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 L7=Math.PI/180;var D7=nb.map(Us);var E7=[ce.zFL,ce.zFR,ce.zRL,ce.zRR];var I7=Array.from({length:ce.rollRate+1},(e,t)=>t);var IE=9.81,_E=.001,NE=.6,OE=2,cM=4;function lM(e,t,r,n=cM){let o=Math.min(e.v.length,t.npts),{ds:a,closed:s}=t,i=r.massTotal*IE*r.wheelbase,c=VE(e.ay.slice(0,o).map((m,f)=>m/Math.max(_E,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 VE(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 uM(e,t,r,n,o={}){let a=o.maxIter??20,s=o.tol??.001,i=Math.min(1,Math.max(.001,o.relax??NE)),c=o.smoothM??cM,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 M=0;M<a;M++){h=M+1;let v=lM(d,t,r,c);f=v.demand.map((F,w)=>f[w]+i*(F-f[w])),p=v.rdot;let R=Rt(e.steady,t,n,{...l,envelope:F=>e.at(f[F]??0)});m.push(R.laptime);let k=Math.abs(R.laptime-d.laptime);if(d=R,g=k<=s?g+1:0,g>=OE){b=!0;break}}let y=0,x=0;for(let M=0;M<t.npts;M++)x+=t.ds[M],e.clamps(f[M]??0)&&(y+=t.ds[M]);return{...d,steady:u,demand:f,rdot:p,history:m,iterations:h,converged:b,clampedFrac:x>0?y/x:0}}var H7=Math.PI/180;var vQ=180/Math.PI;function Aa(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 pM(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=>Aa(p.vs,h,d)),axDecelN:p.decel.map(h=>Aa(p.vs,h,d)),axScrubN:p.scrub.map(h=>Aa(p.vs,h,d))});if(!o){let p=a(e);return d=>({ayMax:Aa(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/Aa(i.vs,i.radius,p),f=p=>p>=u||c.vs.length<2?Aa(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 tI(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 dM(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=pM(s,t),c=[],l=a,u=(f,p)=>{let d=.5*(f+p),h=e(d);l++;let b=tI(i(d),h);s.splice(s.findIndex(g=>g.v>d),0,h),i=pM(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 rI=2,nI=.5,yi=Math.PI/180,fM=21,oI={nCoarse:11,nSteer:13,nNorm:41,nAngle:45},aI={nCoarse:11,nSteer:13,nNorm:41,nAngle:61},sI=.005,iI=.05,pb=e=>e<0?0:e>1?1:e;function cI(e,t,r,n){let o=e.massTotal,a=n.nSteer??7,s=(n.drivenFront?2:0)+(n.drivenRear?2:0),i=Le(e,0,0,r),c=Math.max(1,(i.FL+i.FR+i.RL+i.RR)/4),l=8*yi,u=0,m=(b,g,y)=>{for(let x=b;x<=g;x+=y){let M=Math.abs(t.Fy(x*yi,c,0));M>u&&(u=M,l=x*yi)}};m(1,45,1),m(Math.max(.1,l/yi-1),l/yi+1,.1);let f=[],p=[],d=[],h=[];for(let b=0;b<a;b++){let g=b/(a-1),y=l*(g+Math.sin(Math.PI/2*g))/2,x=Math.abs(t.Fy(y,c,0));f.push(4*x/o),p.push(s*St(t,c,x,!1)/o),d.push(4*St(t,c,x,!0)/o),h.push(-4*x*Math.sin(y)/o)}return f[0]=0,{ayMax:4*u/o,ay:f,axAccel:p,axDecel:d,axScrub:h,rollover:!1}}function ir(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?aI:oI),{nCoarse:c,nSteer:l,nAngle:u}=i,m=Tr(0,1,i.nNorm).map(V=>Math.sin(Math.PI/2*V)),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,x=dt(f);s!==1&&(x.loadFactor=s);let M=sr(f),v=Sv(0,n?.vRes??(e.engine?nI:rI),e.vMax);v[v.length-1]<e.vMax&&v.push(e.vMax);let R=e.fRad.map(V=>V*b),k=e.fAxle,{drivenFront:F,drivenRear:w}=Qn(e),C=Xn(f,F,w),T=(V,N)=>{let G=k?mt(k.vVehicle,V,N):NaN;return Number.isFinite(G)?G:1/0},S=V=>{let N=V*V,{cl:G,cw:K,A:z}=ku(f,V,0,x),j=.5*d*-K*z*N,q=.5*d*-G*z*N,ne=h*(-q+y);return j+ne},A=V=>{let N=S(V)/p*C.powerFactor,G=S(V)/p*C.tractionFactor,K;if(e.engine){let j=S(V);K=oa(e.engine,V,C.effective,j,g).accel-N}else if(k){let j=0;F&&(j+=T(k.fFront,V)),w&&(j+=T(k.fRear,V)),K=g*j/p*C.powerFactor}else{let j=mt(e.vVehicle,R,V),q=g*j/p*C.powerFactor;K=Number.isFinite(q)?q:1/0}let z=wu(f,V,o)/p*C.powerFactor;return{axDrag:N,axDragTyre:G,axDrive:K,axPackCap:z,axPower:Math.min(K,z)}},P=v.map(A),L=e.vMax;for(let V=1;V<v.length;V++){let N=P[V].axDrive+P[V].axDrag;if(N>0)continue;let G=P[V-1].axDrive+P[V-1].axDrag;L=G>0?v[V-1]+(v[V]-v[V-1])*G/(G-N):v[V-1];break}let D=Math.min(e.vMax,(1+iI)*L),E=r==="fast"?cI:Ph,$=V=>{let N=E(x,M,V,{drivenFront:F,drivenRear:w,nSteer:l,yawDemandCn:a,axDrag:S(V)/p,...f.diffYaw?{diffYaw:!0}:{}}),G=N.ay[0],K=N.ay[N.ay.length-1],z=te=>Math.min(Math.max(te*N.ayMax,G),K),j=m.map(te=>Ol(N.ay,N.axAccel,z(te))*C.tractionFactor),q=m.map(te=>Ol(N.ay,N.axDecel,z(te))),ne=m.map(te=>Ol(N.ay,N.axScrub,z(te))*C.tractionFactor);return{v:V,ayMax:N.ayMax,axAccelN:j,axDecelN:q,axScrubN:ne,atLock:N.atLock===!0}},O=r==="fast"?0:Math.min(Jl,D),W=dM($,O,D,c,i.anchorTol??sI),I=[],_=[];for(let V=0;V<v.length;V++){let N=v[V],{axDrag:G,axDragTyre:K,axDrive:z,axPackCap:j,axPower:q}=P[V],{ayMax:ne,axAccelN:te,axDecelN:fe,axScrubN:Y}=W.at(N);I.push({v:N,ayMax:ne,axTyreAcc:te[0],axTyreDec:fe[0],axDrive:z,axPackCap:j,axPower:q,axDrag:G,axDragTyre:K,axAccelN:te,axDecelN:fe,axScrubN:Y});let J=[],re=[];for(let de=0;de<u;de++){let ie=Math.PI*de/(u-1),oe=ne*Math.cos(ie),ue=pb(Math.abs(Math.cos(ie)));J.push({ax:Math.min(mt(m,te,ue)+K,q+G)+mt(m,Y,ue),ay:oe,v:N})}for(let de=u-1;de>=0;de--){let ie=Math.PI*de/(u-1),oe=ne*Math.cos(ie),ue=pb(Math.abs(Math.cos(ie)));re.push({ax:mt(m,fe,ue)+G+mt(m,Y,ue),ay:oe,v:N})}let pe=(de,ie,oe)=>Array.from({length:fM},(ue,Ve)=>({ax:ie+(oe-ie)*(Ve+1)/(fM+1),ay:de,v:N}));_.push([...J,...pe(-ne,J[J.length-1].ax,re[0].ax),...re,...pe(ne,re[re.length-1].ax,J[0].ax)])}return{...bM(I,m),rows:I,norm:m,surf:_}}function Fa(e,t){return e?.length?t.map(r=>Bu(e,r)):t.map(()=>0)}function Bu(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 bM(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 x=y*a(b,d.ayMax,h.ayMax);return x>0?pb(g/x):1},m=(d,h,b=1,g=1)=>{let{a:y,b:x,t:M}=d,v=u(d,h,b),R=b*s(M,y.axAccelN,x.axAccelN,v)+a(M,l(y),l(x)),k=a(M,i(y,g),M===0?0:i(x,g))+a(M,y.axDrag,x.axDrag);return Math.min(R,k)+c(d,v,b)},f=(d,h,b=1,g=1)=>{let{a:y,b:x,t:M}=d,v=u(d,h,b),R=s(M,y.axDecelN,x.axDecelN,v);return(g===1||R>0?b*R:g*b*R)+a(M,y.axDrag,x.axDrag)+c(d,v,b)},p=({a:d,b:h,t:b},g,y=1)=>{let x=t.length-1,M=d.axAccelN,v=h.axAccelN,R=d.axDecelN,k=h.axDecelN,F=d.axScrubN,w=h.axScrubN,C=E=>M[E]+b*(v[E]-M[E]),T=E=>R[E]+b*(k[E]-R[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=x;E>=0;E--){let $=Math.min(y*C(E)+L,D+P)+S(E),O=y*T(E)+P+S(E);if(!(g<=$+1e-6&&g>=O-1e-6))continue;if(E===x)return t[E]*y*A;let W=(N,G,K)=>{if(K(G))return 1;let z=(N-g)/(N-G);return z>0?Math.min(z,1):0},I=N=>g<=N+1e-6,_=N=>g>=N-1e-6,V=Math.min(W(y*C(E)+L+S(E),y*C(E+1)+L+S(E+1),I),W(D+P+S(E),D+P+S(E+1),I),W(y*T(E)+P+S(E),y*T(E+1)+P+S(E+1),_));return(t[E]+V*(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 lI(e,t,r){let n=e.params,o=n.m.value,{drivenFront:a,drivenRear:s}=Qn(e),i=Xn(n,a,s);return c=>wu(n,c,t,r)/o*i.powerFactor}function xi(e,t,r,n){let o=lI(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{...bM(a,e.norm),rows:a,norm:e.norm}}var uI=[-.2,-.08,0,.06,.12,.2,.3];function gM(e,t=!1,r="twoTrack",n,o,a=uI){let s=[...new Set([...a,0])].sort((d,h)=>d-h),i=s.map(d=>ir(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:x}=h(b);if(x===0)return g;let M=(v,R)=>v+x*(R-v);return{vMax:g.vMax,axAccel:(v,R,k=1,F=1)=>M(g.axAccel(v,R,k,F),y.axAccel(v,R,k,F)),axDecel:(v,R,k=1,F=1)=>M(g.axDecel(v,R,k,F),y.axDecel(v,R,k,F)),ay:(v,R,k=1)=>M(g.ay(v,R,k),y.ay(v,R,k)),scrub:(v,R,k=1)=>M(g.scrub?.(v,R,k)??0,y.scrub?.(v,R,k)??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=>xi(y,d,h,b));return{anchors:s,steady:g[s.indexOf(0)],clamps:p,at:f(g)}}}}function yM(e,t,r,n="twoTrack",o){let a=[...new Set([...t,1])].sort((i,c)=>i-c),s=a.map(i=>i===1?r:ir(e,!1,n,o,void 0,0,i));return{...hM(a,s),atSoc:(i,c,l)=>hM(a,s.map(u=>xi(u,i,c,l)))}}function hM(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(M=>g(M,h));let y=m(M=>M.ay(d,0,b));if(!(y>0))return m(M=>g(M,h));let x=h/y;return m(M=>g(M,x*M.ay(d,0,b)))};return{anchors:e,axAccel:(p,d,h,b=1,g=1)=>f(p,d,h,b,(y,x)=>y.axAccel(d,x,b,g)),axDecel:(p,d,h,b=1,g=1)=>{let y=x=>f(p,d,h,b,(M,v)=>M.axDecel(d,v,b,x));return g===1?y(1):jh(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(M=>M.ay(d,h,b));let g=M=>h>0?M.axAccel(d,0,b):-M.axDecel(d,0,b),y=m(g);if(!(y>0))return m(M=>M.ay(d,h,b));let x=h/y;return m(M=>M.ay(d,x*g(M),b))}}}var xM=new WeakMap;function db(e,t){let r=xM.get(e);if(!r){let n=Cr(e).regen?eb(t??Ft(e)):void 0;r={inp:dt(e),ev:sr(e),...n?{regen:n}:{}},xM.set(e,r)}return r}function fb(e,t,r){let n=db(e,r);return mb(n.inp,n.ev,t,n.regen?{regen:n.regen}:{})}function hb(e){let t=pt(e);if(t.mode!=="hydraulic")return null;let r=a=>a.heat?{heat:Tf(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 mI(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 bb(e,t,r,n,o,a=At){if(!e)return null;let s=mI(t);return{...e.front?{front:Dl(e.front.heat,e.front.discs,s.front,r,n,o.front,a)}:{},...e.rear?{rear:Dl(e.rear.heat,e.rear.discs,s.rear,r,n,o.rear,a)}:{}}}var pI=.5,dI=.02,fI=6,$u=9,RM=1e-9,hI={FL:0,FR:0,RL:0,RR:0};function gb(e){return e?[...new Set([...e.padCurve.factor,1])].sort((t,r)=>t-r):[1]}function bI(e,t,r){let n=rr(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 vM(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 kM(e,t,r,n,o=()=>0){let a=Array.from({length:$u},(m,f)=>r*f/($u-1)),s=Ys(),{front:i,rear:c}=n,l=a.map(m=>{let f=o(m),p=h=>Lr(h,t,m,s).limitAt(0,0,hI,f).ax,d=p(e);return i.map(h=>c.map(b=>{if(h===1&&b===1)return 1;let g=d<0?p(bI(e,h,b))/d:1;return Math.abs(g-1)<RM?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($u-2,Math.max(0,Math.floor(m/u))):0,h=u>0?Math.min(1,Math.max(0,(m-a[d])/u)):0,b=vM(i,f),g=vM(c,p),y=M=>{let v=l[M],R=Math.min(i.length-1,b.i+1),k=Math.min(c.length-1,g.i+1),F=v[b.i][g.i]+g.t*(v[b.i][k]-v[b.i][g.i]),w=v[R][g.i]+g.t*(v[R][k]-v[R][g.i]);return F+b.t*(w-F)},x=y(d)+h*(y(Math.min($u-1,d+1))-y(d));return Math.abs(x-1)<RM?1:x}}}function gI(e,t){let{front:r,rear:n}=t;return(o,a)=>e.share(a,r?.[o]??1,n?.[o]??1)}var yI=e=>(e.front??[]).every(t=>t===1)&&(e.rear??[]).every(t=>t===1);function MM(e,t,r){let n=e(),o=1,a=t(n);if(yI(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<fI;c++){let l=e(gI(r,s));o++;let u=Math.abs(l.laptime-n.laptime);if(n=l,u<dI){i=!0;break}a=t(n);let m=(d,h)=>d&&h?d.map((b,g)=>b+pI*((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 pn(e,t){let r=e.engine;if(!r||r.gears.length===0||t.length===0)return;let n=e.params,{drivenFront:o,drivenRear:a}=Qn(e),s=Xn(n,o,a).effective,i=n.power_scale.value,{up:c,down:l}=zf(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:Yf(r.engine.gearbox),limitRpm:r.engine.limitRpm,best:f=>oa(r,f,s,Bu(t,f)*s,i).gear,share:(f,p)=>{let d=Bu(t,f),h=d*s,b=oa(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 SM=new WeakMap;function xb(e){let t=SM.get(e.ggv);return t===void 0&&(t=pn(e.vehicle,e.ggv.rows)??null,SM.set(e.ggv,t)),t??void 0}function xI(e){return e.gear&&e.engineRpm&&e.shifting?{gear:e.gear,rpm:e.engineRpm,shifting:e.shifting}:{}}var Ku=class extends Error{constructor(t){super(t),this.name="EventError"}};function RI(e,t){let{ggv:r}=t,n=at(t.numerics),o=n.accelStep,a=Math.max(1,Math.round(e.distance/o)),s=ya(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=xb(t),c=i?Au(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:EM(t,f,[...u,s[a].v],m,1)}}function vI(e,t){let r=Math.max(1,Math.round(e.laps??1)),[n]=ya(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=EM(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 Hu(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 kI(e,t){let r=e.distance!=null?t.v_limit_endurance?.value??0:0;return r>0?r/3.6:void 0}function MI(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 AM=1;function PM(e,t,r,n){return{v:r.v,ax:r.ax,ay:r.ay,ds:t.ds,axDrag:Fa(e.ggv.rows,r.v),...r.axScrub?{axScrub:r.axScrub}:{},axGrade:n,...t.bank?{bank:t.bank}:{}}}var FM=new WeakMap;function LM(e){let t=e.vehicle.params;if(!t.brakeFade)return null;let r=FM.get(t);if(r===void 0){let n=hb(t),o=n?pt(t):null;if(!n||!o||o.mode!=="hydraulic")r=null;else{let a=db(t,e.vehicle),s=e.ggv.rows,i=kM(a.inp,a.ev,e.vehicle.vMax,{front:gb(o.hydraulic.front.heat),rear:gb(o.hydraulic.rear.heat)},c=>Fa(s,[c])[0]);r={discs:n,table:i}}FM.set(t,r)}return r}function SI(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=xb(e),u=(g,y)=>e.yaw?uM(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(xi(e.ggv,e.vehicle,o,a),t,e.numerics,{standingStart:s,...g?{driveDerate:g}:{},...y?{brakeFade:y}:{},...i?{vCeiling:i}:{},...c?{load:c}:{},...l?{shifts:l}:{}}),m=mn(t.gradient,t.npts),f=g=>n.motorThermal?Dk(e.vehicle,t.ds,e.energyOpts??wr,y=>u(y,g),o,a,m,t.bank).lap:u(void 0,g),p=LM(e);if(!p)return f();let d=hi(n),h=r.discC??{front:d,rear:d};return MM(f,g=>{let y=bb(p.discs,fb(n,PM(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 AI(e,t){let r=kI(e,t.vehicle.params),n=MI(e,t.vehicle.params);return n>0?CI(e,t,n,r):Ri(e,t,r)}function Gu(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 wM=5,FI=.1,wI=.005,CM=12;function CI(e,t,r,n){let o=Ri(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=Gu(o,r);if(i>=0)return s(o,n,!0);let c=Math.min(n??1/0,t.ggv.vMax),l=c/2,u=Ri(e,t,l);a++;let m=Gu(u,r);for(;m<0&&l>wM&&a<CM;)c=l,i=m,l=Math.max(wM,l/2),u=Ri(e,t,l),a++,m=Gu(u,r);if(m<0)return s(u,l,!1);let f=l,p=0;for(;a<CM&&c-l>FI&&m>wI;){let d=c-l,h=Math.min(c-.05*d,Math.max(l+.05*d,l+m*d/(m-i))),b=Ri(e,t,h);a++;let g=Gu(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 DM(e,t,r){return r===0?e:e&&!t}function Ri(e,t,r){let n=t.track;if(!n)throw new Ku(`Event "${e.id}" needs a track.`);let o=Hu(e,n),a=e.standingStart??t.standingStart??!1,s=K=>DM(a,n.closed,K),i=t.vehicle.params,c=hr(xa(i)),l=c.capacityAh,u=i.soc.value,m=hi(i),f=Fu(c,m),p=0,d=0,h=0,b=0,g=[],y=!1,x=-1/0,M=0,v=0,R=!1,k=-1/0,F=0,w=0,C=-1/0,T=(K,z,j=1)=>{K.tempMaxC>C&&(C=K.tempMaxC),K.motorTempMaxC!==void 0&&(y=!0,R=!0,K.motorTempMaxC>x&&(x=K.motorTempMaxC),K.motorTempMaxC>k&&(k=K.motorTempMaxC),M+=(K.motorDerateTimeFrac??0)*z,F+=(K.motorDerateTimeFrac??0)*z,v+=(K.motorLossKwh??0)/j,w+=(K.motorLossKwh??0)/j)},S=null,A,P=hb(i),L={front:m,rear:m},D=null,E=LM(t)!==null,$=(K,z)=>E&&(Math.abs(K.front-z.front)>AM||Math.abs(K.rear-z.rear)>AM),O=(K,z,j)=>{let q=tb(i,K,z);if(D&&D.launch===j&&!LI(q,D.pw)&&!$(L,D.discC))return D.lap;let ne=SI(t,n,{soc:K,packTempC:z,launched:j,...r?{vCeiling:r}:{},...E?{discC:L}:{}});return D={pw:q,launch:j,discC:L,lap:ne},ne},W=mn(n.gradient,n.npts),I=(K,z,j)=>Ra(t.vehicle,n.ds,K.v,K.ax,t.energyOpts,z,j,void 0,W,void 0,{ay:K.ay,bank:n.bank,...K.axScrub?{scrub:K.axScrub}:{}}),_=new WeakMap,V=(K,z)=>{let j=_.get(K);return j||(j=fb(i,PM(t,n,K,W),t.vehicle),_.set(K,j)),bb(P,j,K.v,n.ds,z,m)},N=(K,z,j)=>{let q=`${(100*j/n.npts).toFixed(0)} % of the way through lap ${K+1}`,ne=z.cutoffAt>=0&&z.cutoffAt<=z.emptyAt;return{lapsCompleted:K,lapsAsked:o,why:ne?`the pack reached its ${c.voltageFloor.toFixed(0)} V cut-off ${q}`:`the pack ran out ${q}`}};for(let K=0;K<o;K++){if(u<=0){A={lapsCompleted:K,lapsAsked:o,why:"the pack was empty"};break}let z=s(K),j=u,q=f;R=!1,k=-1/0,F=0,w=0,C=-1/0;let ne=O(u,f,z),te=I(ne,u,f);if(te.emptyAt>=0){A=N(K,te,te.emptyAt);break}let Y=O(te.socEnd,te.tempEndC,z).laptime-ne.laptime,J,re,pe,de,ie=f,oe=-1,ue=null,Ve=1;if(Y<=yb)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(TI,Math.max(2,Math.ceil(Y/(2*yb))));Ve=le;let Re=u,we=f;J=0,re=0,pe=0,de=0;for(let Ke=0;Ke<le;Ke++){let je=O(Re,we,z),be=I(je,Re,we),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,we+=(be.tempEndC-we)/le,Re<=0){oe=Math.round(n.npts*(Ke+1)/le),ue=be;break}}if(ie=we,oe>=0&&ue){A=N(K,ue,oe);break}u=Re}p+=J,d+=re,h+=pe,b+=de,Y<=yb&&(u=te.socEnd),f=ie;let Ae=P?V(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:q,packTempEndC:f,packTempMaxC:Number.isFinite(C)?C:q,energyKwh:re,lossKwh:pe,chargeAh:de,launched:z,substeps:Ve,...r?{vCeiling:r}:{},...R?{motor:{peakWindingC:k,derateTimeFrac:J>0?F/J:0,lossKwh:w}}:{},...Ae?{brakes:{...Ae.front?{front:TM(Ae.front)}:{},...Ae.rear?{rear:TM(Ae.rear)}:{}}}:{}}),S=ne}if(!S){let K=xb(t);S=Rt(xi(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}:{},...xI(S)},energy:{consumed:d,loss:h,...ft(i.motorModel)?{}:{native:{value:b,unit:"Ah"}},remainingFraction:ft(i.motorModel)?1:u,...y?{motor:{peakWindingC:x,derateTimeFrac:p>0?M/p:0,lossKwh:v}}:{}},lapLog:g,...A?{incomplete:A}:{}}}var yb=.05;function TM(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 TI=4,PI=.001;function LI(e,t){return e===t?!1:!Number.isFinite(e)||!Number.isFinite(t)?!0:Math.abs(e-t)>PI*Math.max(1,Math.abs(t))}function EM(e,t,r,n,o,a){return DI(e,t,o,()=>({v:r,ax:n,...a?{lateral:a}:{}}))}function DI(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=Ra(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 IM(e,t){switch(e.kind){case"straightLineAccel":return RI(e,t);case"constantRadius":return vI(e,t);case"trackLap":return AI(e,t)}}function Rb(e,t){let r={};for(let n of e)r[n.id]=IM(n,t);return r}function _M(e,t){if(e.kind!=="trackLap")return e;let{distance:r,...n}=e;return{...n,laps:Math.max(1,Math.round(t))}}function qn(e,t,r,n,o="twoTrack",a){let s=1/0,i=-1/0;for(let f of r){let p=pi(f);if(!p)continue;let d=yk(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=xk({lo:s,hi:i}),l=c.join(","),u=a?.get(l);if(u)return u;let m=yM(e,c,t,o);return a?.set(l,m),m}var zu=e=>e.distance/Math.max(1,e.laps);function Yu(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 EI=e=>e.v.map(t=>t*3.6),II=e=>e.ax.map(t=>t/9.81),_I=e=>e.ay.map(t=>t/9.81),NI=e=>e.ay.map((t,r)=>e.v[r]>1e-6?t/(e.v[r]*e.v[r]):0),Wu=(e,t,r)=>e?.slice()??new Array(t.s.length).fill(r),OI=e=>Wu(e.z,e,0),VI=e=>e.gradient?e.gradient.map(t=>100*Math.tan(t*Math.PI/180)):Wu(void 0,e,0),BI=e=>Wu(e.bank,e,0),$I=e=>Wu(e.mu,e,1);function GI(e){let t=e.s.length,r=Yu(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 vb=[{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 NM(e){let t=Yu(e);return{ds:t,vars:{s:e.s,ds:t,t:GI(e),v:e.v,speed:EI(e),ax:e.ax,ay:e.ay,axg:II(e),ayg:_I(e),curv:NI(e),z:OI(e),grade:VI(e),bank:BI(e),grip:$I(e)}}}function OM(e,t){return{v:e.v,ax:e.ax,ay:e.ay,ds:Yu({s:e.s,length:t}),axGrade:mn(e.gradient,e.v.length),...e.bank?{bank:e.bank}:{},...e.loadFactor?{loadFactor:e.loadFactor}:{}}}function VM(e,t){let r=dt(e);return{pastTurnover:nM(r,sr(e),t),...e.aeroModel?{aeroOutside:rM(r,t)}:{}}}var ju="Flying lap";function kb(e,t){return e.kind!=="trackLap"||e.label!==ju?e.label:e.standingStart??t?"Run":e.label}function KI(e){let t=dt(e);return{yawInertia:t.yawInertia??0,massTotal:t.massTotal,wheelbase:t.wheelbase/1e3}}function HI(e,t,r){let n=e.params,o=n.ggvMode??"twoTrack",a=n.quasiTransient?gM(e,!1,o):null,s=a?a.steady:ir(e,!1,o),i=t?qn(e,s,[t],r,o):void 0;return{ggv:s,...a?{yaw:{family:a,car:KI(n)}}:{},...i?{load:i}:{}}}function zI(e,t){let r=t.lapCounts,n=t.standingStart??!1,o=!1,a=e.events.map(s=>{let i=r?.[s.id]!=null?_M(s,r[s.id]):s,c=kb(i,n),l=c===i.label?i:{...i,label:c};return l!==s&&(o=!0),l});return o?a:e.events}function YI(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=Hu(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 WI(e,t){for(let[r,n]of Object.entries(e))n.trace&&(e[r]={...n,...VM(t,OM(n.trace,zu(n)))})}function vi(e,t,r={}){let n=Ft(e),o=HI(n,r.track,r.numerics),{ggv:a}=o,s=Rb(zI(t,r),{vehicle:n,...o,track:r.track,energyOpts:Cr(e,r.energyOpts),numerics:r.numerics,standingStart:r.standingStart});return YI(s,t,r),WI(s,n.params),{name:e.name,rulesetId:t.id,events:s,ggv:a}}function Mb(e){return{...e,ggv:{rows:e.ggv.rows,vMax:e.ggv.vMax,surf:e.ggv.surf}}}var Sb=["<","<=",">",">=","==","!="],_e=class extends Error{at;constructor(t,r){super(t),this.name="ExprError",this.at=r}},ki=e=>e>="0"&&e<="9",BM=e=>/[A-Za-z_]/.test(e),jI=e=>/[A-Za-z0-9_]/.test(e);function UI(e){let t=[],r=0;for(;r<e.length;){let n=e[r];if(n===" "||n===" "||n===`
|
|
224
|
-
`||n==="\r"){r++;continue}if(ki(n)||n==="."&&ki(e[r+1]??"")){let o=r;for(;r<e.length&&(ki(e[r])||e[r]===".");)r++;if(e[r]==="e"||e[r]==="E"){let i=r;if(r++,(e[r]==="+"||e[r]==="-")&&r++,ki(e[r]??""))for(;r<e.length&&ki(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(BM(n)){let o=r;for(;;){for(;r<e.length&&jI(e[r]);)r++;if(e[r]==="."&&BM(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(Sb.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 Ab(e){let t=UI(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"||!Sb.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"&&Sb.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 Fb(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 Mi=(e,t)=>typeof e=="number"?new Array(t).fill(e):e;function XI(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=XI(e),n=e.map(a=>Mi(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)}),Zn=e=>e!==0&&!Number.isNaN(e),cr=e=>e?1:0;function $M(e,t,r){let n=GM(t,r,"integrate"),o=n.length,a=Mi(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 GM(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 Uu={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)=>Zn(e)?t:r),and:Ne(2,(e,t)=>cr(Zn(e)&&Zn(t))),or:Ne(2,(e,t)=>cr(Zn(e)||Zn(t))),not:Ne(1,e=>cr(!Zn(e))),finite:Ne(1,e=>cr(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=$M(e,t,0),n=t.ds,o=Mi(e,n.length),a=n.length-1;return r[a]+(o[a]+o[0])/2*n[a]}},integrate:{arity:1,call:([e],t)=>$M(e,t,0)},cum:{arity:1,call:([e],t)=>{let r=t.ds?.length??(Array.isArray(e)?e.length:1),n=Mi(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=GM(t,0,"deriv"),n=r.length,o=Mi(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}}},wa={g:9.81,pi:Math.PI,e:Math.E,nan:NaN,inf:1/0},Si={fleetmin:"min",fleetmax:"max"};function Jn(e){switch(e.kind){case"call":return Object.hasOwn(Si,e.name)||e.args.some(Jn);case"unary":return Jn(e.arg);case"binary":return Jn(e.left)||Jn(e.right);default:return!1}}var QI=e=>typeof e=="number"?`${e}`:`between ${e[0]} and ${e[1]}`;function qI(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 ZI(e,t){let r=t.map(c=>({k:c,d:qI(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 lr(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(wa,e.name))return wa[e.name];let r=[...Object.keys(t.vars),...Object.keys(wa)].sort();throw new _e(ZI(e.name,r),e.at)}case"unary":return Tt([lr(e.arg,t)],r=>-r);case"binary":{let r=lr(e.left,t),n=lr(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)=>cr(o<a));case"<=":return Tt([r,n],(o,a)=>cr(o<=a));case">":return Tt([r,n],(o,a)=>cr(o>a));case">=":return Tt([r,n],(o,a)=>cr(o>=a));case"==":return Tt([r,n],(o,a)=>cr(o===a));case"!=":return Tt([r,n],(o,a)=>cr(o!==a))}break}case"call":{let r=Object.hasOwn(Si,e.name)?Si[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(Uu,e.name)?Uu[e.name]:void 0;if(!n){let s=[...Object.keys(Uu),...t.fleet?Object.keys(Si):[]];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 ${QI(n.arity)} argument${o===1&&a===1?"":"s"}, not ${e.args.length}`,e.at);return n.call(e.args.map(s=>lr(s,t)),t)}}throw new _e("Unreachable node",0)}var Ca=e=>Number.isFinite(e)?e:NaN,wb=[{name:"time",unit:"s",what:"the whole event, every lap",read:e=>Ca(e?.time)},{name:"lapTime",unit:"s",what:"one lap \u2014 the last one completed",read:e=>Ca(e?.lapTime)},{name:"distance",unit:"m",what:"distance covered",read:e=>Ca(e?.distance)},{name:"laps",unit:"-",what:"laps completed",read:e=>Ca(e?.laps)},{name:"energy",unit:"kWh",what:"energy drawn over the event",read:e=>Ca(e?.energy?.consumed)},{name:"remaining",unit:"-",what:"share of the pack or tank left afterwards",read:e=>Ca(e?.energy?.remainingFraction)},{name:"finished",unit:"-",what:"1 when the car ran the whole event, else 0",read:e=>e&&!e.incomplete?1:0}],KM=/^[A-Za-z_][A-Za-z0-9_]*$/,JI=new Set([...Object.keys(wa),...vb.map(e=>e.name)]);function Xu(e,t,r=[]){let n=[],o=new Set(r),a=t.map(b=>b.id),s=new Set;for(let b of a)KM.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(!KM.test(b.key)){n.push({key:b.key,message:`"${b.key}" must be one word \u2014 letters, digits and _`});continue}if(JI.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,Ab(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,[...Fb(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=e2(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 wb)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 vb)h[b.name]=[1,1];for(let b of m){let g=i.get(b),y=c.get(b);(Jn(y)||l.get(b).some(R=>p.has(R)))&&p.add(b);let x=g.over!=null?{...d,...h}:d,M=g.over!=null?[1,1]:void 0,v=(R,k,F)=>{let w=lr(R,{vars:x,ds:M,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 R=lr(y,{vars:x,ds:M,fleet:v});Array.isArray(R)&&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(R){let k=R;n.push({key:b,message:k.message,at:k.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 e2(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 t2(e,t,r={}){let n={...r};for(let o of e.eventIds){let a=t.events[o];for(let s of wb)n[`${o}.${s.name}`]=s.read(a)}return{vars:n,laps:new Map,events:t.events}}function HM(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?NM({...n.trace,length:zu(n)}):null,e.laps.set(t.over,r)}return r?{vars:{...e.vars,...r.vars},ds:r.ds}:null}var zM=e=>Array.isArray(e)?NaN:e;function YM(e,t,r,n={}){let o=Object.keys(t),a=o.map(i=>t2(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=HM(b,i);if(!g)continue;let y=zM(lr(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=HM(f,i);f.vars[i.key]=p?zM(lr(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 Ai(e,t,r){return YM(e,t,!0,r)}function Cb(e,t,r){return YM(e,{car:t},!1,r?{car:r}:void 0).car}var Qu=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},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:
|
|
225
225
|
`+r.map(n=>` ${n.key?`${n.key}: `:""}${n.message}`).join(`
|
|
226
|
-
`)),this.name="RulesetDefError",this.problems=r}},wi=e=>typeof e=="number"&&Number.isFinite(e),Fi=e=>wi(e)&&e>0,Pt=(e,t)=>e===void 0||t(e);function r2(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":Fi(a.distance)||r(`${s} needs a distance above zero, in metres`),Pt(a.vStart,i=>wi(i)&&i>=0)||r(`${s}'s entry speed must be zero or more`);break;case"constantRadius":Fi(a.radius)||r(`${s} needs a radius above zero, in metres`),Pt(a.laps,i=>wi(i)&&i>=1)||r(`${s} runs at least one lap`);break;case"trackLap":Pt(a.laps,i=>wi(i)&&i>=1)||r(`${s} runs at least one lap`),Pt(a.distance,Fi)||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,wi)||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,Fi)||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],Fi)||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 WM(e){let t=r2(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}=Xu(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 qu(e){return WM(e).problems}var Tb=e=>Number.isFinite(e)?e:NaN;function n2(e){return e.unit&&e.format!=="time"?`${e.label} (${e.unit})`:e.label}function dn(e){let t=structuredClone(e),{plan:r,problems:n}=WM(t);if(!r)throw new Qu(t.id,n);let o=new WeakMap,a=p=>{let d=o.get(p);return d||(d=Cb(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 Tb(b);let g=h,y=i.get(p);return y!==void 0?Tb(g.parts?.[y]):p===t.score?.total?Tb(g.total):NaN},l=t.kpis.filter(p=>!p.hidden).map(p=>{let d=r.field.has(p.key);return{key:p.key,label:n2(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=Ai(r,p),h={};for(let[b,g]of Object.entries(d)){let y={},x={};for(let[M,v]of Object.entries(u.parts)){y[M]=g[v];let R=s.get(v)?.max;R!=null&&(x[M]=R)}h[b]={total:g[u.total],parts:y,...Object.keys(x).length?{maxima:x}:{},kpis:Object.fromEntries(t.kpis.map(M=>[M.key,g[M.key]]))}}return h}:void 0,f=m||(r.field.size>0?p=>{let d=Ai(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"},jM=[{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}],UM=[{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"}],XM={total:"overall",parts:{[Wt.accel]:"accelPts",[Wt.skidpad]:"skidpadPts",[Wt.autocross]:"autocrossPts",[Wt.endurance]:"endurancePts",efficiency:"efficiencyPts"}},QM={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:jM,kpis:UM,score:XM,track:{minTurnRadius:4.5},battery:ly,traceEventId:Wt.autocross},qM={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:jM,kpis:UM,score:XM,track:{minTurnRadius:4.5},traceEventId:Wt.autocross},Ci=dn(QM),Pb=dn(qM);var Lb="lap",o2=[{kind:"trackLap",id:Lb,label:ju,laps:1}],ZM={id:"trackday",label:"Track day",description:"One flying lap of the selected track. Times and traces only \u2014 no scoring.",events:o2,kpis:[{key:"lap",label:"Lap time",format:"time",lowerBetter:!0,expr:"lap.time"},{key:"topSpeed",label:"Top speed",unit:"km/h",over:Lb,expr:"peak(speed)"},{key:"energy",label:"Energy / lap",unit:"kWh",lowerBetter:!0,expr:"lap.energy"}],traceEventId:Lb},Db=dn(ZM);function fn(e){if(e===null||typeof e!="object")return JSON.stringify(e)??"null";if(Array.isArray(e))return`[${e.map(fn).join(",")}]`;let t=e,r=Object.keys(t).sort(),n=[];for(let o of r)t[o]!==void 0&&n.push(`${JSON.stringify(o)}:${fn(t[o])}`);return`{${n.join(",")}}`}function eo(e){let t=fn(e),r=2166136261;for(let n=0;n<t.length;n++)r^=t.charCodeAt(n),r=r+((r<<1)+(r<<4)+(r<<7)+(r<<8)+(r<<24))>>>0;return r.toString(16).padStart(8,"0").slice(-6)}var Ta=[Ci,Pb,Db],to=Ci.id,Pa=e=>Ta.some(t=>t.id===e),JM=new WeakMap,Ti=new Map,a2=64;function Zu(e){let t=JM.get(e);if(t!==void 0)return t;let r=fn(e),n=Ti.get(r);return n===void 0&&(n=qu(e).length?null:dn(e),Ti.size>=a2&&Ti.delete(Ti.keys().next().value),Ti.set(r,n)),JM.set(e,n),n}function Ju(e,t=[]){if(e==null)return;if(typeof e!="string")return Zu(e)??void 0;let r=Ta.find(o=>o.id===e);if(r)return r;let n=t.find(o=>o.id===e);return n?Zu(n)??void 0:void 0}function ro(e,t=[]){return Ju(e,t)??Ci}function Eb(e=[]){let t=e.filter(r=>!Pa(r.id)).map(r=>Zu(r)).filter(r=>r!==null);return[...Ta,...t]}var Pi=e=>e.definition??e.id;function em(e,t,r){let n=e.length,o=new Array(n);for(let d=0;d<n;d++){let h=d+1<n?e[d+1]:r;o[d]=h-e[d]}let a=new Array(n).fill(0),s=new Array(n).fill(0),i=new Array(n).fill(0),c=new Array(n).fill(0);for(let d=0;d<n;d++){let h=o[(d-1+n)%n],b=o[d];a[d]=h,s[d]=2*(h+b),i[d]=b;let g=t[(d+1)%n],y=t[(d-1+n)%n];c[d]=6*((g-t[d])/b-(t[d]-y)/h)}let l=s2(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],x=t[(d+1)%n];u[d]=y,f[d]=b/2,p[d]=(g-b)/(6*h),m[d]=(x-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 _b(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=Ib(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 s2(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=Ib(e,c,r,n),u=new Array(o).fill(0);u[0]=i,u[o-1]=s;let m=Ib(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 Ib(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 Li(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 eS(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 tS(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 rS(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=>eS(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=tS([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 i2(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=eS(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 c2(e,t,r){let{j:n,t:o}=i2(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=tS([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 Nb(e,t){return t>0?e.z.map((r,n)=>{let o=c2(e,n,t/2);return o?o.value.reduce((a,s,i)=>a+s*e.z[o.j[i]],0):r}):[...e.z]}function l2(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 tm(e){let t=Li(e);if(!t)return 0;let r=rS(t);return r>1e-6?Math.max(10,l2(r,u2(t))):0}function u2(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 ur(e,t,r){let n=e.n;if(e.closed===!1){let a=r-t;return a===0?e.diag[t]:a===1?e.off1[t]:a===2?e.off2[t]:a===-1?e.off1[r]:a===-2?e.off2[r]:0}let o=((r-t)%n+n)%n;return o===0?e.diag[t]:o===1?e.off1[t]:o===2?e.off2[t]:o===n-1?e.off1[r]:o===n-2?e.off2[r]:0}function nm(e,t){let r=e.n,n=new Array(r).fill(0);for(let o=0;o<r;o++){let a=e.diag[o]*t[o];for(let[s,i]of[[1,e.off1],[2,e.off2]]){(o+s<r||e.closed!==!1)&&(a+=i[o]*t[(o+s)%r]);let c=(o-s+r)%r;(o-s>=0||e.closed!==!1)&&(a+=i[c]*t[c])}n[o]=a}return n}function nS(e,t){let r=new Array(e).fill(0),n=new Array(e).fill(0),o=new Array(e).fill(0);for(let a=0;a<e;a++){a>=2&&(o[a]=r[a-2]!==0?t(a,a-2)/r[a-2]:0),a>=1&&(n[a]=r[a-1]!==0?(t(a,a-1)-o[a]*n[a-1])/r[a-1]:0);let s=t(a,a)-n[a]*n[a]-o[a]*o[a];if(!(s>0)||!Number.isFinite(s))return null;r[a]=Math.sqrt(s)}return{d:r,l1:n,l2:o}}function rm(e,t){let r=t.length,n=new Array(r).fill(0);for(let a=0;a<r;a++){let s=t[a];a>=1&&(s-=e.l1[a]*n[a-1]),a>=2&&(s-=e.l2[a]*n[a-2]),n[a]=s/e.d[a]}let o=new Array(r).fill(0);for(let a=r-1;a>=0;a--){let s=n[a];a+1<r&&(s-=e.l1[a+1]*o[a+1]),a+2<r&&(s-=e.l2[a+2]*o[a+2]),o[a]=s/e.d[a]}return o}function m2(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 Ob(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=nS(r,(y,x)=>ur(e,y,x));if(!b)return null;let g=rm(b,t);return g.every(Number.isFinite)?g:null}let n=r-2,a=nS(n,(b,g)=>ur(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]=ur(e,b,r-2),i[b]=ur(e,b,r-1);let c=rm(a,t.slice(0,n)),l=rm(a,s),u=rm(a,i),m=(b,g)=>{let y=0;for(let x=0;x<b.length;x++)y+=b[x]*g[x];return y},f=[[ur(e,r-2,r-2)-m(s,l),ur(e,r-2,r-1)-m(s,u)],[ur(e,r-1,r-2)-m(i,l),ur(e,r-1,r-1)-m(i,u)]],p=[t[r-2]-m(s,c),t[r-1]-m(i,c)],d=m2(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 oS(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=Ob(i,t);if(c){let l=nm(i,c).map((m,f)=>m-t[f]);if(Math.sqrt(l.reduce((m,f)=>m+f*f,0))<=1e-6*Math.max(a,1e-12))return c}o=o===0?n*1e-12:o*10}return null}var aS=4,p2=8,Vb=.001;function d2(e,t,r){let n=[];for(let c=1;c<e.length;c++){let l=e[c]-e[c-1];l>=Vb&&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/fk(r,s,i)))}function f2(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])<Vb||(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:d2(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])<Vb;)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?em(b.slice(0,d),n,b[d]):_b(b,n),y=r?em(b.slice(0,d),o,b[d]):_b(b,o),x=new Array(h);for(let F=0;F<h;F++)x[F]=b[F+1]-b[F];let M=[0],v=[0],R=[0],k=0;for(let F=0;F<h;F++){let w=x[F]/aS;for(let C=0;C<aS;C++){let T=C*w;k+=Kf(S=>Math.hypot(g.d1(F,S),y.d1(F,S)),T,T+w),M.push(k),v.push(F),R.push(T+w)}}return{closed:r,sx:g,sy:y,h:x,sTable:M,segTable:v,uTable:R,length:k,rawCum:c,rawLength:l}}function Di(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 h2=.01,b2=3,sS=10;function g2(e,t,r,n=sS){let o={step:0,uncertainty:1/0},a=e.length;if(a<8||!(r>0))return o;let s=Math.max(sS,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=(x,M,v)=>{let R=x/s;m.push([1,R,R*R,R*R*R,M]),f.push(v)};for(let x=0;x<u;x++)p(t[x]+i,1,e[x]);for(let x=0;x<u;x++)p(t[a-1-x]-r+i,0,e[a-1-x]);let d=Array.from({length:5},()=>new Array(5).fill(0)),h=new Array(5).fill(0);m.forEach((x,M)=>{for(let v=0;v<5;v++){h[v]+=x[v]*f[M];for(let R=0;R<5;R++)d[v][R]+=x[v]*x[R]}});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((x,M)=>{let v=0;for(let R=0;R<5;R++)v+=x[R]*b.x[R];y+=(f[M]-v)**2}),{step:b.x[4],uncertainty:Math.sqrt(y/(m.length-5)*g.x[4])}}function y2(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 x2(e,t,r){let{pos:n,loop:o}=y2(e.length,t),{step:a,uncertainty:s}=g2(e,n,o,r);return Math.abs(a)>Math.max(h2,b2*s)?{z:e.map((i,c)=>i+a*n[c]/o),drift:-a}:{z:e,drift:0}}function R2(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 x=m+Kf(v=>Math.hypot(s.d1(p,v),i.d1(p,v)),h,g),M=Math.hypot(s.d1(p,g),i.d1(p,g));if(M<1e-12)break;g-=(x-t)/M}return{seg:p,du:Math.min(Math.max(g,0),a[p])}}var v2=3,Bb=5;function k2(e,t,r,n=Bb){return am(e,t,r,n)}function am(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 Ob({n:a,diag:i,off1:c,off2:l,closed:r},u)??[...e]}function st(e,t){let r=at(t),n=f2(e,r.fitSpacing),o=n.length,a=Math.max(p2,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}=R2(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),$=Math.hypot(P,L),O=Math.pow(P*P+L*L,1.5);f[C]=O>0?(P*E-L*D)/O:0,p[C]=$>0?-L/$:0,d[C]=$>0?P/$: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?x2(e.z,n.rawCum,g):null,x=y?y.z:e.z,M=g>0?Li(e):null,v=M?Nb({...M,z:x},g):x,R=Di(v,0,h,n),k=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=R[S]-R[A];k[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=R[S]-R[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(v2,e.zReach??tm(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),$=0,O=0;for(let _=-T;_<=T;_++){let V=R[n.closed?(E+_+s)%s:E+_];$+=(_*_-S/P)*V,O+=_*V}let W=2*$/L/(i*i),I=O/S/i;w[D]=W/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?k2(f,i,n.closed,e.turnReach):f,npts:s,length:F,nx:p,ny:d,z:R,gradient:k,...w?{verticalCurvature:w}:{},widthLeft:Di(e.widthLeft,1.5,h,n),widthRight:Di(e.widthRight,1.5,h,n),bank:Di(e.bank,0,h,n),mu:Di(e.mu,1,h,n),...y?.drift?{elevationDrift:y.drift}:{}}}function iS(e,t,r){let n=nm(e,r),o=0;for(let a=0;a<r.length;a++)o+=.5*r[a]*n[a]-t[a]*r[a];return o}function M2(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]-=ur(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 oS(c,i)}var S2=1e-4;function cS(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=iS(e,t,u),f=new Array(a).fill("free"),p=!1;for(let d=0;d<s;d++){let h=nm(e,u).map((x,M)=>x-t[M]),b=!1;for(let x=0;x<a;x++){let M=u[x]<=r[x]+i&&h[x]>=-i?"lo":u[x]>=n[x]-i&&h[x]<=i?"hi":"free";M!==f[x]&&(f[x]=M,b=!0)}if(p&&!b)return{x:u,iterations:d+1,converged:!0,bounds:f};let g=M2(e,t,f,x=>u[x]);if(!g)return{x:u,iterations:d+1,converged:!1,bounds:f};let y=!1;for(let x=1;x>1e-12;x*=.5){let M=!1,v=u.map((F,w)=>{if(f[w]!=="free")return F;let C=F+x*(g[w]-F),T=l(C,w);return T!==C&&(M=!0),T}),R=iS(e,t,v),k=0;for(let F=0;F<a;F++)k+=h[F]*(v[F]-u[F]);if(x===1&&!M||R<m&&R<=m+S2*k){u=v,m=R,p=x===1&&!M,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 $b={lineStep:2,carHalfWidth:.75,margin:.1,foldMargin:.25,referenceReach:5,passes:40,iterations:400},A2=[1,.5,.25,.125,.0625,.03125,.015625,.0078125,.00390625,.001953125,.0009765625],F2=e=>Math.sqrt(e.reduce((t,r)=>t+r*r,0)/(e.length||1));function Ei(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 w2=Math.PI/180,lS=20;function C2(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?lS:Math.min(lS,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),x=n?(y+1)%r:Math.min(y+1,r-1);return e.z[y]+(g-y)*(e.z[x]-e.z[y])})}function T2(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?C2(t,r):t.z;return{...n||o?{z:s.map((i,c)=>i+r[c]*Math.tan(t.bank[c]*w2))}:{},...n?{zReach:e.zReach??tm(e)}:{},...o?{bank:[...t.bank]}:{},...a?{mu:[...t.mu]}:{}}}function uS(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 P2(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),x=Math.hypot(d,h),M=Math.hypot(b,g),v=y*x*M;if(!(v>1e-12))continue;let R=2*c(f,p,d,h)/v,k=Math.sqrt(.5*(y+x)),F=R/(2*k),w=(f*r[u]+p*n[u])/y,C=(b*r[u]+g*n[u])/M,T=(f*r[l]+p*n[l])/y,S=(d*r[l]+h*n[l])/x,A=(d*r[m]+h*n[m])/x,P=(b*r[m]+g*n[m])/M,L=-2*c(r[u],n[u],d,h)/v+R*(w/y+C/M),D=2*c(r[l],n[l],b,g)/v-R*(T/y-S/x),E=2*c(f,p,r[m],n[m])/v-R*(A/x+P/M);s[l]=R*k,i.l[l]=k*L-F*.5*w,i.d[l]=k*D+F*.5*(T-S),i.r[l]=k*E+F*.5*A}return{res:s,jac:i}}function L2(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 D2(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=am(e.x,s,n,t,!0),c=am(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=Ei(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 E2=6;function I2(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(E2/(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 Gb(e,t={}){let r={...$b,...t},n=st(e,{dsTarget:r.lineStep}),o=D2(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=Ei(T.x,T.y,o.closed),A=uS(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=F2(n.curvature),l=uS(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];I2(o,f,p,r.foldMargin);let g=T=>{let S=s(T),A=T2(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:Bb},L=1e-6,D=T.filter((I,_)=>I>=f[_]-L||I<=p[_]+L).length,E=Ei(S.x,S.y,o.closed),$=I=>1/Math.max(...I.map(Math.abs),1e-9),O=0,W=o.closed?S.x.length:S.x.length-1;for(let I=0;I<W;I++){let _=(I+1)%S.x.length,V=S.x[_]-S.x[I],N=S.y[_]-S.y[I];O+=A.z?Math.hypot(V,N,A.z[_]-A.z[I]):Math.hypot(V,N)}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:O},worstRadius:{centreLine:$(n.curvature),racingLine:$(E)}}},y=o.closed?0:1,x=o.closed?a-1:a-2,M=x-y+1,v=new Array(M),R=new Array(M);for(let T=0;T<M;T++)v[T]=p[y+T],R[T]=f[y+T];if(!o.closed&&M>0){let T=(S,A)=>{if(v[S]=Math.max(v[S],p[A]),R[S]=Math.min(R[S],f[A]),v[S]>R[S]){let P=.5*(v[S]+R[S]);v[S]=P,R[S]=P}};T(0,0),T(M-1,a-1),v[0]=R[0]=Math.min(R[0],Math.max(v[0],0))}if(M<7)return g(u);let k=T=>{let S=s(T),P=[...Ei(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=k(u),C;for(let T=0;T<r.passes;T++){let S=s(F),{res:A,jac:P}=P2(S.x,S.y,o.nx,o.ny,o.closed),{M:L,b:D}=L2(P,A,y,x,o.closed),E=cS(L,D,v.map((W,I)=>W-F[y+I]),R.map((W,I)=>W-F[y+I]),{maxIter:r.iterations,bounds:C});C=E.bounds;let $=new Array(a).fill(0);for(let W=0;W<M;W++)$[y+W]=E.x[W];o.closed||($[0]=$[1],$[a-1]=$[a-2]);let O=!1;for(let W of A2){let I=F.map((V,N)=>V+W*$[N]),_=k(I);if(_.integral<w.integral*(1-1e-6)){F=I,w=_,O=!0;break}}if(!O)break}return g(F)}function Kb(e){let t=Math.max(Z(e,"track_front"),Z(e,"track_rear"));return(t>0?t/2e3:.6)+.1}function sm(e,t,r={}){if(!r.racingLine)return{asset:e,numerics:t,line:null};let n=r.params?Kb(r.params):void 0,o=Gb(e,{...r.line,...n?{carHalfWidth:n}:{}});return{asset:o.asset,numerics:{...t,fitSpacing:0},line:o}}function Ii(e,t,r={}){let n=sm(e,t,r);return{track:st(n.asset,n.numerics),line:n.line}}function Hb(e=4,t=Ii){let r=new WeakMap;return(n,o,a={})=>{let s=a.racingLine===!0,i=s?[a.params?Kb(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 mS={racingLine:!1,standingStart:!1},im=256;function _i(e,t,r,n,o=mS,a=Ii){let s=ro(n),{racingLine:i,standingStart:c,lapCounts:l}=o;return e.map(u=>{let{track:m}=a(t,r,{racingLine:i,params:u});return Mb(vi(u,s,{track:m,numerics:r,standingStart:c,lapCounts:l}))})}function zb(e,t){let r=ro(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 Yb(e,t,r){let n={};for(let o of ro(e).metrics)n[o.key]=o.value(t,r);return n}var cm=36;var Ub=287.05287,N2=461.495,lm=9.80665/(Ub*.0065),O2=101325/(Ub*288.15),V2=273.15,B2=-500,$2=6e3,G2=400,K2=1100,um={source:"car",altitudeM:0,pressure:{kind:"standard"},humidityPct:0};function H2(e){return 101325*Math.pow(1-.0065*e/288.15,lm)}function z2(e){return 288.15/.0065*(1-Math.pow(e/O2,1/(lm-1)))}function Y2(e){return 288.15/.0065*(1-Math.pow(e/101325,1/lm))}function W2(e,t){return e*Math.pow(1-.0065*t/288.15,lm)}function j2(e){return 611.21*Math.exp((18.678-e/234.5)*(e/(257.14+e)))}function U2(e,t){switch(e.kind){case"standard":return H2(t);case"qnh":return W2(e.hPa*100,t);case"station":return e.hPa*100}}function Ni(e,t,r=0,n=Y2(e)){let o=t+V2,a=Math.min(.5*e,Math.max(0,Math.min(100,r))/100*j2(t)),s=e-a,i=s/(Ub*o)+a/(N2*o);return{altitudeM:n,p:e,pDry:s,T:o,rho:i,densityAltitudeM:z2(i)}}function pS(e,t){return Ni(U2(e.pressure,e.altitudeM),t,e.humidityPct,e.altitudeM)}var Wb=(e,t,r)=>Math.min(r,Math.max(t,e)),jb=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function mm(e){if(!e||typeof e!="object")return structuredClone(um);let t=e,r=t.pressure??{},n=Wb(jb(r.hPa,1013.25),G2,K2),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:Wb(jb(t.altitudeM,0),B2,$2),pressure:o,humidityPct:Wb(jb(t.humidityPct,0),0,100)}}var Oi=e=>e?.source==="venue";var X2=Math.PI/180;function Q2(){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 q2(){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 Xb(e){let t=-e*X2;return Q([0,Math.cos(t),Math.sin(t)])}function pm(){let e={rodType:"push",pushrodAttach:"lowerArm",steerMode:"rack",spinAxis:Xb(-1),loadedRadius:230,springRate:35,rackAxis:[0,1,0]};return{hardpoints:Q2(),config:e}}function Vi(){let e={rodType:"pull",pushrodAttach:"lowerArm",steerMode:"fixed",spinAxis:Xb(-1.5),loadedRadius:232,springRate:40,rackAxis:[0,1,0]};return{hardpoints:q2(),config:e}}function dm(){let e=[-25,635,460],t=[-40,600,710],r={layout:"mcpherson",actuation:"direct",rodType:"push",pushrodAttach:"upright",steerMode:"rack",spinAxis:Xb(-.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 Qb(){return{front:pm(),rear:Vi(),config:{wheelbase:1600,trackFront:1200,trackRear:1220,frontAxleX:800}}}var Z2=Math.PI/180;function dS(e){let t=-e*Z2;return Q([0,Math.cos(t),Math.sin(t)])}function qb(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:dS(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]=J2(o[l]);return{hardpoints:o,config:c}}function J2(e){return e.map(t=>Math.round(t*10)/10+0)}function oo(e){return{name:e.name,front:qb(pm(),e.front),rear:qb(Vi(),e.rear),config:{wheelbase:e.wheelbase,trackFront:e.trackFront,trackRear:e.trackRear,frontAxleX:e.wheelbase/2}}}function La(e,t,r){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:t}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:r}}}}var Da=600,ao=610,Ea=230,so=232;function io(){let e=Qb();return{...e,name:"Formula Student",front:{...e.front,config:{...e.front.config,actuation:"rocker"}},rear:{...e.rear,config:{...e.rear.config,actuation:"rocker"}}}}function Zb(){return oo({name:"Formula 1",wheelbase:3600,trackFront:1600,trackRear:1600,front:{kx:1.3,ky:800/Da,kz:355/Ea,lowerInnerDz:-5,upperInnerDz:0,camberDeg:-3,loadedRadius:355,springRate:200},rear:{kx:1.3,ky:800/ao,kz:355/so,lowerInnerDz:35,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:220}})}function Bi(){return La(oo({name:"GT car",wheelbase:2700,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/Da,kz:325/Ea,lowerInnerDz:18,upperInnerDz:5,camberDeg:-3.5,loadedRadius:325,springRate:110,actuation:"direct"},rear:{kx:1.2,ky:825/ao,kz:325/so,lowerInnerDz:36,upperInnerDz:15,camberDeg:-2,loadedRadius:325,springRate:120,actuation:"direct"}}),318.6,318.6)}function $i(){return La(oo({name:"Sports car",wheelbase:2750,trackFront:1550,trackRear:1550,front:{kx:1.15,ky:775/Da,kz:320/Ea,lowerInnerDz:36,upperInnerDz:15,camberDeg:-.5,loadedRadius:320,springRate:55,actuation:"direct"},rear:{kx:1.15,ky:775/ao,kz:320/so,lowerInnerDz:57,upperInnerDz:25,camberDeg:-1,loadedRadius:320,springRate:60,actuation:"direct"}}),305.4,309)}function e_(e,t,r,n,o,a){let s=dm(),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:dS(n),springRate:o,rackTravel:a}}}function fS(){return La({name:"Cup car",front:e_(55,-25,-23,-3.5,150,55),rear:qb(Vi(),{kx:1.15,ky:820/ao,kz:320/so,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 hS(){return{...La(oo({name:"Stock car",wheelbase:2794,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/Da,kz:355/Ea,lowerInnerDz:20,upperInnerDz:5,camberDeg:-2.5,loadedRadius:355,springRate:175,actuation:"direct"},rear:{kx:1.2,ky:825/ao,kz:355/so,lowerInnerDz:40,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:150,actuation:"direct"}}),343.8,345.3),chassis:{boxes:[],body:"nascar"}}}function bS(){let e=La(oo({name:"Hill-climb prototype",wheelbase:2550,trackFront:1580,trackRear:1540,front:{kx:1.1,ky:790/Da,kz:300/Ea,lowerInnerDz:10,upperInnerDz:5,camberDeg:-2.5,loadedRadius:300,springRate:90},rear:{kx:1.1,ky:770/ao,kz:300/so,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 gS(){let e=La(oo({name:"Race truck",wheelbase:3700,trackFront:2050,trackRear:1950,front:{kx:1.5,ky:1025/Da,kz:506/Ea,lowerInnerDz:40,upperInnerDz:10,camberDeg:-.5,loadedRadius:506,springRate:200,actuation:"direct"},rear:{kx:1.5,ky:975/ao,kz:506/so,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 tt=(e,t,r)=>({value:e,label:t,unit:r}),yS=(e,t)=>({...nr[e],value:t});function xS(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 co(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:tt(e.m,"vehicle mass (with driver)","kg"),A:tt(e.A,"frontal area","m^2"),c_l:tt(e.cl,"downforce coefficient","-"),c_w:tt(e.cw,"drag coefficient","-"),l_to_d_ratio:tt(e.cw>0?e.cl/e.cw:0,"lift-to-drag ratio","-"),driven_wheels:tt(e.drivenWheels,"driven wheels","-"),fr_0:tt(-.012,"rolling-resistance coefficient","-"),front_aero_diss:tt(e.frontAero,"front aero distribution","-"),front_mass_diss:tt(e.frontMass,"front mass distribution","-"),r_dyn:tt(e.rDyn,"dynamic tyre radius","m"),rho:tt(1.2,"air density","kg/m^3"),gear_ratio:tt(e.gearRatio,"gear ratio","-"),effi_pgb:tt(e.drivetrainEfficiency,"drivetrain efficiency","-"),capacity:tt(e.capacityAh,"pack capacity","Ah"),soc:tt(1,"state of charge","-"),ocv:tt(e.ocv,"pack open-circuit voltage","V"),power_scale:tt(1,"power scaling factor","-"),power_limit_kw:yS("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]=yS(r,n);return t}var Ia={name:"Formula Student",m:300,A:1,cl:3,cw:1.3,frontMass:.47,frontAero:.45,rDyn:.222,drivenWheels:2,gearRatio:11.5,motor:xS(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}},eg={name:"Formula 1",m:798,A:1.5,cl:3,cw:.9,frontMass:.46,frontAero:.44,rDyn:.35,drivenWheels:2,gearRatio:4.9,motor:co(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}},fm={name:"GT car",m:1300,A:2,cl:1.4,cw:.42,frontMass:.5,frontAero:.42,rDyn:.33,drivenWheels:2,gearRatio:3.43,motor:co(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}},hm={name:"Sports car",m:1600,A:2.2,cl:-.1,cw:.3,frontMass:.55,frontAero:.5,rDyn:.32,drivenWheels:2,gearRatio:3.14,motor:co(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}},tg={name:"Cup car",m:1265,A:2.1,cl:.45,cw:.4,frontMass:.62,frontAero:.45,rDyn:.31,drivenWheels:2,gearRatio:3.5,motor:co(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}},rg={name:"Stock car",m:1620,A:2.2,cl:.6,cw:.45,frontMass:.53,frontAero:.45,rDyn:.35,drivenWheels:2,gearRatio:4.1,motor:co(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}},ng={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:co(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}},og={name:"Race truck",m:5300,A:6.2,cl:-.1,cw:.65,frontMass:.6,frontAero:.6,rDyn:.502,drivenWheels:2,gearRatio:3.55,motor:co(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 Jb(e,t,r){return Gr(r({...structuredClone(e),name:t}))}var bm={[Ia.name]:Gr(Ia),"Formula Student +15% downforce":Jb(Ia,"Formula Student +15% downforce",e=>({...e,cl:e.cl*1.15,cw:e.cw*1.08})),"Formula Student -15 kg":Jb(Ia,"Formula Student -15 kg",e=>({...e,m:e.m-15})),"Formula Student +15% power":Jb(Ia,"Formula Student +15% power",e=>({...e,motor:xS(25*1.15,15e3,2e4),powerLimitKw:80*1.15})),[eg.name]:Gr(eg),[fm.name]:Gr(fm),[hm.name]:Gr(hm),[tg.name]:Gr(tg),[rg.name]:Gr(rg),[ng.name]:Gr(ng),[og.name]:Gr(og)},RS=Object.keys(bm),ag=RS.slice(0,4),sg=[Ia.name,eg.name,fm.name,hm.name,tg.name,rg.name,ng.name,og.name];var bte={"Touring car":fm.name,"Street car":hm.name};var t_={bg:"#0e1116",panel:"#161b22",panel2:"#1c232d",border:"#2a323d",borderBright:"#39424e",sunken:"#11161c",ink:"#06090d"},r_={normal:"#d6dde6",dim:"#8b96a3",bright:"#e7ecf3",white:"#ffffff"},n_={label:"#c8d2dc",grid:"#39424e",gridFaint:"#232b35",empty:"#1a2028"},o_={accent:"#4aa3ff",accentInk:"#04121f",warn:"#ffb454",good:"#4ec9a0",bad:"#ff6b6b",badSoft:"#ff8f8f"},a_=["#f0e442","#7b68ee","#f7a8b8","#d55e00","#d8b4fe","#b5e48c"],gm={front:"#a6e22e",rear:"#00b4d8"},vS=["#5b4bd6","#4aa3ff","#4ec9a0","#f0e442"],ig={power:"#ffb454",traction:"#f0845c",front:gm.front,rear:gm.rear,grip:"#73c9b3",braking:"#b48aff",crest:"#e88fd0",below:"rgba(214, 221, 230, 0.32)"},s_={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"},i_={x:"#ff6b6b",y:"#57c75a",z:"#4aa3ff"},c_={line:"#b4bfcb"},l_={compression:"#b48aff",tension:"#ff6b6b"},u_={fz:"#e7ecf3",fx:"#7ad7f0",fy:"#ff54c8"},m_={drivenLine:"#4d7cff",axis:"#eef3fa",slip:"#ffe81a",drive:ig.power,brake:ig.braking},p_={ground:"#101920",grid:"#1a2630",gridMajor:"#26343f",horizon:"#1d2833",bridge:"#6f7a86",coneLeft:"#2f63c9",coneRight:"#d9b51f",coneStart:"#ee7a2c"},d_={chassis:"#435160",volume:"#303b47",tyre:"#435160",tyreLine:"#39424e",tyreFace:"#1c232d"},f_={centreLine:"#4aa3ff",corridorFill:"rgba(74,163,255,0.10)",boundary:"#3d4956",racingLine:"#ffb454",start:"#e7ecf3",finish:"#ff6b6b",direction:"#8b96a3"},h_={SURFACE:t_,TEXT:r_,CHART:n_,ROLE:o_,SERIES:a_,AXLE:gm,LAP_SPEED:vS,LIMITER:ig,RIG:s_,AXIS:i_,CONSTRUCTION:c_,FORCE:l_,TYRE_FORCE:u_,REPLAY:m_,SCENERY:p_,BODY:d_,TRACK:f_},kS=e=>Object.fromEntries(Object.entries(e).map(([t,r])=>[t,Array.isArray(r)?Object.freeze([...r]):Object.freeze({...r})])),ym=kS(h_),vt=ym.SERIES,MS=(()=>{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 kS({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 SS=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},yte=(()=>{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=ym[r],o=MS[r];for(let a of Object.keys(n)){let s=SS(n[a]);s&&!e.has(s)&&e.set(s,o[a])}}return e})();var AS=(e,t)=>new Set(t.flatMap(r=>{let n=e[r];return Array.isArray(n)?[...n]:Object.values(n)}).map(SS).filter(r=>r!==null)),xte=AS(MS,["SERIES","AXLE","LAP_SPEED","LIMITER","ROLE","RIG","FORCE","TYRE_FORCE","REPLAY","AXIS","TRACK","CONSTRUCTION"]),Rte=AS(ym,Object.keys(ym).filter(e=>e!=="SURFACE"));function cg(){return{kind:"simple",name:"Simple motor",rpm:[0,16e3,2e4],torque:[21,21,14],efficiency:.95}}function lg(){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 ug(){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 mg(){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 pg(){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 FS(){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 wS(){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 CS(){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 TS(){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 PS(){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 LS(){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 DS(e){return eo(b_(e))}function b_(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 Gi(e,t){return{...t,fingerprint:DS(e)}}var ES="CC-BY-4.0",g_={title:"PaceDynamics built-in library",url:"https://pacedyn.dev/",licence:ES},IS={fidelity:"generic",licence:ES,sources:[g_]};var xm=e=>Gi(e,IS);var _S=["raw.githubusercontent.com"],NS=["tum-csv"],x_=/^[0-9a-f]{64}$/;function Hi(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"||!x_.test(r)||!NS.includes(n))return!1;try{let o=new URL(t);return o.protocol==="https:"&&_S.includes(o.hostname)&&!o.username&&!o.password&&!o.port}catch{return!1}}var Rm=e=>new URL(e.url).hostname;async function OS(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 R_(e){let t=new URL(e).pathname.split("/").pop()??"";return decodeURIComponent(t).replace(/\.[^.]*$/,"")||"Linked track"}function v_(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 k_={"tum-csv":v_};function VS(e,t){return k_[t.format](e,R_(t.url))}async function dg(e,t,r){let n=await OS(e);if(n!==t.sha256)throw new Error(`${Rm(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=VS(new TextDecoder().decode(e),t),a=await vm(o);if(a!==r)throw new Error(`Linked track ${r} does not convert to its name (it is ${a}).`);return o}var fg=20,S_=new RegExp(`^[0-9a-f]{${fg}}$`),zi=e=>typeof e=="string"&&S_.test(e);async function vm(e){let t=new TextEncoder().encode(fn(e)),r=await globalThis.crypto.subtle.digest("SHA-256",t);return[...new Uint8Array(r)].map(n=>n.toString(16).padStart(2,"0")).join("").slice(0,fg)}var hg=e=>`tracks/${e}.json`;var A_=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function bg(e){return{model:{name:e.name,source:e.source},...e.provenance?{provenance:e.provenance}:{}}}async function gg(e,t){if(!A_(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 vm(e);if(r!==t)throw new Error(`Catalogue track ${t} does not match its name (it is ${r}).`);return e}var lo=(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}),hn=[lo("suspensions","suspensionId","suspension"),lo("tires","tireModelId","tyre",[{key:"tiresRear",ref:"tireModelIdRear",label:"rear tyre"}]),lo("motors","motorModelId","motor"),lo("aeros","aeroModelId","aero map"),lo("batteries","batteryModelId","battery"),lo("brakes","brakeModelId","brakes"),lo("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 km(e){let t={...e};for(let r of hn)for(let n of r.refs)delete t[n];return t}var Mm=vt,Yi=Mm,yg=Mm,bn=[...vt.slice(3),...vt.slice(0,3)],vg=[...vt.slice(1),vt[0]],xg=[...vt.slice(2),...vt.slice(0,2)],Rg=[...vt.slice(4),...vt.slice(0,4)],kg=[...vt.slice(5),...vt.slice(0,5)],Wi=[...vt.slice(2),...vt.slice(0,2)];function Mg(){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 Sg(e,t,r){let n=bm[e];if(!n)throw new Error(`no preset vehicle named "${e}"`);return{id:t,params:{...Xs(structuredClone(n)),energy:{...wr},suspensionId:"sus1"},visible:!0,color:Yi[r%Yi.length]}}function C_(){return ag.map((e,t)=>Sg(e,`v${t+1}`,t))}function T_(){return[Fs(),af(),sf(),cf(),lf(),uf(),mf(),pf(),df(),ff()].map((t,r)=>({id:`t${r+1}`,color:yg[r%yg.length],model:t}))}function P_(){return[Kp(),Hp(),zp(),Yp(),Wp(),jp(),Up(),Xp()].map((t,r)=>({id:`a${r+1}`,color:xg[r%xg.length],model:t}))}function L_(){return[wp(),Cp(),Tp()].map((t,r)=>({id:`b${r+1}`,color:Rg[r%Rg.length],model:t}))}function D_(){return[{id:"brk1",color:kg[0],model:structuredClone(Ef)}]}function E_(){return[{id:"dmp1",color:Wi[0],model:structuredClone(tu)}]}function I_(){return[cg(),lg()].map((t,r)=>({id:`m${r+1}`,color:bn[r%bn.length],model:t}))}function Ag(e){let t=r=>({...r,provenance:xm(r.model)});return{...e,suspensions:e.suspensions.map(t),vehicles:e.vehicles.map(r=>({...r,provenance:xm(km(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 ji(e="Untitled project"){let t=new Date().toISOString(),r=C_();return Ag({schemaVersion:cm,meta:{id:Mg(),name:e,domain:"racecar",rulesetId:to,createdAt:t,updatedAt:t},suspensions:[{id:"sus1",color:vg[0],model:io()}],activeSuspensionId:"sus1",vehicles:r,activeVehicleId:r[0]?.id??null,tires:T_(),motors:I_(),aeros:P_(),batteries:L_(),brakes:D_(),dampers:E_(),tracks:[],activeTrackId:null,mathChannels:[],rulesets:[],studies:[],activeStudyId:null,loadCases:[],reportLayouts:[],tyreSheets:[],kinSheets:[],plans:[],results:[],settings:{numerics:{...mi},ggvMode:"twoTrack",quasiTransient:!1,motorThermal:!1,brakeFade:!1,airTempC:At,air:structuredClone(um),diffYaw:!1,lapCounts:{},pathPlanId:null,useRacingLine:!0,standingStart:!1}})}var __=["front","rear"],Fg=9.81,N_=Math.PI/180;var uo="*",wg=40,BS=.8;function Cg(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 $S(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/Fg*100)/100+0,axG:Math.round(u/Fg*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(wg/3.6,o(wg/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(BS*s,o(BS*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 Tg(e,t,r){let n=!1,o=e.map(a=>{if(!a.follows)return a;let s=$S(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 Pg(e,t){let r=e.speedKmh/3.6,n=e.ayG*Fg;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)/N_}var GS=e=>e.ayG<0?"L":"R";function Lg(e,t=__){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 Dg=(e,t)=>e.travelMin===t.travelMin&&e.travelMax===t.travelMax&&e.rollMaxDeg===t.rollMaxDeg&&e.rollAtLimitDeg===t.rollAtLimitDeg;var O_=9.81,V_=Math.PI/180,Ui={speed:20,ayG:1.2};function Eg(e,t={}){let r=t.operating??Ui,n=t.assemble,o,a,s,i=new Map,c=new Map,l=new Map,u=new Map,m=new Map,f=x=>({speed:x?.speed!==void 0&&Number.isFinite(x.speed)&&x.speed>0?x.speed:r.speed,ayG:x?.ayG!==void 0&&Number.isFinite(x.ayG)?x.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=sr(e.params)}catch{a=null}return a},h=x=>{let M=f(x),v=`${M.speed}|${M.ayG}`,R=i.get(v);if(R!==void 0)return R;let k=d();if(!k)return i.set(v,null),null;let F={cornerStiffness:w=>k.corneringStiffness(w),ayG:M.ayG,speed:M.speed,fyAxle:(w,C)=>2*k.Fy(w,C/2),tire:k};return i.set(v,F),F},b=()=>{if(s!==void 0)return s;let x=p(),M=d();if(!x||!M)return s=null;try{s=Bn(M,x.massTotal*O_*1.2)}catch{s=null}return s},g=x=>{let M=f(x).speed,v=`${M}`,R=c.get(v);if(R!==void 0)return R;let k=p(),F=d(),w=null;if(k&&F)try{w=Th(k,F,M,{steering:!1})}catch{w=null}return c.set(v,w),w};return{operating:r,dynAvailable:!!n,poseAt:x=>{let M=`${x.speedKmh}|${x.ayG}|${x.axG}`,v=m.get(M);if(v!==void 0)return v;let R=null,k=p();try{let F=k?.kinFront,w=k?.kinRear;if(k&&F&&w){let C=Pg(x,k.wheelbase),T=tn(k,F,w,x.speedKmh/3.6)(x.ayG,x.axG,0,C),S=C?Gn(k,C*V_,{FL:T.FL.travel,FR:T.FR.travel}).camber:null,A={};for(let P of["FL","FR","RL","RR"]){let L=P[1]==="R"?T[P].camberRoad:0-T[P].camberRoad;A[P]=L+(S?.[P]??0)}R={corners:T,rollDeg:T.FL.camberRoad-T.FL.camber,steerDeg:C,camber:A,outer:GS(x)}}}catch{R=null}return m.set(M,R),R},operatingAt:f,dynInput:p,tyre:d,dynCtx:h,grip:b,ymd:g,ymdLimit:x=>{let M=`${f(x).speed}`,v=l.get(M);if(v!==void 0)return v;let R=g(x),k=R?ib(R):null;return l.set(M,k),k},reserves:(x,M)=>{let v=f(M),R=`${x}|${v.speed}|${v.ayG}`,k=u.get(R);if(k!==void 0)return k;let F=p(),w=h(M),C=null;if(F&&w)try{C=gi(F,w,x,b()??void 0)}catch{C=null}return u.set(R,C),C}}}var KS=["widthLeft","widthRight","bank","mu"];function Xi(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 Ig(e){let t=Xi(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 Am(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 KS){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 Fm(e,t,r){if(!t.length)return e;let n=Xi(e),o=n.length,a={widthLeft:Sm(e.widthLeft,r.widthLeft),widthRight:Sm(e.widthRight,r.widthRight),bank:Sm(e.bank,r.bank),mu:Sm(e.mu,r.mu)},s={};for(let c of KS){let l=e[c];Array.isArray(l)&&l.length===o&&(s[c]=l)}let i=Am(t,n,a,s);return{...e,...i}}function Sm(e,t){return typeof e=="number"?e:t}var YS=1,HS=4,Cm=Math.PI/180,_g=e=>e===null||!Number.isFinite(e)||e===0?0:1/e;function Ng(e){return e.kind==="arc"?Math.abs(e.radius)*Math.abs(e.angle)*Cm:e.length}function wm(e,t){return e.kind==="straight"?0:e.kind==="arc"?_g(e.radius):t}function zS(e){return e.kind==="straight"?0:e.kind==="arc"?_g(e.radius):_g(e.endRadius)}var Qi=(e,t,r,n,o)=>e+t*o+(n>0?(r-t)*o*o/(2*n):0);function qi(e,t={}){let r=Math.max(.05,t.spacing??YS),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+Ng(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*Cm,b=e.length?wm(e[0],0):0,g=0,y=f,x=(S,A,P)=>{s.push(S),i.push(A),c.push(P)};x(p,d,0);let M=(S,A,P,L,D)=>{let E=D-L;if(E<=0)return;if(Math.abs(A-S)<1e-12){let O=Qi(h,S,S,P,L);if(Math.abs(S)<1e-12)p+=E*Math.cos(O),d+=E*Math.sin(O);else{let W=O+S*E;p+=(Math.sin(W)-Math.sin(O))/S,d+=-(Math.cos(W)-Math.cos(O))/S}return}let $=E/HS;for(let O=0;O<HS;O++){let W=L+O*$,I=Qi(h,S,A,P,W),_=Qi(h,S,A,P,W+$/2),V=Qi(h,S,A,P,W+$);p+=$/6*(Math.cos(I)+4*Math.cos(_)+Math.cos(V)),d+=$/6*(Math.sin(I)+4*Math.sin(_)+Math.sin(V))}};for(let S of e){let A=Ng(S),P=wm(S,b),L=zS(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);M(P,L,A,D,E),D=E,x(p,d,g+E),y+=f}M(P,L,A,D,A),h=Qi(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,R=g;n&&s.length>1&&(s.pop(),i.pop(),c.pop());let k=e.length?wm(e[0],b):0,F={gap:v,headingError:B_((h-o.heading*Cm)/Cm),curvatureError:b-k},w=[];for(let S=0;S<e.length;S++){let A=zS(e[S]),P=S+1<e.length?e[S+1]:n?e[0]:null;if(!P)continue;let L=wm(P,A);w.push({index:S,before:A,after:L,jump:Math.abs(L-A)})}let C=Am(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:R}}function B_(e){let t=e%360;return t>180&&(t-=360),t<-180&&(t+=360),t}var $_={halfWidthM:1.5,spacingM:.5};function Zi(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 ${jS(e).toFixed(0)} m`}}}function jS(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 US=e=>e.kind==="skidpad"||e.kind==="curves"&&e.closed===!0,XS=e=>e.kind==="acceleration",QS=1.5,qS=3;function G_(e,t){let r=e.offsetM,n=e.pitchM,o=Math.max(1,e.gates)*n,a=Math.max(0,e.leadInM),s=QS*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*(qS*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:Zi(e),x:m,y:f,closed:!1,widthLeft:t.halfWidthM,widthRight:t.halfWidthM,fit:"interpolate"}}function K_(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 Og(e,t={}){let r={...$_,...t},n=XS(e),o=K_(e);if(!o){let u=G_(e,r);return{asset:u,peakCurvature:WS(u),worstJoint:0,standingStart:n}}let a=US(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*(qS*Math.PI/180))):r.spacingM,c=qi(o,{name:Zi(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:WS(c.asset),worstJoint:l.reduce((u,m)=>Math.max(u,m.jump),0),standingStart:n}}function WS(e){try{return Math.max(...st(e).curvature.map(Math.abs))}catch{return NaN}}var Pm={courses:[{id:"c1",course:{kind:"manoeuvre",spec:{kind:"skidpad",radiusM:8.375}}}],ggvMode:"twoTrack"};function Vg(e){return e.course.kind==="project"?"the project\u2019s track":e.course.kind==="track"?e.course.name:Zi(e.course.spec)}var ZS=new WeakMap,Tm=new Map;function JS(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=Tm.get(n);if(o)return{...o,numerics:r};let a=Og(e.spec),s={asset:a.asset,standingStart:a.standingStart};return Tm.size>64&&Tm.clear(),Tm.set(n,s),{...s,numerics:r}}function Bg(e,t,r={}){let n=r.lap??Pm,o=r.simParams,a=r.numerics??{},s=n.courses.length?n.courses:Pm.courses,i,c,l,u=new Map,m=new Map,f=new Map,p=new Map,d=M=>(M?.courseId?s.find(v=>v.id===M.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=M=>{let v=d(M);if(!v)return null;let R=m.get(v.id);if(R!==void 0)return R;let k=JS(v.course,r,a),F=null;if(k)try{let w=JSON.stringify(k.numerics),C=ZS.get(k.asset);C||(C=new Map,ZS.set(k.asset,C));let T=C.get(w);T||(T=st(k.asset,k.numerics),C.set(w,T)),F={id:v.id,track:T,standingStart:k.standingStart,numerics:k.numerics,name:k.asset.name}}catch{F=null}return m.set(v.id,F),F},g=()=>{if(c!==void 0)return c;let M=h();if(!M)return c=null;try{l=Ft(M),c=ir(l,!1,n.ggvMode)}catch{c=null}return c},y=M=>{let v=b(M);if(!v)return null;let R=f.get(v.id);if(R!==void 0)return R;let k=g(),F=null;if(k)try{let w=l?qn(l,k,[v.track],v.numerics,n.ggvMode,u):void 0,C=l?pn(l,k.rows):void 0;F=Rt(k,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(M=>!!JS(M.course,r,a))},lapParams:h,courses:()=>s,course:b,ggv:g,lap:y,lapReserve:M=>{let v=b(M);if(!v)return null;let R=p.get(v.id);if(R!==void 0)return R;let k=y(M),F=t.dynInput(),w=t.tyre(),C=null;if(k&&F&&w)try{let T=h();C=Nu(F,w,{v:k.v,ax:k.ax,ay:k.ay,ds:v.track.ds,axDrag:Fa(g()?.rows,k.v),...k.axScrub?{axScrub:k.axScrub}:{},axGrade:mn(v.track.gradient,k.v.length),bank:v.track.bank,...k.loadFactor?{loadFactor:k.loadFactor}:{}},T?{driven:Uf(T)}:{})}catch{C=null}return p.set(v.id,C),C}}}var eA=180/Math.PI,$g={rise:0,sinPitch:0,sinRoll:0};function tA(e){let t=e.kc;return t?rA(e.vehicle,r=>t.ground0[r]):$g}function rA(e,t){let r=e.config,n=No(r),o=0,a=0,s=0,i=0,c=0,l=0,u=0,m=0,f=0;for(let g of _o){let y=Ze(g,r),x=y.axleX-n,M=y.sideSign*Xr(e,y.isFront)/2,v=t(g);if(!Number.isFinite(v))return $g;o++,a+=x,s+=M,i+=v,c+=x*x,l+=M*M,u+=x*M,m+=x*v,f+=M*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 Ji(e,t){let r=e.kc,n=rA(e.vehicle,o=>(r?r.ground0[o]:0)+t[o]);return Q([-n.sinPitch,n.sinRoll,1])}function Gg(e,t,r,n){let o=Q(Qr(e,Ze(t,r)));return-Math.asin(Math.max(-1,Math.min(1,X(o,n))))*eA}function Lm(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=Ja({uprightUpper:c(u.uprightUpper),uprightLower:c(u.uprightLower),wheelCenter:c(u.wheelCenter),spinAxis:m,tieOuter:c(u.tieOuter),loadedRadius:o.loadedRadius,patchShift:o.patchShift&&H_(o.patchShift,e.metrics.toe/eA,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 H_(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 nA(e,t){let r=tA(t);if(r===$g)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 Kg(e,t,r){let n=nA({heave:0,pitch:0,roll:0,steer:0},r);return e-ld(n,[t,0,0],No(r.vehicle.config))}var z_=180/Math.PI;function Hg(e,t){return!e.valid||!e.ic?!1:Math.hypot(e.ic[0]-e.cp[0],e.ic[1]-e.cp[1])<=t}function Dm(e,t,r){let n=Ze(t,e.vehicle.config),o=gt(e,r),a=su(e,t,o[t]),s=a.at("uprightUpper"),i=a.at("uprightLower"),c=a.at("contactPatch"),l=a.at("wheelCenter"),u=A=>{let P=a.velocity(A);return[P[0],P[2]]},m=u(c),f=u(l),p=[c[0],c[2]],d=[l[0],l[2]];if(!a.solved)return{ic:null,line:null,cp:p,wc:d,road:[1,0],swingArmAngleDeg:NaN,tanTheta:NaN,tanThetaHub:NaN,valid:!1,unsolved:!0,sinAngle:0};let h=Ji(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]],x=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},M=a.omega[1],v=Math.hypot(m[0],m[1]),R=Math.abs(M)*1e9>v?[p[0]+m[1]/M,p[1]-m[0]/M]:null,F=R?(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))})(R):0;if(!(Math.abs(m[0]*g[0]+m[1]*g[1])>1e-9))return{ic:R,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=R?[R[0]-p[0],R[1]-p[1]]:[n.isFront?-1:1,0],T=w[0]*C[0]+w[1]*C[1]<0?[-w[0],-w[1]]:w,S=x(m);return{ic:R,line:T,cp:p,wc:d,road:y,swingArmAngleDeg:Math.atan(S)*z_,tanTheta:S,tanThetaHub:x(f),valid:!0,sinAngle:F}}function oA(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 W_=180/Math.PI,j_=Math.PI/180,zg=.5,Em=2,Yg=.25,U_={heave:0,pitch:0,roll:0,steer:0},X_={FL:"FR",FR:"FL",RL:"RR",RR:"RL"},Im=e=>e.ok?e.state:{...e.nearest,converged:!1};function Wg(e,t,r){return t.state?t.solved===!1?{...t.state,converged:!1}:t.state:Im(ge(e,t.travel,t.steer,void 0,r))}var aA=new WeakMap;function sA(e,t){let r=e.ctx[t],n=$e(e.vehicle,t).config.loadedRadius,o=qt(n,e.kc,t),a=aA.get(r);a||(a=new Map,aA.set(r,a));let s=a.get(o);if(!s){let i=qr(t,e.vehicle.config,U_,e.vehicle);s=Im(ge(r,i.travel,i.steer,void 0,o===n?void 0:{loadedRadius:o})),a.set(o,s)}return s}var mr=(e,t)=>!e||!e.lo.converged||!e.hi.converged?NaN:(t(e.hi)-t(e.lo))/(2*e.step),iA=(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 lA(e,t,r,n,o){let a=e.vehicle.config,s=Io(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=Wg(l,m,p),h=sA(e,r),b={lo:Im(ge(l,f.travel-zg,f.steer,void 0,p)),hi:Im(ge(l,f.travel+zg,f.steer,void 0,p)),step:zg},g=c.isFront?{lo:Ee(l,d.beta,f.steer-Em,void 0,p),hi:Ee(l,d.beta,f.steer+Em,void 0,p),step:Em}:null,y=z=>{let j=gt(e,{...t,roll:t.roll+z*j_})[r];return Wg(l,j,j.rigid?void 0:{loadedRadius:j.loadedRadius})},x={lo:y(-Yg),hi:y(Yg),step:Yg},M=q_(e,t,r,c.isFront,u,g),v=Nt(d.points.contactPatch,c),R=Nt(h.points.contactPatch,c),k=Math.abs(v[1])-Math.abs(R[1]),F=X_[r],w=u[F],C=Wg(e.ctx[F],w,w.rigid?void 0:{loadedRadius:w.loadedRadius}),T=C.converged?k+Math.abs(C.points.contactPatch[1])-Math.abs(sA(e,F).points.contactPatch[1]):NaN,S=o??or(e,t,s),A=iu(S,bt(i)),P=A?null:N1(S),L=c.sideSign>0?S.icRight:S.icLeft,D=L?Math.hypot(L[0]-v[1],L[1]-v[2]):1/0,E=Dm(e,r,t),$=E.ic?Math.hypot(E.ic[0]-E.cp[0],E.ic[1]-E.cp[1]):1/0,O=oA(E,s,a.wheelbase,n),W=-mr(b,z=>z.points.damperLength),I=i.config.springRate,_=mr(x,z=>z.metrics.camber),V=Ji(e,{FL:u.FL.ground,FR:u.FR.ground,RL:u.RL.ground,RR:u.RR.ground}),N=e.kc?.loadCase,G=z=>N?Lm(z,r,a,V,{loadedRadius:m.loadedRadius,patchShift:N.patchShift[r]}):z.metrics,K=G(d);return{id:r,converged:d.converged,travel:d.travel,camber:d.metrics.camber,camberRoad:Gg(d.points.spinAxis,r,a,V),toe:d.metrics.toe,caster:K.caster,kpi:K.kpi,scrubRadius:K.scrubRadius,mechanicalTrail:K.mechanicalTrail,scrubAtWheel:K.scrubAtWheel,trailAtWheel:K.trailAtWheel,kingpinOffset:K.kingpinOffset,casterOffset:K.casterOffset,steeringArm:d.metrics.steeringArm,camberGain:mr(b,z=>z.metrics.camber),bumpSteer:mr(b,z=>z.metrics.toe),trackScrubRate:mr(b,z=>Math.abs(Nt(z.points.contactPatch,c)[1])),casterGain:mr(b,z=>G(z).caster),kpiGain:mr(b,z=>G(z).kpi),scrubGain:mr(b,z=>G(z).scrubRadius),trailGain:mr(b,z=>G(z).mechanicalTrail),...c.isFront?{camberPerSteer:iA(g,z=>z.metrics.camber,z=>z.metrics.toe),steerJacking:-iA(g,z=>z.points.contactPatch[2],z=>z.metrics.toe),...M!==void 0?{steerLoad:M}:{}}:{},rollCamber:_,camberRecovery:-100*c.sideSign*_,rollSteer:c.sideSign*mr(x,z=>z.metrics.toe),halfTrackChange:k,trackChange:T,longitudinal:v[0]-R[0],rollCentreHeight:P?P.heightAboveGround:S.heightAboveGround,rollCentreHeightChassis:(P?P.height:S.height)-Kg(0,c.axleX,e),rollCentreLateral:S.lateralAlongGround,rollCentreValid:S.valid,rollCentreUsable:A,rollCentreHeightUsable:A||P!==null,rollCentreSinAngle:S.sinAngle,fvsaLength:D,svsaLength:$,swingArmAngle:E.swingArmAngleDeg,svsaUsable:Hg(E,a.wheelbase),svsaSinAngle:E.sinAngle,...s==="front"?{antiDive:O.brake,antiLift:O.drive}:{antiSquat:O.drive,antiLift:O.brake},decoupled:i.config.actuation==="decoupled",mcpherson:i.config.layout==="mcpherson",springRate:I,motionRatio:W,wheelRate:I*W*W,damperLength:d.points.damperLength,damperTravel:h.points.damperLength-d.points.damperLength,...Q_(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)*W_,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 Q_(e,t,r,n){if(e.config.actuation==="decoupled")return{};let o=n?{droop:n.droopStated?n.droop:null,bump:n.bump}:Vo(t,e.config.coilover),a=t-r;return{...o.droop!==null?{damperToExtended:a-o.droop}:{},...o.bump!==null?{damperToClosed:o.bump-a}:{}}}function q_(e,t,r,n,o,a){if(!a||!n)return;let s=Zc(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],x=g.rigid?void 0:{loadedRadius:g.loadedRadius},R=(b==="FR"?1:-1)*(r==="FR"?1:-1)*Em,k=g.state?{q:[...g.state.pose.t,...g.state.pose.omega],phi:g.state.points.rockerAngle}:void 0,F=ht(ge(y,g.travel,g.steer-R,k,x)),w=ht(ge(y,g.travel,g.steer+R,k,x));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=ls(p,h,[m.hi[0],m.hi[1]]),g=ls(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 ec(e,t,r,n,o){return lA(e,t,r==="front"?"FL":"RL",n,o)}function jg(e,t,r,n){let o=ec(e,t,"front",r,n?.front),a=ec(e,t,"rear",r,n?.rear);return{front:o,rear:a,wheelbaseChange:o.longitudinal-a.longitudinal}}var _m=Math.PI/180,tc={travelSteps:9,heaveSteps:5,rollSteps:4,rackSteps:6},Nm={travelMin:-25,travelMax:25,rollMaxDeg:3,rollAtLimitDeg:2.5};function Z_(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,...Zf(t),drive:Xf(t)}}function uA(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 Ug(e,t=tc,r=Nm,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=qt(P,A.kc,m(S));return L===P?void 0:{loadedRadius:L}},p=(S,A)=>-us(u(),m(S),A),d=new Map,h=new Map,b=new Map,g=new Map,y=new Map,x=new Map,M=new Map,v=null,R=()=>{if(v)return v;u();let S=Z_(e);return v=l!==null&&Number.isFinite(l)?{...S,cgHeight:l}:S},k,F,w=()=>{if(F!==void 0)return F;let S=ol(u().ctx.FL,Ot(s.front.config));return F=S?al(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,()=>ef(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($=>$.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 $=r.travelMin+(r.travelMax-r.travelMin)*E/(L-1);A.push($),P.push(or(u(),{heave:p(S,$),pitch:0,roll:0,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in heave`)}let D=uA(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 $=r.rollMaxDeg*E/(L-1);A.push($),P.push(or(u(),{heave:0,pitch:0,roll:$*_m,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in roll`)}let D=uA(P,E=>Math.abs(P[E].cpLeft?.[0]??0)*Math.abs(A[E]-A[E-1])*_m);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(k!==void 0)return k;try{k=_d(u(),{steerMax:Ot(s.front.config),steps:t.rackSteps})}catch{k=a(500,"the steering sweep threw")}let S=k?.filter(A=>!A.converged).length??0;if(k&&S>0){let A=w();k=A?a(A.violation,A.reason):a(100+10*S,`${S} of ${k.length} steering solves did not converge`)}return k??null},solveAt:(S,A,P=0)=>C(y,`${S}:${A}:${P}`,()=>{try{let L=ge(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(x,`${S.heave}:${S.pitch}:${S.roll}:${S.steer}`,()=>{try{return jg(u(),S,R())}catch{return a(500,"the derived readout threw")}}),readoutAtTravel:(S,A)=>C(M,`${S}:${A}`,()=>{try{return ec(u(),{heave:p(S,A),pitch:0,roll:0,steer:0},S,R())}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*_m),L=u();if(!L.kc)return P;try{let D=gt(L,{heave:0,pitch:0,roll:A*_m,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 J_=Hb();function Xg(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=Ju(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?_i([c],a.track,a.numerics,Pi(s),a.settings,J_)[0]:vi(c,s,{numerics:a.numerics,standingStart:l,lapCounts:u});o={};for(let f of s.metrics)Sc(f)&&(o[f.key]=f.value(m,void 0))}}catch{o=null}return r.set(n,o),o}}}var Om=Math.PI/180,Vm=1e-6;function pA(e,t){let r=e.length;if(r===0)return 0;if(0<=e[0])return t[0];if(0>=e[r-1])return t[r-1];let n=0;for(;e[n+1]<0;)n++;let o=(0-e[n])/(e[n+1]-e[n]);return t[n]+o*(t[n+1]-t[n])}function rc(e){let t=e.measured;if(t)return pA(t.travel,t.camber);let r=Q(e.config.spinAxis);return-Math.asin(Math.max(-1,Math.min(1,r[2])))/Om}function nc(e){let t=e.measured;if(t)return pA(t.travel,t.toe);let[r,n]=e.config.spinAxis;return Math.atan2(r,n)/Om}function Qg(e,t){let r=Math.abs(t.camber)>=Vm,n=Math.abs(t.toe)>=Vm;if(!r&&!n)return e;let o=e.measured;if(o)return{...e,measured:{...o,...r?{camber:o.camber.map(p=>p+t.camber)}:{},...n?{toe:o.toe.map(p=>p+t.toe)}:{}}};let[a,s]=e.config.spinAxis,i=Math.hypot(a,s);if(!(i>0))return e;let c=(rc(e)+t.camber)*Om,l=(nc(e)+t.toe)*Om,[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 Bm(e){let t=e&&typeof e=="object"?e.value:void 0;return typeof t=="number"&&Number.isFinite(t)?t:void 0}function eN(e,t){let r=t;return{front:Bm(r.camber_front_deg)??rc(e.front),rear:Bm(r.camber_rear_deg)??rc(e.rear)}}function tN(e,t){let r=t;return{front:Bm(r.toe_front_deg)??nc(e.front),rear:Bm(r.toe_rear_deg)??nc(e.rear)}}function rN(e){return{camber:{front:rc(e.front),rear:rc(e.rear)},toe:{front:nc(e.front),rear:nc(e.rear)}}}var mA=new WeakMap;function nN(e,t){let r=rN(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)<Vm&&Math.abs(u.toe)<Vm;if(o(n.front)&&o(n.rear))return e;let a=`${t.camber.front}|${t.camber.rear}|${t.toe.front}|${t.toe.rear}`,s=mA.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&&Qg(m,n[Io(u)])])):void 0,l={...e,front:Qg(e.front,n.front),rear:Qg(e.rear,n.rear),...c?{corners:c}:{}};return s||mA.set(e,s=new Map),s.size>=16&&s.clear(),s.set(a,l),l}function _a(e,t){return t?nN(e,{camber:eN(e,t),toe:tN(e,t)}):e}var oN=9.81;function Na(e){let t=Cn(e),r=Math.max(0,e.unsprungPerCorner)*oN,n=a=>{let s=a==="FL"||a==="FR",i=s?"front":"rear",c=Xe(e,i),l=c>0?c:1/0,u=Dp(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 dA=new WeakMap;function aN(e){let t=_a(e.vehicle,e.params);if(t===e.vehicle)return e;let r=dA.get(e);return(!r||r.vehicle!==t)&&dA.set(e,r={...e,vehicle:t}),r}function gn(e,t={}){let r=aN(e),n=Eg(r,t),o=t.assemble?()=>{let l=n.dynInput();if(!l)throw new Error("the car did not assemble");return{kc:Na(l),cgHeight:l.cgHeight}}:void 0,a=Ug(r,t.density,t.envelope,o),s=Bg(r,n,t),i=Xg(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 sN=["x","y","z"],iN=/^(line|plane)\((-?\d+),(-?\d+)\)([uv]?)$/,fA=Math.PI/18e3,hA=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],bA=(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]],cN=e=>Math.hypot(e[0],e[1],e[2]),qg=(e,t)=>[e[0]*t,e[1]*t,e[2]*t];function Zg(e){let t=cN(e);return t>1e-9?qg(e,1/t):null}function lN(e,t){let r=e*fA,n=t*fA;return[Math.cos(n)*Math.cos(r),Math.cos(n)*Math.sin(r),Math.sin(n)]}function pr(e){let t=e.lastIndexOf(".");if(t<0)return null;let r=iN.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:lN(Number(r[2]),Number(r[3]))},coord:n==="line"?"along":r[4]}}function gA(e){let t=Zg(bA([0,0,1],e))??[1,0,0];(t[0]<-1e-9||Math.abs(t[0])<=1e-9&&t[1]<0)&&(t=qg(t,-1));let r=Zg(bA(e,t))??[0,1,0];return(r[2]<-1e-9||Math.abs(r[2])<=1e-9&&r[1]<0)&&(r=qg(r,-1)),[t,r]}function Jg(e){if(e.coord==="along")return e.shape.dir;let[t,r]=gA(e.shape.dir);return e.coord==="u"?t:r}function yA(e,t){let r=pr(t);if(!r)return;let n=sN.map(u=>e[`${r.point}.${u}`]);if(n.some(u=>!u))return;let o=Jg(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 $m=["x","y","z"];var uN=/^(?:hp\.(?:front|rear)\.\w+|(?:heave|roll)\.(?:front|rear)\.(?:outer|inner|anchor))$/;function oc(e){let t=e.lastIndexOf("."),r=e.slice(0,t);if(t<0||!uN.test(r))return null;let n=e.slice(t+1);if(n==="x"||n==="y"||n==="z")return{point:r,axis:n};let o=pr(e);return o?{point:r,axis:o.coord}:null}var ac="*";function e0(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 t0=e=>e?.reads==="speed"||e?.reads==="operating",r0=e=>e?.reads==="lateral"||e?.reads==="operating";function mo(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 Lt(e,t,r){let n=`${t.id}@${mo(r)}`,o=e.values.get(n);if(o!==void 0)return o;let a;try{a=r?.courseId===ac&&t.reads==="course"?mN(e,t,r):r?.stateId===uo&&t.reads==="state"?pN(e,t,r):t.read(e,r)}catch{a=NaN}return e.values.set(n,a),a}function mN(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 pN(e,t,r){if(!t.acrossStates||!e.states.length)return NaN;let n=e.states.map(a=>({v:Lt(e,t,{...r,stateId:a.id}),w:a.weight}));if(n.some(a=>!Number.isFinite(a.v)))return NaN;if(t.acrossStates==="max")return Math.max(...n.map(a=>a.v));if(t.acrossStates==="min")return Math.min(...n.map(a=>a.v));let o=n.reduce((a,s)=>a+s.w,0);return o>0?n.reduce((a,s)=>a+s.v*s.w,0)/o:NaN}function n0(e){let t={mean:"weighted mean",max:"highest",min:"lowest"};return e?.acrossStates?`every state, ${t[e.acrossStates]}`:"every state"}function it(e){return`${e.quantity??e.groupShort??e.group} \xB7 ${e.label}`}var dN={front:"Front",rear:"Rear"},sc={heave:0,pitch:0,roll:0,steer:0};function xA(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 fN(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 ic=e=>e.length?Math.max(...e)-Math.min(...e):NaN;function RA(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 vA(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 Oa(e,t,r){let n=e.stateOf(t?.stateId),o=n?e.poseAt(n):null;return o?r(o):NaN}var cc=(e,t)=>`${e==="front"?"F":"R"}${t}`,kA=e=>e==="L"?"R":"L";function MA(e){let t=dN[e],r=R=>`kin.${e}.${R}`,n=(R,k)=>{let F=R.sweep(e);return F?{x:F.samples.map(w=>w.travel),y:F.samples.map(k)}:{x:[],y:[]}},o=R=>e==="front"?R.vehicle.front:R.vehicle.rear,a=R=>R.params[e==="front"?"heaveFrontDesign":"heaveRearDesign"],s=R=>R.params[e==="front"?"arbFrontDesign":"arbRearDesign"],i=e==="front"?"the front axle":"the rear axle";function c(R){return o(R).config.actuation==="decoupled"?`${i} is decoupled, with no corner damper \u2014 read its heave and roll elements`:null}function l(R){let k=a(R);return k&&k.design.kind!=="none"?null:`${i} has no heave element`}function u(R){let k=a(R);return k?.design.kind==="coil"&&k.linkage?null:`${i} has no heave element on a linkage`}function m(R){let k=s(R);return k&&k.design.kind!=="none"?null:`${i} has no roll element`}function f(R){let k=s(R);return k?.linkage&&k.design.kind!=="none"&&k.design.kind!=="direct"?null:`${i} has no roll element on a linkage`}let p=R=>{if(u(R.car))return null;let k=R.sweep(e);return k?vd(o(R.car),a(R.car).linkage,k.samples):null},d=R=>{if(f(R.car))return null;let k=R.sweep(e);if(!k)return null;let F=s(R.car),w=yd(o(R.car),F.linkage,F.design.kind,k.samples),C=w.atDesign<0?-1:1;return{travel:w.travel,ratio:w.ratio.map(T=>T*C),atDesign:w.atDesign*C}},h=R=>R.readout(sc)?.[e],b=R=>R.readoutAtTravel(e,R.envelope.travelMax),g=R=>{let k=n(R,F=>F.metrics.camber);return k.x.length?{key:r("camberGain"),title:`${t} camber vs travel`,xLabel:"travel [mm]",yLabel:"camber [\xB0]",...k}:null},y=R=>{let k=n(R,F=>F.metrics.toe);return k.x.length?{key:r("bumpSteer"),title:`${t} toe vs travel`,xLabel:"travel [mm]",yLabel:"toe [\xB0]",...k}:null},x=[{id:r("rcStatic"),group:`${t} roll centre`,label:"static height",unit:"mm",scale:30,scope:e,cost:"cheap",read:R=>R.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:R=>{let k=R.rcHeave(e);return k?fN(k.at,k.rc.map(F=>F.height)):NaN},curve:R=>{let k=R.rcHeave(e);return k?{key:r("rcHeaveWorst"),title:`${t} roll-centre height vs wheel travel`,xLabel:"travel [mm]",yLabel:"RC height [mm]",x:k.at,y:k.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:R=>{let k=R.rcRoll(e);return k?ic(k.rc.map(F=>F.height)):NaN},curve:R=>{let k=R.rcRoll(e);return k?{key:r("rcRollSpan"),title:`${t} roll-centre height vs body roll`,xLabel:"roll [\xB0]",yLabel:"RC height [mm]",x:k.at,y:k.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:R=>{let k=R.rcRoll(e);return k?ic(k.rc.map(F=>F.lateral)):NaN},curve:R=>{let k=R.rcRoll(e);return k?{key:r("rcLateralSpan"),title:`${t} roll-centre lateral position vs body roll`,xLabel:"roll [\xB0]",yLabel:"RC lateral [mm]",x:k.at,y:k.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:R=>{let k=R.rcHeave(e),F=R.rcRoll(e);return!k||!F?NaN:Math.min(...k.rc.map(w=>w.sinAngle),...F.rc.map(w=>w.sinAngle))},curve:R=>{let k=R.rcHeave(e);return k?{key:r("minSinAngle"),title:`${t} construction conditioning vs travel`,xLabel:"travel [mm]",yLabel:"sinAngle",x:k.at,y:k.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:R=>h(R)?.fvsaLength??NaN},{id:r("complianceSteer"),group:`${t} compliance`,label:"compliance steer",unit:"\xB0/kN lateral",scale:.05,scope:e,cost:"readout",read:R=>(R.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:R=>(R.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:R=>(R.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:R=>(R.compliance(e)?.toePerMz??0)*1e5},{id:r("staticCamber"),group:`${t} camber & toe`,label:"static camber",unit:"\xB0",scale:1,scope:e,cost:"cheap",read:R=>{let k=R.solveAt(e,0);return k?k.metrics.camber:NaN}},{id:r("staticToe"),group:`${t} camber & toe`,label:"static toe",unit:"\xB0",scale:.5,scope:e,cost:"cheap",read:R=>R.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:R=>h(R)?.camberGain??NaN,curve:R=>g(R)},{id:r("rollCamber"),group:`${t} camber & toe`,label:"camber gain in roll",unit:"\xB0/\xB0",scale:.2,scope:e,cost:"readout",read:R=>h(R)?.rollCamber??NaN},{id:r("rollCamberRecovery"),group:`${t} camber & toe`,label:"camber recovery in roll",unit:"%",scale:20,scope:e,cost:"readout",read:R=>h(R)?.camberRecovery??NaN},{id:r("bumpSteerDesign"),group:`${t} camber & toe`,label:"bump steer at design",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:R=>h(R)?.bumpSteer??NaN,curve:R=>y(R)},{id:r("rollSteer"),group:`${t} camber & toe`,label:"roll steer",unit:"\xB0/\xB0",scale:.1,scope:e,cost:"readout",read:R=>h(R)?.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:R=>{let k=n(R,F=>F.metrics.toe);return k.x.length?xA(k.x,k.y):NaN},curve:R=>y(R)},{id:r("camberGain"),group:`${t} camber & toe`,label:"camber gain, RMS over the travel",unit:"\xB0/mm",scale:.02,scope:e,cost:"cheap",read:R=>{let k=n(R,F=>F.metrics.camber);return k.x.length?xA(k.x,k.y):NaN},curve:R=>g(R)},{id:r("camberSpan"),group:`${t} camber & toe`,label:"camber range over travel",unit:"\xB0",scale:1,scope:e,cost:"cheap",read:R=>ic(n(R,k=>k.metrics.camber).y)},{id:r("toeSpan"),group:`${t} camber & toe`,label:"toe range over travel",unit:"\xB0",scale:.5,scope:e,cost:"cheap",read:R=>ic(n(R,k=>k.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:R=>{let k=R.solveAt(e,R.travelAtRoll(e,R.envelope.rollAtLimitDeg)),F=R.solveAt(e,0);return!k||!F?NaN:Math.abs(k.metrics.camber-F.metrics.camber+R.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:(R,k)=>Oa(R,k,F=>F.camber[cc(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:(R,k)=>Oa(R,k,F=>F.camber[cc(e,kA(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:(R,k)=>Oa(R,k,F=>F.corners[cc(e,F.outer)].bumpToe)},{id:r("caster"),group:`${t} upright`,label:"caster",unit:"\xB0",scale:5,scope:e,cost:"cheap",read:R=>R.solveAt(e,0)?.metrics.caster??NaN},{id:r("kpi"),group:`${t} upright`,label:"kingpin inclination",unit:"\xB0",scale:5,scope:e,cost:"cheap",read:R=>R.solveAt(e,0)?.metrics.kpi??NaN},{id:r("scrubRadius"),group:`${t} upright`,label:"scrub radius",unit:"mm",scale:20,scope:e,cost:"cheap",read:R=>R.solveAt(e,0)?.metrics.scrubRadius??NaN},{id:r("mechanicalTrail"),group:`${t} upright`,label:"mechanical trail",unit:"mm",scale:20,scope:e,cost:"cheap",read:R=>R.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:R=>R.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:R=>R.solveAt(e,0)?.metrics.casterOffset??NaN},{id:r("steeringArm"),group:`${t} upright`,label:"steering arm",unit:"mm",scale:20,scope:e,cost:"cheap",read:R=>R.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:R=>h(R)?.casterGain??NaN},{id:r("kpiGain"),group:`${t} upright`,label:"kingpin inclination gain in bump",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:R=>h(R)?.kpiGain??NaN},{id:r("scrubGain"),group:`${t} upright`,label:"scrub radius gain in bump",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:R=>h(R)?.scrubGain??NaN},{id:r("trailGain"),group:`${t} upright`,label:"mechanical trail gain in bump",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:R=>h(R)?.trailGain??NaN},{id:r("motionRatio"),group:`${t} rates`,label:"motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:c,read:R=>{if(c(R.car))return NaN;let k=R.sweep(e);return k?vA(k.samples.map(F=>F.travel),k.samples.map(F=>F.metrics.motionRatio??NaN))??NaN:NaN},curve:R=>{if(c(R.car))return null;let k=n(R,F=>F.metrics.motionRatio??NaN);return k.x.length?{key:r("motionRatio"),title:`${t} motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",...k}:null}},{id:r("mrSpread"),group:`${t} rates`,label:"motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:c,read:R=>{if(c(R.car))return NaN;let k=R.sweep(e);if(!k)return NaN;let F=k.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:R=>{if(c(R.car))return NaN;let k=R.sweep(e);return k?vA(k.samples.map(F=>F.travel),k.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:R=>p(R)?.atDesign??NaN,curve:R=>{let k=p(R);return k?{key:r("heaveMotionRatio"),title:`${t} heave element motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",x:k.travel,y:k.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:R=>RA(p(R)?.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:R=>l(R.car)||!R.sweep(e)?NaN:fa(R.car.vehicle,R.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:R=>d(R)?.atDesign??NaN,curve:R=>{let k=d(R);return k?{key:r("rollMotionRatio"),title:`${t} roll element motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",x:k.travel,y:k.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:R=>RA(d(R)?.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:R=>m(R.car)||!R.sweep(e)?NaN:zn(R.car.vehicle,R.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:R=>R.axisLength(e,"uca")},{id:r("lcaAxisLength"),group:`${t} package`,label:"lower arm pivot-axis length",unit:"mm",scale:80,scope:e,cost:"geometry",read:R=>R.axisLength(e,"lca")},{id:r("linkLength"),group:`${t} package`,label:"tie/toe link length",unit:"mm",scale:100,scope:e,cost:"geometry",read:R=>R.linkLength(e)},{id:r("trackScrubRate"),group:`${t} package`,label:"track scrub rate",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:R=>R.readout(sc)?.[e].trackScrubRate??NaN},{id:r("trackChange"),group:`${t} package`,label:"track change at full bump",unit:"mm",scale:2,scope:e,cost:"readout",read:R=>b(R)?.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:(R,k)=>Oa(R,k,F=>F.corners[cc(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:(R,k)=>Oa(R,k,F=>F.corners[cc(e,kA(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:R=>c(R.car)?NaN:ic(n(R,k=>k.metrics.damperLength).y),curve:R=>{if(c(R.car))return null;let k=n(R,F=>F.metrics.damperLength);return k.x.length?{key:r("damperStroke"),title:`${t} damper length vs travel`,xLabel:"travel [mm]",yLabel:"length [mm]",...k}:null}}];e==="front"&&x.push({id:r("camberPerSteer"),group:`${t} camber & toe`,label:"camber change with steer",unit:"\xB0/\xB0",scale:.05,scope:"front",cost:"readout",read:R=>h(R)?.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:R=>h(R)?.steerJacking??NaN}),e==="front"?x.push({id:r("antiDive"),group:`${t} anti geometry`,label:"anti-dive",unit:"%",scale:20,scope:"front",cost:"readout",read:R=>R.readout(sc)?.front.antiDive??NaN}):x.push({id:r("antiSquat"),group:`${t} anti geometry`,label:"anti-squat (driving)",unit:"%",scale:20,scope:"rear",cost:"readout",read:R=>R.readout(sc)?.rear.antiSquat??NaN},{id:r("antiLift"),group:`${t} anti geometry`,label:"anti-lift (braking)",unit:"%",scale:20,scope:"rear",cost:"readout",read:R=>R.readout(sc)?.rear.antiLift??NaN});let M=R=>{let k=R.slice(t.length+1);return k.charAt(0).toUpperCase()+k.slice(1)};return[...new Set(x.map(R=>R.group))].flatMap(R=>x.filter(k=>k.group===R)).map(R=>({...R,quantity:`${t} \xB7 ${M(R.group)}`}))}function SA(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 hN=[{id:"kin.front.ackermannCentre",group:"Steering",label:"Ackermann near centre",unit:"%",scale:25,scope:"front",cost:"cheap",read:e=>SA(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=>SA(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}}],bN=[{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)=>Oa(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}}],o0=[...MA("front"),...MA("rear"),...hN,...bN];var AA={understeer:"operating",yawFreq:"speed",yawZeta:"speed",yawStiffness:"operating",steeringTorque:"operating",steeringTorqueGradient:"operating"};function rt(e,t,r,n="cheap"){let o=cb[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,...AA[e]?{reads:AA[e]}:{},read:(a,s)=>{let i=a.dynInput(),c=a.dynCtx(s);return i&&c?o.compute(i,c):NaN}}}var gN=[rt("understeer","Handling \u2014 balance",.1),rt("tlltdFront","Handling \u2014 balance",5),rt("rollStiffFront","Handling \u2014 balance",5)],yN=[rt("yawFreq","Handling \u2014 response",.5),rt("yawZeta","Handling \u2014 response",.2),rt("stabilitySpeed","Handling \u2014 response",50),rt("yawStiffness","Handling \u2014 response",2e4,"trim")],xN=[rt("steeringTorque","Steering feel",1,"trim"),rt("steeringTorqueGradient","Steering feel",2,"trim")],RN=[rt("rollGradient","Ride & body",.5),rt("pitchGradient","Ride & body",.5),rt("rideFreqFront","Ride & body",.5),rt("rideFreqRear","Ride & body",.5),rt("rollFreq","Ride & body",.5),rt("pitchFreq","Ride & body",.5),rt("zetaFront","Ride & body",.2),rt("zetaRear","Ride & body",.2)],vN=[{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}],kN=[{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}],a0=[...gN,...yN,...xN,...RN,...vN,...kN];function MN(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 s0=[{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)=>MN(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 SN(e,t){let r=/^(.*?)\s*\(([^)]+)\)\s*$/.exec(e);return r?{label:r[1],unit:r[2]}:{label:e,unit:t?"s":""}}function AN(e){return e==="s"||e==="kWh"?.1:e==="km/h"?2:1}var FA=new WeakMap;function Gm(e){let t=FA.get(e);return t||(t=e.metrics.filter(Sc).map(r=>{let{label:n,unit:o}=SN(r.label,r.format==="time");return{id:`event.${e.id}.${r.key}`,group:`Events \xB7 ${e.label}`,groupShort:"Events",label:n,unit:o,scale:AN(o),scope:"car",cost:"session",read:a=>a.session(e.id)?.[r.key]??NaN}}),FA.set(e,t),t)}var i0=Ta.flatMap(Gm);var Km=[...o0,...a0,...s0,...i0],Va=Object.fromEntries(Km.map(e=>[e.id,e]));var wA={all:Km,byId:Va},CA=new WeakMap;function Kr(e=[]){if(e.length===0)return wA;let t=CA.get(e);if(t)return t;let r=Eb(e).filter(n=>!Pa(n.id)).flatMap(Gm);return t=r.length?{all:[...Km,...r],byId:{...Va,...Object.fromEntries(r.map(n=>[n.id,n]))}}:wA,CA.set(e,t),t}var lc=180/Math.PI,Ba=Math.PI/180,wN=.2;function Hm(e,t){let r=H(t,e);return Q(r[0]<0?ed(r):r)}var zm=e=>({side:Math.atan2(e[2],e[0])*lc,plan:Math.atan2(e[1],e[0])*lc}),Ym=(e,t)=>Q([1,Math.tan(t*Ba),Math.tan(e*Ba)]),uc=e=>Math.abs(e[0])>=wN,Wm=(e,t)=>Math.atan(t/Math.max(e,1))*lc,jm=(e,t)=>Math.tan(t*Ba)*Math.max(e,1);var yn=["side","plan","clock","len"],jt={uca:{fore:"ucaFront",aft:"ucaRear",ball:"uprightUpper"},lca:{fore:"lcaFront",aft:"lcaRear",ball:"uprightLower"}},mc={uca:"upper arm",lca:"lower arm"},CN=1,TA=(e,t)=>Hm(e[jt[t].fore],e[jt[t].aft]);function PA(e){let t=Q(H(Jp,U(e,X(Jp,e))));return{e1:t,e2:ae(e,t)}}function c0(e,t){let r=TA(e,t);if(!uc(r))return`the ${mc[t]}'s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it`;let n=jt[t],o=Ur(e[n.ball],e[n.fore],r);return Math.hypot(...H(o,e[n.ball]))>=CN?null:`the ${mc[t]}'s ball joint sits on its own pivot axis, so the arm has no length to swing on`}function Hr(e,t){let r=jt[t],n=e[r.ball],o=TA(e,t),a=Ur(n,e[r.fore],o),s=H(a,n),i=Math.hypot(s[0],s[1],s[2]),{e1:c,e2:l}=PA(o),u=i>0?U(s,1/i):c;return{...zm(o),clock:Math.atan2(X(u,l),X(u,c))*lc,len:i,sFront:X(H(e[r.fore],a),o),sRear:X(H(e[r.aft],a),o)}}function l0(e,t){let r=Ym(e.side,e.plan),{e1:n,e2:o}=PA(r),a=ee(U(n,Math.cos(e.clock*Ba)),U(o,Math.sin(e.clock*Ba))),s=ee(t,U(a,e.len));return{fore:ee(s,U(r,e.sFront)),aft:ee(s,U(r,e.sRear))}}function LA(e,t,r,n){let o=jt[t],a={...Hr(e,t),[r]:n},{fore:s,aft:i}=l0(a,e[o.ball]);return{...e,[o.fore]:s,[o.aft]:i}}function DA(e,t){return t==="clock"?e.len:Math.abs(e.sFront-e.sRear)/2}function Um(e,t,r){return t==="len"?r:Wm(DA(e,t),r)}function u0(e,t,r){return t==="len"?r:jm(DA(e,t),r)}var po=["side","plan","atY","atZ"],fo={fore:"rockerPivotA",aft:"rockerPivotB"},TN=5,EA=e=>Hm(e.rockerPivotA,e.rockerPivotB);function $a(e){return Math.hypot(...H(e.rockerPivotB,e.rockerPivotA))<TN?"the rocker\u2019s two pivots are the same point, so there is no axis to describe":uc(EA(e))?null:"the rocker\u2019s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it"}function xn(e){let t=EA(e),r=uc(t)?t:[1,0,0],n=e.rockerPivotA,o=ee(n,U(r,-n[0]/r[0]));return{...zm(r),atY:o[1],atZ:o[2],sA:X(H(n,o),r),sB:X(H(e.rockerPivotB,o),r)}}function m0(e){let t=Ym(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 IA(e,t,r){if($a(e))return e;let{a:n,b:o}=m0({...xn(e),[t]:r});return{...e,rockerPivotA:n,rockerPivotB:o}}var _A=e=>Math.abs(e.sA-e.sB)/2;function p0(e,t,r){return t==="side"||t==="plan"?Wm(_A(e),r):r}function d0(e,t,r){return t==="side"||t==="plan"?jm(_A(e),r):r}var Xt={front:"Front",rear:"Rear"},Ut=["x","y","z"],Oe=(e,t)=>t==="front"?e.front:e.rear,pc=(e,t,r)=>t==="front"?{...e,front:r}:{...e,rear:r},NA=[{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"}]}],OA={damperChassis:"strut top mount",pushrodOuter:"strut lower mount"},ho=30;function PN(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).config.layout==="mcpherson";for(let o of NA)for(let{key:a,label:s}of o.keys){let i=n&&OA[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:ho,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:pc(l.vehicle,r,{...m,hardpoints:p})}}})}}return t}var LN={side:"axis side-view angle",plan:"axis plan-view angle",clock:"arm clock angle",len:"effective arm length"},DN={side:"\xB0",plan:"\xB0",clock:"\xB0",len:"mm"};function EN(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=c0(a,o)?null:Hr(a,o);for(let i of yn)t.push({id:`arm.${r}.${o}.${i}`,group:`${Xt[r]} ${n?"arm axes":"wishbone axes"}`,label:`${mc[o]} \u2014 ${LN[i]}`,scope:Xt[r],unit:DN[i],defaultSpan:s?Um(s,i,ho):ho,read:c=>Hr(Oe(c.vehicle,r).hardpoints,o)[i],write:(c,l)=>{let u=Oe(c.vehicle,r),m=LA(u.hardpoints,o,i,l);return{...c,vehicle:pc(c.vehicle,r,{...u,hardpoints:m})}}})}}return t}var IN={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"},_N={side:"\xB0",plan:"\xB0",atY:"mm",atZ:"mm"};function NN(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).hardpoints,o=$a(n)?null:xn(n);for(let a of po)t.push({id:`rocker.${r}.${a}`,group:`${Xt[r]} rocker axis`,label:`rocker \u2014 ${IN[a]}`,scope:Xt[r],unit:_N[a],defaultSpan:o?p0(o,a,ho):ho,read:s=>xn(Oe(s.vehicle,r).hardpoints)[a],write:(s,i)=>{let c=Oe(s.vehicle,r),l=IA(c.hardpoints,a,i);return{...s,vehicle:pc(s.vehicle,r,{...c,hardpoints:l})}}})}return t}var Xm={front:"heaveFrontDesign",rear:"heaveRearDesign"},f0={front:"arbFrontDesign",rear:"arbRearDesign"};function ON(e,t){return{heave:e.config.actuation==="decoupled"?"heave element":"third spring",roll:t?.design.kind==="coil"?"roll shock":"anti-roll bar"}}var Qm=e=>/^(heave|roll)\.(front|rear)\.(outer|inner|anchor)\.[xyz]$/.test(e);function VN(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r),o=e.params[Xm[r]],a=e.params[f0[r]],s=ON(n,a),i=d=>d.params[Xm[r]],c=d=>d.params[f0[r]],l=(d,h)=>({...d,params:{...d.params,[Xm[r]]:h}}),u=(d,h)=>({...d,params:{...d.params,[f0[r]]:h}}),m={group:`${Xt[r]} heave & roll elements`,scope:Xt[r]},f=(d,h,b,g,y)=>{for(let x of b)t.push({...m,id:`${d}.${Ut[x]}`,label:`${h} ${Ut[x]}`,unit:"mm",defaultSpan:ho,read:M=>g(M)[x],write:(M,v)=>{let R=[...g(M)];return R[x]=v,y(M,R)}})},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=x=>c(x).linkage,b=Zr(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],x=>h(x).outer,(x,M)=>u(x,{...c(x),linkage:{...h(x),outer:M}})),f(`roll.${r}.inner`,`${s.roll} ${y}`,[0,1,2],x=>h(x).inner,(x,M)=>u(x,{...c(x),linkage:{...h(x),inner:M}}))}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 BN=[{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 $N(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:pc(u.vehicle,r,p)}}})};for(let a of["ucaFront","ucaRear","lcaFront","lcaRear","tieRod","pushRod"])o(`link.${a}`,`${GN[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}`,`${KN[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 GN={ucaFront:"UCA front leg",ucaRear:"UCA rear leg",lcaFront:"LCA front leg",lcaRear:"LCA rear leg",tieRod:"tie rod",pushRod:"push/pull rod"},KN={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 HN(){return BN.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:pc(t.vehicle,e.axle,o)}}}))}function zN(e){let t=Ln(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=>Ln(c.params.steeringSystem)[n],write:(c,l)=>({...c,params:{...c.params,steeringSystem:Ln({...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 YN(e){let t=ci(e.params),r=[];for(let n of["front","rear"]){if(t[n]!=="diff")continue;let o=Wn(e.params.driveline?.[n]);if(o?.kind!=="clutch"&&o?.kind!=="torsen")continue;let a=(s,i)=>{let c=bu[`${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=>Wn(l.params.driveline?.[n])?.[s],write:(l,u)=>({...l,params:{...l.params,driveline:hu({...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 WN(e){if(Vl(e.params)!=="hydraulic")return[];let t=[{id:"brakeSetup.barFront",group:"Brakes",label:`${nh("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=tr(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:rh(a.circuit?`${a.circuit}.${String(a.key)}`:a.key),unit:s,defaultSpan:i,read:c=>n(tr(c.params.brakeModel),a),write:(c,l)=>{let u=tr(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:tr(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 VA=e=>!!e&&typeof e=="object"&&"value"in e&&"label"in e;function BA(e){let t={...e};for(let r of Object.keys(t)){let n=t[r];VA(n)&&(t[r]={...n})}return t}function jN(e){let t=[];for(let r of lk(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 VA(s)?s.value:NaN},write:(a,s)=>{let i=BA(a.params);return vu(i,n.label,s),{...a,params:i}}})}return t}function $A(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 NA)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 yn)t[`arm.${s}.${l}.${u}`]={why:c};for(let l of po)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 po)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[Xm[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 yn)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=c0(i.hardpoints,l);if(u)for(let m of yn)t[`arm.${s}.${l}.${m}`]={why:u,useInstead:`hp.${s}.${jt[l].fore}.z`}}let c=$a(i.hardpoints);if(c&&i.config.actuation!=="direct")for(let l of po)t[`rocker.${s}.${l}`]={why:c,useInstead:`hp.${s}.${fo.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?zh:Yh;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(yu))t[`param.${s}`]={why:i};for(let[s,i]of Object.entries(xu(e.params)))t[`param.${s}`]={why:i};let a=Vl(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 GA(e){let t={...XN,...$A(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[...PN(e),...EN(e),...NN(e),...VN(e),...HN(),...zN(e),...WN(e),...YN(e),...$N(e),...jN(e.params)].map(r)}var UN={spring_front:"cfg.front.springRate",spring_rear:"cfg.rear.springRate"},XN=Object.fromEntries(Object.entries(Hh).map(([e,t])=>[`param.${e}`,{why:t,useInstead:UN[e]}])),ct=e=>e.scope?`${e.scope} \xB7 ${e.label}`:e.label;function Gt(e){let t={};for(let n of GA(e))t[n.id]=n;let r=(n,o)=>{if(typeof o!="string")return;let a=yA(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 h0=e=>e.step!==void 0&&Number.isFinite(e.step)&&e.step>0?e.step:0,b0=e=>h0(e)>0||(e.values?.length??0)>0,g0=e=>e.some(b0),KA=e=>1e-9*Math.max(1,Math.abs(e.lo),Math.abs(e.hi));function HA(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=h0(e);if(!r||!Number.isFinite(e.start))return t;let n=KA(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 zA=(e,t)=>t.map((r,n)=>e[n]&&b0(e[n])?HA(e[n],r):r);function y0(e,t=1e3){if(e.values?.length)return e.values.length;let r=h0(e);if(!r||!Number.isFinite(e.start))return 1/0;let n=KA(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 x0(e,t,r){let n=zA(e.variables,t),o=n.every((a,s)=>a===t[s]);return{x:n,score:o?r:kr(e,n)}}function k0(e,t){if(!e.variables.some(WA))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(jA(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 WA=e=>!!(e.fixed||e.around||e.follows)||jA(e),jA=e=>!!e.values?.length&&(e.lo!==Math.min(...e.values)||e.hi!==Math.max(...e.values));function Dt(e,t){if(!t.variables.some(WA))return t;let r=Gt(e);return k0(t,n=>{let o=r[n];if(!o)return NaN;try{return o.read(e)}catch{return NaN}})}function dr(e){return[...e.objectives,...e.constraints,...e.watches??[]]}var Zm=e=>(e.metrics??Kr()).byId;function M0(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 Jm(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]))}),F0(e,o,t.followers,n)}function S0(e,t,r={}){let n=t.states??[],o=n.some(c=>c.follows);if(!o&&!t.envelopeFollows)return t;let a=gn(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=Tg(n,c,ZN(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=Zm(r),u=A0(t,l),m=dr(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=gn(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?qN(e,Lg(c,u),u):null,d=p&&m.length?QN(p,f):p;d&&!Dg(d,t.envelope)&&(i=d)}return s===n&&i===t.envelope?t:{...t,states:s,envelope:i}}var qm=3;function QN(e,t){let r=(c,l)=>t({...e,travelMin:c,travelMax:l}),n=e.travelMin-qm,o=e.travelMax+qm;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+qm)),i=Math.max(1,Math.min(e.travelMax,o-qm));return s===e.travelMin&&i===e.travelMax?e:{...e,travelMin:s,travelMax:i}}function A0(e,t){let r=new Set;for(let n of dr(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 qN(e,t,r){if(!t)return null;let n=_a(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:tc.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 ZN(e){let t=e.projectTrack?.();if(!t)return null;try{return Cg(st(t.asset,t.numerics))}catch{return null}}function F0(e,t,r,n){if(!r?.length)return t;let o=t;for(let a of r){let s=n[a.id],i=n[a.follows];if(!s||!i)continue;let c=i.read(t)-i.read(e);Number.isFinite(c)&&c!==0&&(o=s.write(o,s.read(e)+c))}return o}function dc(e,t){if(!Number.isFinite(t))return NaN;if(e.op==="max")return t-e.limit;if(e.op==="min")return e.limit-t;let r=e.limit2??e.limit;return Math.max(e.limit-t,t-r)}var UA=(e,t="")=>t&&t!=="-"?`${e} ${t}`:`${e}`;function XA(e,t,r){let n=t??Va[e.metricId],o=(n?it(n):e.metricId)+fc(e.at,n,r),a=s=>UA(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 fc(e,t,r){if(!e&&t?.reads!=="state")return"";e??={};let n=[];if(t?.reads==="state")if(e.stateId===uo)n.push(n0(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&&t0(t)&&n.push(`${(e.speed*3.6).toFixed(0)} km/h`),e.ayG!==void 0&&r0(t)&&n.push(`${e.ayG.toFixed(2)} g`),e.courseId===ac&&t?.reads==="course")n.push(e0(t));else if(e.courseId&&t?.reads==="course"){let o=r?.lap.courses.find(a=>a.id===e.courseId);o&&n.push(Vg(o))}return n.length?` @ ${n.join(", ")}`:""}function QA(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 qA=5e-4;function ZA(e,t){return e.cost!=="lap"&&e.cost!=="session"?0:Number.isFinite(t)?qA*Math.abs(t):0}function ep(e,t,r={}){t=Dt(e,t);let n=M0(e,t),o=Gt(e),a=Zm(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??`${it(b)} could not be computed`};let y=dc(h,g);y>0&&(p+=y/b.scale,d.push(`${XA(h,b,t)} (${UA(g.toFixed(3),b.unit)})`))}return d.length===0?ws:{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=F0(e,f,t.followers,o),{car:f,ev:gn(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:it(p)+fc(f.at,p,t),raw:d,unit:p.unit,weight:f.weight,contribution:QA(f,p,d),resolution:Math.abs(f.weight)*ZA(p,d)/p.scale}})}}function R0(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 JA(e,t){if(e.variables.some(o=>o.id===t))return!0;let r=oc(t);if(!r||!$m.includes(r.axis))return!1;if(e.variables.some(o=>pr(o.id)?.point===r.point))return!0;let n=R0(t);return!!n&&e.variables.some(o=>/^(arm|rocker)\./.test(o.id)&&R0(o.id)===n)}function JN(e,t){let r=e.followers??[],n=new Map(r.map(i=>[i.id,i.follows])),o=i=>{let c=t[i],l=oc(i);return c&&l&&$m.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 JA(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 w0(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=Zm(r),c=dr(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=dr(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 x=new Set([...y.map(M=>M.id),uo]);for(let M of m){let v=i[M.metricId];M.at?.stateId&&!x.has(M.at.stateId)?s.push(`${it(v)} names a state this study no longer has. Point it at one of the states under Conditions.`):M.at?.stateId===uo&&!v.acrossStates&&s.push(`${it(v)} is read at one state at a time, not over every state.`)}}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),ac]);for(let y of dr(t))if(y.at?.courseId&&!f.has(y.at.courseId)){let x=i[y.metricId];s.push(`${x?it(x):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(x=>/arb_|spring|heave_|front_mass_diss|cg_height|^hp\./.test(x.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 x=a[y.id];if(!x){s.push(`\u201C${y.id}\u201D is not a variable this car has.`);continue}if(y.values&&y.values.length<2?s.push(`${ct(x)}: list two values or more, or fix it where it is.`):y.hi>y.lo?y.step!==void 0&&y0({...y,start:x.read(e)})<2&&s.push(`${ct(x)}: a step of ${y.step} ${x.unit} leaves no other place to land in its box. Make the step finer or the box wider, or fix it.`):s.push(`${ct(x)}: the upper bound must be above the lower one (${y.lo} to ${y.hi}).`),x.supersededBy){let v=x.supersededBy.useInstead?a[x.supersededBy.useInstead]:void 0,R=v?ct(v):void 0;s.push(`${ct(x)} cannot be searched: ${x.supersededBy.why}.`+(R?` Use ${R} instead.`:""))}let M=x.read(e);Number.isFinite(M)&&(M<y.lo||M>y.hi)&&s.push(`${ct(x)} starts at ${M.toFixed(1)} ${x.unit}, outside its own bounds.`)}let p=t.followers??[],d=new Map;for(let y of[...t.variables.map(x=>x.id),...p.map(x=>x.id)]){let x=R0(y);if(!x)continue;let M=d.get(x);M||d.set(x,M={arms:[],coords:[]}),(/^(arm|rocker)\./.test(y)?M.arms:M.coords).push(y)}for(let[y,x]of d){if(x.arms.length===0||x.coords.length===0)continue;let M=R=>a[R]?ct(a[R]):R,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 (${x.arms.map(M).join(", ")}) and as pivot coordinates (${x.coords.map(M).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(x=>x.id),...b]){let x=oc(y);if(!x)continue;let M=pr(y),v=b.has(y)?"with":M?`${M.shape.kind}:${y.slice(y.lastIndexOf(".")+1).replace(/[uv]$/,"")}`:"axes",R=h.get(x.point);R||h.set(x.point,R=new Set),R.add(v)}for(let[y,x]of h){if(x.size<2||x.size===2&&x.has("axes")&&x.has("with"))continue;let M=[...x].map(w=>w.split(":")[0]),v=w=>M.filter(C=>C===w).length,R=[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),k=a[`${y}.x`],F=k?ct({...k,label:k.label.replace(/ x$/,"")}):y;s.push(`${F} is moved more than one way at once \u2014 ${R.join(" and ")}. Each write moves it off the other's, so keep one.`)}s.push(...JN(t,a));for(let y of t.constraints){let x=i[y.metricId];if(!x){s.push(`\u201C${y.metricId}\u201D is not a metric.`);continue}y.op==="band"&&!((y.limit2??y.limit)>y.limit)&&s.push(`${it(x)}: 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 dr(t))if(y.at?.speed!==void 0&&!(y.at.speed>0)){let x=i[y.metricId];s.push(`${x?it(x):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 dr(t)){let x=i[y.metricId],M=x?.unavailable?.(e);!x||!M||g.has(x.id)||(g.add(x.id),s.push(`${it(x)} cannot be read on this car: ${M}.`))}for(let y of t.objectives)i[y.metricId]?y.weight>0?y.goal==="target"&&!Number.isFinite(y.target)?s.push(`${it(i[y.metricId])}: \u201Chit a value\u201D needs a value.`):y.goal==="target"&&y.tolerance!==void 0&&!(y.tolerance>=0)&&s.push(`${it(i[y.metricId])}: the tolerance must be zero or more.`):s.push(`${it(i[y.metricId])}: weight must be positive.`):s.push(`\u201C${y.metricId}\u201D is not a metric.`);return s}var eF=.1,tF=2e3,v0=3;function C0(e,t,r={},n=tF){t=Dt(e,t);let o=ep(e,t,r),a=Zm(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}@${mo(L.at)}`]=Lt(S.ev,D,L.at))}return P},p=S=>m.map(A=>S[`${A.metricId}@${mo(A.at)}`]).map(A=>Number.isFinite(A)?A.toFixed(9):"x").join("|"),d=f(l,dr(t)),h=p(d),b=[],g=[],y={},x=[],M=0;t.variables.forEach((S,A)=>{let P=s[S.id];if(!P)return;if(x.length>=v0&&M>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),$=performance.now()-D;M+=$,x.push($);let O=f(E);y[P.id]=O,p(O)===h&&b.push(P)});let v=t.variables[0],R=v?t.variables.indexOf(v):-1;for(let S=0;v&&x.length>0&&x.length<v0;S++){let A=[...i];A[R]=i[R]+(v.hi-i[R])*(.4+.15*S)||v.hi;let P=performance.now();c(A),x.push(performance.now()-P)}let k=[...x].sort((S,A)=>S-A),F=k.length?k[k.length>>1]:0,w=[],C=dr(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?Jr(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{msPerEval:F,values:d,samples:x.length,times:x,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 tO=[{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:rO.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 rO=["setup:m","characteristics:peak_power","characteristics:power_to_weight","characteristics:cla","characteristics:cda","characteristics:pack_energy","characteristics:maxAy","characteristics:top_speed"];var Aae=new Set(tO.map(e=>e.kind));var rF={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 T0=["FL","FR","RL","RR"],kt=(e,t,r)=>({input:e,from:r?r[0]:rF[e].from,to:r?r[1]:rF[e].to,n:t}),Tae=[{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:T0,y:["wheelLoad"]},{id:"travel-roll",form:"curves",title:"Wheel travel through roll",sweep:kt("roll",25),wheels:T0,y:["travel"]},{id:"toe-roll",form:"curves",title:"Roll steer, all four",sweep:kt("roll",25),wheels:T0,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 P0(e){let t=Number(e);return Number.isFinite(t)?Math.min(Ff,Math.max(Af,t)):At}var oF=6e4;var Mse=[{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 fO=new Set(["color","visible","source","origin"]),Ise=["id",...fO];var iF=.18/1.18,cF={induction:{kind:"natural"}},lF=e=>e.breathing??cF;function tp(e){switch(e?.kind){case"sae-j1349":return Ni(99e3,25);case"measured":return Ni(e.hPa*100,e.tempC);default:return Ni(101325,20)}}var bO=tp(void 0);function uF(e,t){let r=tp(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 mF(e,t){let r=e.induction;if(r.kind==="table"){let o=s=>Be(r.densityAltitudeM,r.powerPct,s),a=o(tp(e.rated).densityAltitudeM);return a>0?Math.max(0,o(t.densityAltitudeM)/a):0}let n=e.frictionShare??iF;return Math.max(0,(uF(e,t)-n)/(1-n))}var sF=new WeakMap;function D0(e,t){let r=e.asRated??e,n=`${t.p}|${t.pDry}|${t.T}`,o=sF.get(r);o||sF.set(r,o=new Map);let a=o.get(n);if(a)return a;let s=mF(lF(r),t),i={...r,torque:r.torque.map(c=>c*s),asRated:r};return o.set(n,i),i}function RO(e){return JSON.parse(E0(I0(e,"public/laptime/index.json"),"utf8")).tracks}var vO=async e=>{let t=await fetch(e.url);if(!t.ok)throw new Error(`The track could not be read from ${Rm(e)} (${t.status}).`);return new Uint8Array(await t.arrayBuffer())};function pF(e,t=new Map,r=vO){let n=RO(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(!zi(o.address))throw new Error(`"${o.address}" is not a catalogue address`);if(!Hi(o.link))throw new Error("This track is linked to a source this version does not read from.");i=await dg(await r(o.link),o.link,o.address)}else if(o.kind==="catalogue"){if(!zi(o.address))throw new Error(`"${o.address}" is not a catalogue address`);let c=JSON.parse(E0(I0(e,"public/catalogue",hg(o.address)),"utf8"));i=await gg(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(E0(I0(e,"public/laptime",c),"utf8"))}return t.set(a,i),structuredClone(i)}}var kO=9.81;function dF(e,t=e.tireModel,r=e.tireModelRear){if(!t)return e;let n=e.m.value*kO/4,o=ba(e,t,r),a=Ie(o.front).rollingRadius(n),s=o.rear===o.front?a:Ie(o.rear).rollingRadius(n),i=MO(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 MO(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 SO=1e-6;function fF(e,t,r){let n=e.cgReference;if(!n||!e.cg_height)return e;let o=tk(e,t,r);if(o===void 0||Math.abs(o-n.standingRadius)<SO)return e;let a=n.typed??e.cg_height.value;return{...e,cg_height:{...e.cg_height,value:ha(e.cg_height.value,n.standingRadius,o)},cgReference:{...n,standingRadius:o,typed:a}}}function hF(e,t,r){let n=e.rcRoad,o=e.rc_front,a=e.rc_rear;if(!n||!o||!a)return e;let s=fu(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 bF=e=>({brakeFade:e.brakeFade,airTempC:e.airTempC,diffYaw:e.diffYaw,...Oi(e.air)?{air:e.air}:{}});var bo=(e,t)=>t?e.find(r=>r.id===t)?.model:void 0;function go(e){return{tire:t=>bo(e.tires,t),motor:t=>bo(e.motors,t),aero:t=>bo(e.aeros,t),battery:t=>bo(e.batteries,t),brake:t=>bo(e.brakes??[],t),damper:t=>bo(e.dampers??[],t),suspensionOf:t=>_a(_0(e,t),t)}}function _0(e,t){let r=bo(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 yo(e,t,r){let n={front:t.tire(e.tireModelId),rear:t.tire(e.tireModelIdRear)};return N0(U1(t.suspensionOf(e),e,n),t,r)}function AO(e){return Oi(e.air)?pS(e.air,e.airTempC??At):void 0}var FO="the air the session states, at its venue";function wO(e,t){return t?{...e,rho:{...e.rho,value:t.rho},readouts:{...e.readouts,rho:FO}}:e}function CO(e,t,r){if(!r)return{rho:e.rho,motorModel:t,readouts:e.readouts};let{rho:n,readouts:o}=wO(e,r);return{rho:n,motorModel:t&&ft(t)?D0(t,r):t,air:r,readouts:o}}function N0(e,t,r){let n=t.tire(e.tireModelId),o=t.tire(e.tireModelIdRear),a=hF(fF(dF(ak(rk(dk(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}=CO(a,t.motor(e.motorModelId),AO(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),...Js(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 DO=e=>e!==!1,EO=(e,t,r)=>r&&t>0?(e%t+t)%t:Math.min(Math.max(e,0),t);function IO(e,t,r){let n=e.points.filter(o=>Number.isFinite(o.at)&&Number.isFinite(o.z)).map(o=>({...o,at:EO(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 _O(e,t,r){let n=IO(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 NO(e,t,r,n){let o=t-e.at;return n&&r>0?o-r*Math.round(o/r):o}function OO(e,t,r,n){for(let s of e){let i=NO(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 gF(e,t,r,n){let o=DO(n),a=_O(e,r,o);return a.length?t.map(s=>OO(a,s,r,o)):t.map(()=>0)}function hc(e,t){if(!t?.points.length)return e;let r=Xi(e),{zSmoothing:n,...o}=e;return{...o,z:gF(t,r,Ig(e),e.closed)}}var rp={widthLeft:1.5,widthRight:1.5,bank:0,mu:1};function yF(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 bc(e,t){let r=yF(e.source);return xF(e,r?await t(r):void 0)}function xF(e,t){let{source:r}=e;if(r.kind==="segments"){let{segments:i,closed:c,spacing:l}=r,{asset:u}=qi(i,{name:e.name,closed:c,spacing:l,base:rp});return hc(u,r.profile)}let n=r.sections??[];if(r.kind==="inline")return hc(Fm(r.asset,n,rp),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 hc(Fm({...t,...o!==void 0?{widthLeft:o}:{},...a!==void 0?{widthRight:a}:{},...s!==void 0?{closed:s}:{}},n,rp),r.profile)}var lle=1/500;var ule=5*Math.PI/180;var xle=1/3;var GO=[4,2,1,.5,.25,.125];function RF(e,t,r={}){let n=[...r.steps??GO].sort((g,y)=>y-g),o=at(r.numerics),a=r.tolPct??.5,s=Ft(e),i=e.ggvMode??"twoTrack",c=ir(s,!1,i),l={...o,dsTarget:n[0]??o.dsTarget},u=n.length?qn(s,c,[st(t,l)],l,i):void 0,m=pn(s,c.rows),f=n.map((g,y)=>{let x={...o,dsTarget:g},M=Date.now(),v=st(t,x),R=Rt(c,v,x,{...u?{load:u}:{},...m?{shifts:m}:{}});return r.onStep?.(y+1,n.length),{dsTarget:g,npts:v.npts,lapTime:R.laptime,ms:Date.now()-M}}),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 Ga(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:P0(t.airTempC??r.airTempC),...Oi(mm(t.air??r.air))?{air:mm(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:at(r.numerics)}}async function np(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 bc(r,t)}}function zO(e,t){let r=structuredClone(e);for(let[n,o]of Object.entries(t))if(!vu(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 O0=(e,t)=>{let r=e?.name;return typeof r=="string"&&r?r:t};function YO(e,t){let r={};for(let n of hn){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:O0(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:O0(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:O0(i.model,i.id),byFallback:!0}:null;continue}r[n.doc]=null}return r}function WO(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 vF(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 kF=e=>e.length<2?e[0]??"":`${e.slice(0,-1).join(", ")} and ${e[e.length-1]}`;async function op(e,t,r={}){let n=Ga(e,r.settings),{entry:o,asset:a}=await np(e,t),s=go(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]?zO(d.params,r.overrides[d.id]):d.params;return yo(structuredClone(h),s,n)}),l=Pi(ro(e.meta.rulesetId,e.rulesets)),u=_i(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}=zb(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:WO(u[h]),metrics:Yb(l,u[h],p?.[d.id]),fitted:YO(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 MF(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=Ga(e),{asset:a}=await np(e,t),s=yo(structuredClone(n.params),go(e),o);return RF(s,a,{...r.steps?{steps:r.steps}:{},numerics:o.numerics,...r.tolPct!==void 0?{tolPct:r.tolPct}:{},...r.onStep?{onStep:r.onStep}:{}})}var jO=(e,t)=>e[t]??[],UO=(e,t,r)=>r<=1?[e]:Array.from({length:r},(n,o)=>e+(t-e)*o/(r-1));function ap(e){return e.kind==="param"?UO(e.start,e.end,Math.max(1,Math.round(e.steps))):e.kind==="part"?[...e.partIds]:[...e.values]}var SF=e=>e.kind==="param"?e.label:e.kind==="part"?`${e.part} model`:e.setting;function XO(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=yo(structuredClone(r.params),go(e),Ga(e)),o=mk(n,{geometry:!0}),a=Ru(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=hn.find(l=>l.doc===i.part);if(!c)throw new Error(`"${i.part}" is not a library \u2014 it is one of ${hn.map(l=>l.doc).join(", ")}`);for(let l of i.partIds)if(!jO(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*ap(c).length,1);if(s>im)throw new Error(`that grid is ${s} runs, over the ${im} cap \u2014 a run is a whole session. Drop an axis or use fewer steps.`)}var QO=e=>e.map(t=>String(typeof t=="number"?Number(t.toPrecision(4)):t)).join(" \xD7 ");function qO(e,t){let r=[...new Set(e.flatMap(o=>(o.didNotFinish??[]).map(a=>a.label)))],n=e.map(o=>({name:QO(o.at),events:r.map(a=>({label:a,incomplete:o.didNotFinish?.find(s=>s.label===a)}))}));return vF(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`:kF(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 ZO(e){let t=[[]];for(let r of e){let n=ap(r),o=[];for(let a of n)for(let s of t)o.push([...s,a]);t=o}return t}async function AF(e,t,r,n){XO(e,r);let o=ZO(r.axes),a=[],s=!1;for(let[u,m]of o.entries()){let f=structuredClone(e),p=f.vehicles.find(M=>M.id===r.vehicleId),d={...r.settings},h={};r.axes.forEach((M,v)=>{let R=m[v];if(M.kind==="param")h[M.label]=R;else if(M.kind==="part"){let k=hn.find(F=>F.doc===M.part);p.params[k.ref]=R}else d[M.setting]=R});let b=r.fleet?f.vehicles.filter(M=>M.visible||M.id===r.vehicleId).map(M=>M.id):[r.vehicleId],g=await op(f,t,{vehicleIds:b,settings:d,...Object.keys(h).length?{overrides:{[r.vehicleId]:h}}:{}});s=g.fleetScored;let y=g.vehicles.find(M=>M.id===r.vehicleId),x=y.events.flatMap(M=>M.incomplete?[{label:M.label,...M.incomplete}]:[]);a.push({at:m,metrics:y.metrics,...x.length?{didNotFinish:x}:{}}),n?.(u+1,o.length)}let i=Object.keys(a[0]?.metrics??{}),c=[];r.axes.forEach((u,m)=>{if(ap(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(SF(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(...qO(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:SF(u),values:ap(u)})),runs:a,metricKeys:i,fleetScored:s,flat:c,caveats:l}}var Ame=Math.PI/180;function V0(e){if(!e.chassis)return e;let{chassis:t,...r}=e;return r}var yhe=180/Math.PI;var YV={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:to,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 jbe=YV.id;var gc=.02;function VF(e){let t=Math.max(gc,Math.abs(e.heaveMotionRatio)),r=Math.max(gc,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 jV=(e,t)=>({od:t,id:Math.min(e.id,t-.5)}),UV=(e,t)=>e/(2*t*t);function OF(e,t){switch(e.kind){case"ubar":case"blade":case"torsionTube":return{...e,section:jV(e.section,t)};default:return e}}function BF(e,t,r){let n=Math.max(gc,Math.abs(r));if(e?.kind==="coil"){let l=UV(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=>ni(OF(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 OF(a,c)}function $F(e,t,r,n){let o=e?.design,a=BF(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 XV=Math.PI/180,sp=1e-6;function QV(e){return!(ve(e.rockerPivotA,e.rockerPivotB)<sp||ve(e.rockerToPushrod,e.rockerPivotA)<sp||ve(e.rockerToDamper,e.rockerPivotA)<sp||ve(e.rockerToDamper,e.damperChassis)<sp)}function zF(e){if(!QV(e.hardpoints))return!1;let t={...e,config:{...e.config,actuation:"rocker"}};try{let r=et(t);for(let n of[-20,-1,0,1,20]){let o=ge(r,n,0);if(!o.ok||!Number.isFinite(o.state.metrics.damperLength))return!1}return!0}catch{return!1}}function YF(e){if(e.config.actuation!=="direct"||zF(e))return;let{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}=ZV(e);return{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}}var GF=40;function ip(e,t={}){let r=e.hardpoints,n=r.pushrodOuter,o=r.damperChassis,a=ve(n,o),s=ee(n,U(H(o,n),qV)),i=t.armRod??Math.max(25,.15*a),c=t.armDamper??i,l=[s[0]-GF,s[1],s[2]],u=[s[0]+GF,s[1],s[2]],m=Q(H(u,l)),f=H(n,s),p=Q(H(f,U(m,KF(f,m)))),d=It(p,m,(t.armAngleDeg??60)*XV),h=ee(s,U(d,i)),b=H(o,s),g=Q(H(b,U(m,KF(b,m)))),y=U(Q(ae(m,g)),t.damperSide??1),x=ee(s,U(y,c));return{...r,rockerPivotA:l,rockerPivotB:u,rockerToPushrod:h,rockerToDamper:x}}var qV=.72,KF=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2];function HF(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 ZV(e,t={}){let r=t.target??HF(e),n=t.armAngleDeg,o=ip(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=ip(e,{armRod:s,armAngleDeg:n,damperSide:p}),h={...e,config:{...e.config,actuation:"rocker"},hardpoints:d};try{let b=et(h),g=ge(b,15,0),y=ge(b,-15,0);if(g.ok&&y.ok&&g.state.metrics.damperLength<y.state.metrics.damperLength)return p}catch{}}return 1})(),c=(p,d)=>{try{return HF({...e,config:{...e.config,actuation:"rocker"},hardpoints:ip(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 x=(d+h)/2,M=c(p,x);if(!Number.isFinite(M))break;b=x,M<r?d=x:h=x}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 ip(e,{armRod:u,armAngleDeg:n,armDamper:m,damperSide:i})}var ige=Array.from({length:19},(e,t)=>-45+5*t);var cge=Math.PI/180;function JV(e){let t=e.hardpoints,r=Q(H(t.rockerPivotB,t.rockerPivotA)),n=Ur(t.rockerToDamper,t.rockerPivotA,r),o=.6*jr(H(t.rockerToDamper,n)),a=ae(r,Ky),s=jr(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 e5=(e,t)=>({...e,config:{...e.config,actuation:t}});function G0(e,t,r,n){let o=r==="front"?e.front:e.rear,a=uu(o),s=o.config.springRate*a*a,i=Z(t,r==="front"?"damper_front":"damper_rear")*a*a,c=r==="front"?t.arbFrontDesign:t.arbRearDesign,l=zn(e,t)[r]??Z(t,r==="front"?"arb_front":"arb_rear"),u=fa(e,t)[r]??Z(t,r==="front"?"heave_spring_front":"heave_spring_rear"),m=YF(o),f=e5(m?{...o,hardpoints:{...o.hardpoints,...m}}:o,"decoupled"),p=r==="front"?t.heaveFrontDesign:t.heaveRearDesign,d=n?.heave??WF(p?.linkage,w=>An(f,w).atDesign)??Md(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??WF(h?g:c?.linkage,w=>Go(f,w,{kind:b}).atDesign)??(h?JV(f):P1(f)),x=An(f,d).atDesign,M=Go(f,y,{kind:b}).atDesign,v=pu(e,t),R=VF({cornerWheelRate:s,cornerDamper:i,arbWheelRate:l,heaveWheelRate:u,heaveWheelDamping:r==="front"?v.heaveFront:v.heaveRear,rollWheelDamping:r==="front"?v.rollFront:v.rollRear,heaveMotionRatio:x,rollMotionRatio:M}),k=!c||c.design.kind==="none"?{design:{kind:"coil",rate:1},linkage:y}:{...c,linkage:y},F=$F({design:p?.design??{kind:"none"},linkage:d,damper:p?.damper},k,R,M);return m?{...F,crank:m}:F}function WF(e,t){return e&&Math.abs(t(e))>=gc?e:void 0}var cp=[{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"]}],K0=()=>({arbFront:void 0,arbRear:void 0,heaveFront:void 0,heaveRear:void 0}),t5={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]}},r5={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]}},n5=()=>({outer:[0,189,486],attach:"rocker",mount:{kind:"chassis",anchor:[-225,0,486]}}),o5={rate:60,motionRatio:1},a5={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]}},s5=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]}},i5={kind:"coil",rate:1560,motionRatio:1,gap:0,bothWays:!0},c5=40,l5={rockerPivotA:[50,130,440],rockerPivotB:[-50,130,440],rockerToPushrod:[10,170,460],rockerToDamper:[-20,64,440],damperChassis:[-20,64,215]},jF=()=>({outer:[-50,130,480],attach:"rocker",shaftStation:-50}),UF=()=>({outer:[50,130,400],inner:[50,130,480],attach:"rocker",shaftStationOuter:50,shaftStationInner:50}),u5=e=>[e[0],e[1],e[2]];function m5(e){let t=r=>({...r,hardpoints:{...r.hardpoints,...QF(l5)},config:{...r.config,actuation:"decoupled"}});return{...e,front:t(e.front),rear:t(e.rear)}}function QF(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,u5(r)]))}function qF(e,t=io(),r=e==="pull"?r5:t5){let n=(o,a)=>({...o,hardpoints:{...o.hardpoints,...QF(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 lp(e,t){let r=H0(e),n=Ka(e);if(e==="heave")return{meta:r,vehicle:n,components:{...K0(),heaveFront:{design:{...Vh,...o5},linkage:n5()}}};if(e!=="decoupled")return{meta:r,vehicle:n,components:K0()};let o=G0(n,t,"front",{heave:jF(),roll:UF()}),a=G0(n,t,"rear",{heave:jF(),roll:UF()});return{meta:r,vehicle:n,components:{arbFront:o.arb,arbRear:a.arb,heaveFront:o.heave,heaveRear:a.heave}}}function Ka(e){let{name:t}=H0(e);if(e==="direct")return{...Bi(),name:t};if(e==="mcpherson"){let n=$i(),o=dm();return{...n,front:{...o,config:{...o.config,loadedRadius:n.front.config.loadedRadius}},name:t}}let r=p5(qF(e==="pullrod"?"pull":"push"));return{...e==="decoupled"?m5(r):r,name:t}}var XF={front:221.7,rear:220.9};function p5(e){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:XF.front}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:XF.rear}}}}function H0(e){let t=cp.find(r=>r.id===e);if(!t)throw new Error(`Unknown suspension template: ${e}`);return t}function up(){let e=t=>({design:{...i5},linkage:s5(t),damper:c5});return{meta:H0("heave"),vehicle:qF("push",Zb(),a5),components:{...K0(),heaveFront:e("front"),heaveRear:e("rear")}}}var ZF=[10,25,50,100,200,300],d5=[{id:"c1",label:"Soft",scale:.7},{id:"c2",label:"Medium",scale:1},{id:"c3",label:"Firm",scale:1.4}],JF=e=>Math.round(e*100)/100;function f5(e,t,r){let n=ZF.map(o=>JF(r*o));return{id:e,label:t,speedMmS:[...ZF],bumpN:n,reboundN:[...n]}}function h5(e){return{name:e.name,body:{...e.body},curves:d5.map(t=>f5(t.id,t.label,JF(e.coefficient*t.scale)))}}function yc(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:Wi[e.dampers.length%Wi.length],model:h5(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)`,z0={car:{name:lt("Formula Student damper"),coefficient:2.5,body:{extended:249,stroke:55}}},mp={car:z0.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}}},pp={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}}},Y0={car:{name:lt("Sports car damper"),coefficient:2.4,body:{extended:515,stroke:110}}},tw={car:{name:lt("Sports car strut"),coefficient:2.4,body:{extended:310,stroke:120}},rear:Y0.car},rw={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}}},aw={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 za(e){return e.vehicles=e.vehicles.slice(0,1),e.activeVehicleId=e.vehicles[0]?.id??null,e}function Rn(e,t){let r=ji(e);return r.meta.rulesetId=t,r}function xo(e,t,r,n){let o=Rn(e,t);return o.suspensions=[{...o.suspensions[0],model:n()}],o.vehicles=[Sg(r,"v1",0)],o.activeVehicleId="v1",o}var[,b5,g5,y5,x5,R5,v5,k5]=sg;function W0(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 sw(){return{...Ka("decoupled"),name:io().name}}var M5=[{label:"Formula Student (decoupled)",vehicle:sw,components:e=>yc(lp("decoupled",e).components,mp)},{label:"Formula 1 (third springs)",vehicle:()=>up().vehicle,components:()=>yc(up().components,pp)}],j0={"direct-coilover":"direct",pushrod:"pushrod",pullrod:"pullrod","third-spring":"heave","mcpherson-strut":"mcpherson"},S5=[...M5.map(e=>e.vehicle),...Object.values(j0).map(e=>()=>Ka(e))];function Ha(e){let t=yc(lp("decoupled",e.vehicles[0].params).components,mp);e.suspensions=[{...e.suspensions[0],model:sw()}];for(let r of e.vehicles)W0(r.params,t);return fr(e,mp),e}var Ro={title:"OpenStreetMap",url:"https://www.openstreetmap.org/copyright",licence:"ODbL-1.0",credit:"\xA9 OpenStreetMap contributors"},dp={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"},iw={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]"},cw={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"},A5={id:"cota",name:"Circuit of the Americas, Austin",address:"e0c6ea889d708cf15f9c",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Ro,dp,cw]}},F5={id:"laguna-seca",name:"Laguna Seca, Monterey",address:"185b5811b9c423ef44ef",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Ro,dp,cw]}},w5={id:"nordschleife",name:"Nordschleife, N\xFCrburg",address:"74c49603c7b2f15985c6",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Ro,iw]}},C5={id:"brands-hatch",name:"Brands Hatch, Kent",address:"c4953e3c25eaba4a5b7e",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Ro,{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."}]}},T5={id:"bristol",name:"Bristol, Tennessee",address:"f0e23953669a414ad600",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Ro,dp]}},P5={id:"pikes-peak",name:"Pikes Peak, Colorado",address:"3de137fe33b5c2875036",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Ro,dp]},standingStart:!0},L5={source:"venue",altitudeM:3580,pressure:{kind:"standard"},humidityPct:0},D5=10,E5={id:"nurburg-sprint",name:"Sprintstrecke, N\xFCrburg",address:"1875636cdbb615aa2756",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Ro,iw]}};function vo(e,t){let{id:r,name:n,address:o,provenance:a,standingStart:s}=t,i={kind:"catalogue",id:r,address:o},c=Gi(bg({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 vn(e,t,r){let n=e.vehicles[0].params,o=`m${e.motors.length+1}`;e.motors=[...e.motors,{id:o,color:bn[e.motors.length%bn.length],model:t}];let a=Z1({},{...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 I5=3.8,fp={hubPlanetary:14.5,inboardChain:4,engineChain:3.4},_5="Hub motor, 35 kW (example)";function U0(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 lw(e){let t=e.motors.find(r=>r.id==="m1");return t.model={...t.model,name:_5},t.id}function hp(e,t,r){let n=za(Ha(Rn(e,r)));return n.vehicles[0].params.name=t,n}function N5(){let e=hp("Formula Student combustion car","Formula Student combustion","fs-cv");vn(e,mg(),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 O5(){let e=hp("Formula Student AWD car","Formula Student AWD","fs-ev");return U0(e,lw(e),4,"awd",fp.hubPlanetary,"hub"),e}function V5(){let e=hp("Formula Student RWD hub-motor car","Formula Student RWD hub motors","fs-ev");return U0(e,lw(e),2,"rear",fp.hubPlanetary,"hub"),e}function B5(){let e=hp("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:bn[e.motors.length%bn.length],model:ug()}],U0(e,t,1,"rear",fp.inboardChain),e.vehicles[0].params.driveline={rear:structuredClone(xt.clutch)},e}function $5(){let e=za(Ha(Rn("Formula Student endurance energy","fs-ev"))),t=e.vehicles[0],r=structuredClone(t);if(r.id="v2",r.color=Yi[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 G5(){let e=up(),t=xo("Formula 1 car","trackday",b5,()=>e.vehicle);return W0(t.vehicles[0].params,yc(e.components,pp)),fr(t,pp),vn(t,pg(),I5),vo(t,A5)}function uw(e="GT car",t=Bi){let r=xo(e,"trackday",g5,t);return fr(r,ew),vn(r,FS(),r.vehicles[0].params.gear_ratio.value),vo(r,F5)}function mw(e="Sports car",t=$i,r=Y0){let n=xo(e,"trackday",y5,t);return fr(n,r),vn(n,wS(),n.vehicles[0].params.gear_ratio.value),vo(n,w5)}function K5(){let e=xo("Cup car","trackday",x5,fS);return fr(e,rw),vn(e,CS(),e.vehicles[0].params.gear_ratio.value),vo(e,C5)}function H5(){let e=xo("Stock car","trackday",R5,hS);return fr(e,nw),vn(e,TS(),e.vehicles[0].params.gear_ratio.value),vo(e,T5)}function z5(){let e=xo("Hill-climb prototype","trackday",v5,bS);return fr(e,ow),vn(e,PS(),e.vehicles[0].params.gear_ratio.value),e.settings.air=structuredClone(L5),e.settings.airTempC=D5,vo(e,P5)}function Y5(){let e=xo("Race truck","trackday",k5,gS);return fr(e,aw),vn(e,LS(),e.vehicles[0].params.gear_ratio.value),vo(e,E5)}function W5(e){let t=cp.find(o=>o.id===e);if(e==="direct")return uw(t.name,()=>Ka(e));if(e==="mcpherson")return mw(t.name,()=>Ka(e),tw);let r=za(Rn(t.name,"trackday")),n=lp(e,r.vehicles[0].params);return r.suspensions=[{...r.suspensions[0],model:n.vehicle}],W0(r.vehicles[0].params,n.components),fr(r,z0),r}function xc(e,t,r){let n=j0[e],o=cp.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:()=>W5(n)}}var j5=[{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:()=>Ha(Rn("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:$5},{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:()=>za(Ha(Rn("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:N5},{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:O5},{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:V5},{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:B5},{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:G5},{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:uw},{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:mw},{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:K5},{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:H5},{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:z5},{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:Y5},{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:()=>za(Ha(Rn("Suspension study","trackday")))},xc("direct-coilover","The GT car\u2019s wishbones driving coilovers straight into the towers, at Laguna Seca.","On the GT car, at Laguna Seca."),xc("pushrod","The FS car on pushrods: a rod from each lower wishbone works a rocker.","On the Formula Student car, at FSG."),xc("pullrod","The FS car on pullrods: a rod from each upper wishbone pulls a low rocker.","On the Formula Student car, at FSG."),xc("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."),xc("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:()=>za(Ha(Rn("Tyre study","fs-ev")))}],pw=j5.map(e=>({...e,load:()=>Ag(e.load())}));var dw={width:320,height:200},Wge=[.6*dw.width-9,.6*dw.height-9];var fw=new WeakMap,hw=new WeakMap,X0=e=>JSON.stringify(e,(t,r)=>r===1/0?"Infinity":r);function bw(e,t){if(!t){let a=fw.get(e);return a||(a=Ct(e),fw.set(e,a)),a}let r=hw.get(e);r||(r=new Map,hw.set(e,r));let n=X0(t),o=r.get(n);return o||(r.size>=4&&r.clear(),o=Ct(e,t),r.set(n,o)),o}var Q5=Math.PI/180,q5=e=>e>1?e/100:e;function Rc(e){let t=null;return()=>(t??={v:e()}).v}function gw(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 yw=new WeakMap,Q0={heave:0,pitch:0,roll:0,steer:0},xw=[0,1,2,3,4],Rw=[-20,-10,0,10,20];function kw(e,t){let r=_r(e,Q0),n=["front","rear"],o=c=>{let l=ai(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 xw){let l=c===0?null:_r(e,{...Q0,roll:c*Q5});n.forEach((u,m)=>{let f=l?ai(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 Rw){let l=c===0?null:_r(e,{...Q0,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:xw,rcFront:s[0].rc,rcRear:s[1].rc,rcSplitFront:s[0].split,rcSplitRear:s[1].split},heave:{drop:Rw,rcFront:i[0],rcRear:i[1]}}}var vw=new WeakMap;function Z5(e,t,r,n){let o=vw.get(e);o||(o=new Map,vw.set(e,o));let a=`${X0(r)}|${n[0]}|${n[1]}`,s=o.get(a);if(!s){o.size>=4&&o.clear();try{s=kw(bw(e,r),n)}catch{s=t.rigidMigration(n)}o.set(a,s)}return s}function J5(e){let t=yw.get(e);if(t)return t;let r=Ct(e),n=_r(r,{heave:0,pitch:0,roll:0,steer:0}),o=gw(e.front),a=gw(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:da(n.front),rcGainRear:da(n.rear),rigidMigration:i=>kw(r,i),kinFront:Rc(()=>qo(e.front)),kinRear:Rc(()=>qo(e.rear))};return yw.set(e,s),s}function Mw(e,t,r,n){let o=J5(e),a=zn(e,t),s=fa(e,t),i=z1(e,t),c=pu(e,t),l=Y1(e,t),u=j1(t),m=W1(e,t),f=Hn(e.front),p=Hn(e.rear),d=Kn(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,Z(t,"cop_long"))),copHeight:Z(t,"cop_height"),...t.aeroModel?{model:t.aeroModel}:{},rideHeightFront:Z(t,"ride_height_front"),rideHeightRear:Z(t,"ride_height_rear")},b=9.81,g=q5(t.front_mass_diss.value),y=ba(t,r,n),x=Ie(y.front),M=y.rear===y.front?x:Ie(y.rear),v=n??t.tireModelRear??r,R=t.m.value*b*g/2,k=t.m.value*b*(1-g)/2,F=x.corneringStiffness(R),w=M.corneringStiffness(k),C=(r?x.verticalStiffness():0)||Z(t,"tire_vertical_rate"),T=(v?M.verticalStiffness():0)||Z(t,"tire_vertical_rate"),S=er(r)??0,A=er(v)??0,P=gu({freeRadius:S,staticLoad:R,tyreRate:C,surveyed:e.front.config.loadedRadius},{freeRadius:A,staticLoad:k,tyreRate:T,surveyed:e.rear.config.loadedRadius},g),L=$t(S,R,C,e.front.config.loadedRadius),D=$t(A,k,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)],$=Rc(()=>ui(o.kinFront(),Z(t,"camber_front_deg"))),O=Rc(()=>ui(o.kinRear(),Z(t,"camber_rear_deg"))),W=Rc(()=>Z5(e,o,Na(V),E)),I=Bs({...t,wheelbase:{...t.wheelbase,value:o.wheelbase}}),_=li(t),V={massTotal:t.m.value,frontMassFrac:g,steeringSystem:t.steeringSystem,tv:eu(t),cgHeight:ha(Z(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:Z(t,"tire_vertical_damping"),arbFront:a.front??Z(t,"arb_front"),arbRear:a.rear??Z(t,"arb_rear"),brakeBalanceFront:I.balanceFront,brakes:I,..._?{driveline:_}:{},heaveSpringFront:s.front??Z(t,"heave_spring_front"),heaveSpringRear:s.rear??Z(t,"heave_spring_rear"),unsprungPerCorner:Z(t,"unsprung_mass"),unsprungCgHeight:$t(S,R,C,o.unsprungCgHeight),tyreFreeRadius:S,...A!==S?{tyreFreeRadiusRear:A}:{},rcHeightFront:E[0],rcHeightRear:E[1],corneringStiffnessFront:F,corneringStiffnessRear:w,get kinFront(){return $()},get kinRear(){return O()},damperFront:f?0:d?.front?.rate??Z(t,"damper_front")*o.mrFront*o.mrFront,damperRear:p?0:d?.rear?.rate??Z(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:Z(t,"unsprung_mass"),get rollCentreCurve(){return W().roll},get rcHeaveCurve(){return W().heave},aero:h,yawInertia:Z(t,"I_yaw"),rollInertia:Z(t,"I_roll"),pitchInertia:Z(t,"I_pitch"),get steerFront(){return du(e.front,L)},ackermannPct:Z(t,"ackermann_pct"),toeFrontDeg:Z(t,"toe_front_deg"),toeRearDeg:Z(t,"toe_rear_deg")};return V}var Aw=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}),Z0={ggvMode:"twoTrack"},Sw=new WeakMap;function J0(e,t=Z0){let r=Sw.get(e.vehicle);r||Sw.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={...Aw(e.params),suspensionOf:()=>e.vehicle};n.set(o,a=yo(e.params,s,t))}return a}var Fw=(e=Z0)=>t=>J0(t,e),ww=(e=Z0)=>t=>Mw(t.vehicle,N0(t.params,Aw(t.params),e),t.params.tireModel,t.params.tireModelRear);function e3(e,t){return J0(e,t.switches)}var ey=e=>Kr(e?.rulesets);function Cw(e,t,r,n,o={},a=()=>r.standingStart){let s=J0(n,r.switches),i=(l,u)=>{let m=sm(l,t,{racingLine:r.racingLine,params:s});return{asset:m.asset,numerics:m.numerics,standingStart:u,racingLine:r.racingLine}},c=Object.fromEntries(Object.entries(o).map(([l,u])=>[l,i(u,a(l))]));return{course:e?i(e,r.standingStart):null,numerics:t,tracks:c,switches:r.switches}}var Tw=e=>[...new Set(e.lap.courses.flatMap(t=>t.course.kind==="track"?[t.course.trackId]:[]))],Pw=e=>{let t=e?.session;return t?{sessionParams:r=>e3(r,t),session:()=>t}:{}},bp=e=>({metrics:ey(e),assemble:ww(e?.switches),simParams:Fw(e?.switches),projectTrack:()=>e?.course??null,libraryTrack:t=>e?.tracks?.[t]??null,numerics:e?.numerics,...Pw(e)}),t3=(e,t)=>({density:e.density,envelope:e.envelope,states:e.states,operating:e.operating,lap:e.lap,assemble:ww(t?.switches),simParams:Fw(t?.switches),projectTrack:()=>t?.course??null,libraryTrack:r=>t?.tracks?.[r]??null,numerics:t?.numerics,...Pw(t)}),Lw="nelder-mead",Dw=600,vc=[0,.15,.15];function Ew(e,t,r,n=vc.length){let o=ny(t);return vc.slice(0,Math.max(1,n)).map((a,s)=>({...e,seed:s+1,startJitter:a,car:o,...r?{lap:r}:{}}))}function Iw(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 _w(e,t,r,n,o=.01){let a=ey(n).byId;return r3(e,t,r,n).filter(s=>s.excess>-o*(a[s.metricId]?.scale??1))}function r3(e,t,r,n){let o;try{o=gn(Jm(e,t,r),t3(t,n))}catch{return[]}return n3(o,t,ey(n))}function n3(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=`${it(a)}${fc(o.at,a)}`;n.push({key:o.key,metricId:o.metricId,label:i,unit:a.unit==="-"?"":a.unit,value:s,excess:dc(o,s)})}return n}var o3=.05;function a3(e,t){if(t.id.startsWith("hp.")||Qm(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 d0(xn(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 u0(Hr(o.hardpoints,n[2]),n[3],1)}function Nw(e,t,r){let n=r.filter(f=>f.score.feasible);if(n.length<2)return null;let o=t.map(f=>a3(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(o3,m),unit:a}}var s3={steeringSystem:!0,brakeSetup:!0,driveline:!0,heaveFrontDesign:!0,heaveRearDesign:!0,arbFrontDesign:!0,arbRearDesign:!0},Ow=e=>Object.hasOwn(s3,e);function q0(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 i3(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":Ow(t)||q0(e)?"block":null}function ty(e,t){t=Dt(e,t);let r=Gt(e);return[...t.variables,...t.followers??[]].filter(n=>r[n.id]&&!r[n.id].supersededBy&&!i3(n.id)).map(n=>ct(r[n.id]))}function Vw(e,t,r){t=Dt(e,t);let n=Gt(e),o=Jm(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[fo.fore,fo.aft]){let y=b.hardpoints[g];for(let x=0;x<3;x++)a.push({kind:"hardpoint",axle:f,key:g,axis:x,value:y[x]})}}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 x=b.hardpoints[y];for(let M=0;M<3;M++)a.push({kind:"hardpoint",axle:f,key:y,axis:M,value:x[M]})}}else if(m==="hp"&&pr(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(Ow(m)||q0(c.id)){let h=q0(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 ry(e){let t=performance.now(),r=bp(e.lap),n=e.follow?S0(e.car,e.spec,r):e.spec,{dead:o,unprobed:a,...s}=C0(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 ny=e=>e.vehicle.chassis?{...e,vehicle:V0(e.vehicle)}:e;function Bw(e,t){try{let r=oy(e.car,e.spec,e.lap),n=ea.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&&g0(r.variables)?x0(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 oy=(e,t,r)=>ep(e,t,bp(r));function $w(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),...Js(e,t.damper)}}function Gw(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 Kw=e=>({ggvMode:e.ggvMode,quasiTransient:e.quasiTransient===!0&&e.ggvMode!=="fast",motorThermal:e.motorThermal===!0,...bF({brakeFade:e.brakeFade===!0,airTempC:e.airTempC,diffYaw:e.diffYaw===!0,...e.air?{air:e.air}:{}})});function c3(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 Hw(e,t){let r=t.plannedPath!==void 0,n=c3(t);return{...Cw(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 ay(e,t){let r=e.vehicles.find(o=>o.id===t);if(!r)throw new Error(`this project holds no vehicle "${t}"`);let n=go(e);return Gw(structuredClone(_0(e,r.params)),structuredClone(r.params),$w(r.params,n))}var l3="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 sy(e,t,r,n){if(e.settings.pathPlanId)throw new Error(l3);let o=Ga(e),a=e.tracks.length?(await np(e,t)).asset:null,s={};for(let i of n?Tw(n):[]){let c=e.tracks.find(l=>l.id===i);c&&(s[i]=await bc(c,t))}return Hw(r,{track:a,numerics:o.numerics,racingLine:o.racingLine,standingStart:o.standingStart,lapCounts:o.lapCounts??{},switches:Kw(o),rulesets:e.rulesets??[],library:s,standingOf:i=>e.tracks.find(c=>c.id===i)?.standingStart===!0})}async function zw(e,t,r,n){let o=ay(e,r),a=Dt(o,n),s=await sy(e,t,o,a);return ry({id:0,car:o,spec:a,lap:s})}async function Yw(e,t,r,n){let o=ay(e,r),a=Dt(o,n),s=ty(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 sy(e,t,o,a)}catch(l){return{problems:[l instanceof Error?l.message:String(l)]}}let c=w0(o,a,{...bp(i),metrics:Kr(e.rulesets)});return c.length?{problems:c}:{problems:[],msPerEval:ry({id:0,car:o,spec:a,lap:i}).msPerEval,carFingerprint:eo(ny(o))}}async function u3(e,t,r,n,o,a=[]){let s=Ew(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(Bw(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 Ww(e,t,r,n){let o=ay(e,r.vehicleId),a=Dt(o,r.spec),s=ty(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 sy(e,t,o,a),c=r.method??Lw;if(!ea.some(b=>b.name===c))throw new Error(`unknown method "${c}" \u2014 it is one of ${ea.map(b=>b.name).join(", ")}`);let l=r.budget??Dw,u=Math.max(1,Math.min(r.seeds??vc.length,vc.length)),m=await u3(o,{spec:a,method:c,budget:l},i,u,n),f=oy(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:Iw(f.variables,b.x),constraints:_w(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)=>Cs(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?Nw(o,f.variables,m.runs.map(b=>({x:b.x,score:b.score}))):null,writes:Vw(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 Uw(){if(typeof process.threadCpuUsage!="function")return performance.now();let e=process.threadCpuUsage();return(e.user+e.system)/1e3}async function p3(e,t){let r=pF(e.root);switch(e.kind){case"sweep":return AF(e.doc,r,e.req,t);case"convergence":return MF(e.doc,r,{vehicleId:e.vehicleId,...e.steps?{steps:e.steps}:{},...e.tolPct!==void 0?{tolPct:e.tolPct}:{},onStep:t});case"study":return Ww(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 op(e.doc,r,{...e.vehicleIds?{vehicleIds:e.vehicleIds}:{},...e.settings?{settings:e.settings}:{},...e.overrides?{overrides:e.overrides}:{}});case"probe":return zw(e.doc,r,e.vehicleId,e.spec);case"quote":return Yw(e.doc,r,e.vehicleId,e.spec)}}if(jw){let e=jw,t=r=>e.postMessage(r);(async()=>{try{let r=await p3(m3,(n,o)=>t({type:"progress",done:n,total:o}));t({type:"done",result:r,cpuMs:Uw()})}catch(r){t({type:"failed",message:r instanceof Error?r.message:String(r),cpuMs:Uw()})}})()}export{p3 as runJob,Uw as threadCpuMs};
|
|
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};
|