@pacedyn/mcp 0.394.4 → 0.396.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/worker.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{parentPort as eT,workerData as KB}from"node:worker_threads";import{readFileSync as Ry}from"node:fs";import{join as vy}from"node:path";var Hc=e=>e.format!=="points"&&!e.field;var ft=e=>e?.kind==="ice";var qy={packVoltageMax:600,segmentVoltageMax:120,powerLimitKw:80};var Ee=e=>typeof e=="number"&&Number.isFinite(e);function rT(e){let{soc:t,ocv:r,r0:n}=e;if(!Array.isArray(t)||t.length<2)return"The curve needs at least two state-of-charge points.";if(!t.every(Ee))return"The state-of-charge axis contains a value that is not a number.";if(t[0]<0||t[t.length-1]>1)return`The state-of-charge axis must lie within 0 to 1 (it runs ${t[0]} to ${t[t.length-1]}).`;for(let o=1;o<t.length;o++)if(!(t[o]>t[o-1]))return`The state-of-charge axis must increase (${t[o-1]} then ${t[o]}).`;if(!Array.isArray(r)||r.length!==t.length)return`The curve has ${Array.isArray(r)?r.length:0} voltages against ${t.length} state-of-charge points.`;if(!r.every(Ee))return"The open-circuit voltage contains a value that is not a number.";if(r.some(o=>o<=0))return"The open-circuit voltage must be positive everywhere.";for(let o=1;o<r.length;o++)if(r[o]<r[o-1])return`The open-circuit voltage must rise with state of charge (${r[o-1]} V at ${t[o-1]} then ${r[o]} V at ${t[o]}).`;if(!Array.isArray(n)||n.length!==t.length)return`The curve has ${Array.isArray(n)?n.length:0} resistances against ${t.length} state-of-charge points.`;if(!n.every(Ee))return"The resistance contains a value that is not a number.";if(n.some(o=>o<0))return"The resistance cannot be negative.";if(e.rTempC!==void 0||e.rGrid!==void 0){let o=e.rTempC,a=e.rGrid;if(!Array.isArray(o)||o.length<1)return"The resistance temperature axis needs at least one temperature.";if(!o.every(Ee))return"The resistance temperature axis contains a value that is not a number.";for(let s=1;s<o.length;s++)if(!(o[s]>o[s-1]))return`The temperature axis must increase (${o[s-1]} then ${o[s]} \xB0C).`;if(!Array.isArray(a)||a.length!==o.length)return`The resistance grid has ${Array.isArray(a)?a.length:0} rows against ${o.length} temperatures.`;for(let s=0;s<a.length;s++){let i=a[s];if(!Array.isArray(i)||i.length!==t.length)return`Resistance row ${s+1} has ${Array.isArray(i)?i.length:0} values against ${t.length} state-of-charge points.`;if(!i.every(Ee))return"The resistance grid contains a value that is not a number.";if(i.some(c=>c<0))return"The resistance grid contains a negative resistance."}}return null}function nT(e){return!e||typeof e!="object"?"The cell has no curve.":e.kind==="table"?rT(e):e.kind==="analytic"?!Ee(e.vCut)||!Ee(e.vNom)||!Ee(e.vFull)?"The cut-off, nominal and full voltages must be numbers.":e.vCut<=0?"The cut-off voltage must be positive.":e.vCut<e.vNom&&e.vNom<e.vFull?!Ee(e.r0)||e.r0<0?"The cell resistance must be a number and cannot be negative.":e.socAtNom!==void 0&&(!Ee(e.socAtNom)||e.socAtNom<=0||e.socAtNom>=1)?"The state of charge the nominal voltage is met at must lie strictly between 0 and 1.":null:`The voltages must order cut-off < nominal < full (given ${e.vCut}, ${e.vNom}, ${e.vFull} V).`:`Unknown cell curve kind "${e.kind}".`}function zc(e){if(!e||typeof e!="object")return"Not a battery model.";let t=e.cell;if(!t||typeof t!="object")return"The model has no cell.";if(!Ee(t.capacityAh)||t.capacityAh<=0)return"The cell capacity must be a positive number of amp-hours.";if(!Ee(t.vMin)||t.vMin<0)return"The cut-off voltage must be a number and cannot be negative.";if(!Ee(t.vMax)||t.vMax<=0)return"The maximum cell voltage must be a positive number.";if(!(t.vMin<t.vMax))return`The cut-off voltage (${t.vMin} V) must be below the maximum (${t.vMax} V).`;if(!Ee(t.iMaxA)||t.iMaxA<0)return"The discharge current limit must be a number of amps, 0 for no limit.";if(t.iMaxChargeA!==void 0&&(!Ee(t.iMaxChargeA)||t.iMaxChargeA<0))return"The charge current limit must be a number of amps, 0 for no limit.";if(t.massKg!==void 0&&(!Ee(t.massKg)||t.massKg<0))return"The cell mass must be a number and cannot be negative.";let r=nT(t.curve);if(r)return r;let n=t.curve.kind==="table"?t.curve.ocv[t.curve.ocv.length-1]:t.curve.vFull;if(t.vMin>=n)return`The cut-off voltage (${t.vMin} V) is at or above the cell's voltage at full charge (${n} V), so no power could ever be drawn.`;let o=e.thermal;if(o!==void 0){if(!o||typeof o!="object")return"The thermal model must be an object, or absent.";if(!Ee(o.heatCapacityJPerK)||o.heatCapacityJPerK<=0)return"The cell heat capacity must be a positive number of joules per kelvin.";if(!Ee(o.coolingWPerK)||o.coolingWPerK<0)return"The cooling must be a number of watts per kelvin and cannot be negative.";if(o.startC!==void 0&&!Ee(o.startC))return"The starting temperature must be a number.";if(o.entropicVPerK!==void 0&&!Ee(o.entropicVPerK))return"The entropic coefficient must be a number.";if(o.derateFromC!==void 0){if(!Ee(o.derateFromC))return"The temperature the derate starts at must be a number.";if(o.derateToC!==void 0){if(!Ee(o.derateToC))return"The temperature the derate ends at must be a number.";if(!(o.derateToC>o.derateFromC))return`The derate must end above where it starts (given ${o.derateFromC} then ${o.derateToC} \xB0C).`}}else if(o.derateToC!==void 0)return"The derate has an end temperature but no start; give both or neither."}let a=e.pack;if(!a||typeof a!="object")return"The model has no pack.";if(!Number.isInteger(a.series)||a.series<1)return"The pack needs a whole number of cells in series, at least one.";if(!Number.isInteger(a.parallel)||a.parallel<1)return"The pack needs a whole number of strings in parallel, at least one.";if(!Ee(a.busResistance)||a.busResistance<0)return"The busbar resistance must be a number and cannot be negative.";if(a.seriesPerSegment!==void 0&&a.seriesPerSegment!==0){if(!Number.isInteger(a.seriesPerSegment)||a.seriesPerSegment<1)return"The cells per segment must be a whole number, at least one.";if(a.seriesPerSegment>a.series)return`A segment cannot hold more cells (${a.seriesPerSegment}) than the pack has in series (${a.series}).`}return null}function Ln(e,t){let r=e.length;if(r<=1)return{i:0,t:0,clamped:!1};if(t<=e[0])return{i:0,t:0,clamped:t<e[0]};if(t>=e[r-1])return{i:r-2,t:1,clamped:t>e[r-1]};let n=0,o=r-1;for(;o-n>1;){let a=n+o>>1;e[a]<=t?n=a:o=a}return{i:n,t:(t-e[n])/(e[o]-e[n]),clamped:!1}}function $e(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function Yc(e,t,r,n,o){let a=e.length,s=t.length;if(a===0||s===0)return 0;let i=Ln(e,n),c=Ln(t,o),l=Math.min(i.i+1,a-1),u=Math.min(c.i+1,s-1),m=r[c.i][i.i],f=r[c.i][l],p=r[u][i.i],d=r[u][l],h=m+i.t*(f-m),b=p+i.t*(d-p);return h+c.t*(b-h)}var Io=[0,.05,.1,.2,.3,.4,.5,.6,.7,.8,.9,1],jp={nmc:[0,.29,.4,.483,.525,.567,.608,.667,.733,.8,.892,1],lfp:[0,.478,.591,.626,.652,.67,.678,.696,.704,.722,.757,1],lipo:[0,.333,.433,.517,.575,.625,.667,.717,.775,.833,.908,1],other:[0,.05,.1,.2,.3,.4,.5,.6,.7,.8,.9,1]},Qy=[0,.05,.1,.2,.5,.8,1],Zy=[2.2,1.55,1.3,1.12,1,.97,.98];function Jy(e){return $e(Qy,Zy,e)}var ex=[-20,-10,0,10,25,40,60],tx=[4,2.8,2,1.4,1,.82,.75];function Up(e){return $e(ex,tx,e)}var rx=.5;function Xp(e,t){let{vFull:r,vNom:n,vCut:o,r0:a}=e,s=r-o;if(!(s>0))throw new Error(`The full voltage (${r} V) must be above the cut-off (${o} V).`);let i=(n-o)/s;if(!(i>0&&i<1))throw new Error(`The nominal voltage (${n} V) must lie between the cut-off (${o} V) and full (${r} V).`);let c=jp[t]??jp.other,l=e.socAtNom??rx,u=Io.includes(l)?[...Io]:[...Io,l].sort((h,b)=>h-b),m=$e(Io,c,l),f=m>0&&m<1?Math.log(i)/Math.log(m):1,p=[],d=[];for(let h of u){let b=$e(Io,c,h);p.push(o+s*Math.pow(b,f)),d.push(e.constantResistance?a:a*Jy(h))}return{kind:"table",soc:u,ocv:p,r0:d}}function qp(e){let t=e.soc,r=e.ocv,n=[0,...t.filter(a=>a>0&&a<1),1],o=0;for(let a=1;a<n.length;a++){let s=n[a-1],i=n[a];o+=($e(t,r,s)+$e(t,r,i))/2*(i-s)}return o}var _o=25,nx=new WeakMap;function xr(e){let t=nx.get(e);if(t)return t;let r=zc(e);if(r)throw new Error(r);let{cell:n,pack:o}=e,a=n.curve.kind==="table"?n.curve:Xp(n.curve,n.chemistry),s=o.series,i=o.parallel,c=s/i,l=a.rTempC,u=a.rGrid,m=i*n.capacityAh,f=s*n.vMin,p=n.iMaxA>0?i*n.iMaxA:1/0,d=n.iMaxChargeA!==void 0&&n.iMaxChargeA>0?n.iMaxChargeA:n.iMaxA/4,h=d>0?i*d:1/0,b=F=>s*$e(a.soc,a.ocv,F),g=(F,w=_o)=>{let C=l&&u?Yc(a.soc,l,u,F,w):$e(a.soc,a.r0,F)*Up(w);return c*C+o.busResistance},y=(F,w,C)=>b(F)-w*g(F,C),R=(F,w,C)=>{if(!(F>0))return 0;let T=b(w),S=g(w,C);if(!(S>0))return F/T;let A=T*T-4*S*F;return A<0?NaN:2*F/(T+Math.sqrt(A))},k=(F,w,C)=>{if(!(F>0))return 0;let T=b(w),S=g(w,C);return S>0?2*F/(T+Math.sqrt(T*T+4*S*F)):F/T},v=F=>{let w=e.thermal;if(!w||w.derateFromC===void 0)return 1;let C=w.derateToC??w.derateFromC;return F<=w.derateFromC?1:!(C>w.derateFromC)||F>=C?0:1-(F-w.derateFromC)/(C-w.derateFromC)},x=(F,w,C=0)=>{let T=b(F),S=g(F,w),A=S>0?T/(2*S):1/0,P=G=>{if(!(S>0))return G*T;let K=Math.min(G,A);return K*(T-K*S)},L=S>0?Math.max(0,(T-f)/S):1/0,D=C>0&&Number.isFinite(C)?C:1/0,E=S>0?P(L):1/0,V=Number.isFinite(p)?P(p):1/0,N=S>0?T*T/(4*S):1/0,z=[["rules",D],["voltage-floor",E],["current",V],["matched-load",N]],I=z[0][0],_=z[0][1];for(let[G,K]of z)K<_&&(_=K,I=G);let B=v(w??_o);B<1&&(_=Number.isFinite(_)?_*B:_,I="temperature");let O=Number.isFinite(_)?R(_,F,w):1/0;return{watts:_,binding:I,rules:D,voltageFloor:E,current:V,matchedLoad:N,derate:B,amps:O,volts:Number.isFinite(O)?T-O*S:T}},M={model:e,table:a,capacityAh:m,chargeC:m*3600,energyKwh:m*(s*qp(a))/1e3,socRange:[a.soc[0],a.soc[a.soc.length-1]],voltageAtFull:s*a.ocv[a.ocv.length-1],voltageCeiling:s*n.vMax,voltageFloor:f,currentCeiling:p,chargeCurrentCeiling:h,massKg:n.massKg!==void 0?s*i*n.massKg:null,thermal:e.thermal?{heatCapacityJPerK:s*i*e.thermal.heatCapacityJPerK,coolingWPerK:s*i*e.thermal.coolingWPerK,...e.thermal.startC!==void 0?{startC:e.thermal.startC}:{},entropicVPerK:s*(e.thermal.entropicVPerK??0)}:null,derateAt:v,ocv:b,resistance:g,terminalVoltage:y,currentFor:R,chargeCurrentFor:k,maxPower:x};return nx.set(e,M),M}function Qp(e){return{name:e.name,chemistry:e.chemistry,capacityAh:e.capacityAh,curve:{kind:"analytic",vFull:e.vFull,vNom:e.vNom,vCut:e.vCut,r0:e.r0},iMaxA:e.iMaxA,...e.iMaxChargeA!==void 0?{iMaxChargeA:e.iMaxChargeA}:{},vMin:e.vCut,vMax:e.vFull,...e.massKg!==void 0?{massKg:e.massKg}:{}}}var ox={name:"High-power NMC pouch 4.0 Ah",chemistry:"nmc",capacityAh:4,vCut:3,vNom:3.6,vFull:4.2,r0:.0025,iMaxA:100,iMaxChargeA:40,massKg:.09},ax={name:"LFP prismatic 20 Ah",chemistry:"lfp",capacityAh:20,vCut:2.5,vNom:3.2,vFull:3.65,r0:.002,iMaxA:200,iMaxChargeA:60,massKg:.4},sx={name:"NMC cylindrical 3.4 Ah",chemistry:"nmc",capacityAh:3.4,vCut:3,vNom:3.6,vFull:4.2,r0:.03,iMaxA:10,iMaxChargeA:3,massKg:.048};function Zp(){return{name:"Formula Student accumulator",cell:Qp(ox),pack:{series:140,parallel:2,busResistance:.02,seriesPerSegment:28},provenance:{source:"assumed",note:"Assumed high-power NMC pouch pack sized to the Formula Student rules; the cell curve and resistance are class-level guesses, not a measurement."}}}function Jp(){return{name:"LFP pack",cell:Qp(ax),pack:{series:160,parallel:1,busResistance:.02,seriesPerSegment:32},provenance:{source:"assumed",note:"Assumed LFP prismatic pack; the flat plateau is the chemistry, the numbers are class-level guesses."}}}function ed(){return{name:"Road car pack",cell:Qp(sx),pack:{series:96,parallel:74,busResistance:.01},provenance:{source:"assumed",note:"Assumed road-electric pack of cylindrical energy cells; capacity and voltage are class-typical, the resistance is a guess."}}}function td(e,t,r="Constant pack"){return{name:r,cell:{name:"Constant cell",chemistry:"other",capacityAh:e,curve:{kind:"table",soc:[0,1],ocv:[t,t],r0:[0,0]},iMaxA:0,vMin:0,vMax:t},pack:{series:1,parallel:1,busResistance:0},provenance:{source:"assumed",note:"The constant pack: one open-circuit voltage, no internal resistance and no current limit \u2014 what a car carried before the battery was a model. It cannot sag, so its power never fades."}}}function Wc(e){if(e.kind==="ice"){let n=e.gearbox.efficiency;return{model:e,maxTorque:o=>o>e.limitRpm?0:$e(e.rpm,e.torque,o),efficiency:()=>n}}let t=n=>$e(e.rpm,e.torque,n),r=e.kind==="simple"?()=>e.efficiency:(n,o)=>Yc(e.effRpm,e.effTorque,e.effGrid,n,o);return{model:e,maxTorque:t,efficiency:r}}function rd(e){let t=e.resistanceAtC??20,r=e.torqueConstant,n=e.speedLossW??0,o=e.speedLossAtRpm??0,a=e.speedLossExponent??1.5,s=e.derateFromC,i=e.derateToC,c=d=>Math.max(0,e.terminalResistanceOhm*(1+.00393*(d-t))),l=d=>n>0&&o>0?n*Math.pow(Math.max(0,d)/o,a):0,u=(d,h,b)=>{let g=r>0?Math.abs(h)/r:0;return 1.5*c(b)*g*g+l(d)},m=(d,h)=>{let b=e.coolingWPerK*(h-e.coolantC)-l(d);return!(b>0)||r<=0?0:r*Math.sqrt(b/(1.5*c(h)))},f=e.coolingWPerK>0?e.heatCapacityJPerK/e.coolingWPerK:1/0,p=Number.isFinite(f)?.25*f:1/0;return{spec:e,startC:e.startC??e.coolantC,lossW:u,step(d,h,b){if(!(b>0)||!(e.heatCapacityJPerK>0))return d;let g=Number.isFinite(p)?Math.max(1,Math.ceil(b/p)):1,y=b/g,R=d;for(let k=0;k<g;k++)R+=(h-e.coolingWPerK*(R-e.coolantC))*y/e.heatCapacityJPerK;return R},continuousTorque:m,derate(d,h,b){if(s===void 0||i===void 0||!(i>s)||!(b>0)||h<=s)return 1;let g=Math.min(1,m(d,i)/b);return h>=i?g:1-(1-g)*(h-s)/(i-s)},equilibriumC(d){return e.coolingWPerK>0?e.coolantC+d/e.coolingWPerK:1/0}}}function Xe(e,t){return t==="rear"&&e.tireRateRear!==void 0?e.tireRateRear:e.tireRate}function nd(e,t){let r=e.tyreFreeRadiusRear;return(t==="rear"&&r!==void 0?r:e.tyreFreeRadius)??0}var jc=9.81,ix=(e,t)=>e*(t*t)/2*(Math.PI/180)/1e3,ns=(e,t)=>e+t>0?e*t/(e+t):0,cx=.5;function Uc(e,t,r){if(!(r>0))return 1;let n=e*jc*t*(Math.PI/180)/r;return 1/(1-Math.min(cx,n))}function od(e,t,r){return r>0?e*jc*t/(r*r):0}function lx(e,t,r,n,o){if(!(n>0)||!(o>0))return 1;let a=od(e,t,r)*(1/n+1/o);return 1/(1-Math.min(cx,a))}function we(e){let t=4*e.unsprungPerCorner,r=Math.max(0,e.massTotal-t),n=r*e.frontMassFrac,o=r*(1-e.frontMassFrac),a=Xe(e,"front"),s=Xe(e,"rear"),i=e.wheelRateFront+(e.heaveSpringFront??0),c=e.wheelRateRear+(e.heaveSpringRear??0),l=ns(i,a),u=ns(c,s),m=(V,N)=>{let z=N/2;return z>0?1/(2*Math.PI)*Math.sqrt(V*1e3/z):0},f=m(l,n),p=m(u,o),d=ns(e.wheelRateFront+e.arbFront,a),h=ns(e.wheelRateRear+e.arbRear,s),b=ix(d,e.trackFront),g=ix(h,e.trackRear),y=b+g,R=y>0?b/y:.5,k=e.rcHeightFront+(e.rcHeightRear-e.rcHeightFront)*(1-e.frontMassFrac),v=(e.cgHeight-k)/1e3,x=r*jc*v,M=Uc(r,v,y),F=y>0?x/y*M:0,w=e.massTotal*jc*e.cgHeight/e.wheelbase,C=2*l,T=2*u,S=lx(r,e.cgHeight,e.wheelbase,C,T),P=(C>0&&T>0?(w/C+w/T)/e.wheelbase*S:0)*(180/Math.PI),L=e.wheelbase*e.wheelbase*ns(C,T)*(Math.PI/180)/1e3,D=e.damperFront??2.5,E=e.damperRear??2.5;return{sprungMass:r,sprungFront:n,sprungRear:o,rideRateFront:l,rideRateRear:u,rideFreqFront:f,rideFreqRear:p,rollRateFront:b,rollRateRear:g,rollRateTotal:y,rollWheelRateFront:d,rollWheelRateRear:h,frontRollStiffFrac:R,rollGradient:F,pitchGradient:P,pitchRate:L,cgRollGain:M,cgPitchGain:S,rideDampingFront:D+(e.heaveDamperFront??0),rideDampingRear:E+(e.heaveDamperRear??0),rollDampingFront:D+(e.rollDamperFront??0),rollDampingRear:E+(e.rollDamperRear??0)}}var qr=["clFront","clRear","cd"],Qr=e=>e.frame?.kind==="pitch";function No(e){return Qr(e)?{x:e.axes.h,y:e.axes.pitch}:{x:e.axes.hFront,y:e.axes.hRear}}var Xc=e=>e.frame?.kind==="pitch",ux=e=>e.kind==="map";var qc=45,Qe=e=>typeof e=="number"&&Number.isFinite(e);function Qc(e,t,r="mm",n="ride height"){if(!Array.isArray(t)||t.length<1)return`The ${e} axis needs at least one ${n}.`;if(!t.every(Qe))return`The ${e} axis contains a value that is not a number.`;for(let o=1;o<t.length;o++)if(!(t[o]>t[o-1]))return`The ${e} axis must increase (${t[o-1]} then ${t[o]} ${r}).`;return null}function mx(e,t){if(t===void 0)return null;for(let r of qr){let n=t[r];if(!n||!Array.isArray(n.deg)||!Array.isArray(n.factor))return`The ${e} correction of ${r} needs degrees and factors.`;if(n.deg.length<1)return`The ${e} correction of ${r} needs at least one angle.`;if(n.deg.length!==n.factor.length)return`The ${e} correction of ${r} has ${n.factor.length} factors against ${n.deg.length} angles.`;if(!n.deg.every(Qe)||!n.factor.every(Qe))return`The ${e} correction of ${r} contains a value that is not a number.`;if(n.deg[0]<0)return`The ${e} correction of ${r} is against the absolute angle; it cannot start below zero.`;for(let o=1;o<n.deg.length;o++)if(!(n.deg[o]>n.deg[o-1]))return`The ${e} correction of ${r} must increase in angle (${n.deg[o-1]} then ${n.deg[o]}\xB0).`;if(n.factor.some(o=>o<0))return`The ${e} correction of ${r} has a negative factor.`}return null}function px(e,t){return t===void 0?null:!Qe(t.dCl)||!Qe(t.dBalance)||!Qe(t.dCd)?`The ${e} slopes must be numbers.`:!Qe(t.maxDeg)||!(t.maxDeg>0)?`The ${e} response needs a positive angle to be valid to.`:null}function os(e){if(!e||typeof e!="object")return"Not an aero model.";if(!Qe(e.area)||e.area<=0)return"The reference area must be a positive number of square metres.";if(e.kind==="map"){let t,r,n,o;if(e.frame==null){let i=Qc("front ride-height",e.axes?.hFront);if(i)return i;let c=Qc("rear ride-height",e.axes?.hRear);if(c)return c;[t,r,n,o]=[e.axes.hFront,e.axes.hRear,"front ride heights","rear ride heights"]}else if(e.frame?.kind==="pitch"){if(!Qe(e.frame.refX))return"The point the ride height is read at must be a number of millimetres aft of the front axle.";let i=Qc("ride-height",e.axes?.h);if(i)return i;let c=Qc("pitch",e.axes?.pitch,"\xB0","pitch");if(c)return c;let l=e.axes.pitch.find(u=>Math.abs(u)>=qc);if(l!==void 0)return`A pitch of ${l}\xB0 is not a car's attitude \u2014 is the axis a rake in millimetres? Pitch is in degrees.`;[t,r,n,o]=[e.axes.h,e.axes.pitch,"ride heights","pitches"]}else return`Unknown aero map frame "${e.frame.kind}".`;let a=t.length,s=r.length;for(let i of qr){let c=e[i];if(!Array.isArray(c)||c.length!==s)return`${i} has ${Array.isArray(c)?c.length:0} rows against ${s} ${o} \u2014 they must match.`;for(let l=0;l<s;l++){let u=c[l];if(!Array.isArray(u)||u.length!==a)return`${i} row ${l+1} has ${Array.isArray(u)?u.length:0} values against ${a} ${n}.`;if(!u.every(Qe))return`${i} contains a value that is not a number.`}}return mx("yaw",e.attitude?.yaw)??mx("roll",e.attitude?.roll)}if(e.kind==="sensitivity"){let t;if(e.frame==null)t=["hFront","hRear"];else if(e.frame?.kind==="pitch"){if(!Qe(e.frame.refX))return"The point the ride height is read at must be a number of millimetres aft of the front axle.";t=["h","pitch"]}else return`Unknown aero sensitivity frame "${e.frame.kind}".`;let r=e.ref,n=e.slope,o=e.range,a=s=>s==="pitch"?"\xB0":" mm";if(!r||!Qe(r[t[0]])||!Qe(r[t[1]]))return e.frame?"The reference ride height and pitch must be numbers.":"The reference ride heights must be numbers.";for(let s of qr){if(!e.at||!Qe(e.at[s]))return`${s} at the reference must be a number.`;let i=n?.[s];if(!i||!Qe(i[t[0]])||!Qe(i[t[1]]))return`The slopes of ${s} must be numbers.`}for(let s of t){let i=o?.[s],c=r[s];if(!i||!Qe(i[0])||!Qe(i[1]))return`The ${s} range must be two numbers.`;if(!(i[1]>i[0]))return`The ${s} range must run from low to high (${i[0]} to ${i[1]}${a(s)}).`;if(c<i[0]||c>i[1])return`The reference ${s} of ${c}${a(s)} lies outside its range ${i[0]}\u2013${i[1]}${a(s)}.`;if(s==="pitch"&&(Math.abs(i[0])>=qc||Math.abs(i[1])>=qc))return`A pitch range reaching ${Math.abs(i[0])>=qc?i[0]:i[1]}\xB0 is not a car's attitude. Pitch is in degrees.`}return px("yaw",e.attitude?.yaw)??px("roll",e.attitude?.roll)}return`Unknown aero model kind "${e.kind}".`}var dx=180/Math.PI;function Oo(e,t,r,n){let o=(n-r)/t;return{h:r+e.refX*o,pitch:Math.atan(o)*dx}}function Vo(e,t,r,n){let o=Math.tan(n/dx);return{hFront:r-e.refX*o,hRear:r+(t-e.refX)*o}}var C$=180/Math.PI,oT=["hFront","hRear"],aT=["h","pitch"],id=e=>e?.kind==="pitch"?aT:oT,Mt=(e,t)=>e[t],Zc=(e,t)=>e[t],ad=(e,t)=>({[e[0]]:t(e[0]),[e[1]]:t(e[1])});function sT(e){if(!(!e.yaw&&!e.roll))return{...e.yaw?{yaw:{...e.yaw}}:{},...e.roll?{roll:{...e.roll}}:{}}}function cd(e){let t=id(e.frame),r=e.balanceFront,n=e.cl*r,o=e.cl*(1-r),a=ad(t,c=>Mt(e.dCl,c)*r+e.cl*Mt(e.dBalance,c)),s=ad(t,c=>Mt(e.dCl,c)*(1-r)-e.cl*Mt(e.dBalance,c)),i=sT(e);return{kind:"sensitivity",name:e.name,area:e.area,...e.frame?{frame:{...e.frame}}:{},ref:{...e.ref},at:{clFront:n,clRear:o,cd:e.cd},slope:{clFront:a,clRear:s,cd:ad(t,c=>Mt(e.dCd,c))},range:{[t[0]]:[...Zc(e.range,t[0])],[t[1]]:[...Zc(e.range,t[1])]},provenance:{...e.provenance},...i?{attitude:i}:{}}}function Jc(e,t,r){let n=Math.min(Math.abs(r),t.maxDeg),o=e.clFront+e.clRear,a=o!==0?e.clFront/o:.5,s=o+t.dCl*n,i=a+t.dBalance*n,c=e.clFront!==0?s*i/e.clFront:1,l=e.clRear!==0?s*(1-i)/e.clRear:1,u=e.cd!==0?(e.cd+t.dCd*n)/e.cd:1;return{clFront:c,clRear:l,cd:u}}function sd(e,t,r=11){let n=Array.from({length:r},(a,s)=>t.maxDeg*s/(r-1)),o=n.map(a=>Jc(e,t,a));return{clFront:{deg:[...n],factor:o.map(a=>a.clFront)},clRear:{deg:[...n],factor:o.map(a=>a.clRear)},cd:{deg:[...n],factor:o.map(a=>a.cd)}}}function fx(e){if(!(!e.attitude?.yaw&&!e.attitude?.roll))return{...e.attitude.yaw?{yaw:sd(e.at,e.attitude.yaw)}:{},...e.attitude.roll?{roll:sd(e.at,e.attitude.roll)}:{}}}function hx(e,t,r,n=0,o=0){let[a,s]=id(e.frame),i=t-Mt(e.ref,a),c=r-Mt(e.ref,s),l={clFront:e.at.clFront+Mt(e.slope.clFront,a)*i+Mt(e.slope.clFront,s)*c,clRear:e.at.clRear+Mt(e.slope.clRear,a)*i+Mt(e.slope.clRear,s)*c,cd:e.at.cd+Mt(e.slope.cd,a)*i+Mt(e.slope.cd,s)*c},u=e.attitude?.yaw?Jc(e.at,e.attitude.yaw,n):{clFront:1,clRear:1,cd:1},m=e.attitude?.roll?Jc(e.at,e.attitude.roll,o):{clFront:1,clRear:1,cd:1};return{clFront:l.clFront*u.clFront*m.clFront,clRear:l.clRear*u.clRear*m.clRear,cd:l.cd*u.cd*m.cd}}function ld(e){let[t,r]=id(e.frame),n=[...Zc(e.range,t)],o=[...Zc(e.range,r)],a=i=>o.map(c=>n.map(l=>i(hx(e,l,c)))),s=fx(e);return{kind:"map",name:e.name,area:e.area,...e.frame?{frame:{...e.frame}}:{},axes:{[t]:n,[r]:o},clFront:a(i=>i.clFront),clRear:a(i=>i.clRear),cd:a(i=>i.cd),provenance:{...e.provenance},...s?{attitude:s}:{}}}var ud=180/Math.PI,bx=new WeakMap,gx=new WeakMap,md=new WeakMap;function Zr(e,t){let r=gx.get(e);if(r)return r;let n=t?.wheelbase,o=n!==void 0?md.get(e)?.get(n):void 0;if(o)return o;let a=iT(e),s=a.map;if(!Qr(s)){let l=cT(e,a);return gx.set(e,l),l}if(n===void 0||!Number.isFinite(n)||n<=0)throw new Error("A ride-height-and-pitch aero map is read with the car\u2019s wheelbase, and none was given.");let i=lT(e,a,s.frame,n),c=md.get(e);return c||(c=new Map,md.set(e,c)),c.set(n,i),i}function iT(e){let t=bx.get(e);if(t)return t;let r=os(e);if(r)throw new Error(r);let n=e.kind==="map"?e:ld(e),{x:o,y:a}=No(n),s=o.length,i=a.length,c=n.attitude?.yaw,l=n.attitude?.roll,u=!!(c||l),m={clFront:1,clRear:1,cd:1,clamped:!1},f=(y,R)=>{let k=Math.abs(R),v=y.clFront.deg[y.clFront.deg.length-1];return{clFront:$e(y.clFront.deg,y.clFront.factor,k),clRear:$e(y.clRear.deg,y.clRear.factor,k),cd:$e(y.cd.deg,y.cd.factor,k),clamped:k>v}},p=(y,R)=>{if(!u)return m;let k=c?f(c,y):m,v=l?f(l,R):m;return{clFront:k.clFront*v.clFront,clRear:k.clRear*v.clRear,cd:k.cd*v.cd,clamped:k.clamped||v.clamped}},d=(y,R,k=0,v=0)=>{let x=Ln(o,y),M=Ln(a,R),F=Math.min(x.i+1,s-1),w=Math.min(M.i+1,i-1),C=S=>{let A=S[M.i][x.i],P=S[M.i][F],L=S[w][x.i],D=S[w][F],E=A+x.t*(P-A),V=L+x.t*(D-L);return E+M.t*(V-E)},T=p(k,v);return{clFront:u?C(n.clFront)*T.clFront:C(n.clFront),clRear:u?C(n.clRear)*T.clRear:C(n.clRear),cd:u?C(n.cd)*T.cd:C(n.cd),clampedRide:x.clamped||M.clamped,clampedAttitude:T.clamped}},h={x:[o[0],o[s-1]],y:[a[0],a[i-1]]},b=(y,R,k=!1,v=0,x=0)=>{let M=p(v,x),F=Ln(o,k?Math.min(Math.max(y,h.x[0]),h.x[1]):y),w=Ln(a,k?Math.min(Math.max(R,h.y[0]),h.y[1]):R),C=Math.min(F.i+1,s-1),T=Math.min(w.i+1,i-1),S=C>F.i?o[C]-o[F.i]:0,A=T>w.i?a[T]-a[w.i]:0,P={};for(let L of qr){let D=n[L],E=D[w.i][F.i],V=D[w.i][C],N=D[T][F.i],z=D[T][C],I=F.clamped||S===0?0:((V-E)*(1-w.t)+(z-N)*w.t)/S,_=w.clamped||A===0?0:((N-E)*(1-F.t)+(z-V)*F.t)/A;P[L]=u?{x:I*M[L],y:_*M[L]}:{x:I,y:_}}return P},g={map:n,x:h.x,y:h.y,hasAttitude:u,factors:p,at:d,slopes:b};return bx.set(e,g),g}function cT(e,t){let r={x:t.x,y:t.y,at:t.at,toAxles:(o,a)=>({hFront:o,hRear:a}),fromAxles:(o,a)=>({x:o,y:a})},n=(o,a,s=!1,i=0,c=0)=>{let l=t.slopes(o,a,s,i,c),u={};for(let m of qr)u[m]={hFront:l[m].x,hRear:l[m].y};return u};return{model:e,map:t.map,area:t.map.area,grid:r,hasAttitude:t.hasAttitude,at:t.at,slopes:n,factors:t.factors}}function lT(e,t,r,n){let o=r.refX,a=o/n,s=(l,u,m=0,f=0)=>{let p=(u-l)/n;return t.at(l+o*p,Math.atan(p)*ud,m,f)},i=(l,u,m=!1,f=0,p=0)=>{let d=(u-l)/n,h=t.slopes(l+o*d,Math.atan(d)*ud,m,f,p),b=ud/(n*(1+d*d)),g={};for(let y of qr)g[y]={hFront:h[y].x*(1-a)-h[y].y*b,hRear:h[y].x*a+h[y].y*b};return g},c={frame:r,x:t.x,y:t.y,at:t.at,toAxles:(l,u)=>Vo(r,n,l,u),fromAxles:(l,u)=>{let m=Oo(r,n,l,u);return{x:m.h,y:m.pitch}}};return{model:e,map:t.map,area:t.map.area,grid:c,hasAttitude:t.hasAttitude,at:s,slopes:i,factors:t.factors}}function pd(e){let t=e.clFront+e.clRear;return{cl:t,balanceFront:t!==0?e.clFront/t:.5}}var he=(e,t)=>e*t/100,qe=e=>e/100,yx={name:"Formula Student aero",area:1,cl:3,balanceFront:.45,cd:1.3,ref:{hFront:30,hRear:35},range:{hFront:[5,60],hRear:[10,70]},dCl:{hFront:he(3,-.4),hRear:he(3,.1)},dBalance:{hFront:qe(-.3),hRear:qe(.15)},dCd:{hFront:he(1.3,-.1),hRear:he(1.3,.05)},yaw:{dCl:he(3,-1),dBalance:qe(-.3),dCd:he(1.3,.5),maxDeg:10},roll:{dCl:he(3,-.5),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for an undertray-and-wings Formula Student car, ride height, yaw and roll; not measured."},xx={name:"Formula 1 aero",area:1.5,cl:3,balanceFront:.44,cd:.9,ref:{hFront:35,hRear:70},range:{hFront:[0,60],hRear:[20,100]},dCl:{hFront:he(3,-.3),hRear:he(3,-.15)},dBalance:{hFront:qe(-.15),hRear:qe(.15)},dCd:{hFront:he(.9,-.15),hRear:he(.9,-.05)},yaw:{dCl:he(3,-1.5),dBalance:qe(.2),dCd:he(.9,.8),maxDeg:8},roll:{dCl:he(3,-1),dBalance:qe(-.3),dCd:0,maxDeg:2},note:"Assumed class-level sensitivities for a ground-effect floor, ride height, yaw and roll; not measured."},Rx={name:"GT car aero",area:2,cl:1.4,balanceFront:.42,cd:.42,ref:{hFront:55,hRear:75},range:{hFront:[10,90],hRear:[10,110]},dCl:{hFront:he(1.4,-.3),hRear:he(1.4,.05)},dBalance:{hFront:qe(-.25),hRear:qe(.15)},dCd:{hFront:he(.42,-.1),hRear:0},yaw:{dCl:he(1.4,-.8),dBalance:qe(-.2),dCd:he(.42,.6),maxDeg:10},roll:{dCl:he(1.4,-.3),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a splitter-and-wing GT car, ride height, yaw and roll; not measured."},vx={name:"Sports car aero",area:2.2,cl:-.1,balanceFront:.5,cd:.3,ref:{hFront:130,hRear:140},range:{hFront:[80,180],hRear:[100,200]},dCl:{hFront:-5e-4,hRear:0},dBalance:{hFront:0,hRear:0},dCd:{hFront:2e-4,hRear:0},yaw:{dCl:0,dBalance:0,dCd:he(.3,.5),maxDeg:10},note:"Assumed class-level sensitivities for a road car with no aero devices; not measured."},kx={name:"Cup car aero",area:2.1,cl:.45,balanceFront:.45,cd:.4,ref:{hFront:64,hRear:78},range:{hFront:[20,100],hRear:[30,120]},dCl:{hFront:he(.45,-.4),hRear:he(.45,.05)},dBalance:{hFront:qe(-.25),hRear:qe(.15)},dCd:{hFront:he(.4,-.1),hRear:0},yaw:{dCl:he(.45,-1.2),dBalance:qe(-.2),dCd:he(.4,.6),maxDeg:10},roll:{dCl:he(.45,-.3),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a splitter-and-wing cup hatchback, ride height, yaw and roll; not measured."},Mx={name:"Stock car aero",area:2.2,cl:.6,balanceFront:.45,cd:.45,ref:{hFront:75,hRear:90},range:{hFront:[20,110],hRear:[30,130]},dCl:{hFront:he(.6,-.35),hRear:he(.6,.05)},dBalance:{hFront:qe(-.25),hRear:qe(.15)},dCd:{hFront:he(.45,-.1),hRear:0},yaw:{dCl:he(.6,-1),dBalance:qe(-.2),dCd:he(.45,.6),maxDeg:10},roll:{dCl:he(.6,-.3),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a splitter-and-spoiler stock car, ride height, yaw and roll; not measured."},Sx={name:"Hill-climb prototype aero",area:1.2,cl:2.5,balanceFront:.42,cd:.9,ref:{hFront:45,hRear:55},range:{hFront:[10,80],hRear:[15,95]},dCl:{hFront:he(2.5,-.35),hRear:he(2.5,.05)},dBalance:{hFront:qe(-.25),hRear:qe(.15)},dCd:{hFront:he(.9,-.1),hRear:he(.9,.05)},yaw:{dCl:he(2.5,-1),dBalance:qe(-.3),dCd:he(.9,.5),maxDeg:10},roll:{dCl:he(2.5,-.5),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a winged sports prototype with a flat floor and diffuser, ride height, yaw and roll; not measured."},Ax={name:"Race truck aero",area:6.2,cl:-.1,balanceFront:.6,cd:.65,ref:{hFront:110,hRear:240},range:{hFront:[60,160],hRear:[180,300]},dCl:{hFront:-5e-4,hRear:0},dBalance:{hFront:0,hRear:0},dCd:{hFront:2e-4,hRear:0},yaw:{dCl:0,dBalance:0,dCd:he(.65,.5),maxDeg:10},note:"Assumed class-level sensitivities for a cab-over race truck with a chin spoiler and deflectors, ride height and yaw; not measured."};function Rr(e){return cd({name:e.name,area:e.area,cl:e.cl,balanceFront:e.balanceFront,cd:e.cd,ref:e.ref,range:e.range,dCl:e.dCl,dBalance:e.dBalance,dCd:e.dCd,...e.yaw?{yaw:e.yaw}:{},...e.roll?{roll:e.roll}:{},provenance:{source:"assumed",note:e.note}})}var dd=()=>Rr(yx),fd=()=>Rr(xx),hd=()=>Rr(Rx),bd=()=>Rr(vx),gd=()=>Rr(kx),yd=()=>Rr(Mx),xd=()=>Rr(Sx),Rd=()=>Rr(Ax);function Dn(e,t){let r=.5*e.rho*e.area*t*t,n=e.cl*r,o=e.cw*r,a=n*e.copLongFront;return{downforce:n,drag:o,downFront:a,downRear:n-a}}function el(e,t){let r=e.massTotal;if(!(r>0))return{front:0,rear:0};let n=Math.max(0,Math.min(1,e.frontMassFrac)),o=2*e.unsprungPerCorner,a=(s,i)=>i>0?Math.min(1,s/i):0;return{front:(t.sprungMass*n+o*a(t.rideRateFront,Xe(e,"front")))/r,rear:(t.sprungMass*(1-n)+o*a(t.rideRateRear,Xe(e,"rear")))/r}}function tl(e,t,r,n){let o=t.front*r+t.rear*n;return o===0?e:Math.max(Math.min(1,e),e-o)}function vd(e,t){return e.wheelbase>0?e.massTotal*t*9.81/e.wheelbase:0}function Bo(e,t,r){let n=2*t.rideRateFront,o=2*t.rideRateRear;return!(n>0)||!(o>0)?0:Math.min(od(t.sprungMass,r,e.wheelbase),.5*n*o/(n+o))}function as(e,t,r,n,o){let a=e.cgHeight,s=vd(e,r);if(n===0&&o===0&&s===0)return{height:a,forward:0,noseLoad:0,dropFront:0,dropRear:0};let i=el(e,t),c=2*t.rideRateFront,l=2*t.rideRateRear,u=a,m=0,f=0,p=0;for(let h=0;h<6;h++){p=Bo(e,t,u);let b=n-s*u,g=o+s*u;if(p>0){let k=c*l-p*(c+l);m=(b*(l-p)-p*g)/k,f=(g*(c-p)-p*b)/k}else m=c>0?b/c:0,f=l>0?g/l:0;let y=tl(a,i,m,f),R=Math.abs(y-u);if(u=y,R<1e-9)break}let d=m-f;return{height:u,forward:e.wheelbase>0?u*d/e.wheelbase:0,noseLoad:p*d,dropFront:m,dropRear:f}}var kd={yawDeg:0,rollDeg:0},Fx=1e-4,uT=40,wx=50;function Jr(e,t,r=0){let n=e.aero?.model;if(!(!n||!Zr(n,e).hasAttitude))return{yawDeg:r,rollDeg:we(e).rollGradient*t}}function $o(e,t){if(e.rideHeightFront!=null&&e.rideHeightRear!=null)return{hFront:e.rideHeightFront,hRear:e.rideHeightRear};let r=e.model,n=(a,s,i)=>{if(t!==void 0&&t>0)return Vo(a,t,s,i);throw new Error("A ride-height-and-pitch aero model is read with the car\u2019s wheelbase, and none was given.")},o={hFront:0,hRear:0};if(r?.kind==="sensitivity")o=Xc(r)?n(r.frame,r.ref.h,r.ref.pitch):r.ref;else if(r){let{x:a,y:s}=No(r),i=(a[0]+a[a.length-1])/2,c=(s[0]+s[s.length-1])/2;o=Qr(r)?n(r.frame,i,c):{hFront:i,hRear:c}}return{hFront:e.rideHeightFront??o.hFront,hRear:e.rideHeightRear??o.hRear}}var Cx=new WeakMap;function vr(e,t,r=0,n){let o=e.aero;if(!o?.model)return null;let a=Cx.get(e);a||(a=new Map,Cx.set(e,a));let s=n&&Zr(o.model,e).hasAttitude?n:kd,i=s===kd?`${t}|${r}`:`${t}|${r}|${s.yawDeg.toFixed(3)}|${s.rollDeg.toFixed(3)}`,c=a.get(i);if(c)return c;let l=mT(e,o,t,r,s);return a.size>4096&&a.clear(),a.set(i,l),l}function mT(e,t,r,n,o){let a=Zr(t.model,e),s=we(e),i=2*s.rideRateFront,c=2*s.rideRateRear,l=$o(t,e.wheelbase),u=.5*t.rho*r*r,m=a.area,f=e.wheelbase>0?t.copHeight/e.wheelbase:0,p=el(e,s),d=vd(e,n),h=(C,T)=>tl(e.cgHeight,p,l.hFront-C,l.hRear-T),b=(C,T)=>l.hFront-C-(l.hRear-T),g=(C,T)=>{let S=a.at(C,T,o.yawDeg,o.rollDeg),A=u*m*S.clFront,P=u*m*S.clRear,L=u*m*S.cd,D=L*f,E=h(C,T),V=d*E,N=Bo(e,s,E)*b(C,T),z=A-V-D+N,I=P+V+D-N,_=C-l.hFront+(i>0?z/i:0),B=T-l.hRear+(c>0?I/c:0);return{c:S,downFront:A,downRear:P,drag:L,rF:_,rR:B,norm:Math.hypot(_,B)}},y=(C,T,S=!1)=>{let A=a.slopes(C,T,S,o.yawDeg,o.rollDeg),P=i>0?u*m/i:0,L=c>0?u*m/c:0;return[[P*(A.clFront.hFront-f*A.cd.hFront),P*(A.clFront.hRear-f*A.cd.hRear)],[L*(A.clRear.hFront+f*A.cd.hFront),L*(A.clRear.hRear+f*A.cd.hRear)]]},R=l.hFront,k=l.hRear,v=g(R,k),x=0;for(;v.norm>=Fx&&x<uT;){x++;let C=y(R,k),T=i>0?d/i:0,S=c>0?d/c:0,A=Bo(e,s,h(R,k)),P=i>0?A/i:0,L=c>0?A/c:0,D=1+C[0][0]-T*p.front-P,E=C[0][1]-T*p.rear+P,V=C[1][0]+S*p.front+L,N=1+C[1][1]+S*p.rear-L,z=D*N-E*V,I,_;Math.abs(z)>1e-9?(I=-(N*v.rF-E*v.rR)/z,_=-(-V*v.rF+D*v.rR)/z):(I=-.5*v.rF,_=-.5*v.rR);let B=Math.max(1,Math.abs(I)/wx,Math.abs(_)/wx);I/=B,_/=B;let O=1;for(let G=0;G<6;G++){let K=g(R+O*I,k+O*_);if(K.norm<=v.norm||G===5){R+=O*I,k+=O*_,v=K;break}O*=.5}}let M=y(R,k,!0),F=2+M[0][0]+M[1][1],w=(1+M[0][0])*(1+M[1][1])-M[0][1]*M[1][0];return{v:r,axG:n,hFront:R,hRear:k,cgHeight:h(R,k),cgForward:e.wheelbase>0?h(R,k)*b(R,k)/e.wheelbase:0,cgNoseLoad:Bo(e,s,h(R,k))*b(R,k),clFront:v.c.clFront,clRear:v.c.clRear,cd:v.c.cd,area:m,downforce:v.downFront+v.downRear,drag:v.drag,downFront:v.downFront,downRear:v.downRear,gain:pT(M),stable:w>0&&F>0,converged:v.norm<Fx,iterations:x,clampedRide:v.c.clampedRide,yawDeg:o.yawDeg,rollDeg:o.rollDeg,clampedAttitude:v.c.clampedAttitude}}function pT(e){let t=e[0][0]+e[1][1],r=e[0][0]*e[1][1]-e[0][1]*e[1][0],n=t*t-4*r;if(n>=0){let o=Math.sqrt(n);return Math.max(Math.abs((t+o)/2),Math.abs((t-o)/2))}return Math.sqrt(r)}function ss(e,t,r=0,n){let o=vr(e,t,r,n);return o?{downforce:o.downforce,drag:o.drag,downFront:o.downFront,downRear:o.downRear}:e.aero?Dn(e.aero,t):{downforce:0,drag:0,downFront:0,downRear:0}}function dT(e,t,r,n){let o=Dn(t,r),a=we(e),s=$o(t,e.wheelbase),i=e.wheelbase>0?o.drag*t.copHeight/e.wheelbase:0,c=as(e,a,n,o.downFront-i,o.downRear+i),l=o.downforce;return{v:r,axG:n,hFront:s.hFront-c.dropFront,hRear:s.hRear-c.dropRear,cgHeight:c.height,cgForward:c.forward,cgNoseLoad:c.noseLoad,clFront:t.cl*t.copLongFront,clRear:t.cl*(1-t.copLongFront),cd:t.cw,area:t.area,downforce:l,drag:o.drag,downFront:o.downFront,downRear:o.downRear,gain:0,stable:!0,converged:!0,iterations:0,clampedRide:!1,yawDeg:0,rollDeg:0,clampedAttitude:!1}}function Md(e,t,r=0,n){let o=vr(e,t,r,n);return o||(e.aero?dT(e,e.aero,t,r):null)}function rl(e,t=0,r=0,n,o){if(e.aero&&t>0){if(e.aero.model){let i=vr(e,t,r,n);return{height:i.cgHeight,forward:i.cgForward,noseLoad:i.cgNoseLoad}}let a=Dn(e.aero,t),s=e.wheelbase>0?a.drag*e.aero.copHeight/e.wheelbase:0;return as(e,o??we(e),r,a.downFront-s,a.downRear+s)}return r===0?{height:e.cgHeight,forward:0,noseLoad:0}:as(e,o??we(e),r,0,0)}var Tx=[0,1,0],Sd=[0,0,1],ee=(e,t)=>[e[0]+t[0],e[1]+t[1],e[2]+t[2]],H=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],U=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],Ad=e=>[-e[0],-e[1],-e[2]],X=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],ae=(e,t)=>[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]],fT=e=>X(e,e),en=e=>Math.sqrt(X(e,e)),is=(e,t)=>fT(H(e,t)),ve=(e,t)=>en(H(e,t)),q=e=>{let t=en(e);return t<1e-12?[0,0,0]:[e[0]/t,e[1]/t,e[2]/t]};var tn=(e,t,r)=>{let n=q(r),o=H(e,t);return ee(t,U(n,X(o,n)))},Px=(e,t,r)=>ve(e,tn(e,t,r));var bT=1e-6;function gT(e){if(e<bT){let n=e*e;return[1-n/6,.5-n/24]}let t=Math.sin(e),r=Math.cos(e);return[t/e,(1-r)/(e*e)]}function ot(e,t){let r=Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]);if(r<1e-14)return t;let[n,o]=gT(r),a=ae(e,t),s=ae(e,a);return ee(t,ee(U(a,n),U(s,o)))}function It(e,t,r){let n=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);if(n<1e-14)return e;let o=[t[0]/n,t[1]/n,t[2]/n];return ot(U(o,r),e)}function Jt(e,t){let r=t.length,n=e.map(a=>a.slice()),o=t.slice();return Dx(n,o,r,new Array(r).fill(0))}function Lx(e,t,r){return Dx(e,t,t.length,r)}function Dx(e,t,r,n){let o=1/0,a=0;for(let s=0;s<r;s++){let i=s,c=Math.abs(e[s][s]);for(let u=s+1;u<r;u++){let m=Math.abs(e[u][s]);m>c&&(c=m,i=u)}if(c<1e-14){for(let u=0;u<r;u++)n[u]=NaN;return{x:n,condProxy:1/0,singular:!0}}if(o=Math.min(o,c),a=Math.max(a,c),i!==s){let u=e[s];e[s]=e[i],e[i]=u;let m=t[s];t[s]=t[i],t[i]=m}let l=e[s][s];for(let u=s+1;u<r;u++){let m=e[u][s]/l;if(m!==0){for(let f=s;f<r;f++)e[u][f]-=m*e[s][f];t[u]-=m*t[s]}}}for(let s=r-1;s>=0;s--){let i=t[s];for(let c=s+1;c<r;c++)i-=e[s][c]*n[c];n[s]=i/e[s][s]}return{x:n,condProxy:a/o,singular:!1}}var Ex=e=>{let t=0;for(let r of e)t=Math.max(t,Math.abs(r));return t},Ix=e=>{let t=0;for(let r of e)t+=r*r;return t},yT=Math.sqrt(Number.EPSILON);function _x(e,t,r={}){let n=r.maxIter??60,o=r.tol??1e-10,a=t.length,s=r.scales??new Array(a).fill(1),i=t.slice(),c=e(i),l=Ex(c),u=Ix(c),m=.001,f=1,p=c.length,d=Array.from({length:p},()=>new Array(a).fill(0)),h=Array.from({length:a},()=>new Array(a).fill(0)),b=Array.from({length:a},()=>new Array(a).fill(0)),g=new Array(a).fill(0),y=new Array(a).fill(0),R=new Array(a).fill(0),k=new Array(a).fill(0),v=new Array(a).fill(0);for(let x=0;x<n;x++){if(l<o)return{x:i,residualNorm:l,iterations:x,converged:!0,condProxy:f};for(let C=0;C<a;C++){let T=yT*Math.max(Math.abs(i[C]),s[C]);for(let A=0;A<a;A++)k[A]=i[A];k[C]+=T;let S=e(k);for(let A=0;A<p;A++)d[A][C]=(S[A]-c[A])/T}let M=0;for(let C=0;C<a;C++){for(let S=0;S<a;S++){let A=0;for(let P=0;P<p;P++)A+=d[P][C]*d[P][S];h[C][S]=A}let T=0;for(let S=0;S<p;S++)T+=d[S][C]*c[S];g[C]=T,M=Math.max(M,h[C][C])}let F=Math.max(M,1e-9),w=!1;for(let C=0;C<18;C++){let T=m*F;for(let A=0;A<a;A++){let P=h[A],L=b[A];for(let D=0;D<a;D++)L[D]=A===D?P[D]+T:P[D];y[A]=-g[A]}let S=Lx(b,y,R);if(f=Math.max(f,S.condProxy),!S.singular){for(let L=0;L<a;L++)v[L]=i[L]+R[L];let A=e(v),P=Ix(A);if(P<u){for(let L=0;L<a;L++)i[L]=v[L];c=A,u=P,l=Ex(c),m=Math.max(m*.3,1e-12),w=!0;break}}m=Math.min(m*4,1e12)}if(!w)break}return{x:i,residualNorm:l,iterations:n,converged:l<o,condProxy:f}}function cs(e,t,r,n){let o=e*e+t*t,a=Math.sqrt(o);if(!(a>1e-12*n))return{c1:1,s1:0,c2:1,s2:0,margin:0,ok:!1,free:!0};let s=Math.abs(r),i=1-s/a;if(i<0){let l=r>=0?1:-1,u=l*e/a,m=l*t/a;return{c1:u,s1:m,c2:u,s2:m,margin:i,ok:i>=-1e-12,free:!1}}let c=Math.sqrt((a-s)*(a+s));return{c1:(e*r-t*c)/o,s1:(t*r+e*c)/o,c2:(e*r+t*c)/o,s2:(t*r-e*c)/o,margin:i,ok:!0,free:!1}}function Fd(e,t){return[e[0]*t[0]-e[1]*t[1]-e[2]*t[2]-e[3]*t[3],e[0]*t[1]+e[1]*t[0]+e[2]*t[3]-e[3]*t[2],e[0]*t[2]-e[1]*t[3]+e[2]*t[0]+e[3]*t[1],e[0]*t[3]+e[1]*t[2]-e[2]*t[1]+e[3]*t[0]]}var Nx=e=>[e[0],-e[1],-e[2],-e[3]];function Ox(e,t){let[r,n,o,a]=e,s=2*(o*t[2]-a*t[1]),i=2*(a*t[0]-n*t[2]),c=2*(n*t[1]-o*t[0]);return[t[0]+r*s+(o*c-a*i),t[1]+r*i+(a*s-n*c),t[2]+r*c+(n*i-o*s)]}function Vx(e,t){let r=e[0]*t[0]+e[1]*t[1]+e[2]*t[2];if(1+r<1e-14){let o=Math.abs(e[0])<.6?[1,0,0]:[0,1,0],a=e[1]*o[2]-e[2]*o[1],s=e[2]*o[0]-e[0]*o[2],i=e[0]*o[1]-e[1]*o[0],c=Math.hypot(a,s,i);return[0,a/c,s/c,i/c]}let n=Math.sqrt(2*(1+r));return[(1+r)/n,(e[1]*t[2]-e[2]*t[1])/n,(e[2]*t[0]-e[0]*t[2])/n,(e[0]*t[1]-e[1]*t[0])/n]}function Bx(e,t,r){let n,o;return t>=0?(n=Math.sqrt((1+t)/2),o=r/(2*n)):(o=(r>=0?1:-1)*Math.sqrt((1-t)/2),n=r/(2*o)),[n,o*e[0],o*e[1],o*e[2]]}function wd(e,t,r){let n=e[0],o=e[1],a=e[2],s=t[0],i=t[1],c=t[2],l=r[0],u=r[1],m=r[2],f=n+i+m;if(f>=n&&f>=i&&f>=m){let h=Math.sqrt(1+f),b=.5/h;return[.5*h,(c-u)*b,(l-a)*b,(o-s)*b]}if(n>=i&&n>=m){let h=Math.sqrt(1+n-i-m),b=.5/h;return[(c-u)*b,.5*h,(s+o)*b,(l+a)*b]}if(i>=m){let h=Math.sqrt(1-n+i-m),b=.5/h;return[(l-a)*b,(s+o)*b,.5*h,(u+c)*b]}let p=Math.sqrt(1-n-i+m),d=.5/p;return[(o-s)*d,(l+a)*d,(u+c)*d,.5*p]}function $x(e){let t=Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]);if(t===0)return[1,0,0,0];let r=Math.sin(t/2)/t;return[Math.cos(t/2),r*e[0],r*e[1],r*e[2]]}function Gx(e){let[t,r,n,o]=e;t<0&&(t=-t,r=-r,n=-n,o=-o);let a=Math.sqrt(r*r+n*n+o*o);if(a===0)return[0,0,0];let s=2*Math.atan2(a,t)/a;return[s*r,s*n,s*o]}function xT(e){let t=Math.abs(e[0])<.6?[1,0,0]:[0,1,0],r=q(ae(e,t));return[r,ae(e,r)]}function RT(e){let t=e.hardpoints,r=q(H(t.damperChassis,t.pushrodOuter)),[n,o]=xT(r);return{top:t.damperChassis,lower0:t.pushrodOuter,axis0:r,e1:n,e2:o}}function Cd(e){let t=e.hardpoints,r=t.wheelCenter,n=q(H(t.ucaRear,t.ucaFront)),o=H(t.uprightUpper,t.ucaFront),a=X(o,n),s=H(o,U(n,a)),i=X(s,s),c=q(H(t.lcaRear,t.lcaFront)),l=H(t.uprightLower,t.lcaFront),u=is(t.tieOuter,t.tieInner);return{c0:r,ucaFront:t.ucaFront,ucaDir:n,ubj0:t.uprightUpper,ubjAxial0:a,ubjRadius2:i,lcaFront:t.lcaFront,lcaDir:c,lbj0:t.uprightLower,lbjRel0:l,tro0:t.tieOuter,tieInner0:t.tieInner,tieLen2:u,rackAxis:q(e.config.rackAxis),steerMovesRack:e.config.steerMode==="rack",ubjRadiusRef:Math.max(1,2*Math.sqrt(i)),tieLenRef:Math.max(1,2*Math.sqrt(u)),...e.config.layout==="mcpherson"?{strut:RT(e)}:{}}}function _t(e,t,r){let n=[t[3],t[4],t[5]],o=[t[0],t[1],t[2]],a=H(r,e.c0);return ee(ee(ot(n,a),e.c0),o)}function Td(e,t){return ee(e.lcaFront,It(e.lbjRel0,e.lcaDir,t))}function Go(e,t){return e.steerMovesRack?ee(e.tieInner0,U(e.rackAxis,t)):e.tieInner0}function Pd(e,t,r,n){let o=_t(e,t,e.lbj0),a=Td(e,r),s=o[0]-a[0],i=o[1]-a[1],c=o[2]-a[2],l,u;if(e.strut){let d=e.strut,h=[t[3],t[4],t[5]],b=H(d.top,_t(e,t,d.lower0));l=X(b,ot(h,d.e1)),u=X(b,ot(h,d.e2))}else{let d=_t(e,t,e.ubj0),h=H(d,e.ucaFront),b=X(h,e.ucaDir),g=H(h,U(e.ucaDir,b));l=b-e.ubjAxial0,u=(X(g,g)-e.ubjRadius2)/e.ubjRadiusRef}let m=_t(e,t,e.tro0),f=Go(e,n),p=(is(m,f)-e.tieLen2)/e.tieLenRef;return[s,i,c,l,u,p]}var ls=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]),nl=e=>{let t=ls(e);return[e[0]/t,e[1]/t,e[2]/t]},vT=(e,t)=>H(e,U(t,X(e,t))),Ld=e=>nl(ae(e,Math.abs(e[0])<.6?[1,0,0]:[0,1,0]));function kT(e,t){let r=e.ucaDir,n=ee(e.ucaFront,U(r,e.ubjAxial0)),o=Math.sqrt(e.ubjRadius2),a=vT(H(e.ubj0,e.ucaFront),r),s=ls(a)>1e-9?nl(a):Ld(r),i=ae(r,s),c=H(e.ubj0,e.lbj0),l=X(c,c);if(!(l>1e-18))return"free";let u=H(n,t),m=X(u,u),f=cs(2*o*X(s,u),2*o*X(i,u),l-m-o*o,2*o*Math.sqrt(m));if(f.free)return"free";let p=nl(c),d=(h,b)=>{let g=ee(n,ee(U(s,o*h),U(i,o*b))),y=nl(H(g,t));return{q1:Vx(p,y),k:y,margin:f.margin,ok:f.ok}};return f.margin>0?[d(f.c1,f.s1),d(f.c2,f.s2)]:[d(f.c1,f.s1)]}function MT(e,t,r){let n=t.axis0,o=ee(t.lower0,U(n,X(H(e.lbj0,t.lower0),n))),a=H(o,e.lbj0),s=ls(a),i=s>1e-9?U(a,1/s):Ld(n),c=H(t.top,r),l=ls(c);if(!(l>1e-9))return"free";let u=U(c,1/l),m=s/l,f=1-m,p=f>=0?Math.sqrt((1-m)*(1+m)):0,d=Ld(u),h=b=>{let g=b*p,y=ee(U(u,g),U(d,Math.min(m,1))),R=H(U(u,Math.min(m,1)),U(d,g));return{q1:Fd(wd(R,y,ae(R,y)),Nx(wd(i,n,ae(i,n)))),k:u,margin:f,ok:f>=0}};return f>0?[h(1),h(-1)]:[h(1)]}function ST(e,t,r,n){let{k:o}=n,a=Ox(n.q1,H(e.tro0,e.lbj0)),s=X(a,o),i=H(a,U(o,s)),c=ls(i);if(!(c>1e-9))return"free";let l=U(i,1/c),u=ae(o,l),m=ee(t,U(o,s)),f=H(m,r),p=X(f,f),d=cs(2*c*X(f,l),2*c*X(f,u),e.tieLen2-p-c*c,2*c*Math.sqrt(p));if(d.free)return"free";let h=(g,y)=>({q:Fd(Bx(o,g,y),n.q1)});return{roots:d.margin>0?[h(d.c1,d.s1),h(d.c2,d.s2)]:[h(d.c1,d.s1)],margin:d.margin,ok:d.ok}}function Kx(e,t,r,n=[0,0,0,0,0,0]){let o=Td(e,t),a=Go(e,r),s=$x([n[3],n[4],n[5]]),i=h=>Math.abs(h[0]*s[0]+h[1]*s[1]+h[2]*s[2]+h[3]*s[3]),c=e.strut?MT(e,e.strut,o):kT(e,o);if(c==="free")return{x:n.slice(),converged:!1,margin:0,free:!0};let l=null,u=null;for(let h of c){let b=ST(e,o,a,h);if(b==="free")return{x:n.slice(),converged:!1,margin:0,free:!0};let g=Math.min(h.margin,b.margin),y=b.ok&&h.ok;for(let{q:R}of b.roots){let k=i(R);y&&(!l||k>l.near)&&(l={q:R,margin:g,near:k}),!y&&(!u||k>u.near)&&(u={q:R,margin:g,near:k})}}let{q:m,margin:f}=l??u,p=Gx(m),d=H(H(o,e.c0),ot(p,H(e.lbj0,e.c0)));return{x:[d[0],d[1],d[2],p[0],p[1],p[2]],converged:l!==null,margin:f,free:!1}}function zx(e){let t=q(H(e.rockerPivotB,e.rockerPivotA));return{pivotA:e.rockerPivotA,axis:t,rprRel0:H(e.rockerToPushrod,e.rockerPivotA),rdmRel0:H(e.rockerToDamper,e.rockerPivotA),damperChassis:e.damperChassis,rodLen2:is(e.pushrodOuter,e.rockerToPushrod),damperLen0:ve(e.rockerToDamper,e.damperChassis)}}var AT=(e,t)=>ee(e.pivotA,It(e.rprRel0,e.axis,t)),Dd=(e,t)=>ee(e.pivotA,It(e.rdmRel0,e.axis,t));function us(e,t){return{pushrod:AT(e,t),damper:Dd(e,t)}}function Yx(e,t,r=0){let n=X(e.rprRel0,e.axis),o=H(e.rprRel0,U(e.axis,n)),a=ae(e.axis,o),s=H(ee(e.pivotA,U(e.axis,n)),t),i=X(o,o),c=X(s,s),l=cs(2*X(s,o),2*X(s,a),e.rodLen2-c-i,2*Math.sqrt(i*c));if(l.free){let p=Math.abs(e.rodLen2-c-i)<=1e-9*e.rodLen2;return{phi:r,damperLength:ve(Dd(e,r),e.damperChassis),converged:p,margin:0}}let u=Hx(Math.atan2(l.s1,l.c1),r),m=Hx(Math.atan2(l.s2,l.c2),r),f=Math.abs(m-r)<Math.abs(u-r)?m:u;return{phi:f,damperLength:ve(Dd(e,f),e.damperChassis),converged:l.ok,margin:l.margin}}function Hx(e,t){let r=2*Math.PI;return e+r*Math.round((t-e)/r)}function Wx(e,t,r,n){return ee(t,ot(U(q(r),n),H(e,t)))}function jx(e,t,r,n){let o=q(n),a=f=>{let p=H(f,r);return H(p,U(o,X(p,o)))},s=a(e),i=a(t),c=Math.hypot(s[0],s[1],s[2]),l=Math.hypot(i[0],i[1],i[2]);if(c<1e-9||l<1e-9)return 0;let u=Math.min(1,Math.max(-1,X(s,i)/(c*l))),m=X(ae(s,i),o)/(c*l);return Math.atan2(m,u)}function Ux(e,t,r,n){return ee(t,ot(U(q(r),n),H(e,t)))}var ol=180/Math.PI,FT=(e,t,r)=>Math.max(t,Math.min(r,e)),Xx=[NaN,NaN,NaN];function ms(e){let t=q(e.spinAxis),r=q(H(e.uprightUpper,e.uprightLower)),n=-Math.asin(FT(t[2],-1,1))*ol,o=Math.atan2(t[0],t[1])*ol,a=Math.atan2(-r[0],r[2])*ol,s=Math.atan2(-r[1],r[2])*ol,i=q(ee([0,0,-1],U(t,t[2]))),c=ee(e.wheelCenter,U(i,e.loadedRadius)),l=e.patchShift?[c[0]+e.patchShift.x,c[1]+e.patchShift.y,c[2]]:c,u=e.uprightLower,m=Math.abs(r[2])>1e-9,f=w=>ee(u,U(r,(w-u[2])/r[2])),p=m?f(l[2]):Xx,d=m?f(e.wheelCenter[2]):Xx,h=l[1]-p[1],b=p[0]-l[0],g=q(ae(t,[0,0,1])),y=ae([0,0,1],g),R=H(l,p),k=X(R,y),v=-X(R,g),x=e.wheelCenter[1]-d[1],M=d[0]-e.wheelCenter[0],F=Px(e.tieOuter,u,r);return{camber:n,toe:o,caster:a,kpi:s,scrubRadius:h,mechanicalTrail:b,scrubAtWheel:k,trailAtWheel:v,kingpinOffset:x,casterOffset:M,steeringArm:F,contactPatch:l,kingpinGround:p,kingpinAtHub:d}}function tt(e){return{corner:e,inv:Cd(e),rocker:zx(e.hardpoints)}}var wT=[20,20,20,.2,.2,.2];function Qx(e,t,r,n=[0,0,0,0,0,0]){let o=Kx(e,t,r,n);if(!o.free)return o;let a=CT(e,t,r,n);return{x:a.x,converged:a.converged,margin:0}}function CT(e,t,r,n=[0,0,0,0,0,0]){return _x(o=>Pd(e,o,t,r),n,{scales:wT,tol:1e-10,maxIter:40})}var TT=.01,al=1.2,ht=e=>e.ok?e.state:null,at=e=>e.ok?e.state:e.nearest;function ye(e,t,r,n,o){let a=0,s=Ie(e,a,r,n,o);if(Math.abs(s.travel-t)<1e-4)return qx(s,t,!1);let c=(Ie(e,.02,r,Ed(s),o).travel-s.travel)/.02;(!Number.isFinite(c)||Math.abs(c)<1e-6)&&(c=1);let l=f=>Math.max(-al,Math.min(al,f)),u=l((t-s.travel)/c),m=Ie(e,u,r,Ed(s),o);for(let f=0;f<12&&!(Math.abs(m.travel-t)<1e-4);f++){let p=m.travel-s.travel,d=Math.abs(p)<1e-9?u:u-(m.travel-t)*((u-a)/p);a=u,s=m,u=l(d),m=Ie(e,u,r,Ed(s),o)}return qx(m,t,Math.abs(u)===al)}function qx(e,t,r){let n=e.travel-t,o=Math.abs(n)<=TT,a=r&&!o;return e.converged&&o?{ok:!0,reached:!0,travelMiss:n,clamped:!1,state:e}:{ok:!1,why:e.converged?"unreached":"unconverged",reached:o,travelMiss:n,clamped:a,nearest:e}}function Ed(e){return{q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle}}function PT(e,t,r,n,o){switch(e){case"upright":return _t(t,r,o.pushrodOuter);case"upperArm":{let a=_t(t,r,t.ubj0),s=jx(t.ubj0,a,t.ucaFront,t.ucaDir);return Ux(o.pushrodOuter,t.ucaFront,t.ucaDir,s)}default:return Wx(o.pushrodOuter,t.lcaFront,t.lcaDir,n)}}function Ie(e,t,r,n,o){let{inv:a,corner:s}=e,i=n?.q??[0,0,0,0,0,0],c=Qx(a,t,r,i),l=c.x,u=[l[3],l[4],l[5]],m={t:[l[0],l[1],l[2]],omega:u},f=s.hardpoints,p=s.config,d=a.strut,h=d?d.top:_t(a,l,f.uprightUpper),b=_t(a,l,f.uprightLower),g=_t(a,l,f.tieOuter),y=_t(a,l,f.wheelCenter),R=q(ot(u,p.spinAxis)),k=PT(d?"upright":p.pushrodAttach,a,l,t,f),v=d?d.top:f.damperChassis,x=d||p.actuation==="direct"?{phi:0,damperLength:ve(k,v),converged:!0,margin:1}:Yx(e.rocker,k,n?.phi??0),M=ms({uprightUpper:h,uprightLower:b,wheelCenter:y,spinAxis:R,tieOuter:g,loadedRadius:o?.loadedRadius??p.loadedRadius,patchShift:o?.patchShift});return{pose:m,beta:t,travel:l[2],steer:r,points:{uprightUpper:h,uprightLower:b,tieOuter:g,wheelCenter:y,pushrodOuter:k,spinAxis:R,contactPatch:M.contactPatch,kingpinGround:M.kingpinGround,kingpinAtHub:M.kingpinAtHub,rockerAngle:x.phi,damperLength:x.damperLength},metrics:{camber:M.camber,toe:M.toe,caster:M.caster,kpi:M.kpi,scrubRadius:M.scrubRadius,mechanicalTrail:M.mechanicalTrail,scrubAtWheel:M.scrubAtWheel,trailAtWheel:M.trailAtWheel,kingpinOffset:M.kingpinOffset,casterOffset:M.casterOffset,steeringArm:M.steeringArm,damperLength:x.damperLength},converged:c.converged&&x.converged,margin:Math.min(c.margin,x.margin)}}var Ko=e=>e==="FL"||e==="FR"?"front":"rear",Jx=e=>e==="FL"||e==="RL"?"left":"right";function Ge(e,t){return e.corners?.[t]??LT(e[Ko(t)],Jx(t))}function eR(e){let t=e.config.springSplit;return e.config.actuation==="decoupled"||t===void 0||!Number.isFinite(t)||Math.abs(t)>=1?0:t}var Zx=new WeakMap;function LT(e,t){let r=eR(e);if(r===0)return e;let n=Zx.get(e);if(!n){let o=a=>{let{springSplit:s,...i}=e.config;return{...e,config:{...i,springRate:e.config.springRate*a},...e.measured?{measured:{...e.measured,springRate:e.measured.springRate*a}}:{}}};n={left:o(1-r),right:o(1+r)},Zx.set(e,n)}return n[t]}var er=["FL","FR","RL","RR"],bt=e=>2*e.hardpoints.wheelCenter[1],Nt=(e,t)=>t?bt(Ge(e,"FL"))/2+bt(Ge(e,"FR"))/2:bt(Ge(e,"RL"))/2+bt(Ge(e,"RR"))/2;function Ze(e,t){let r=e==="FL"||e==="FR";return{axleX:r?t.frontAxleX:t.frontAxleX-t.wheelbase,sideSign:e==="FR"||e==="RR"?1:-1,isFront:r}}function Ot(e,t){return[t.axleX+e[0],t.sideSign*e[1],e[2]]}function rn(e,t){return[e[0],t.sideSign*e[1],e[2]]}function nn(e){return e.frontAxleX-e.wheelbase/2}function Id(e,t,r){return t[2]+e.heave+(t[0]-r)*Math.sin(e.pitch)-t[1]*Math.sin(e.roll)}function on(e,t,r,n){let o=Ze(e,t),a=(n?Nt(n,o.isFront):o.isFront?t.trackFront:t.trackRear)/2,s=o.sideSign*a,i=o.axleX-nn(t),c=-r.heave-i*Math.sin(r.pitch)+s*Math.sin(r.roll),l=o.isFront?o.sideSign*r.steer:0;return{travel:c,steer:l}}var DT={travelMin:-40,travelMax:40,steps:41,steer:0};function ps(e){return{q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle}}function Ke(e,t={}){let r={...DT,...t},n=tt(e);return Ho(n,r)}function Ho(e,t){let r=t.steer,n=.01,o=Ie(e,n,r),a=Ie(e,-n,r),s=(o.travel-a.travel)/(2*n);(!Number.isFinite(s)||Math.abs(s)<1e-6)&&(s=1);let i=Math.max(Math.abs(t.travelMax),Math.abs(t.travelMin)),c=Math.min(1.2,1.5*i/Math.abs(s)),l=Math.max(20,t.steps*2),u=[],m=Ie(e,0,r);u.push({beta:0,travel:m.travel,warm:ps(m),converged:m.converged});let f=ps(m);for(let R=1;R<=l;R++){let k=c*R/l,v=Ie(e,k,r,f);f=ps(v),u.push({beta:k,travel:v.travel,warm:f,converged:v.converged})}f=ps(m);for(let R=1;R<=l;R++){let k=-c*R/l,v=Ie(e,k,r,f);f=ps(v),u.push({beta:k,travel:v.travel,warm:f,converged:v.converged})}u.sort((R,k)=>R.beta-k.beta);let p=u[u.length-1].travel>=u[0].travel,d=!1;for(let R=1;R<u.length;R++){let k=u[R].travel-u[R-1].travel;(p&&k<-1e-6||!p&&k>1e-6)&&(d=!0)}let h=u.filter(R=>R.converged).map(R=>R.travel),b=h.length?[Math.min(...h),Math.max(...h)]:[0,0],g=h.length>0&&b[0]<=t.travelMin+1e-6&&b[1]>=t.travelMax-1e-6,y=[];for(let R=0;R<t.steps;R++){let k=t.steps===1?t.travelMin:t.travelMin+(t.travelMax-t.travelMin)*R/(t.steps-1),v=ET(u,k,p),x=IT(u,v);y.push(Ie(e,v,r,x))}return _T(y,e.corner.config.actuation==="decoupled"?0:e.corner.config.springRate),{samples:y,covered:g,reach:b,fold:d,unconverged:y.filter(R=>!R.converged).length}}function ET(e,t,r){let n=r?e.slice():e.slice().reverse();if(t<=n[0].travel)return n[0].beta;if(t>=n[n.length-1].travel)return n[n.length-1].beta;for(let o=1;o<n.length;o++){let a=n[o-1],s=n[o];if(t>=Math.min(a.travel,s.travel)&&t<=Math.max(a.travel,s.travel)){let i=s.travel-a.travel,c=Math.abs(i)<1e-9?0:(t-a.travel)/i;return a.beta+c*(s.beta-a.beta)}}return n[n.length-1].beta}function IT(e,t){let r=e[0],n=1/0;for(let o of e){let a=Math.abs(o.beta-t);a<n&&(n=a,r=o)}return r.warm}function _d(e,t,r){return r===0?(e[1]-e[0])/(t[1]-t[0]):r===e.length-1?(e[r]-e[r-1])/(t[r]-t[r-1]):(e[r+1]-e[r-1])/(t[r+1]-t[r-1])}function _T(e,t){if(e.length<2)return;let r=e.map(s=>s.travel),n=e.map(s=>s.metrics.camber),o=e.map(s=>s.metrics.toe),a=e.map(s=>s.metrics.damperLength);for(let s=0;s<e.length;s++){let i=_d(n,r,s),c=_d(o,r,s),l=-_d(a,r,s);e[s].metrics.camberGain=i,e[s].metrics.bumpSteer=c,e[s].metrics.motionRatio=l,e[s].metrics.wheelRate=t*l*l}}var sl=e=>e!==void 0&&Number.isFinite(e)&&e>0;function NT(e){return e&&sl(e.helperRate)&&sl(e.helperTravel)?{rate:e.helperRate,travel:e.helperTravel}:null}function Nd(e,t,r){let n=t/e;return r?n+Math.min(t/r.rate,r.travel):n}function ds(e,t,r,n){if(!(e>0)||!Number.isFinite(e)||!(t>0)||!Number.isFinite(t))return null;let o=NT(n),a=-Nd(e,t,o),s=zo(r,n);return{rate:e,preload:t,helper:o,free:a,pull:null,droop:s.droop??a,droopStated:s.droop!==null,bump:s.bump,holdsLoad:!0}}function zo(e,t){if(!Number.isFinite(e))return{droop:null,bump:null};let r=sl(t?.extended)&&t.extended>e?t.extended:null,n=r!==null&&sl(t?.stroke)?r-t.stroke:null;return{droop:r!==null?e-r:null,bump:n!==null&&n<e?e-n:null}}function Od(e,t){if(!(e>0)||!Number.isFinite(e))return null;let r=zo(t.length0,t.coilover),n=t.free===-1/0||t.pull!==null&&t.pull>=t.free;if(n&&r.droop===null&&r.bump===null)return null;let o=n?-1/0:t.free;return{rate:e,preload:o===-1/0?0:-e*o,helper:null,free:o,pull:n?null:t.pull,droop:r.droop??-1/0,droopStated:r.droop!==null,bump:r.bump,holdsLoad:!1}}function OT(e,t){let{rate:r,preload:n,helper:o}=e;if(!o)return t>e.free-1e-9?n+r*t:e.pull!==null&&t<e.pull+1e-9?r*(t-e.pull):0;let a=Nd(r,n,o)+t;if(a<=0)return 0;let s=o.rate*o.travel;return a>=s/r+o.travel?n>=s?n+r*t:r*(a-o.travel):a*r*o.rate/(r+o.rate)}function VT(e,t){let{rate:r,preload:n,helper:o}=e;if(!o)return t>e.free-1e-9||e.pull!==null&&t<e.pull+1e-9?r:0;let a=Nd(r,n,o)+t;return a<=0?0:a>=o.rate*o.travel/r+o.travel?r:r*o.rate/(r+o.rate)}function Yo(e,t){let r=OT(e,t),n=e.free;return e.holdsLoad&&t<n&&e.droop<n&&(r+=.001*e.rate*(Math.max(t,e.droop)-n)),t<e.droop&&(r+=1e3*e.rate*(t-e.droop)),e.bump!==null&&t>e.bump&&(r+=1e3*e.rate*(t-e.bump)),r}function Vd(e,t){let r=VT(e,t),n=e.free;return e.holdsLoad&&t<n&&t>e.droop&&(r+=.001*e.rate),t<e.droop&&(r+=1e3*e.rate),e.bump!==null&&t>e.bump&&(r+=1e3*e.rate),r}function Bd(e){let t=e.free,r=[t,e.droop];return e.helper&&r.push(e.helper.rate*e.helper.travel/e.rate+e.helper.travel+t),e.bump!==null&&r.push(e.bump),e.pull!==null&&r.push(e.pull),[...new Set(r.filter(Number.isFinite))].sort((n,o)=>n-o)}var il={min:-60,max:60,steps:61},$d=e=>({travel:[e.min,e.max],force:[0,0],motionRatio:[0,0],spring:null}),tR=new WeakMap;function BT(e,t){let r=tR.get(e.corner);r||tR.set(e.corner,r=new Map);let n=`${t.min}|${t.max}|${t.steps}`,o=r.get(n);return o||r.set(n,o=Ho(e,{travelMin:t.min,travelMax:t.max,steps:t.steps,steer:0})),o}function hs(e,t,r=il,n=e.corner.config.coilover){let o=e.corner.config;if(o.actuation==="decoupled")return $d(r);let a=BT(e,r),s=GT(e,o.springRate,a.samples),i=[];for(let h of a.samples){let b=h.metrics.motionRatio;!h.converged||b===void 0||!Number.isFinite(b)||!Number.isFinite(h.metrics.damperLength)||i.length>0&&h.travel<=i[i.length-1].t+1e-6||i.push({t:h.travel,L:h.metrics.damperLength,mr:b})}if(i.length<2)return $d(r);let c=HT(i,0);if(!(Math.abs(c.mr)>1e-6))return $d(r);let l=t/c.mr,u=ds(s,l,c.L,n),m=u?$T(i,Bd(u).map(h=>c.L-h)):i,f=m.map(h=>(u?Yo(u,c.L-h.L):l+s*(c.L-h.L))*h.mr-t),p=h=>h===null?null:m.find(b=>b.L===c.L-h)?.t??null,d=u?Bd(u).map(p).filter(h=>h!==null):[];return{travel:m.map(h=>h.t),force:f,motionRatio:m.map(h=>h.mr),spring:{rate:s,preload:l,length0:c.L,law:u},...u?{stops:{droop:p(u.droop),bump:p(u.bump)}}:{},...d.length?{kinks:d}:{},length:m.map(h=>h.L)}}function Gd(e,t){if(!e.spring)return null;let r=e.travel.length,n=e.length;if(n&&n.length===r&&r>=2){let s=tr(e.travel,t),i=(t-e.travel[s])/(e.travel[s+1]-e.travel[s]);return e.spring.length0-(n[s]+i*(n[s+1]-n[s]))}if(r<2)return 0;let o=64,a=0;for(let s=0;s<o;s++){let i=t*s/o,c=t*(s+1)/o;a+=(fs(e,i)+fs(e,c))/2*(c-i)}return a}function $T(e,t){let r=[...e];for(let n of t)for(let o=0;o+1<e.length;o++){let a=e[o],s=e[o+1];if(a.L===n)break;if((a.L-n)*(s.L-n)>=0)continue;let i=(n-a.L)/(s.L-a.L);r.push({t:a.t+i*(s.t-a.t),L:n,mr:a.mr+i*(s.mr-a.mr)});break}return r.sort((n,o)=>n.t-o.t),r.filter((n,o)=>o===0||n.t>r[o-1].t+1e-6)}function GT(e,t,r){let n=e.corner.compliance?.links?.pushRod;if(n===void 0||!(n>0)||!Number.isFinite(n)||!(t>0))return t;let o=e.corner.config.actuation==="direct"?n:KT(e,n,r);return!(o>0)||!Number.isFinite(o)?t:t*o/(t+o)}function KT(e,t,r){let n;for(let m of r)m.converged&&(!n||Math.abs(m.travel)<Math.abs(n.travel))&&(n=m);if(!n)return t;let o=e.corner.hardpoints,a=us(e.rocker,n.points.rockerAngle),s=q(H(o.rockerPivotB,o.rockerPivotA)),i=(m,f)=>Math.abs(X(s,ae(H(m,o.rockerPivotA),q(H(f,m))))),c=i(a.pushrod,n.points.pushrodOuter),l=i(a.damper,o.damperChassis);if(!(l>1e-9)||!(c>1e-9))return t;let u=c/l;return t*u*u}function fs(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.motionRatio[0];let n=tr(e.travel,t),o=(t-e.travel[n])/(e.travel[n+1]-e.travel[n]);return e.motionRatio[n]+o*(e.motionRatio[n+1]-e.motionRatio[n])}function kr(e,t,r){if(!e.spring)return Yt(e,t);let{rate:n,preload:o,length0:a,law:s}=e.spring,i=fs(e,0),c=a-r;return(s?Yo(s,c):o+n*c)*fs(e,t)-o*i}function HT(e,t){let r=tr(e.map(s=>s.t),t),n=e[r],o=e[r+1],a=(t-n.t)/(o.t-n.t);return{L:n.L+a*(o.L-n.L),mr:n.mr+a*(o.mr-n.mr)}}function tr(e,t){let r=e.length;if(t<=e[0])return 0;if(t>=e[r-1])return r-2;let n=0,o=r-1;for(;o-n>1;){let a=n+o>>1;e[a]<=t?n=a:o=a}return n}function Yt(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.force[0];let n=tr(e.travel,t),o=(t-e.travel[n])/(e.travel[n+1]-e.travel[n]);return e.force[n]+o*(e.force[n+1]-e.force[n])}function Wo(e,t){let r=e.travel.length;if(r<3)return bs(e,t);let n=tr(e.travel,t),o=(e.force[n+1]-e.force[n])/(e.travel[n+1]-e.travel[n]),a=i=>i===0||i===r-1||e.kinks?.includes(e.travel[i])?o:(e.force[i+1]-e.force[i-1])/(e.travel[i+1]-e.travel[i-1]),s=Math.max(0,Math.min(1,(t-e.travel[n])/(e.travel[n+1]-e.travel[n])));return a(n)+s*(a(n+1)-a(n))}function bs(e,t){if(e.travel.length<2)return 0;let n=tr(e.travel,t);return(e.force[n+1]-e.force[n])/(e.travel[n+1]-e.travel[n])}function De(e,t,r){let n=e.hardpoints;switch(t.attach){case"upright":{let o=H(t.outer,n.wheelCenter);return ee(ee(ot(r.pose.omega,o),n.wheelCenter),r.pose.t)}case"lowerArm":{let o=q(H(n.lcaRear,n.lcaFront));return ee(n.lcaFront,ot(U(o,r.beta),H(t.outer,n.lcaFront)))}case"rocker":{let o=q(H(n.rockerPivotB,n.rockerPivotA));return ee(n.rockerPivotA,It(H(t.outer,n.rockerPivotA),o,r.points.rockerAngle))}}}function an(e,t,r){return e.config.actuation==="decoupled"&&t.attach==="rocker"&&r==="coil"}function Kd(e,t,r){return an(e,t,r)?[t.inner[0],-t.inner[1],t.inner[2]]:t.inner}function jo(e,t,r){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return Hd(e,t,r.kind,Ke(e,{travelMin:n,travelMax:o,steps:a}).samples)}function Hd(e,t,r,n){let o=q(H(t.outer,Kd(e,t,r))),a=[],s=[],i=t.outer;for(let p of n)a.push(p.travel),s.push(X(H(De(e,t,p),i),o));let c=a.length,l=new Array(c).fill(0);for(let p=0;p<c;p++){let d=Math.max(0,p-1),h=Math.min(c-1,p+1),b=a[h]-a[d];l[p]=b!==0?(s[h]-s[d])/b:0}let u=l[0];for(let p=1;p<c;p++)if(a[p]>=0){let d=a[p]-a[p-1],h=d!==0?(0-a[p-1])/d:0;u=l[p-1]+h*(l[p]-l[p-1]);break}let m=l.filter(p=>Math.abs(p)>1e-9).map(Math.sign),f=m.length>0&&m.some(p=>p!==m[0]);return{travel:a,ratio:l,linkTravel:s,atDesign:u,reverses:f}}function zd(e,t){let{travel:r,ratio:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}function Yd(e,t){let{travel:r,linkTravel:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}var gs=e=>e.mount??{kind:"rockerToRocker"},aR=e=>[e[0],0,e[2]],zT=e=>2*Math.abs(e[1]),YT=(e,t)=>Math.hypot(e[0]-t[0],e[2]-t[2]);function ll(e,t){return t.kind==="chassis"?YT(e,t.anchor):zT(e)}function ys(e,t,r){if(r.kind==="chassis"){let s=[(e[0]+t[0])/2,(e[1]-t[1])/2,(e[2]+t[2])/2];return Math.hypot(s[0]-r.anchor[0],s[1],s[2]-r.anchor[2])}let n=e[0]-t[0],o=e[1]+t[1],a=e[2]-t[2];return Math.hypot(n,o,a)}function En(e,t,r={}){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return Wd(e,t,Ke(e,{travelMin:n,travelMax:o,steps:a}).samples)}function Wd(e,t,r){let n=gs(t),o=d=>De(e,{...t,inner:t.outer},r[d]),a=[],s=[],i=[];for(let d=0;d<r.length;d++)a.push(r[d].travel),i.push(ll(o(d),n));let c=nR(a,i,0);for(let d of i)s.push(c-d);let l=a.length,u=new Array(l).fill(0);for(let d=0;d<l;d++){let h=Math.max(0,d-1),b=Math.min(l-1,d+1),g=a[b]-a[h];u[d]=g!==0?(s[b]-s[h])/g:0}let m=rR(a,20),f=rR(a,-20),p=ys(o(m),o(f),n);return{travel:a,ratio:u,springTravel:s,atDesign:nR(a,u,0),installedLength:c,rollSensitivity:c-p}}function rR(e,t){let r=0,n=1/0;for(let o=0;o<e.length;o++){let a=Math.abs(e[o]-t);a<n&&(n=a,r=o)}return r}function nR(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];for(let o=1;o<n;o++)if(e[o]>=r){let a=e[o]-e[o-1],s=a!==0?(r-e[o-1])/a:0;return t[o-1]+s*(t[o]-t[o-1])}return t[n-1]}function jd(e,t,r){let n={outer:t.outer,attach:t.attach},o=Ke(e,{travelMin:-5,travelMax:5,steps:3}),a=d=>aR(De(e,{...n,inner:n.outer},o.samples[d])),s=a(1),i=a(2),c=a(0),l=i[0]-c[0],u=i[2]-c[2],m=Math.hypot(l,u),f=m>1e-9?[l/m,u/m]:[0,1],p=r??Math.max(80,2*Math.abs(t.outer[1])*.5);return[s[0]+f[0]*p,0,s[2]+f[1]*p]}function Ud(e,t){let r=e.hardpoints,n=r.rockerPivotA,o=oR(cl(r.rockerPivotB,r.rockerPivotA)),a=Math.max(30,.6*sR(cl(r.rockerToDamper,n))),s=cl(r.rockerToDamper,n),i=oR(cl(s,WT(o,jT(s,o)))),c=UT(o,i),l=null,u=-1/0;for(let m=0;m<360;m+=10){let f=m*Math.PI/180,d={outer:[n[0]+a*(Math.cos(f)*i[0]+Math.sin(f)*c[0]),n[1]+a*(Math.cos(f)*i[1]+Math.sin(f)*c[1]),n[2]+a*(Math.cos(f)*i[2]+Math.sin(f)*c[2])],attach:"rocker"},h=t==="chassis"?{...d,mount:{kind:"chassis",anchor:jd(e,d)}}:d,b;try{b=En(e,h,{travelMin:-20,travelMax:20,steps:9})}catch{continue}let g=b.atDesign/(1+4*Math.abs(b.rollSensitivity));Number.isFinite(g)&&g>u&&(u=g,l=h)}return l??{outer:r.rockerToDamper,attach:"rocker"}}var cl=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],WT=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],jT=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],sR=e=>Math.hypot(e[0],e[1],e[2]),oR=e=>{let t=sR(e)||1;return[e[0]/t,e[1]/t,e[2]/t]},UT=(e,t)=>[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]];var Xd=.001,XT=e=>({outer:e.outer,inner:e.outer,attach:e.attach}),fR=(e,t,r)=>(ll(e.at0,t)-ll(r,t))/2,qT=(e,t)=>X(H(t,e.pickup.at0),e.axis);function qd(e,t){let r=e.length;return t.map((n,o)=>{let a=Math.max(0,o-1),s=Math.min(r-1,o+1);return(t[s]-t[a])/(e[s]-e[a])})}function iR(e,t){let r=[0,1,2].map(n=>qd(e,t.map(o=>o[n])));return t.map((n,o)=>[r[0][o],r[1][o],r[2][o]])}function Qd(e){return{travel:e,heave:e.map(t=>t/2),heaveRatio:e.map(()=>.5),roll:[...e],rollRatio:e.map(()=>1)}}function cR(e,t,r,n){let o=e.corner;if(!t.heave&&!t.roll)return{side:Qd([n.min,n.max]),pickups:{}};let a=at(ye(e,0,0)),s={};if(t.heave&&r){let h=XT(t.heave);s.heave={corner:o,link:h,at0:De(o,h,a)}}if(t.roll){let h=t.roll;s.roll={pickup:{corner:o,link:h,at0:De(o,h,a)},axis:q(H(h.outer,Kd(o,h,t.rollKind??"coil")))}}let i=t.roll&&an(o,t.roll,t.rollKind??"coil")?{near:t.roll,far:{...t.roll,outer:t.roll.inner}}:null,c=Ho(e,{travelMin:n.min,travelMax:n.max,steps:n.steps,steer:0}),l=[],u=[],m=[],f=[],p=[];for(let h of c.samples)!h.converged||l.length>0&&h.travel<=l[l.length-1]+1e-6||(l.push(h.travel),u.push(s.heave&&r?fR(s.heave,r,De(o,s.heave.link,h)):h.travel/2),m.push(s.roll?qT(s.roll,De(o,s.roll.pickup.link,h)):h.travel),i&&(f.push(De(o,i.near,h)),p.push(De(o,i.far,h))));if(l.length<2)return{side:Qd([n.min,n.max]),pickups:{}};let d={travel:l,heave:u,heaveRatio:qd(l,u),roll:m,rollRatio:qd(l,m)};return i&&(d.eyes={near:f,nearRatio:iR(l,f),far:p,farRatio:iR(l,p)}),{side:d,pickups:s}}function ul(e,t,r){let n=tr(e,r);return t[n]+(r-e[n])/(e[n+1]-e[n])*(t[n+1]-t[n])}function lR(e,t,r){let n=tr(e,r);return(t[n+1]-t[n])/(e[n+1]-e[n])}function _e(e,t){return{h:ul(e.travel,e.heave,t),dh:ul(e.travel,e.heaveRatio,t),ddh:lR(e.travel,e.heaveRatio,t),r:ul(e.travel,e.roll,t),dr:ul(e.travel,e.rollRatio,t),ddr:lR(e.travel,e.rollRatio,t)}}function uR(e,t,r,n){let o=tr(e,n),a=e[o+1]-e[o],s=(n-e[o])/a,i=(u,m)=>[u[0]+s*(m[0]-u[0]),u[1]+s*(m[1]-u[1]),u[2]+s*(m[2]-u[2])],c=r[o],l=r[o+1];return{p:i(t[o],t[o+1]),d:i(c,l),dd:[(l[0]-c[0])/a,(l[1]-c[1])/a,(l[2]-c[2])/a]}}var Zd=(e,t)=>Math.hypot(e[0]-t[0],e[1]+t[1],e[2]-t[2]);function Jd(e,t){let r=e.side[0].eyes,n=e.side[1].eyes;if(!r||!n)return null;let o=uR(e.side[0].travel,r.near,r.nearRatio,t[0]),a=uR(e.side[1].travel,n.far,n.farRatio,t[1]),s=[o.p[0]-a.p[0],o.p[1]+a.p[1],o.p[2]-a.p[2]],i=Math.hypot(s[0],s[1],s[2]),c=[s[0]/i,s[1]/i,s[2]/i],l=o.d,u=[-a.d[0],a.d[1],-a.d[2]],m=[-a.dd[0],a.dd[1],-a.dd[2]],f=X(c,l),p=X(c,u),d=(X(l,u)-f*p)/i;return{L:i,dL:[f,p],ddL:[[(X(l,l)-f*f)/i+X(c,o.dd),d],[d,(X(u,u)-p*p)/i+X(c,m)]]}}var hR=(e,t)=>e.bump!==null&&t>e.bump?e.rate*(t-e.bump):e.droop!==null&&t<e.droop?e.rate*(t-e.droop):0,QT=(e,t)=>e.bump!==null&&t>e.bump||e.droop!==null&&t<e.droop?e.rate:0;function xs(e,t,r,n,o=0){let a=e.rollStop;if(!a)return r;let s=Jd(e,t);if(!s)return r;let i=hR(a,a.length0-(n??s.L+o));return i===0?r:[r[0]-i*s.dL[0],r[1]-i*s.dL[1]]}function ml(e,t){let r=Qd(e.travel);return t==="heave"?{...e,heave:r.heave,heaveRatio:r.heaveRatio}:{...e,roll:r.roll,rollRatio:r.rollRatio}}var pl=(e,t)=>e?e.law?Yo(e.law,t):e.preload+e.rate*t:0,mR=(e,t)=>e?e.law?Vd(e.law,t):e.rate:0;function Rs(e,t,r,n,o){let a=pl(e.heave,n),s=pl(e.roll,o);return[a*t.dh+s*t.dr,a*r.dh-s*r.dr]}var pR=(e,t)=>_e(e[0],t).h+_e(e[1],t).h;function ZT(e,t){let r=e.gap>0?pR(t,e.gap):0;return e.bothWays?{free:r,pull:e.gap>0?pR(t,-e.gap):0}:{free:r,pull:null}}function JT(e,t,r){let n={...t,outer:t.inner},o=(u,m)=>{let f=ht(ye(e[0],u,0)),p=ht(ye(e[1],m,0));if(!f||!p)return NaN;let d=De(e[0].corner,t,f),h=De(e[1].corner,n,p);return Math.hypot(d[0]-h[0],d[1]+h[1],d[2]-h[2])},a=1,s=o(0,0),i=o(-a,a)-o(a,-a),c=_e(r[0],a).r-_e(r[1],-a).r-(_e(r[0],-a).r-_e(r[1],a).r),l=i/c;return Number.isFinite(s)&&s>0&&Number.isFinite(l)&&Math.abs(l)>Xd?{length0:s,scale:l}:null}function bR(e,t,r,n=il){let o=r.heave?gs(r.heave):void 0,a=cR(e[0],r,o,n),s=e[1].corner===e[0].corner?a:cR(e[1],r,o,n),i=[a.side,s.side],c=!!(a.pickups.heave&&s.pickups.heave),l=!!(a.pickups.roll&&s.pickups.roll),u=r.carriesLoad?void 0:r.heaveSeat,m=u?u.rate:(t[0].heaveRate+t[1].heaveRate)/2,f=(t[0].arbRate+t[1].arbRate)/2,p=i.map(A=>_e(A,0));c&&!(Math.abs(p[0].dh+p[1].dh)>Xd)&&(i=[ml(i[0],"heave"),ml(i[1],"heave")],c=!1),l&&!(Math.abs(p[0].dr+p[1].dr)>Xd)&&(i=[ml(i[0],"roll"),ml(i[1],"roll")],l=!1),p=i.map(A=>_e(A,0));let d=p[0].dh+p[1].dh,h=p[0].dr+p[1].dr,b=m>0?2*m/(d*d):0,g=f>0?2*f/(h*h):0,y=0,R=0;if(r.carriesLoad){let A=[t[0].springLoad,t[1].springLoad];if(b>0&&g>0){let P=-p[0].dh*p[1].dr-p[1].dh*p[0].dr;Math.abs(P)>1e-12&&(y=(-A[0]*p[1].dr-A[1]*p[0].dr)/P,R=(p[0].dh*A[1]-p[1].dh*A[0])/P)}else b>0?y=(A[0]+A[1])/d:g>0&&(R=(A[0]-A[1])/h)}let k={};if(c&&o){let A=[a.pickups.heave,s.pickups.heave];k.heave={pickups:A,mount:o,span0:ys(A[0].at0,A[1].at0,o)}}let v=k.heave?k.heave.span0:NaN,x=k.heave?r.coilover:void 0,M=r.carriesLoad?ds(b,y,v,x):u?Od(b,{...ZT(u,i),length0:v,coilover:x}):null,F=b>0?{rate:b,preload:y,...M?{law:M}:{}}:null;if(l&&(k.roll={pickups:[a.pickups.roll.pickup,s.pickups.roll.pickup],axes:[a.pickups.roll.axis,s.pickups.roll.axis]},r.roll&&an(e[0].corner,r.roll,r.rollKind??"coil"))){let A=JT(e,r.roll,i);A&&(k.roll.unit=A)}let w=g>0?{rate:g,preload:R}:null,C={side:i,heave:F,roll:w,force0:[0,0],carriesLoad:r.carriesLoad,read:k},T=k.roll?.unit,S=T&&g>0&&i[0].eyes&&i[1].eyes?zo(T.length0,r.rollCoilover):null;return T&&S&&(S.droop!==null||S.bump!==null)&&(C.rollStop={length0:T.length0,rate:1e3*g/(T.scale*T.scale),...S}),C.force0=xs(C,[0,0],Rs(C,p[0],p[1],p[0].h+p[1].h,p[0].r-p[1].r)),C}function vs(e,t,r){let n=_e(e.side[0],t[0]),o=_e(e.side[1],t[1]),a=r?xs(e,t,Rs(e,n,o,n.h+o.h+r.heave,n.r-o.r+r.roll),void 0,r.unit):xs(e,t,Rs(e,n,o,n.h+o.h,n.r-o.r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function ef(e,t,r){let n=_e(e.side[0],t[0]),o=_e(e.side[1],t[1]),a=r?n.h+o.h+r.heave:n.h+o.h,s=r?n.r-o.r+r.roll:n.r-o.r,i=mR(e.heave,a),c=mR(e.roll,s),l=pl(e.heave,a),u=pl(e.roll,s),m=i*n.dh*o.dh-c*n.dr*o.dr,f=[[i*n.dh*n.dh+l*n.ddh+c*n.dr*n.dr+u*n.ddr,m],[m,i*o.dh*o.dh+l*o.ddh+c*o.dr*o.dr-u*o.ddr]],p=e.rollStop,d=p?Jd(e,t):null;if(!p||!d)return f;let h=p.length0-(r?d.L+r.unit:d.L),b=QT(p,h);if(b===0)return f;let g=hR(p,h),y=(k,v)=>b*d.dL[k]*d.dL[v]-g*d.ddL[k][v],R=m+y(0,1);return[[f[0][0]+y(0,0),R],[R,f[1][1]+y(1,1)]]}function tf(e,t,r){let n=ef(e,t);return n[r][0]+n[r][1]}function eP(e,t,r){let n=e.read.heave;if(!n)return _e(e.side[0],t[0]).h+_e(e.side[1],t[1]).h;let[o,a]=n.pickups;return n.span0-ys(De(o.corner,o.link,r[0]),De(a.corner,a.link,r[1]),n.mount)}function tP(e,t,r){let n=e.read.roll;if(!n)return _e(e.side[0],t[0]).r-_e(e.side[1],t[1]).r;let o=a=>X(H(De(n.pickups[a].corner,n.pickups[a].link,r[a]),n.pickups[a].at0),n.axes[a]);return o(0)-o(1)}function rP(e,t){let r=e.read.roll;if(!e.rollStop||!r)return;let[n,o]=r.pickups;return Zd(De(n.corner,n.link,t[0]),De(o.corner,{...o.link,outer:o.link.inner},t[1]))}function ks(e,t,r){let n=_e(e.side[0],t[0]),o=_e(e.side[1],t[1]),a=xs(e,t,Rs(e,n,o,eP(e,t,r),tP(e,t,r)),rP(e,r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function rf(e,t,r,n){let o=_e(e.side[0],r),a=_e(e.side[1],r),s=e.read.heave,i=s?.pickups[t],c=s&&i&&n?2*fR(i,s.mount,De(i.corner,i.link,n)):o.h+a.h,l=e.rollStop&&n?e.read.roll?.pickups[t]:void 0,u=l&&n?Zd(De(l.corner,l.link,n),De(l.corner,{...l.link,outer:l.link.inner},n)):void 0;return xs(e,[r,r],Rs(e,o,a,c,n?0:o.r-a.r),u)[t]-e.force0[t]}function nf(e,t,r,n){let o=Wo(e,r[n]);return t?.carriesLoad?o+tf(t,r,n):o}function gR(e,t){return _e(e.side[0],t[0]).h+_e(e.side[1],t[1]).h}function yR(e,t){return Jd(e,t)?.L??null}var of=e=>e==="FR"||e==="RR"?1:0,dl=(e,t)=>e.elements?.[t==="FL"||t==="FR"?"front":"rear"]??null;var xR=e=>Number.isFinite(e)&&e>0?1/e:0;var RR=(e,t)=>{let r=e[0][0]*e[1][1]-e[0][1]*e[1][0];return Math.abs(r)>1e-14?[(t[0]*e[1][1]-t[1]*e[0][1])/r,(e[0][0]*t[1]-e[1][0]*t[0])/r]:null},nP=(e,t)=>[e[0][0]*t[0]+e[0][1]*t[1],e[1][0]*t[0]+e[1][1]*t[1]],vR=1e-8,oP=40;function aP(e,t,r,n){return{force:(s,i)=>{if(r){let u=vs(r,s,n);return[Yt(t[0],s[0])+i[0]+u[0],Yt(t[1],s[1])+i[1]+u[1]]}let c=(s[0]+s[1])/2,l=(s[0]-s[1])/2;return[Yt(t[0],s[0])+i[0]+e[0].heaveRate*c+e[0].arbRate*l,Yt(t[1],s[1])+i[1]+e[1].heaveRate*c-e[1].arbRate*l]},stiffness:(s,i=bs)=>{if(r){let c=ef(r,s,n);return[[i(t[0],s[0])+c[0][0],c[0][1]],[c[1][0],i(t[1],s[1])+c[1][1]]]}return[[i(t[0],s[0])+e[0].heaveRate/2+e[0].arbRate/2,e[0].heaveRate/2-e[0].arbRate/2],[e[1].heaveRate/2-e[1].arbRate/2,i(t[1],s[1])+e[1].heaveRate/2+e[1].arbRate/2]]}}}function Uo(e,t,r,n,o,a=[0,0],s=[0,0],i=null,c){let l=[xR(r[0].tyreRate),xR(r[1].tyreRate)],u=[r[0].staticLoad,r[1].staticLoad],m=aP(r,n,i,c),f=P=>m.force(P,a),p=m.stiffness([0,0]),d=[l[0]>0?l[0]:1/Math.max(1,Math.abs(p[0][0])),l[1]>0?l[1]:1/Math.max(1,Math.abs(p[1][1]))],h=(P,L)=>{let D=L===1?f(P):m.force(P,[a[0]*L,a[1]*L]),E=[D[0]+s[0]*L,D[1]+s[1]*L],V=[P[0]+t[0]*L+E[0]*l[0]-e[0]*L,P[1]+t[1]*L+E[1]*l[1]-e[1]*L],N=[d[0]*(u[0]+E[0]),d[1]*(u[1]+E[1])],z=[N[0]<V[0],N[1]<V[1]];return{f:E,on:V,off:N,lifted:z,r:[Math.min(V[0],N[0]),Math.min(V[1],N[1])]}},b=(P,L)=>[L[0]?[d[0]*P[0][0],d[0]*P[0][1]]:[1+P[0][0]*l[0],P[0][1]*l[0]],L[1]?[d[1]*P[1][0],d[1]*P[1][1]]:[P[1][0]*l[1],1+P[1][1]*l[1]]],g=P=>Math.max(Math.abs(P[0]),Math.abs(P[1])),y=(P,L)=>{let D=[P[0],P[1]],E=h(D,L),V=!1,N=0;for(;N<oP;N++){if(g(E.r)<vR){V=!0;break}let z=RR(b(m.stiffness(D),E.lifted),[-E.r[0],-E.r[1]]);if(!z)break;let I=1,_=[D[0]+z[0],D[1]+z[1]],B=h(_,L);for(let O=0;O<8&&g(B.r)>g(E.r);O++)I/=2,_=[D[0]+I*z[0],D[1]+I*z[1]],B=h(_,L);D=_,E=B}return!V&&g(E.r)<vR&&(V=!0),{t:D,b:E,converged:V,it:N}},R=y(o?[o[0],o[1]]:[e[0]-t[0],e[1]-t[1]],1),k=R.it;if(!R.converged){let P=0,L=[0,0],D=.25;for(;P<1&&D>=1/256;){let E=Math.min(1,P+D),V=y(L,E);k+=V.it,V.converged?(P=E,L=V.t,E===1&&(R=V)):D/=2}}let{t:v,b:x,converged:M}=R,F=x.lifted,w=[F[0]?-u[0]:x.f[0],F[1]?-u[1]:x.f[1]],C=[F[0]?Math.max(0,x.on[0]):0,F[1]?Math.max(0,x.on[1]):0],T=m.stiffness(v,Wo),S=b(T,F);return{t:v,dF:w,lifted:F,clearance:C,converged:M,iterations:k,respond:(P,L,D=[0,0])=>{let E=[F[0]?-d[0]*D[0]:P[0]-L[0]-D[0]*l[0],F[1]?-d[1]*D[1]:P[1]-L[1]-D[1]*l[1]],V=RR(S,E);if(!V)return[NaN,NaN];let N=nP(T,V);return[F[0]?0:N[0]+D[0],F[1]?0:N[1]+D[1]]}}}var In=e=>!(Number.isFinite(e.tyreRate)&&e.tyreRate>0);function rr(e,t,r){return t?.input.corners[r].staticLoadedRadius??e}var af=["FL","FR","RL","RR"],SR={front:["FL","FR"],rear:["RL","RR"]},sP=512,iP=5e-4,cP=8;function fl(e,t){let r={},n={},o=new Map;for(let s of af){let i=e.ctx[s],c=t.corners[s],l=c.staticLoadedRadius;n[s]=at(ye(i,0,0,void 0,l===void 0?void 0:{loadedRadius:l})).points.contactPatch[2];let u=t.cornerCoilover?.[s==="FL"||s==="FR"?"front":"rear"],m=`${af.findIndex(p=>Ge(e.vehicle,p)===Ge(e.vehicle,s))}|${c.springLoad}|${u?`${u.extended}/${u.stroke}`:""}`,f=o.get(m);f?r[s]=f:(r[s]=u?hs(i,c.springLoad,void 0,u):hs(i,c.springLoad),o.set(m,r[s]))}let a={front:null,rear:null};for(let s of["front","rear"]){let i=t.elements?.[s];if(!i)continue;let c=SR[s];a[s]=bR([e.ctx[c[0]],e.ctx[c[1]]],[t.corners[c[0]],t.corners[c[1]]],i)}return{input:t,curve:r,elements:a,ground0:n,memo:new Map}}function AR(e,t,r){if(!(r>0)||!Number.isFinite(r)||!Number.isFinite(t)||t<=0)return 0;let n=Math.min(t/r,e);return 2*Math.sqrt(Math.max(0,2*e*n-n*n))}var lP=e=>`${e.heave}|${e.pitch}|${e.roll}|${e.steer}`;function sf(e,t,r){return{travel:r.travel,steer:r.steer,ground:r.travel,tyreDeflection:0,load:NaN,loadedRadius:rr(Ge(e.vehicle,t).config.loadedRadius,e.kc,t),lifted:!1,contactLength:0,converged:!0,rigid:!0,rideRate:NaN,wheelRateAtLoad:NaN}}var uP=e=>e?{q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle}:void 0;function kR(e,t,r,n){let o=SR[n],a=e.vehicle.config,s=o.map(w=>on(w,a,r,e.vehicle)),i=[t.input.corners[o[0]],t.input.corners[o[1]]],c=t.loadCase;if(!c&&i.every(In))return{corners:[sf(e,o[0],s[0]),sf(e,o[1],s[1])],respond:null};let l=o.map(w=>t.curve[w]),u=t.elements?.[n]??null,m=o.map(w=>rr(Ge(e.vehicle,w).config.loadedRadius,t,w)),f=[s[0].travel+(c?.ground[o[0]]??0),s[1].travel+(c?.ground[o[1]]??0)],p=[c?.linkLoad[o[0]]??0,c?.linkLoad[o[1]]??0],d=[c?.patchShift[o[0]],c?.patchShift[o[1]]],h=[0,0],b=[0,0],g,y=Uo(f,h,i,l,void 0,void 0,p,u),R=[void 0,void 0],k=[!0,!0],v=[0,0],x=!1;for(let w=0;w<cP;w++){w>0&&(y=Uo(f,h,i,l,g,b,p,u)),v=[Number.isFinite(i[0].tyreRate)&&i[0].tyreRate>0?y.dF[0]/i[0].tyreRate:0,Number.isFinite(i[1].tyreRate)&&i[1].tyreRate>0?y.dF[1]/i[1].tyreRate:0];let C=[0,0],T=[0,0];for(let A=0;A<2;A++){let P=ye(e.ctx[o[A]],y.t[A],s[A].steer,uP(R[A]),{loadedRadius:m[A]-v[A],patchShift:d[A]}),L=at(P);R[A]=L,k[A]=P.ok,C[A]=L.points.contactPatch[2]-t.ground0[o[A]]-y.t[A]-v[A],T[A]=kr(l[A],y.t[A],L.points.damperLength)-Yt(l[A],y.t[A])}if(u){let A=ks(u,y.t,[R[0],R[1]]),P=vs(u,y.t);T[0]+=A[0]-P[0],T[1]+=A[1]-P[1]}let S=Math.max(Math.abs(C[0]-h[0]),Math.abs(C[1]-h[1]),Math.abs(T[0]-b[0])/Math.max(1,i[0].tyreRate),Math.abs(T[1]-b[1])/Math.max(1,i[1].tyreRate));if(h=C,b=T,g=y.t,S<iP){x=!0;break}}let M=y.respond([1,1],[0,0]);return{corners:[0,1].map(w=>{let C=R[w];return{travel:y.t[w],steer:s[w].steer,ground:f[w],tyreDeflection:v[w],load:i[w].staticLoad+y.dF[w],loadedRadius:m[w]-v[w],lifted:y.lifted[w],clearance:y.clearance[w],contactLength:AR(m[w]-v[w],i[w].staticLoad+y.dF[w],i[w].tyreRate),converged:y.converged&&x&&k[w],rigid:!1,state:C,solved:k[w],rideRate:M[w],wheelRateAtLoad:nf(l[w],u,y.t,w)}}),respond:y.respond}}function FR(e,t){let r=e.kc,n=lP(t),o=r.memo.get(n);if(o)return o;let a=kR(e,r,t,"front"),s=kR(e,r,t,"rear"),i={corners:{FL:a.corners[0],FR:a.corners[1],RL:s.corners[0],RR:s.corners[1]},respond:{front:a.respond,rear:s.respond}};return r.memo.size>=sP&&r.memo.clear(),r.memo.set(n,i),i}function gt(e,t){if(!e.kc){let r={};for(let n of af)r[n]=sf(e,n,on(n,e.vehicle.config,t,e.vehicle));return r}return FR(e,t).corners}function hl(e,t,r){return e.kc?FR(e,t).respond[r]:null}function Ms(e,t,r,n=0){let o=e.kc;if(!o)return r;let a=o.input.corners[t];if(In(a))return r;let s=on(t,e.vehicle.config,{heave:0,pitch:0,roll:0,steer:n},e.vehicle).steer,i=rr(Ge(e.vehicle,t).config.loadedRadius,o,t),c=o.loadCase,l=c?.linkLoad[t]??0,u=c?.patchShift[t],m=at(ye(e.ctx[t],r,s,void 0,{loadedRadius:i,patchShift:u})),f=dl(o,t),p=kr(o.curve[t],r,m.points.damperLength)+(f?rf(f,of(t),r,m):a.heaveRate*r),h=Math.max(p+l,-a.staticLoad)/a.tyreRate;return(h===0?m:at(ye(e.ctx[t],r,s,void 0,{loadedRadius:i-h,patchShift:u}))).points.contactPatch[2]-o.ground0[t]-(c?.ground[t]??0)}var mP=180/Math.PI,pP=[0,0,1];function dP(e,t){let r=rn(e,t),n=U(ae(pP,r),-t.sideSign);return-Math.atan2(n[1],n[0])*mP}var wR=e=>1/Math.tan(e*Math.PI/180),CR=.05,TR=.001;function PR(e,t,r){if(!Number.isFinite(e)||!Number.isFinite(t))return NaN;if(!(Math.abs(e)<TR&&Math.abs(t)<TR))return e>0&&t>0?100*(wR(t)-wR(e))/r:NaN}function fP(e,t){let r=Nt(e.vehicle,!0)/e.vehicle.config.wheelbase,n=t("FL",0).deg,o=t("FR",0).deg,a=(c,l)=>{let u=c+l>=0;return{left:u,inner:u?c:-l,outer:u?l:-c}},s,i=()=>{if(s===void 0){let c=[CR,-CR].map(l=>{let{inner:u,outer:m}=a(t("FL",l).deg-n,t("FR",l).deg-o);return PR(u,m,r)??NaN});s=(c[0]+c[1])/2}return s};return c=>{let l=t("FL",c),u=t("FR",c),{left:m,inner:f,outer:p}=a(l.deg-n,u.deg-o),d=PR(f,p,r);return{steerL:l.deg,steerR:u.deg,inner:f,outer:p,toeDiff:f-p,ackermannPct:d??i(),inside:d===void 0?null:m?"left":"right",converged:l.ok&&u.ok}}}function cf(e,t){let r=e.vehicle.config,n={FL:Ze("FL",r),FR:Ze("FR",r)},o=t.travel??0,a=fP(e,(i,c)=>{let l=ht(ye(e.ctx[i],o,n[i].sideSign*c));return{deg:l?dP(l.points.spinAxis,n[i]):NaN,ok:l!==null}}),s=[];for(let i=0;i<t.steps;i++){let c=t.steps===1?0:-t.steerMax+2*t.steerMax*i/(t.steps-1),{inside:l,...u}=a(c);s.push({steerInput:c,...u})}return s}var LR=35,DR=55,Vt=e=>e.rackTravel&&e.rackTravel>0?e.rackTravel:LR,lf=e=>e.rackRatio&&e.rackRatio>0?e.rackRatio:DR;var uf=e=>({q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle});function ER(e,t,r,n,o){let a=ye(e,n,0,void 0,o),s=at(a),i=a.ok?0:1,c=s.points.contactPatch[2],l={steer:s.metrics.toe,camber:s.metrics.camber,lift:0,contactPatch:s.points.contactPatch,spinAxis:s.points.spinAxis,yaw:-s.metrics.toe*Math.PI/180},u=p=>{let d=[l],h=uf(s);for(let b=1;b<=r;b++){let g=p*(t*b)/r,y=Ie(e,s.beta,g,h,o),R=ht(ye(e,n,g,uf(y),o));if(!R||!y.converged){i++,d.push({...d[d.length-1]});continue}d.push({steer:R.metrics.toe,camber:R.metrics.camber,lift:-(y.points.contactPatch[2]-c),contactPatch:y.points.contactPatch,spinAxis:y.points.spinAxis,yaw:-y.metrics.toe*Math.PI/180}),h=uf(y)}return d},m=u(1),f=u(-1);return{travelMm:n,unsolved:i,centre:l,positive:m,negative:f}}function hP(e,t){return e.map((r,n)=>{let o=n===0?0:n-1,a=n===e.length-1?e.length-1:n+1,s=t[a]-t[o];if(!(s>0))return{longitudinal:0,lateral:0,vertical:0,yaw:0};let i=U(H(e[a].contactPatch,e[o].contactPatch),1/s),c=q(ae(r.spinAxis,[0,0,1])),l=ae([0,0,1],c);return{longitudinal:X(i,c),lateral:X(i,l),vertical:i[2],yaw:(e[a].yaw-e[o].yaw)/s}})}function IR(e,t,r){let n=o=>({steerDeg:o.map(a=>Math.abs(a.steer-e.centre.steer)),camberDeg:o.map(a=>a.camber-e.centre.camber),liftMm:o.map(a=>a.lift),jacobian:hP(o,t)});return{travelMm:e.travelMm,inner:n(r?e.positive:e.negative),outer:n(r?e.negative:e.positive)}}function bP(e){return e.positive[1].steer-e.centre.steer<0}function gP(e,t,r){return{meanDeg:t.map((n,o)=>.5*(r.inner.steerDeg[o]+r.outer.steerDeg[o])),innerDeg:r.inner.steerDeg,outerDeg:r.outer.steerDeg,innerCamber:r.inner.camberDeg,outerCamber:r.outer.camberDeg,innerLift:r.inner.liftMm,outerLift:r.outer.liftMm,rackRatioMmPerRev:lf(e.config),innerJacobian:r.inner.jacobian,outerJacobian:r.outer.jacobian}}function mf(e,t,r=13,n=-40,o=40,a=5,s){let i=tt(e),c=Array.from({length:r+1},(b,g)=>t*g/r),l=ER(i,t,r,0,s),u=bP(l),m=IR(l,c,u),f=Math.max(2,Math.floor(a)),p=Array.from({length:f},(b,g)=>n+(o-n)*g/(f-1));p.some(b=>Math.abs(b)<1e-9)||p.push(0),p.sort((b,g)=>b-g);let d=l.unsolved,h=p.map(b=>{if(Math.abs(b)<1e-9)return m;let g=ER(i,t,r,b,s);return d+=g.unsolved,IR(g,c,u)});return{...gP(e,c,m),..._R(l.unsolved),travelSurface:{rackMm:c,rows:h,..._R(d)}}}var _R=e=>e>0?{unsolved:e}:{};function nr(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function bl(e,t,r){let n=e.length;if(n===0)return{longitudinal:0,lateral:0,vertical:0,yaw:0};let o,a;if(r<=e[0])o=a=0;else if(r>=e[n-1])o=a=n-1;else for(o=0,a=n-1;a-o>1;){let l=o+a>>1;e[l]<=r?o=l:a=l}let s=t[o];if(o===a)return{longitudinal:s.longitudinal,lateral:s.lateral,vertical:s.vertical,yaw:s.yaw};let i=t[a],c=(r-e[o])/(e[a]-e[o]);return{longitudinal:s.longitudinal+c*(i.longitudinal-s.longitudinal),lateral:s.lateral+c*(i.lateral-s.lateral),vertical:s.vertical+c*(i.vertical-s.vertical),yaw:s.yaw+c*(i.yaw-s.yaw)}}function NR(e,t){let r=e.rows;if(r.length<=1||t<=r[0].travelMm)return{lo:0,hi:0,t:0};let n=r.length-1;if(t>=r[n].travelMm)return{lo:n,hi:n,t:0};let o=0,a=n;for(;a-o>1;){let s=o+a>>1;r[s].travelMm<=t?o=s:a=s}return{lo:o,hi:a,t:(t-r[o].travelMm)/(r[a].travelMm-r[o].travelMm)}}var _n=(e,t,r)=>e+r*(t-e);function Xo(e,t,r,n,o){let a=nr(e.rackMm,e.rows[n.lo][t][r],o);if(n.lo===n.hi)return a;let s=nr(e.rackMm,e.rows[n.hi][t][r],o);return _n(a,s,n.t)}function OR(e,t,r,n){let o=bl(e.rackMm,e.rows[r.lo][t].jacobian,n);if(r.lo===r.hi)return o;let a=bl(e.rackMm,e.rows[r.hi][t].jacobian,n);return{longitudinal:_n(o.longitudinal,a.longitudinal,r.t),lateral:_n(o.lateral,a.lateral,r.t),vertical:_n(o.vertical,a.vertical,r.t),yaw:_n(o.yaw,a.yaw,r.t)}}function qo(e,t,r,n){let o=e.travelSurface;if(!o||o.rackMm.length<2||o.rows.length===0)return Qo(e,t);let a=NR(o,r),s=NR(o,n),i=(p,d,h)=>{let b=o.rows[d.lo][p].steerDeg[h];return d.lo===d.hi?b:_n(b,o.rows[d.hi][p].steerDeg[h],d.t)},c=new Array(o.rackMm.length);for(let p=0;p<c.length;p++)c[p]=.5*(i("inner",a,p)+i("outer",s,p));let l=Math.max(0,t),u=c.length-1,m=o.rackMm[u],f=l>c[u];if(l<=c[0])m=o.rackMm[0],f=!1;else if(!f){let p=1;for(;p<c.length-1&&c[p]<l;)p++;let d=p-1,h=c[p]-c[d],b=Math.abs(h)>1e-12?(l-c[d])/h:0;m=_n(o.rackMm[d],o.rackMm[p],b)}return{innerDeg:Xo(o,"inner","steerDeg",a,m),outerDeg:Xo(o,"outer","steerDeg",s,m),innerCamber:Xo(o,"inner","camberDeg",a,m),outerCamber:Xo(o,"outer","camberDeg",s,m),innerLift:Xo(o,"inner","liftMm",a,m),outerLift:Xo(o,"outer","liftMm",s,m),innerJacobian:OR(o,"inner",a,m),outerJacobian:OR(o,"outer",s,m),atLock:f}}function Qo(e,t){let r=e.meanDeg.length-1;return{innerDeg:nr(e.meanDeg,e.innerDeg,t),outerDeg:nr(e.meanDeg,e.outerDeg,t),innerCamber:nr(e.meanDeg,e.innerCamber,t),outerCamber:nr(e.meanDeg,e.outerCamber,t),innerLift:e.innerLift?nr(e.meanDeg,e.innerLift,t):0,outerLift:e.outerLift?nr(e.meanDeg,e.outerLift,t):0,...e.innerJacobian&&e.outerJacobian?{innerJacobian:bl(e.meanDeg,e.innerJacobian,t),outerJacobian:bl(e.meanDeg,e.outerJacobian,t)}:{},atLock:r>=0&&t>e.meanDeg[r]}}var yP=()=>({lift:{FL:0,FR:0,RL:0,RR:0},travel:{FL:0,FR:0,RL:0,RR:0},load:{FL:0,FR:0,RL:0,RR:0},rollDeg:0});function Zo(e,t,r=we(e),n){let o=e.steerFront;if(!o?.innerLift||!o.outerLift||o.meanDeg.length<2||Math.abs(t)<1e-12)return yP();let a=Math.abs(t),s=t>0,i=n&&o.travelSurface?qo(o,a,s?n.FL:n.FR,s?n.FR:n.FL):null,c=i?.innerLift??nr(o.meanDeg,o.innerLift,a),l=i?.outerLift??nr(o.meanDeg,o.outerLift,a),u=s?c:l,m=s?l:c,f=.5*(u+m),p=r.rollWheelRateFront,d=r.rollWheelRateRear,h=e.trackFront,b=e.trackRear,g=p*h*h+d*b*b,y=g>0?p*h*(m-u)/g:0,R={FL:u-f+.5*h*y,FR:m-f-.5*h*y,RL:.5*b*y,RR:-.5*b*y};return{lift:{FL:u,FR:m,RL:0,RR:0},travel:R,load:{FL:p*R.FL,FR:p*R.FR,RL:d*R.RL,RR:d*R.RR},rollDeg:y===0?0:-Math.atan(y)*180/Math.PI}}function pf(e,t,r){let n=t/r,o=a=>1/Math.tan(a*Math.PI/180);for(let a=0;a<e.meanDeg.length;a++)if(e.outerDeg[a]>.3&&e.innerDeg[a]>.3)return 100*(o(e.outerDeg[a])-o(e.innerDeg[a]))/n;return NaN}var Ss=9.81;function Jo(e,t,r=0,n=0,o=0){if(!e.aero||t<=0)return{FL:0,FR:0,RL:0,RR:0};let a=e.aero.model?vr(e,t,r,Jr(e,n,o)):Dn(e.aero,t),s=a.downFront/2,i=a.downRear/2,c=a.drag*(e.aero.copHeight/1e3)/(e.wheelbase/1e3)/2;return{FL:s-c,FR:s-c,RL:i+c,RR:i+c}}function df(e,t,r=0,n=0,o=0){if(!e.aero?.model||t<=0)return!1;let a=vr(e,t,r,Jr(e,n,o));return a!=null&&(a.clampedRide||a.clampedAttitude)}function Nn(e){let t=e.loadFactor===void 0?e.massTotal*Ss:e.massTotal*Ss*e.loadFactor,r=t*e.frontMassFrac,n=t*(1-e.frontMassFrac);return{FL:r/2,FR:r/2,RL:n/2,RR:n/2}}function VR(e,t=we(e),r=e.cgHeight){let n=e.trackFront/1e3,o=e.trackRear/1e3,a=e.rcHeightFront/1e3,s=e.rcHeightRear/1e3,i=(e.rcHeightFront+(e.rcHeightRear-e.rcHeightFront)*(1-e.frontMassFrac))/1e3,c=r/1e3-i,l=2*e.unsprungPerCorner,u=e.unsprungCgHeight/1e3,m=t.sprungMass*c*Uc(t.sprungMass,c,t.rollRateTotal),f=(m*t.frontRollStiffFrac+t.sprungFront*a+l*u)/n,p=(m*(1-t.frontRollStiffFrac)+t.sprungRear*s+l*u)/o;return{cf:f,cr:p}}function ff(e){let{cf:t,cr:r}=VR(e);return t+r>0?t/(t+r):.5}function BR(e,t,r){if(e.FL>=0&&e.FR>=0&&e.RL>=0&&e.RR>=0)return{loads:{FL:Math.max(0,e.FL),FR:Math.max(0,e.FR),RL:Math.max(0,e.RL),RR:Math.max(0,e.RR)},lifted:{FL:!1,FR:!1,RL:!1,RR:!1},overturned:!1};let n=e.FL+e.FR+e.RL+e.RR;if(!(n>0))return{loads:{FL:0,FR:0,RL:0,RR:0},lifted:{FL:!0,FR:!0,RL:!0,RR:!0},overturned:!0};let o=!1,a=e.FL+e.FR,s=e.RL+e.RR;a<0?(a=0,s=n,o=!0):s<0&&(s=0,a=n,o=!0);let i=(e.FR-e.FL)*t+(e.RR-e.RL)*r,c=Math.min(a,Math.max(-a,e.FR-e.FL)),l=Math.min(s,Math.max(-s,e.RR-e.RL)),u=i-(c*t+l*r);if(u!==0){let f=u>0?1:-1,p=(f*a-c)*t;f*u>=f*p?(c=f*a,u-=p):(c+=u/t,u=0);let d=(f*s-l)*r;u!==0&&(f*u>=f*d?(l=f*s,u-=d):(l+=u/r,u=0)),Math.abs(u)>1e-9*(Math.abs(i)+n*(t+r))&&(o=!0)}let m={FL:Math.max(0,(a-c)/2),FR:Math.max(0,(a+c)/2),RL:Math.max(0,(s-l)/2),RR:Math.max(0,(s+l)/2)};return{loads:m,lifted:{FL:m.FL===0,FR:m.FR===0,RL:m.RL===0,RR:m.RR===0},overturned:o}}function Ce(e,t,r,n=0,o=0,a=0,s,i){return gl(e,t,r,n,o,a,s,i).loads}function gl(e,t,r,n=0,o=0,a=0,s,i){let c=Nn(e),l=we(e),u=rl(e,n,r,Jr(e,t,o),l),{cf:m,cr:f}=VR(e,l,u.height),p=m*t*Ss,d=f*t*Ss,h=e.massTotal*(r*Ss)*u.height/e.wheelbase-u.noseLoad,b=Jo(e,n,r,t,o),g=(i??Zo(e,a,l,s)).load,y={FL:c.FL-p-h/2+b.FL+g.FL,FR:c.FR+p-h/2+b.FR+g.FR,RL:c.RL-d+h/2+b.RL+g.RL,RR:c.RR+d+h/2+b.RR+g.RR};return BR(y,e.trackFront,e.trackRear)}var hf=Math.PI/180;function xl(e,t){let r=8*hf,n=0,o=0;for(let a=1;a<=90;a++){let s=a*.5,i=Math.abs(e.Fy(s*hf,t,0));if(i>n&&(n=i,r=s*hf,o=a),a>o+12&&i<.995*n)break}return{aPeak:r,fyPeak:n}}function $R(e,t,r,n,o){if(n===t)return r;let a=(o-t)/(n-t);return a<=0?e:a>=1?r:e+a*(r-e)}var Fs=.999;function St(e,t,r,n,o){if(t<=0)return 0;let{aPeak:a,fyPeak:s}=o??xl(e,t),i=Math.min(Math.abs(r),Fs*s),c=n?-1:1,l=(v,x)=>Math.abs(e.forces({Fz:t,kappa:c*v,alpha:x}).Fy),u=.3,m=u,f=l(u,a);if(f<i){let v=0,x=u,M=NaN,F=f;for(let w=0;w<9;w++){let C=.5*(v+x),T=l(C,a);T>=i?(v=C,M=T):(x=C,F=T)}Number.isNaN(M)&&(M=l(0,a)),m=M<i?0:$R(v,M,x,F,i)}if(m<=0)return 0;let p=v=>{if(i===0)return c*e.forces({Fz:t,kappa:c*v,alpha:0}).Fx;let x=0,M=a,F=NaN,w=NaN;for(let C=0;C<5;C++){let T=.5*(x+M),S=l(v,T);S<i?(x=T,F=S):(M=T,w=S)}return Number.isNaN(F)&&(F=l(v,0)),Number.isNaN(w)&&(w=l(v,a)),c*e.forces({Fz:t,kappa:c*v,alpha:$R(x,F,M,w,i)}).Fx},d=4,h=v=>m*v/d,b=[0],g=1;for(let v=1;v<=d;v++)b.push(p(h(v))),b[v]>b[g]&&(g=v);let[y,R]=g===d?[d-1,d-2]:b[g-1]>=b[g+1]?[g-1,g+1]:[g+1,g-1],k=kP(p,h(g-1),h(Math.min(d,g+1)),h(g),b[g],h(y),b[y],h(R),b[R],xP);return c*Math.max(0,k)}var xP=.01,RP=20,vP=(3-Math.sqrt(5))/2;function kP(e,t,r,n,o,a,s,i,c,l){o=-o,s=-s,c=-c;let u=r-t,m=0;for(let f=0;f<RP;f++){let p=l*Math.abs(n)+1e-10,d=.5*(t+r);if(Math.abs(n-d)<=2*p-.5*(r-t))break;let h=!0;if(Math.abs(u)>p){let y=(n-a)*(o-c),R=(n-i)*(o-s),k=(n-i)*R-(n-a)*y;R=2*(R-y),R>0&&(k=-k),R=Math.abs(R);let v=u;if(u=m,Math.abs(k)<Math.abs(.5*R*v)&&k>R*(t-n)&&k<R*(r-n)){m=k/R;let x=n+m;(x-t<2*p||r-x<2*p)&&(m=d>=n?p:-p),h=!1}}h&&(u=n>=d?t-n:r-n,m=vP*u);let b=Math.abs(m)>=p?n+m:n+(m>=0?p:-p),g=-e(b);g<=o?(b>=n?t=n:r=n,i=a,c=s,a=n,s=o,n=b,o=g):(b<n?t=b:r=b,g<=s||a===n?(i=a,c=s,a=b,s=g):(g<=c||i===n||i===a)&&(i=b,c=g))}return-o}function yf(e,t){return e.model?.kind==="simple"?null:HR(e,t)}var GR=new WeakMap,bf=100,KR=1.35,gf=18,or=41,yl=41,As=65;function HR(e,t){let r=GR.get(e);if(r)return r;let n=Math.log(KR),o=(p,d)=>{let h=M=>Math.abs(St(e,p,M,d)),b=h(0),g=t.muY(p)*p,y=new Float64Array(or),R=b>0&&g>0?Math.max(1,t.muX(p)*p/b):1;if(!(b>0)||!(g>0))y.fill(1);else{let M=[],F=[];for(let C=0;C<yl;C++){let T=Math.sin(.5*Math.PI*C/(yl-1));M.push(T),F.push(C===0?1:C===yl-1?0:Math.min(F[C-1],h(T*g)/b))}let w=yl-1;for(let C=0;C<or;C++){let T=C/(or-1);for(;w>0&&F[w-1]<T;)w--;let S=w>0?F[w-1]-F[w]:0;y[C]=w===0?M[0]:M[w]+(S>0?(T-F[w])/S:0)*(M[w-1]-M[w])}y[0]=1,y[or-1]=0}let k=new Float64Array(As),v=M=>Math.atan2(y[M],M/(or-1)/R),x=or-2;for(let M=0;M<As;M++){let F=.5*Math.PI*M/(As-1),w=Math.cos(F),C=Math.sin(F);for(;x>0&&v(x)<F;)x--;let T=x/(or-1)/R,S=y[x],A=(x+1)/(or-1)/R,P=y[x+1],L=w*(P-S)-C*(A-T),D=Math.abs(L)>1e-12?(T*(P-S)-S*(A-T))/L:Math.hypot(T,S);k[M]=D>0?D:Math.hypot(T,S)}return{room:y,scale:R,edge:k}},a=Array.from({length:gf},(p,d)=>bf*KR**d),s=a.map(p=>o(p,!1)),i=a.map(p=>o(p,!0)),c=(p,d)=>{let h=Math.min(1,Math.abs(d)*p.scale)*(or-1),b=Math.min(or-2,Math.floor(h));return p.room[b]+(h-b)*(p.room[b+1]-p.room[b])},l=p=>{let d=p>bf?Math.log(p/bf)/n:0;if(d>=gf-1)return[gf-2,1];let h=Math.floor(d);return[h,d-h]},u=(p,d,h)=>{if(h===0)return 1;let b=h<0?i:s,g=c(b[p],h);return d>0?g+d*(c(b[p+1],h)-g):g},m=(p,d,h)=>{let b=d<0?i:s,[g,y]=l(p),R=Math.atan2(Math.abs(h),Math.abs(d))/(.5*Math.PI)*(As-1),k=Math.min(As-2,Math.floor(R)),v=M=>M.edge[k]+(R-k)*(M.edge[k+1]-M.edge[k]),x=v(b[g]);return y>0?x+y*(v(b[g+1])-x):x},f={keeps(p,d){if(d===0)return 1;let[h,b]=l(p);return u(h,b,d)},atLoad(p){let[d,h]=l(p);return b=>u(d,h,b)},use(p,d,h){let b=Math.hypot(d,h);return b>0?Math.min(1,b/m(p,d,h)):0},reach:m};return GR.set(e,f),f}var MP=[["front","FL","FR"],["rear","RL","RR"]];function ea(e,t,r,n){let o={...e},a=0,s=Fs;for(let[i,c,l]of MP){let u=(k,v)=>n(i,Math.max(0,v[k])).fyPeak,m=Math.min(s,e[c]),f=Math.min(s,e[l]),p=m*u(c,r)+f*u(l,r);if(!(p>0))continue;let d=u(c,t),h=u(l,t),b=m*d+f*h,g=b>0?p/b:1/0,y=m*g,R=f*g;y<=s?R<=s||(R=s,y=d>0?(p-s*h)/d:1/0):(y=s,R=h>0?(p-s*d)/h:1/0),(!(y<=s)||!(R<=s))&&(a+=Math.max(0,p-s*(d+h)),y=Math.min(s,y),R=Math.min(s,R)),o[c]=y,o[l]=R}return{util:o,short:a}}var zR=.001,SP=1e-5,YR=100;function AP(e,t,r,n){if(!(n>zR))return r;let o=t,a=Math.abs(r-t)<YR?t+Math.sign(r-t)*YR:r;for(let s=0;s<60&&Math.abs(a-o)>SP;s++){let i=.5*(o+a);e(i)>zR?a=i:o=i}return o}function Rl(e,t,r){let n;return{at:o=>{if(n!==void 0)return r<0?Math.max(o,n):Math.min(o,n);if(!((o-t)*r>0))return o;let a=AP(e,t,o,e(o));return a!==o&&(n=a),a},edge:()=>n}}function vl(e,t){let r=n=>{try{return ye(e,0,n).ok}catch{return!1}};for(let n of[1,-1]){if(r(n*t))continue;let o=0;for(let a=1;a<=6;a++){let s=n*t*a/6;if(!r(s))break;o=Math.abs(s)}return{lock:t,reached:o,side:n}}return null}var xf=40;function kl(e){return{violation:Math.max(0,e.lock-e.reached),reason:`the steering reaches only ${e.reached.toFixed(0)} mm of the ${e.lock.toFixed(0)} mm rack travel${e.side<0?" (other side)":""}`}}var WR=[0,0,0];function FP(e,t){let r=q(H(e.rockerPivotB,e.rockerPivotA)),n=q(H(e.rockerToPushrod,e.pushrodOuter)),o=q(H(e.damperChassis,e.rockerToDamper)),a=Math.abs(X(r,ae(H(e.rockerToPushrod,e.rockerPivotA),n))),s=Math.abs(X(r,ae(H(e.rockerToDamper,e.rockerPivotA),o)));return s<1e-9?0:t*a/s}function Ml(e,t,r){if(e.mcpherson)return wP(e,t,r);let n=[{r:e.uprightUpper,c:e.ucaFront},{r:e.uprightUpper,c:e.ucaRear},{r:e.uprightLower,c:e.lcaFront},{r:e.uprightLower,c:e.lcaRear},{r:e.tieOuter,c:e.tieInner},{r:e.pushrodOuter,c:e.direct?e.damperChassis:e.rockerToPushrod}],o=e.wheelCenter,a=[[],[],[],[],[],[]];for(let m=0;m<6;m++){let f=q(H(n[m].c,n[m].r)),p=ae(H(n[m].r,o),f);a[0][m]=f[0],a[1][m]=f[1],a[2][m]=f[2],a[3][m]=p[0],a[4][m]=p[1],a[5][m]=p[2]}let s=ae(H(e.contactPatch,o),t),i=r??WR,c=[-t[0],-t[1],-t[2],-(s[0]+i[0]),-(s[1]+i[1]),-(s[2]+i[2])],l=Jt(a,c),u=l.x;return{ucaFront:u[0],ucaRear:u[1],lcaFront:u[2],lcaRear:u[3],tieRod:u[4],pushRod:u[5],damper:l.singular||e.decoupled?NaN:e.direct?u[5]:FP(e,u[5]),condProxy:l.condProxy,singular:l.singular}}function wP(e,t,r){let n=e.wheelCenter,o=e.damperChassis,a=[{at:e.uprightLower,dir:q(H(e.lcaFront,e.uprightLower))},{at:e.uprightLower,dir:q(H(e.lcaRear,e.uprightLower))},{at:e.tieOuter,dir:q(H(e.tieInner,e.tieOuter))},{at:o,dir:[1,0,0]},{at:o,dir:[0,1,0]},{at:o,dir:[0,0,1]}],s=[[],[],[],[],[],[]];for(let b=0;b<6;b++){let g=a[b].dir,y=ae(H(a[b].at,n),g);s[0][b]=g[0],s[1][b]=g[1],s[2][b]=g[2],s[3][b]=y[0],s[4][b]=y[1],s[5][b]=y[2]}let i=ae(H(e.contactPatch,n),t),c=r??WR,l=[-t[0],-t[1],-t[2],-(i[0]+c[0]),-(i[1]+c[1]),-(i[2]+c[2])],u=Jt(s,l),m=u.x,f=[m[3],m[4],m[5]],p=q(H(o,e.pushrodOuter)),d=X(f,p),h=Math.hypot(f[0]-d*p[0],f[1]-d*p[1],f[2]-d*p[2]);return{ucaFront:NaN,ucaRear:NaN,lcaFront:m[0],lcaRear:m[1],tieRod:m[2],pushRod:u.singular?NaN:d,damper:u.singular?NaN:d,condProxy:u.condProxy,singular:u.singular,strutSide:u.singular?NaN:h,topMount:f}}function Rf(e,t){let r=q(e.spinAxis),n=ae(H(e.contactPatch,e.wheelCenter),t),o=X(n,r);return[-o*r[0],-o*r[1],-o*r[2]]}var CP=[0,0,0];function ws(e,t,r,n){let o=e.direct?e.damperChassis:e.rockerToPushrod;if(e.mcpherson)return{...Ml(e,r,n),armResidual:0};if(t==="upright")return{...Ml(e,r,n),armResidual:0};let a=t==="lowerArm",s=a?{bj:e.uprightUpper,front:e.ucaFront,rear:e.ucaRear}:{bj:e.uprightLower,front:e.lcaFront,rear:e.lcaRear},i=a?{bj:e.uprightLower,front:e.lcaFront,rear:e.lcaRear}:{bj:e.uprightUpper,front:e.ucaFront,rear:e.ucaRear},c=e.wheelCenter,l=q(H(s.front,s.bj)),u=q(H(s.rear,s.bj)),m=q(H(e.tieInner,e.tieOuter)),f=[{at:s.bj,dir:l},{at:s.bj,dir:u},{at:e.tieOuter,dir:m},{at:i.bj,dir:[1,0,0]},{at:i.bj,dir:[0,1,0]},{at:i.bj,dir:[0,0,1]}],p=[[],[],[],[],[],[]];for(let Z=0;Z<6;Z++){let ne=f[Z].dir,te=ae(H(f[Z].at,c),ne);p[0][Z]=ne[0],p[1][Z]=ne[1],p[2][Z]=ne[2],p[3][Z]=te[0],p[4][Z]=te[1],p[5][Z]=te[2]}let d=ae(H(e.contactPatch,c),r),h=n??CP,b=[-r[0],-r[1],-r[2],-(d[0]+h[0]),-(d[1]+h[1]),-(d[2]+h[2])],g=Jt(p,b),y=g.singular,R=g.x,k=R[0],v=R[1],x=R[2],M=[R[3],R[4],R[5]],F=q(H(i.rear,i.front)),w=q(H(o,e.pushrodOuter)),C=U(M,-1),T=(Z,ne)=>X(F,ae(H(Z,i.front),ne)),S=T(e.pushrodOuter,w),A=Math.abs(S)>1e-9?-T(i.bj,C)/S:NaN,P=ee(C,U(w,A)),L=U(P,-1),D=q(H(i.front,i.bj)),E=q(H(i.rear,i.bj)),V=X(D,D),N=X(D,E),z=X(E,E),I=X(D,L),_=X(E,L),B=V*z-N*N,O=NaN,G=NaN,K=NaN;if(Math.abs(B)>1e-12){O=(I*z-_*N)/B,G=(V*_-N*I)/B;let Z=ee(U(D,O),U(E,G)),ne=H(L,Z);K=Math.hypot(ne[0],ne[1],ne[2])}let Y=a?{f:k,r:v}:{f:O,r:G},j=a?{f:O,r:G}:{f:k,r:v};return{ucaFront:Y.f,ucaRear:Y.r,lcaFront:j.f,lcaRear:j.r,tieRod:x,pushRod:A,damper:y||!Number.isFinite(A)||e.decoupled?NaN:e.direct?A:TP(e,A),condProxy:g.condProxy,singular:y,armResidual:K}}function TP(e,t){let r=q(H(e.rockerPivotB,e.rockerPivotA)),n=q(H(e.rockerToPushrod,e.pushrodOuter)),o=q(H(e.damperChassis,e.rockerToDamper)),a=Math.abs(X(r,ae(H(e.rockerToPushrod,e.rockerPivotA),n))),s=Math.abs(X(r,ae(H(e.rockerToDamper,e.rockerPivotA),o)));return s<1e-9?0:t*a/s}var t4=Math.PI/180;function Cs(e,t){let r=Math.min(Math.max(t,e.range[0]),e.range[1])-e.reference;return Math.max(.2,1+e.perDegC*r+e.perDegC2*r*r)}var UR=["QSX3","QSX8","QSX13","QSX14"],PP=["QSX1"],Sl=["PHY1","PHY2","PHY3","PKY6","PKY7","PVY1","PVY2","PVY3","PVY4","PEY3","PEY4","QHZ1","QHZ2","QHZ3","QHZ4","QEZ4","QEZ5","QDZ6","QDZ7","QDZ8","QDZ9","QDZ10","QDZ11","SSZ1","SSZ3","SSZ4","RBY3","RHX1","RVY1","RVY2","RVY3",...UR];function LP(e){let t=["PKY6","PKY7","PVY3","PVY4","PHY3","PEY4","RVY3","QHZ3","QHZ4","QEZ5","QDZ8","QDZ9","QDZ10","QDZ11","SSZ3","SSZ4"];return e==="5.2"?[...t,"QBZ4","QDZ3"]:t}function DP(e){let t=new Set(LP(e)),r=Sl.filter(n=>!UR.includes(n));return[...r.filter(n=>!t.has(n)),...[...t].filter(n=>!r.includes(n)),...PP]}function EP(e,t){let r={...e};for(let n of t)r[n]!==void 0&&r[n]!==0&&(r[n]=-r[n]);return r}var Mr=(e,t,r)=>Number.isFinite(e[t])?e[t]:r;function XR(e,t){return t!=="5.2"?Mr(e,"PKY6",0)*Mr(e,"LKYC",1):Mr(e,"PKY1",-15)*Math.sin(Mr(e,"PKY4",2)*Math.atan(1/Mr(e,"PKY2",2)))*Mr(e,"LKY",1)*Mr(e,"PHY3",0)+Mr(e,"PVY3",0)*Mr(e,"LMUY",1)}var jR=.1;function qR(e){if(e.fitData)return"sae";let t=XR(e.coeffs,e.version);return t>jR?"sae":t<-jR?"iso":null}function Ts(e){return e.axisSystem??qR(e)??"sae"}function Al(e){let t=new Set,r=n=>{for(let o of n)t.has(o)?t.delete(o):t.add(o)};return Ts(e)==="iso"&&r(Sl),e.axisSystem&&e.side==="left"&&r(DP(e.version)),t.size?EP(e.coeffs,t):e.coeffs}var n4=Math.PI/180;var $=(e,t)=>Number.isFinite(e)?e:t;function ZR(e){let t=Al(e);return{PCX1:$(t.PCX1,1.65),PDX1:$(t.PDX1,1),PDX2:$(t.PDX2,0),PDX3:$(t.PDX3,0),PEX1:$(t.PEX1,0),PEX2:$(t.PEX2,0),PEX3:$(t.PEX3,0),PEX4:$(t.PEX4,0),PHX1:$(t.PHX1,0),PHX2:$(t.PHX2,0),PKX1:$(t.PKX1,20),PKX2:$(t.PKX2,0),PKX3:$(t.PKX3,0),PPX1:$(t.PPX1,0),PPX2:$(t.PPX2,0),PPX3:$(t.PPX3,0),PPX4:$(t.PPX4,0),PVX1:$(t.PVX1,0),PVX2:$(t.PVX2,0),PCY1:$(t.PCY1,1.3),PDY1:$(t.PDY1,1),PDY2:$(t.PDY2,0),PDY3:$(t.PDY3,0),PEY1:$(t.PEY1,0),PEY2:$(t.PEY2,0),PEY3:$(t.PEY3,0),PEY4:$(t.PEY4,0),PEY5:$(t.PEY5,0),PHY1:$(t.PHY1,0),PHY2:$(t.PHY2,0),PHY3:$(t.PHY3,0),PKY1:$(t.PKY1,-15),PKY2:$(t.PKY2,2),PKY3:$(t.PKY3,0),PKY4:$(t.PKY4,2),PKY5:$(t.PKY5,0),PKY6:$(t.PKY6,0),PKY7:$(t.PKY7,0),PPY1:$(t.PPY1,0),PPY2:$(t.PPY2,0),PPY3:$(t.PPY3,0),PPY4:$(t.PPY4,0),PPY5:$(t.PPY5,0),PVY1:$(t.PVY1,0),PVY2:$(t.PVY2,0),PVY3:$(t.PVY3,0),PVY4:$(t.PVY4,0),RBX1:$(t.RBX1,0),RBX2:$(t.RBX2,0),RBX3:$(t.RBX3,0),RBY1:$(t.RBY1,0),RBY2:$(t.RBY2,0),RBY3:$(t.RBY3,0),RBY4:$(t.RBY4,0),RCX1:$(t.RCX1,1),RCY1:$(t.RCY1,1),REX1:$(t.REX1,0),REX2:$(t.REX2,0),REY1:$(t.REY1,0),REY2:$(t.REY2,0),RHX1:$(t.RHX1,0),RHY1:$(t.RHY1,0),RHY2:$(t.RHY2,0),RVY1:$(t.RVY1,0),RVY2:$(t.RVY2,0),RVY3:$(t.RVY3,0),RVY4:$(t.RVY4,0),RVY5:$(t.RVY5,1),RVY6:$(t.RVY6,0),PPZ1:$(t.PPZ1,0),PPZ2:$(t.PPZ2,0),QBZ1:$(t.QBZ1,8),QBZ2:$(t.QBZ2,0),QBZ3:$(t.QBZ3,0),QBZ4:$(t.QBZ4,0),QBZ5:$(t.QBZ5,0),QBZ6:$(t.QBZ6,0),QBZ9:$(t.QBZ9,0),QBZ10:$(t.QBZ10,0),QCZ1:$(t.QCZ1,1.1),QDZ1:$(t.QDZ1,.1),QDZ2:$(t.QDZ2,0),QDZ3:$(t.QDZ3,0),QDZ4:$(t.QDZ4,0),QDZ6:$(t.QDZ6,0),QDZ7:$(t.QDZ7,0),QDZ8:$(t.QDZ8,0),QDZ9:$(t.QDZ9,0),QDZ10:$(t.QDZ10,0),QDZ11:$(t.QDZ11,0),QEZ1:$(t.QEZ1,0),QEZ2:$(t.QEZ2,0),QEZ3:$(t.QEZ3,0),QEZ4:$(t.QEZ4,0),QEZ5:$(t.QEZ5,0),QHZ1:$(t.QHZ1,0),QHZ2:$(t.QHZ2,0),QHZ3:$(t.QHZ3,0),QHZ4:$(t.QHZ4,0),SSZ1:$(t.SSZ1,0),SSZ2:$(t.SSZ2,0),SSZ3:$(t.SSZ3,0),SSZ4:$(t.SSZ4,0),QSX1:$(t.QSX1,0),QSX2:$(t.QSX2,0),QSX3:$(t.QSX3,0),QSX4:$(t.QSX4,0),QSX5:$(t.QSX5,0),QSX6:$(t.QSX6,0),QSX7:$(t.QSX7,0),QSX8:$(t.QSX8,0),QSX9:$(t.QSX9,0),QSX10:$(t.QSX10,0),QSX11:$(t.QSX11,0),QSX12:$(t.QSX12,0),QSX13:$(t.QSX13,0),QSX14:$(t.QSX14,0),PPMX1:$(t.PPMX1,0),QSY1:$(t.QSY1,0),QSY2:$(t.QSY2,0),QSY3:$(t.QSY3,0),QSY4:$(t.QSY4,0),QSY5:$(t.QSY5,0),QSY6:$(t.QSY6,0),QSY7:$(t.QSY7,0),QSY8:$(t.QSY8,0),LONGVL:t.LONGVL!==void 0&&t.LONGVL>0?t.LONGVL:16.7,LCX:$(t.LCX,1),LCY:$(t.LCY,1),LEX:$(t.LEX,1),LEY:$(t.LEY,1),LFZO:$(t.LFZO,1),LHX:$(t.LHX,1),LHY:$(t.LHY,1),LKX:$(t.LKX,1),LKY:$(t.LKY,1),LKYC:$(t.LKYC,1),LKZC:$(t.LKZC,1),LMUX:$(t.LMUX,1),LMUY:$(t.LMUY,1),LMX:$(t.LMX,1),LMY:$(t.LMY,1),LVMX:$(t.LVMX,1),LRES:$(t.LRES,1),LS:$(t.LS,1),LTR:$(t.LTR,1),LVX:$(t.LVX,1),LVY:$(t.LVY,1),LVYKA:$(t.LVYKA,1),LXAL:$(t.LXAL,1),LYKA:$(t.LYKA,1)}}var QR=new WeakMap;function Ps(e){let t=QR.get(e);return t===void 0&&(t=ZR(e),QR.set(e,t)),t}var JR=e=>e>=0?1:-1;function Fl(e,t,r=0,n){let o=Ps(e),a=Math.max(1,t),s=r,i=o.LFZO*e.fnomin,c=(a-i)/i,l=e.nomPressure>0&&n?(n-e.nomPressure)/e.nomPressure:0,u=e.unloadedR0,m=(o.PDY1+o.PDY2*c)*(1+o.PPY3*l+o.PPY4*l*l)*(1-o.PDY3*s*s)*o.LMUY,f=o.PCY1*o.LCY,p=m*a,d=o.PKY1*i*(1+o.PPY1*l)*Math.sin(o.PKY4*Math.atan(a/((o.PKY2+o.PKY5*s*s)*(1+o.PPY2*l)*i)))*(1-o.PKY3*Math.abs(s))*o.LKY,h=e.version!=="5.2",b=a*(o.PKY6+o.PKY7*c)*(1+o.PPY5*l)*o.LKYC,g=a*(o.PVY3+o.PVY4*c)*s*o.LKYC*o.LMUY,y=Math.abs(d)>1e-6?d:1e-6*(d<0?-1:1),R=h?(o.PHY1+o.PHY2*c)*o.LHY+(b*s-g)/y:(o.PHY1+o.PHY2*c)*o.LHY+o.PHY3*s,k=h?a*(o.PVY1+o.PVY2*c)*o.LVY*o.LMUY+g:a*((o.PVY1+o.PVY2*c)*o.LVY+(o.PVY3+o.PVY4*c)*s)*o.LMUY,v=f*p!==0?d/(f*p):0;return{Fz:a,g:s,dfz:c,dpi:l,Fz0p:i,R0:u,Cy:f,Dy:p,By:v,SHy:R,SVy:k,Kya:d,muy:m,EyA:o.PEY1+o.PEY2*c,EyG:1+o.PEY5*s*s,EyS:o.PEY3+o.PEY4*s,LEY:o.LEY}}function wl(e,t,r=0,n){let o=Fl(e,t,r,n),a=Ps(e),{Fz:s,g:i,dfz:c,dpi:l,Fz0p:u,R0:m,muy:f,Kya:p,SVy:d,By:h,Cy:b,Dy:g,SHy:y}=o,R=(a.PHX1+a.PHX2*c)*a.LHX,k=(a.PDX1+a.PDX2*c)*(1+a.PPX3*l+a.PPX4*l*l)*(1-a.PDX3*i*i)*a.LMUX,v=a.PCX1*a.LCX,x=k*s,M=s*(a.PKX1+a.PKX2*c)*Math.exp(a.PKX3*c)*(1+a.PPX1*l+a.PPX2*l*l)*a.LKX,F=v*x!==0?M/(v*x):0,w=Math.abs(p)>1e-6?p:1e-6*(p<0?-1:1),C=e.version!=="5.2",T=s*(a.PVX1+a.PVX2*c)*a.LVX*a.LMUX,S=a.REX1+a.REX2*c;S>1&&(S=1);let A=a.REY1+a.REY2*c;return A>1&&(A=1),{Fz:s,g:i,dfz:c,dpi:l,Fz0p:u,R0:m,Cy:b,Dy:g,By:h,SHy:y,SVy:d,Kya:p,muy:f,EyA:o.EyA,EyG:o.EyG,EyS:o.EyS,LEY:o.LEY,SHx:R,Cx:v,Dx:x,Bx:F,SVx:T,ExA:a.PEX1+a.PEX2*c+a.PEX3*c*c,PEX4:a.PEX4,LEX:a.LEX,SHxa:a.RHX1,Bxa0:a.RBX1+a.RBX3*i*i,RBX2:a.RBX2,LXAL:a.LXAL,Cxa:a.RCX1,Exa:S,SHyk:a.RHY1+a.RHY2*c,Byk0:a.RBY1+a.RBY4*i*i,RBY2:a.RBY2,RBY3:a.RBY3,LYKA:a.LYKA,Cyk:a.RCY1,Eyk:A,DVykA:f*s*(a.RVY1+a.RVY2*c+a.RVY3*i),RVY4:a.RVY4,RVY5:a.RVY5,RVY6:a.RVY6,LVYKA:a.LVYKA,SHt:a.QHZ1+a.QHZ2*c+(a.QHZ3+a.QHZ4*c)*i,Bt:C?(a.QBZ1+a.QBZ2*c+a.QBZ3*c*c)*(1+a.QBZ5*Math.abs(i)+a.QBZ6*i*i)*(a.LKY/a.LMUY):(a.QBZ1+a.QBZ2*c+a.QBZ3*c*c)*(1+a.QBZ4*i+a.QBZ5*Math.abs(i))*(a.LKY/a.LMUY),Ct:a.QCZ1,Dt:C?s*(m/u)*(a.QDZ1+a.QDZ2*c)*(1-a.PPZ1*l)*(1+a.QDZ3*Math.abs(i)+a.QDZ4*i*i)*a.LTR:s*(m/u)*(a.QDZ1+a.QDZ2*c)*(1-a.PPZ1*l)*(1+a.QDZ3*i+a.QDZ4*i*i)*a.LTR,EtA:a.QEZ1+a.QEZ2*c+a.QEZ3*c*c,EtG:a.QEZ4+a.QEZ5*i,Br:a.QBZ9*(a.LKY/a.LMUY)+a.QBZ10*h*b,Dr:C?s*m*((a.QDZ6+a.QDZ7*c)*a.LRES+((a.QDZ8+a.QDZ9*c)*(1+a.PPZ2*l)+(a.QDZ10+a.QDZ11*c)*Math.abs(i))*i*a.LKZC)*a.LMUY:s*m*((a.QDZ6+a.QDZ7*c)*a.LRES+(a.QDZ8+a.QDZ9*c)*(1+a.PPZ2*l)*i)*a.LMUY,arOff:p!==0?d/p:0,sixOne:C,kk:M/w*(M/w),sS0:m*(a.SSZ1+(a.SSZ3+a.SSZ4*c)*i)*a.LS,sS2:m*a.SSZ2*a.LS/u}}function Ls(e,t){let r=t+e.SHy,n=e.EyA*(e.EyG-e.EyS*JR(r))*e.LEY;n>1&&(n=1);let o=e.By*r;return e.Dy*Math.sin(e.Cy*Math.atan(o-n*(o-Math.atan(o))))+e.SVy}function Cl(e,t){let r=t+e.SHx,n=e.ExA*(1-e.PEX4*JR(r))*e.LEX;n>1&&(n=1);let o=e.Bx*r;return e.Dx*Math.sin(e.Cx*Math.atan(o-n*(o-Math.atan(o))))+e.SVx}function ev(e,t,r){if(r===0)return t;if(e.sixOne)return Math.sqrt(t*t+e.kk*r*r)*Math.sign(t);let n=Math.tan(t);return Math.atan(Math.sqrt(n*n+e.kk*r*r))*Math.sign(t)}function IP(e,t,r,n){let o=t+e.SHt,a=e.EtA*(1+e.EtG*(2/Math.PI)*Math.atan(e.Bt*e.Ct*o));a>1&&(a=1);let s=ev(e,o,r),i=e.Bt*s;return e.Dt*Math.cos(e.Ct*Math.atan(i-a*(i-Math.atan(i))))*n}function _P(e,t,r,n){return e.Dr*Math.cos(Math.atan(e.Br*ev(e,t+e.SHy+e.arOff,r)))*n}function tv(e,t,r,n,o,a){let s=Math.cos(t),i=IP(e,t,r,s),c=_P(e,t,r,s);return-i*(o-a)+c+(e.sS0+e.sS2*o)*n}function rv(e,t,r){let n=e.Bxa0*Math.cos(Math.atan(e.RBX2*t))*e.LXAL,o=r+e.SHxa,a=Math.cos(e.Cxa*Math.atan(n*e.SHxa-e.Exa*(n*e.SHxa-Math.atan(n*e.SHxa))))||1;return Math.cos(e.Cxa*Math.atan(n*o-e.Exa*(n*o-Math.atan(n*o))))/a*Cl(e,t)}function vf(e,t){let r=e.sS0===0&&e.sS2===0?0:rv(e,0,t);return tv(e,t,0,r,Ls(e,t),0)}function Tl(e,t,r){let n=Ls(e,r),o=rv(e,t,r),a=e.Byk0*Math.cos(Math.atan(e.RBY2*(r-e.RBY3)))*e.LYKA,s=t+e.SHyk,i=Math.cos(e.Cyk*Math.atan(a*e.SHyk-e.Eyk*(a*e.SHyk-Math.atan(a*e.SHyk))))||1,c=Math.cos(e.Cyk*Math.atan(a*s-e.Eyk*(a*s-Math.atan(a*s))))/i,u=e.DVykA*Math.cos(Math.atan(e.RVY4*r))*Math.sin(e.RVY5*Math.atan(e.RVY6*t))*e.LVYKA,m=c*n+u;return{Fx:o,Fy:m,Mz:tv(e,r,t,o,m,u)}}var Ds=(e,t)=>Math.max(.1,e.muY0+e.loadSensY*(t-e.nominalLoad)),Es=(e,t)=>Math.max(.1,e.muX0+e.loadSensX*(t-e.nominalLoad)),nv=(e,t,r)=>Ds(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cy*Math.atan(e.By*r)),ov=(e,t,r)=>Es(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cx*Math.atan(e.Bx*r));function kf(e,t){let r=Math.max(1,t.Fz),n=Ds(e,r)*r,o=Es(e,r)*r,a=n*Math.sin(e.Cy*Math.atan(e.By*t.alpha)),s=o*Math.sin(e.Cx*Math.atan(e.Bx*t.kappa)),i=Math.hypot(o>0?s/o:0,n>0?a/n:0);return i>1&&(s/=i,a/=i),{Fx:s,Fy:a,Mz:0}}var ta=Math.PI/180;function sn(e){if(e.kind==="simple")return"none";let t=e.missing?.some(n=>/^aligning moment Mz\b/i.test(n))??!1,r=["QBZ1","QCZ1","QDZ1"].every(n=>Number.isFinite(e.coeffs[n]));return t||!r?"assumed":"model"}function av(e){let t=e.thermal?.operating;if(t===void 0||!e.thermal)return e;let{lateral:r,longitudinal:n,aligning:o}=e.thermal,a=r?Cs(r,t):1,s=n?Cs(n,t):1,i=o?Cs(o,t):1;if(a===1&&s===1&&i===1)return e;if(e.kind==="simple")return{...e,muY0:e.muY0*a,muX0:e.muX0*s};let c={...e.coeffs},l=(u,m)=>{c[u]=(c[u]??1)*m};return l("LMUY",a),l("LMUX",s),l("LTR",i),l("LRES",i),{...e,coeffs:c}}function ra(e,t,r){let n=0,o=0;for(let s=r;s<=t;s+=r){let i=Math.abs(e(s));i>o&&(o=i,n=s)}let a=r/10;for(let s=Math.max(a,n-r);s<=n+r;s+=a)o=Math.max(o,Math.abs(e(s)));return o}function Pe(e){let t=av(e),r=t,n=t,o=null,a=NaN,s=NaN,i=NaN,c=(v,x,M)=>(o!==null&&v===a&&x===s&&M===i||(o=wl(r,v,x,M),a=v,s=x,i=M),o),l=null,u=NaN,m=NaN,f=NaN,p=(v,x,M)=>(l!==null&&v===u&&x===m&&M===f||(l=Fl(r,v,x,M),u=v,m=x,f=M),l),d=v=>e.kind==="magic"?Tl(c(v.Fz,v.gamma??0,v.p),v.kappa,v.alpha):kf(n,v),h=(v,x,M=0,F)=>e.kind==="magic"?Ls(p(x,M,F),v):nv(n,x,v),b=(v,x,M=0,F)=>e.kind==="magic"?Cl(c(x,M,F),v):ov(n,x,v),g=(v,x,M=0,F)=>e.kind==="magic"?vf(c(x,M,F),v):d({Fz:x,kappa:0,alpha:v,gamma:M,p:F}).Mz,y=v=>e.kind==="simple"?Ds(n,v):ra(x=>h(x*ta,v),45,1)/Math.max(1,v),R=v=>e.kind==="simple"?Es(n,v):ra(x=>b(x,v),.6,.02)/Math.max(1,v),k=v=>{let x=.1*ta;return Math.abs((h(x,v)-h(-x,v))/(2*x))};return{model:e,forces:d,Fx:b,Fy:h,Mz:g,muX:R,muY:y,corneringStiffness:k,verticalStiffness:()=>e.verticalStiffness,rollingRadius:v=>{if(e.kind==="magic"&&e.missing?.includes("UNLOADED_RADIUS"))return 0;let x=e.unloadedR0??0;if(!(x>0))return 0;let M=e.verticalStiffness*1e3;if(!(M>0))return x;let F=e.rollingFraction??.306;return x-F*Math.max(0,v)/M},relaxationLength:v=>{let x=e.relaxation;if(!x)return 0;let M=x.carcassStiffness??0;if(!(M>0))return x.sigma;let F=k(Math.max(0,v));return F>0?F/(M*1e3):x.sigma}}}function na(e){let t=Math.max(1,e.model.kind==="magic"?e.model.fnomin:e.model.nominalLoad);return e.Fy(2*ta,t,0)-e.Fy(-2*ta,t,0)>=0?1:-1}function Is(e,t=e.kind==="magic"?e.fnomin:e.nominalLoad){let r=Pe(e),n=2*ta,o=3*ta,a=r.Fy(n,t,0),s=r.Fy(n,t,o);return!Number.isFinite(a)||!Number.isFinite(s)?!1:Math.abs(s-a)>1}var NP=Math.PI/180;function ge(e,t){return e.axle?e.axle(t):e}function Ll(e,t){if(e===t)return e;let r=na(e)*na(t),n=(l,u)=>.5*(l+u),o=(l,u)=>l>0&&u>0?n(l,u):l>0?l:u>0?u:0,a=l=>{let u=e.forces(l),m=t.forces(l);return{Fx:n(u.Fx,m.Fx),Fy:n(u.Fy,r*m.Fy),Mz:n(u.Mz,r*m.Mz)}},s=(l,u,m=0,f)=>n(e.Fx(l,u,m,f),t.Fx(l,u,m,f)),i=(l,u,m=0,f)=>n(e.Fy(l,u,m,f),r*t.Fy(l,u,m,f)),c=(l,u,m=0,f)=>n(e.Mz(l,u,m,f),r*t.Mz(l,u,m,f));return{model:e.model,forces:a,Fx:s,Fy:i,Mz:c,muX:l=>ra(u=>s(u,l),.6,.02)/Math.max(1,l),muY:l=>ra(u=>i(u*NP,l),45,1)/Math.max(1,l),corneringStiffness:l=>n(e.corneringStiffness(l),t.corneringStiffness(l)),verticalStiffness:()=>o(e.verticalStiffness(),t.verticalStiffness()),rollingRadius:l=>o(e.rollingRadius(l),t.rollingRadius(l)),relaxationLength:l=>o(e.relaxationLength(l),t.relaxationLength(l)),axle:l=>l==="front"?e:t}}function ut(e){if(sv.has(e))return e;let t=iv.get(e);if(t)return t;let r;if(e.axle){let n=e.axle("front"),o=e.axle("rear"),a=ut(n),s=ut(o);r=a===n&&s===o?e:Ll(a,s)}else na(e)>0?r=e:r={...e,forces:n=>{let o=e.forces(n);return{Fx:o.Fx,Fy:-o.Fy,Mz:-o.Mz}},Fy:(n,o,a,s)=>-e.Fy(n,o,a,s),Mz:(n,o,a,s)=>-e.Mz(n,o,a,s)};return sv.add(r),r!==e&&iv.set(e,r),r}var sv=new WeakSet,iv=new WeakMap;var Dl=25*(Math.PI/180);function OP(e){let t=.6180339887,r=0,n=Dl,o=n-t*(n-r),a=r+t*(n-r),s=e(o),i=e(a);for(let l=0;l<12;l++)s>i?(n=a,a=o,i=s,o=n-t*(n-r),s=e(o)):(r=o,o=a,s=i,a=r+t*(n-r),i=e(a));return{alpha:s>i?o:a,force:Math.max(s,i)}}function _s(e,t,r,n,o=0){let a=Math.abs(t);if(!(a>0))return 0;let s=u=>Math.abs(e.Fy(u,r,0))+Math.abs(e.Fy(u,n,0)),i=0,c=Dl;if(s(Dl)<=a){let u=OP(s);if(u.force<=a)return u.alpha;c=u.alpha}else if(o>0){let u=Math.max(0,o*.6),m=Math.min(Dl,o*1.6+.001);s(u)<a&&s(m)>=a&&(i=u,c=m)}let l=.001*a;for(let u=0;u<12;u++){let m=.5*(i+c),f=s(m)-a;if(f<0?i=m:c=m,Math.abs(f)<=l)return m}return c}var Mf={shaft:!1,trail:0,hub:[0,0,0]};function lv(e){let t=e.spinAxis,r=Math.hypot(t[0],t[1]);if(r<1e-9)return[1,0,0];let n=[-t[1]/r,t[0]/r,0];return n[0]<0?[-n[0],-n[1],0]:n}function Sf(e,t,r){let n=r.shaft?Rf(e,t):[0,0,0];if(r.trail!==0){let a=lv(e),s=[t[0],t[1],0],i=H(s,U(a,X(s,a)));n=ee(n,ae(U(a,-r.trail),i))}let o=r.hub;return(o[0]!==0||o[1]!==0||o[2]!==0)&&(n=H(n,ae(H(e.contactPatch,e.wheelCenter),o))),{force:ee(t,o),moment:n}}var VP=(e,t)=>{let r=e!==void 0&&e>0?1/e:0,n=t!==void 0&&t>0?1/t:0;return r+n},El={ucaFront:0,ucaRear:0,lcaFront:0,lcaRear:0,tieRod:0,pushRod:0,rack:0};function On(e){return!e.measured}function Vn(e){if(!e)return!1;let t=r=>!!r&&Object.values(r).some(n=>n!==void 0&&n>0&&Number.isFinite(n));return t(e.links)||t(e.bushings)||e.rack!==void 0&&e.rack>0}function Ns(e,t){let r=e.corner.hardpoints,n=us(e.rocker,t.points.rockerAngle);return{ucaFront:r.ucaFront,ucaRear:r.ucaRear,lcaFront:r.lcaFront,lcaRear:r.lcaRear,tieInner:Go(e.inv,t.steer),rockerPivotA:r.rockerPivotA,rockerPivotB:r.rockerPivotB,damperChassis:e.inv.strut?t.points.uprightUpper:r.damperChassis,uprightUpper:t.points.uprightUpper,uprightLower:t.points.uprightLower,tieOuter:t.points.tieOuter,wheelCenter:t.points.wheelCenter,pushrodOuter:t.points.pushrodOuter,contactPatch:t.points.contactPatch,kingpinGround:t.points.kingpinGround,kingpinAtHub:t.points.kingpinAtHub,rockerToPushrod:n.pushrod,rockerToDamper:n.damper,spinAxis:t.points.spinAxis,direct:e.corner.config.actuation==="direct",decoupled:e.corner.config.actuation==="decoupled",mcpherson:e.inv.strut!==void 0,loadedRadius:e.corner.config.loadedRadius,tyreDeflection:0,load:NaN,lifted:!1,clearance:0,contactLength:0}}function Af(e,t,r=0){let n=t.links??{},o=t.bushings??{},a=(l,u,m)=>{let f=VP(u,m);return f>0&&Number.isFinite(l)?l*f:0},s=o.topMount,i=e.topMount,c=i&&s!==void 0&&s>0&&i.every(Number.isFinite)?[-i[0]/s,-i[1]/s,-i[2]/s]:void 0;return{...c?{topMount:c}:{},ucaFront:a(e.ucaFront,n.ucaFront,o.ucaFront),ucaRear:a(e.ucaRear,n.ucaRear,o.ucaRear),lcaFront:a(e.lcaFront,n.lcaFront,o.lcaFront),lcaRear:a(e.lcaRear,n.lcaRear,o.lcaRear),tieRod:a(e.tieRod,n.tieRod,o.tieInner),pushRod:a(e.pushRod,n.pushRod,void 0),rack:r}}function uv(e,t,r,n){let o=ve(e,t);if(!(o>1e-9))return{axial:r,radius2:0};let a=(r*r-n*n+o*o)/(2*o);return{axial:a,radius2:Math.max(0,r*r-a*a)}}function Os(e,t){let r=e.corner.hardpoints,n=e.inv,o={...n};if(n.strut&&t.topMount&&t.topMount.some(i=>i!==0)&&(o.strut={...n.strut,top:ee(n.strut.top,t.topMount)}),t.ucaFront!==0||t.ucaRear!==0){let i=uv(r.ucaFront,r.ucaRear,ve(r.uprightUpper,r.ucaFront)+t.ucaFront,ve(r.uprightUpper,r.ucaRear)+t.ucaRear);o.ubjAxial0=i.axial,o.ubjRadius2=i.radius2}if(t.lcaFront!==0||t.lcaRear!==0){let i=uv(r.lcaFront,r.lcaRear,ve(r.uprightLower,r.lcaFront)+t.lcaFront,ve(r.uprightLower,r.lcaRear)+t.lcaRear),c=X(n.lbjRel0,n.lcaDir),l=H(n.lbjRel0,U(n.lcaDir,c)),u=Math.hypot(l[0],l[1],l[2]);o.lbjRel0=u>1e-9?ee(U(n.lcaDir,i.axial),U(l,Math.sqrt(i.radius2)/u)):ee(U(n.lcaDir,i.axial),l)}if(t.tieRod!==0){let i=Math.sqrt(n.tieLen2)+t.tieRod;o.tieLen2=i*i}if(t.rack!==0&&(o.tieInner0=ee(n.tieInner0,U(n.rackAxis,t.rack))),t.pushRod===0)return{corner:e.corner,inv:o,rocker:e.rocker};let a=Math.sqrt(e.rocker.rodLen2)+t.pushRod,s={...e.rocker,rodLen2:a*a};return{corner:e.corner,inv:o,rocker:s}}var BP=8,$P=1e-5,GP=e=>({q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle});function Ff(e,t,r){let n=Sf(e,r.force,r.extras??Mf),o=r.alignMoment?ee(n.moment,[0,0,r.alignMoment]):n.moment;return ws(e,t,n.force,o)}function _l(e,t,r,n,o,a,s=0){let i=Ie(e,t,r,o,a),c=e.corner.compliance;if(!(Vn(c)&&On(e.corner)))return{state:i,forces:Ff(Ns(e,i),e.corner.config.pushrodAttach,n),deflection:El,rigid:i,iterations:0,converged:!0,bypassed:!0};let u=i,m=e,f=e.corner.config.pushrodAttach,p=Ff(Ns(e,i),f,n),d=El,h=!1,b=0;for(;b<BP;b++){let g=Ns(m,u);if(p=Ff(g,f,n),p.singular)break;d=Af(p,c,s),m=Os(e,d);let y=Ie(m,t,r,GP(u),a),R=ve(y.points.wheelCenter,u.points.wheelCenter);if(u=y,R<$P){h=!0;break}}return{state:u,forces:p,deflection:d,rigid:i,iterations:b+1,converged:h&&u.converged,bypassed:!1}}var Il=1e3,mv=1e5;function pv(e,t,r,n,o){let a=_l(e,t,r,n,void 0,o);return{toe:a.state.metrics.toe,camber:a.state.metrics.camber,patch:a.state.points.contactPatch,converged:a.converged,bypassed:a.bypassed}}function Nl(e,t,r,n,o){let a={force:[0,0,n]},s=(b,g=0)=>pv(e,t,r,{force:b,alignMoment:g},o),i=pv(e,t,r,a,o);if(i.bypassed)return{toePerLateral:0,camberPerLateral:0,toePerLongitudinal:0,camberPerLongitudinal:0,toePerAligning:0,lateralPatch:0,longitudinalPatch:0,bypassed:!0,converged:!0};let c=s([0,Il,n]),l=s([0,-Il,n]),u=s([Il,0,n]),m=s([-Il,0,n]),f=s([0,0,n],mv),p=s([0,0,n],-mv),d=(b,g)=>(b-g)/2,h=[i,c,l,u,m,f,p].every(b=>b.converged);return{toePerLateral:d(c.toe,l.toe),camberPerLateral:d(c.camber,l.camber),toePerLongitudinal:d(u.toe,m.toe),camberPerLongitudinal:d(u.camber,m.camber),toePerAligning:d(f.toe,p.toe),lateralPatch:d(c.patch[1],l.patch[1]),longitudinalPatch:d(u.patch[0],m.patch[0]),bypassed:!1,converged:h}}var KP=1e3;function wf(e,t=KP){if(!Vn(e.compliance)||!On(e))return;let r=tt(e),n=Ie(r,0,0),o=Nl(r,n.beta,0,t);if(!o.bypassed)return{toePerFy:o.toePerLateral/1e3,camberPerFy:o.camberPerLateral/1e3,toePerFx:o.toePerLongitudinal/1e3,camberPerFx:o.camberPerLongitudinal/1e3,toePerMz:o.toePerAligning/1e5}}function oa(e,t=-xf,r=xf,n=21){let o=e.measured;if(o)return{travel:[...o.travel],motionRatio:[...o.motionRatio],camber:[...o.camber],toe:[...o.toe],damperLen:o.damperLen?[...o.damperLen]:o.travel.map(()=>0)};let a=Ke(e,{travelMin:t,travelMax:r,steps:n}),s=wf(e);return{travel:a.samples.map(i=>i.travel),motionRatio:a.samples.map(i=>i.metrics.motionRatio??1),camber:a.samples.map(i=>i.metrics.camber),toe:a.samples.map(i=>i.metrics.toe),damperLen:a.samples.map(i=>i.metrics.damperLength),...s?{compliance:s}:{}}}function Ol(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function cn(e,t){return{motionRatio:Ol(e.travel,e.motionRatio,t),camber:Ol(e.travel,e.camber,t),toe:Ol(e.travel,e.toe,t),damperLen:Ol(e.travel,e.damperLen,t)}}var dv=Math.PI/180,HP=9.81;function ln(e,t,r,n=0){let o=we(e),a=e.wheelbase*(1-e.frontMassFrac),s=e.wheelbase*e.frontMassFrac,i=Jo(e,n),c=e.aero?.model?(k,v,x)=>Jo(e,n,v,k,x):()=>i,l=cn(t,0),u=cn(r,0),m=e.loadFactor,f=m!==void 0&&m!==1?(m-1)*e.massTotal*HP:0,p=f*e.frontMassFrac/2,d=f*(1-e.frontMassFrac)/2,h=(k,v)=>v>0&&Number.isFinite(v)&&k+v>0?v/(k+v):1,b=Xe(e,"front"),g=Xe(e,"rear"),y={F:h(e.wheelRateFront+(e.heaveSpringFront??0),b),R:h(e.wheelRateRear+(e.heaveSpringRear??0),g)},R={F:h(e.wheelRateFront+e.arbFront,b),R:h(e.wheelRateRear+e.arbRear,g)};return(k,v,x=0,M=0)=>{let F=c(k,v,x),w=o.rollGradient*k,C=w*dv,T=o.pitchGradient*v*dv,S=(V,N)=>{let z=N==="F"?e.trackFront:e.trackRear,I=N==="F"?o.rideRateFront:o.rideRateRear,_=(V==="R"?1:-1)*(z/2)*Math.tan(C),B=(N==="R"?s:-a)*Math.tan(T),O=`${N}${V}`,G=f?F[O]+(N==="F"?p:d):F[O],K=I>0?G/I:0;return{anti:_,sym:B+K}},A={FL:S("L","F"),FR:S("R","F"),RL:S("L","R"),RR:S("R","R")},P=V=>{let N=V[0];return A[V].sym*y[N]+A[V].anti*R[N]},L=Zo(e,M,o,{FL:P("FL"),FR:P("FR")}),D=w+L.rollDeg,E=(V,N)=>{let z=N==="F"?t:r,I=N==="F"?l:u,_=`${N==="F"?"F":"R"}${V}`,B=A[_].sym+A[_].anti+L.travel[_],O=P(_)+L.travel[_]*R[N],G=B-O,K=cn(z,O),Y=(V==="R"?1:-1)*K.camber;return{travel:O,tyre:G,ground:B,camber:Y,camberRoad:Y+D,toe:K.toe,bumpToe:K.toe-I.toe,damperTravel:I.damperLen-K.damperLen}};return{FL:E("L","F"),FR:E("R","F"),RL:E("L","R"),RR:E("R","R"),steeringJacking:L}}}var Cf=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function Bn(e){return{enabled:e?.enabled===!0,roadFeedbackGain:Math.min(2,Math.max(0,Cf(e?.roadFeedbackGain,1))),turnInFrictionNm:Math.max(0,Cf(e?.turnInFrictionNm,0)),columnStiffnessNmPerRad:Math.max(0,Cf(e?.columnStiffnessNmPerRad,0))}}function Tf(e,t,r){let n=Bn(r);if(!n.enabled)return{roadNm:e,assistanceNm:0,frictionNm:0,columnTwistDeg:0,driverNm:e};let o=e*(n.roadFeedbackGain-1),a=t===0?0:Math.sign(t)*n.turnInFrictionNm,s=e+o+a,i=n.columnStiffnessNmPerRad>0?s/n.columnStiffnessNmPerRad*(180/Math.PI):0;return{roadNm:e,assistanceNm:o,frictionNm:a,columnTwistDeg:i,driverNm:s}}var fv=()=>({totalNm:0,aligningNm:0,lateralNm:0,longitudinalNm:0,jackingNm:0});function $n(e){let t=e.steerFront;return!!(t?.rackRatioMmPerRev&&t.innerJacobian&&t.innerJacobian.length>=2&&t.outerJacobian&&t.outerJacobian.length>=2&&t.meanDeg.length>=2)}function Vs(e,t,r,n="model",o){let a=e.steerFront;if(!$n(e)||!a)return null;let s=t<0?-1:1,c=a.rackRatioMmPerRev/(2*Math.PI)/1e3,l=t>=0,u=o&&a.travelSurface?qo(a,Math.abs(t),l?o.FL:o.FR,l?o.FR:o.FL):Qo(a,Math.abs(t));if(!u.innerJacobian||!u.outerJacobian)return null;let m=(b,g)=>{let y=r[b],R=b==="FL"?-1:1,k=-R*y.Fy,x={aligning:1e3*(-R*y.Mz)*g.yaw,lateral:k*g.lateral,longitudinal:y.Fx*g.longitudinal,jacking:y.Fz*g.vertical},M=fv();M.aligningNm=-s*x.aligning*c,M.lateralNm=-s*x.lateral*c,M.longitudinalNm=-s*x.longitudinal*c,M.jackingNm=-s*x.jacking*c,M.totalNm=M.aligningNm+M.lateralNm+M.longitudinalNm+M.jackingNm;let F=-s*(x.aligning+x.lateral+x.longitudinal+x.jacking);return{moment:M,rackN:F}},f=m("FL",l?u.innerJacobian:u.outerJacobian),p=m("FR",l?u.outerJacobian:u.innerJacobian),d=fv();for(let b of[f.moment,p.moment])d.aligningNm+=b.aligningNm,d.lateralNm+=b.lateralNm,d.longitudinalNm+=b.longitudinalNm,d.jackingNm+=b.jackingNm,d.totalNm+=b.totalNm;let h=Tf(d.totalNm,t,e.steeringSystem);return d.totalNm=h.driverNm,{...d,roadNm:h.roadNm,assistanceNm:h.assistanceNm,frictionNm:h.frictionNm,columnTwistDeg:h.columnTwistDeg,rackForceN:f.rackN+p.rackN,aligningSource:n,perWheel:{FL:f.moment,FR:p.moment}}}var zP=e=>"front"in e&&"rear"in e;function aa(e,t){return zP(e)?e[t]:e}function Lf(e,t,r=24){let n=Math.max(1,t),o=n/Math.max(1,r-1),a=[],s=[],i=[];for(let l=0;l<r;l++){let u=l*o;a.push(u),s.push(e.muX(u)),i.push(e.muY(u))}let c=(l,u)=>{if(!(u>0))return l[0];if(u>=n)return l[r-1];let m=Math.min(r-2,Math.floor(u/o)),f=(u-a[m])/o;return l[m]+f*(l[m+1]-l[m])};return{muX:l=>c(s,l),muY:l=>c(i,l)}}function Pf(e,t){let r=Math.max(0,t.Fz),n=e.muY(r)*r,o=e.muX(r)*r;if(!(n>0))return{fyUsed:0,fyMax:0,fyRes:0};let a=o>0?Math.min(1,Math.abs(t.Fx)/o):0,s=n*Math.sqrt(Math.max(0,1-a*a)),i=Math.abs(t.Fy);return{fyUsed:i,fyMax:s,fyRes:Math.max(0,s-i)}}function hv(e,t,r){let n=Pf(e,t),o=Pf(e,r);return{left:n,right:o,fyRes:n.fyRes+o.fyRes}}function Sr(e,t,r){let n=hv(aa(e,"front"),t.FL,t.FR),o=hv(aa(e,"rear"),t.RL,t.RR),a=r.lf>0&&Number.isFinite(r.lf)?r.lf:0,s=r.lr>0&&Number.isFinite(r.lr)?r.lr:0,i=o.fyRes*s,c=n.fyRes*a,l=i-c,u=Math.max(Math.abs(i),Math.abs(c));return{stabil:i,agil:c,diff:l,rel:u>0?l/u:0,front:n,rear:o}}var Bs=[{q:"p",section:"INFLATION_PRESSURE_RANGE",min:"PRESMIN",max:"PRESMAX",what:"pressure"},{q:"fz",section:"VERTICAL_FORCE_RANGE",min:"FZMIN",max:"FZMAX",what:"load"},{q:"kappa",section:"LONG_SLIP_RANGE",min:"KPUMIN",max:"KPUMAX",what:"slip ratio"},{q:"alpha",section:"SLIP_ANGLE_RANGE",min:"ALPMIN",max:"ALPMAX",what:"slip angle"},{q:"gamma",section:"INCLINATION_ANGLE_RANGE",min:"CAMMIN",max:"CAMMAX",what:"inclination"}],WP=Bs.flatMap(e=>[e.min,e.max]);function jP(e){let t={};for(let r of Bs){let n=e[r.min],o=e[r.max],a={};Number.isFinite(n)&&(a.min=n),Number.isFinite(o)&&(a.max=o),(a.min!==void 0||a.max!==void 0)&&(t[r.q]=a)}return Object.keys(t).length?t:void 0}function Vl(e){if(e.kind==="magic")return e.range??jP(e.coeffs)}function Df(e){return Math.max(1,e.kind==="magic"?e.fnomin:e.nominalLoad)}function bv(e,t,r,n,o){let a=(r-t)/n,s=t,i=e(t);for(let c=t+a;c<=r;c+=a){let l=e(c);o(l,i)&&(i=l,s=c)}return s}function Wt(e){let t=gv.get(e);if(t!==void 0)return t;let r=10*Df(e.model),{turnover:n,collapse:o}=XP(e,r),a=n??o??r;return gv.set(e,a),a}var gv=new WeakMap;function XP(e,t){let r=Df(e.model),n=m=>e.muY(m),o=m=>n(m)*m,a=80,s=t/a,i=null,c=o(s);for(let m=2;m<=a;m++){let f=o(m*s);if(f<c){i=bv(o,(m-2)*s,m*s,20,(p,d)=>p>d);break}c=f}let l=null,u=n(s);for(let m=2;m<=a;m++){let f=n(m*s);if(f>u){let p=bv(n,(m-2)*s,m*s,40,(d,h)=>d<h);n(p)<.05*n(r)&&(l=p);break}u=f}return{turnover:i,collapse:l}}var yv=.1;function Bl(e,t=Df(e)){let r=Pe(e).muX(t);return{muX:r,none:Number.isFinite(r)&&r<yv}}var xv=["FL","FR","RL","RR"],qP=e=>e==="FL"||e==="RL",QP=e=>e==="FL"||e==="FR"?"front":"rear";function $l(e,t,r,n){if(!(e.full>e.open)||n.ayDir===0)return e.full;let o=n.halfTrack[e.axle],a={};for(let l of xv)a[l]={...t[l]};let s=l=>{let u=0;for(let f of xv)QP(f)===e.axle&&(a[f].Fx=e.sense*(f===e.strong?l-e.open/2:e.open/2),u-=(qP(f)?o:-o)*a[f].Fx);let m=Sr(r,a,n.arms);return u*n.ayDir>=0?Math.abs(u)<=m.stabil:Math.abs(u)<=m.agil};if(s(e.full))return e.full;let i=e.open,c=e.full;for(let l=0;l<20&&c-i>.001*e.full;l++){let u=.5*(i+c);s(u)?i=u:c=u}return i}var ZP=[["PCY1","Shape factor Cfy for lateral forces",1.3],["PDY1","Lateral friction Muy",1],["PDY2","Variation of friction Muy with load",0],["PDY3","Variation of friction Muy with squared camber",0],["PEY1","Lateral curvature Efy at Fznom",0],["PEY2","Variation of curvature Efy with load",0],["PEY3","Zero order camber dependency of curvature Efy",0],["PEY4","Variation of curvature Efy with camber",0],["PEY5","Variation of curvature Efy with camber squared",0],["PKY1","Maximum value of stiffness Kfy/Fznom",-15],["PKY2","Load at which Kfy reaches maximum value",2],["PKY3","Variation of Kfy/Fznom with camber",0],["PKY4","Curvature of stiffness Kfy",2],["PKY5","Peak stiffness variation with camber squared",0],["PKY6","Fy camber stiffness factor",0],["PKY7","Vertical load dependency of camber stiffness",0],["PHY1","Horizontal shift Shy at Fznom",0],["PHY2","Variation of shift Shy with load",0],["PHY3","Variation of shift Shy with camber",0],["PVY1","Vertical shift in Svy/Fz at Fznom",0],["PVY2","Variation of shift Svy/Fz with load",0],["PVY3","Variation of shift Svy/Fz with camber",0],["PVY4","Variation of shift Svy/Fz with camber and load",0],["PPY1","Influence of inflation pressure on cornering stiffness",0],["PPY2","Influence of inflation pressure on dependency of nominal tyre load on cornering stiffness",0],["PPY3","Linear influence of inflation pressure on lateral peak friction",0],["PPY4","Quadratic influence of inflation pressure on lateral peak friction",0],["PPY5","Influence of inflation pressure on camber stiffness",0]],JP=[["PCX1","Shape factor Cfx for longitudinal force",1.65],["PDX1","Longitudinal friction Mux at Fznom",1],["PDX2","Variation of friction Mux with load",0],["PDX3","Variation of friction Mux with camber squared",0],["PEX1","Longitudinal curvature Efx at Fznom",0],["PEX2","Variation of curvature Efx with load",0],["PEX3","Variation of curvature Efx with load squared",0],["PEX4","Factor in curvature Efx while driving",0],["PKX1","Longitudinal slip stiffness Kfx/Fz at Fznom",20],["PKX2","Variation of slip stiffness Kfx/Fz with load",0],["PKX3","Exponent in slip stiffness Kfx/Fz with load",0],["PHX1","Horizontal shift Shx at Fznom",0],["PHX2","Variation of shift Shx with load",0],["PVX1","Vertical shift Svx/Fz at Fznom",0],["PVX2","Variation of shift Svx/Fz with load",0],["PPX1","Linear influence of inflation pressure on longitudinal slip stiffness",0],["PPX2","Quadratic influence of inflation pressure on longitudinal slip stiffness",0],["PPX3","Linear influence of inflation pressure on peak longitudinal friction",0],["PPX4","Quadratic influence of inflation pressure on peak longitudinal friction",0]],eL=[["QBZ1","Trail slope factor for trail Bpt at Fznom",8],["QBZ2","Variation of slope Bpt with load",0],["QBZ3","Variation of slope Bpt with load squared",0],["QBZ4","Variation of slope Bpt with camber",0],["QBZ5","Variation of slope Bpt with absolute camber",0],["QBZ6","Camber influence Bt",0],["QBZ9","Factor for scaling factors of slope factor Br of Mzr",0],["QBZ10","Factor for dimensionless cornering stiffness of Br of Mzr",0],["QCZ1","Shape factor Cpt for pneumatic trail",1.1],["QDZ1","Peak trail Dpt = Dpt*(Fz/Fznom*R0)",.1],["QDZ2","Variation of peak Dpt with load",0],["QDZ3","Variation of peak Dpt with camber",0],["QDZ4","Variation of peak Dpt with camber squared",0],["QDZ6","Peak residual torque Dmr = Dmr/(Fz*R0)",0],["QDZ7","Variation of peak factor Dmr with load",0],["QDZ8","Variation of peak factor Dmr with camber",0],["QDZ9","Variation of peak factor Dmr with camber and load",0],["QDZ10","Variation of peak factor Dmr with camber squared",0],["QDZ11","Variation of Dmr with camber squared and load",0],["QEZ1","Trail curvature Ept at Fznom",0],["QEZ2","Variation of curvature Ept with load",0],["QEZ3","Variation of curvature Ept with load squared",0],["QEZ4","Variation of curvature Ept with sign of Alpha-t",0],["QEZ5","Variation of Ept with camber and sign Alpha-t",0],["QHZ1","Trail horizontal shift Sht at Fznom",0],["QHZ2","Variation of shift Sht with load",0],["QHZ3","Variation of shift Sht with camber",0],["QHZ4","Variation of shift Sht with camber and load",0],["PPZ1","Effect of inflation pressure on length of pneumatic trail",0],["PPZ2","Influence of inflation pressure on residual aligning torque",0],["SSZ1","Nominal value of s/R0: effect of Fx on Mz",0],["SSZ2","Variation of distance s/R0 with Fy/Fznom",0],["SSZ3","Variation of distance s/R0 with camber",0],["SSZ4","Variation of distance s/R0 with load and camber",0]],tL=[["RBX1","Slope factor for combined slip Fx reduction",0],["RBX2","Variation of slope Fx reduction with kappa",0],["RBX3","Influence of camber on stiffness for Fx combined",0],["RCX1","Shape factor for combined slip Fx reduction",1],["REX1","Curvature factor of combined Fx",0],["REX2","Curvature factor of combined Fx with load",0],["RHX1","Shift factor for combined slip Fx reduction",0],["RBY1","Slope factor for combined Fy reduction",0],["RBY2","Variation of slope Fy reduction with alpha",0],["RBY3","Shift term for alpha in slope Fy reduction",0],["RBY4","Influence of camber on stiffness of Fy combined",0],["RCY1","Shape factor for combined Fy reduction",1],["REY1","Curvature factor of combined Fy",0],["REY2","Curvature factor of combined Fy with load",0],["RHY1","Shift factor for combined Fy reduction",0],["RHY2","Shift factor for combined Fy reduction with load",0],["RVY1","Kappa induced side force Svyk/Muy*Fz at Fznom",0],["RVY2","Variation of Svyk/Muy*Fz with load",0],["RVY3","Variation of Svyk/Muy*Fz with camber",0],["RVY4","Variation of Svyk/Muy*Fz with alpha",0],["RVY5","Variation of Svyk/Muy*Fz with kappa",1],["RVY6","Variation of Svyk/Muy*Fz with atan(kappa)",0]],rL=[["LFZO","Scale factor of nominal (rated) load",1],["LCX","Scale factor of Fx shape factor",1],["LMUX","Scale factor of Fx peak friction coefficient",1],["LEX","Scale factor of Fx curvature factor",1],["LKX","Scale factor of Fx slip stiffness",1],["LHX","Scale factor of Fx horizontal shift",1],["LVX","Scale factor of Fx vertical shift",1],["LCY","Scale factor of Fy shape factor",1],["LMUY","Scale factor of Fy peak friction coefficient",1],["LEY","Scale factor of Fy curvature factor",1],["LKY","Scale factor of Fy cornering stiffness",1],["LKYC","Scale factor of camber force stiffness",1],["LKZC","Scale factor of camber torque stiffness",1],["LHY","Scale factor of Fy horizontal shift",1],["LVY","Scale factor of Fy vertical shift",1],["LTR","Scale factor of peak of pneumatic trail",1],["LRES","Scale factor for offset of residual torque",1],["LXAL","Scale factor of alpha influence on Fx",1],["LYKA","Scale factor of kappa influence on Fy",1],["LVYKA","Scale factor of kappa induced Fy",1],["LS","Scale factor of moment arm of Fx",1]],vv=[["lateral",ZP],["longitudinal",JP],["aligning",eL],["combined",tL],["scaling",rL]].flatMap(([e,t])=>t.map(([r,n,o])=>({key:r,section:e,text:n,fallback:o}))),sH=new Map(vv.map(e=>[e.key,e]));var nL=/^\$\s*EDITED\s+([A-Z][A-Z0-9_]*)\s+was\s+(absent|[-+0-9.eE]+)\s*$/;function kv(e){let t={};for(let r of e.split(/\r?\n/)){let n=r.trim().match(nL);if(!n)continue;let o=n[2]==="absent"?null:parseFloat(n[2]);(o===null||Number.isFinite(o))&&(t[n[1]]=o)}return Object.keys(t).length?t:void 0}var aL=/^\s*\$\s*UNLOADED_RADIUS_STAND_IN\s*=\s*([0-9.eE+-]+)/,sL=/^\$-+ written by (?:PaceDynamics|PaceLab)\b/m,iL=/^\$\s*AXIS_SYSTEM\s*=\s*(ISO-W|SAE)\b/m;function cL(e){let t=e.match(iL);return t?{axisSystem:t[1]==="SAE"?"sae":"iso",trustSide:!0}:sL.test(e)?{axisSystem:"sae",trustSide:!1}:{axisSystem:"iso",trustSide:!0}}function lL(e){return e>=62?"6.2":e>=61?"6.1":"5.2"}var Mv=new Map([["pa",1],["pascal",1],["kpa",1e3],["kilopascal",1e3],["mpa",1e6],["megapascal",1e6],["bar",1e5],["psi",6894.757293168]]);function uL(e,t,r){let n=r.PRESSURE?.trim().toLowerCase(),o=n===void 0?1:Mv.get(n);if(o===void 0)return;let a=(c,l)=>l===1?c:Number((c*l).toPrecision(12)),s=e.NOMPRES??e.INFLPRES;if(s!==void 0)return a(s,o);let i=e.INFLATION_PRESSURE;if(i!==void 0)return n!==void 0?a(i,o):t.PROPERTY_FILE_FORMAT?.trim().toUpperCase()==="MF_05"?a(i,1e5):void 0}var mL=new Map([["radians",1],["radian",1],["rad",1],["degrees",Math.PI/180],["degree",Math.PI/180],["deg",Math.PI/180]]);function pL(e,t){let r=(s,i)=>s===void 0?1:i.get(s.trim().toLowerCase()),n=r(t.ANGLE,mL),o={fz:1,kappa:1,alpha:n,gamma:n,p:r(t.PRESSURE,Mv)},a={};for(let s of Bs){let i=o[s.q];if(i===void 0)continue;let c={};for(let[l,u]of[["min",s.min],["max",s.max]]){let m=e[u];Number.isFinite(m)&&(c[l]=i===1?m:Number((m*i).toPrecision(12)),delete e[u])}(c.min!==void 0||c.max!==void 0)&&(a[s.q]=c)}return Object.keys(a).length?a:void 0}function $s(e,t="imported",r={}){let n=cL(e),o=r.axisSystem??n.axisSystem,a={},s={},i={},c="",l;for(let g of e.split(/\r?\n/)){let y=g.match(aL);y&&(l=parseFloat(y[1]));let R=g.replace(/[$!].*$/,"").trim();if(!R)continue;if(R.startsWith("[")){c=(R.match(/^\[([^\]]*)/)?.[1]??"").trim().toUpperCase();continue}let k=R.indexOf("=");if(k<0)continue;let v=R.slice(0,k).trim().toUpperCase(),x=R.slice(k+1).trim(),M=x.match(/^'([^']*)'|^"([^"]*)"/);if(M){s[v]=M[1]??M[2]??"",c==="UNITS"&&(i[v]=s[v]);continue}let F=parseFloat(x);Number.isFinite(F)&&(a[v]=F)}let u=lL(a.FITTYP??62),m=kv(e),f=m?Object.fromEntries(Object.entries(m).filter(([g])=>a[g]!==void 0)):void 0,p=a.VERTICAL_STIFFNESS??a.KZ??0,d=uL(a,s,i),h=pL(a,i),b=[];return a.UNLOADED_RADIUS===void 0&&a.R0===void 0&&b.push("UNLOADED_RADIUS"),p<=0&&b.push("VERTICAL_STIFFNESS"),a.FNOMIN===void 0&&b.push("FNOMIN"),d===void 0&&b.push("NOMPRES"),{kind:"magic",name:t,version:u,coeffs:a,axisSystem:o,side:n.trustSide?s.TYRESIDE==="RIGHT"?"right":s.TYRESIDE==="LEFT"?"left":void 0:void 0,fnomin:a.FNOMIN??5e3,unloadedR0:a.UNLOADED_RADIUS??a.R0??(l!==void 0&&l>0?l:.3),...a.WIDTH!==void 0&&a.WIDTH>0?{sectionWidth:a.WIDTH}:{},verticalStiffness:p>0?p/1e3:0,...a.FREFF!==void 0&&!a.DREFF?{rollingFraction:a.FREFF}:{},...a.LATERAL_STIFFNESS!==void 0&&a.LATERAL_STIFFNESS>0?{relaxation:{sigma:0,carcassStiffness:a.LATERAL_STIFFNESS/1e3,source:"fitted"}}:{},nomPressure:d??0,missing:b,...f&&Object.keys(f).length?{edited:f}:{},...h?{range:h}:{}}}function ar(e){if(!e)return null;let t=e.unloadedR0;return t===void 0||!(t>0)||e.kind==="magic"&&e.missing?.includes("UNLOADED_RADIUS")?null:t*1e3}var fH=Math.PI/180;var xH=Math.PI/180,RH=180/Math.PI;function Gs(){return{kind:"simple",name:"Simple (default)",Bx:11,Cx:1.6,muX0:1.7,loadSensX:-8e-5,By:9,Cy:1.4,muY0:1.6,loadSensY:-1e-4,nominalLoad:1500,verticalStiffness:120}}var Fv=`$ AXIS_SYSTEM = SAE (authored in the evaluation frame: y right)
2
+ import{parentPort as tT,workerData as HB}from"node:worker_threads";import{readFileSync as Ry}from"node:fs";import{join as vy}from"node:path";var zc=e=>e.format!=="points"&&!e.field;var ft=e=>e?.kind==="ice";var Qy={packVoltageMax:600,segmentVoltageMax:120,powerLimitKw:80};var Ee=e=>typeof e=="number"&&Number.isFinite(e);function nT(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 oT(e){return!e||typeof e!="object"?"The cell has no curve.":e.kind==="table"?nT(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 Yc(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=oT(t.curve);if(r)return r;let n=t.curve.kind==="table"?t.curve.ocv[t.curve.ocv.length-1]:t.curve.vFull;if(t.vMin>=n)return`The cut-off voltage (${t.vMin} V) is at or above the cell's voltage at full charge (${n} V), so no power could ever be drawn.`;let o=e.thermal;if(o!==void 0){if(!o||typeof o!="object")return"The thermal model must be an object, or absent.";if(!Ee(o.heatCapacityJPerK)||o.heatCapacityJPerK<=0)return"The cell heat capacity must be a positive number of joules per kelvin.";if(!Ee(o.coolingWPerK)||o.coolingWPerK<0)return"The cooling must be a number of watts per kelvin and cannot be negative.";if(o.startC!==void 0&&!Ee(o.startC))return"The starting temperature must be a number.";if(o.entropicVPerK!==void 0&&!Ee(o.entropicVPerK))return"The entropic coefficient must be a number.";if(o.derateFromC!==void 0){if(!Ee(o.derateFromC))return"The temperature the derate starts at must be a number.";if(o.derateToC!==void 0){if(!Ee(o.derateToC))return"The temperature the derate ends at must be a number.";if(!(o.derateToC>o.derateFromC))return`The derate must end above where it starts (given ${o.derateFromC} then ${o.derateToC} \xB0C).`}}else if(o.derateToC!==void 0)return"The derate has an end temperature but no start; give both or neither."}let a=e.pack;if(!a||typeof a!="object")return"The model has no pack.";if(!Number.isInteger(a.series)||a.series<1)return"The pack needs a whole number of cells in series, at least one.";if(!Number.isInteger(a.parallel)||a.parallel<1)return"The pack needs a whole number of strings in parallel, at least one.";if(!Ee(a.busResistance)||a.busResistance<0)return"The busbar resistance must be a number and cannot be negative.";if(a.seriesPerSegment!==void 0&&a.seriesPerSegment!==0){if(!Number.isInteger(a.seriesPerSegment)||a.seriesPerSegment<1)return"The cells per segment must be a whole number, at least one.";if(a.seriesPerSegment>a.series)return`A segment cannot hold more cells (${a.seriesPerSegment}) than the pack has in series (${a.series}).`}return null}function Ln(e,t){let r=e.length;if(r<=1)return{i:0,t:0,clamped:!1};if(t<=e[0])return{i:0,t:0,clamped:t<e[0]};if(t>=e[r-1])return{i:r-2,t:1,clamped:t>e[r-1]};let n=0,o=r-1;for(;o-n>1;){let a=n+o>>1;e[a]<=t?n=a:o=a}return{i:n,t:(t-e[n])/(e[o]-e[n]),clamped:!1}}function $e(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function Wc(e,t,r,n,o){let a=e.length,s=t.length;if(a===0||s===0)return 0;let i=Ln(e,n),c=Ln(t,o),l=Math.min(i.i+1,a-1),u=Math.min(c.i+1,s-1),m=r[c.i][i.i],f=r[c.i][l],p=r[u][i.i],d=r[u][l],h=m+i.t*(f-m),b=p+i.t*(d-p);return h+c.t*(b-h)}var Io=[0,.05,.1,.2,.3,.4,.5,.6,.7,.8,.9,1],Xp={nmc:[0,.29,.4,.483,.525,.567,.608,.667,.733,.8,.892,1],lfp:[0,.478,.591,.626,.652,.67,.678,.696,.704,.722,.757,1],lipo:[0,.333,.433,.517,.575,.625,.667,.717,.775,.833,.908,1],other:[0,.05,.1,.2,.3,.4,.5,.6,.7,.8,.9,1]},qy=[0,.05,.1,.2,.5,.8,1],Zy=[2.2,1.55,1.3,1.12,1,.97,.98];function Jy(e){return $e(qy,Zy,e)}var ex=[-20,-10,0,10,25,40,60],tx=[4,2.8,2,1.4,1,.82,.75];function Qp(e){return $e(ex,tx,e)}var rx=.5;function qp(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=Xp[t]??Xp.other,l=e.socAtNom??rx,u=Io.includes(l)?[...Io]:[...Io,l].sort((h,b)=>h-b),m=$e(Io,c,l),f=m>0&&m<1?Math.log(i)/Math.log(m):1,p=[],d=[];for(let h of u){let b=$e(Io,c,h);p.push(o+s*Math.pow(b,f)),d.push(e.constantResistance?a:a*Jy(h))}return{kind:"table",soc:u,ocv:p,r0:d}}function Zp(e){let t=e.soc,r=e.ocv,n=[0,...t.filter(a=>a>0&&a<1),1],o=0;for(let a=1;a<n.length;a++){let s=n[a-1],i=n[a];o+=($e(t,r,s)+$e(t,r,i))/2*(i-s)}return o}var _o=25,nx=new WeakMap;function Rr(e){let t=nx.get(e);if(t)return t;let r=Yc(e);if(r)throw new Error(r);let{cell:n,pack:o}=e,a=n.curve.kind==="table"?n.curve:qp(n.curve,n.chemistry),s=o.series,i=o.parallel,c=s/i,l=a.rTempC,u=a.rGrid,m=i*n.capacityAh,f=s*n.vMin,p=n.iMaxA>0?i*n.iMaxA:1/0,d=n.iMaxChargeA!==void 0&&n.iMaxChargeA>0?n.iMaxChargeA:n.iMaxA/4,h=d>0?i*d:1/0,b=F=>s*$e(a.soc,a.ocv,F),g=(F,w=_o)=>{let C=l&&u?Wc(a.soc,l,u,F,w):$e(a.soc,a.r0,F)*Qp(w);return c*C+o.busResistance},y=(F,w,C)=>b(F)-w*g(F,C),R=(F,w,C)=>{if(!(F>0))return 0;let T=b(w),S=g(w,C);if(!(S>0))return F/T;let A=T*T-4*S*F;return A<0?NaN:2*F/(T+Math.sqrt(A))},k=(F,w,C)=>{if(!(F>0))return 0;let T=b(w),S=g(w,C);return S>0?2*F/(T+Math.sqrt(T*T+4*S*F)):F/T},v=F=>{let w=e.thermal;if(!w||w.derateFromC===void 0)return 1;let C=w.derateToC??w.derateFromC;return F<=w.derateFromC?1:!(C>w.derateFromC)||F>=C?0:1-(F-w.derateFromC)/(C-w.derateFromC)},x=(F,w,C=0)=>{let T=b(F),S=g(F,w),A=S>0?T/(2*S):1/0,P=G=>{if(!(S>0))return G*T;let K=Math.min(G,A);return K*(T-K*S)},L=S>0?Math.max(0,(T-f)/S):1/0,D=C>0&&Number.isFinite(C)?C:1/0,E=S>0?P(L):1/0,V=Number.isFinite(p)?P(p):1/0,N=S>0?T*T/(4*S):1/0,z=[["rules",D],["voltage-floor",E],["current",V],["matched-load",N]],I=z[0][0],_=z[0][1];for(let[G,K]of z)K<_&&(_=K,I=G);let B=v(w??_o);B<1&&(_=Number.isFinite(_)?_*B:_,I="temperature");let O=Number.isFinite(_)?R(_,F,w):1/0;return{watts:_,binding:I,rules:D,voltageFloor:E,current:V,matchedLoad:N,derate:B,amps:O,volts:Number.isFinite(O)?T-O*S:T}},M={model:e,table:a,capacityAh:m,chargeC:m*3600,energyKwh:m*(s*Zp(a))/1e3,socRange:[a.soc[0],a.soc[a.soc.length-1]],voltageAtFull:s*a.ocv[a.ocv.length-1],voltageCeiling:s*n.vMax,voltageFloor:f,currentCeiling:p,chargeCurrentCeiling:h,massKg:n.massKg!==void 0?s*i*n.massKg:null,thermal:e.thermal?{heatCapacityJPerK:s*i*e.thermal.heatCapacityJPerK,coolingWPerK:s*i*e.thermal.coolingWPerK,...e.thermal.startC!==void 0?{startC:e.thermal.startC}:{},entropicVPerK:s*(e.thermal.entropicVPerK??0)}:null,derateAt:v,ocv:b,resistance:g,terminalVoltage:y,currentFor:R,chargeCurrentFor:k,maxPower:x};return nx.set(e,M),M}function Jp(e){return{name:e.name,chemistry:e.chemistry,capacityAh:e.capacityAh,curve:{kind:"analytic",vFull:e.vFull,vNom:e.vNom,vCut:e.vCut,r0:e.r0},iMaxA:e.iMaxA,...e.iMaxChargeA!==void 0?{iMaxChargeA:e.iMaxChargeA}:{},vMin:e.vCut,vMax:e.vFull,...e.massKg!==void 0?{massKg:e.massKg}:{}}}var ox={name:"High-power NMC pouch 4.0 Ah",chemistry:"nmc",capacityAh:4,vCut:3,vNom:3.6,vFull:4.2,r0:.0025,iMaxA:100,iMaxChargeA:40,massKg:.09},ax={name:"LFP prismatic 20 Ah",chemistry:"lfp",capacityAh:20,vCut:2.5,vNom:3.2,vFull:3.65,r0:.002,iMaxA:200,iMaxChargeA:60,massKg:.4},sx={name:"NMC cylindrical 3.4 Ah",chemistry:"nmc",capacityAh:3.4,vCut:3,vNom:3.6,vFull:4.2,r0:.03,iMaxA:10,iMaxChargeA:3,massKg:.048};function ed(){return{name:"Formula Student accumulator",cell:Jp(ox),pack:{series:140,parallel:2,busResistance:.02,seriesPerSegment:28},provenance:{source:"assumed",note:"Assumed high-power NMC pouch pack sized to the Formula Student rules; the cell curve and resistance are class-level guesses, not a measurement."}}}function td(){return{name:"LFP pack",cell:Jp(ax),pack:{series:160,parallel:1,busResistance:.02,seriesPerSegment:32},provenance:{source:"assumed",note:"Assumed LFP prismatic pack; the flat plateau is the chemistry, the numbers are class-level guesses."}}}function rd(){return{name:"Road car pack",cell:Jp(sx),pack:{series:96,parallel:74,busResistance:.01},provenance:{source:"assumed",note:"Assumed road-electric pack of cylindrical energy cells; capacity and voltage are class-typical, the resistance is a guess."}}}function nd(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 jc(e){if(e.kind==="ice"){let n=e.gearbox.efficiency;return{model:e,maxTorque:o=>o>e.limitRpm?0:$e(e.rpm,e.torque,o),efficiency:()=>n}}let t=n=>$e(e.rpm,e.torque,n),r=e.kind==="simple"?()=>e.efficiency:(n,o)=>Wc(e.effRpm,e.effTorque,e.effGrid,n,o);return{model:e,maxTorque:t,efficiency:r}}function od(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 ad(e,t){let r=e.tyreFreeRadiusRear;return(t==="rear"&&r!==void 0?r:e.tyreFreeRadius)??0}var Uc=9.81,ix=(e,t)=>e*(t*t)/2*(Math.PI/180)/1e3,ns=(e,t)=>e+t>0?e*t/(e+t):0,cx=.5;function Xc(e,t,r){if(!(r>0))return 1;let n=e*Uc*t*(Math.PI/180)/r;return 1/(1-Math.min(cx,n))}function sd(e,t,r){return r>0?e*Uc*t/(r*r):0}function lx(e,t,r,n,o){if(!(n>0)||!(o>0))return 1;let a=sd(e,t,r)*(1/n+1/o);return 1/(1-Math.min(cx,a))}function we(e){let t=4*e.unsprungPerCorner,r=Math.max(0,e.massTotal-t),n=r*e.frontMassFrac,o=r*(1-e.frontMassFrac),a=Xe(e,"front"),s=Xe(e,"rear"),i=e.wheelRateFront+(e.heaveSpringFront??0),c=e.wheelRateRear+(e.heaveSpringRear??0),l=ns(i,a),u=ns(c,s),m=(V,N)=>{let z=N/2;return z>0?1/(2*Math.PI)*Math.sqrt(V*1e3/z):0},f=m(l,n),p=m(u,o),d=ns(e.wheelRateFront+e.arbFront,a),h=ns(e.wheelRateRear+e.arbRear,s),b=ix(d,e.trackFront),g=ix(h,e.trackRear),y=b+g,R=y>0?b/y:.5,k=e.rcHeightFront+(e.rcHeightRear-e.rcHeightFront)*(1-e.frontMassFrac),v=(e.cgHeight-k)/1e3,x=r*Uc*v,M=Xc(r,v,y),F=y>0?x/y*M:0,w=e.massTotal*Uc*e.cgHeight/e.wheelbase,C=2*l,T=2*u,S=lx(r,e.cgHeight,e.wheelbase,C,T),P=(C>0&&T>0?(w/C+w/T)/e.wheelbase*S:0)*(180/Math.PI),L=e.wheelbase*e.wheelbase*ns(C,T)*(Math.PI/180)/1e3,D=e.damperFront??2.5,E=e.damperRear??2.5;return{sprungMass:r,sprungFront:n,sprungRear:o,rideRateFront:l,rideRateRear:u,rideFreqFront:f,rideFreqRear:p,rollRateFront:b,rollRateRear:g,rollRateTotal:y,rollWheelRateFront:d,rollWheelRateRear:h,frontRollStiffFrac:R,rollGradient:F,pitchGradient:P,pitchRate:L,cgRollGain:M,cgPitchGain:S,rideDampingFront:D+(e.heaveDamperFront??0),rideDampingRear:E+(e.heaveDamperRear??0),rollDampingFront:D+(e.rollDamperFront??0),rollDampingRear:E+(e.rollDamperRear??0)}}var Qr=["clFront","clRear","cd"],qr=e=>e.frame?.kind==="pitch";function No(e){return qr(e)?{x:e.axes.h,y:e.axes.pitch}:{x:e.axes.hFront,y:e.axes.hRear}}var Qc=e=>e.frame?.kind==="pitch",ux=e=>e.kind==="map";var qc=45,qe=e=>typeof e=="number"&&Number.isFinite(e);function Zc(e,t,r="mm",n="ride height"){if(!Array.isArray(t)||t.length<1)return`The ${e} axis needs at least one ${n}.`;if(!t.every(qe))return`The ${e} axis contains a value that is not a number.`;for(let o=1;o<t.length;o++)if(!(t[o]>t[o-1]))return`The ${e} axis must increase (${t[o-1]} then ${t[o]} ${r}).`;return null}function mx(e,t){if(t===void 0)return null;for(let r of Qr){let n=t[r];if(!n||!Array.isArray(n.deg)||!Array.isArray(n.factor))return`The ${e} correction of ${r} needs degrees and factors.`;if(n.deg.length<1)return`The ${e} correction of ${r} needs at least one angle.`;if(n.deg.length!==n.factor.length)return`The ${e} correction of ${r} has ${n.factor.length} factors against ${n.deg.length} angles.`;if(!n.deg.every(qe)||!n.factor.every(qe))return`The ${e} correction of ${r} contains a value that is not a number.`;if(n.deg[0]<0)return`The ${e} correction of ${r} is against the absolute angle; it cannot start below zero.`;for(let o=1;o<n.deg.length;o++)if(!(n.deg[o]>n.deg[o-1]))return`The ${e} correction of ${r} must increase in angle (${n.deg[o-1]} then ${n.deg[o]}\xB0).`;if(n.factor.some(o=>o<0))return`The ${e} correction of ${r} has a negative factor.`}return null}function px(e,t){return t===void 0?null:!qe(t.dCl)||!qe(t.dBalance)||!qe(t.dCd)?`The ${e} slopes must be numbers.`:!qe(t.maxDeg)||!(t.maxDeg>0)?`The ${e} response needs a positive angle to be valid to.`:null}function os(e){if(!e||typeof e!="object")return"Not an aero model.";if(!qe(e.area)||e.area<=0)return"The reference area must be a positive number of square metres.";if(e.kind==="map"){let t,r,n,o;if(e.frame==null){let i=Zc("front ride-height",e.axes?.hFront);if(i)return i;let c=Zc("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=Zc("ride-height",e.axes?.h);if(i)return i;let c=Zc("pitch",e.axes?.pitch,"\xB0","pitch");if(c)return c;let l=e.axes.pitch.find(u=>Math.abs(u)>=qc);if(l!==void 0)return`A pitch of ${l}\xB0 is not a car's attitude \u2014 is the axis a rake in millimetres? Pitch is in degrees.`;[t,r,n,o]=[e.axes.h,e.axes.pitch,"ride heights","pitches"]}else return`Unknown aero map frame "${e.frame.kind}".`;let a=t.length,s=r.length;for(let i of Qr){let c=e[i];if(!Array.isArray(c)||c.length!==s)return`${i} has ${Array.isArray(c)?c.length:0} rows against ${s} ${o} \u2014 they must match.`;for(let l=0;l<s;l++){let u=c[l];if(!Array.isArray(u)||u.length!==a)return`${i} row ${l+1} has ${Array.isArray(u)?u.length:0} values against ${a} ${n}.`;if(!u.every(qe))return`${i} contains a value that is not a number.`}}return mx("yaw",e.attitude?.yaw)??mx("roll",e.attitude?.roll)}if(e.kind==="sensitivity"){let t;if(e.frame==null)t=["hFront","hRear"];else if(e.frame?.kind==="pitch"){if(!qe(e.frame.refX))return"The point the ride height is read at must be a number of millimetres aft of the front axle.";t=["h","pitch"]}else return`Unknown aero sensitivity frame "${e.frame.kind}".`;let r=e.ref,n=e.slope,o=e.range,a=s=>s==="pitch"?"\xB0":" mm";if(!r||!qe(r[t[0]])||!qe(r[t[1]]))return e.frame?"The reference ride height and pitch must be numbers.":"The reference ride heights must be numbers.";for(let s of Qr){if(!e.at||!qe(e.at[s]))return`${s} at the reference must be a number.`;let i=n?.[s];if(!i||!qe(i[t[0]])||!qe(i[t[1]]))return`The slopes of ${s} must be numbers.`}for(let s of t){let i=o?.[s],c=r[s];if(!i||!qe(i[0])||!qe(i[1]))return`The ${s} range must be two numbers.`;if(!(i[1]>i[0]))return`The ${s} range must run from low to high (${i[0]} to ${i[1]}${a(s)}).`;if(c<i[0]||c>i[1])return`The reference ${s} of ${c}${a(s)} lies outside its range ${i[0]}\u2013${i[1]}${a(s)}.`;if(s==="pitch"&&(Math.abs(i[0])>=qc||Math.abs(i[1])>=qc))return`A pitch range reaching ${Math.abs(i[0])>=qc?i[0]:i[1]}\xB0 is not a car's attitude. Pitch is in degrees.`}return px("yaw",e.attitude?.yaw)??px("roll",e.attitude?.roll)}return`Unknown aero model kind "${e.kind}".`}var dx=180/Math.PI;function Oo(e,t,r,n){let o=(n-r)/t;return{h:r+e.refX*o,pitch:Math.atan(o)*dx}}function Vo(e,t,r,n){let o=Math.tan(n/dx);return{hFront:r-e.refX*o,hRear:r+(t-e.refX)*o}}var T$=180/Math.PI,aT=["hFront","hRear"],sT=["h","pitch"],ld=e=>e?.kind==="pitch"?sT:aT,St=(e,t)=>e[t],Jc=(e,t)=>e[t],id=(e,t)=>({[e[0]]:t(e[0]),[e[1]]:t(e[1])});function iT(e){if(!(!e.yaw&&!e.roll))return{...e.yaw?{yaw:{...e.yaw}}:{},...e.roll?{roll:{...e.roll}}:{}}}function ud(e){let t=ld(e.frame),r=e.balanceFront,n=e.cl*r,o=e.cl*(1-r),a=id(t,c=>St(e.dCl,c)*r+e.cl*St(e.dBalance,c)),s=id(t,c=>St(e.dCl,c)*(1-r)-e.cl*St(e.dBalance,c)),i=iT(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:id(t,c=>St(e.dCd,c))},range:{[t[0]]:[...Jc(e.range,t[0])],[t[1]]:[...Jc(e.range,t[1])]},provenance:{...e.provenance},...i?{attitude:i}:{}}}function el(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 cd(e,t,r=11){let n=Array.from({length:r},(a,s)=>t.maxDeg*s/(r-1)),o=n.map(a=>el(e,t,a));return{clFront:{deg:[...n],factor:o.map(a=>a.clFront)},clRear:{deg:[...n],factor:o.map(a=>a.clRear)},cd:{deg:[...n],factor:o.map(a=>a.cd)}}}function fx(e){if(!(!e.attitude?.yaw&&!e.attitude?.roll))return{...e.attitude.yaw?{yaw:cd(e.at,e.attitude.yaw)}:{},...e.attitude.roll?{roll:cd(e.at,e.attitude.roll)}:{}}}function hx(e,t,r,n=0,o=0){let[a,s]=ld(e.frame),i=t-St(e.ref,a),c=r-St(e.ref,s),l={clFront:e.at.clFront+St(e.slope.clFront,a)*i+St(e.slope.clFront,s)*c,clRear:e.at.clRear+St(e.slope.clRear,a)*i+St(e.slope.clRear,s)*c,cd:e.at.cd+St(e.slope.cd,a)*i+St(e.slope.cd,s)*c},u=e.attitude?.yaw?el(e.at,e.attitude.yaw,n):{clFront:1,clRear:1,cd:1},m=e.attitude?.roll?el(e.at,e.attitude.roll,o):{clFront:1,clRear:1,cd:1};return{clFront:l.clFront*u.clFront*m.clFront,clRear:l.clRear*u.clRear*m.clRear,cd:l.cd*u.cd*m.cd}}function md(e){let[t,r]=ld(e.frame),n=[...Jc(e.range,t)],o=[...Jc(e.range,r)],a=i=>o.map(c=>n.map(l=>i(hx(e,l,c)))),s=fx(e);return{kind:"map",name:e.name,area:e.area,...e.frame?{frame:{...e.frame}}:{},axes:{[t]:n,[r]:o},clFront:a(i=>i.clFront),clRear:a(i=>i.clRear),cd:a(i=>i.cd),provenance:{...e.provenance},...s?{attitude:s}:{}}}var pd=180/Math.PI,bx=new WeakMap,gx=new WeakMap,dd=new WeakMap;function Zr(e,t){let r=gx.get(e);if(r)return r;let n=t?.wheelbase,o=n!==void 0?dd.get(e)?.get(n):void 0;if(o)return o;let a=cT(e),s=a.map;if(!qr(s)){let l=lT(e,a);return gx.set(e,l),l}if(n===void 0||!Number.isFinite(n)||n<=0)throw new Error("A ride-height-and-pitch aero map is read with the car\u2019s wheelbase, and none was given.");let i=uT(e,a,s.frame,n),c=dd.get(e);return c||(c=new Map,dd.set(e,c)),c.set(n,i),i}function cT(e){let t=bx.get(e);if(t)return t;let r=os(e);if(r)throw new Error(r);let n=e.kind==="map"?e:md(e),{x:o,y:a}=No(n),s=o.length,i=a.length,c=n.attitude?.yaw,l=n.attitude?.roll,u=!!(c||l),m={clFront:1,clRear:1,cd:1,clamped:!1},f=(y,R)=>{let k=Math.abs(R),v=y.clFront.deg[y.clFront.deg.length-1];return{clFront:$e(y.clFront.deg,y.clFront.factor,k),clRear:$e(y.clRear.deg,y.clRear.factor,k),cd:$e(y.cd.deg,y.cd.factor,k),clamped:k>v}},p=(y,R)=>{if(!u)return m;let k=c?f(c,y):m,v=l?f(l,R):m;return{clFront:k.clFront*v.clFront,clRear:k.clRear*v.clRear,cd:k.cd*v.cd,clamped:k.clamped||v.clamped}},d=(y,R,k=0,v=0)=>{let x=Ln(o,y),M=Ln(a,R),F=Math.min(x.i+1,s-1),w=Math.min(M.i+1,i-1),C=S=>{let A=S[M.i][x.i],P=S[M.i][F],L=S[w][x.i],D=S[w][F],E=A+x.t*(P-A),V=L+x.t*(D-L);return E+M.t*(V-E)},T=p(k,v);return{clFront:u?C(n.clFront)*T.clFront:C(n.clFront),clRear:u?C(n.clRear)*T.clRear:C(n.clRear),cd:u?C(n.cd)*T.cd:C(n.cd),clampedRide:x.clamped||M.clamped,clampedAttitude:T.clamped}},h={x:[o[0],o[s-1]],y:[a[0],a[i-1]]},b=(y,R,k=!1,v=0,x=0)=>{let M=p(v,x),F=Ln(o,k?Math.min(Math.max(y,h.x[0]),h.x[1]):y),w=Ln(a,k?Math.min(Math.max(R,h.y[0]),h.y[1]):R),C=Math.min(F.i+1,s-1),T=Math.min(w.i+1,i-1),S=C>F.i?o[C]-o[F.i]:0,A=T>w.i?a[T]-a[w.i]:0,P={};for(let L of Qr){let D=n[L],E=D[w.i][F.i],V=D[w.i][C],N=D[T][F.i],z=D[T][C],I=F.clamped||S===0?0:((V-E)*(1-w.t)+(z-N)*w.t)/S,_=w.clamped||A===0?0:((N-E)*(1-F.t)+(z-V)*F.t)/A;P[L]=u?{x:I*M[L],y:_*M[L]}:{x:I,y:_}}return P},g={map:n,x:h.x,y:h.y,hasAttitude:u,factors:p,at:d,slopes:b};return bx.set(e,g),g}function lT(e,t){let r={x:t.x,y:t.y,at:t.at,toAxles:(o,a)=>({hFront:o,hRear:a}),fromAxles:(o,a)=>({x:o,y:a})},n=(o,a,s=!1,i=0,c=0)=>{let l=t.slopes(o,a,s,i,c),u={};for(let m of Qr)u[m]={hFront:l[m].x,hRear:l[m].y};return u};return{model:e,map:t.map,area:t.map.area,grid:r,hasAttitude:t.hasAttitude,at:t.at,slopes:n,factors:t.factors}}function uT(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)*pd,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)*pd,m,f,p),b=pd/(n*(1+d*d)),g={};for(let y of Qr)g[y]={hFront:h[y].x*(1-a)-h[y].y*b,hRear:h[y].x*a+h[y].y*b};return g},c={frame:r,x:t.x,y:t.y,at:t.at,toAxles:(l,u)=>Vo(r,n,l,u),fromAxles:(l,u)=>{let m=Oo(r,n,l,u);return{x:m.h,y:m.pitch}}};return{model:e,map:t.map,area:t.map.area,grid:c,hasAttitude:t.hasAttitude,at:s,slopes:i,factors:t.factors}}function fd(e){let t=e.clFront+e.clRear;return{cl:t,balanceFront:t!==0?e.clFront/t:.5}}var he=(e,t)=>e*t/100,Qe=e=>e/100,yx={name:"Formula Student aero",area:1,cl:3,balanceFront:.45,cd:1.3,ref:{hFront:30,hRear:35},range:{hFront:[5,60],hRear:[10,70]},dCl:{hFront:he(3,-.4),hRear:he(3,.1)},dBalance:{hFront:Qe(-.3),hRear:Qe(.15)},dCd:{hFront:he(1.3,-.1),hRear:he(1.3,.05)},yaw:{dCl:he(3,-1),dBalance:Qe(-.3),dCd:he(1.3,.5),maxDeg:10},roll:{dCl:he(3,-.5),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for an undertray-and-wings Formula Student car, ride height, yaw and roll; not measured."},xx={name:"Formula 1 aero",area:1.5,cl:3,balanceFront:.44,cd:.9,ref:{hFront:35,hRear:70},range:{hFront:[0,60],hRear:[20,100]},dCl:{hFront:he(3,-.3),hRear:he(3,-.15)},dBalance:{hFront:Qe(-.15),hRear:Qe(.15)},dCd:{hFront:he(.9,-.15),hRear:he(.9,-.05)},yaw:{dCl:he(3,-1.5),dBalance:Qe(.2),dCd:he(.9,.8),maxDeg:8},roll:{dCl:he(3,-1),dBalance:Qe(-.3),dCd:0,maxDeg:2},note:"Assumed class-level sensitivities for a ground-effect floor, ride height, yaw and roll; not measured."},Rx={name:"GT car aero",area:2,cl:1.4,balanceFront:.42,cd:.42,ref:{hFront:55,hRear:75},range:{hFront:[10,90],hRear:[10,110]},dCl:{hFront:he(1.4,-.3),hRear:he(1.4,.05)},dBalance:{hFront:Qe(-.25),hRear:Qe(.15)},dCd:{hFront:he(.42,-.1),hRear:0},yaw:{dCl:he(1.4,-.8),dBalance:Qe(-.2),dCd:he(.42,.6),maxDeg:10},roll:{dCl:he(1.4,-.3),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a splitter-and-wing GT car, ride height, yaw and roll; not measured."},vx={name:"Sports car aero",area:2.2,cl:-.1,balanceFront:.5,cd:.3,ref:{hFront:130,hRear:140},range:{hFront:[80,180],hRear:[100,200]},dCl:{hFront:-5e-4,hRear:0},dBalance:{hFront:0,hRear:0},dCd:{hFront:2e-4,hRear:0},yaw:{dCl:0,dBalance:0,dCd:he(.3,.5),maxDeg:10},note:"Assumed class-level sensitivities for a road car with no aero devices; not measured."},kx={name:"Cup car aero",area:2.1,cl:.45,balanceFront:.45,cd:.4,ref:{hFront:64,hRear:78},range:{hFront:[20,100],hRear:[30,120]},dCl:{hFront:he(.45,-.4),hRear:he(.45,.05)},dBalance:{hFront:Qe(-.25),hRear:Qe(.15)},dCd:{hFront:he(.4,-.1),hRear:0},yaw:{dCl:he(.45,-1.2),dBalance:Qe(-.2),dCd:he(.4,.6),maxDeg:10},roll:{dCl:he(.45,-.3),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a splitter-and-wing cup hatchback, ride height, yaw and roll; not measured."},Mx={name:"Stock car aero",area:2.2,cl:.6,balanceFront:.45,cd:.45,ref:{hFront:75,hRear:90},range:{hFront:[20,110],hRear:[30,130]},dCl:{hFront:he(.6,-.35),hRear:he(.6,.05)},dBalance:{hFront:Qe(-.25),hRear:Qe(.15)},dCd:{hFront:he(.45,-.1),hRear:0},yaw:{dCl:he(.6,-1),dBalance:Qe(-.2),dCd:he(.45,.6),maxDeg:10},roll:{dCl:he(.6,-.3),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a splitter-and-spoiler stock car, ride height, yaw and roll; not measured."},Sx={name:"Hill-climb prototype aero",area:1.2,cl:2.5,balanceFront:.42,cd:.9,ref:{hFront:45,hRear:55},range:{hFront:[10,80],hRear:[15,95]},dCl:{hFront:he(2.5,-.35),hRear:he(2.5,.05)},dBalance:{hFront:Qe(-.25),hRear:Qe(.15)},dCd:{hFront:he(.9,-.1),hRear:he(.9,.05)},yaw:{dCl:he(2.5,-1),dBalance:Qe(-.3),dCd:he(.9,.5),maxDeg:10},roll:{dCl:he(2.5,-.5),dBalance:0,dCd:0,maxDeg:3},note:"Assumed class-level sensitivities for a winged sports prototype with a flat floor and diffuser, ride height, yaw and roll; not measured."},Ax={name:"Race truck aero",area:6.2,cl:-.1,balanceFront:.6,cd:.65,ref:{hFront:110,hRear:240},range:{hFront:[60,160],hRear:[180,300]},dCl:{hFront:-5e-4,hRear:0},dBalance:{hFront:0,hRear:0},dCd:{hFront:2e-4,hRear:0},yaw:{dCl:0,dBalance:0,dCd:he(.65,.5),maxDeg:10},note:"Assumed class-level sensitivities for a cab-over race truck with a chin spoiler and deflectors, ride height and yaw; not measured."};function vr(e){return ud({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 hd=()=>vr(yx),bd=()=>vr(xx),gd=()=>vr(Rx),yd=()=>vr(vx),xd=()=>vr(kx),Rd=()=>vr(Mx),vd=()=>vr(Sx),kd=()=>vr(Ax);function Dn(e,t){let r=.5*e.rho*e.area*t*t,n=e.cl*r,o=e.cw*r,a=n*e.copLongFront;return{downforce:n,drag:o,downFront:a,downRear:n-a}}function tl(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 rl(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 Md(e,t){return e.wheelbase>0?e.massTotal*t*9.81/e.wheelbase:0}function Bo(e,t,r){let n=2*t.rideRateFront,o=2*t.rideRateRear;return!(n>0)||!(o>0)?0:Math.min(sd(t.sprungMass,r,e.wheelbase),.5*n*o/(n+o))}function as(e,t,r,n,o){let a=e.cgHeight,s=Md(e,r);if(n===0&&o===0&&s===0)return{height:a,forward:0,noseLoad:0,dropFront:0,dropRear:0};let i=tl(e,t),c=2*t.rideRateFront,l=2*t.rideRateRear,u=a,m=0,f=0,p=0;for(let h=0;h<6;h++){p=Bo(e,t,u);let b=n-s*u,g=o+s*u;if(p>0){let k=c*l-p*(c+l);m=(b*(l-p)-p*g)/k,f=(g*(c-p)-p*b)/k}else m=c>0?b/c:0,f=l>0?g/l:0;let y=rl(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 Sd={yawDeg:0,rollDeg:0},Fx=1e-4,mT=40,wx=50;function Jr(e,t,r=0){let n=e.aero?.model;if(!(!n||!Zr(n,e).hasAttitude))return{yawDeg:r,rollDeg:we(e).rollGradient*t}}function $o(e,t){if(e.rideHeightFront!=null&&e.rideHeightRear!=null)return{hFront:e.rideHeightFront,hRear:e.rideHeightRear};let r=e.model,n=(a,s,i)=>{if(t!==void 0&&t>0)return Vo(a,t,s,i);throw new Error("A ride-height-and-pitch aero model is read with the car\u2019s wheelbase, and none was given.")},o={hFront:0,hRear:0};if(r?.kind==="sensitivity")o=Qc(r)?n(r.frame,r.ref.h,r.ref.pitch):r.ref;else if(r){let{x:a,y:s}=No(r),i=(a[0]+a[a.length-1])/2,c=(s[0]+s[s.length-1])/2;o=qr(r)?n(r.frame,i,c):{hFront:i,hRear:c}}return{hFront:e.rideHeightFront??o.hFront,hRear:e.rideHeightRear??o.hRear}}var Cx=new WeakMap;function kr(e,t,r=0,n){let o=e.aero;if(!o?.model)return null;let a=Cx.get(e);a||(a=new Map,Cx.set(e,a));let s=n&&Zr(o.model,e).hasAttitude?n:Sd,i=s===Sd?`${t}|${r}`:`${t}|${r}|${s.yawDeg.toFixed(3)}|${s.rollDeg.toFixed(3)}`,c=a.get(i);if(c)return c;let l=pT(e,o,t,r,s);return a.size>4096&&a.clear(),a.set(i,l),l}function pT(e,t,r,n,o){let a=Zr(t.model,e),s=we(e),i=2*s.rideRateFront,c=2*s.rideRateRear,l=$o(t,e.wheelbase),u=.5*t.rho*r*r,m=a.area,f=e.wheelbase>0?t.copHeight/e.wheelbase:0,p=tl(e,s),d=Md(e,n),h=(C,T)=>rl(e.cgHeight,p,l.hFront-C,l.hRear-T),b=(C,T)=>l.hFront-C-(l.hRear-T),g=(C,T)=>{let S=a.at(C,T,o.yawDeg,o.rollDeg),A=u*m*S.clFront,P=u*m*S.clRear,L=u*m*S.cd,D=L*f,E=h(C,T),V=d*E,N=Bo(e,s,E)*b(C,T),z=A-V-D+N,I=P+V+D-N,_=C-l.hFront+(i>0?z/i:0),B=T-l.hRear+(c>0?I/c:0);return{c:S,downFront:A,downRear:P,drag:L,rF:_,rR:B,norm:Math.hypot(_,B)}},y=(C,T,S=!1)=>{let A=a.slopes(C,T,S,o.yawDeg,o.rollDeg),P=i>0?u*m/i:0,L=c>0?u*m/c:0;return[[P*(A.clFront.hFront-f*A.cd.hFront),P*(A.clFront.hRear-f*A.cd.hRear)],[L*(A.clRear.hFront+f*A.cd.hFront),L*(A.clRear.hRear+f*A.cd.hRear)]]},R=l.hFront,k=l.hRear,v=g(R,k),x=0;for(;v.norm>=Fx&&x<mT;){x++;let C=y(R,k),T=i>0?d/i:0,S=c>0?d/c:0,A=Bo(e,s,h(R,k)),P=i>0?A/i:0,L=c>0?A/c:0,D=1+C[0][0]-T*p.front-P,E=C[0][1]-T*p.rear+P,V=C[1][0]+S*p.front+L,N=1+C[1][1]+S*p.rear-L,z=D*N-E*V,I,_;Math.abs(z)>1e-9?(I=-(N*v.rF-E*v.rR)/z,_=-(-V*v.rF+D*v.rR)/z):(I=-.5*v.rF,_=-.5*v.rR);let B=Math.max(1,Math.abs(I)/wx,Math.abs(_)/wx);I/=B,_/=B;let O=1;for(let G=0;G<6;G++){let K=g(R+O*I,k+O*_);if(K.norm<=v.norm||G===5){R+=O*I,k+=O*_,v=K;break}O*=.5}}let M=y(R,k,!0),F=2+M[0][0]+M[1][1],w=(1+M[0][0])*(1+M[1][1])-M[0][1]*M[1][0];return{v:r,axG:n,hFront:R,hRear:k,cgHeight:h(R,k),cgForward:e.wheelbase>0?h(R,k)*b(R,k)/e.wheelbase:0,cgNoseLoad:Bo(e,s,h(R,k))*b(R,k),clFront:v.c.clFront,clRear:v.c.clRear,cd:v.c.cd,area:m,downforce:v.downFront+v.downRear,drag:v.drag,downFront:v.downFront,downRear:v.downRear,gain:dT(M),stable:w>0&&F>0,converged:v.norm<Fx,iterations:x,clampedRide:v.c.clampedRide,yawDeg:o.yawDeg,rollDeg:o.rollDeg,clampedAttitude:v.c.clampedAttitude}}function dT(e){let t=e[0][0]+e[1][1],r=e[0][0]*e[1][1]-e[0][1]*e[1][0],n=t*t-4*r;if(n>=0){let o=Math.sqrt(n);return Math.max(Math.abs((t+o)/2),Math.abs((t-o)/2))}return Math.sqrt(r)}function ss(e,t,r=0,n){let o=kr(e,t,r,n);return o?{downforce:o.downforce,drag:o.drag,downFront:o.downFront,downRear:o.downRear}:e.aero?Dn(e.aero,t):{downforce:0,drag:0,downFront:0,downRear:0}}function fT(e,t,r,n){let o=Dn(t,r),a=we(e),s=$o(t,e.wheelbase),i=e.wheelbase>0?o.drag*t.copHeight/e.wheelbase:0,c=as(e,a,n,o.downFront-i,o.downRear+i),l=o.downforce;return{v:r,axG:n,hFront:s.hFront-c.dropFront,hRear:s.hRear-c.dropRear,cgHeight:c.height,cgForward:c.forward,cgNoseLoad:c.noseLoad,clFront:t.cl*t.copLongFront,clRear:t.cl*(1-t.copLongFront),cd:t.cw,area:t.area,downforce:l,drag:o.drag,downFront:o.downFront,downRear:o.downRear,gain:0,stable:!0,converged:!0,iterations:0,clampedRide:!1,yawDeg:0,rollDeg:0,clampedAttitude:!1}}function Ad(e,t,r=0,n){let o=kr(e,t,r,n);return o||(e.aero?fT(e,e.aero,t,r):null)}function nl(e,t=0,r=0,n,o){if(e.aero&&t>0){if(e.aero.model){let i=kr(e,t,r,n);return{height:i.cgHeight,forward:i.cgForward,noseLoad:i.cgNoseLoad}}let a=Dn(e.aero,t),s=e.wheelbase>0?a.drag*e.aero.copHeight/e.wheelbase:0;return as(e,o??we(e),r,a.downFront-s,a.downRear+s)}return r===0?{height:e.cgHeight,forward:0,noseLoad:0}:as(e,o??we(e),r,0,0)}var Tx=[0,1,0],Fd=[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],wd=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]],hT=e=>X(e,e),en=e=>Math.sqrt(X(e,e)),is=(e,t)=>hT(H(e,t)),ve=(e,t)=>en(H(e,t)),Q=e=>{let t=en(e);return t<1e-12?[0,0,0]:[e[0]/t,e[1]/t,e[2]/t]};var tn=(e,t,r)=>{let n=Q(r),o=H(e,t);return ee(t,U(n,X(o,n)))},Px=(e,t,r)=>ve(e,tn(e,t,r));var gT=1e-6;function yT(e){if(e<gT){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]=yT(r),a=ae(e,t),s=ae(e,a);return ee(t,ee(U(a,n),U(s,o)))}function It(e,t,r){let n=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);if(n<1e-14)return e;let o=[t[0]/n,t[1]/n,t[2]/n];return ot(U(o,r),e)}function Jt(e,t){let r=t.length,n=e.map(a=>a.slice()),o=t.slice();return Dx(n,o,r,new Array(r).fill(0))}function Lx(e,t,r){return Dx(e,t,t.length,r)}function Dx(e,t,r,n){let o=1/0,a=0;for(let s=0;s<r;s++){let i=s,c=Math.abs(e[s][s]);for(let u=s+1;u<r;u++){let m=Math.abs(e[u][s]);m>c&&(c=m,i=u)}if(c<1e-14){for(let u=0;u<r;u++)n[u]=NaN;return{x:n,condProxy:1/0,singular:!0}}if(o=Math.min(o,c),a=Math.max(a,c),i!==s){let u=e[s];e[s]=e[i],e[i]=u;let m=t[s];t[s]=t[i],t[i]=m}let l=e[s][s];for(let u=s+1;u<r;u++){let m=e[u][s]/l;if(m!==0){for(let f=s;f<r;f++)e[u][f]-=m*e[s][f];t[u]-=m*t[s]}}}for(let s=r-1;s>=0;s--){let i=t[s];for(let c=s+1;c<r;c++)i-=e[s][c]*n[c];n[s]=i/e[s][s]}return{x:n,condProxy:a/o,singular:!1}}var Ex=e=>{let t=0;for(let r of e)t=Math.max(t,Math.abs(r));return t},Ix=e=>{let t=0;for(let r of e)t+=r*r;return t},xT=Math.sqrt(Number.EPSILON);function _x(e,t,r={}){let n=r.maxIter??60,o=r.tol??1e-10,a=t.length,s=r.scales??new Array(a).fill(1),i=t.slice(),c=e(i),l=Ex(c),u=Ix(c),m=.001,f=1,p=c.length,d=Array.from({length:p},()=>new Array(a).fill(0)),h=Array.from({length:a},()=>new Array(a).fill(0)),b=Array.from({length:a},()=>new Array(a).fill(0)),g=new Array(a).fill(0),y=new Array(a).fill(0),R=new Array(a).fill(0),k=new Array(a).fill(0),v=new Array(a).fill(0);for(let x=0;x<n;x++){if(l<o)return{x:i,residualNorm:l,iterations:x,converged:!0,condProxy:f};for(let C=0;C<a;C++){let T=xT*Math.max(Math.abs(i[C]),s[C]);for(let A=0;A<a;A++)k[A]=i[A];k[C]+=T;let S=e(k);for(let A=0;A<p;A++)d[A][C]=(S[A]-c[A])/T}let M=0;for(let C=0;C<a;C++){for(let S=0;S<a;S++){let A=0;for(let P=0;P<p;P++)A+=d[P][C]*d[P][S];h[C][S]=A}let T=0;for(let S=0;S<p;S++)T+=d[S][C]*c[S];g[C]=T,M=Math.max(M,h[C][C])}let F=Math.max(M,1e-9),w=!1;for(let C=0;C<18;C++){let T=m*F;for(let A=0;A<a;A++){let P=h[A],L=b[A];for(let D=0;D<a;D++)L[D]=A===D?P[D]+T:P[D];y[A]=-g[A]}let S=Lx(b,y,R);if(f=Math.max(f,S.condProxy),!S.singular){for(let L=0;L<a;L++)v[L]=i[L]+R[L];let A=e(v),P=Ix(A);if(P<u){for(let L=0;L<a;L++)i[L]=v[L];c=A,u=P,l=Ex(c),m=Math.max(m*.3,1e-12),w=!0;break}}m=Math.min(m*4,1e12)}if(!w)break}return{x:i,residualNorm:l,iterations:n,converged:l<o,condProxy:f}}function cs(e,t,r,n){let o=e*e+t*t,a=Math.sqrt(o);if(!(a>1e-12*n))return{c1:1,s1:0,c2:1,s2:0,margin:0,ok:!1,free:!0};let s=Math.abs(r),i=1-s/a;if(i<0){let l=r>=0?1:-1,u=l*e/a,m=l*t/a;return{c1:u,s1:m,c2:u,s2:m,margin:i,ok:i>=-1e-12,free:!1}}let c=Math.sqrt((a-s)*(a+s));return{c1:(e*r-t*c)/o,s1:(t*r+e*c)/o,c2:(e*r+t*c)/o,s2:(t*r-e*c)/o,margin:i,ok:!0,free:!1}}function Cd(e,t){return[e[0]*t[0]-e[1]*t[1]-e[2]*t[2]-e[3]*t[3],e[0]*t[1]+e[1]*t[0]+e[2]*t[3]-e[3]*t[2],e[0]*t[2]-e[1]*t[3]+e[2]*t[0]+e[3]*t[1],e[0]*t[3]+e[1]*t[2]-e[2]*t[1]+e[3]*t[0]]}var Nx=e=>[e[0],-e[1],-e[2],-e[3]];function Ox(e,t){let[r,n,o,a]=e,s=2*(o*t[2]-a*t[1]),i=2*(a*t[0]-n*t[2]),c=2*(n*t[1]-o*t[0]);return[t[0]+r*s+(o*c-a*i),t[1]+r*i+(a*s-n*c),t[2]+r*c+(n*i-o*s)]}function Vx(e,t){let r=e[0]*t[0]+e[1]*t[1]+e[2]*t[2];if(1+r<1e-14){let o=Math.abs(e[0])<.6?[1,0,0]:[0,1,0],a=e[1]*o[2]-e[2]*o[1],s=e[2]*o[0]-e[0]*o[2],i=e[0]*o[1]-e[1]*o[0],c=Math.hypot(a,s,i);return[0,a/c,s/c,i/c]}let n=Math.sqrt(2*(1+r));return[(1+r)/n,(e[1]*t[2]-e[2]*t[1])/n,(e[2]*t[0]-e[0]*t[2])/n,(e[0]*t[1]-e[1]*t[0])/n]}function Bx(e,t,r){let n,o;return t>=0?(n=Math.sqrt((1+t)/2),o=r/(2*n)):(o=(r>=0?1:-1)*Math.sqrt((1-t)/2),n=r/(2*o)),[n,o*e[0],o*e[1],o*e[2]]}function Td(e,t,r){let n=e[0],o=e[1],a=e[2],s=t[0],i=t[1],c=t[2],l=r[0],u=r[1],m=r[2],f=n+i+m;if(f>=n&&f>=i&&f>=m){let h=Math.sqrt(1+f),b=.5/h;return[.5*h,(c-u)*b,(l-a)*b,(o-s)*b]}if(n>=i&&n>=m){let h=Math.sqrt(1+n-i-m),b=.5/h;return[(c-u)*b,.5*h,(s+o)*b,(l+a)*b]}if(i>=m){let h=Math.sqrt(1-n+i-m),b=.5/h;return[(l-a)*b,(s+o)*b,.5*h,(u+c)*b]}let p=Math.sqrt(1-n-i+m),d=.5/p;return[(o-s)*d,(l+a)*d,(u+c)*d,.5*p]}function $x(e){let t=Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]);if(t===0)return[1,0,0,0];let r=Math.sin(t/2)/t;return[Math.cos(t/2),r*e[0],r*e[1],r*e[2]]}function Gx(e){let[t,r,n,o]=e;t<0&&(t=-t,r=-r,n=-n,o=-o);let a=Math.sqrt(r*r+n*n+o*o);if(a===0)return[0,0,0];let s=2*Math.atan2(a,t)/a;return[s*r,s*n,s*o]}function RT(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 vT(e){let t=e.hardpoints,r=Q(H(t.damperChassis,t.pushrodOuter)),[n,o]=RT(r);return{top:t.damperChassis,lower0:t.pushrodOuter,axis0:r,e1:n,e2:o}}function Pd(e){let t=e.hardpoints,r=t.wheelCenter,n=Q(H(t.ucaRear,t.ucaFront)),o=H(t.uprightUpper,t.ucaFront),a=X(o,n),s=H(o,U(n,a)),i=X(s,s),c=Q(H(t.lcaRear,t.lcaFront)),l=H(t.uprightLower,t.lcaFront),u=is(t.tieOuter,t.tieInner);return{c0:r,ucaFront:t.ucaFront,ucaDir:n,ubj0:t.uprightUpper,ubjAxial0:a,ubjRadius2:i,lcaFront:t.lcaFront,lcaDir:c,lbj0:t.uprightLower,lbjRel0:l,tro0:t.tieOuter,tieInner0:t.tieInner,tieLen2:u,rackAxis:Q(e.config.rackAxis),steerMovesRack:e.config.steerMode==="rack",ubjRadiusRef:Math.max(1,2*Math.sqrt(i)),tieLenRef:Math.max(1,2*Math.sqrt(u)),...e.config.layout==="mcpherson"?{strut:vT(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 Ld(e,t){return ee(e.lcaFront,It(e.lbjRel0,e.lcaDir,t))}function Go(e,t){return e.steerMovesRack?ee(e.tieInner0,U(e.rackAxis,t)):e.tieInner0}function Dd(e,t,r,n){let o=_t(e,t,e.lbj0),a=Ld(e,r),s=o[0]-a[0],i=o[1]-a[1],c=o[2]-a[2],l,u;if(e.strut){let d=e.strut,h=[t[3],t[4],t[5]],b=H(d.top,_t(e,t,d.lower0));l=X(b,ot(h,d.e1)),u=X(b,ot(h,d.e2))}else{let d=_t(e,t,e.ubj0),h=H(d,e.ucaFront),b=X(h,e.ucaDir),g=H(h,U(e.ucaDir,b));l=b-e.ubjAxial0,u=(X(g,g)-e.ubjRadius2)/e.ubjRadiusRef}let m=_t(e,t,e.tro0),f=Go(e,n),p=(is(m,f)-e.tieLen2)/e.tieLenRef;return[s,i,c,l,u,p]}var ls=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]),ol=e=>{let t=ls(e);return[e[0]/t,e[1]/t,e[2]/t]},kT=(e,t)=>H(e,U(t,X(e,t))),Ed=e=>ol(ae(e,Math.abs(e[0])<.6?[1,0,0]:[0,1,0]));function MT(e,t){let r=e.ucaDir,n=ee(e.ucaFront,U(r,e.ubjAxial0)),o=Math.sqrt(e.ubjRadius2),a=kT(H(e.ubj0,e.ucaFront),r),s=ls(a)>1e-9?ol(a):Ed(r),i=ae(r,s),c=H(e.ubj0,e.lbj0),l=X(c,c);if(!(l>1e-18))return"free";let u=H(n,t),m=X(u,u),f=cs(2*o*X(s,u),2*o*X(i,u),l-m-o*o,2*o*Math.sqrt(m));if(f.free)return"free";let p=ol(c),d=(h,b)=>{let g=ee(n,ee(U(s,o*h),U(i,o*b))),y=ol(H(g,t));return{q1:Vx(p,y),k:y,margin:f.margin,ok:f.ok}};return f.margin>0?[d(f.c1,f.s1),d(f.c2,f.s2)]:[d(f.c1,f.s1)]}function ST(e,t,r){let n=t.axis0,o=ee(t.lower0,U(n,X(H(e.lbj0,t.lower0),n))),a=H(o,e.lbj0),s=ls(a),i=s>1e-9?U(a,1/s):Ed(n),c=H(t.top,r),l=ls(c);if(!(l>1e-9))return"free";let u=U(c,1/l),m=s/l,f=1-m,p=f>=0?Math.sqrt((1-m)*(1+m)):0,d=Ed(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:Cd(Td(R,y,ae(R,y)),Nx(Td(i,n,ae(i,n)))),k:u,margin:f,ok:f>=0}};return f>0?[h(1),h(-1)]:[h(1)]}function AT(e,t,r,n){let{k:o}=n,a=Ox(n.q1,H(e.tro0,e.lbj0)),s=X(a,o),i=H(a,U(o,s)),c=ls(i);if(!(c>1e-9))return"free";let l=U(i,1/c),u=ae(o,l),m=ee(t,U(o,s)),f=H(m,r),p=X(f,f),d=cs(2*c*X(f,l),2*c*X(f,u),e.tieLen2-p-c*c,2*c*Math.sqrt(p));if(d.free)return"free";let h=(g,y)=>({q:Cd(Bx(o,g,y),n.q1)});return{roots:d.margin>0?[h(d.c1,d.s1),h(d.c2,d.s2)]:[h(d.c1,d.s1)],margin:d.margin,ok:d.ok}}function Kx(e,t,r,n=[0,0,0,0,0,0]){let o=Ld(e,t),a=Go(e,r),s=$x([n[3],n[4],n[5]]),i=h=>Math.abs(h[0]*s[0]+h[1]*s[1]+h[2]*s[2]+h[3]*s[3]),c=e.strut?ST(e,e.strut,o):MT(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=AT(e,o,a,h);if(b==="free")return{x:n.slice(),converged:!1,margin:0,free:!0};let g=Math.min(h.margin,b.margin),y=b.ok&&h.ok;for(let{q:R}of b.roots){let k=i(R);y&&(!l||k>l.near)&&(l={q:R,margin:g,near:k}),!y&&(!u||k>u.near)&&(u={q:R,margin:g,near:k})}}let{q:m,margin:f}=l??u,p=Gx(m),d=H(H(o,e.c0),ot(p,H(e.lbj0,e.c0)));return{x:[d[0],d[1],d[2],p[0],p[1],p[2]],converged:l!==null,margin:f,free:!1}}function zx(e){let t=Q(H(e.rockerPivotB,e.rockerPivotA));return{pivotA:e.rockerPivotA,axis:t,rprRel0:H(e.rockerToPushrod,e.rockerPivotA),rdmRel0:H(e.rockerToDamper,e.rockerPivotA),damperChassis:e.damperChassis,rodLen2:is(e.pushrodOuter,e.rockerToPushrod),damperLen0:ve(e.rockerToDamper,e.damperChassis)}}var FT=(e,t)=>ee(e.pivotA,It(e.rprRel0,e.axis,t)),Id=(e,t)=>ee(e.pivotA,It(e.rdmRel0,e.axis,t));function us(e,t){return{pushrod:FT(e,t),damper:Id(e,t)}}function Yx(e,t,r=0){let n=X(e.rprRel0,e.axis),o=H(e.rprRel0,U(e.axis,n)),a=ae(e.axis,o),s=H(ee(e.pivotA,U(e.axis,n)),t),i=X(o,o),c=X(s,s),l=cs(2*X(s,o),2*X(s,a),e.rodLen2-c-i,2*Math.sqrt(i*c));if(l.free){let p=Math.abs(e.rodLen2-c-i)<=1e-9*e.rodLen2;return{phi:r,damperLength:ve(Id(e,r),e.damperChassis),converged:p,margin:0}}let u=Hx(Math.atan2(l.s1,l.c1),r),m=Hx(Math.atan2(l.s2,l.c2),r),f=Math.abs(m-r)<Math.abs(u-r)?m:u;return{phi:f,damperLength:ve(Id(e,f),e.damperChassis),converged:l.ok,margin:l.margin}}function Hx(e,t){let r=2*Math.PI;return e+r*Math.round((t-e)/r)}function Wx(e,t,r,n){return ee(t,ot(U(Q(r),n),H(e,t)))}function jx(e,t,r,n){let o=Q(n),a=f=>{let p=H(f,r);return H(p,U(o,X(p,o)))},s=a(e),i=a(t),c=Math.hypot(s[0],s[1],s[2]),l=Math.hypot(i[0],i[1],i[2]);if(c<1e-9||l<1e-9)return 0;let u=Math.min(1,Math.max(-1,X(s,i)/(c*l))),m=X(ae(s,i),o)/(c*l);return Math.atan2(m,u)}function Ux(e,t,r,n){return ee(t,ot(U(Q(r),n),H(e,t)))}var al=180/Math.PI,wT=(e,t,r)=>Math.max(t,Math.min(r,e)),Xx=[NaN,NaN,NaN];function ms(e){let t=Q(e.spinAxis),r=Q(H(e.uprightUpper,e.uprightLower)),n=-Math.asin(wT(t[2],-1,1))*al,o=Math.atan2(t[0],t[1])*al,a=Math.atan2(-r[0],r[2])*al,s=Math.atan2(-r[1],r[2])*al,i=Q(ee([0,0,-1],U(t,t[2]))),c=ee(e.wheelCenter,U(i,e.loadedRadius)),l=e.patchShift?[c[0]+e.patchShift.x,c[1]+e.patchShift.y,c[2]]:c,u=e.uprightLower,m=Math.abs(r[2])>1e-9,f=w=>ee(u,U(r,(w-u[2])/r[2])),p=m?f(l[2]):Xx,d=m?f(e.wheelCenter[2]):Xx,h=l[1]-p[1],b=p[0]-l[0],g=Q(ae(t,[0,0,1])),y=ae([0,0,1],g),R=H(l,p),k=X(R,y),v=-X(R,g),x=e.wheelCenter[1]-d[1],M=d[0]-e.wheelCenter[0],F=Px(e.tieOuter,u,r);return{camber:n,toe:o,caster:a,kpi:s,scrubRadius:h,mechanicalTrail:b,scrubAtWheel:k,trailAtWheel:v,kingpinOffset:x,casterOffset:M,steeringArm:F,contactPatch:l,kingpinGround:p,kingpinAtHub:d}}function tt(e){return{corner:e,inv:Pd(e),rocker:zx(e.hardpoints)}}var CT=[20,20,20,.2,.2,.2];function qx(e,t,r,n=[0,0,0,0,0,0]){let o=Kx(e,t,r,n);if(!o.free)return o;let a=TT(e,t,r,n);return{x:a.x,converged:a.converged,margin:0}}function TT(e,t,r,n=[0,0,0,0,0,0]){return _x(o=>Dd(e,o,t,r),n,{scales:CT,tol:1e-10,maxIter:40})}var PT=.01,sl=1.2,ht=e=>e.ok?e.state:null,at=e=>e.ok?e.state:e.nearest;function ye(e,t,r,n,o){let a=0,s=Ie(e,a,r,n,o);if(Math.abs(s.travel-t)<1e-4)return Qx(s,t,!1);let c=(Ie(e,.02,r,_d(s),o).travel-s.travel)/.02;(!Number.isFinite(c)||Math.abs(c)<1e-6)&&(c=1);let l=f=>Math.max(-sl,Math.min(sl,f)),u=l((t-s.travel)/c),m=Ie(e,u,r,_d(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,_d(s),o)}return Qx(m,t,Math.abs(u)===sl)}function Qx(e,t,r){let n=e.travel-t,o=Math.abs(n)<=PT,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 _d(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 LT(e,t,r,n,o){switch(e){case"upright":return _t(t,r,o.pushrodOuter);case"upperArm":{let a=_t(t,r,t.ubj0),s=jx(t.ubj0,a,t.ucaFront,t.ucaDir);return Ux(o.pushrodOuter,t.ucaFront,t.ucaDir,s)}default:return Wx(o.pushrodOuter,t.lcaFront,t.lcaDir,n)}}function Ie(e,t,r,n,o){let{inv:a,corner:s}=e,i=n?.q??[0,0,0,0,0,0],c=qx(a,t,r,i),l=c.x,u=[l[3],l[4],l[5]],m={t:[l[0],l[1],l[2]],omega:u},f=s.hardpoints,p=s.config,d=a.strut,h=d?d.top:_t(a,l,f.uprightUpper),b=_t(a,l,f.uprightLower),g=_t(a,l,f.tieOuter),y=_t(a,l,f.wheelCenter),R=Q(ot(u,p.spinAxis)),k=LT(d?"upright":p.pushrodAttach,a,l,t,f),v=d?d.top:f.damperChassis,x=d||p.actuation==="direct"?{phi:0,damperLength:ve(k,v),converged:!0,margin:1}:Yx(e.rocker,k,n?.phi??0),M=ms({uprightUpper:h,uprightLower:b,wheelCenter:y,spinAxis:R,tieOuter:g,loadedRadius:o?.loadedRadius??p.loadedRadius,patchShift:o?.patchShift});return{pose:m,beta:t,travel:l[2],steer:r,points:{uprightUpper:h,uprightLower:b,tieOuter:g,wheelCenter:y,pushrodOuter:k,spinAxis:R,contactPatch:M.contactPatch,kingpinGround:M.kingpinGround,kingpinAtHub:M.kingpinAtHub,rockerAngle:x.phi,damperLength:x.damperLength},metrics:{camber:M.camber,toe:M.toe,caster:M.caster,kpi:M.kpi,scrubRadius:M.scrubRadius,mechanicalTrail:M.mechanicalTrail,scrubAtWheel:M.scrubAtWheel,trailAtWheel:M.trailAtWheel,kingpinOffset:M.kingpinOffset,casterOffset:M.casterOffset,steeringArm:M.steeringArm,damperLength:x.damperLength},converged:c.converged&&x.converged,margin:Math.min(c.margin,x.margin)}}var Ko=e=>e==="FL"||e==="FR"?"front":"rear",Jx=e=>e==="FL"||e==="RL"?"left":"right";function Ge(e,t){return e.corners?.[t]??DT(e[Ko(t)],Jx(t))}function eR(e){let t=e.config.springSplit;return e.config.actuation==="decoupled"||t===void 0||!Number.isFinite(t)||Math.abs(t)>=1?0:t}var Zx=new WeakMap;function DT(e,t){let r=eR(e);if(r===0)return e;let n=Zx.get(e);if(!n){let o=a=>{let{springSplit:s,...i}=e.config;return{...e,config:{...i,springRate:e.config.springRate*a},...e.measured?{measured:{...e.measured,springRate:e.measured.springRate*a}}:{}}};n={left:o(1-r),right:o(1+r)},Zx.set(e,n)}return n[t]}var er=["FL","FR","RL","RR"],bt=e=>2*e.hardpoints.wheelCenter[1],Nt=(e,t)=>t?bt(Ge(e,"FL"))/2+bt(Ge(e,"FR"))/2:bt(Ge(e,"RL"))/2+bt(Ge(e,"RR"))/2;function Ze(e,t){let r=e==="FL"||e==="FR";return{axleX:r?t.frontAxleX:t.frontAxleX-t.wheelbase,sideSign:e==="FR"||e==="RR"?1:-1,isFront:r}}function Ot(e,t){return[t.axleX+e[0],t.sideSign*e[1],e[2]]}function rn(e,t){return[e[0],t.sideSign*e[1],e[2]]}function nn(e){return e.frontAxleX-e.wheelbase/2}function Nd(e,t,r){return t[2]+e.heave+(t[0]-r)*Math.sin(e.pitch)-t[1]*Math.sin(e.roll)}function on(e,t,r,n){let o=Ze(e,t),a=(n?Nt(n,o.isFront):o.isFront?t.trackFront:t.trackRear)/2,s=o.sideSign*a,i=o.axleX-nn(t),c=-r.heave-i*Math.sin(r.pitch)+s*Math.sin(r.roll),l=o.isFront?o.sideSign*r.steer:0;return{travel:c,steer:l}}var ET={travelMin:-40,travelMax:40,steps:41,steer:0};function ps(e){return{q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle}}function Ke(e,t={}){let r={...ET,...t},n=tt(e);return Ho(n,r)}function Ho(e,t){let r=t.steer,n=.01,o=Ie(e,n,r),a=Ie(e,-n,r),s=(o.travel-a.travel)/(2*n);(!Number.isFinite(s)||Math.abs(s)<1e-6)&&(s=1);let i=Math.max(Math.abs(t.travelMax),Math.abs(t.travelMin)),c=Math.min(1.2,1.5*i/Math.abs(s)),l=Math.max(20,t.steps*2),u=[],m=Ie(e,0,r);u.push({beta:0,travel:m.travel,warm:ps(m),converged:m.converged});let f=ps(m);for(let R=1;R<=l;R++){let k=c*R/l,v=Ie(e,k,r,f);f=ps(v),u.push({beta:k,travel:v.travel,warm:f,converged:v.converged})}f=ps(m);for(let R=1;R<=l;R++){let k=-c*R/l,v=Ie(e,k,r,f);f=ps(v),u.push({beta:k,travel:v.travel,warm:f,converged:v.converged})}u.sort((R,k)=>R.beta-k.beta);let p=u[u.length-1].travel>=u[0].travel,d=!1;for(let R=1;R<u.length;R++){let k=u[R].travel-u[R-1].travel;(p&&k<-1e-6||!p&&k>1e-6)&&(d=!0)}let h=u.filter(R=>R.converged).map(R=>R.travel),b=h.length?[Math.min(...h),Math.max(...h)]:[0,0],g=h.length>0&&b[0]<=t.travelMin+1e-6&&b[1]>=t.travelMax-1e-6,y=[];for(let R=0;R<t.steps;R++){let k=t.steps===1?t.travelMin:t.travelMin+(t.travelMax-t.travelMin)*R/(t.steps-1),v=IT(u,k,p),x=_T(u,v);y.push(Ie(e,v,r,x))}return NT(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 IT(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 _T(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 Od(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 NT(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=Od(n,r,s),c=Od(o,r,s),l=-Od(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 il=e=>e!==void 0&&Number.isFinite(e)&&e>0;function OT(e){return e&&il(e.helperRate)&&il(e.helperTravel)?{rate:e.helperRate,travel:e.helperTravel}:null}function Vd(e,t,r){let n=t/e;return r?n+Math.min(t/r.rate,r.travel):n}function ds(e,t,r,n){if(!(e>0)||!Number.isFinite(e)||!(t>0)||!Number.isFinite(t))return null;let o=OT(n),a=-Vd(e,t,o),s=zo(r,n);return{rate:e,preload:t,helper:o,free:a,pull:null,droop:s.droop??a,droopStated:s.droop!==null,bump:s.bump,holdsLoad:!0}}function zo(e,t){if(!Number.isFinite(e))return{droop:null,bump:null};let r=il(t?.extended)&&t.extended>e?t.extended:null,n=r!==null&&il(t?.stroke)?r-t.stroke:null;return{droop:r!==null?e-r:null,bump:n!==null&&n<e?e-n:null}}function Bd(e,t){if(!(e>0)||!Number.isFinite(e))return null;let r=zo(t.length0,t.coilover),n=t.free===-1/0||t.pull!==null&&t.pull>=t.free;if(n&&r.droop===null&&r.bump===null)return null;let o=n?-1/0:t.free;return{rate:e,preload:o===-1/0?0:-e*o,helper:null,free:o,pull:n?null:t.pull,droop:r.droop??-1/0,droopStated:r.droop!==null,bump:r.bump,holdsLoad:!1}}function VT(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=Vd(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 BT(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=Vd(r,n,o)+t;return a<=0?0:a>=o.rate*o.travel/r+o.travel?r:r*o.rate/(r+o.rate)}function Yo(e,t){let r=VT(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 $d(e,t){let r=BT(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 Gd(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 cl={min:-60,max:60,steps:61},Kd=e=>({travel:[e.min,e.max],force:[0,0],motionRatio:[0,0],spring:null}),tR=new WeakMap;function $T(e,t){let r=tR.get(e.corner);r||tR.set(e.corner,r=new Map);let n=`${t.min}|${t.max}|${t.steps}`,o=r.get(n);return o||r.set(n,o=Ho(e,{travelMin:t.min,travelMax:t.max,steps:t.steps,steer:0})),o}function hs(e,t,r=cl,n=e.corner.config.coilover){let o=e.corner.config;if(o.actuation==="decoupled")return Kd(r);let a=$T(e,r),s=KT(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 Kd(r);let c=zT(i,0);if(!(Math.abs(c.mr)>1e-6))return Kd(r);let l=t/c.mr,u=ds(s,l,c.L,n),m=u?GT(i,Gd(u).map(h=>c.L-h)):i,f=m.map(h=>(u?Yo(u,c.L-h.L):l+s*(c.L-h.L))*h.mr-t),p=h=>h===null?null:m.find(b=>b.L===c.L-h)?.t??null,d=u?Gd(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 Hd(e,t){if(!e.spring)return null;let r=e.travel.length,n=e.length;if(n&&n.length===r&&r>=2){let s=tr(e.travel,t),i=(t-e.travel[s])/(e.travel[s+1]-e.travel[s]);return e.spring.length0-(n[s]+i*(n[s+1]-n[s]))}if(r<2)return 0;let o=64,a=0;for(let s=0;s<o;s++){let i=t*s/o,c=t*(s+1)/o;a+=(fs(e,i)+fs(e,c))/2*(c-i)}return a}function GT(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 KT(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:HT(e,n,r);return!(o>0)||!Number.isFinite(o)?t:t*o/(t+o)}function HT(e,t,r){let n;for(let m of r)m.converged&&(!n||Math.abs(m.travel)<Math.abs(n.travel))&&(n=m);if(!n)return t;let o=e.corner.hardpoints,a=us(e.rocker,n.points.rockerAngle),s=Q(H(o.rockerPivotB,o.rockerPivotA)),i=(m,f)=>Math.abs(X(s,ae(H(m,o.rockerPivotA),Q(H(f,m))))),c=i(a.pushrod,n.points.pushrodOuter),l=i(a.damper,o.damperChassis);if(!(l>1e-9)||!(c>1e-9))return t;let u=c/l;return t*u*u}function fs(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.motionRatio[0];let n=tr(e.travel,t),o=(t-e.travel[n])/(e.travel[n+1]-e.travel[n]);return e.motionRatio[n]+o*(e.motionRatio[n+1]-e.motionRatio[n])}function Mr(e,t,r){if(!e.spring)return Yt(e,t);let{rate:n,preload:o,length0:a,law:s}=e.spring,i=fs(e,0),c=a-r;return(s?Yo(s,c):o+n*c)*fs(e,t)-o*i}function zT(e,t){let r=tr(e.map(s=>s.t),t),n=e[r],o=e[r+1],a=(t-n.t)/(o.t-n.t);return{L:n.L+a*(o.L-n.L),mr:n.mr+a*(o.mr-n.mr)}}function tr(e,t){let r=e.length;if(t<=e[0])return 0;if(t>=e[r-1])return r-2;let n=0,o=r-1;for(;o-n>1;){let a=n+o>>1;e[a]<=t?n=a:o=a}return n}function Yt(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.force[0];let n=tr(e.travel,t),o=(t-e.travel[n])/(e.travel[n+1]-e.travel[n]);return e.force[n]+o*(e.force[n+1]-e.force[n])}function Wo(e,t){let r=e.travel.length;if(r<3)return bs(e,t);let n=tr(e.travel,t),o=(e.force[n+1]-e.force[n])/(e.travel[n+1]-e.travel[n]),a=i=>i===0||i===r-1||e.kinks?.includes(e.travel[i])?o:(e.force[i+1]-e.force[i-1])/(e.travel[i+1]-e.travel[i-1]),s=Math.max(0,Math.min(1,(t-e.travel[n])/(e.travel[n+1]-e.travel[n])));return a(n)+s*(a(n+1)-a(n))}function bs(e,t){if(e.travel.length<2)return 0;let n=tr(e.travel,t);return(e.force[n+1]-e.force[n])/(e.travel[n+1]-e.travel[n])}function De(e,t,r){let n=e.hardpoints;switch(t.attach){case"upright":{let o=H(t.outer,n.wheelCenter);return ee(ee(ot(r.pose.omega,o),n.wheelCenter),r.pose.t)}case"lowerArm":{let o=Q(H(n.lcaRear,n.lcaFront));return ee(n.lcaFront,ot(U(o,r.beta),H(t.outer,n.lcaFront)))}case"rocker":{let o=Q(H(n.rockerPivotB,n.rockerPivotA));return ee(n.rockerPivotA,It(H(t.outer,n.rockerPivotA),o,r.points.rockerAngle))}}}function an(e,t,r){return e.config.actuation==="decoupled"&&t.attach==="rocker"&&r==="coil"}function zd(e,t,r){return an(e,t,r)?[t.inner[0],-t.inner[1],t.inner[2]]:t.inner}function jo(e,t,r){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return Yd(e,t,r.kind,Ke(e,{travelMin:n,travelMax:o,steps:a}).samples)}function Yd(e,t,r,n){let o=Q(H(t.outer,zd(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 Wd(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 jd(e,t){let{travel:r,linkTravel:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}var gs=e=>e.mount??{kind:"rockerToRocker"},aR=e=>[e[0],0,e[2]],YT=e=>2*Math.abs(e[1]),WT=(e,t)=>Math.hypot(e[0]-t[0],e[2]-t[2]);function ul(e,t){return t.kind==="chassis"?WT(e,t.anchor):YT(e)}function ys(e,t,r){if(r.kind==="chassis"){let s=[(e[0]+t[0])/2,(e[1]-t[1])/2,(e[2]+t[2])/2];return Math.hypot(s[0]-r.anchor[0],s[1],s[2]-r.anchor[2])}let n=e[0]-t[0],o=e[1]+t[1],a=e[2]-t[2];return Math.hypot(n,o,a)}function En(e,t,r={}){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return Ud(e,t,Ke(e,{travelMin:n,travelMax:o,steps:a}).samples)}function Ud(e,t,r){let n=gs(t),o=d=>De(e,{...t,inner:t.outer},r[d]),a=[],s=[],i=[];for(let d=0;d<r.length;d++)a.push(r[d].travel),i.push(ul(o(d),n));let c=nR(a,i,0);for(let d of i)s.push(c-d);let l=a.length,u=new Array(l).fill(0);for(let d=0;d<l;d++){let h=Math.max(0,d-1),b=Math.min(l-1,d+1),g=a[b]-a[h];u[d]=g!==0?(s[b]-s[h])/g:0}let m=rR(a,20),f=rR(a,-20),p=ys(o(m),o(f),n);return{travel:a,ratio:u,springTravel:s,atDesign:nR(a,u,0),installedLength:c,rollSensitivity:c-p}}function rR(e,t){let r=0,n=1/0;for(let o=0;o<e.length;o++){let a=Math.abs(e[o]-t);a<n&&(n=a,r=o)}return r}function nR(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];for(let o=1;o<n;o++)if(e[o]>=r){let a=e[o]-e[o-1],s=a!==0?(r-e[o-1])/a:0;return t[o-1]+s*(t[o]-t[o-1])}return t[n-1]}function Xd(e,t,r){let n={outer:t.outer,attach:t.attach},o=Ke(e,{travelMin:-5,travelMax:5,steps:3}),a=d=>aR(De(e,{...n,inner:n.outer},o.samples[d])),s=a(1),i=a(2),c=a(0),l=i[0]-c[0],u=i[2]-c[2],m=Math.hypot(l,u),f=m>1e-9?[l/m,u/m]:[0,1],p=r??Math.max(80,2*Math.abs(t.outer[1])*.5);return[s[0]+f[0]*p,0,s[2]+f[1]*p]}function Qd(e,t){let r=e.hardpoints,n=r.rockerPivotA,o=oR(ll(r.rockerPivotB,r.rockerPivotA)),a=Math.max(30,.6*sR(ll(r.rockerToDamper,n))),s=ll(r.rockerToDamper,n),i=oR(ll(s,jT(o,UT(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:Xd(e,d)}}:d,b;try{b=En(e,h,{travelMin:-20,travelMax:20,steps:9})}catch{continue}let g=b.atDesign/(1+4*Math.abs(b.rollSensitivity));Number.isFinite(g)&&g>u&&(u=g,l=h)}return l??{outer:r.rockerToDamper,attach:"rocker"}}var ll=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],jT=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],UT=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],sR=e=>Math.hypot(e[0],e[1],e[2]),oR=e=>{let t=sR(e)||1;return[e[0]/t,e[1]/t,e[2]/t]},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 qd=.001,QT=e=>({outer:e.outer,inner:e.outer,attach:e.attach}),fR=(e,t,r)=>(ul(e.at0,t)-ul(r,t))/2,qT=(e,t)=>X(H(t,e.pickup.at0),e.axis);function Zd(e,t){let r=e.length;return t.map((n,o)=>{let a=Math.max(0,o-1),s=Math.min(r-1,o+1);return(t[s]-t[a])/(e[s]-e[a])})}function iR(e,t){let r=[0,1,2].map(n=>Zd(e,t.map(o=>o[n])));return t.map((n,o)=>[r[0][o],r[1][o],r[2][o]])}function Jd(e){return{travel:e,heave:e.map(t=>t/2),heaveRatio:e.map(()=>.5),roll:[...e],rollRatio:e.map(()=>1)}}function cR(e,t,r,n){let o=e.corner;if(!t.heave&&!t.roll)return{side:Jd([n.min,n.max]),pickups:{}};let a=at(ye(e,0,0)),s={};if(t.heave&&r){let h=QT(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,zd(o,h,t.rollKind??"coil")))}}let i=t.roll&&an(o,t.roll,t.rollKind??"coil")?{near:t.roll,far:{...t.roll,outer:t.roll.inner}}:null,c=Ho(e,{travelMin:n.min,travelMax:n.max,steps:n.steps,steer:0}),l=[],u=[],m=[],f=[],p=[];for(let h of c.samples)!h.converged||l.length>0&&h.travel<=l[l.length-1]+1e-6||(l.push(h.travel),u.push(s.heave&&r?fR(s.heave,r,De(o,s.heave.link,h)):h.travel/2),m.push(s.roll?qT(s.roll,De(o,s.roll.pickup.link,h)):h.travel),i&&(f.push(De(o,i.near,h)),p.push(De(o,i.far,h))));if(l.length<2)return{side:Jd([n.min,n.max]),pickups:{}};let d={travel:l,heave:u,heaveRatio:Zd(l,u),roll:m,rollRatio:Zd(l,m)};return i&&(d.eyes={near:f,nearRatio:iR(l,f),far:p,farRatio:iR(l,p)}),{side:d,pickups:s}}function ml(e,t,r){let n=tr(e,r);return t[n]+(r-e[n])/(e[n+1]-e[n])*(t[n+1]-t[n])}function lR(e,t,r){let n=tr(e,r);return(t[n+1]-t[n])/(e[n+1]-e[n])}function _e(e,t){return{h:ml(e.travel,e.heave,t),dh:ml(e.travel,e.heaveRatio,t),ddh:lR(e.travel,e.heaveRatio,t),r:ml(e.travel,e.roll,t),dr:ml(e.travel,e.rollRatio,t),ddr:lR(e.travel,e.rollRatio,t)}}function uR(e,t,r,n){let o=tr(e,n),a=e[o+1]-e[o],s=(n-e[o])/a,i=(u,m)=>[u[0]+s*(m[0]-u[0]),u[1]+s*(m[1]-u[1]),u[2]+s*(m[2]-u[2])],c=r[o],l=r[o+1];return{p:i(t[o],t[o+1]),d:i(c,l),dd:[(l[0]-c[0])/a,(l[1]-c[1])/a,(l[2]-c[2])/a]}}var ef=(e,t)=>Math.hypot(e[0]-t[0],e[1]+t[1],e[2]-t[2]);function tf(e,t){let r=e.side[0].eyes,n=e.side[1].eyes;if(!r||!n)return null;let o=uR(e.side[0].travel,r.near,r.nearRatio,t[0]),a=uR(e.side[1].travel,n.far,n.farRatio,t[1]),s=[o.p[0]-a.p[0],o.p[1]+a.p[1],o.p[2]-a.p[2]],i=Math.hypot(s[0],s[1],s[2]),c=[s[0]/i,s[1]/i,s[2]/i],l=o.d,u=[-a.d[0],a.d[1],-a.d[2]],m=[-a.dd[0],a.dd[1],-a.dd[2]],f=X(c,l),p=X(c,u),d=(X(l,u)-f*p)/i;return{L:i,dL:[f,p],ddL:[[(X(l,l)-f*f)/i+X(c,o.dd),d],[d,(X(u,u)-p*p)/i+X(c,m)]]}}var hR=(e,t)=>e.bump!==null&&t>e.bump?e.rate*(t-e.bump):e.droop!==null&&t<e.droop?e.rate*(t-e.droop):0,ZT=(e,t)=>e.bump!==null&&t>e.bump||e.droop!==null&&t<e.droop?e.rate:0;function xs(e,t,r,n,o=0){let a=e.rollStop;if(!a)return r;let s=tf(e,t);if(!s)return r;let i=hR(a,a.length0-(n??s.L+o));return i===0?r:[r[0]-i*s.dL[0],r[1]-i*s.dL[1]]}function pl(e,t){let r=Jd(e.travel);return t==="heave"?{...e,heave:r.heave,heaveRatio:r.heaveRatio}:{...e,roll:r.roll,rollRatio:r.rollRatio}}var dl=(e,t)=>e?e.law?Yo(e.law,t):e.preload+e.rate*t:0,mR=(e,t)=>e?e.law?$d(e.law,t):e.rate:0;function Rs(e,t,r,n,o){let a=dl(e.heave,n),s=dl(e.roll,o);return[a*t.dh+s*t.dr,a*r.dh-s*r.dr]}var pR=(e,t)=>_e(e[0],t).h+_e(e[1],t).h;function JT(e,t){let r=e.gap>0?pR(t,e.gap):0;return e.bothWays?{free:r,pull:e.gap>0?pR(t,-e.gap):0}:{free:r,pull:null}}function eP(e,t,r){let n={...t,outer:t.inner},o=(u,m)=>{let f=ht(ye(e[0],u,0)),p=ht(ye(e[1],m,0));if(!f||!p)return NaN;let d=De(e[0].corner,t,f),h=De(e[1].corner,n,p);return Math.hypot(d[0]-h[0],d[1]+h[1],d[2]-h[2])},a=1,s=o(0,0),i=o(-a,a)-o(a,-a),c=_e(r[0],a).r-_e(r[1],-a).r-(_e(r[0],-a).r-_e(r[1],a).r),l=i/c;return Number.isFinite(s)&&s>0&&Number.isFinite(l)&&Math.abs(l)>qd?{length0:s,scale:l}:null}function bR(e,t,r,n=cl){let o=r.heave?gs(r.heave):void 0,a=cR(e[0],r,o,n),s=e[1].corner===e[0].corner?a:cR(e[1],r,o,n),i=[a.side,s.side],c=!!(a.pickups.heave&&s.pickups.heave),l=!!(a.pickups.roll&&s.pickups.roll),u=r.carriesLoad?void 0:r.heaveSeat,m=u?u.rate:(t[0].heaveRate+t[1].heaveRate)/2,f=(t[0].arbRate+t[1].arbRate)/2,p=i.map(A=>_e(A,0));c&&!(Math.abs(p[0].dh+p[1].dh)>qd)&&(i=[pl(i[0],"heave"),pl(i[1],"heave")],c=!1),l&&!(Math.abs(p[0].dr+p[1].dr)>qd)&&(i=[pl(i[0],"roll"),pl(i[1],"roll")],l=!1),p=i.map(A=>_e(A,0));let d=p[0].dh+p[1].dh,h=p[0].dr+p[1].dr,b=m>0?2*m/(d*d):0,g=f>0?2*f/(h*h):0,y=0,R=0;if(r.carriesLoad){let A=[t[0].springLoad,t[1].springLoad];if(b>0&&g>0){let P=-p[0].dh*p[1].dr-p[1].dh*p[0].dr;Math.abs(P)>1e-12&&(y=(-A[0]*p[1].dr-A[1]*p[0].dr)/P,R=(p[0].dh*A[1]-p[1].dh*A[0])/P)}else b>0?y=(A[0]+A[1])/d:g>0&&(R=(A[0]-A[1])/h)}let k={};if(c&&o){let A=[a.pickups.heave,s.pickups.heave];k.heave={pickups:A,mount:o,span0:ys(A[0].at0,A[1].at0,o)}}let v=k.heave?k.heave.span0:NaN,x=k.heave?r.coilover:void 0,M=r.carriesLoad?ds(b,y,v,x):u?Bd(b,{...JT(u,i),length0:v,coilover:x}):null,F=b>0?{rate:b,preload:y,...M?{law:M}:{}}:null;if(l&&(k.roll={pickups:[a.pickups.roll.pickup,s.pickups.roll.pickup],axes:[a.pickups.roll.axis,s.pickups.roll.axis]},r.roll&&an(e[0].corner,r.roll,r.rollKind??"coil"))){let A=eP(e,r.roll,i);A&&(k.roll.unit=A)}let w=g>0?{rate:g,preload:R}:null,C={side:i,heave:F,roll:w,force0:[0,0],carriesLoad:r.carriesLoad,read:k},T=k.roll?.unit,S=T&&g>0&&i[0].eyes&&i[1].eyes?zo(T.length0,r.rollCoilover):null;return T&&S&&(S.droop!==null||S.bump!==null)&&(C.rollStop={length0:T.length0,rate:1e3*g/(T.scale*T.scale),...S}),C.force0=xs(C,[0,0],Rs(C,p[0],p[1],p[0].h+p[1].h,p[0].r-p[1].r)),C}function vs(e,t,r){let n=_e(e.side[0],t[0]),o=_e(e.side[1],t[1]),a=r?xs(e,t,Rs(e,n,o,n.h+o.h+r.heave,n.r-o.r+r.roll),void 0,r.unit):xs(e,t,Rs(e,n,o,n.h+o.h,n.r-o.r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function rf(e,t,r){let n=_e(e.side[0],t[0]),o=_e(e.side[1],t[1]),a=r?n.h+o.h+r.heave:n.h+o.h,s=r?n.r-o.r+r.roll:n.r-o.r,i=mR(e.heave,a),c=mR(e.roll,s),l=dl(e.heave,a),u=dl(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?tf(e,t):null;if(!p||!d)return f;let h=p.length0-(r?d.L+r.unit:d.L),b=ZT(p,h);if(b===0)return f;let g=hR(p,h),y=(k,v)=>b*d.dL[k]*d.dL[v]-g*d.ddL[k][v],R=m+y(0,1);return[[f[0][0]+y(0,0),R],[R,f[1][1]+y(1,1)]]}function nf(e,t,r){let n=rf(e,t);return n[r][0]+n[r][1]}function tP(e,t,r){let n=e.read.heave;if(!n)return _e(e.side[0],t[0]).h+_e(e.side[1],t[1]).h;let[o,a]=n.pickups;return n.span0-ys(De(o.corner,o.link,r[0]),De(a.corner,a.link,r[1]),n.mount)}function rP(e,t,r){let n=e.read.roll;if(!n)return _e(e.side[0],t[0]).r-_e(e.side[1],t[1]).r;let o=a=>X(H(De(n.pickups[a].corner,n.pickups[a].link,r[a]),n.pickups[a].at0),n.axes[a]);return o(0)-o(1)}function nP(e,t){let r=e.read.roll;if(!e.rollStop||!r)return;let[n,o]=r.pickups;return ef(De(n.corner,n.link,t[0]),De(o.corner,{...o.link,outer:o.link.inner},t[1]))}function ks(e,t,r){let n=_e(e.side[0],t[0]),o=_e(e.side[1],t[1]),a=xs(e,t,Rs(e,n,o,tP(e,t,r),rP(e,t,r)),nP(e,r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function of(e,t,r,n){let o=_e(e.side[0],r),a=_e(e.side[1],r),s=e.read.heave,i=s?.pickups[t],c=s&&i&&n?2*fR(i,s.mount,De(i.corner,i.link,n)):o.h+a.h,l=e.rollStop&&n?e.read.roll?.pickups[t]:void 0,u=l&&n?ef(De(l.corner,l.link,n),De(l.corner,{...l.link,outer:l.link.inner},n)):void 0;return xs(e,[r,r],Rs(e,o,a,c,n?0:o.r-a.r),u)[t]-e.force0[t]}function af(e,t,r,n){let o=Wo(e,r[n]);return t?.carriesLoad?o+nf(t,r,n):o}function gR(e,t){return _e(e.side[0],t[0]).h+_e(e.side[1],t[1]).h}function yR(e,t){return tf(e,t)?.L??null}var sf=e=>e==="FR"||e==="RR"?1:0,fl=(e,t)=>e.elements?.[t==="FL"||t==="FR"?"front":"rear"]??null;var xR=e=>Number.isFinite(e)&&e>0?1/e:0;var RR=(e,t)=>{let r=e[0][0]*e[1][1]-e[0][1]*e[1][0];return Math.abs(r)>1e-14?[(t[0]*e[1][1]-t[1]*e[0][1])/r,(e[0][0]*t[1]-e[1][0]*t[0])/r]:null},oP=(e,t)=>[e[0][0]*t[0]+e[0][1]*t[1],e[1][0]*t[0]+e[1][1]*t[1]],vR=1e-8,aP=40;function sP(e,t,r,n){return{force:(s,i)=>{if(r){let u=vs(r,s,n);return[Yt(t[0],s[0])+i[0]+u[0],Yt(t[1],s[1])+i[1]+u[1]]}let c=(s[0]+s[1])/2,l=(s[0]-s[1])/2;return[Yt(t[0],s[0])+i[0]+e[0].heaveRate*c+e[0].arbRate*l,Yt(t[1],s[1])+i[1]+e[1].heaveRate*c-e[1].arbRate*l]},stiffness:(s,i=bs)=>{if(r){let c=rf(r,s,n);return[[i(t[0],s[0])+c[0][0],c[0][1]],[c[1][0],i(t[1],s[1])+c[1][1]]]}return[[i(t[0],s[0])+e[0].heaveRate/2+e[0].arbRate/2,e[0].heaveRate/2-e[0].arbRate/2],[e[1].heaveRate/2-e[1].arbRate/2,i(t[1],s[1])+e[1].heaveRate/2+e[1].arbRate/2]]}}}function Uo(e,t,r,n,o,a=[0,0],s=[0,0],i=null,c){let l=[xR(r[0].tyreRate),xR(r[1].tyreRate)],u=[r[0].staticLoad,r[1].staticLoad],m=sP(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<aP;N++){if(g(E.r)<vR){V=!0;break}let z=RR(b(m.stiffness(D),E.lifted),[-E.r[0],-E.r[1]]);if(!z)break;let I=1,_=[D[0]+z[0],D[1]+z[1]],B=h(_,L);for(let O=0;O<8&&g(B.r)>g(E.r);O++)I/=2,_=[D[0]+I*z[0],D[1]+I*z[1]],B=h(_,L);D=_,E=B}return!V&&g(E.r)<vR&&(V=!0),{t:D,b:E,converged:V,it:N}},R=y(o?[o[0],o[1]]:[e[0]-t[0],e[1]-t[1]],1),k=R.it;if(!R.converged){let P=0,L=[0,0],D=.25;for(;P<1&&D>=1/256;){let E=Math.min(1,P+D),V=y(L,E);k+=V.it,V.converged?(P=E,L=V.t,E===1&&(R=V)):D/=2}}let{t:v,b:x,converged:M}=R,F=x.lifted,w=[F[0]?-u[0]:x.f[0],F[1]?-u[1]:x.f[1]],C=[F[0]?Math.max(0,x.on[0]):0,F[1]?Math.max(0,x.on[1]):0],T=m.stiffness(v,Wo),S=b(T,F);return{t:v,dF:w,lifted:F,clearance:C,converged:M,iterations:k,respond:(P,L,D=[0,0])=>{let E=[F[0]?-d[0]*D[0]:P[0]-L[0]-D[0]*l[0],F[1]?-d[1]*D[1]:P[1]-L[1]-D[1]*l[1]],V=RR(S,E);if(!V)return[NaN,NaN];let N=oP(T,V);return[F[0]?0:N[0]+D[0],F[1]?0:N[1]+D[1]]}}}var In=e=>!(Number.isFinite(e.tyreRate)&&e.tyreRate>0);function rr(e,t,r){return t?.input.corners[r].staticLoadedRadius??e}var cf=["FL","FR","RL","RR"],SR={front:["FL","FR"],rear:["RL","RR"]},iP=512,cP=5e-4,lP=8;function hl(e,t){let r={},n={},o=new Map;for(let s of cf){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=`${cf.findIndex(p=>Ge(e.vehicle,p)===Ge(e.vehicle,s))}|${c.springLoad}|${u?`${u.extended}/${u.stroke}`:""}`,f=o.get(m);f?r[s]=f:(r[s]=u?hs(i,c.springLoad,void 0,u):hs(i,c.springLoad),o.set(m,r[s]))}let a={front:null,rear:null};for(let s of["front","rear"]){let i=t.elements?.[s];if(!i)continue;let c=SR[s];a[s]=bR([e.ctx[c[0]],e.ctx[c[1]]],[t.corners[c[0]],t.corners[c[1]]],i)}return{input:t,curve:r,elements:a,ground0:n,memo:new Map}}function AR(e,t,r){if(!(r>0)||!Number.isFinite(r)||!Number.isFinite(t)||t<=0)return 0;let n=Math.min(t/r,e);return 2*Math.sqrt(Math.max(0,2*e*n-n*n))}var uP=e=>`${e.heave}|${e.pitch}|${e.roll}|${e.steer}`;function lf(e,t,r){return{travel:r.travel,steer:r.steer,ground:r.travel,tyreDeflection:0,load:NaN,loadedRadius:rr(Ge(e.vehicle,t).config.loadedRadius,e.kc,t),lifted:!1,contactLength:0,converged:!0,rigid:!0,rideRate:NaN,wheelRateAtLoad:NaN}}var mP=e=>e?{q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle}:void 0;function kR(e,t,r,n){let o=SR[n],a=e.vehicle.config,s=o.map(w=>on(w,a,r,e.vehicle)),i=[t.input.corners[o[0]],t.input.corners[o[1]]],c=t.loadCase;if(!c&&i.every(In))return{corners:[lf(e,o[0],s[0]),lf(e,o[1],s[1])],respond:null};let l=o.map(w=>t.curve[w]),u=t.elements?.[n]??null,m=o.map(w=>rr(Ge(e.vehicle,w).config.loadedRadius,t,w)),f=[s[0].travel+(c?.ground[o[0]]??0),s[1].travel+(c?.ground[o[1]]??0)],p=[c?.linkLoad[o[0]]??0,c?.linkLoad[o[1]]??0],d=[c?.patchShift[o[0]],c?.patchShift[o[1]]],h=[0,0],b=[0,0],g,y=Uo(f,h,i,l,void 0,void 0,p,u),R=[void 0,void 0],k=[!0,!0],v=[0,0],x=!1;for(let w=0;w<lP;w++){w>0&&(y=Uo(f,h,i,l,g,b,p,u)),v=[Number.isFinite(i[0].tyreRate)&&i[0].tyreRate>0?y.dF[0]/i[0].tyreRate:0,Number.isFinite(i[1].tyreRate)&&i[1].tyreRate>0?y.dF[1]/i[1].tyreRate:0];let C=[0,0],T=[0,0];for(let A=0;A<2;A++){let P=ye(e.ctx[o[A]],y.t[A],s[A].steer,mP(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]=Mr(l[A],y.t[A],L.points.damperLength)-Yt(l[A],y.t[A])}if(u){let A=ks(u,y.t,[R[0],R[1]]),P=vs(u,y.t);T[0]+=A[0]-P[0],T[1]+=A[1]-P[1]}let S=Math.max(Math.abs(C[0]-h[0]),Math.abs(C[1]-h[1]),Math.abs(T[0]-b[0])/Math.max(1,i[0].tyreRate),Math.abs(T[1]-b[1])/Math.max(1,i[1].tyreRate));if(h=C,b=T,g=y.t,S<cP){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:af(l[w],u,y.t,w)}}),respond:y.respond}}function FR(e,t){let r=e.kc,n=uP(t),o=r.memo.get(n);if(o)return o;let a=kR(e,r,t,"front"),s=kR(e,r,t,"rear"),i={corners:{FL:a.corners[0],FR:a.corners[1],RL:s.corners[0],RR:s.corners[1]},respond:{front:a.respond,rear:s.respond}};return r.memo.size>=iP&&r.memo.clear(),r.memo.set(n,i),i}function gt(e,t){if(!e.kc){let r={};for(let n of cf)r[n]=lf(e,n,on(n,e.vehicle.config,t,e.vehicle));return r}return FR(e,t).corners}function bl(e,t,r){return e.kc?FR(e,t).respond[r]:null}function Ms(e,t,r,n=0){let o=e.kc;if(!o)return r;let a=o.input.corners[t];if(In(a))return r;let s=on(t,e.vehicle.config,{heave:0,pitch:0,roll:0,steer:n},e.vehicle).steer,i=rr(Ge(e.vehicle,t).config.loadedRadius,o,t),c=o.loadCase,l=c?.linkLoad[t]??0,u=c?.patchShift[t],m=at(ye(e.ctx[t],r,s,void 0,{loadedRadius:i,patchShift:u})),f=fl(o,t),p=Mr(o.curve[t],r,m.points.damperLength)+(f?of(f,sf(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 pP=180/Math.PI,dP=[0,0,1];function fP(e,t){let r=rn(e,t),n=U(ae(dP,r),-t.sideSign);return-Math.atan2(n[1],n[0])*pP}var wR=e=>1/Math.tan(e*Math.PI/180),CR=.05,TR=.001;function PR(e,t,r){if(!Number.isFinite(e)||!Number.isFinite(t))return NaN;if(!(Math.abs(e)<TR&&Math.abs(t)<TR))return e>0&&t>0?100*(wR(t)-wR(e))/r:NaN}function hP(e,t){let r=Nt(e.vehicle,!0)/e.vehicle.config.wheelbase,n=t("FL",0).deg,o=t("FR",0).deg,a=(c,l)=>{let u=c+l>=0;return{left:u,inner:u?c:-l,outer:u?l:-c}},s,i=()=>{if(s===void 0){let c=[CR,-CR].map(l=>{let{inner:u,outer:m}=a(t("FL",l).deg-n,t("FR",l).deg-o);return PR(u,m,r)??NaN});s=(c[0]+c[1])/2}return s};return c=>{let l=t("FL",c),u=t("FR",c),{left:m,inner:f,outer:p}=a(l.deg-n,u.deg-o),d=PR(f,p,r);return{steerL:l.deg,steerR:u.deg,inner:f,outer:p,toeDiff:f-p,ackermannPct:d??i(),inside:d===void 0?null:m?"left":"right",converged:l.ok&&u.ok}}}function uf(e,t){let r=e.vehicle.config,n={FL:Ze("FL",r),FR:Ze("FR",r)},o=t.travel??0,a=hP(e,(i,c)=>{let l=ht(ye(e.ctx[i],o,n[i].sideSign*c));return{deg:l?fP(l.points.spinAxis,n[i]):NaN,ok:l!==null}}),s=[];for(let i=0;i<t.steps;i++){let c=t.steps===1?0:-t.steerMax+2*t.steerMax*i/(t.steps-1),{inside:l,...u}=a(c);s.push({steerInput:c,...u})}return s}var LR=35,DR=55,Vt=e=>e.rackTravel&&e.rackTravel>0?e.rackTravel:LR,mf=e=>e.rackRatio&&e.rackRatio>0?e.rackRatio:DR;var pf=e=>({q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle});function ER(e,t,r,n,o){let a=ye(e,n,0,void 0,o),s=at(a),i=a.ok?0:1,c=s.points.contactPatch[2],l={steer:s.metrics.toe,camber:s.metrics.camber,lift:0,contactPatch:s.points.contactPatch,spinAxis:s.points.spinAxis,yaw:-s.metrics.toe*Math.PI/180},u=p=>{let d=[l],h=pf(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,pf(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=pf(y)}return d},m=u(1),f=u(-1);return{travelMm:n,unsolved:i,centre:l,positive:m,negative:f}}function bP(e,t){return e.map((r,n)=>{let o=n===0?0:n-1,a=n===e.length-1?e.length-1:n+1,s=t[a]-t[o];if(!(s>0))return{longitudinal:0,lateral:0,vertical:0,yaw:0};let i=U(H(e[a].contactPatch,e[o].contactPatch),1/s),c=Q(ae(r.spinAxis,[0,0,1])),l=ae([0,0,1],c);return{longitudinal:X(i,c),lateral:X(i,l),vertical:i[2],yaw:(e[a].yaw-e[o].yaw)/s}})}function IR(e,t,r){let n=o=>({steerDeg:o.map(a=>Math.abs(a.steer-e.centre.steer)),camberDeg:o.map(a=>a.camber-e.centre.camber),liftMm:o.map(a=>a.lift),jacobian:bP(o,t)});return{travelMm:e.travelMm,inner:n(r?e.positive:e.negative),outer:n(r?e.negative:e.positive)}}function gP(e){return e.positive[1].steer-e.centre.steer<0}function yP(e,t,r){return{meanDeg:t.map((n,o)=>.5*(r.inner.steerDeg[o]+r.outer.steerDeg[o])),innerDeg:r.inner.steerDeg,outerDeg:r.outer.steerDeg,innerCamber:r.inner.camberDeg,outerCamber:r.outer.camberDeg,innerLift:r.inner.liftMm,outerLift:r.outer.liftMm,rackRatioMmPerRev:mf(e.config),innerJacobian:r.inner.jacobian,outerJacobian:r.outer.jacobian}}function df(e,t,r=13,n=-40,o=40,a=5,s){let i=tt(e),c=Array.from({length:r+1},(b,g)=>t*g/r),l=ER(i,t,r,0,s),u=gP(l),m=IR(l,c,u),f=Math.max(2,Math.floor(a)),p=Array.from({length:f},(b,g)=>n+(o-n)*g/(f-1));p.some(b=>Math.abs(b)<1e-9)||p.push(0),p.sort((b,g)=>b-g);let d=l.unsolved,h=p.map(b=>{if(Math.abs(b)<1e-9)return m;let g=ER(i,t,r,b,s);return d+=g.unsolved,IR(g,c,u)});return{...yP(e,c,m),..._R(l.unsolved),travelSurface:{rackMm:c,rows:h,..._R(d)}}}var _R=e=>e>0?{unsolved:e}:{};function nr(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function gl(e,t,r){let n=e.length;if(n===0)return{longitudinal:0,lateral:0,vertical:0,yaw:0};let o,a;if(r<=e[0])o=a=0;else if(r>=e[n-1])o=a=n-1;else for(o=0,a=n-1;a-o>1;){let l=o+a>>1;e[l]<=r?o=l:a=l}let s=t[o];if(o===a)return{longitudinal:s.longitudinal,lateral:s.lateral,vertical:s.vertical,yaw:s.yaw};let i=t[a],c=(r-e[o])/(e[a]-e[o]);return{longitudinal:s.longitudinal+c*(i.longitudinal-s.longitudinal),lateral:s.lateral+c*(i.lateral-s.lateral),vertical:s.vertical+c*(i.vertical-s.vertical),yaw:s.yaw+c*(i.yaw-s.yaw)}}function NR(e,t){let r=e.rows;if(r.length<=1||t<=r[0].travelMm)return{lo:0,hi:0,t:0};let n=r.length-1;if(t>=r[n].travelMm)return{lo:n,hi:n,t:0};let o=0,a=n;for(;a-o>1;){let s=o+a>>1;r[s].travelMm<=t?o=s:a=s}return{lo:o,hi:a,t:(t-r[o].travelMm)/(r[a].travelMm-r[o].travelMm)}}var _n=(e,t,r)=>e+r*(t-e);function Xo(e,t,r,n,o){let a=nr(e.rackMm,e.rows[n.lo][t][r],o);if(n.lo===n.hi)return a;let s=nr(e.rackMm,e.rows[n.hi][t][r],o);return _n(a,s,n.t)}function OR(e,t,r,n){let o=gl(e.rackMm,e.rows[r.lo][t].jacobian,n);if(r.lo===r.hi)return o;let a=gl(e.rackMm,e.rows[r.hi][t].jacobian,n);return{longitudinal:_n(o.longitudinal,a.longitudinal,r.t),lateral:_n(o.lateral,a.lateral,r.t),vertical:_n(o.vertical,a.vertical,r.t),yaw:_n(o.yaw,a.yaw,r.t)}}function Qo(e,t,r,n){let o=e.travelSurface;if(!o||o.rackMm.length<2||o.rows.length===0)return qo(e,t);let a=NR(o,r),s=NR(o,n),i=(p,d,h)=>{let b=o.rows[d.lo][p].steerDeg[h];return d.lo===d.hi?b:_n(b,o.rows[d.hi][p].steerDeg[h],d.t)},c=new Array(o.rackMm.length);for(let p=0;p<c.length;p++)c[p]=.5*(i("inner",a,p)+i("outer",s,p));let l=Math.max(0,t),u=c.length-1,m=o.rackMm[u],f=l>c[u];if(l<=c[0])m=o.rackMm[0],f=!1;else if(!f){let p=1;for(;p<c.length-1&&c[p]<l;)p++;let d=p-1,h=c[p]-c[d],b=Math.abs(h)>1e-12?(l-c[d])/h:0;m=_n(o.rackMm[d],o.rackMm[p],b)}return{innerDeg:Xo(o,"inner","steerDeg",a,m),outerDeg:Xo(o,"outer","steerDeg",s,m),innerCamber:Xo(o,"inner","camberDeg",a,m),outerCamber:Xo(o,"outer","camberDeg",s,m),innerLift:Xo(o,"inner","liftMm",a,m),outerLift:Xo(o,"outer","liftMm",s,m),innerJacobian:OR(o,"inner",a,m),outerJacobian:OR(o,"outer",s,m),atLock:f}}function qo(e,t){let r=e.meanDeg.length-1;return{innerDeg:nr(e.meanDeg,e.innerDeg,t),outerDeg:nr(e.meanDeg,e.outerDeg,t),innerCamber:nr(e.meanDeg,e.innerCamber,t),outerCamber:nr(e.meanDeg,e.outerCamber,t),innerLift:e.innerLift?nr(e.meanDeg,e.innerLift,t):0,outerLift:e.outerLift?nr(e.meanDeg,e.outerLift,t):0,...e.innerJacobian&&e.outerJacobian?{innerJacobian:gl(e.meanDeg,e.innerJacobian,t),outerJacobian:gl(e.meanDeg,e.outerJacobian,t)}:{},atLock:r>=0&&t>e.meanDeg[r]}}var xP=()=>({lift:{FL:0,FR:0,RL:0,RR:0},travel:{FL:0,FR:0,RL:0,RR:0},load:{FL:0,FR:0,RL:0,RR:0},rollDeg:0});function Zo(e,t,r=we(e),n){let o=e.steerFront;if(!o?.innerLift||!o.outerLift||o.meanDeg.length<2||Math.abs(t)<1e-12)return xP();let a=Math.abs(t),s=t>0,i=n&&o.travelSurface?Qo(o,a,s?n.FL:n.FR,s?n.FR:n.FL):null,c=i?.innerLift??nr(o.meanDeg,o.innerLift,a),l=i?.outerLift??nr(o.meanDeg,o.outerLift,a),u=s?c:l,m=s?l:c,f=.5*(u+m),p=r.rollWheelRateFront,d=r.rollWheelRateRear,h=e.trackFront,b=e.trackRear,g=p*h*h+d*b*b,y=g>0?p*h*(m-u)/g:0,R={FL:u-f+.5*h*y,FR:m-f-.5*h*y,RL:.5*b*y,RR:-.5*b*y};return{lift:{FL:u,FR:m,RL:0,RR:0},travel:R,load:{FL:p*R.FL,FR:p*R.FR,RL:d*R.RL,RR:d*R.RR},rollDeg:y===0?0:-Math.atan(y)*180/Math.PI}}function ff(e,t,r){let n=t/r,o=a=>1/Math.tan(a*Math.PI/180);for(let a=0;a<e.meanDeg.length;a++)if(e.outerDeg[a]>.3&&e.innerDeg[a]>.3)return 100*(o(e.outerDeg[a])-o(e.innerDeg[a]))/n;return NaN}var Ss=9.81;function Jo(e,t,r=0,n=0,o=0){if(!e.aero||t<=0)return{FL:0,FR:0,RL:0,RR:0};let a=e.aero.model?kr(e,t,r,Jr(e,n,o)):Dn(e.aero,t),s=a.downFront/2,i=a.downRear/2,c=a.drag*(e.aero.copHeight/1e3)/(e.wheelbase/1e3)/2;return{FL:s-c,FR:s-c,RL:i+c,RR:i+c}}function hf(e,t,r=0,n=0,o=0){if(!e.aero?.model||t<=0)return!1;let a=kr(e,t,r,Jr(e,n,o));return a!=null&&(a.clampedRide||a.clampedAttitude)}function Nn(e){let t=e.loadFactor===void 0?e.massTotal*Ss:e.massTotal*Ss*e.loadFactor,r=t*e.frontMassFrac,n=t*(1-e.frontMassFrac);return{FL:r/2,FR:r/2,RL:n/2,RR:n/2}}function VR(e,t=we(e),r=e.cgHeight){let n=e.trackFront/1e3,o=e.trackRear/1e3,a=e.rcHeightFront/1e3,s=e.rcHeightRear/1e3,i=(e.rcHeightFront+(e.rcHeightRear-e.rcHeightFront)*(1-e.frontMassFrac))/1e3,c=r/1e3-i,l=2*e.unsprungPerCorner,u=e.unsprungCgHeight/1e3,m=t.sprungMass*c*Xc(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 bf(e){let{cf:t,cr:r}=VR(e);return t+r>0?t/(t+r):.5}function BR(e,t,r){if(e.FL>=0&&e.FR>=0&&e.RL>=0&&e.RR>=0)return{loads:{FL:Math.max(0,e.FL),FR:Math.max(0,e.FR),RL:Math.max(0,e.RL),RR:Math.max(0,e.RR)},lifted:{FL:!1,FR:!1,RL:!1,RR:!1},overturned:!1};let n=e.FL+e.FR+e.RL+e.RR;if(!(n>0))return{loads:{FL:0,FR:0,RL:0,RR:0},lifted:{FL:!0,FR:!0,RL:!0,RR:!0},overturned:!0};let o=!1,a=e.FL+e.FR,s=e.RL+e.RR;a<0?(a=0,s=n,o=!0):s<0&&(s=0,a=n,o=!0);let i=(e.FR-e.FL)*t+(e.RR-e.RL)*r,c=Math.min(a,Math.max(-a,e.FR-e.FL)),l=Math.min(s,Math.max(-s,e.RR-e.RL)),u=i-(c*t+l*r);if(u!==0){let f=u>0?1:-1,p=(f*a-c)*t;f*u>=f*p?(c=f*a,u-=p):(c+=u/t,u=0);let d=(f*s-l)*r;u!==0&&(f*u>=f*d?(l=f*s,u-=d):(l+=u/r,u=0)),Math.abs(u)>1e-9*(Math.abs(i)+n*(t+r))&&(o=!0)}let m={FL:Math.max(0,(a-c)/2),FR:Math.max(0,(a+c)/2),RL:Math.max(0,(s-l)/2),RR:Math.max(0,(s+l)/2)};return{loads:m,lifted:{FL:m.FL===0,FR:m.FR===0,RL:m.RL===0,RR:m.RR===0},overturned:o}}function Ce(e,t,r,n=0,o=0,a=0,s,i){return yl(e,t,r,n,o,a,s,i).loads}function yl(e,t,r,n=0,o=0,a=0,s,i){let c=Nn(e),l=we(e),u=nl(e,n,r,Jr(e,t,o),l),{cf:m,cr:f}=VR(e,l,u.height),p=m*t*Ss,d=f*t*Ss,h=e.massTotal*(r*Ss)*u.height/e.wheelbase-u.noseLoad,b=Jo(e,n,r,t,o),g=(i??Zo(e,a,l,s)).load,y={FL:c.FL-p-h/2+b.FL+g.FL,FR:c.FR+p-h/2+b.FR+g.FR,RL:c.RL-d+h/2+b.RL+g.RL,RR:c.RR+d+h/2+b.RR+g.RR};return BR(y,e.trackFront,e.trackRear)}var gf=Math.PI/180;function Rl(e,t){let r=8*gf,n=0,o=0;for(let a=1;a<=90;a++){let s=a*.5,i=Math.abs(e.Fy(s*gf,t,0));if(i>n&&(n=i,r=s*gf,o=a),a>o+12&&i<.995*n)break}return{aPeak:r,fyPeak:n}}function $R(e,t,r,n,o){if(n===t)return r;let a=(o-t)/(n-t);return a<=0?e:a>=1?r:e+a*(r-e)}var Fs=.999;function At(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),Fs*s),c=n?-1:1,l=(v,x)=>Math.abs(e.forces({Fz:t,kappa:c*v,alpha:x}).Fy),u=.3,m=u,f=l(u,a);if(f<i){let v=0,x=u,M=NaN,F=f;for(let w=0;w<9;w++){let C=.5*(v+x),T=l(C,a);T>=i?(v=C,M=T):(x=C,F=T)}Number.isNaN(M)&&(M=l(0,a)),m=M<i?0:$R(v,M,x,F,i)}if(m<=0)return 0;let p=v=>{if(i===0)return c*e.forces({Fz:t,kappa:c*v,alpha:0}).Fx;let x=0,M=a,F=NaN,w=NaN;for(let C=0;C<5;C++){let T=.5*(x+M),S=l(v,T);S<i?(x=T,F=S):(M=T,w=S)}return Number.isNaN(F)&&(F=l(v,0)),Number.isNaN(w)&&(w=l(v,a)),c*e.forces({Fz:t,kappa:c*v,alpha:$R(x,F,M,w,i)}).Fx},d=4,h=v=>m*v/d,b=[0],g=1;for(let v=1;v<=d;v++)b.push(p(h(v))),b[v]>b[g]&&(g=v);let[y,R]=g===d?[d-1,d-2]:b[g-1]>=b[g+1]?[g-1,g+1]:[g+1,g-1],k=MP(p,h(g-1),h(Math.min(d,g+1)),h(g),b[g],h(y),b[y],h(R),b[R],RP);return c*Math.max(0,k)}var RP=.01,vP=20,kP=(3-Math.sqrt(5))/2;function MP(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<vP;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=kP*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 Rf(e,t){return e.model?.kind==="simple"?null:HR(e,t)}var GR=new WeakMap,yf=100,KR=1.35,xf=18,or=41,xl=41,As=65;function HR(e,t){let r=GR.get(e);if(r)return r;let n=Math.log(KR),o=(p,d)=>{let h=M=>Math.abs(At(e,p,M,d)),b=h(0),g=t.muY(p)*p,y=new Float64Array(or),R=b>0&&g>0?Math.max(1,t.muX(p)*p/b):1;if(!(b>0)||!(g>0))y.fill(1);else{let M=[],F=[];for(let C=0;C<xl;C++){let T=Math.sin(.5*Math.PI*C/(xl-1));M.push(T),F.push(C===0?1:C===xl-1?0:Math.min(F[C-1],h(T*g)/b))}let w=xl-1;for(let C=0;C<or;C++){let T=C/(or-1);for(;w>0&&F[w-1]<T;)w--;let S=w>0?F[w-1]-F[w]:0;y[C]=w===0?M[0]:M[w]+(S>0?(T-F[w])/S:0)*(M[w-1]-M[w])}y[0]=1,y[or-1]=0}let k=new Float64Array(As),v=M=>Math.atan2(y[M],M/(or-1)/R),x=or-2;for(let M=0;M<As;M++){let F=.5*Math.PI*M/(As-1),w=Math.cos(F),C=Math.sin(F);for(;x>0&&v(x)<F;)x--;let T=x/(or-1)/R,S=y[x],A=(x+1)/(or-1)/R,P=y[x+1],L=w*(P-S)-C*(A-T),D=Math.abs(L)>1e-12?(T*(P-S)-S*(A-T))/L:Math.hypot(T,S);k[M]=D>0?D:Math.hypot(T,S)}return{room:y,scale:R,edge:k}},a=Array.from({length:xf},(p,d)=>yf*KR**d),s=a.map(p=>o(p,!1)),i=a.map(p=>o(p,!0)),c=(p,d)=>{let h=Math.min(1,Math.abs(d)*p.scale)*(or-1),b=Math.min(or-2,Math.floor(h));return p.room[b]+(h-b)*(p.room[b+1]-p.room[b])},l=p=>{let d=p>yf?Math.log(p/yf)/n:0;if(d>=xf-1)return[xf-2,1];let h=Math.floor(d);return[h,d-h]},u=(p,d,h)=>{if(h===0)return 1;let b=h<0?i:s,g=c(b[p],h);return d>0?g+d*(c(b[p+1],h)-g):g},m=(p,d,h)=>{let b=d<0?i:s,[g,y]=l(p),R=Math.atan2(Math.abs(h),Math.abs(d))/(.5*Math.PI)*(As-1),k=Math.min(As-2,Math.floor(R)),v=M=>M.edge[k]+(R-k)*(M.edge[k+1]-M.edge[k]),x=v(b[g]);return y>0?x+y*(v(b[g+1])-x):x},f={keeps(p,d){if(d===0)return 1;let[h,b]=l(p);return u(h,b,d)},atLoad(p){let[d,h]=l(p);return b=>u(d,h,b)},use(p,d,h){let b=Math.hypot(d,h);return b>0?Math.min(1,b/m(p,d,h)):0},reach:m};return GR.set(e,f),f}var SP=[["front","FL","FR"],["rear","RL","RR"]];function ea(e,t,r,n){let o={...e},a=0,s=Fs;for(let[i,c,l]of SP){let u=(k,v)=>n(i,Math.max(0,v[k])).fyPeak,m=Math.min(s,e[c]),f=Math.min(s,e[l]),p=m*u(c,r)+f*u(l,r);if(!(p>0))continue;let d=u(c,t),h=u(l,t),b=m*d+f*h,g=b>0?p/b:1/0,y=m*g,R=f*g;y<=s?R<=s||(R=s,y=d>0?(p-s*h)/d:1/0):(y=s,R=h>0?(p-s*d)/h:1/0),(!(y<=s)||!(R<=s))&&(a+=Math.max(0,p-s*(d+h)),y=Math.min(s,y),R=Math.min(s,R)),o[c]=y,o[l]=R}return{util:o,short:a}}var zR=.001,AP=1e-5,YR=100;function FP(e,t,r,n){if(!(n>zR))return r;let o=t,a=Math.abs(r-t)<YR?t+Math.sign(r-t)*YR:r;for(let s=0;s<60&&Math.abs(a-o)>AP;s++){let i=.5*(o+a);e(i)>zR?a=i:o=i}return o}function vl(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=FP(e,t,o,e(o));return a!==o&&(n=a),a},edge:()=>n}}function kl(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 vf=40;function Ml(e){return{violation:Math.max(0,e.lock-e.reached),reason:`the steering reaches only ${e.reached.toFixed(0)} mm of the ${e.lock.toFixed(0)} mm rack travel${e.side<0?" (other side)":""}`}}var WR=[0,0,0];function wP(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 CP(e,t,r);let n=[{r:e.uprightUpper,c:e.ucaFront},{r:e.uprightUpper,c:e.ucaRear},{r:e.uprightLower,c:e.lcaFront},{r:e.uprightLower,c:e.lcaRear},{r:e.tieOuter,c:e.tieInner},{r:e.pushrodOuter,c:e.direct?e.damperChassis:e.rockerToPushrod}],o=e.wheelCenter,a=[[],[],[],[],[],[]];for(let m=0;m<6;m++){let f=Q(H(n[m].c,n[m].r)),p=ae(H(n[m].r,o),f);a[0][m]=f[0],a[1][m]=f[1],a[2][m]=f[2],a[3][m]=p[0],a[4][m]=p[1],a[5][m]=p[2]}let s=ae(H(e.contactPatch,o),t),i=r??WR,c=[-t[0],-t[1],-t[2],-(s[0]+i[0]),-(s[1]+i[1]),-(s[2]+i[2])],l=Jt(a,c),u=l.x;return{ucaFront:u[0],ucaRear:u[1],lcaFront:u[2],lcaRear:u[3],tieRod:u[4],pushRod:u[5],damper:l.singular||e.decoupled?NaN:e.direct?u[5]:wP(e,u[5]),condProxy:l.condProxy,singular:l.singular}}function CP(e,t,r){let n=e.wheelCenter,o=e.damperChassis,a=[{at:e.uprightLower,dir:Q(H(e.lcaFront,e.uprightLower))},{at:e.uprightLower,dir:Q(H(e.lcaRear,e.uprightLower))},{at:e.tieOuter,dir:Q(H(e.tieInner,e.tieOuter))},{at:o,dir:[1,0,0]},{at:o,dir:[0,1,0]},{at:o,dir:[0,0,1]}],s=[[],[],[],[],[],[]];for(let b=0;b<6;b++){let g=a[b].dir,y=ae(H(a[b].at,n),g);s[0][b]=g[0],s[1][b]=g[1],s[2][b]=g[2],s[3][b]=y[0],s[4][b]=y[1],s[5][b]=y[2]}let i=ae(H(e.contactPatch,n),t),c=r??WR,l=[-t[0],-t[1],-t[2],-(i[0]+c[0]),-(i[1]+c[1]),-(i[2]+c[2])],u=Jt(s,l),m=u.x,f=[m[3],m[4],m[5]],p=Q(H(o,e.pushrodOuter)),d=X(f,p),h=Math.hypot(f[0]-d*p[0],f[1]-d*p[1],f[2]-d*p[2]);return{ucaFront:NaN,ucaRear:NaN,lcaFront:m[0],lcaRear:m[1],tieRod:m[2],pushRod:u.singular?NaN:d,damper:u.singular?NaN:d,condProxy:u.condProxy,singular:u.singular,strutSide:u.singular?NaN:h,topMount:f}}function kf(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 TP=[0,0,0];function ws(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 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??TP,b=[-r[0],-r[1],-r[2],-(d[0]+h[0]),-(d[1]+h[1]),-(d[2]+h[2])],g=Jt(p,b),y=g.singular,R=g.x,k=R[0],v=R[1],x=R[2],M=[R[3],R[4],R[5]],F=Q(H(i.rear,i.front)),w=Q(H(o,e.pushrodOuter)),C=U(M,-1),T=(Z,ne)=>X(F,ae(H(Z,i.front),ne)),S=T(e.pushrodOuter,w),A=Math.abs(S)>1e-9?-T(i.bj,C)/S:NaN,P=ee(C,U(w,A)),L=U(P,-1),D=Q(H(i.front,i.bj)),E=Q(H(i.rear,i.bj)),V=X(D,D),N=X(D,E),z=X(E,E),I=X(D,L),_=X(E,L),B=V*z-N*N,O=NaN,G=NaN,K=NaN;if(Math.abs(B)>1e-12){O=(I*z-_*N)/B,G=(V*_-N*I)/B;let Z=ee(U(D,O),U(E,G)),ne=H(L,Z);K=Math.hypot(ne[0],ne[1],ne[2])}let Y=a?{f:k,r:v}:{f:O,r:G},j=a?{f:O,r:G}:{f:k,r:v};return{ucaFront:Y.f,ucaRear:Y.r,lcaFront:j.f,lcaRear:j.r,tieRod:x,pushRod:A,damper:y||!Number.isFinite(A)||e.decoupled?NaN:e.direct?A:PP(e,A),condProxy:g.condProxy,singular:y,armResidual:K}}function PP(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 r4=Math.PI/180;function Cs(e,t){let r=Math.min(Math.max(t,e.range[0]),e.range[1])-e.reference;return Math.max(.2,1+e.perDegC*r+e.perDegC2*r*r)}var UR=["QSX3","QSX8","QSX13","QSX14"],LP=["QSX1"],Al=["PHY1","PHY2","PHY3","PKY6","PKY7","PVY1","PVY2","PVY3","PVY4","PEY3","PEY4","QHZ1","QHZ2","QHZ3","QHZ4","QEZ4","QEZ5","QDZ6","QDZ7","QDZ8","QDZ9","QDZ10","QDZ11","SSZ1","SSZ3","SSZ4","RBY3","RHX1","RVY1","RVY2","RVY3",...UR];function DP(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 EP(e){let t=new Set(DP(e)),r=Al.filter(n=>!UR.includes(n));return[...r.filter(n=>!t.has(n)),...[...t].filter(n=>!r.includes(n)),...LP]}function IP(e,t){let r={...e};for(let n of t)r[n]!==void 0&&r[n]!==0&&(r[n]=-r[n]);return r}var Sr=(e,t,r)=>Number.isFinite(e[t])?e[t]:r;function XR(e,t){return t!=="5.2"?Sr(e,"PKY6",0)*Sr(e,"LKYC",1):Sr(e,"PKY1",-15)*Math.sin(Sr(e,"PKY4",2)*Math.atan(1/Sr(e,"PKY2",2)))*Sr(e,"LKY",1)*Sr(e,"PHY3",0)+Sr(e,"PVY3",0)*Sr(e,"LMUY",1)}var jR=.1;function QR(e){if(e.fitData)return"sae";let t=XR(e.coeffs,e.version);return t>jR?"sae":t<-jR?"iso":null}function Ts(e){return e.axisSystem??QR(e)??"sae"}function Fl(e){let t=new Set,r=n=>{for(let o of n)t.has(o)?t.delete(o):t.add(o)};return Ts(e)==="iso"&&r(Al),e.axisSystem&&e.side==="left"&&r(EP(e.version)),t.size?IP(e.coeffs,t):e.coeffs}var o4=Math.PI/180;var $=(e,t)=>Number.isFinite(e)?e:t;function ZR(e){let t=Fl(e);return{PCX1:$(t.PCX1,1.65),PDX1:$(t.PDX1,1),PDX2:$(t.PDX2,0),PDX3:$(t.PDX3,0),PEX1:$(t.PEX1,0),PEX2:$(t.PEX2,0),PEX3:$(t.PEX3,0),PEX4:$(t.PEX4,0),PHX1:$(t.PHX1,0),PHX2:$(t.PHX2,0),PKX1:$(t.PKX1,20),PKX2:$(t.PKX2,0),PKX3:$(t.PKX3,0),PPX1:$(t.PPX1,0),PPX2:$(t.PPX2,0),PPX3:$(t.PPX3,0),PPX4:$(t.PPX4,0),PVX1:$(t.PVX1,0),PVX2:$(t.PVX2,0),PCY1:$(t.PCY1,1.3),PDY1:$(t.PDY1,1),PDY2:$(t.PDY2,0),PDY3:$(t.PDY3,0),PEY1:$(t.PEY1,0),PEY2:$(t.PEY2,0),PEY3:$(t.PEY3,0),PEY4:$(t.PEY4,0),PEY5:$(t.PEY5,0),PHY1:$(t.PHY1,0),PHY2:$(t.PHY2,0),PHY3:$(t.PHY3,0),PKY1:$(t.PKY1,-15),PKY2:$(t.PKY2,2),PKY3:$(t.PKY3,0),PKY4:$(t.PKY4,2),PKY5:$(t.PKY5,0),PKY6:$(t.PKY6,0),PKY7:$(t.PKY7,0),PPY1:$(t.PPY1,0),PPY2:$(t.PPY2,0),PPY3:$(t.PPY3,0),PPY4:$(t.PPY4,0),PPY5:$(t.PPY5,0),PVY1:$(t.PVY1,0),PVY2:$(t.PVY2,0),PVY3:$(t.PVY3,0),PVY4:$(t.PVY4,0),RBX1:$(t.RBX1,0),RBX2:$(t.RBX2,0),RBX3:$(t.RBX3,0),RBY1:$(t.RBY1,0),RBY2:$(t.RBY2,0),RBY3:$(t.RBY3,0),RBY4:$(t.RBY4,0),RCX1:$(t.RCX1,1),RCY1:$(t.RCY1,1),REX1:$(t.REX1,0),REX2:$(t.REX2,0),REY1:$(t.REY1,0),REY2:$(t.REY2,0),RHX1:$(t.RHX1,0),RHY1:$(t.RHY1,0),RHY2:$(t.RHY2,0),RVY1:$(t.RVY1,0),RVY2:$(t.RVY2,0),RVY3:$(t.RVY3,0),RVY4:$(t.RVY4,0),RVY5:$(t.RVY5,1),RVY6:$(t.RVY6,0),PPZ1:$(t.PPZ1,0),PPZ2:$(t.PPZ2,0),QBZ1:$(t.QBZ1,8),QBZ2:$(t.QBZ2,0),QBZ3:$(t.QBZ3,0),QBZ4:$(t.QBZ4,0),QBZ5:$(t.QBZ5,0),QBZ6:$(t.QBZ6,0),QBZ9:$(t.QBZ9,0),QBZ10:$(t.QBZ10,0),QCZ1:$(t.QCZ1,1.1),QDZ1:$(t.QDZ1,.1),QDZ2:$(t.QDZ2,0),QDZ3:$(t.QDZ3,0),QDZ4:$(t.QDZ4,0),QDZ6:$(t.QDZ6,0),QDZ7:$(t.QDZ7,0),QDZ8:$(t.QDZ8,0),QDZ9:$(t.QDZ9,0),QDZ10:$(t.QDZ10,0),QDZ11:$(t.QDZ11,0),QEZ1:$(t.QEZ1,0),QEZ2:$(t.QEZ2,0),QEZ3:$(t.QEZ3,0),QEZ4:$(t.QEZ4,0),QEZ5:$(t.QEZ5,0),QHZ1:$(t.QHZ1,0),QHZ2:$(t.QHZ2,0),QHZ3:$(t.QHZ3,0),QHZ4:$(t.QHZ4,0),SSZ1:$(t.SSZ1,0),SSZ2:$(t.SSZ2,0),SSZ3:$(t.SSZ3,0),SSZ4:$(t.SSZ4,0),QSX1:$(t.QSX1,0),QSX2:$(t.QSX2,0),QSX3:$(t.QSX3,0),QSX4:$(t.QSX4,0),QSX5:$(t.QSX5,0),QSX6:$(t.QSX6,0),QSX7:$(t.QSX7,0),QSX8:$(t.QSX8,0),QSX9:$(t.QSX9,0),QSX10:$(t.QSX10,0),QSX11:$(t.QSX11,0),QSX12:$(t.QSX12,0),QSX13:$(t.QSX13,0),QSX14:$(t.QSX14,0),PPMX1:$(t.PPMX1,0),QSY1:$(t.QSY1,0),QSY2:$(t.QSY2,0),QSY3:$(t.QSY3,0),QSY4:$(t.QSY4,0),QSY5:$(t.QSY5,0),QSY6:$(t.QSY6,0),QSY7:$(t.QSY7,0),QSY8:$(t.QSY8,0),LONGVL:t.LONGVL!==void 0&&t.LONGVL>0?t.LONGVL:16.7,LCX:$(t.LCX,1),LCY:$(t.LCY,1),LEX:$(t.LEX,1),LEY:$(t.LEY,1),LFZO:$(t.LFZO,1),LHX:$(t.LHX,1),LHY:$(t.LHY,1),LKX:$(t.LKX,1),LKY:$(t.LKY,1),LKYC:$(t.LKYC,1),LKZC:$(t.LKZC,1),LMUX:$(t.LMUX,1),LMUY:$(t.LMUY,1),LMX:$(t.LMX,1),LMY:$(t.LMY,1),LVMX:$(t.LVMX,1),LRES:$(t.LRES,1),LS:$(t.LS,1),LTR:$(t.LTR,1),LVX:$(t.LVX,1),LVY:$(t.LVY,1),LVYKA:$(t.LVYKA,1),LXAL:$(t.LXAL,1),LYKA:$(t.LYKA,1)}}var qR=new WeakMap;function Ps(e){let t=qR.get(e);return t===void 0&&(t=ZR(e),qR.set(e,t)),t}var JR=e=>e>=0?1:-1;function wl(e,t,r=0,n){let o=Ps(e),a=Math.max(1,t),s=r,i=o.LFZO*e.fnomin,c=(a-i)/i,l=e.nomPressure>0&&n?(n-e.nomPressure)/e.nomPressure:0,u=e.unloadedR0,m=(o.PDY1+o.PDY2*c)*(1+o.PPY3*l+o.PPY4*l*l)*(1-o.PDY3*s*s)*o.LMUY,f=o.PCY1*o.LCY,p=m*a,d=o.PKY1*i*(1+o.PPY1*l)*Math.sin(o.PKY4*Math.atan(a/((o.PKY2+o.PKY5*s*s)*(1+o.PPY2*l)*i)))*(1-o.PKY3*Math.abs(s))*o.LKY,h=e.version!=="5.2",b=a*(o.PKY6+o.PKY7*c)*(1+o.PPY5*l)*o.LKYC,g=a*(o.PVY3+o.PVY4*c)*s*o.LKYC*o.LMUY,y=Math.abs(d)>1e-6?d:1e-6*(d<0?-1:1),R=h?(o.PHY1+o.PHY2*c)*o.LHY+(b*s-g)/y:(o.PHY1+o.PHY2*c)*o.LHY+o.PHY3*s,k=h?a*(o.PVY1+o.PVY2*c)*o.LVY*o.LMUY+g:a*((o.PVY1+o.PVY2*c)*o.LVY+(o.PVY3+o.PVY4*c)*s)*o.LMUY,v=f*p!==0?d/(f*p):0;return{Fz:a,g:s,dfz:c,dpi:l,Fz0p:i,R0:u,Cy:f,Dy:p,By:v,SHy:R,SVy:k,Kya:d,muy:m,EyA:o.PEY1+o.PEY2*c,EyG:1+o.PEY5*s*s,EyS:o.PEY3+o.PEY4*s,LEY:o.LEY}}function Cl(e,t,r=0,n){let o=wl(e,t,r,n),a=Ps(e),{Fz:s,g:i,dfz:c,dpi:l,Fz0p:u,R0:m,muy:f,Kya:p,SVy:d,By:h,Cy:b,Dy:g,SHy:y}=o,R=(a.PHX1+a.PHX2*c)*a.LHX,k=(a.PDX1+a.PDX2*c)*(1+a.PPX3*l+a.PPX4*l*l)*(1-a.PDX3*i*i)*a.LMUX,v=a.PCX1*a.LCX,x=k*s,M=s*(a.PKX1+a.PKX2*c)*Math.exp(a.PKX3*c)*(1+a.PPX1*l+a.PPX2*l*l)*a.LKX,F=v*x!==0?M/(v*x):0,w=Math.abs(p)>1e-6?p:1e-6*(p<0?-1:1),C=e.version!=="5.2",T=s*(a.PVX1+a.PVX2*c)*a.LVX*a.LMUX,S=a.REX1+a.REX2*c;S>1&&(S=1);let A=a.REY1+a.REY2*c;return A>1&&(A=1),{Fz:s,g:i,dfz:c,dpi:l,Fz0p:u,R0:m,Cy:b,Dy:g,By:h,SHy:y,SVy:d,Kya:p,muy:f,EyA:o.EyA,EyG:o.EyG,EyS:o.EyS,LEY:o.LEY,SHx:R,Cx:v,Dx:x,Bx:F,SVx:T,ExA:a.PEX1+a.PEX2*c+a.PEX3*c*c,PEX4:a.PEX4,LEX:a.LEX,SHxa:a.RHX1,Bxa0:a.RBX1+a.RBX3*i*i,RBX2:a.RBX2,LXAL:a.LXAL,Cxa:a.RCX1,Exa:S,SHyk:a.RHY1+a.RHY2*c,Byk0:a.RBY1+a.RBY4*i*i,RBY2:a.RBY2,RBY3:a.RBY3,LYKA:a.LYKA,Cyk:a.RCY1,Eyk:A,DVykA:f*s*(a.RVY1+a.RVY2*c+a.RVY3*i),RVY4:a.RVY4,RVY5:a.RVY5,RVY6:a.RVY6,LVYKA:a.LVYKA,SHt:a.QHZ1+a.QHZ2*c+(a.QHZ3+a.QHZ4*c)*i,Bt:C?(a.QBZ1+a.QBZ2*c+a.QBZ3*c*c)*(1+a.QBZ5*Math.abs(i)+a.QBZ6*i*i)*(a.LKY/a.LMUY):(a.QBZ1+a.QBZ2*c+a.QBZ3*c*c)*(1+a.QBZ4*i+a.QBZ5*Math.abs(i))*(a.LKY/a.LMUY),Ct:a.QCZ1,Dt:C?s*(m/u)*(a.QDZ1+a.QDZ2*c)*(1-a.PPZ1*l)*(1+a.QDZ3*Math.abs(i)+a.QDZ4*i*i)*a.LTR:s*(m/u)*(a.QDZ1+a.QDZ2*c)*(1-a.PPZ1*l)*(1+a.QDZ3*i+a.QDZ4*i*i)*a.LTR,EtA:a.QEZ1+a.QEZ2*c+a.QEZ3*c*c,EtG:a.QEZ4+a.QEZ5*i,Br:a.QBZ9*(a.LKY/a.LMUY)+a.QBZ10*h*b,Dr:C?s*m*((a.QDZ6+a.QDZ7*c)*a.LRES+((a.QDZ8+a.QDZ9*c)*(1+a.PPZ2*l)+(a.QDZ10+a.QDZ11*c)*Math.abs(i))*i*a.LKZC)*a.LMUY:s*m*((a.QDZ6+a.QDZ7*c)*a.LRES+(a.QDZ8+a.QDZ9*c)*(1+a.PPZ2*l)*i)*a.LMUY,arOff:p!==0?d/p:0,sixOne:C,kk:M/w*(M/w),sS0:m*(a.SSZ1+(a.SSZ3+a.SSZ4*c)*i)*a.LS,sS2:m*a.SSZ2*a.LS/u}}function Ls(e,t){let r=t+e.SHy,n=e.EyA*(e.EyG-e.EyS*JR(r))*e.LEY;n>1&&(n=1);let o=e.By*r;return e.Dy*Math.sin(e.Cy*Math.atan(o-n*(o-Math.atan(o))))+e.SVy}function Tl(e,t){let r=t+e.SHx,n=e.ExA*(1-e.PEX4*JR(r))*e.LEX;n>1&&(n=1);let o=e.Bx*r;return e.Dx*Math.sin(e.Cx*Math.atan(o-n*(o-Math.atan(o))))+e.SVx}function ev(e,t,r){if(r===0)return t;if(e.sixOne)return Math.sqrt(t*t+e.kk*r*r)*Math.sign(t);let n=Math.tan(t);return Math.atan(Math.sqrt(n*n+e.kk*r*r))*Math.sign(t)}function _P(e,t,r,n){let o=t+e.SHt,a=e.EtA*(1+e.EtG*(2/Math.PI)*Math.atan(e.Bt*e.Ct*o));a>1&&(a=1);let s=ev(e,o,r),i=e.Bt*s;return e.Dt*Math.cos(e.Ct*Math.atan(i-a*(i-Math.atan(i))))*n}function NP(e,t,r,n){return e.Dr*Math.cos(Math.atan(e.Br*ev(e,t+e.SHy+e.arOff,r)))*n}function tv(e,t,r,n,o,a){let s=Math.cos(t),i=_P(e,t,r,s),c=NP(e,t,r,s);return-i*(o-a)+c+(e.sS0+e.sS2*o)*n}function rv(e,t,r){let n=e.Bxa0*Math.cos(Math.atan(e.RBX2*t))*e.LXAL,o=r+e.SHxa,a=Math.cos(e.Cxa*Math.atan(n*e.SHxa-e.Exa*(n*e.SHxa-Math.atan(n*e.SHxa))))||1;return Math.cos(e.Cxa*Math.atan(n*o-e.Exa*(n*o-Math.atan(n*o))))/a*Tl(e,t)}function Mf(e,t){let r=e.sS0===0&&e.sS2===0?0:rv(e,0,t);return tv(e,t,0,r,Ls(e,t),0)}function Pl(e,t,r){let n=Ls(e,r),o=rv(e,t,r),a=e.Byk0*Math.cos(Math.atan(e.RBY2*(r-e.RBY3)))*e.LYKA,s=t+e.SHyk,i=Math.cos(e.Cyk*Math.atan(a*e.SHyk-e.Eyk*(a*e.SHyk-Math.atan(a*e.SHyk))))||1,c=Math.cos(e.Cyk*Math.atan(a*s-e.Eyk*(a*s-Math.atan(a*s))))/i,u=e.DVykA*Math.cos(Math.atan(e.RVY4*r))*Math.sin(e.RVY5*Math.atan(e.RVY6*t))*e.LVYKA,m=c*n+u;return{Fx:o,Fy:m,Mz:tv(e,r,t,o,m,u)}}var Ds=(e,t)=>Math.max(.1,e.muY0+e.loadSensY*(t-e.nominalLoad)),Es=(e,t)=>Math.max(.1,e.muX0+e.loadSensX*(t-e.nominalLoad)),nv=(e,t,r)=>Ds(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cy*Math.atan(e.By*r)),ov=(e,t,r)=>Es(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cx*Math.atan(e.Bx*r));function Sf(e,t){let r=Math.max(1,t.Fz),n=Ds(e,r)*r,o=Es(e,r)*r,a=n*Math.sin(e.Cy*Math.atan(e.By*t.alpha)),s=o*Math.sin(e.Cx*Math.atan(e.Bx*t.kappa)),i=Math.hypot(o>0?s/o:0,n>0?a/n:0);return i>1&&(s/=i,a/=i),{Fx:s,Fy:a,Mz:0}}var ta=Math.PI/180;function sn(e){if(e.kind==="simple")return"none";let t=e.missing?.some(n=>/^aligning moment Mz\b/i.test(n))??!1,r=["QBZ1","QCZ1","QDZ1"].every(n=>Number.isFinite(e.coeffs[n]));return t||!r?"assumed":"model"}function av(e){let t=e.thermal?.operating;if(t===void 0||!e.thermal)return e;let{lateral:r,longitudinal:n,aligning:o}=e.thermal,a=r?Cs(r,t):1,s=n?Cs(n,t):1,i=o?Cs(o,t):1;if(a===1&&s===1&&i===1)return e;if(e.kind==="simple")return{...e,muY0:e.muY0*a,muX0:e.muX0*s};let c={...e.coeffs},l=(u,m)=>{c[u]=(c[u]??1)*m};return l("LMUY",a),l("LMUX",s),l("LTR",i),l("LRES",i),{...e,coeffs:c}}function ra(e,t,r){let n=0,o=0;for(let s=r;s<=t;s+=r){let i=Math.abs(e(s));i>o&&(o=i,n=s)}let a=r/10;for(let s=Math.max(a,n-r);s<=n+r;s+=a)o=Math.max(o,Math.abs(e(s)));return o}function Pe(e){let t=av(e),r=t,n=t,o=null,a=NaN,s=NaN,i=NaN,c=(v,x,M)=>(o!==null&&v===a&&x===s&&M===i||(o=Cl(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=wl(r,v,x,M),u=v,m=x,f=M),l),d=v=>e.kind==="magic"?Pl(c(v.Fz,v.gamma??0,v.p),v.kappa,v.alpha):Sf(n,v),h=(v,x,M=0,F)=>e.kind==="magic"?Ls(p(x,M,F),v):nv(n,x,v),b=(v,x,M=0,F)=>e.kind==="magic"?Tl(c(x,M,F),v):ov(n,x,v),g=(v,x,M=0,F)=>e.kind==="magic"?Mf(c(x,M,F),v):d({Fz:x,kappa:0,alpha:v,gamma:M,p:F}).Mz,y=v=>e.kind==="simple"?Ds(n,v):ra(x=>h(x*ta,v),45,1)/Math.max(1,v),R=v=>e.kind==="simple"?Es(n,v):ra(x=>b(x,v),.6,.02)/Math.max(1,v),k=v=>{let x=.1*ta;return Math.abs((h(x,v)-h(-x,v))/(2*x))};return{model:e,forces:d,Fx:b,Fy:h,Mz:g,muX:R,muY:y,corneringStiffness:k,verticalStiffness:()=>e.verticalStiffness,rollingRadius:v=>{if(e.kind==="magic"&&e.missing?.includes("UNLOADED_RADIUS"))return 0;let x=e.unloadedR0??0;if(!(x>0))return 0;let M=e.verticalStiffness*1e3;if(!(M>0))return x;let F=e.rollingFraction??.306;return x-F*Math.max(0,v)/M},relaxationLength:v=>{let x=e.relaxation;if(!x)return 0;let M=x.carcassStiffness??0;if(!(M>0))return x.sigma;let F=k(Math.max(0,v));return F>0?F/(M*1e3):x.sigma}}}function na(e){let t=Math.max(1,e.model.kind==="magic"?e.model.fnomin:e.model.nominalLoad);return e.Fy(2*ta,t,0)-e.Fy(-2*ta,t,0)>=0?1:-1}function Is(e,t=e.kind==="magic"?e.fnomin:e.nominalLoad){let r=Pe(e),n=2*ta,o=3*ta,a=r.Fy(n,t,0),s=r.Fy(n,t,o);return!Number.isFinite(a)||!Number.isFinite(s)?!1:Math.abs(s-a)>1}var OP=Math.PI/180;function ge(e,t){return e.axle?e.axle(t):e}function Dl(e,t){if(e===t)return e;let r=na(e)*na(t),n=(l,u)=>.5*(l+u),o=(l,u)=>l>0&&u>0?n(l,u):l>0?l:u>0?u:0,a=l=>{let u=e.forces(l),m=t.forces(l);return{Fx:n(u.Fx,m.Fx),Fy:n(u.Fy,r*m.Fy),Mz:n(u.Mz,r*m.Mz)}},s=(l,u,m=0,f)=>n(e.Fx(l,u,m,f),t.Fx(l,u,m,f)),i=(l,u,m=0,f)=>n(e.Fy(l,u,m,f),r*t.Fy(l,u,m,f)),c=(l,u,m=0,f)=>n(e.Mz(l,u,m,f),r*t.Mz(l,u,m,f));return{model:e.model,forces:a,Fx:s,Fy:i,Mz:c,muX:l=>ra(u=>s(u,l),.6,.02)/Math.max(1,l),muY:l=>ra(u=>i(u*OP,l),45,1)/Math.max(1,l),corneringStiffness:l=>n(e.corneringStiffness(l),t.corneringStiffness(l)),verticalStiffness:()=>o(e.verticalStiffness(),t.verticalStiffness()),rollingRadius:l=>o(e.rollingRadius(l),t.rollingRadius(l)),relaxationLength:l=>o(e.relaxationLength(l),t.relaxationLength(l)),axle:l=>l==="front"?e:t}}function ut(e){if(sv.has(e))return e;let t=iv.get(e);if(t)return t;let r;if(e.axle){let n=e.axle("front"),o=e.axle("rear"),a=ut(n),s=ut(o);r=a===n&&s===o?e:Dl(a,s)}else na(e)>0?r=e:r={...e,forces:n=>{let o=e.forces(n);return{Fx:o.Fx,Fy:-o.Fy,Mz:-o.Mz}},Fy:(n,o,a,s)=>-e.Fy(n,o,a,s),Mz:(n,o,a,s)=>-e.Mz(n,o,a,s)};return sv.add(r),r!==e&&iv.set(e,r),r}var sv=new WeakSet,iv=new WeakMap;var El=25*(Math.PI/180);function VP(e){let t=.6180339887,r=0,n=El,o=n-t*(n-r),a=r+t*(n-r),s=e(o),i=e(a);for(let l=0;l<12;l++)s>i?(n=a,a=o,i=s,o=n-t*(n-r),s=e(o)):(r=o,o=a,s=i,a=r+t*(n-r),i=e(a));return{alpha:s>i?o:a,force:Math.max(s,i)}}function _s(e,t,r,n,o=0){let a=Math.abs(t);if(!(a>0))return 0;let s=u=>Math.abs(e.Fy(u,r,0))+Math.abs(e.Fy(u,n,0)),i=0,c=El;if(s(El)<=a){let u=VP(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(El,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 Af={shaft:!1,trail:0,hub:[0,0,0]};function lv(e){let t=e.spinAxis,r=Math.hypot(t[0],t[1]);if(r<1e-9)return[1,0,0];let n=[-t[1]/r,t[0]/r,0];return n[0]<0?[-n[0],-n[1],0]:n}function Ff(e,t,r){let n=r.shaft?kf(e,t):[0,0,0];if(r.trail!==0){let a=lv(e),s=[t[0],t[1],0],i=H(s,U(a,X(s,a)));n=ee(n,ae(U(a,-r.trail),i))}let o=r.hub;return(o[0]!==0||o[1]!==0||o[2]!==0)&&(n=H(n,ae(H(e.contactPatch,e.wheelCenter),o))),{force:ee(t,o),moment:n}}var BP=(e,t)=>{let r=e!==void 0&&e>0?1/e:0,n=t!==void 0&&t>0?1/t:0;return r+n},Il={ucaFront:0,ucaRear:0,lcaFront:0,lcaRear:0,tieRod:0,pushRod:0,rack:0};function On(e){return!e.measured}function Vn(e){if(!e)return!1;let t=r=>!!r&&Object.values(r).some(n=>n!==void 0&&n>0&&Number.isFinite(n));return t(e.links)||t(e.bushings)||e.rack!==void 0&&e.rack>0}function Ns(e,t){let r=e.corner.hardpoints,n=us(e.rocker,t.points.rockerAngle);return{ucaFront:r.ucaFront,ucaRear:r.ucaRear,lcaFront:r.lcaFront,lcaRear:r.lcaRear,tieInner:Go(e.inv,t.steer),rockerPivotA:r.rockerPivotA,rockerPivotB:r.rockerPivotB,damperChassis:e.inv.strut?t.points.uprightUpper:r.damperChassis,uprightUpper:t.points.uprightUpper,uprightLower:t.points.uprightLower,tieOuter:t.points.tieOuter,wheelCenter:t.points.wheelCenter,pushrodOuter:t.points.pushrodOuter,contactPatch:t.points.contactPatch,kingpinGround:t.points.kingpinGround,kingpinAtHub:t.points.kingpinAtHub,rockerToPushrod:n.pushrod,rockerToDamper:n.damper,spinAxis:t.points.spinAxis,direct:e.corner.config.actuation==="direct",decoupled:e.corner.config.actuation==="decoupled",mcpherson:e.inv.strut!==void 0,loadedRadius:e.corner.config.loadedRadius,tyreDeflection:0,load:NaN,lifted:!1,clearance:0,contactLength:0}}function wf(e,t,r=0){let n=t.links??{},o=t.bushings??{},a=(l,u,m)=>{let f=BP(u,m);return f>0&&Number.isFinite(l)?l*f:0},s=o.topMount,i=e.topMount,c=i&&s!==void 0&&s>0&&i.every(Number.isFinite)?[-i[0]/s,-i[1]/s,-i[2]/s]:void 0;return{...c?{topMount:c}:{},ucaFront:a(e.ucaFront,n.ucaFront,o.ucaFront),ucaRear:a(e.ucaRear,n.ucaRear,o.ucaRear),lcaFront:a(e.lcaFront,n.lcaFront,o.lcaFront),lcaRear:a(e.lcaRear,n.lcaRear,o.lcaRear),tieRod:a(e.tieRod,n.tieRod,o.tieInner),pushRod:a(e.pushRod,n.pushRod,void 0),rack:r}}function uv(e,t,r,n){let o=ve(e,t);if(!(o>1e-9))return{axial:r,radius2:0};let a=(r*r-n*n+o*o)/(2*o);return{axial:a,radius2:Math.max(0,r*r-a*a)}}function Os(e,t){let r=e.corner.hardpoints,n=e.inv,o={...n};if(n.strut&&t.topMount&&t.topMount.some(i=>i!==0)&&(o.strut={...n.strut,top:ee(n.strut.top,t.topMount)}),t.ucaFront!==0||t.ucaRear!==0){let i=uv(r.ucaFront,r.ucaRear,ve(r.uprightUpper,r.ucaFront)+t.ucaFront,ve(r.uprightUpper,r.ucaRear)+t.ucaRear);o.ubjAxial0=i.axial,o.ubjRadius2=i.radius2}if(t.lcaFront!==0||t.lcaRear!==0){let i=uv(r.lcaFront,r.lcaRear,ve(r.uprightLower,r.lcaFront)+t.lcaFront,ve(r.uprightLower,r.lcaRear)+t.lcaRear),c=X(n.lbjRel0,n.lcaDir),l=H(n.lbjRel0,U(n.lcaDir,c)),u=Math.hypot(l[0],l[1],l[2]);o.lbjRel0=u>1e-9?ee(U(n.lcaDir,i.axial),U(l,Math.sqrt(i.radius2)/u)):ee(U(n.lcaDir,i.axial),l)}if(t.tieRod!==0){let i=Math.sqrt(n.tieLen2)+t.tieRod;o.tieLen2=i*i}if(t.rack!==0&&(o.tieInner0=ee(n.tieInner0,U(n.rackAxis,t.rack))),t.pushRod===0)return{corner:e.corner,inv:o,rocker:e.rocker};let a=Math.sqrt(e.rocker.rodLen2)+t.pushRod,s={...e.rocker,rodLen2:a*a};return{corner:e.corner,inv:o,rocker:s}}var $P=8,GP=1e-5,KP=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 Cf(e,t,r){let n=Ff(e,r.force,r.extras??Af),o=r.alignMoment?ee(n.moment,[0,0,r.alignMoment]):n.moment;return ws(e,t,n.force,o)}function Nl(e,t,r,n,o,a,s=0){let i=Ie(e,t,r,o,a),c=e.corner.compliance;if(!(Vn(c)&&On(e.corner)))return{state:i,forces:Cf(Ns(e,i),e.corner.config.pushrodAttach,n),deflection:Il,rigid:i,iterations:0,converged:!0,bypassed:!0};let u=i,m=e,f=e.corner.config.pushrodAttach,p=Cf(Ns(e,i),f,n),d=Il,h=!1,b=0;for(;b<$P;b++){let g=Ns(m,u);if(p=Cf(g,f,n),p.singular)break;d=wf(p,c,s),m=Os(e,d);let y=Ie(m,t,r,KP(u),a),R=ve(y.points.wheelCenter,u.points.wheelCenter);if(u=y,R<GP){h=!0;break}}return{state:u,forces:p,deflection:d,rigid:i,iterations:b+1,converged:h&&u.converged,bypassed:!1}}var _l=1e3,mv=1e5;function pv(e,t,r,n,o){let a=Nl(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 Ol(e,t,r,n,o){let a={force:[0,0,n]},s=(b,g=0)=>pv(e,t,r,{force:b,alignMoment:g},o),i=pv(e,t,r,a,o);if(i.bypassed)return{toePerLateral:0,camberPerLateral:0,toePerLongitudinal:0,camberPerLongitudinal:0,toePerAligning:0,lateralPatch:0,longitudinalPatch:0,bypassed:!0,converged:!0};let c=s([0,_l,n]),l=s([0,-_l,n]),u=s([_l,0,n]),m=s([-_l,0,n]),f=s([0,0,n],mv),p=s([0,0,n],-mv),d=(b,g)=>(b-g)/2,h=[i,c,l,u,m,f,p].every(b=>b.converged);return{toePerLateral:d(c.toe,l.toe),camberPerLateral:d(c.camber,l.camber),toePerLongitudinal:d(u.toe,m.toe),camberPerLongitudinal:d(u.camber,m.camber),toePerAligning:d(f.toe,p.toe),lateralPatch:d(c.patch[1],l.patch[1]),longitudinalPatch:d(u.patch[0],m.patch[0]),bypassed:!1,converged:h}}var HP=1e3;function Tf(e,t=HP){if(!Vn(e.compliance)||!On(e))return;let r=tt(e),n=Ie(r,0,0),o=Ol(r,n.beta,0,t);if(!o.bypassed)return{toePerFy:o.toePerLateral/1e3,camberPerFy:o.camberPerLateral/1e3,toePerFx:o.toePerLongitudinal/1e3,camberPerFx:o.camberPerLongitudinal/1e3,toePerMz:o.toePerAligning/1e5}}function oa(e,t=-vf,r=vf,n=21){let o=e.measured;if(o)return{travel:[...o.travel],motionRatio:[...o.motionRatio],camber:[...o.camber],toe:[...o.toe],damperLen:o.damperLen?[...o.damperLen]:o.travel.map(()=>0)};let a=Ke(e,{travelMin:t,travelMax:r,steps:n}),s=Tf(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 cn(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 dv=Math.PI/180,zP=9.81;function ln(e,t,r,n=0){let o=we(e),a=e.wheelbase*(1-e.frontMassFrac),s=e.wheelbase*e.frontMassFrac,i=Jo(e,n),c=e.aero?.model?(k,v,x)=>Jo(e,n,v,k,x):()=>i,l=cn(t,0),u=cn(r,0),m=e.loadFactor,f=m!==void 0&&m!==1?(m-1)*e.massTotal*zP:0,p=f*e.frontMassFrac/2,d=f*(1-e.frontMassFrac)/2,h=(k,v)=>v>0&&Number.isFinite(v)&&k+v>0?v/(k+v):1,b=Xe(e,"front"),g=Xe(e,"rear"),y={F:h(e.wheelRateFront+(e.heaveSpringFront??0),b),R:h(e.wheelRateRear+(e.heaveSpringRear??0),g)},R={F:h(e.wheelRateFront+e.arbFront,b),R:h(e.wheelRateRear+e.arbRear,g)};return(k,v,x=0,M=0)=>{let F=c(k,v,x),w=o.rollGradient*k,C=w*dv,T=o.pitchGradient*v*dv,S=(V,N)=>{let z=N==="F"?e.trackFront:e.trackRear,I=N==="F"?o.rideRateFront:o.rideRateRear,_=(V==="R"?1:-1)*(z/2)*Math.tan(C),B=(N==="R"?s:-a)*Math.tan(T),O=`${N}${V}`,G=f?F[O]+(N==="F"?p:d):F[O],K=I>0?G/I:0;return{anti:_,sym:B+K}},A={FL:S("L","F"),FR:S("R","F"),RL:S("L","R"),RR:S("R","R")},P=V=>{let N=V[0];return A[V].sym*y[N]+A[V].anti*R[N]},L=Zo(e,M,o,{FL:P("FL"),FR:P("FR")}),D=w+L.rollDeg,E=(V,N)=>{let z=N==="F"?t:r,I=N==="F"?l:u,_=`${N==="F"?"F":"R"}${V}`,B=A[_].sym+A[_].anti+L.travel[_],O=P(_)+L.travel[_]*R[N],G=B-O,K=cn(z,O),Y=(V==="R"?1:-1)*K.camber;return{travel:O,tyre:G,ground:B,camber:Y,camberRoad:Y+D,toe:K.toe,bumpToe:K.toe-I.toe,damperTravel:I.damperLen-K.damperLen}};return{FL:E("L","F"),FR:E("R","F"),RL:E("L","R"),RR:E("R","R"),steeringJacking:L}}}var Pf=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function Bn(e){return{enabled:e?.enabled===!0,roadFeedbackGain:Math.min(2,Math.max(0,Pf(e?.roadFeedbackGain,1))),turnInFrictionNm:Math.max(0,Pf(e?.turnInFrictionNm,0)),columnStiffnessNmPerRad:Math.max(0,Pf(e?.columnStiffnessNmPerRad,0))}}function Lf(e,t,r){let n=Bn(r);if(!n.enabled)return{roadNm:e,assistanceNm:0,frictionNm:0,columnTwistDeg:0,driverNm:e};let o=e*(n.roadFeedbackGain-1),a=t===0?0:Math.sign(t)*n.turnInFrictionNm,s=e+o+a,i=n.columnStiffnessNmPerRad>0?s/n.columnStiffnessNmPerRad*(180/Math.PI):0;return{roadNm:e,assistanceNm:o,frictionNm:a,columnTwistDeg:i,driverNm:s}}var fv=()=>({totalNm:0,aligningNm:0,lateralNm:0,longitudinalNm:0,jackingNm:0});function $n(e){let t=e.steerFront;return!!(t?.rackRatioMmPerRev&&t.innerJacobian&&t.innerJacobian.length>=2&&t.outerJacobian&&t.outerJacobian.length>=2&&t.meanDeg.length>=2)}function Vs(e,t,r,n="model",o){let a=e.steerFront;if(!$n(e)||!a)return null;let s=t<0?-1:1,c=a.rackRatioMmPerRev/(2*Math.PI)/1e3,l=t>=0,u=o&&a.travelSurface?Qo(a,Math.abs(t),l?o.FL:o.FR,l?o.FR:o.FL):qo(a,Math.abs(t));if(!u.innerJacobian||!u.outerJacobian)return null;let m=(b,g)=>{let y=r[b],R=b==="FL"?-1:1,k=-R*y.Fy,x={aligning:1e3*(-R*y.Mz)*g.yaw,lateral:k*g.lateral,longitudinal:y.Fx*g.longitudinal,jacking:y.Fz*g.vertical},M=fv();M.aligningNm=-s*x.aligning*c,M.lateralNm=-s*x.lateral*c,M.longitudinalNm=-s*x.longitudinal*c,M.jackingNm=-s*x.jacking*c,M.totalNm=M.aligningNm+M.lateralNm+M.longitudinalNm+M.jackingNm;let F=-s*(x.aligning+x.lateral+x.longitudinal+x.jacking);return{moment:M,rackN:F}},f=m("FL",l?u.innerJacobian:u.outerJacobian),p=m("FR",l?u.outerJacobian:u.innerJacobian),d=fv();for(let b of[f.moment,p.moment])d.aligningNm+=b.aligningNm,d.lateralNm+=b.lateralNm,d.longitudinalNm+=b.longitudinalNm,d.jackingNm+=b.jackingNm,d.totalNm+=b.totalNm;let h=Lf(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 YP=e=>"front"in e&&"rear"in e;function aa(e,t){return YP(e)?e[t]:e}function Ef(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 Df(e,t){let r=Math.max(0,t.Fz),n=e.muY(r)*r,o=e.muX(r)*r;if(!(n>0))return{fyUsed:0,fyMax:0,fyRes:0};let a=o>0?Math.min(1,Math.abs(t.Fx)/o):0,s=n*Math.sqrt(Math.max(0,1-a*a)),i=Math.abs(t.Fy);return{fyUsed:i,fyMax:s,fyRes:Math.max(0,s-i)}}function hv(e,t,r){let n=Df(e,t),o=Df(e,r);return{left:n,right:o,fyRes:n.fyRes+o.fyRes}}function Ar(e,t,r){let n=hv(aa(e,"front"),t.FL,t.FR),o=hv(aa(e,"rear"),t.RL,t.RR),a=r.lf>0&&Number.isFinite(r.lf)?r.lf:0,s=r.lr>0&&Number.isFinite(r.lr)?r.lr:0,i=o.fyRes*s,c=n.fyRes*a,l=i-c,u=Math.max(Math.abs(i),Math.abs(c));return{stabil:i,agil:c,diff:l,rel:u>0?l/u:0,front:n,rear:o}}var Bs=[{q:"p",section:"INFLATION_PRESSURE_RANGE",min:"PRESMIN",max:"PRESMAX",what:"pressure"},{q:"fz",section:"VERTICAL_FORCE_RANGE",min:"FZMIN",max:"FZMAX",what:"load"},{q:"kappa",section:"LONG_SLIP_RANGE",min:"KPUMIN",max:"KPUMAX",what:"slip ratio"},{q:"alpha",section:"SLIP_ANGLE_RANGE",min:"ALPMIN",max:"ALPMAX",what:"slip angle"},{q:"gamma",section:"INCLINATION_ANGLE_RANGE",min:"CAMMIN",max:"CAMMAX",what:"inclination"}],jP=Bs.flatMap(e=>[e.min,e.max]);function UP(e){let t={};for(let r of Bs){let n=e[r.min],o=e[r.max],a={};Number.isFinite(n)&&(a.min=n),Number.isFinite(o)&&(a.max=o),(a.min!==void 0||a.max!==void 0)&&(t[r.q]=a)}return Object.keys(t).length?t:void 0}function Bl(e){if(e.kind==="magic")return e.range??UP(e.coeffs)}function If(e){return Math.max(1,e.kind==="magic"?e.fnomin:e.nominalLoad)}function bv(e,t,r,n,o){let a=(r-t)/n,s=t,i=e(t);for(let c=t+a;c<=r;c+=a){let l=e(c);o(l,i)&&(i=l,s=c)}return s}function Wt(e){let t=gv.get(e);if(t!==void 0)return t;let r=10*If(e.model),{turnover:n,collapse:o}=QP(e,r),a=n??o??r;return gv.set(e,a),a}var gv=new WeakMap;function QP(e,t){let r=If(e.model),n=m=>e.muY(m),o=m=>n(m)*m,a=80,s=t/a,i=null,c=o(s);for(let m=2;m<=a;m++){let f=o(m*s);if(f<c){i=bv(o,(m-2)*s,m*s,20,(p,d)=>p>d);break}c=f}let l=null,u=n(s);for(let m=2;m<=a;m++){let f=n(m*s);if(f>u){let p=bv(n,(m-2)*s,m*s,40,(d,h)=>d<h);n(p)<.05*n(r)&&(l=p);break}u=f}return{turnover:i,collapse:l}}var yv=.1;function $l(e,t=If(e)){let r=Pe(e).muX(t);return{muX:r,none:Number.isFinite(r)&&r<yv}}var xv=["FL","FR","RL","RR"],qP=e=>e==="FL"||e==="RL",ZP=e=>e==="FL"||e==="FR"?"front":"rear";function Gl(e,t,r,n){if(!(e.full>e.open)||n.ayDir===0)return e.full;let o=n.halfTrack[e.axle],a={};for(let l of xv)a[l]={...t[l]};let s=l=>{let u=0;for(let f of xv)ZP(f)===e.axle&&(a[f].Fx=e.sense*(f===e.strong?l-e.open/2:e.open/2),u-=(qP(f)?o:-o)*a[f].Fx);let m=Ar(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 JP=[["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]],eL=[["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]],tL=[["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]],rL=[["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]],nL=[["LFZO","Scale factor of nominal (rated) load",1],["LCX","Scale factor of Fx shape factor",1],["LMUX","Scale factor of Fx peak friction coefficient",1],["LEX","Scale factor of Fx curvature factor",1],["LKX","Scale factor of Fx slip stiffness",1],["LHX","Scale factor of Fx horizontal shift",1],["LVX","Scale factor of Fx vertical shift",1],["LCY","Scale factor of Fy shape factor",1],["LMUY","Scale factor of Fy peak friction coefficient",1],["LEY","Scale factor of Fy curvature factor",1],["LKY","Scale factor of Fy cornering stiffness",1],["LKYC","Scale factor of camber force stiffness",1],["LKZC","Scale factor of camber torque stiffness",1],["LHY","Scale factor of Fy horizontal shift",1],["LVY","Scale factor of Fy vertical shift",1],["LTR","Scale factor of peak of pneumatic trail",1],["LRES","Scale factor for offset of residual torque",1],["LXAL","Scale factor of alpha influence on Fx",1],["LYKA","Scale factor of kappa influence on Fy",1],["LVYKA","Scale factor of kappa induced Fy",1],["LS","Scale factor of moment arm of Fx",1]],vv=[["lateral",JP],["longitudinal",eL],["aligning",tL],["combined",rL],["scaling",nL]].flatMap(([e,t])=>t.map(([r,n,o])=>({key:r,section:e,text:n,fallback:o}))),iH=new Map(vv.map(e=>[e.key,e]));var oL=/^\$\s*EDITED\s+([A-Z][A-Z0-9_]*)\s+was\s+(absent|[-+0-9.eE]+)\s*$/;function kv(e){let t={};for(let r of e.split(/\r?\n/)){let n=r.trim().match(oL);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 sL=/^\s*\$\s*UNLOADED_RADIUS_STAND_IN\s*=\s*([0-9.eE+-]+)/,iL=/^\$-+ written by (?:PaceDynamics|PaceLab)\b/m,cL=/^\$\s*AXIS_SYSTEM\s*=\s*(ISO-W|SAE)\b/m;function lL(e){let t=e.match(cL);return t?{axisSystem:t[1]==="SAE"?"sae":"iso",trustSide:!0}:iL.test(e)?{axisSystem:"sae",trustSide:!1}:{axisSystem:"iso",trustSide:!0}}function uL(e){return e>=62?"6.2":e>=61?"6.1":"5.2"}var Mv=new Map([["pa",1],["pascal",1],["kpa",1e3],["kilopascal",1e3],["mpa",1e6],["megapascal",1e6],["bar",1e5],["psi",6894.757293168]]);function mL(e,t,r){let n=r.PRESSURE?.trim().toLowerCase(),o=n===void 0?1:Mv.get(n);if(o===void 0)return;let a=(c,l)=>l===1?c:Number((c*l).toPrecision(12)),s=e.NOMPRES??e.INFLPRES;if(s!==void 0)return a(s,o);let i=e.INFLATION_PRESSURE;if(i!==void 0)return n!==void 0?a(i,o):t.PROPERTY_FILE_FORMAT?.trim().toUpperCase()==="MF_05"?a(i,1e5):void 0}var pL=new Map([["radians",1],["radian",1],["rad",1],["degrees",Math.PI/180],["degree",Math.PI/180],["deg",Math.PI/180]]);function dL(e,t){let r=(s,i)=>s===void 0?1:i.get(s.trim().toLowerCase()),n=r(t.ANGLE,pL),o={fz:1,kappa:1,alpha:n,gamma:n,p:r(t.PRESSURE,Mv)},a={};for(let s of Bs){let i=o[s.q];if(i===void 0)continue;let c={};for(let[l,u]of[["min",s.min],["max",s.max]]){let m=e[u];Number.isFinite(m)&&(c[l]=i===1?m:Number((m*i).toPrecision(12)),delete e[u])}(c.min!==void 0||c.max!==void 0)&&(a[s.q]=c)}return Object.keys(a).length?a:void 0}function $s(e,t="imported",r={}){let n=lL(e),o=r.axisSystem??n.axisSystem,a={},s={},i={},c="",l;for(let g of e.split(/\r?\n/)){let y=g.match(sL);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=uL(a.FITTYP??62),m=kv(e),f=m?Object.fromEntries(Object.entries(m).filter(([g])=>a[g]!==void 0)):void 0,p=a.VERTICAL_STIFFNESS??a.KZ??0,d=mL(a,s,i),h=dL(a,i),b=[];return a.UNLOADED_RADIUS===void 0&&a.R0===void 0&&b.push("UNLOADED_RADIUS"),p<=0&&b.push("VERTICAL_STIFFNESS"),a.FNOMIN===void 0&&b.push("FNOMIN"),d===void 0&&b.push("NOMPRES"),{kind:"magic",name:t,version:u,coeffs:a,axisSystem:o,side:n.trustSide?s.TYRESIDE==="RIGHT"?"right":s.TYRESIDE==="LEFT"?"left":void 0:void 0,fnomin:a.FNOMIN??5e3,unloadedR0:a.UNLOADED_RADIUS??a.R0??(l!==void 0&&l>0?l:.3),...a.WIDTH!==void 0&&a.WIDTH>0?{sectionWidth:a.WIDTH}:{},verticalStiffness:p>0?p/1e3:0,...a.FREFF!==void 0&&!a.DREFF?{rollingFraction:a.FREFF}:{},...a.LATERAL_STIFFNESS!==void 0&&a.LATERAL_STIFFNESS>0?{relaxation:{sigma:0,carcassStiffness:a.LATERAL_STIFFNESS/1e3,source:"fitted"}}:{},nomPressure:d??0,missing:b,...f&&Object.keys(f).length?{edited:f}:{},...h?{range:h}:{}}}function ar(e){if(!e)return null;let t=e.unloadedR0;return t===void 0||!(t>0)||e.kind==="magic"&&e.missing?.includes("UNLOADED_RADIUS")?null:t*1e3}var hH=Math.PI/180;var RH=Math.PI/180,vH=180/Math.PI;function Gs(){return{kind:"simple",name:"Simple (default)",Bx:11,Cx:1.6,muX0:1.7,loadSensX:-8e-5,By:9,Cy:1.4,muY0:1.6,loadSensY:-1e-4,nominalLoad:1500,verticalStiffness:120}}var Fv=`$ AXIS_SYSTEM = SAE (authored in the evaluation frame: y right)
3
3
  [MODEL]
4
4
  FITTYP = 62
5
5
  [DIMENSION]
@@ -108,7 +108,7 @@ QHZ1 = 0
108
108
  QHZ2 = 0
109
109
  QHZ3 = 0
110
110
  QHZ4 = 0
111
- `;function Ef(){return $s(Fv,"Example MF6.2")}var fL=Math.PI/180,wv=2,Cv=2;function Tv(e){let t=Math.sin(Cv*Math.atan(1/wv)),r=-e.corneringStiffness/(e.Fz0*t),n=e.camberStiffness/fL/e.Fz0,o=(a,s=5)=>Number(a.toFixed(s)).toString();return`$ AXIS_SYSTEM = SAE (authored in the evaluation frame: y right, +inclination gives +Fy)
111
+ `;function _f(){return $s(Fv,"Example MF6.2")}var hL=Math.PI/180,wv=2,Cv=2;function Tv(e){let t=Math.sin(Cv*Math.atan(1/wv)),r=-e.corneringStiffness/(e.Fz0*t),n=e.camberStiffness/hL/e.Fz0,o=(a,s=5)=>Number(a.toFixed(s)).toString();return`$ AXIS_SYSTEM = SAE (authored in the evaluation frame: y right, +inclination gives +Fy)
112
112
  [MODEL]
113
113
  FITTYP = 62
114
114
  [DIMENSION]
@@ -220,7 +220,7 @@ QHZ1 = 0
220
220
  QHZ2 = 0
221
221
  QHZ3 = 0
222
222
  QHZ4 = 0
223
- `}function Ar(e){let t=$s(Tv(e),e.name);return{...t,missing:[...t.missing??[],"a particular tyre \u2014 every coefficient is derived from class-level targets stated in generic.ts, on the road; run it with grip_scale = stiffness_scale = 1"]}}var Pv={name:"Formula Student 18x6-10",R0:.228,width:.1524,Fz0:950,Kz:110,pressure:83,muY:1.8,muX:1.7,muYLoad:-.2,muXLoad:-.15,corneringStiffness:26e3,slipStiffnessPerLoad:32,camberStiffness:45,Cy:1.5,Cx:1.6,RBY1:12,RBY2:12,RBX1:13,RBX2:10,trail:.08},Lv={name:"Formula 1 slick 18in",R0:.36,width:.305,Fz0:5e3,Kz:300,pressure:150,muY:1.8,muX:1.7,muYLoad:-.15,muXLoad:-.12,corneringStiffness:15e4,slipStiffnessPerLoad:28,camberStiffness:260,Cy:1.45,Cx:1.6,RBY1:12,RBY2:12,RBX1:13,RBX2:10,trail:.09},Dv={name:"GT slick 18in",R0:.33,width:.3,Fz0:4e3,Kz:280,pressure:180,muY:1.45,muX:1.4,muYLoad:-.12,muXLoad:-.1,corneringStiffness:11e4,slipStiffnessPerLoad:24,camberStiffness:190,Cy:1.4,Cx:1.6,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.09},Ev={name:"Street tyre 245/40 R18",R0:.325,width:.245,Fz0:4e3,Kz:220,pressure:240,muY:1.05,muX:1,muYLoad:-.1,muXLoad:-.08,corneringStiffness:75e3,slipStiffnessPerLoad:20,camberStiffness:100,Cy:1.3,Cx:1.55,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.12},Iv={name:"Cup slick 18in",R0:.32,width:.25,Fz0:3500,Kz:280,pressure:180,muY:1.42,muX:1.38,muYLoad:-.12,muXLoad:-.1,corneringStiffness:9e4,slipStiffnessPerLoad:24,camberStiffness:160,Cy:1.4,Cx:1.6,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.09},_v={name:"Stock car slick 18in",R0:.357,width:.32,Fz0:4500,Kz:320,pressure:200,muY:1.35,muX:1.3,muYLoad:-.12,muXLoad:-.1,corneringStiffness:125e3,slipStiffnessPerLoad:22,camberStiffness:170,Cy:1.4,Cx:1.6,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.09},Nv={name:"Hill-climb slick 13in",R0:.3,width:.3,Fz0:2e3,Kz:200,pressure:150,muY:1.75,muX:1.65,muYLoad:-.18,muXLoad:-.14,corneringStiffness:6e4,slipStiffnessPerLoad:28,camberStiffness:90,Cy:1.45,Cx:1.6,RBY1:12,RBY2:12,RBX1:13,RBX2:10,trail:.085},Ov={name:"Race truck tyre 315/70 R22.5",R0:.506,width:.315,Fz0:13e3,Kz:1e3,pressure:800,muY:1.1,muX:1.05,muYLoad:-.1,muXLoad:-.08,corneringStiffness:15e4,slipStiffnessPerLoad:14,camberStiffness:200,Cy:1.3,Cx:1.55,RBY1:10,RBY2:10,RBX1:11,RBX2:10,trail:.1},If=()=>Ar(Pv),_f=()=>Ar(Lv),Nf=()=>Ar(Dv),Of=()=>Ar(Ev),Vf=()=>Ar(Iv),Bf=()=>Ar(_v),$f=()=>Ar(Nv),Gf=()=>Ar(Ov);var Vv=e=>Number.isFinite(e)&&e>0;function Gl(e,t){let r=Vv(t.grip)?t.grip:1,n=Vv(t.stiffness)?t.stiffness:1;if(r===1&&n===1)return e;if(e.kind==="simple"){let o=n/r;return{...e,muX0:e.muX0*r,muY0:e.muY0*r,loadSensX:e.loadSensX*r,loadSensY:e.loadSensY*r,Bx:e.Bx*o,By:e.By*o}}return{...e,coeffs:{...e.coeffs,LMUX:(e.coeffs.LMUX??1)*r,LMUY:(e.coeffs.LMUY??1)*r,LKX:(e.coeffs.LKX??1)*n,LKY:(e.coeffs.LKY??1)*n}}}var Ks={ok:!0,violation:0},Gn=1e7;function Fr(e,t){let r;try{r=e.build(t)}catch(s){return{total:Gn*2,feasible:!1,terms:[],reason:`build failed: ${String(s)}`}}let n=e.feasible(r);if(!n.ok)return{total:Gn+Math.max(0,n.violation),feasible:!1,terms:[],reason:n.reason};let o;try{o=e.terms(r)}catch(s){return{total:Gn*2,feasible:!1,terms:[],reason:`objective threw: ${String(s)}`}}let a=0;for(let s of o)a+=s.contribution;return Number.isFinite(a)?{total:a,feasible:!0,terms:o}:{total:Gn*2,feasible:!1,terms:o,reason:"objective was not finite"}}var Hs=(e,t)=>!t||(e.feasible!==t.feasible?e.feasible:e.total<t.total);function Kf(e,t){return t.map((r,n)=>Math.min(e[n].hi,Math.max(e[n].lo,r)))}var wr=e=>e.map(t=>t.start);function Kl(e){let t=e>>>0;return()=>{t=t+1831565813>>>0;let r=Math.imul(t^t>>>15,1|t);return r=r+Math.imul(r^r>>>7,61|r)^r,((r^r>>>14)>>>0)/4294967296}}function hL(e){let t=0;for(;t===0;)t=e();return Math.sqrt(-2*Math.log(t))*Math.cos(2*Math.PI*e())}function Hf(e,t){let{budget:r}=t,n=Math.max(1,Math.floor(t.progressEvery??1)),o=e.variables,a=p=>Kf(o,p.map((d,h)=>o[h].lo+d*(o[h].hi-o[h].lo))),s=p=>p.map((d,h)=>(d-o[h].lo)/(o[h].hi-o[h].lo)),i=0,c=0,l=null,u=null,m=[];return{vars:o,denorm:a,norm:s,evaluate:p=>{if(i>=r)return l?.total??Number.POSITIVE_INFINITY;i++;let d=p.map(g=>Math.min(1,Math.max(0,g))),h=Fr(e,a(d));h.feasible||c++;let b=Hs(h,l)?h:l;return b===h&&(l=h,u=d),m.push(b.total),t.onProgress&&(i%n===0||i===r)&&t.onProgress({evaluations:i,budget:r,x:a(u),score:b,infeasible:c}),h.total},left:()=>r-i,result:p=>({method:p,x:u?a(u):wr(o),score:l??Fr(e,wr(o)),evaluations:i,history:m,infeasible:c})}}var zf=(e,t,r,n=0,o)=>{let a=t?r.norm(wr(e.variables)):e.variables.map(()=>.5);return!(n>0)||!o?a:a.map(s=>Math.min(1,Math.max(0,s+n*2*(o()-.5))))};function Bv(e,t){let r=Hf(e,t),n=Kl(t.seed??1),o=e.variables.length;for(r.evaluate(zf(e,t.warmStart!==!1,r,t.startJitter,n));r.left()>0;){let a=[];for(let s=0;s<o;s++)a.push(n());r.evaluate(a)}return r.result("random")}function sa(e,t){let r=Hf(e,t),n=e.variables.length,o=Kl(t.seed??1),a=1,s=2,i=.5,c=.5,l=zf(e,t.warmStart!==!1,r,t.startJitter,o),u=.25;for(;r.left()>0;){let m=[{u:l,f:r.evaluate(l)}];for(let f=0;f<n&&r.left()>0;f++){let p=l.slice();p[f]+=p[f]+u>1?-u:u,m.push({u:p,f:r.evaluate(p)})}for(;r.left()>0;){m.sort((g,y)=>g.f-y.f);let f=m[n],p=new Array(n).fill(0);for(let g=0;g<n;g++)for(let y=0;y<n;y++)p[y]+=m[g].u[y]/n;let d=g=>p.map((y,R)=>y+g*(y-f.u[R])),h=d(a),b=r.evaluate(h);if(b<m[0].f){let g=d(s),y=r.evaluate(g);m[n]=y<b?{u:g,f:y}:{u:h,f:b}}else if(b<m[n-1].f)m[n]={u:h,f:b};else{let g=d(-i),y=r.evaluate(g);if(y<f.f)m[n]={u:g,f:y};else{let R=m[0],k=0;for(let v=1;v<=n;v++)for(let x=0;x<n;x++)k=Math.max(k,Math.abs(m[v].u[x]-R.u[x]));if(k<1e-4)break;for(let v=1;v<=n&&r.left()>0;v++){let x=m[v].u.map((M,F)=>R.u[F]+c*(M-R.u[F]));m[v]={u:x,f:r.evaluate(x)}}}}}m.sort((f,p)=>f.f-p.f),l=m[0].u.map(f=>Math.min(1,Math.max(0,f+.05*(o()-.5)))),u=Math.max(.02,u*.5)}return r.result("nelder-mead")}function $v(e,t){let r=Hf(e,t),n=e.variables.length,o=Kl(t.seed??1),a=4+Math.floor(3*Math.log(n)),s=Math.floor(a/2),i=[];for(let M=1;M<=s;M++)i.push(Math.log(s+.5)-Math.log(M));let c=i.reduce((M,F)=>M+F,0);for(let M=0;M<s;M++)i[M]/=c;let l=1/i.reduce((M,F)=>M+F*F,0),u=(l+2)/(n+l+5),m=1+2*Math.max(0,Math.sqrt((l-1)/(n+1))-1)+u,f=(4+l/n)/(n+4+2*l/n),p=(n+2)/3,d=Math.min(1,p*2/((n+1.3)**2+l)),h=Math.min(1-d,p*2*(l-2+1/l)/((n+2)**2+l)),b=Math.sqrt(n)*(1-1/(4*n)+1/(21*n*n)),g=zf(e,t.warmStart!==!1,r,t.startJitter,o),y=.25,R=new Array(n).fill(1),k=new Array(n).fill(0),v=new Array(n).fill(0),x=0;for(;r.left()>0;){x++;let M=[];for(let S=0;S<a&&r.left()>0;S++){let A=[];for(let L=0;L<n;L++)A.push(hL(o));let P=g.map((L,D)=>L+y*R[D]*A[D]);M.push({z:A,u:P,f:r.evaluate(P)})}if(M.length<s)break;M.sort((S,A)=>S.f-A.f);let F=g.slice(),w=new Array(n).fill(0);g=new Array(n).fill(0);for(let S=0;S<s;S++)for(let A=0;A<n;A++)g[A]+=i[S]*M[S].u[A],w[A]+=i[S]*M[S].z[A];g=g.map(S=>Math.min(1,Math.max(0,S)));for(let S=0;S<n;S++)k[S]=(1-u)*k[S]+Math.sqrt(u*(2-u)*l)*w[S];let C=Math.sqrt(k.reduce((S,A)=>S+A*A,0)),T=C/Math.sqrt(1-(1-u)**(2*x))/b<1.4+2/(n+1)?1:0;for(let S=0;S<n;S++){let A=(g[S]-F[S])/(y*R[S]);v[S]=(1-f)*v[S]+T*Math.sqrt(f*(2-f)*l)*A}for(let S=0;S<n;S++){let A=0;for(let D=0;D<s;D++)A+=i[D]*M[D].z[S]*M[D].z[S];let P=R[S]*R[S],L=(1-d-h)*P+d*(v[S]*v[S]+(1-T)*f*(2-f)*P)+h*A*P;R[S]=Math.sqrt(Math.max(1e-12,L))}if(y*=Math.exp(u/m*(C/b-1)),y<1e-6||y>10)break}return r.result("sep-cma-es")}var ia=[{name:"random",run:Bv},{name:"nelder-mead",run:sa},{name:"sep-cma-es",run:$v}];var OH=Math.PI/180;var Hl=Math.PI/180;var GH={Fz:100,alpha:.25*Hl,kappa:.005,gamma:.5*Hl,p:6900},Gv={Fz:100,alpha:1*Hl,kappa:.02,gamma:.5*Hl,p:6900};var Kv=Math.PI/180,jH={t:{s:1,sec:1,ms:.001},v:{"m/s":1,"km/h":1/3.6,"km/hr":1/3.6,kph:1/3.6},alpha:{rad:1,deg:Kv},gamma:{rad:1,deg:Kv},p:{pa:1,kpa:1e3,bar:1e5,mpa:1e6},rl:{m:1,mm:.001,cm:.01},Fz:{n:1},Fx:{n:1},Fy:{n:1},Mz:{nm:1,"n-m":1}};var ZH=Math.PI/180;var wL=Math.PI/180;var az=3*wL;var uz=Math.PI/180;var kz=Math.PI/180;var _L={RCX1:1,RCY1:1,REX1:0,REY1:0,RBY3:0,RHX1:0,RHY1:0},Yv={RBX1:15,RBX2:15,RBY1:18,RBY2:19,..._L};var Ez=Math.PI/180;var GL=Math.PI/180,zl=[{id:"alpha",symbol:"\u03B1",name:"Slip angle",group:"inputs",unit:"rad"},{id:"kappa",symbol:"\u03BA",name:"Slip ratio",group:"inputs",unit:"-"},{id:"gamma",symbol:"\u03B3",name:"Inclination",group:"inputs",unit:"rad"},{id:"Fz",symbol:"Fz",name:"Vertical load",group:"inputs",unit:"N",quantity:"force"},{id:"p",symbol:"p",name:"Inflation pressure",group:"inputs",unit:"Pa",quantity:"pressure"},{id:"V",symbol:"V",name:"Speed",group:"inputs",unit:"m/s",quantity:"speed"},{id:"Fx",symbol:"Fx",name:"Longitudinal force",group:"forces",unit:"N",quantity:"force"},{id:"Fy",symbol:"Fy",name:"Lateral force",group:"forces",unit:"N",quantity:"force"},{id:"Mx",symbol:"Mx",name:"Overturning moment",group:"moments",unit:"N\xB7m"},{id:"My",symbol:"My",name:"Rolling-resistance moment",group:"moments",unit:"N\xB7m"},{id:"Mz",symbol:"Mz",name:"Aligning moment",group:"moments",unit:"N\xB7m"},{id:"t",symbol:"t",name:"Pneumatic trail",group:"aligning",unit:"m",quantity:"length"},{id:"Mzr",symbol:"Mzr",name:"Residual aligning moment",group:"aligning",unit:"N\xB7m"},{id:"s",symbol:"s",name:"Lever arm of Fx",group:"aligning",unit:"m",quantity:"length"},{id:"muX",symbol:"\u03BCx",name:"Longitudinal friction Fx/Fz",group:"friction",unit:"-"},{id:"muY",symbol:"\u03BCy",name:"Lateral friction Fy/Fz",group:"friction",unit:"-"},{id:"use",symbol:"use",name:"Friction ellipse used",group:"friction",unit:"-"},{id:"FyRel",symbol:"Fy/Fy,peak",name:"Lateral force over its peak at this load",group:"friction",unit:"-"},{id:"FxRel",symbol:"Fx/Fx,peak",name:"Driving force over its peak at this load",group:"friction",unit:"-"},{id:"dFyda",symbol:"\u2202Fy/\u2202\u03B1",name:"Cornering stiffness at the point",group:"stiffness",unit:"N/rad"},{id:"dFxdk",symbol:"\u2202Fx/\u2202\u03BA",name:"Slip stiffness at the point",group:"stiffness",unit:"N"},{id:"dFydg",symbol:"\u2202Fy/\u2202\u03B3",name:"Camber stiffness at the point",group:"stiffness",unit:"N/rad"},{id:"kz",symbol:"kz",name:"Vertical stiffness",group:"stiffness",unit:"N/mm",quantity:"springRate"},{id:"FxPeak",symbol:"Fx,peak",name:"Peak driving force",group:"characteristics",unit:"N",quantity:"force",characteristic:!0},{id:"FyPeak",symbol:"Fy,peak",name:"Peak lateral force",group:"characteristics",unit:"N",quantity:"force",characteristic:!0},{id:"muXPeak",symbol:"\u03BCx,peak",name:"Peak longitudinal friction",group:"characteristics",unit:"-",characteristic:!0},{id:"muYPeak",symbol:"\u03BCy,peak",name:"Peak lateral friction",group:"characteristics",unit:"-",characteristic:!0},{id:"kappaPeak",symbol:"\u03BA at peak",name:"Slip ratio at peak driving force",group:"characteristics",unit:"-",characteristic:!0},{id:"alphaPeak",symbol:"\u03B1 at peak",name:"Slip angle at peak lateral force",group:"characteristics",unit:"rad",characteristic:!0},{id:"Calpha",symbol:"C\u03B1",name:"Cornering stiffness at zero slip",group:"characteristics",unit:"N/rad",characteristic:!0},{id:"bestCamber",symbol:"\u03B3 best",name:"Camber for the most side force",group:"characteristics",unit:"rad",characteristic:!0},{id:"R0",symbol:"R0",name:"Free radius",group:"geometry",unit:"m",quantity:"length",characteristic:!0},{id:"Rl",symbol:"Rl",name:"Loaded radius",group:"geometry",unit:"m",quantity:"length",characteristic:!0},{id:"Re",symbol:"Re",name:"Effective rolling radius",group:"geometry",unit:"m",quantity:"length",characteristic:!0},{id:"width",symbol:"w",name:"Section width",group:"geometry",unit:"m",quantity:"length",characteristic:!0},{id:"sigmaA",symbol:"\u03C3\u03B1",name:"Lateral relaxation length",group:"transient",unit:"m",quantity:"length",characteristic:!0},{id:"Fr",symbol:"Fr",name:"Rolling-resistance force My/Re",group:"power",unit:"N",quantity:"force"},{id:"cr",symbol:"cr",name:"Rolling-resistance coefficient Fr/Fz",group:"power",unit:"-"},{id:"Pslip",symbol:"P slip",name:"Slip power |Fx\xB7Vsx| + |Fy\xB7Vsy|",group:"power",unit:"W"},{id:"Proll",symbol:"P roll",name:"Rolling power My\xB7\u03A9",group:"power",unit:"W"}],Uz=new Map(zl.map(e=>[e.id,e]));var Xz=.01*GL;var We=Math.PI/180;var Uv=new Set(zl.filter(e=>e.group!=="inputs"&&(e.unit==="N"||e.unit==="N\xB7m"||e.unit==="N/rad")).map(e=>e.id)),Xv={alpha:{from:-15*We,to:15*We,n:61},kappa:{from:-.25,to:.25,n:61},gamma:{from:-6*We,to:6*We,n:49},Fz:{from:200,to:3e3,n:40,follow:!0},p:{from:5e4,to:15e4,n:21},V:{from:0,to:40,n:41,follow:!0}},Xf={alpha:{from:0,to:12*We,n:7},kappa:{from:-.2,to:.2,n:9},gamma:{from:-4*We,to:4*We,n:5},Fz:{from:400,to:1600,n:5},p:{from:6e4,to:12e4,n:4},V:{from:5,to:35,n:4}};var qf={alpha:{from:0,to:12*We,n:25},kappa:{from:-.2,to:.2,n:25},gamma:{from:-4*We,to:4*We,n:17},Fz:{from:300,to:1800,n:16},p:{from:6e4,to:12e4,n:13},V:{from:5,to:35,n:13}};var ke=(e,t,r,n={},o={})=>({id:e,form:"curves",sweep:[{input:t,...Xv[t],...o}],x:t,y:r,...n}),Yl=(e,[t,r],n,o,a={})=>({id:e,form:"carpet",sweep:[{input:t,...Xf[t]},{input:r,...Xf[r]}],x:n,y:[o],...a}),Cr=(e,t)=>({id:e,fixed:t}),Bt={input:"Fz",values:"car"},Uf={alpha:0,kappa:0},yt={kappa:0},Wv={alpha:0},HL={input:"Fz",values:[500,1e3,1500]},zL=[{id:"overview",name:"Overview",cards:[Cr("tyre","tyre"),ke("fy","alpha",["Fy"],{title:"Lateral force",hold:yt}),ke("mz","alpha",["Mz"],{title:"Aligning moment",hold:yt}),ke("fx","kappa",["Fx"],{title:"Longitudinal force",hold:Wv}),Yl("combined-carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Cr("ellipse","ellipse")]},{id:"lateral",name:"Lateral",cards:[ke("fy-load","alpha",["Fy"],{title:"Lateral force per wheel load",series:Bt,hold:yt}),ke("muy-load","alpha",["muY"],{title:"Lateral force per unit load",series:Bt,hold:yt}),ke("fy-peak","alpha",["Fy"],{title:"Lateral force over its peak",series:Bt,hold:yt,scale:{per:"peak"}},{from:0,to:15*We,n:61}),ke("muy-peak","Fz",["muYPeak"],{title:"Peak lateral \u03BC over load"}),ke("calpha","Fz",["Calpha"],{title:"Cornering stiffness over load"}),ke("alpha-peak","Fz",["alphaPeak"],{title:"Slip angle at the peak over load"})]},{id:"aligning",name:"Aligning",cards:[ke("mz-load","alpha",["Mz"],{title:"Aligning moment per wheel load",series:Bt,hold:yt}),ke("trail","alpha",["t"],{title:"Pneumatic trail",series:Bt,hold:yt},{from:0,to:12*We,n:49}),ke("mzr","alpha",["Mzr"],{title:"Residual aligning moment",series:Bt,hold:yt},{from:0,to:12*We,n:49}),Yl("gough",["alpha","Fz"],"Fy","Mz",{title:"Gough plot",hold:yt}),ke("steering-feel","alpha",["t"],{title:"Steering feel",x:"FyRel",series:Bt,hold:yt},{from:0,to:12*We,n:49})]},{id:"longitudinal",name:"Longitudinal",cards:[ke("fx-load","kappa",["Fx"],{title:"Longitudinal force per wheel load",series:Bt,hold:Wv}),ke("mux-peak","Fz",["muXPeak"],{title:"Peak longitudinal \u03BC over load"}),ke("kx","Fz",["dFxdk"],{title:"Slip stiffness at zero slip over load",hold:Uf}),ke("kappa-peak","Fz",["kappaPeak"],{title:"Slip ratio at the peak over load"})]},{id:"combined",name:"Combined",cards:[Yl("carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Yl("envelope-load",["kappa","alpha"],"Fy","Fx",{title:"Friction envelope per load",scale:{per:"Fz"},facet:HL}),ke("fy-kappa","kappa",["Fy"],{title:"Side force while driving or braking",series:{input:"alpha",values:[2*We,4*We,8*We]}}),ke("fx-kappa","kappa",["Fx"],{title:"Driving force while cornering",series:{input:"alpha",values:[0,4*We,8*We]}}),Cr("ellipse","ellipse")]},{id:"camber",name:"Camber",cards:[ke("fy-gamma","alpha",["Fy"],{title:"Lateral force per inclination",series:{input:"gamma",values:[-4,-2,0,2,4].map(e=>e*We)},hold:yt}),ke("camber-sweep","gamma",["FyPeak","Fy"],{title:"Peak, and camber thrust at zero slip",hold:{alpha:0}}),{id:"camber-map",title:"Camber map",form:"map",sweep:[{input:"gamma",...qf.gamma},{input:"Fz",...qf.Fz,follow:!0}],x:"gamma",y:["Fz"],z:"muYPeak"},ke("camber-stiffness","alpha",["dFydg"],{title:"Camber stiffness at the point",series:Bt,hold:yt}),ke("mx","alpha",["Mx"],{title:"Overturning moment",series:Bt,hold:yt})]},{id:"rolling",name:"Rolling and radius",cards:[ke("my","V",["My"],{title:"Rolling-resistance moment",series:Bt,hold:Uf}),ke("radius","Fz",["R0","Rl","Re"],{title:"Radius over load"},{from:0}),ke("p-roll","V",["Proll"],{title:"Rolling power",series:Bt,hold:Uf})]},{id:"transient",name:"Transient",cards:[ke("sigma","Fz",["sigmaA"],{title:"Relaxation length over load"})]},{id:"tyres",name:"Side by side",cards:[{id:"trade-off",title:"Grip against cornering stiffness",form:"points",sweep:[],x:"Calpha",y:["muYPeak"]},{id:"pressure-family",title:"Peak \u03BCy over pressure, by family",form:"points",sweep:[],x:"p",y:["muYPeak"],family:!0},ke("delta-fy","alpha",["Fy"],{title:"Lateral force, minus the reference",hold:yt,scale:{delta:!0}}),ke("delta-mu","Fz",["muYPeak"],{title:"Peak lateral \u03BC over load, minus the reference",scale:{delta:!0}}),ke("delta-calpha","Fz",["Calpha"],{title:"Cornering stiffness over load, minus the reference",scale:{delta:!0}})]},{id:"car",name:"Car",cards:[Cr("operating","operating"),Cr("wheels","wheels")]},{id:"fit",name:"Fit check",cards:[Cr("fitLateral","fitLateral"),Cr("fitLongitudinal","fitLongitudinal"),Cr("fitCoupling","fitCoupling"),Cr("fitEnvelope","fitEnvelope")]}];var QL=5670374e-14,Qf=273.15,Zv=.95,Jv=60,Wl=10,ZL=.55,At=25,Zf=-20,Jf=50,Ys={tempC:[20,100,200,550,650,750],factor:[.8,.92,1,1,.85,.65]},Ws={discMassKg:.5,discOuterMm:220,specificHeatJPerKgK:460,emissivity:.6,coolingWPerM2K:200,padCurve:{tempC:[...Ys.tempC],factor:[...Ys.factor]}},jl={...Ws,discMassKg:.4,discOuterMm:200,padCurve:{tempC:[...Ys.tempC],factor:[...Ys.factor]}};function eh(e,t){let r=t==="front"?Ws:jl,n=Math.round(2*e.effRadiusMm+40);return{...r,discOuterMm:n,discMassKg:Math.round(100*r.discMassKg*(n/r.discOuterMm)**2)/100,padCurve:{tempC:[...r.padCurve.tempC],factor:[...r.padCurve.factor]}}}var JL=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},zs=(e,t,r,n)=>Math.min(r,Math.max(t,JL(e,n)));function eD(e,t){let r=e,n=Array.isArray(r?.tempC)?r.tempC:[],o=Array.isArray(r?.factor)?r.factor:[],a=[];for(let i=0;i<Math.min(n.length,o.length);i++){let c=Number(n[i]),l=Number(o[i]);Number.isFinite(c)&&Number.isFinite(l)&&a.push([Math.min(1500,Math.max(-50,c)),Math.min(2,Math.max(.05,l))])}a.sort((i,c)=>i[0]-c[0]);let s=a.filter((i,c)=>c===0||i[0]>a[c-1][0]);return s.length?{tempC:s.map(i=>i[0]),factor:s.map(i=>i[1])}:{tempC:[...t.tempC],factor:[...t.factor]}}function th(e,t){return{discMassKg:zs(e?.discMassKg,.05,20,t.discMassKg),discOuterMm:zs(e?.discOuterMm,50,600,t.discOuterMm),specificHeatJPerKgK:zs(e?.specificHeatJPerKgK,100,3e3,t.specificHeatJPerKgK),emissivity:zs(e?.emissivity,.02,1,t.emissivity),coolingWPerM2K:zs(e?.coolingWPerM2K,Wl,5e3,t.coolingWPerM2K),padCurve:eD(e?.padCurve,t.padCurve)}}function Ul(e,t){let r=e.tempC,n=e.factor,o=Math.min(r.length,n.length);if(o===0)return 1;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=1;for(;a<o-1&&r[a]<t;)a++;return n[a-1]+(t-r[a-1])/(r[a]-r[a-1])*(n[a]-n[a-1])}function rh(e,t=1){let r=e.discMassKg*e.specificHeatJPerKgK,n=e.discOuterMm*.001/2,o=2*Math.PI*n*n,a=Jv/3.6,s=e.emissivity*QL*o,i=m=>Wl+(e.coolingWPerM2K-Wl)*Math.pow(Math.max(0,m)*t/a,ZL),c=(m,f,p)=>{let d=m+Qf,h=p+Qf;return i(f)*o*(m-p)+s*(d**4-h**4)},l=(m,f)=>i(f)*o+4*s*Math.max(0,m+Qf)**3,u=(m,f)=>r/l(f,m);return{heatCapacityJPerK:r,areaM2:o,convectionAt:i,coolingW:c,timeConstantS:u,step(m,f,p,d,h){if(!(d>0))return m+f/r;let b=u(p,m+Math.max(0,f)/r),g=Math.max(1,Math.ceil(d/(.25*b))),y=d/g,R=f/g;for(let k=0;k<g;k++)m+=(R-c(m,p,h)*y)/r;return m},padFactor:m=>Ul(e.padCurve,m),window:e1(e.padCurve)}}function Xl(e,t,r,n,o,a,s=At){let i=n.length,c=new Array(i),l=new Array(i),u=new Array(i),m=Zv/Math.max(1,t),f=a,p=f,d=0,h=0,b=0;for(let g=0;g<i;g++){let y=Math.max(0,r[g]??0);c[g]=f,l[g]=y*n[g],u[g]=e.padFactor(f);let R=y*(o[g]??0);d+=R,f<e.window.fromC?h+=R:f>e.window.toC&&(b+=R);let k=g+1<i?n[g+1]:n[g],v=.5*(n[g]+k),x=v>0?(o[g]??0)/v:0;f=e.step(f,m*R,v,x,s),f>p&&(p=f)}return{tempC:c,heatW:l,padFactor:u,startC:a,endC:f,maxC:p,workJ:d,coldWorkJ:h,hotWorkJ:b}}function e1(e){let t=e.tempC,r=Math.min(t.length,e.factor.length);if(r===0)return{fromC:-1/0,toC:1/0};let n=Math.max(...e.factor.slice(0,r)),o=null;for(let c=0;c<r;c++){if(e.factor[c]<n-1e-9)continue;let l=c;for(;l+1<r&&e.factor[l+1]>=n-1e-9;)l++;l>c&&(!o||t[l]-t[c]>o.toC-o.fromC)&&(o={fromC:t[c],toC:t[l]}),c=l}if(o)return o;let a=NaN,s=NaN,i=NaN;for(let c=Math.floor(t[0]);c<=Math.ceil(t[r-1])+1;c++){let l=c<=Math.ceil(t[r-1])&&Ul(e,c)>=.98*n;l&&Number.isNaN(i)&&(i=c),!l&&!Number.isNaN(i)&&((Number.isNaN(a)||c-1-i>s-a)&&(a=i,s=c-1),i=NaN)}return{fromC:a,toC:s}}var nh=1e5,o1=.001,Kn={pedalRatio:4,pedalForceMaxN:0,barFront:.5,masterFrontMm:15.875,masterRearMm:15.875,valve:"none",valveKneeBar:20,valveSlope:.3,front:{location:"outboard",discs:2,pistonsPerSide:2,pistonDiaMm:25.4,padMu:.45,effRadiusMm:90,ratio:1},rear:{location:"outboard",discs:2,pistonsPerSide:1,pistonDiaMm:25.4,padMu:.45,effRadiusMm:80,ratio:1},adjusterPitchMm:1,barLengthMm:0},ah={fullAtBar:10,maxPowerKw:0,fadeBelowKmh:0,distribution:"equal"};var sh=s1(Ql(Kn,"Formula Student brakes")),ih=40,a1={ideal:!1,barFront:Kn.barFront,pedalForceMaxN:0,testSpeedKmh:ih,regen:ah};function t1(e){let{heat:t,...r}=e;return t?{...r,heat:{...t,padCurve:{tempC:[...t.padCurve.tempC],factor:[...t.padCurve.factor]}}}:r}function s1(e){let t=(r,n)=>r.heat?r:{...r,heat:eh(r,n)};return{...e,front:t(e.front,"front"),rear:t(e.rear,"rear")}}function Ql(e,t){return{name:t,pedalRatio:e.pedalRatio,masterFrontMm:e.masterFrontMm,masterRearMm:e.masterRearMm,valve:e.valve,valveKneeBar:e.valveKneeBar,valveSlope:e.valveSlope,front:t1(e.front),rear:t1(e.rear),adjusterPitchMm:e.adjusterPitchMm,barLengthMm:e.barLengthMm}}function ch(e,t){return i1({...e,barFront:t.barFront,pedalForceMaxN:t.pedalForceMaxN})}function lh(e,t){let r=Pr(t),n=e?sr(e):void 0;return{mode:r.ideal?"tyre":n?"hydraulic":"balance",hydraulic:n?ch(n,r):Kn,regen:r.regen}}var tD=["none","proportioning","limiter"],ql=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},Je=(e,t,r,n)=>Math.min(r,Math.max(t,ql(e,n))),rD=(e,t)=>{let r=ql(e,t);return r>0?r:t};function r1(e,t,r){let n=e?.location==="inboard"?"inboard":e?.location==="outboard"?"outboard":t.location;return{location:n,discs:Math.max(1,Math.min(4,Math.round(ql(e?.discs,n==="inboard"?1:t.discs)))),pistonsPerSide:Math.max(1,Math.min(6,Math.round(ql(e?.pistonsPerSide,t.pistonsPerSide)))),pistonDiaMm:Je(e?.pistonDiaMm,5,80,t.pistonDiaMm),padMu:Je(e?.padMu,.05,1.5,t.padMu),effRadiusMm:Je(e?.effRadiusMm,20,300,t.effRadiusMm),ratio:n==="inboard"?Je(e?.ratio,1,20,t.ratio):1,...e?.heat&&typeof e.heat=="object"?{heat:th(e.heat,t.heat??r)}:{}}}function i1(e){let t=Kn;return{pedalRatio:Je(e?.pedalRatio,.5,15,t.pedalRatio),pedalForceMaxN:Je(e?.pedalForceMaxN,0,5e3,t.pedalForceMaxN),barFront:Je(e?.barFront,.05,.95,t.barFront),masterFrontMm:Je(e?.masterFrontMm,8,40,t.masterFrontMm),masterRearMm:Je(e?.masterRearMm,8,40,t.masterRearMm),valve:tD.includes(e?.valve)?e?.valve:t.valve,valveKneeBar:Je(e?.valveKneeBar,0,200,t.valveKneeBar),valveSlope:Je(e?.valveSlope,0,1,t.valveSlope),front:r1(e?.front,t.front,Ws),rear:r1(e?.rear,t.rear,jl),adjusterPitchMm:rD(e?.adjusterPitchMm,t.adjusterPitchMm),barLengthMm:Je(e?.barLengthMm,0,500,t.barLengthMm)}}function nD(e){let t=ah;return{fullAtBar:Je(e?.fullAtBar,0,200,t.fullAtBar),maxPowerKw:Je(e?.maxPowerKw,0,1e3,t.maxPowerKw),fadeBelowKmh:Je(e?.fadeBelowKmh,0,100,t.fadeBelowKmh),distribution:e?.distribution==="wheel"?"wheel":"equal"}}function sr(e){let t=i1(e??void 0),r=typeof e?.name=="string"&&e.name.trim()?e.name:oD;return Ql(t,r)}function Pr(e){return{ideal:e?.ideal===!0,barFront:Je(e?.barFront,.05,.95,Kn.barFront),pedalForceMaxN:Je(e?.pedalForceMaxN,0,5e3,0),testSpeedKmh:Je(e?.testSpeedKmh,5,150,ih),regen:nD(e?.regen)}}var oD="Formula Student brakes";var oh=e=>Math.PI/4*(e*o1)**2;function un(e,t){let r=e.pistonsPerSide*oh(e.pistonDiaMm)*nh;return e.discs*2*e.padMu*r*e.effRadiusMm*o1*e.ratio/Math.max(.05,t)}function c1(e,t){if(e.valve==="none"||t<=e.valveKneeBar)return t;let r=e.valve==="limiter"?0:e.valveSlope;return e.valveKneeBar+r*(t-e.valveKneeBar)}function js(e,t){let r=Math.max(0,t)*e.pedalRatio,n=e.barFront*r/oh(e.masterFrontMm)/nh,o=(1-e.barFront)*r/oh(e.masterRearMm)/nh;return{front:n,rearIn:o,rear:c1(e,o)}}function aD(e,t){let r=js(e,1);return{front:un(e.front,t)*r.front,rear:un(e.rear,t)*r.rearIn}}function Us(e,t){let r=aD(e,t);return r.front/Math.max(1e-12,r.front+r.rear)}function Xs(e,t){let r=[],n=[],o=[],a=e.vVehicle.length,s=Math.max(1,Math.floor(a/60));for(let c=0;c<a;c+=s)i(c);return(a-1)%s!==0&&i(a-1),{v:r,front:n,rear:o};function i(c){let l=e.vVehicle[c],u=l1(t,l),m=t.maxPowerKw>0&&l>0?t.maxPowerKw*1e3/l:1/0,f=Math.max(0,e.fFront[c]),p=Math.max(0,e.fRear[c]),d=f+p>0?Math.min(1,m/(f+p)):1;r.push(l),n.push(f*d*u),o.push(p*d*u)}}function l1(e,t){let r=e.fadeBelowKmh/3.6;return r>0?Math.max(0,Math.min(1,t/r)):1}function Tr(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]||1);return t[o]+s*(t[a]-t[o])}var n1=new WeakMap;function Hn(e){let t=n1.get(e);return t||(t=e.mode==="hydraulic"&&e.hydraulic?iD(e,e.hydraulic):sD(e),n1.set(e,t)),t}function sD(e){let t=Math.min(.99,Math.max(.01,e.balanceFront));return{mode:e.mode,equalLeftRight:e.mode!=="tyre",uMax:1/0,shares:{front:t,rear:1-t},demand:r=>({front:t*r,rear:(1-t)*r,regenFront:0,regenRear:0,pFront:0,pRear:0,pedalN:0}),controlFor:r=>Math.max(0,r)}}function iD(e,t){let r=un(t.front,e.tyreRadiusM),n=un(t.rear,e.tyreRadiusM),o=e.regen,a=(c,l)=>{let u=js(t,c),m=0,f=0;if(o&&u.front>0){let p=o.fullAtBar>0?Math.min(1,u.front/o.fullAtBar):1;m=p*Tr(o.v,o.front,l),f=p*Tr(o.v,o.rear,l)}return{front:r*u.front+m,rear:n*u.rear+f,regenFront:m,regenRear:f,pFront:u.front,pRear:u.rear,pedalN:c}},s=t.pedalForceMaxN>0?t.pedalForceMaxN:1/0,i=(c,l)=>{let u=a(c,l);return u.front+u.rear};return{mode:"hydraulic",equalLeftRight:!0,uMax:s,demand:a,controlFor:(c,l)=>{if(!(c>0))return 0;let u=100;for(;i(u,l)<c&&u<1e6;)u*=2;if(u=Math.min(u,s),i(u,l)<=c)return u;let m=0;for(let f=0;f<60;f++){let p=.5*(m+u);i(p,l)<c?m=p:u=p}return u}}}function uh(e,t,r){let n=t>0?e.controlFor(t,r):0,o=e.demand(n>0?n:1,r),a=o.front+o.rear;return a>0?o.front/a:.5}var Zl=Fs,cD=.1,zn=(e,t)=>e.a*Math.sqrt(Math.max(0,1-(t/Math.max(1e-9,e.b))**2));function Jl(e,t,r){if(!(r>t))return t;let n=(Math.sqrt(5)-1)/2,o=t,a=r,s=a-n*(a-o),i=o+n*(a-o),c=e(s),l=e(i);for(let f=0;f<48;f++)c<l?(o=s,s=i,c=l,i=o+n*(a-o),l=e(i)):(a=i,i=s,l=c,s=a-n*(a-o),c=e(s));let u=.5*(o+a),m=e(u);for(let f of[t,r]){let p=e(f);p>m&&(u=f,m=p)}return u}function dh(e,t,r){let n=Math.max(0,r-Zl*t.b),o=Math.min(r,Zl*e.b);if(!(n<=o))return;let a=(c,l)=>c.a*c.a*Math.max(0,1-(l/Math.max(1e-9,c.b))**2),s=c=>a(e,c)-a(t,r-c),i;if(s(n)<=0)i=n;else if(s(o)>=0)i=o;else{let c=n,l=o;for(let u=0;u<40;u++){let m=.5*(c+l);s(m)>0?c=m:l=m}i=.5*(c+l)}return{lo:n,hi:o,y1:i,c1:e.cap(i),c2:t.cap(r-i)}}function fh(e,t,r,n,o=0){let a=Math.max(0,r),s=dh(e,t,a),i=s?s.c1:0,c=s?s.c2:0,l=s?Math.min(i,c):0,[u,m]=e.a<=t.a?[e,t]:[t,e],f=u.Fz/Math.max(1e-9,u.Fz+m.Fz),p=Math.max(0,Math.min(1,1-f/cD)),d=p>0&&a<Zl*m.b?m.cap(a):0,h=d>l?l+p*(d-l):0,b=Math.max(0,Math.min(u.slide,u.a)),g={xNoLock:l,xLock:h,slide:b,ceiling:Math.max(0,n)},y=Math.max(0,o);if(!(y>0)||!s)return{...g,regenWheel:s?y:0,mixedMax:2*l,regenRoom:T=>2*Math.max(0,l-T)};let{lo:R,hi:k}=s,v=Jl(T=>{let S=zn(e,T),A=zn(t,a-T);return Math.min(S+A,2*Math.min(S,A)+y)},R,k),x=e.cap(v),M=t.cap(a-v),F=Math.max(2*l,Math.min(x+M,2*Math.min(x,M)+y)),w=(T,S,A)=>Math.min(y,Math.max(0,T-A))+Math.min(y,Math.max(0,S-A));return{...g,regenWheel:y,mixedMax:F,regenRoom:T=>{let S=w(i,c,T);if(!(a>0))return S;let A=E=>Zl*E.b*Math.sqrt(Math.max(0,1-(T/Math.max(1e-9,E.a))**2)),P=Math.max(R,a-A(t)),L=Math.min(k,A(e));if(!(P<=L))return S;let D=Jl(E=>Math.min(y,zn(e,E)-T)+Math.min(y,zn(t,a-E)-T),P,L);return Math.max(S,w(e.cap(D),t.cap(a-D),T))}}}var mh=e=>Math.max(e.xNoLock,e.xLock),ph=e=>Math.max(e.mixedMax,2*e.xLock);function ca(e,t,r=0){let n=1e-9*Math.max(1,t),o=Math.max(0,r);if(t<=e.xNoLock+n)return Math.min(2*t+(o>0?Math.min(o,e.regenRoom(t)):0),e.ceiling);if(t<=e.xLock+n){let a=o>0?Math.min(e.regenWheel>0?Math.min(o,e.regenWheel):o/2,Math.max(0,e.xLock-t)):0;return Math.min(t+e.slide+a,e.ceiling)}return NaN}function la(e,t){let r=t/2,n=1e-9*Math.max(1,r);return r<=e.mixedMax/2+n?Math.min(t,e.ceiling):r<=e.xLock+n?Math.min(r+e.slide,e.ceiling):NaN}function qs(e,t,r,n){return e.shares?lD(e,e.shares,t,r,n):uD(e,t,r,n)}function u1(e,t){let r=e[0],n=t(r.u);for(let o of e.slice(1)){let a=t(o.u);a>n&&(r=o,n=a)}return{cand:r,force:n}}function lD(e,t,r,n,o){let a=ph(r),s=ph(n),i=Math.min(t.front>0?a/t.front:1/0,t.rear>0?s/t.rear:1/0,e.uMax),c=Number.isFinite(e.uMax)&&i>=e.uMax,l=b=>{let g=la(r,t.front*b),y=la(n,t.rear*b);return Number.isFinite(g)&&Number.isFinite(y)?g+y:-1/0},u=a>0?t.front*i/a:1/0,m=s>0?t.rear*i/s:1/0,f=[{u:i,by:c?"pedal":u>=m?"front":"rear"}];if(r.xLock>r.xNoLock){let b=t.front>0?r.mixedMax/t.front:1/0;b<i&&f.push({u:b,by:"front"})}if(n.xLock>n.xNoLock){let b=t.rear>0?n.mixedMax/t.rear:1/0;b<i&&f.push({u:b,by:"rear"})}let{cand:p,force:d}=u1(f,l),h=e.demand(p.u,o);return{force:Math.max(0,Number.isFinite(d)?d:0),control:p.u,demand:h,limitedBy:p.by,lockFront:h.front/2>r.mixedMax/2*(1+1e-9),lockRear:h.rear/2>n.mixedMax/2*(1+1e-9)}}function uD(e,t,r,n){let o=mh(t),a=mh(r),s=v=>(v.front-v.regenFront)/2,i=v=>(v.rear-v.regenRear)/2,c=v=>{let x=e.demand(v,n);return s(x)<=o*(1+1e-12)&&i(x)<=a*(1+1e-12)},l=(v,x)=>{if(v(e.demand(x,n)))return x;let M=0,F=x;for(let w=0;w<60;w++){let C=.5*(M+F);v(e.demand(C,n))?M=C:F=C}return M},u=Number.isFinite(e.uMax)?e.uMax:100;if(!Number.isFinite(e.uMax))for(;c(u)&&u<1e7;)u*=2;let m=c(u)?u:l(v=>s(v)<=o&&i(v)<=a,u),f=Number.isFinite(e.uMax)&&m>=e.uMax,p=v=>{let x=e.demand(v,n),M=ca(t,s(x),x.regenFront),F=ca(r,i(x),x.regenRear);return Number.isFinite(M)&&Number.isFinite(F)?M+F:-1/0},d=e.demand(m,n),h=o>0?s(d)/o:1/0,b=a>0?i(d)/a:1/0,g=[{u:m,by:f?"pedal":h>=b?"front":"rear"}];if(t.xLock>t.xNoLock){let v=l(x=>s(x)<=t.xNoLock,m);v<m&&g.push({u:v,by:"front"})}if(r.xLock>r.xNoLock){let v=l(x=>i(x)<=r.xNoLock,m);v<m&&g.push({u:v,by:"rear"})}let{cand:y,force:R}=u1(g,p),k=e.demand(y.u,n);return{force:Math.max(0,Number.isFinite(R)?R:0),control:y.u,demand:k,limitedBy:y.by,lockFront:s(k)>t.xNoLock*(1+1e-9),lockRear:i(k)>r.xNoLock*(1+1e-9)}}var Lr={regen:!0,regenEfficiency:.6};function Dr(e,t){let r=e.energy??t??Lr;return{regen:r.regen===!0,regenEfficiency:Math.min(1,Math.max(0,Number.isFinite(r.regenEfficiency)?r.regenEfficiency:0))}}function Er(e,t,r){let n=Math.max(0,Math.floor(r));if(n===0)return[];if(n===1)return[e];let o=new Array(n),a=(t-e)/(n-1);for(let s=0;s<n;s++)o[s]=e+a*s;return o[n-1]=t,o}function m1(e,t,r){let n=[],o=Math.floor((r-e)/t+1e-9);for(let a=0;a<=o;a++)n.push(e+t*a);return n}function mt(e,t,r){let n=e.length;if(r<e[0]||r>e[n-1])return NaN;if(r===e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function eu(e,t,r){let n=e.length;if(!(r>=e[0]&&r<=e[n-1]))return NaN;if(n<3)return n===1?t[0]:t[0]+(r-e[0])/(e[1]-e[0])*(t[1]-t[0]);let o=0,a=n-1;for(;a-o>1;){let d=o+a>>1;e[d]<=r?o=d:a=d}if(o===n-1)return t[n-1];let s=d=>e[d+1]-e[d],i=d=>(t[d+1]-t[d])/s(d),c=d=>{if(d===0||d===n-1){let[y,R]=d===0?[0,1]:[n-2,n-3],k=i(y)*(1+s(y)/(s(y)+s(R)))-i(R)*(s(y)/(s(y)+s(R)));return k*i(y)<=0?0:Math.abs(k)>2*Math.abs(i(y))?2*i(y):k}let h=i(d-1),b=i(d),g=(h*s(d)+b*s(d-1))/(s(d-1)+s(d));return(Math.sign(h)+Math.sign(b))*Math.min(Math.abs(h),Math.abs(b),.5*Math.abs(g))},l=s(o),u=i(o),m=c(o),f=c(o+1),p=r-e[o];return t[o]+p*(m+p*((3*u-2*m-f)/l+p*(m+f-2*u)/(l*l)))}function Qs(e,t,r){return r.map(n=>mt(e,t,n))}var Zs=e=>e.reduce((t,r)=>r>t?r:t,-1/0),ua=e=>e.reduce((t,r)=>r<t?r:t,1/0);var mD=[-.906179845938664,-.538469310105683,0,.538469310105683,.906179845938664],pD=[.236926885056189,.478628670499366,.568888888888889,.478628670499366,.236926885056189];function hh(e,t,r){let n=.5*(r-t),o=.5*(t+r),a=0;for(let s=0;s<5;s++)a+=pD[s]*e(n*mD[s]+o);return n*a}var dD=Math.PI*2,fD=.5/3.6;function Js(e,t){let r=Math.max(0,Math.round(e));if(t==="front")return{front:r,rear:0};if(t==="rear")return{front:0,rear:r};let n=Math.floor(r/2);return{front:n,rear:r-n}}function bh(e,t,r,n,o){let a=e.rpm,s=e.torque,i=a.length,c=new Array(i),l=new Array(i);for(let g=0;g<i;g++){let y=a[g]/60*dD;c[g]=y*o/n,l[g]=s[g]*n/o}let u=Zs(c),m=Er(ua(c),u,u/fD),f=Qs(c,l,m),{front:p,rear:d}=Js(t,r),h=f.map(g=>g*p),b=f.map(g=>g*d);return{vVehicle:m,fFront:h,fRear:b,vMax:u}}var p1=60/(2*Math.PI),d1=.1,f1=.08,h1=0;function gh(e){let t=(r,n)=>r===void 0||!Number.isFinite(r)?n:Math.max(0,r);return{up:t(e.upshiftTime,d1),down:t(e.downshiftTime,f1)}}function yh(e){let t=e.driveKept;return t===void 0||!Number.isFinite(t)?h1:Math.max(0,Math.min(1,t))}function xh(e,t,r){let{primary:n,ratios:o,efficiency:a}=e.gearbox,s=t>0&&r>0&&n>0,i=(b,g)=>b/p1*r/g,c=s?o.filter(b=>b>0).map(b=>{let g=n*b*t;return{ratio:g,vIdle:i(e.idleRpm,g),vLimit:i(e.limitRpm,g)}}):[],l=Math.max(0,Math.min(1,a)),u=Math.max(0,e.inertia),m=b=>b>e.limitRpm?0:Math.max(0,$e(e.rpm,e.torque,b)),f=(b,g)=>{let y=c[g];return y?b*y.ratio/r*p1:0},p=(b,g)=>g===0&&c.length>0&&b<c[0].vIdle,d=(b,g)=>{let y=c[g];return y?p(b,g)?m(e.idleRpm)*y.ratio*l/r:b<y.vIdle||b>y.vLimit?0:m(f(b,g))*y.ratio*l/r:0},h=(b,g)=>{let y=c[g];return!y||p(b,g)?0:u*y.ratio*y.ratio/(r*r)};return{engine:e,gears:c,efficiency:l,rDyn:r,vMax:c.length?c[c.length-1].vLimit:0,rpm:f,torque:m,force:d,inertiaMass:h,slipping:p}}function ma(e,t,r,n=0,o=1){let a=-1,s=-1/0;for(let i=0;i<e.gears.length;i++){let c=(o*e.force(t,i)+n)/(r+e.inertiaMass(t,i));c>=s&&(s=c,a=i)}return{gear:a,accel:s}}function Rh(e,t){let r=0;for(let n=0;n<e.gears.length;n++)r=Math.max(r,e.force(t,n));return r}var b1=9.81,g1=Math.PI*2;function Ft(e){let t=e.motor.rpm,r=e.motor.torque,n=t.length,o=new Array(n),a=new Array(n),s=new Array(n),i=new Array(n),c=new Array(n),l=e.gear_ratio.value,u=e.r_dyn.value;for(let v=0;v<n;v++)o[v]=r[v]*t[v]*(g1/60),a[v]=t[v]/60*g1,s[v]=a[v]*u/l,i[v]=r[v]*l,c[v]=i[v]/u;let m=Zs(s),f=m,p=.5/3.6,d=Er(ua(s),m,m/p),h=Qs(s,c,d),b=Er(ua(t),Zs(t),250),g=Qs(t,o,b).map(v=>v*e.power_scale.value),y,R=f,k;if(e.motorModel?.kind==="ice"){k=xh(e.motorModel,l,u);let v=Er(0,k.vMax,Math.max(2,Math.ceil(k.vMax/p)+1)),x=v.map(w=>Rh(k,w)),M=v.map(()=>0),F=e.motorPlacement==="front";y={vVehicle:v,fFront:F?x:M,fRear:F?M:x,vMax:k.vMax},R=k.vMax}else e.motorModel&&(y=bh(e.motorModel,Math.max(1,Math.round(e.motorCount??e.driven_wheels.value)),e.motorPlacement??"rear",l,u),R=y.vMax);return{params:e,g:b1,FG:e.m.value*b1,vMax:R,vVehicle:d,fRad:h,uMotor:b,pMotor:g,vRad:s,fAxle:y,...k?{engine:k}:{}}}var mn=e=>e.motorModel?.kind==="ice"?Js(1,e.motorPlacement==="front"?"front":"rear"):Js(Math.max(1,Math.round(e.motorCount??e.driven_wheels?.value??2)),e.motorPlacement??"rear");function y1(e){let t=mn(e);return t.front>=2||t.rear>=2}function x1(e){return y1(e)?e.motorMount??"hub":"chassis"}function vh(e){if(!e.motorModel)return{front:!1,rear:!0};let t=mn(e);return{front:t.front>0,rear:t.rear>0}}function kh(e){let t=mn(e),r=t.front>0,n=t.rear>0,o=e.front_mass_diss?.value??.5,a=Math.max(0,Math.min(1,o>1?o/100:o)),s=x1(e)==="chassis",i=c=>c===1||c>1&&s;return{front:r&&n?a:r?1:0,inboard:{front:i(t.front),rear:i(t.rear)}}}function pt(e){return lh(e.brakeModel,e.brakeSetup)}function tu(e){return Pr(e.brakeSetup).ideal?"tyre":e.brakeModel||e.brakeModelId?"hydraulic":"balance"}function R1(e,t){if(!(ft(e.motorModel)||!Dr(e).regen))return Xs(ru(Ft(e)),t??pt(e).regen)}function ru(e){return e.fAxle??{vVehicle:e.vVehicle,fFront:e.vVehicle.map(()=>0),fRear:e.fRad.map(t=>t*e.params.driven_wheels.value)}}function Mh(e,t=pt(e)){if(t.mode==="hydraulic")return Us(t.hydraulic,e.r_dyn.value);if(t.mode==="tyre"){let r=e.front_mass_diss.value>1?e.front_mass_diss.value/100:e.front_mass_diss.value;return Math.min(.95,Math.max(.05,r+Q(e,"cg_height")/Math.max(1,Q(e,"wheelbase"))))}return Q(e,"brake_balance")}function Sh(e,t=pt(e)){return{front:t.hydraulic.front.location==="inboard",rear:t.hydraulic.rear.location==="inboard"}}function Ah(e){let t=pt(e);return{brakeBalanceFront:Mh(e,t),brakeInboard:Sh(e,t)}}function v1(e,t=pt(e)){if(t.mode==="tyre"||t.regen.distribution!=="wheel"||ft(e.motorModel))return;let r=mn(e),n={front:r.front>=2,rear:r.rear>=2};return n.front||n.rear?n:void 0}function ei(e){let t=pt(e),r=e.r_dyn.value,n=Sh(e,t),o=Mh(e,t),a=v1(e,t),s=t.mode==="hydraulic"||a?R1(e,t.regen):void 0;return{mode:t.mode,balanceFront:o,...t.mode==="hydraulic"?{hydraulic:t.hydraulic}:{},tyreRadiusM:r,inboard:n,...s?{regen:{...s,fullAtBar:t.regen.fullAtBar}}:{},...s&&a?{regenPerWheel:a}:{}}}var bD=9.81;function Fh(e,t){if(ft(e.motorModel))return()=>0;let r=pt(e),n=Xs(t,r.regen);if(r.mode==="hydraulic"){let a=Hn({mode:"hydraulic",balanceFront:Us(r.hydraulic,e.r_dyn.value),hydraulic:r.hydraulic,tyreRadiusM:e.r_dyn.value,regen:{...n,fullAtBar:r.regen.fullAtBar}});return(s,i)=>{if(!(s>0))return 0;let c=a.demand(a.controlFor(s,i),i);return Math.min(s,c.regenFront+c.regenRear)}}let o=r.mode==="tyre"?gD(e):()=>Math.min(.99,Math.max(.01,Q(e,"brake_balance")));return(a,s,i)=>{if(!(a>0))return 0;let c=o(s,i);return Math.min(c*a,Tr(n.v,n.front,s))+Math.min((1-c)*a,Tr(n.v,n.rear,s))}}function gD(e){let t=e.m.value*bD,r=e.front_mass_diss.value>1?e.front_mass_diss.value/100:e.front_mass_diss.value,n=Q(e,"cg_height")/Math.max(1,Q(e,"wheelbase")),o=1-Math.max(0,Math.min(1,Q(e,"cop_long"))),a=.5*e.rho.value*e.c_l.value*e.A.value;return(s,i)=>{let c=Math.max(0,a*s*s),l=t*(r+Math.abs(i)*n)+c*o;return Math.min(.99,Math.max(.01,l/(t+c)))}}function k1(e){let t=e==="front"?"Front axle":"Rear axle";return{[`${e}.location`]:{section:t,label:"Disc location",control:"Mounting"},[`${e}.discs`]:{section:t,label:"Discs",control:"Mounting"},[`${e}.ratio`]:{section:t,label:"Reduction to the wheel",unit:": 1"},[`${e}.pistonsPerSide`]:{section:t,label:"Pistons a side"},[`${e}.pistonDiaMm`]:{section:t,label:"Piston bore",unit:"mm"},[`${e}.padMu`]:{section:t,label:"Pad friction \u03BC"},[`${e}.effRadiusMm`]:{section:t,label:"Effective radius",unit:"mm"},[`${e}.heat.discMassKg`]:{section:t,label:"Disc mass",unit:"kg"},[`${e}.heat.discOuterMm`]:{section:t,label:"Disc diameter",unit:"mm"},[`${e}.heat.specificHeatJPerKgK`]:{section:t,label:"Specific heat",unit:"J/(kg\xB7K)"},[`${e}.heat.emissivity`]:{section:t,label:"Emissivity"},[`${e}.heat.coolingWPerM2K`]:{section:t,label:"Cooling at 60 km/h",unit:"W/(m\xB2\xB7K)"},[`${e}.heat.padCurve.tempC`]:{section:t,label:"Pad curve temperature",unit:"\xB0C"},[`${e}.heat.padCurve.factor`]:{section:t,label:"Pad curve friction"}}}var wh={pedalRatio:{section:"Pedal box & bar",label:"Pedal ratio",unit:": 1"},barLengthMm:{section:"Pedal box & bar",label:"Bar length, clevis to clevis",unit:"mm"},adjusterPitchMm:{section:"Pedal box & bar",label:"Adjuster pitch",unit:"mm/turn"},masterFrontMm:{section:"Master cylinders",label:"Front bore",unit:"mm"},masterRearMm:{section:"Master cylinders",label:"Rear bore",unit:"mm"},valve:{section:"Rear valve",label:"Valve"},valveKneeBar:{section:"Rear valve",label:"Knee",unit:"bar"},valveSlope:{section:"Rear valve",label:"Gain above the knee"},...k1("front"),...k1("rear")},Ch={ideal:{label:"Ideal brakes"},barFront:{label:"Balance bar"},pedalForceMaxN:{label:"Pedal force",unit:"N"},testSpeedKmh:{section:"Brake test",label:"Speed",unit:"km/h"},"regen.maxPowerKw":{section:"Regen",label:"Power ceiling",unit:"kW"},"regen.fadeBelowKmh":{section:"Regen",label:"Fades out below",unit:"km/h"},"regen.fullAtBar":{section:"Regen",label:"Full at",unit:"bar"},"regen.distribution":{section:"Regen",label:"Wheel by wheel"}};function Th(e){let t=wh[e];return`${t.label}, ${t.section}`.toLowerCase()}function Ph(e){let t=Ch[e];return t.section?`${t.section} ${t.label.charAt(0).toLowerCase()}${t.label.slice(1)}`:t.label}var M1=new WeakMap;function ir(e){if(e.brakes)return e.brakes;let t=M1.get(e);if(!t){let r=Math.max(.05,(e.unsprungCgHeight||230)/1e3);t=e.brakeBalanceFront!=null?{mode:"balance",balanceFront:e.brakeBalanceFront,tyreRadiusM:r}:{mode:"tyre",balanceFront:e.frontMassFrac,tyreRadiusM:r},M1.set(e,t)}return t}var Ir=e=>Hn(ir(e));var vD=Math.PI/180,pa=Object.freeze({tbr:1,preloadN:0}),nu=Object.freeze({tbr:1/0,preloadN:0}),Dh=e=>e.faces*e.muClutch*e.rFrictionMm/e.rRampMm;function Eh(e,t){if(!(e>0)||Number.isNaN(t))return 0;let r=Math.tan(Math.min(90,t)*vD);return r>0?Math.min(1,e/r):1}function A1(e){if(e>=1)return 1/0;let t=e>0?e:0;return(1+t)/(1-t)}function ou(e){return e===1/0?1:e>1?(e-1)/(e+1):0}function da(e,t){return e.tbr===1/0?1/0:(e.preloadN>0?e.preloadN:0)+ou(e.tbr)*Math.abs(t)}function ri(e,t,r){let n=o=>o!==void 0&&o>0&&r>0?o/r:0;switch(e.kind){case"open":return pa;case"spool":return nu;case"independent":return t==="hubs"?pa:nu;case"clutch":{let o=n(e.preloadNm);return t==="hubs"?{tbr:1,preloadN:o}:{tbr:A1(Eh(Dh(e),t==="drive"?e.rampDriveDeg:e.rampCoastDeg)),preloadN:o}}case"torsen":{let o=n(e.preloadNm);if(t==="hubs")return{tbr:1,preloadN:o};let a=t==="drive"?e.tbrDrive:e.tbrCoast;return{tbr:a>1?a:1,preloadN:o}}}}function ti(e,t,r){let n=Math.max(0,Math.min(e,t)),o=Math.max(0,Math.max(e,t)),a=r.tbr>1?r.tbr:1,s=r.preloadN>0?r.preloadN:0;return a===1/0||s===1/0?n+o:n+Math.min(o,a*n+s*(1+a)/2)}var S1=4;function Lh(e,t){let r=0;for(let a of e)r=Math.max(r,ti(a.m1,a.m2,t));let n=t.tbr>1?t.tbr:1,o=(t.preloadN>0?t.preloadN:0)*(1+n)/2;if(n===1/0||o===1/0)return r;for(let a=0;a+1<e.length;a++){let s=e[a],i=e[a+1].m1-s.m1,c=e[a+1].m2-s.m2,l=f=>{f>0&&f<1&&(r=Math.max(r,ti(s.m1+f*i,s.m2+f*c,t)))};i!==c&&l((s.m2-s.m1)/(i-c));let u=i+c-(1+n)*i,m=i+c-(1+n)*c;u!==0&&l(((1+n)*s.m1+o-s.m1-s.m2)/u),m!==0&&l(((1+n)*s.m2+o-s.m1-s.m2)/m)}return r}function ni(e,t,r,n,o){let a=Math.max(0,o),s=n.tbr>1?n.tbr:1,i=n.preloadN>0?n.preloadN:0;if(s===1/0||i===1/0)return a;let c=Math.max(0,r),l=dh(e,t,c),u=l?2*Math.min(l.c1,l.c2):0;if(!l||s===1&&i===0||!(a>u))return Math.min(u,a);let m=Jl(b=>zn(e,b)+zn(t,c-b),l.lo,l.hi),f=[{m1:l.c1,m2:l.c2}];for(let b=1;b<=S1&&m!==l.y1;b++){let g=l.y1+(m-l.y1)*b/S1;f.push({m1:e.cap(g),m2:t.cap(c-g)})}let p=Lh(f,pa),d=Lh(f,nu);if(!(d>p))return u;let h=(Lh(f,{tbr:s,preloadN:i})-p)/(d-p);return Math.min(a,u+(a-u)*Math.min(1,Math.max(0,h)))}function F1(e,t,r,n,o,a){return Ih(e,o,ni(t,r,n,o,a))}function Ih(e,t,r){let n=Math.max(e.xNoLock,r/2),o=t.tbr===1/0||!(e.xLock>n)?0:e.xLock;return e.regenWheel>0?{...e,xNoLock:n,xLock:o,mixedMax:Math.max(e.mixedMax,2*n)}:{...e,xNoLock:n,xLock:o,mixedMax:2*n,regenRoom:a=>2*Math.max(0,n-a)}}function _h(e,t,r,n=30){let o=t,a=e(o),s=a-o;if(!(Math.abs(s)>r))return{x:o,fx:a,evals:1};let i=a,c=e(i),l=c-i,u=2;for(;Math.abs(l)>r&&u<n;){let m=s<0!=l<0,f=l-s,p=f!==0?i-l*(i-o)/f:NaN;m?p>Math.min(o,i)&&p<Math.max(o,i)||(p=.5*(o+i)):Number.isFinite(p)?Math.abs(p-i)>10*Math.abs(l)&&(p=i+Math.sign(p-i)*10*Math.abs(l)):p=c;let d=e(p),h=d-p;if(u++,m&&h<0==l<0?s*=.5:(o=i,s=l),i=p,c=d,l=h,s<0!=l<0&&Math.abs(i-o)<=r)break}return{x:i,fx:c,evals:u}}function w1(e,t,r,n,o,a=60){let s=t,i=e(s),c=i-s,l=1;if(!(Math.abs(c)>n))return{x:s,fx:i,evals:l};let u=Math.sign(r-t),m=Math.abs(r-t),f=0;for(let p=o;l<a;p*=2){if(f=Math.min(f+p,m),f>m-n)return null;let d=t+u*f,h=e(d),b=h-d;if(l++,!(Math.abs(b)>n))return{x:d,fx:h,evals:l};if(c<0!=b<0)return T1(e,s,c,d,h,b,n,l,a);s=d,c=b}return null}function C1(e,t,r,n=60){let o=t,a=e(o),s=a-o;if(!(Math.abs(s)>r))return{x:o,fx:a,evals:1};let i=Math.sign(s),c=a;for(let l=2;;l++){let u=e(c),m=u-c;if(!(Math.abs(m)>r))return{x:c,fx:u,evals:l};if(s<0!=m<0)return T1(e,o,s,c,u,m,r,l,n);if(l>=n)return{x:c,fx:u,evals:l};let f=Math.abs(c-o),p=s!==m?m*(c-o)/(s-m):NaN,d=p*i>0?Math.min(Math.abs(p),10*Math.abs(m),2*f):2*f;o=c,s=m,c+=i*d}}function T1(e,t,r,n,o,a,s,i,c){let l=t,u=r,m=n,f=a,p=n,d=o,h=0;for(;i<c&&Math.abs(m-l)>s;){p=(l*f-m*u)/(f-u),d=e(p);let b=d-p;if(i++,!(Math.abs(b)>s))break;b<0==u<0?(l=p,u=b,h===-1&&(f*=.5),h=-1):(m=p,f=b,h===1&&(u*=.5),h=1)}return{x:p,fx:d,evals:i}}function au(e,t){return Math.abs(e.fx-e.x)>t?e.x:e.fx}var kD=(e,t)=>{let r=e.brakes?.hydraulic?.[t];return!!r&&r.location==="inboard"&&r.discs===1};function $t(e,t,r){let n=e.driveline?.[t];if(n)return r>=0?n.drive:kD(e,t)?n.coast:n.hubs}var P1=e=>e.tbr>1||e.preloadN>0;var MD=9.81,L1=["FL","FR","RL","RR"],Nh=e=>e==="FL"||e==="FR",su=e=>Nh(e)?"front":"rear",D1={front:["FL","FR"],rear:["RL","RR"]},si=()=>({peak:new Map,freeBrake:new Map}),ai=25;function oi(e,t){let r=Math.max(0,e)/ai,n=Math.floor(r),o=r-n,a=t(n);return o>0?a+o*(t(n+1)-a):a}var pn=1e-4,SD=.05;function _r(e,t,r,n=si(),o=!1){let a=r,s=e.massTotal,i=n.peak,c=(S,A)=>{let P=`${S}:${A}`,L=i.get(P);return L||(L=xl(ge(t,S),Math.max(1,A*ai)),i.set(P,L)),L},l=(S,A)=>({aPeak:oi(A,P=>c(S,P).aPeak),fyPeak:oi(A,P=>c(S,P).fyPeak)}),u=n.freeBrake,m=(S,A)=>{let P=`${S}:${A}`,L=u.get(P);if(L===void 0){let D=Math.max(1,A*ai);L=St(ge(t,S),D,0,!0,c(S,A)),u.set(P,L)}return L},f=(S,A)=>A>0?oi(A,P=>m(S,P)):0,p=Ir(e),d=ir(e),h=S=>d.regen&&d.regenPerWheel?.[S]?Tr(d.regen.v,d.regen[S],a)/2:0,b=h("front"),g=h("rear"),y=(S,A,P)=>{let L=Math.max(0,A[S]),D=l(su(S),L);return St(ge(t,su(S)),L,P[S]*D.fyPeak,!0,D)},R=(S,A,P,L,D=!0)=>{let E=te=>{let fe=Math.max(0,A[te]),W=ge(t,S),J=l(S,fe);return{Fz:fe,a:Math.abs(f(S,fe)),b:J.fyPeak,slide:fe>0?Math.abs(W.forces({Fz:fe,kappa:-1,alpha:0}).Fx):0,cap:re=>Math.abs(St(W,fe,re,!0,J))}},V=te=>Math.abs(P[te])*l(su(te),Math.max(0,A[te])).fyPeak,[N,z]=D1[S],I=E(N),_=E(z),B=V(N)+V(z),O=fh(I,_,B,L,S==="front"?b:g),G=D?O:{...O,xLock:0},K=$t(e,S,-1),Y=K&&P1(K)?K:void 0;if(!Y)return{axle:S,eq:G,cap:G};let j=Number.isFinite(L)?L:I.cap(V(N))+_.cap(V(z)),Z=F1(G,I,_,B,Y,j);return{axle:S,eq:G,cap:Z,law:Y,strong:()=>I.cap(V(N))>=_.cap(V(z))?N:z}},k=(S,A,P,L)=>R(S,A,P,L).cap,v=(S,A,P)=>{let L=S.demand,D=p.shares?la(A,L.front):ca(A,(L.front-L.regenFront)/2,L.regenFront),E=p.shares?la(P,L.rear):ca(P,(L.rear-L.regenRear)/2,L.regenRear);return{front:Number.isFinite(D)?D:0,rear:Number.isFinite(E)?E:0}},x=S=>({muX:A=>A>0?Math.abs(f(S,A))/A:0,muY:A=>A>0?l(S,A).fyPeak/A:0}),M={front:x("front"),rear:x("rear")},F={lf:e.wheelbase/1e3*(1-e.frontMassFrac),lr:e.wheelbase/1e3*e.frontMassFrac},w={front:e.trackFront/2e3,rear:e.trackRear/2e3},C=(S,A,P,L,D)=>{let E=L.cap,V=D.cap,N=qs(p,E,V,a),z={arms:F,halfTrack:w,ayDir:Math.sign(S)};for(let I=0;I<2;I++){let _=v(N,E,V),B={};for(let G of L1){let K=Math.max(0,A[G]);B[G]={Fz:K,Fy:Math.abs(P[G])*l(su(G),K).fyPeak,Fx:-(Nh(G)?_.front:_.rear)/2}}let O=G=>{if(!G.law||!G.strong)return G.cap;let K={axle:G.axle,strong:G.strong(),full:2*G.cap.xNoLock,open:2*G.eq.xNoLock,sense:-1};return Ih(G.eq,G.law,$l(K,B,M,z))};E=O(L),V=O(D),N=qs(p,E,V,a)}return{limit:N,front:E,rear:V}};return{peakAt:l,axle:k,ceiling:(S,A,P)=>{let[L,D]=D1[S];return Math.abs(y(L,A,P)+y(D,A,P))},limitAt:(S,A,P,L=0)=>{let D={FL:0,FR:0,RL:0,RR:0},E=Ce(e,S,0,a,0,A),V,N=fe=>(V?.ax!==fe&&(V={ax:fe,loads:Ce(e,S,(fe+L)/MD,a,0,A)}),V.loads),z=Rl(fe=>ea(P,N(fe),E,l).short,-L,-1),I=P,_={front:0,rear:0},B,O,G=(fe,W=!0)=>{let J=z.at(fe);D=N(J),I=ea(P,D,E,l).util;let re=0,pe=0,de=0;for(let ie of L1){let oe=y(ie,D,I);re+=oe,Nh(ie)?pe+=oe:de+=oe}if(_={front:Math.abs(pe),rear:Math.abs(de)},p.mode!=="tyre"){let ie=R("front",D,I,Math.abs(pe),W),oe=R("rear",D,I,Math.abs(de),W);if(o&&(ie.law||oe.law)){let ue=C(S,D,I,ie,oe);B=ue.limit,O={front:ue.front,rear:ue.rear}}else B=qs(p,ie.cap,oe.cap,a),O={front:ie.cap,rear:oe.cap};re=-B.force}return re/s},K=_h(G,0,pn),Y=au(K,pn),j=Y;if(B?.lockFront||B?.lockRear){let fe=_h(J=>G(J,!1),0,pn);j=au(fe,pn);let W=w1(G,fe.x,K.x,pn,SD);W||G(K.x),Y=au(W??K,pn)}let Z=z.edge(),ne=Z!==void 0&&Y<Z;ne&&(Y=Math.min(0,Z),G(Y),j=Math.max(j,Y));let te={loads:D,ceiling:_,limit:B,axles:O};return{ax:Y,axUnlocked:j,...ne?{edge:Z}:{},...te,split:()=>te.limit&&te.axles?v(te.limit,te.axles.front,te.axles.rear):{...te.ceiling}}}}}var cu=9.81;function AD(e,t,r){let n=Ce(e,0,t,r),o=Math.max(0,n.FL)+Math.max(0,n.FR),a=Math.max(0,n.RL)+Math.max(0,n.RR);return o+a>0?o/(o+a):e.frontMassFrac}var _1=(e,t)=>t.mode==="hydraulic"&&!!ir(e).regen;function fa(e,t,r=0,n,o=0){if(!e.brakes&&e.brakeBalanceFront==null)return e.frontMassFrac;let a=Ir(e);if(a.shares&&a.mode!=="tyre")return a.shares.front;let s=n&&_1(e,a)?N1(e,n):void 0,i=s?.shares??E1.get(e);i||E1.set(e,i=new Map);let c=Math.round(Math.abs(t)/.005),l=Math.round(Math.max(0,r)/.25),u=s?Math.round(o/.01):0,m=O1(c,l,u),f=i.get(m);if(f===void 0){let p=-c*.005,d=l*.25,h=e.massTotal*Math.abs(p)*cu;if(s){let b=B1(a,V1(e,s,c,l,u),h,d);f=b.front+b.rear>0?b.front/(b.front+b.rear):.5}else f=a.mode==="tyre"?AD(e,p,d):uh(a,h,d);i.size>5e4&&i.clear(),i.set(m,f)}return f}var E1=new WeakMap;function lu(e,t,r,n,o=0){let a=Ir(e);if(!_1(e,a))return;let s=Math.round(Math.max(0,r)/(e.massTotal*cu)/.005),i=Math.round(Math.max(0,n)/.25);return B1(a,V1(e,N1(e,t),s,i,Math.round(o/.01)),Math.max(0,r),n)}var I1=new WeakMap;function N1(e,t){let r=I1.get(e);r||I1.set(e,r=new WeakMap);let n=r.get(t);return n||r.set(t,n={ev:t,tyres:si(),shares:new Map,rooms:new Map,speeds:new Map}),n}var O1=(e,t,r)=>(r*1001+e)*100003+t;function V1(e,t,r,n,o){let a=O1(r,n,o),s=t.rooms.get(a);if(!s){let i=n*.25,c=o*.01,l=t.speeds.get(n);l||(l={cap:_r(e,t.ev,i,t.tyres),dragG:-Math.max(0,ss(e,i).drag)/(e.massTotal*cu)},t.speeds.set(n,l));let{cap:u}=l,m=Ce(e,c,-r*.005+l.dragG,i),f=Math.abs(c)*e.massTotal*cu,p=b=>{let[g,y]=b==="front"?["FL","FR"]:["RL","RR"],R=f*(b==="front"?e.frontMassFrac:1-e.frontMassFrac),k=u.peakAt(b,Math.max(0,m[g])).fyPeak+u.peakAt(b,Math.max(0,m[y])).fyPeak,v=R>0&&k>0?Math.min(1,R/k):0;return u.axle(b,m,{FL:v,FR:v,RL:v,RR:v},1/0)},d,h;s=(b,g)=>(b==="front"?d??=p("front"):h??=p("rear")).regenRoom(g),t.rooms.size>5e4&&t.rooms.clear(),t.rooms.set(a,s)}return s}function iu(e,t,r,n){let o=e.demand(r,n),a=o.front-o.regenFront,s=o.rear-o.regenRear,i=o.regenFront>0?Math.min(o.regenFront,t("front",a/2)):0,c=o.regenRear>0?Math.min(o.regenRear,t("rear",s/2)):0;return{front:i===o.regenFront?o.front:a+i,rear:c===o.regenRear?o.rear:s+c,regenFront:i,regenRear:c,demand:o}}function B1(e,t,r,n){if(!(r>0))return iu(e,t,1,n);let o=c=>c.front+c.rear,a=e.controlFor(r,n),s=iu(e,t,a,n);if(o(s)>=r||!(a<e.uMax))return s;let i=a;for(;o(s)<r&&i<e.uMax&&i<1e7;)a=i,i=Math.min(e.uMax,2*i),s=iu(e,t,i,n);if(o(s)<r)return s;for(let c=0;c<60&&i-a>1e-10*i;c++){let l=.5*(a+i),u=iu(e,t,l,n);o(u)<r?a=l:(i=l,s=u)}return s}var ha={rel:.003,abs:2,kappa:1e-5,iters:12},Oh={rel:1e-6,abs:.001,kappa:1e-12,iters:40};function Yn(e,t,r,n=ha){let o=t>=0?1:-1,a=Math.abs(t),s=Math.max(n.abs,n.rel*a),i=e(0);if(Math.abs(i.Fx)-a>=0)return{kappa:0,forces:i};let c=0,l=i,u=Math.abs(i.Fx)-a,m=Math.min(.3,Math.max(.004,Math.abs(r)||.02)),f=e(o*m),p=Math.abs(f.Fx)-a,d=null;for(;p<0&&m<.3;){let g=Math.min(.3,m*1.9),y=e(o*g),R=Math.abs(y.Fx);if(R<Math.abs(f.Fx)){d={kappa:g,forces:y};break}c=m,l=f,u=p,m=g,f=y,p=R-a}if(p<0){let g=CD(e,o,c,l,m,f,d),y=Math.abs(g.forces.Fx);if(y<a)return{kappa:o*g.kappa,forces:g.forces};m=g.kappa,f=g.forces,p=y-a}let h=f,b=o*m;for(let g=0;g<n.iters&&m-c>n.kappa;g++){let y=p-u,R=Math.abs(y)>1e-12?(c*p-m*u)/y:.5*(c+m);R>c&&R<m||(R=.5*(c+m));let k=e(o*R),v=Math.abs(k.Fx)-a;if(h=k,b=o*R,Math.abs(v)<s)break;v<0?(c=R,u=v,p*=.5):(m=R,p=v,u*=.5)}return{kappa:b,forces:h}}var $1=1e-6,FD=40,wD=(3-Math.sqrt(5))/2;function CD(e,t,r,n,o,a,s){let i=a,c,l,u,m=-Math.abs(a.Fx),f,p,d=-Math.abs(n.Fx);if(s){c=s.kappa;let g=-Math.abs(s.forces.Fx);[l,f,u,p]=g<=d?[c,g,r,d]:[r,d,c,g]}else{c=.3;let g=.3*(1-$1),y=e(t*g),R=-Math.abs(y.Fx);if(R>=m)return{kappa:o,forces:a};[l,f,u,p]=[o,m,r,d],o=g,m=R,i=y}d<m&&([l,f]=[o,m],o=r,m=d,i=n);let h=c-r,b=0;for(let g=0;g<FD;g++){let y=$1*Math.abs(o)+1e-10,R=.5*(r+c);if(Math.abs(o-R)<=2*y-.5*(c-r))break;let k=!0;if(Math.abs(h)>y){let F=(o-l)*(m-p),w=(o-u)*(m-f),C=(o-u)*w-(o-l)*F;w=2*(w-F),w>0&&(C=-C),w=Math.abs(w);let T=h;if(h=b,Math.abs(C)<Math.abs(.5*w*T)&&C>w*(r-o)&&C<w*(c-o)){b=C/w;let S=o+b;(S-r<2*y||c-S<2*y)&&(b=R>=o?y:-y),k=!1}}k&&(h=o>=R?r-o:c-o,b=wD*h);let v=Math.abs(b)>=y?o+b:o+(b>=0?y:-y),x=e(t*v),M=-Math.abs(x.Fx);M<=m?(v>=o?r=o:c=o,u=l,p=f,l=o,f=m,o=v,m=M,i=x):(v<o?r=v:c=v,M<=f||l===o?(u=l,p=f,l=v,f=M):(M<=p||u===o||u===l)&&(u=v,p=M))}return{kappa:o,forces:i}}var uu=e=>Math.max(2,.003*Math.abs(e)),TD=(e,t)=>Math.max(t.abs,t.rel*Math.abs(e)),Vh=.5,PD=.03;function LD(e,t,r,n,o){let a=.5*(e.vx+t.vx),s=v=>{let x=(1+v)*a/e.vx-1,M=(1+v)*a/t.vx-1,F=e.at(x),w=t.at(M);return{kappaM:v,kl:x,kr:M,fl:F,fr:w,g:F.Fx+w.Fx-r}},i=TD(r,o),c=Math.max(-Vh,Math.min(Vh,n)),l=s(c);if(Math.abs(c)>PD){let v=s(.8*c);(l.g-v.g)/(c-v.kappaM)>0||(l=s(0))}if(Math.abs(l.g)<i)return l;let u=l.g<0?1:-1,m=l,f=l,p=.004,d=l;for(let v=0;v<12;v++){let x=m.kappaM+u*p;if(Math.abs(x)>Vh)break;let M=s(x);if(Math.abs(M.g)<i)return M;if(Math.abs(M.g)<Math.abs(d.g)&&(d=M),Math.sign(M.g)!==Math.sign(m.g)){f=M;break}if(u*(M.g-m.g)<=0)return d;m=M,p*=1.9}if(f===l)return d;let h=m,b=f,g=h.g,y=b.g,R=Math.abs(g)<Math.abs(y)?h:b,k=Math.min(1e-7,o.kappa);for(let v=0;v<30&&Math.abs(b.kappaM-h.kappaM)>k;v++){let x=y-g,M=Math.abs(x)>1e-12?(h.kappaM*y-b.kappaM*g)/x:.5*(h.kappaM+b.kappaM),F=Math.min(h.kappaM,b.kappaM),w=Math.max(h.kappaM,b.kappaM);M>F&&M<w||(M=.5*(F+w));let C=s(M);if(R=C,Math.abs(C.g)<i)break;Math.sign(C.g)===Math.sign(g)?(h=C,g=C.g,y*=.5):(b=C,y=C.g,g*=.5)}return R}function G1(e,t,r,n){let o=(e*(1+t*n)+t*r)/(1-t*n);return e+o>=0?o:(e*(1-t*n)+t*r)/(1+t*n)}function Bh(e,t,r,n,o,a=ha){let s=LD(e,t,r,o,a),i=s.fr.Fx-s.fl.Fx,c=da(n,r);if(Math.abs(i)<=c){let R=r-(s.fl.Fx+s.fr.Fx),k=Math.max(0,Math.abs(R)-uu(r))/2;return{left:{kappa:s.kl,forces:s.fl,want:s.fl.Fx+R/2,short:k},right:{kappa:s.kr,forces:s.fr,want:s.fr.Fx+R/2,short:k},locked:!0,spoolKappa:s.kappaM}}let l=Math.sign(i),u=r/2-l*c/2,m=r/2+l*c/2,f=Yn(e.at,u,e.seed||s.kl,a),p=Yn(t.at,m,t.seed||s.kr,a),d=Math.abs(u-f.forces.Fx)>uu(u),h=Math.abs(m-p.forces.Fx)>uu(m),b=Math.max(0,n.preloadN),g=ou(n.tbr);d&&!h?p=Yn(t.at,G1(f.forces.Fx,l,b,g),p.kappa,a):h&&!d&&(f=Yn(e.at,G1(p.forces.Fx,-l,b,g),f.kappa,a));let y=(R,k)=>({kappa:R.kappa,forces:R.forces,want:k,short:Math.max(0,Math.abs(k-R.forces.Fx)-uu(k))});return{left:y(f,u),right:y(p,m),locked:!1,spoolKappa:s.kappaM}}var DD={front:["FL","FR"],rear:["RL","RR"]},ED=Object.freeze({Fx:0,Fy:0,Mz:0});function mu(e,t,r,n){let o=r;for(let a of["front","rear"]){let[s,i]=DD[a],c=r[s]+r[i],l=$t(e,a,c);if(!l||!(da(l,c)>0))continue;let u=ge(t,a),m=n.alpha[a],f=(a==="front"?e.trackFront:e.trackRear)/2e3,p=(h,b)=>{let g=Math.max(0,n.Fz[h]);return{at:g>0?y=>u.forces({Fz:g,kappa:y,alpha:m,gamma:0}):()=>ED,vx:Math.max(.05,1-b*n.curvature),seed:0}},d=Bh(p(s,f),p(i,-f),c,l,n.seed?.[a]??0);n.seed&&(n.seed[a]=d.spoolKappa),o===r&&(o={...r}),o[s]=d.left.want,o[i]=d.right.want}return o}var Me=9.81,se=Math.PI/180,ID=8,_D=1e-6,fn=["FL","FR","RL","RR"],jt=e=>e==="FL"||e==="FR",dn=e=>jt(e)?"front":"rear";function ci(e,t){let r=ge(e,"front"),n=ge(e,"rear");return r===n?jn(r,t):{front:jn(r,t),rear:jn(n,t)}}function jn(e,t){return Lf(e,Math.min(t,Wt(e)))}var du=e=>e==="FL"||e==="RL";function ga(e,t,r=0,n,o=0){let a=t?.axG??0,s=Number.isFinite(t?.tvRearDiffN)?t?.tvRearDiffN:0;if(!(!!a&&Number.isFinite(a))&&!s)return null;let c=e.massTotal*a*Me,l=a>=0?Math.min(1,Math.max(0,t?.driveFrontFrac??0)):Math.min(.99,Math.max(.01,fa(e,a,r,n,o))),u=c*l/2,m=c*(1-l)/2;return{axG:a,fx:{FL:u,FR:u,RL:m-s/2,RR:m+s/2}}}function Wh(e,t,r,n){return Math.abs(Un(e,t,r,n!==void 0?{steerMaxDeg:n}:{}).peak.steerDeg)}function jh(e,t,r,n){let o=e.tv;if(!o?.enabled)return 0;let a=ck(o)(t,Math.abs(r),n);return r<0?-a:a}function Uh(e,t,r=0,n,o=0,a=0,s){let i=ga(e,{axG:t,driveFrontFrac:a},r,n,o),c=i?i.fx:{FL:0,FR:0,RL:0,RR:0};return i&&s&&n?mu(e,n,c,s):c}var li=e=>du(e)?-1:1,Xh=(e,t,r,n,o)=>t*e.Fy(t*r,n,t*o);function zh(e){let t=e.wheelbase/1e3,r=t*(1-e.frontMassFrac),n=t*e.frontMassFrac;return{wb:t,lf:r,lr:n,m:e.massTotal}}function ND(e,t,r){let n=Math.abs(t),o=e.steerFront;if(o&&o.meanDeg.length>1){let u=t>=0,m=r&&o.travelSurface?qo(o,n/se,u?r.FL:r.FR,u?r.FR:r.FL):Qo(o,n/se);return{innerMag:m.innerDeg*se,outerMag:m.outerDeg*se,innerCamber:m.innerCamber,outerCamber:m.outerCamber,atLock:m.atLock}}let a=e.trackFront/1e3,s=e.wheelbase/1e3,i=(e.ackermannPct??0)/100,c=n,l=n;if(n>1e-4){let u=s/Math.tan(n),m=Math.atan(s/Math.max(.05,u-a/2)),f=Math.atan(s/(u+a/2));c=n+i*(m-n),l=n+i*(f-n)}return{innerMag:c,outerMag:l,innerCamber:0,outerCamber:0,atLock:!1}}function Xn(e,t,r){let n=(e.toeFrontDeg??0)*se,o=(e.toeRearDeg??0)*se,a=ND(e,t,r),s=t>=0?1:-1,i=t>=0,c=s*(i?a.innerMag:a.outerMag),l=s*(i?a.outerMag:a.innerMag);return{steer:{FL:c-n,FR:l+n,RL:-o,RR:o},camber:{FL:i?a.innerCamber:a.outerCamber,FR:i?a.outerCamber:a.innerCamber,RL:0,RR:0},atLock:a.atLock}}function qh(e,t,r){if(r.Fz<=0)return 0;let n=ut(ge(e,dn(t))),o=li(t),a=Math.abs(r.kappa)<1e-12?n.Mz(o*r.slipRad,r.Fz,o*r.camberRad):n.forces({Fz:r.Fz,kappa:r.kappa,alpha:o*r.slipRad,gamma:o*r.camberRad}).Mz;return o*a}function K1(e,t,r,n){if(!$n(e))return null;let o=ut(ge(t,"front")),a={};for(let s of["FL","FR"]){let i=n[s];a[s]={Fz:i.Fz,Fx:i.Fx,Fy:i.Fy,Mz:qh(o,s,i)}}return Vs(e,r/se,a,sn(o.model),{FL:n.FL.travelMm,FR:n.FR.travelMm})}var H1=()=>({totalNm:[],aligningNm:[],lateralNm:[],longitudinalNm:[],jackingNm:[]});function z1(e,t){e.totalNm.push(t.totalNm),e.aligningNm.push(t.aligningNm),e.lateralNm.push(t.lateralNm),e.longitudinalNm.push(t.longitudinalNm),e.jackingNm.push(t.jackingNm)}var OD=Object.freeze({Fx:0,Fy:0,Mz:0});function Y1(e,t,r){let n=t==="front"?(r?.FL??0)+(r?.FR??0):(r?.RL??0)+(r?.RR??0),o=$t(e,t,n);return o&&da(o,n)>0?{F:n,law:o}:null}function wt(e,t,r,n,o,a,s,i,c){let l=s?.fx,u=s?.axG??0,{wb:m,lf:f,lr:p,m:d}=zh(e),h=Y1(e,"front",l),b=Y1(e,"rear",l),g={front:0,rear:0},y=i!==void 0&&i>0&&Number.isFinite(i)?i:null,R=W=>y===null?r:Math.sqrt(Math.max(0,W)*y),k=ut(ge(t,"front")),v=ut(ge(t,"rear")),x=e.trackFront/2e3,M=e.trackRear/2e3,F=!!(e.kinFront&&e.kinRear),w=F&&y===null?ln(e,e.kinFront,e.kinRear,r):null,C=NaN,T=null,S=W=>{if(!F)return null;if(y===null)return w;let J=R(W);return J!==C&&(C=J,T=ln(e,e.kinFront,e.kinRear,J)),T},A={},P={FL:0,FR:0,RL:0,RR:0},L=e.kinFront?.compliance,D=e.kinRear?.compliance,E=!!(L||D),V=!!(L?.toePerMz||D?.toePerMz),N=W=>jt(W)?L:D,z={FL:{fy:0,fx:0,mz:0},FR:{fy:0,fx:0,mz:0},RL:{fy:0,fx:0,mz:0},RR:{fy:0,fx:0,mz:0}},I=!1,_=W=>{let J=W/r,re=y===null?n+f*J/r:n+f/y,pe=y===null?n-p*J/r:n-p/y,de=S(W),ie=R(W),oe=de?de(W/Me,u,n/se,o/se):null,ue=oe?{FL:oe.FL.travel,FR:oe.FR.travel}:void 0,Be=gl(e,W/Me,u,ie,n/se,o/se,ue,oe?.steeringJacking),Ae=Be.loads;I=Be.overturned;let le=Xn(e,o,ue),Re=le.steer,Te=0,ze=be=>{let Fe=Math.max(0,Ae[be]),xe=li(be),me=jt(be)?k:v,Le=N(be),Se=0,Ye=0;if(Le){let Pn=z[be];Se=Le.toePerFy*Pn.fy+Le.toePerFx*Pn.fx+Le.toePerMz*Pn.mz,Ye=Le.camberPerFy*Pn.fy+Le.camberPerFx*Pn.fx}let Ue=Re[be]+(oe?xe*oe[be].bumpToe*se:0)+xe*Se*se,zt=Ue-(jt(be)?re:pe),Tn=(oe?oe[be].camberRoad:0)*se+xe*(le.camber[be]+Ye)*se;return{Fz:Fe,mir:xe,t:me,gains:Le,complianceToe:Se,steerK:Ue,slip:zt,camberRad:Tn}},je=(be,Fe)=>{let xe=y===null?J/r:1/y,me=jt(be)?f:-p,Le=(du(be)?1:-1)*(jt(be)?x:M),Se=(Math.cos(n)-Le*xe)*Math.cos(Fe.steerK)+(Math.sin(n)+me*xe)*Math.sin(Fe.steerK);return{at:Fe.Fz>0?Ye=>Fe.t.forces({Fz:Fe.Fz,kappa:Ye,alpha:Fe.mir*Fe.slip,gamma:Fe.mir*Fe.camberRad}):()=>OD,vx:Math.max(.05,Se),seed:P[be]}};for(let be=0;be<(E?ID:1);be++){Te=0;let Fe=0,xe={};for(let me of fn){let Le=jt(me)?h:b;if(Le&&!xe[me]){let[Eo,Et]=jt(me)?["FL","FR"]:["RL","RR"],Kc=ze(Eo),Uy=ze(Et),Xy=dn(me),Wp=Bh(je(Eo,Kc),je(Et,Uy),Le.F,Le.law,g[Xy],Oh);g[Xy]=Wp.spoolKappa,xe[Eo]={w:Kc,share:Wp.left},xe[Et]={w:Uy,share:Wp.right}}let Se=xe[me]?.w??ze(me),{Fz:Ye,mir:Ue,t:zt,gains:Tn,complianceToe:Pn,steerK:Kp,slip:Hp,camberRad:zp}=Se,rs=l?.[me]??0,Po,Lo=0,Yp=0,Gc=0,Do=xe[me]?.share;if(Do)P[me]=Do.kappa,Yp=Do.kappa,Lo=Do.forces.Fx,Gc=Do.short,Po=Ue*Do.forces.Fy;else if(rs===0||Ye<=0)Po=Xh(zt,Ue,Hp,Ye,zp),Gc=Ye<=0?Math.abs(rs):0;else{let Et=Yn(Kc=>zt.forces({Fz:Ye,kappa:Kc,alpha:Ue*Hp,gamma:Ue*zp}),rs,P[me],Oh);P[me]=Et.kappa,Yp=Et.kappa,Lo=Et.forces.Fx,Gc=Math.max(0,Math.abs(rs-Lo)-Math.max(ha.abs,ha.rel*Math.abs(rs))),Po=Ue*Et.forces.Fy}if(A[me]={Fz:Ye,travelMm:oe?.[me].travel??0,steerRad:Kp,slipRad:Hp,camberRad:zp,Fy:Po,Fx:Lo,kappa:Yp,fxShort:Gc,lifted:Be.lifted[me]},Tn){let Eo=V&&Tn.toePerMz?qh(zt,me,A[me]):0;z[me]={fy:-Ue*Po,fx:Lo,mz:-Ue*Eo*1e3};let Et=z[me];Fe=Math.max(Fe,Math.abs(Tn.toePerFy*Et.fy+Tn.toePerFx*Et.fx+Tn.toePerMz*Et.mz-Pn))}Te+=Po*Math.cos(Kp)+Lo*Math.sin(Kp)}if(Fe<_D)break}return Te/d},B=W=>{let J=Ce(e,0,u,W,0,o/se);return J.FL+J.FR+J.RL+J.RR},O=Math.max(20,3.5*B(r)/d);if(y!==null){O=4*Me;for(let W=0;W<8;W++){let J=Math.min(40*Me,3.5*B(R(O))/d);if(J<=O)break;O=J}O=Math.max(20,O)}let G=W=>_(W)-W,K=Math.max(.001,O*1e-4),Y=(W,J,re,pe)=>{let de=W,ie=re,oe=J,ue=pe,Be=de;for(let Ae=0;Ae<40;Ae++){let le=ue-oe,Re=Math.abs(le)>1e-12?(de*ue-ie*oe)/le:.5*(de+ie),Te=Math.min(de,ie),ze=Math.max(de,ie);Re>Te&&Re<ze||(Re=.5*(de+ie));let je=G(Re);if(Be=Re,Math.abs(je)<1e-4||ze-Te<1e-6)break;je<0==oe<0?(de=Re,oe=je,ue*=.5):(ie=Re,ue=je,oe*=.5)}return Be},j=(W,J,re,pe=!1)=>{let de=(Ae,le)=>re>0?Ae>0&&le<0:le>0&&Ae<0,ie=W,oe=J,ue=W+re*Math.min(Math.abs(J),O);if(!pe&&Math.abs(ue-W)>K){let Ae=G(ue);if(de(oe,Ae))return{root:Y(ie,oe,ue,Ae),last:ie};ie=ue,oe=Ae}let Be=pe?O/24:Math.max(O/24,Math.abs(ue-W)/4);for(let Ae=1;Ae<=24;Ae++){let le=ie+re*Be;if(Math.abs(le)>O)break;let Re=G(le);if(de(oe,Re))return{root:Y(ie,oe,le,Re),last:ie};if(pe&&Re*re<0&&(Re-oe)*re<0)break;ie=le,oe=Re}return{root:null,last:ie}},Z=c??null;if(c===void 0&&a!==void 0&&Number.isFinite(a)&&Math.abs(a)<=O){let W=G(a);if(Math.abs(W)<=1e-4)G(a+K)<0&&G(a-K)>0&&(Z=a);else{let J=j(a,W,Math.sign(W)).root;Z=J!==null&&(J===0||Math.sign(J)===Math.sign(a))?J:null}}let ne=Z===null;if(Z===null){let W=G(0),J=G(K),re=Math.abs(W)<=1e-4,pe=re?y!==null?1:o!==0?Math.sign(o):J>0?1:-1:Math.sign(W),de=re?pe*K:0,ie=re?pe>0?J:G(-K):W,oe=j(de,ie,pe);Z=oe.root??(re?0:oe.last)}let te=_(Z);if(ne&&o!==0&&y===null){let W=Math.sign(o);if(Z*W<=0||(A.RL.Fy+A.RR.Fy)*W<0){let J={...A},re=I,pe=W*Math.max(Z*W+K,n*W*r*r/p),de=null;if(pe*W<O){let ie=G(pe);if(ie*W>0)de=j(pe,ie,W).root;else{let oe=pe+W*O/24,ue=G(oe);(ue-ie)*W>0&&(de=j(oe,ue,W,ue*W<=0).root)}}de!==null&&de*W>0?(Z=de,te=_(Z)):(Object.assign(A,J),I=re)}}let fe=f*(A.FL.Fy*Math.cos(A.FL.steerRad)+A.FR.Fy*Math.cos(A.FR.steerRad))-p*(A.RL.Fy+A.RR.Fy);if(s||h||b){let W=J=>(du(J)?1:-1)*(jt(J)?x:M);for(let J of fn){let re=A[J],pe=jt(J)?f:-p;fe+=pe*re.Fx*Math.sin(re.steerRad)-W(J)*re.Fx*Math.cos(re.steerRad)}}return y!==null&&Z<-1e-6?{ay:NaN,cn:NaN,wheels:A,overturned:I,res:NaN}:{ay:Z/Me,cn:fe/(d*Me*m),wheels:A,overturned:I,res:te-Z}}function VD(e,t,r,n,o,a,s,i=0){let c=20*se,l=.001,u=(h,b)=>{let g=wt(e,t,r,h,n,b,s);return{cn:g.cn-i,ay:g.ay*Me}},m=h=>n===0||i!==0||Math.abs(h)<.05||Math.sign(h)===Math.sign(n),f=(h,b,g,y)=>{let R=u(h,y);if(Math.abs(R.cn)<1e-5)return{beta:h,trimmed:!0};let k=y===void 0?void 0:R.ay,v={pos:{b:h,cn:R.cn,ay:k},neg:{b:h,cn:R.cn,ay:k}},x=null,M=h,F=Math.abs(R.cn);for(let w=0;w<b.length&&!x;w++)for(let C of[v.pos,v.neg]){let T=C===v.pos?1:-1,S=h+T*b[w];if(Math.abs(S)>c)continue;let A=u(S,C.ay);if(Math.abs(A.cn)<F&&m(A.ay)&&(F=Math.abs(A.cn),M=S),A.cn===0&&m(A.ay))return{beta:S,trimmed:!0};if(A.cn<0!=C.cn<0){let P={lo:C.b,hi:S,ayLo:C.ay},L=W1(u,P),D=u(L,C.ay);if(Math.abs(D.cn)<l&&m(D.ay))return x=P,{beta:L,trimmed:!0}}C.b=S,C.cn=A.cn,y!==void 0&&(C.ay=A.ay)}return x?{beta:W1(u,x),trimmed:!0}:g?{beta:M,trimmed:!1}:null},p=[.25,.75,2,5].map(h=>h*se);if(o!==void 0&&Number.isFinite(o)&&Math.abs(o)<=c){let h=f(o,p,!1,a);if(h)return h;if(!s&&i===0&&a!==void 0&&Number.isFinite(a)){let b=BD(e,t,r,n,o,a,c);if(b&&m(b.ay))return{beta:b.beta,trimmed:!0,ay:b.ay}}}let d=[1,3,7,15,20].map(h=>h*se).filter(h=>h<=c);return f(0,d,!0)??{beta:0,trimmed:!1}}function W1(e,t){let{lo:r,hi:n}=t,o=t.ayLo,a=e(r,o).cn,s=e(n,o).cn,i=r;for(let c=0;c<40;c++){let l=s-a,u=Math.abs(l)>1e-12?(r*s-n*a)/l:.5*(r+n);u>Math.min(r,n)&&u<Math.max(r,n)||(u=.5*(r+n));let m=e(u,o),f=m.cn;if(o!==void 0&&(o=m.ay),i=u,Math.abs(f)<1e-5||Math.abs(n-r)<1e-5)break;f<0==a<0?(r=u,a=f,s*=.5):(n=u,s=f,a*=.5)}return i}function BD(e,t,r,n,o,a,s){let i=(f,p)=>{let d=wt(e,t,r,f,n,void 0,null,void 0,p);return{r:d.res,c:d.cn}},c=o,l=a,u=i(c,l),m=0;for(let f=0;f<$D;f++){let p=i(c+$h,l),d=i(c,l+Gh),h=(p.r-u.r)/$h,b=(d.r-u.r)/Gh,g=(p.c-u.c)/$h,y=(d.c-u.c)/Gh,R=h*y-b*g;if(!Number.isFinite(R)||R===0||Math.abs(R)<zD*(Math.abs(h*y)+Math.abs(b*g)))return null;if(f===0)m=Math.sign(R);else if(Math.sign(R)!==m)return null;if(Math.abs(u.r)<=1e-4&&Math.abs(u.c)<=1e-5)return{beta:c,ay:l};let k=(u.c*b-u.r*y)/R,v=(u.r*g-u.c*h)/R,x=Math.min(1,GD/Math.max(Math.abs(k),1e-300),KD/Math.max(Math.abs(v),1e-300));if(c+=x*k,l+=x*v,Math.abs(c-o)>HD||Math.abs(c)>s||l*a<0)return null;u=i(c,l)}return null}var $D=8,$h=1e-5,Gh=.001,GD=1*se,KD=2,HD=5*se,zD=.5;function J1(e,t,r,n,o,a,s,i){let c=wt(e,t,r,n,o,a,s,void 0,i),l=c.ay*Me/r,u={},m=0;for(let d of fn){let h=c.wheels[d],b=ge(t,dn(d)),g=Wt(b),y=b.muY(Math.min(h.Fz,g)),R=b.muX(Math.min(h.Fz,g));m+=h.fxShort,u[d]={Fz:h.Fz,steerDeg:h.steerRad/se,slipDeg:h.slipRad/se,camberDeg:h.camberRad/se,Fy:h.Fy,Fx:h.Fx,Mz:qh(b,d,h),gripUtil:y*h.Fz>0?Math.hypot(h.Fy/(y*h.Fz),R*h.Fz>0?h.Fx/(R*h.Fz):0):0,...h.Fz>g?{pastTurnover:!0}:{},lifted:h.lifted}}let f=Vs(e,o/se,u,sn(ge(t,"front").model),{FL:c.wheels.FL.travelMm,FR:c.wheels.FR.travelMm}),p=Xn(e,o,e.kinFront&&e.kinRear?{FL:c.wheels.FL.travelMm,FR:c.wheels.FR.travelMm}:void 0);return{wheels:u,ay:c.ay,ax:s?.axG??0,beta:n/se,yawRate:l*180/Math.PI,steerDeg:o/se,...p.atLock?{lockDeg:(p.steer.FL+p.steer.FR)/2/se}:{},converged:!0,trimmed:!c.overturned,overturned:c.overturned,driving:!1,fxShortfall:m,...f?{steering:f}:{}}}function Or(e,t,r,n,o,a,s=0){let i=Math.max(8,r),c=Wn(e,t,i,n,o,a,s);return n!==0&&o?.driving===void 0&&(c.driving=aE(e,t,i,c,a,s)),c}function Wn(e,t,r,n,o,a,s){let i=n*se,c=ga(e,a,r,t),l=o&&Number.isFinite(o.ay)?o.ay*Me:void 0,u=o&&Number.isFinite(o.beta)?o.beta*se:void 0,{beta:m,trimmed:f,ay:p}=VD(e,t,r,i,u,l,c,s),d=J1(e,t,r,m,i,l,c,p),h={...d,trimmed:f&&!d.overturned};return h.driving=n===0?h.trimmed:o?.driving!==void 0&&o.driving&&h.trimmed&&Math.abs(h.beta-o.beta)<=YD,h}var YD=3;function Un(e,t,r,n={}){let o=Math.max(8,r),a=n.direction??1,s=n.yawDemandCn??0,i=n.steerMaxDeg??WD,c=typeof n.op=="function"?n.op:()=>n.op,l=typeof n.op=="function"?null:`${o}|${a}|${s}|${i}|${n.op?`${n.op.axG}|${n.op.driveFrontFrac??""}|${n.op.tvRearDiffN??""}`:""}`;if(l!==null){let x=Kh.get(e)?.get(t)?.get(l);if(x)return x}let u=(x,M)=>M.trimmed&&Math.abs(M.beta-x.beta)<=fu&&Math.abs(M.ay-x.ay)*Me<=hu,m=!1,f=(x,M)=>{let F=Wn(e,t,o,a*x,M,c(a*x),s);return u(M,F)?(F.driving=!0,F):(m=F.overturned,null)},p=[Wn(e,t,o,0,void 0,c(0),s)],d=null,h=!1,b,g=x=>{let M=p.length-1;for(;M>1&&x.sb*(p[M].beta-p[M-1].beta)>=0;)M--;let F=a*(x.state.ay-p[M].ay)>0,w=C=>x.sb*(C.beta-x.state.beta)>0||a*C.steerDeg>=a*x.state.steerDeg||F&&a*C.ay>=a*x.state.ay;for(;p.length>Math.max(2,M)&&w(p[p.length-1]);)p.pop();b={state:x.state,stall:p[p.length-1]},p.push(x.state),d=Math.abs(x.state.steerDeg)},y=(x,M=!1)=>M||rE(p[p.length-1],x)?nE(e,t,o,a,p,x,c,s):null,R=p[0].trimmed?p[0]:null;if(!R){let x=0;for(let M=j1;M<=i&&!R;M+=j1){let F=Wn(e,t,o,a*M,void 0,c(a*M),s);if(F.trimmed){let w=M;R=F;for(let C=0;C<6;C++){let T=.5*(x+w),S=Wn(e,t,o,a*T,void 0,c(a*T),s);S.trimmed?(w=T,R=S):x=T}}else x=M}R&&(R.driving=!0,p.push(R))}if(R){let x=Math.abs(R.steerDeg),M=Math.min(Hh,100/(o*o)),F=R;for(;x<i;){let w=Math.min(i,x+M),C=f(w,F);if(C){let L=y(C);if(L){g(L);break}if(p.push(C),w>=i||ik(e,a*w))break;Math.abs(C.beta-F.beta)<.5*fu&&Math.abs(C.ay-F.ay)*Me<.5*hu&&(M=Math.min(Hh,1.5*M)),x=w,F=C;continue}if(M>jD){M*=.5;continue}let T=m,S=!1,A=null;for(let L of UD){let D=Math.min(i,x+L);if(D<=x)continue;let E=f(D,F);if(E){if(A=y(E,!0),A)break;p.push(E),x=D,F=E,M=Math.min(Hh,100/(o*o)),S=!0;break}}if(S)continue;if(A){g(A);break}d=x,h=T;let P=T?null:tE(e,t,o,a,p,c,s);P&&g(P);break}}else d=0;let k=p[0];for(let x of p)a*x.ay>a*k.ay&&(k=x);let v={states:p,foldDeg:d,rollover:h,peak:k,...b?{fold:b}:{}};if(l!==null){let x=Kh.get(e);x||(x=new WeakMap,Kh.set(e,x));let M=x.get(t);M||(M=new Map,x.set(t,M)),M.size>256&&M.clear(),M.set(l,v)}return v}var Kh=new WeakMap,WD=90,fu=1.5,hu=2.5,Hh=5,jD=.002,UD=[.5,1],j1=2.5,ek=.01,Nr=.001,XD=.05,qD=.25,QD=5,ZD=2,U1=1e-8,JD=1e-7,eE=1e-6;function tk(e,t,r,n,o,a,s){let i=n*se,c=o.ay*Me,l=b=>{let g=wt(e,t,r,i,b*se,c,ga(e,a(b),r,t));return{g:g.cn-s,ay:g.ay}},u=o.steerDeg,m=l(u),f=u+(u<0?-.001:.001),p=l(f),d=()=>p.g===0||Math.abs(f-u)<U1;for(let b=0;b<40&&Math.sign(m.g)===Math.sign(p.g)&&!d();b++){let g=(p.g-m.g)/(f-u),y=g!==0?f-p.g/g:f+2*(f-u);if(!Number.isFinite(y))return null;let R=2*Math.abs(f-u)+.001;if(y=f+Math.max(-R,Math.min(R,y-f)),u=f,m=p,f=y,p=l(f),Math.abs(f-o.steerDeg)>ZD)return null}let h={x:f,ay:p.ay};if(Math.sign(m.g)!==Math.sign(p.g)){let b=u,g=m.g,y=f,R=p.g;for(let k=0;k<60&&R!==0&&Math.abs(y-b)>U1;k++){let v=(b*R-y*g)/(R-g),x=l(v);if(h={x:v,ay:x.ay},x.g===0)break;Math.sign(x.g)===Math.sign(g)?(b=v,g=x.g,R*=.5):(y=v,R=x.g,g*=.5)}}else if(!d())return null;return Math.abs(h.ay-o.ay)*Me>hu?null:{steerDeg:h.x,ay:h.ay}}function ii(e,t,r,n,o){let a=J1(e,t,r,n.beta*se,n.steerDeg*se,n.ay*Me,ga(e,o(n.steerDeg),r,t));return{...a,trimmed:!a.overturned,driving:!a.overturned}}function tE(e,t,r,n,o,a,s){let i=o.length;if(i<3)return null;let c=o[i-1],l=i-2;for(;l>1&&o[l].beta===c.beta;)l--;let u=o[l],m=Math.sign(c.beta-u.beta);if(m===0||!u.driving)return null;let f=rk(e,t,r,a,s),p=f(u.beta,u),d=f(c.beta,c);if(!p||!d)return null;let h=n*d.steerDeg>=n*p.steerDeg,b=h?p:d,g=h?d:p,y=h?m:-m,R=null;for(let x=ek;Math.abs(g.beta-c.beta)<=fu;x*=1.5){let M=f(g.beta+y*x);if(!M)return null;if(n*M.steerDeg<=n*g.steerDeg){R=M;break}b=g,g=M}if(!R)return null;let k=nk(f,n,b,g,R);if(!k)return null;let v=ii(e,t,r,k,a);return!v.trimmed||Math.abs(v.beta-c.beta)>fu||Math.abs(v.ay-c.ay)*Me>hu?null:{state:v,sb:m}}function rk(e,t,r,n,o){let a=[];return(s,i)=>{if(!i){i=a[0];for(let u of a)Math.abs(u.beta-s)<Math.abs(i.beta-s)&&(i=u)}let c=tk(e,t,r,s,i,n,o);if(!c)return null;let l={beta:s,...c};return a.push(l),l}}function rE(e,t){let r=Math.abs(t.beta-e.beta);return r>qD&&r>QD*Math.abs(t.steerDeg-e.steerDeg)}function nE(e,t,r,n,o,a,s,i){let c=o.length;if(c<2)return null;let l=o[c-1],u=c-2;for(;u>0&&o[u].beta===l.beta;)u--;let m=o[u],f=Math.sign(a.beta-l.beta);if(f===0||Math.sign(l.beta-m.beta)!==f||!m.driving)return null;let p=rk(e,t,r,s,i),d=p(m.beta,m),h=p(l.beta,l);if(!d||!h||n*h.steerDeg<n*d.steerDeg)return null;let b=d,g=h,y=null;for(let R=ek;f*(a.beta-g.beta)>0;R=Math.min(XD,1.5*R)){let k=p(f*(a.beta-g.beta)>R?g.beta+f*R:a.beta);if(!k)return null;let v=n*k.steerDeg<=n*g.steerDeg;if(!y)v&&(y=[b,g,k]);else if(!v){let x=nk(p,n,...y);if(!x)return null;let M=ii(e,t,r,x,s);return M.trimmed?{state:M,sb:f}:null}b=g,g=k}return null}function nk(e,t,r,n,o){let a=p=>-t*p.steerDeg,s=Math.min(r.beta,o.beta),i=Math.max(r.beta,o.beta),c=n,l=a(r)<=a(o)?r:o,u=l===r?o:r,m=i-s,f=0;for(let p=0;p<100;p++){let d=.5*(s+i);if(Math.abs(c.beta-d)<=2*Nr-.5*(i-s))break;let h=!0;if(Math.abs(m)>Nr){let g=(c.beta-l.beta)*(a(c)-a(u)),y=(c.beta-u.beta)*(a(c)-a(l)),R=(c.beta-u.beta)*y-(c.beta-l.beta)*g;y=2*(y-g),y>0&&(R=-R),y=Math.abs(y);let k=m;if(m=f,Math.abs(R)<Math.abs(.5*y*k)&&R>y*(s-c.beta)&&R<y*(i-c.beta)){f=R/y;let v=c.beta+f;(v-s<2*Nr||i-v<2*Nr)&&(f=d>=c.beta?Nr:-Nr),h=!1}}h&&(m=c.beta>=d?s-c.beta:i-c.beta,f=ak*m);let b=e(Math.abs(f)>=Nr?c.beta+f:c.beta+(f>=0?Nr:-Nr));if(!b)return null;a(b)<=a(c)?(b.beta>=c.beta?s=c.beta:i=c.beta,u=l,l=c,c=b):(b.beta<c.beta?s=b.beta:i=b.beta,a(b)<=a(l)||l===c?(u=l,l=b):(a(b)<=a(u)||u===c||u===l)&&(u=b))}return c}function Qh(e,t,r,n,o,a,s=[n.stall]){let i=typeof o.op=="function"?o.op:()=>o.op,c=o.yawDemandCn??0,l="steerDeg"in a?b=>Math.abs(b.steerDeg)-Math.abs(a.steerDeg):b=>Math.abs(b.ay)-Math.abs(a.ayG),u=[...s,n.state].map(b=>({beta:b.beta,steerDeg:b.steerDeg,ay:b.ay})),m=u[0],f=u[u.length-1],p=l(m),d=l(f);if(p>0||d<0)return null;if(d===0)return ii(e,t,r,f,i);let h=m;for(let b=0;b<60&&Math.abs(f.beta-m.beta)>1e-9;b++){let g=(m.beta*d-f.beta*p)/(d-p),y=u[0];for(let x of u)Math.abs(x.beta-g)<Math.abs(y.beta-g)&&(y=x);let R=tk(e,t,r,g,y,i,c);if(!R)return null;let k={beta:g,...R};u.push(k),h=k;let v=l(k);if(Math.abs(v)<("steerDeg"in a?JD:eE))break;v<0?(m=k,p=v,d*=.5):(f=k,d=v,p*=.5)}return ii(e,t,r,h,i)}function oE(e,t,r,n,o,a){let s=Math.abs(o),{states:i}=n;if(s>Math.abs(i[i.length-1].steerDeg)+1e-9)return null;let c=0;for(;c<i.length-1&&Math.abs(i[c+1].steerDeg)<=s;)c++;let l=i[c];if(Math.abs(Math.abs(l.steerDeg)-s)<1e-9)return l;if(n.fold&&l===n.fold.stall)return Qh(e,t,r,n.fold,a,{steerDeg:o});let u=typeof a.op=="function"?a.op(o):a.op,m=Wn(e,t,r,o,l,u,a.yawDemandCn??0);return m.driving?m:null}function aE(e,t,r,n,o,a){if(!n.trimmed)return!1;let s=n.steerDeg<0?-1:1,{states:i}=Un(e,t,r,{direction:s,op:o,yawDemandCn:a}),c=Math.abs(n.steerDeg);if(c>Math.abs(i[i.length-1].steerDeg)+1e-9)return!1;let l=0;for(;l<i.length-2&&Math.abs(i[l+1].steerDeg)<c;)l++;let u=i[l],m=i[Math.min(l+1,i.length-1)],f=Math.abs(m.steerDeg)-Math.abs(u.steerDeg),p=f>0?Math.min(1,Math.max(0,(c-Math.abs(u.steerDeg))/f)):0,d=u.beta+p*(m.beta-u.beta),h=u.ay+p*(m.ay-u.ay);return Math.abs(n.beta-d)<=1&&Math.abs(n.ay-h)<=.05}function hn(e,t,r,n,o){let a=Math.max(8,r),s=n>=0?1:-1,i=Math.abs(n),c=(b,g)=>Or(e,t,a,s*b,g,o),l=Un(e,t,a,{direction:s,op:o}),{fold:u}=l;if(u&&Math.abs(u.state.steerDeg)<=ba){if(i>Math.abs(u.state.ay))return q1(e,t,a,s,i,o);if(i>Math.abs(u.stall.ay)){let b=Qh(e,t,a,u,{direction:s,op:o},{ayG:i});if(b)return b}}let m=l.states.filter(b=>Math.abs(b.steerDeg)<=ba),f=m[m.length-1],p=l.states.length>m.length;p&&Math.abs(f.steerDeg)<ba&&m.push(c(ba,f));let d=m.findIndex(b=>Math.abs(b.ay)>=i);if(d===0)return Or(e,t,a,0,void 0,o);if(d>0)return X1(m[d-1],m[d],i,c);let h=ok(m,c,void 0,p||l.foldDeg===null);return h.ay>=i?X1(h.below,h.state,i,c):l.foldDeg!==null&&l.foldDeg<ba?q1(e,t,a,s,i,o):h.state}var ba=20;function X1(e,t,r,n){let o={steer:Math.abs(e.steerDeg),f:Math.abs(e.ay)-r},a={steer:Math.abs(t.steerDeg),f:Math.abs(t.ay)-r},s=a.f===o.f?.5:-o.f/(a.f-o.f),i={ay:e.ay+s*(t.ay-e.ay),beta:e.beta+s*(t.beta-e.beta),driving:e.driving},c=0,l=null,u=1/0;for(let m=0;m<60;m++){let f=a.f===o.f?.5*(o.steer+a.steer):o.steer-o.f*(a.steer-o.steer)/(a.f-o.f),p=n(f,i),d=Math.abs(p.ay)-r;if(Math.abs(d)<u&&(l=p,u=Math.abs(d)),Math.abs(d)<=sE||a.steer-o.steer<=iE)break;d<0?(o={steer:f,f:d},c===-1&&(a.f*=.5),c=-1):(a={steer:f,f:d},c===1&&(o.f*=.5),c=1)}return l}var sE=1e-9,iE=1e-7;function ok(e,t,r,n=!1){let o=r??0;if(r===void 0)for(let x=1;x<e.length;x++)Math.abs(e[x].ay)>Math.abs(e[o].ay)&&(o=x);let a=e[Math.max(0,o-1)],s=Math.abs(e[o].steerDeg),i=cE/4,c,l,u,m,f,p,d,h,b=null,g;if(o>0&&o<e.length-1){let x=e[o+1];g=w=>{if(w<s)return t(w,a);let C=t(w,e[o]);return C.ay===e[o].ay?t(w,a):C},c=Math.abs(a.steerDeg),l=Math.abs(x.steerDeg),u=s,m=-Math.abs(e[o].ay);let[M,F]=Math.abs(a.ay)>=Math.abs(x.ay)?[a,x]:[x,a];f=Math.abs(M.steerDeg),p=-Math.abs(M.ay),d=Math.abs(F.steerDeg),h=-Math.abs(F.ay)}else{let x=Math.abs(e[o].lockDeg??e[o].steerDeg),M=x-lE,F=o>0&&n&&M>Math.abs(a.steerDeg)?t(M,a):null;if(!F||Math.abs(F.ay)<=Math.abs(e[o].ay)){let w=t(s,a);return{state:w,below:a,ay:Math.abs(w.ay)}}g=w=>t(w,a),c=Math.abs(a.steerDeg),l=x,u=M,m=-Math.abs(F.ay),b=F,f=x,p=-Math.abs(e[o].ay),d=c,h=-Math.abs(a.ay)}let y=l-c,R=0;for(let x=0;x<100;x++){let M=.5*(c+l);if(Math.abs(u-M)<=2*i-.5*(l-c))break;let F=!0;if(Math.abs(y)>i){let S=(u-f)*(m-h),A=(u-d)*(m-p),P=(u-d)*A-(u-f)*S;A=2*(A-S),A>0&&(P=-P),A=Math.abs(A);let L=y;if(y=R,Math.abs(P)<Math.abs(.5*A*L)&&P>A*(c-u)&&P<A*(l-u)){R=P/A;let D=u+R;(D-c<2*i||l-D<2*i)&&(R=M>=u?i:-i),F=!1}}F&&(y=u>=M?c-u:l-u,R=ak*y);let w=Math.abs(R)>=i?u+R:u+(R>=0?i:-i),C=g(w),T=-Math.abs(C.ay);T<=m?(w>=u?c=u:l=u,d=f,h=p,f=u,p=m,u=w,m=T,b=C):(w<u?c=w:l=w,T<=p||f===u?(d=f,h=p,f=w,p=T):(T<=h||d===u||d===f)&&(d=w,h=T))}let k=b??t(s,a),v=Math.abs(k.steerDeg)>s?e[o]:a;return{state:k,below:v,ay:Math.abs(k.ay)}}var cE=.001,lE=.01,ak=(3-Math.sqrt(5))/2;function q1(e,t,r,n,o,a){let s=l=>Math.abs(Or(e,t,r,n*l,void 0,a).ay),i=0,c=ba;if(s(c)<o)return Or(e,t,r,n*c,void 0,a);for(let l=0;l<28;l++){let u=.5*(i+c);s(u)<o?i=u:c=u}return Or(e,t,r,n*.5*(i+c),void 0,a)}function Zh(e,t,r,n,o){let a=hn(e,t,r,n,o);return a.steering?Math.abs(a.steering.totalNm):NaN}function Jh(e,t,r,n,o){if(!$n(e))return NaN;let a=n<0?-1:1,s=Math.abs(n),i=hn(e,t,r,a*s,o);if(!i.steering)return NaN;let c=Math.abs(i.steerDeg);for(let l of[.05,.1,.2,.4]){let u=Math.max(0,c-l),m=c+l,f=Or(e,t,r,a*u,void 0,o),p=Or(e,t,r,a*m,void 0,o),d=f.steering?Math.abs(f.steering.totalNm):NaN,h=p.steering?Math.abs(p.steering.totalNm):NaN,b=Math.abs(p.ay)-Math.abs(f.ay);if(Number.isFinite(d)&&Number.isFinite(h)&&b>=.01||l===.4&&Number.isFinite(d)&&Number.isFinite(h)&&b>.001)return(h-d)/b}return NaN}function Yh(e,t,r,n,o,a){let s=Math.max(8,r),i=wt(e,t,s,n*se,o*se,void 0,ga(e,a,s,t));return{ay:i.ay,cn:i.cn}}function eb(e,t,r,n,o){let a=Math.max(8,r),s=hn(e,t,a,n,o),i=.5,c=Yh(e,t,a,s.beta+i,s.steerDeg,o).cn,l=Yh(e,t,a,s.beta-i,s.steerDeg,o).cn;return(c-l)/(2*i*se)*e.massTotal*Me*(e.wheelbase/1e3)}function tb(e,t,r,n){let o=Math.max(8,r),{branch:a,opts:s}=uE(e,t,o,n);return sk(e,t,o,a,s)}function uE(e,t,r,n){if(!e.tv?.enabled){let s=n?{op:n}:{};return{branch:Un(e,t,r,s),opts:s}}let o=Wh(e,t,r),a={op:s=>{let i=jh(e,r,s,o);return i===0?n:{axG:n?.axG??0,driveFrontFrac:n?.driveFrontFrac,tvRearDiffN:i}}};return{branch:Un(e,t,r,a),opts:a}}function sk(e,t,r,n,o){let a=typeof o.op=="function"?o.op:()=>o.op,s=o.yawDemandCn??0;if(n.fold&&n.peak===n.fold.state)return ii(e,t,r,n.peak,a);let i=(l,u)=>Wn(e,t,r,l,u,a(l),s),c=n.states[0].driving||!n.peak.driving?n.states:n.states.slice(1);return ok(c,i,c.indexOf(n.peak),n.foldDeg===null).state}function rb(e,t,r,n={}){let o=n.radius!==void 0&&n.radius>0&&Number.isFinite(n.radius)?n.radius:void 0,a=o===void 0?Math.max(8,r):Math.max(8,Math.sqrt(Me*o)),s=(n.betaMaxDeg??10)*se,i=(n.deltaMaxDeg??10)*se,[c,l]=n.betaRangeDeg?[n.betaRangeDeg[0]*se,n.betaRangeDeg[1]*se]:[-s,s],[u,m]=n.deltaRangeDeg?[n.deltaRangeDeg[0]*se,n.deltaRangeDeg[1]*se]:[-i,i],{lf:f,lr:p}=zh(e),d=o===void 0?0:p/o,h=o===void 0?0:(f+p)/o,b=n.nLines??9,g=n.nPts??21,y=n.steering!==!1&&$n(e),R=y?sn(ge(t,"front").model):void 0,k=(I,_,B,O)=>B===1?I:I+(_-I)*O/(B-1),v=e.tv?.enabled?Wh(e,t,a):0,x=I=>{let _=jh(e,a,I/se,v);return!n.axG&&_===0?null:ga(e,{axG:n.axG??0,driveFrontFrac:n.driveFrontFrac,tvRearDiffN:_},a,t)},{lf:M,lr:F}=zh(e),w=n.reserves?ci(t,e.massTotal*Me*1.2):null,C=I=>w?Sr(w,{FL:I.FL,FR:I.FR,RL:I.RL,RR:I.RR},{lf:M,lr:F}):null,T=[],S={ay:[],cn:[]},A=0;for(let I=0;I<b;I++){let _=k(u,m,b,I),B=x(_),O=[],G=[],K=[],Y=[],j=w?{stabil:[],agil:[]}:void 0,Z=y?H1():void 0,ne;for(let W=0;W<g;W++){let J=k(c,l,g,W),re=wt(e,t,a,J,_,ne,B,o);if(ne=Number.isFinite(re.ay)?re.ay*Me:void 0,O.push(re.ay),G.push(re.cn),K.push(J/se),Y.push(_/se),j){let pe=C(re.wheels);j.stabil.push(pe.stabil),j.agil.push(pe.agil)}Z&&z1(Z,K1(e,t,_,re.wheels)),Math.abs(re.ay)>A&&(A=Math.abs(re.ay))}T.push({label:`\u03B4 ${(_/se).toFixed(0)}\xB0`,ay:O,cn:G,betaDeg:K,deltaDeg:Y,reserve:j,steering:Z});let te=null,fe=1/0;for(let W=1;W<G.length;W++){if(!Number.isFinite(G[W-1])||!Number.isFinite(G[W])||G[W-1]!==0&&G[W-1]<0==G[W]<0)continue;let J=G[W-1]===G[W]?0:G[W-1]/(G[W-1]-G[W]),re=O[W-1]+J*(O[W]-O[W-1]);if(o===void 0&&_!==0&&Math.abs(re)>=.05&&Math.sign(re)!==Math.sign(_))continue;let pe=Math.abs(K[W-1]+J*(K[W]-K[W-1])-d/se);pe<fe&&(fe=pe,te=re)}te!==null&&(S.ay.push(te),S.cn.push(0))}let P=[];for(let I=0;I<b;I++){let _=k(c,l,b,I),B=[],O=[],G=[],K=[],Y=w?{stabil:[],agil:[]}:void 0,j=y?H1():void 0,Z;for(let ne=0;ne<g;ne++){let te=k(u,m,g,ne),fe=wt(e,t,a,_,te,Z,x(te),o);if(Z=Number.isFinite(fe.ay)?fe.ay*Me:void 0,B.push(fe.ay),O.push(fe.cn),G.push(_/se),K.push(te/se),Y){let W=C(fe.wheels);Y.stabil.push(W.stabil),Y.agil.push(W.agil)}j&&z1(j,K1(e,t,te,fe.wheels))}P.push({label:`\u03B2 ${(_/se).toFixed(0)}\xB0`,ay:B,cn:O,betaDeg:G,deltaDeg:K,reserve:Y,steering:j})}let L=.5*se,D=x(h),E,V;if(o===void 0)E=(wt(e,t,a,d+L,h,void 0,D,o).cn-wt(e,t,a,d-L,h,void 0,D,o).cn)/(2*L),V=(wt(e,t,a,d,h+L,void 0,x(h+L),o).cn-wt(e,t,a,d,h-L,void 0,x(h-L),o).cn)/(2*L);else{let I=(O,G)=>wt(e,t,a,O,G,void 0,x(G),o).cn,_=(O,G,K)=>Number.isFinite(O)?(-3*O+4*G-K)/(2*L):(K-G)/L,B=I(d,h);E=-_(B,I(d-L,h),I(d-2*L,h)),V=_(B,I(d,h+L),I(d,h+2*L))}let N=0;if(D&&D.axG){let I=wt(e,t,a,d,h,void 0,D,o),_=0;for(let B of fn)_+=I.wheels[B].fxShort;N=_/Math.abs(e.massTotal*D.axG*Me)}let z=S.ay.reduce((I,_)=>Math.max(I,Math.abs(_)),0);return{isoBeta:P,isoDelta:T,trim:S,maxAy:A,stability:E,control:V,speed:o===void 0?a:Math.sqrt(z*Me*o),...o!==void 0?{radius:o}:{},axG:D?.axG??0,axShortfall:N,...R?{steeringAligningSource:R}:{}}}function ik(e,t){return Xn(e,t*se).atLock}function mE(e,t,r,n,o=_r(e,t,r)){let a=r,s=e.massTotal,i=fn.filter(g=>jt(g)?n.drivenFront:n.drivenRear),c=o.peakAt,l={front:n.drivenFront?$t(e,"front",1):void 0,rear:n.drivenRear?$t(e,"rear",1):void 0},u=new Map,m=(g,y)=>{let R=`${g}:${y}`,k=u.get(R);if(k===void 0){let v=Math.max(1,y*ai);k=St(ge(t,g),v,0,!1,c(g,v)),u.set(R,k)}return k},f=(g,y)=>y>0?oi(y,R=>m(g,R)):0,p=(g,y,R,k)=>{let v=ge(t,g),x=D=>{let E=Math.max(0,R[D]),V=c(g,E);return{Fz:E,a:f(g,E),b:V.fyPeak,slide:0,cap:N=>E>0?St(v,E,N,!1,V):0}},[M,F]=g==="front"?["FL","FR"]:["RL","RR"],w=x(M),C=x(F),T=k[M]*w.b,S=k[F]*C.b,A=w.cap(T)+C.cap(S),P=ni(w,C,T+S,y,A);return{l:M,r:F,full:P,asHeld:()=>({axle:g,strong:w.cap(T)>=C.cap(S)?M:F,full:P,open:ni(w,C,T+S,pa,A),sense:1})}},d=g=>({muX:y=>y>0?f(g,y)/y:0,muY:y=>y>0?c(g,y).fyPeak/y:0}),h={front:d("front"),rear:d("rear")},b=g=>({arms:{lf:e.wheelbase/1e3*(1-e.frontMassFrac),lr:e.wheelbase/1e3*e.frontMassFrac},halfTrack:{front:e.trackFront/2e3,rear:e.trackRear/2e3},ayDir:Math.sign(g)});return{limitAt:(g,y,R,k=0)=>{let v={FL:0,FR:0,RL:0,RR:0},x=Ce(e,g,0,a,0,y),M,F=P=>(M?.ax!==P&&(M={ax:P,loads:Ce(e,g,(P+k)/Me,a,0,y)}),M.loads),w=Rl(P=>ea(R,F(P),x,c).short,-k,1),C=R,T=P=>{let L=w.at(P);v=F(L),C=ea(R,v,x,c).util;let D=0,E=n.diffYaw?{fx:{FL:0,FR:0,RL:0,RR:0},axles:[]}:null;for(let V of i){let N=l[dn(V)];if(N){if(du(V)){let B=p(dn(V),N,v,C);D+=B.full,E&&(E.fx[B.l]=E.fx[B.r]=B.full/2,E.axles.push(B.asHeld()))}continue}let z=Math.max(0,v[V]),I=c(dn(V),z),_=St(ge(t,dn(V)),z,C[V]*I.fyPeak,!1,I);D+=_,E&&(E.fx[V]=_)}if(E){let V={};for(let N of fn){let z=Math.max(0,v[N]);V[N]={Fz:z,Fy:C[N]*c(dn(N),z).fyPeak,Fx:E.fx[N]}}for(let N of E.axles)D+=$l(N,V,h,b(g))-N.full}return D/s},S=C1(T,-k,pn).fx,A=w.edge();return A!==void 0&&S>A&&(S=A,T(S)),{ax:S,loads:v}}}}var pu=.05,Q1=.001,Z1=16,bu=8;function nb(e,t,r,n){let o=Math.max(bu,r),a=n.nSteer??7,s=e.tv?.enabled?Wh(e,t,o,n.steerMaxDeg):0,i=I=>{let _=jh(e,o,I,s);return _===0?void 0:{axG:0,tvRearDiffN:_}},c=n.yawDemandCn??0,l={op:i,yawDemandCn:c,...n.steerMaxDeg!==void 0?{steerMaxDeg:n.steerMaxDeg}:{}},u=Un(e,t,o,l),m=I=>{let _={},B={};for(let O of fn)_[O]=I.wheels[O].slipDeg*se,B[O]=Math.min(1,I.wheels[O].gripUtil);return{steerDeg:I.steerDeg,ayMs:Math.max(0,I.ay*Me),ayG:I.ay,slip:_,util:B,scrub:I.ay>0?pE(I,e.massTotal):0}},f=null,p=I=>{if(f&&I===f.steerDeg)return m(f);let _=oE(e,t,o,u,I,l);if(_)return m(_);let B=u.states[0];for(let O of u.states)O.steerDeg<=I&&(B=O);return m(B)},d=u.peak.driving&&u.peak.ay>0?sk(e,t,o,u,l):null,h=d?Math.max(0,d.ay*Me):0,b=d?[...u.states.filter(I=>I.steerDeg<d.steerDeg),d]:u.states,g=d?b.findIndex(I=>I.ay*Me>=.995*h):0,y=b[g].steerDeg,{fold:R}=u;if(d&&R&&u.peak===R.state){let I=.995*h/Me,_=u.states.indexOf(R.stall),B=_-1;for(;B>0&&u.states[B].beta===R.stall.beta;)B--;let O=Math.sign(R.stall.beta-u.states[B].beta),G=_;for(;G>0&&u.states[G].ay>=I&&Math.sign(u.states[G].beta-u.states[G-1].beta)!==-O;)G--;u.states[G].ay<I&&(f=Qh(e,t,o,R,l,{ayG:I},u.states.slice(G,_+1)))}if(f)y=f.steerDeg;else if(g>0){let I=b[g-1].steerDeg,_=y;for(let B=0;B<8&&_-I>.001;B++){let O=.5*(I+_);p(O).ayMs>=.995*h?_=O:I=O}y=_}let k=[];for(let I=0;I<(h>0?a:1);I++){let _=I/(a-1);k.push(p(y*(_+Math.sin(Math.PI/2*_))/2))}k[0].ayMs=0;let v=[],x=[],M=[],F=[],w=_r(e,t,o,void 0,n.diffYaw===!0),C=mE(e,t,o,n,w),T=n.axDrag??0,S=I=>{let _=w.limitAt(I.ayMs/Me,I.steerDeg,I.util,T+I.scrub);return{axD:_.edge!==void 0&&_.edge>0?_.edge:_.ax,locked:_.axUnlocked-_.ax>pu}},A=I=>C.limitAt(I.ayMs/Me,I.steerDeg,I.util,T+I.scrub).ax,P=k.map(I=>({p:I,axA:A(I),...S(I)})),L=[];for(let I=0;I+1<P.length;I++){let _=P[I],B=P[I+1],O=[];_.locked!==B.locked?O.push({read:S,past:G=>G.locked===B.locked,braking:!0}):(B.axA>_.axA+pu&&O.push({read:G=>({axA:A(G)}),past:G=>(G.axA??-1/0)>_.axA}),-B.axD>-_.axD+pu&&O.push({read:S,past:G=>-(G.axD??0)>-_.axD}));for(let{read:G,past:K,braking:Y}of O){let j=_.p.steerDeg,Z=B.p.steerDeg,ne=null,te=_.axD,fe=B.axD;for(let W=0;W<Z1&&Z-j>Q1&&!(Y&&Math.abs(fe-te)<=pu);W++){let J=.5*(j+Z),re=p(J),pe=G(re);K(pe)?(Z=J,ne={p:re,r:pe},fe=pe.axD??fe):(j=J,te=pe.axD??te)}if(ne){let{p:W,r:J}=ne,re=J.axD!==void 0&&J.locked!==void 0?{axD:J.axD,locked:J.locked}:S(W);L.push({p:W,axA:J.axA??A(W),...re})}}}P.push(...L),P.sort((I,_)=>I.p.steerDeg-_.p.steerDeg);let D=I=>I.axA+T+I.p.scrub,E=.001*Math.max(1,k[k.length-1].ayMs),V=[];for(let I=0;I+1<P.length;I++){let _=P[I],B=P[I+1];if(!(D(_)>=0&&D(B)<0))continue;let O=_.p.steerDeg,G=B.p.steerDeg,K=null,Y=null;for(let Z=0;Z<Z1&&G-O>Q1;Z++){let ne=.5*(O+G),te=p(ne);D({p:te,axA:A(te)})>=0?(O=ne,K=te):(G=ne,Y=te)}let j=K??Y;j&&j.ayMs>_.p.ayMs&&j.ayMs<B.p.ayMs&&V.push({p:j,axA:-(T+j.scrub),steady:!0,...S(j)})}P.push(...V),P.sort((I,_)=>I.p.steerDeg-_.p.steerDeg);let N=!1;for(let{p:I,axA:_,axD:B,steady:O}of P){let G=v.length-1,K=G>=0&&(O||N?!(I.ayMs>v[G]):I.ayMs-v[G]<E);N=O===!0&&!K,K?(x[G]=Math.max(x[G],_),M[G]=Math.min(M[G],B)):(v.push(I.ayMs),x.push(_),M.push(B),F.push(I.scrub))}for(let I=v.length-2;I>=0;I--)x[I]=Math.max(x[I],x[I+1]),M[I]=Math.min(M[I],M[I+1]);return{ayMax:v[v.length-1],ay:v,axAccel:x,axDecel:M,axScrub:F,rollover:u.rollover,atLock:d!==null&&ik(e,d.steerDeg)}}function pE(e,t){let r=e.beta*se,n=0;for(let o of fn){let a=e.wheels[o],s=a.steerDeg*se-r;n+=a.Fx*(Math.cos(s)-1)-a.Fy*Math.sin(s)}return n/t}var pU=Math.PI/180,dU={speeds:Array.from({length:23},(e,t)=>8+t),steerMaxDeg:14,steerSteps:29};function lk(e=150,t=300,r=18,n=25){return(o,a,s)=>{let i=Math.min(1,Math.max(0,(o-r)/(n-r))),c=s>0?Math.min(1,a/s):0;return(e+i*(t-e))*c}}var ya={enabled:!1,kp:3e3,ffLow:150,ffHigh:300,vLow:18,vHigh:25},ck=e=>lk(e.ffLow,e.ffHigh,e.vLow,e.vHigh);var cr={power_limit_kw:{value:0,label:"battery power limit (0 = none)",unit:"kW"},v_limit_endurance:{value:0,label:"endurance speed limit (0 = none)",unit:"km/h"},endurance_reserve:{value:0,label:"endurance energy reserve (0 = flat out)",unit:"%"},grip_scale:{value:1,label:"grip scale (rig \u2192 road)",unit:"-"},stiffness_scale:{value:1,label:"stiffness scale (rig \u2192 road)",unit:"-"},camber_front_deg:{value:0,label:"static camber front (\u2212 top in)",unit:"\xB0"},camber_rear_deg:{value:0,label:"static camber rear (\u2212 top in)",unit:"\xB0"},cg_height:{value:300,label:"CG height",unit:"mm"},tire_vertical_rate:{value:100,label:"tyre vertical rate",unit:"N/mm"},tire_vertical_damping:{value:0,label:"tyre vertical damping",unit:"N\xB7s/mm"},arb_front:{value:20,label:"ARB front (@wheel)",unit:"N/mm"},arb_rear:{value:15,label:"ARB rear (@wheel)",unit:"N/mm"},heave_spring_front:{value:0,label:"Heave spring front (@wheel)",unit:"N/mm"},heave_spring_rear:{value:0,label:"Heave spring rear (@wheel)",unit:"N/mm"},unsprung_mass:{value:8,label:"unsprung mass/corner",unit:"kg"},brake_balance:{value:.6,label:"brake balance (front)",unit:"-"},damper_front:{value:2.5,label:"damper front",unit:"N\xB7s/mm"},damper_rear:{value:2.5,label:"damper rear",unit:"N\xB7s/mm"},cop_long:{value:.5,label:"CoP aft of front",unit:"\xB7wb"},cop_height:{value:300,label:"CoP height",unit:"mm"},ride_height_front:{value:30,label:"static ride height front (laden)",unit:"mm"},ride_height_rear:{value:35,label:"static ride height rear (laden)",unit:"mm"},I_yaw:{value:295,label:"yaw inertia Izz",unit:"kg\xB7m\xB2"},I_roll:{value:95,label:"roll inertia Ixx",unit:"kg\xB7m\xB2"},I_pitch:{value:380,label:"pitch inertia Iyy",unit:"kg\xB7m\xB2"},I_wheel:{value:0,label:"rotating inertia per wheel",unit:"kg\xB7m\xB2"},I_rotor:{value:0,label:"driveline inertia at the motor",unit:"kg\xB7m\xB2"},ackermann_pct:{value:50,label:"Ackermann",unit:"%"},toe_front_deg:{value:0,label:"static toe front (+ in)",unit:"\xB0"},toe_rear_deg:{value:0,label:"static toe rear (+ in)",unit:"\xB0"},spring_front:{value:35,label:"spring front (@spring)",unit:"N/mm"},spring_rear:{value:40,label:"spring rear (@spring)",unit:"N/mm"},mr_front:{value:1,label:"motion ratio front",unit:"-"},mr_rear:{value:1,label:"motion ratio rear",unit:"-"},track_front:{value:1200,label:"track front",unit:"mm"},track_rear:{value:1200,label:"track rear",unit:"mm"},wheelbase:{value:1535,label:"wheelbase",unit:"mm"},rc_front:{value:30,label:"roll centre front",unit:"mm"},rc_rear:{value:40,label:"roll centre rear",unit:"mm"},tv_enabled:{value:0,label:"torque vectoring",unit:"0/1"},tv_kp:{value:3e3,label:"TV yaw-rate gain",unit:"N per rad/s"},tv_ff_low:{value:150,label:"TV feedforward, low speed",unit:"N"},tv_ff_high:{value:300,label:"TV feedforward, high speed",unit:"N"},tv_v_low:{value:18,label:"TV feedforward ramp start",unit:"m/s"},tv_v_high:{value:25,label:"TV feedforward ramp end",unit:"m/s"}},dE=["k_yaw","k_roll","k_pitch"];function ui(e){for(let t of dE)delete e[t];for(let t of Object.keys(cr)){let r=e[t];if(!r){e[t]={...cr[t]};continue}e[t]={...r,label:cr[t].label,unit:cr[t].unit}}return e}function Q(e,t){return e[t]?.value??cr[t].value}function gu(e){let t=(r,n)=>e[r]?.value??n;return{enabled:t("tv_enabled",0)>=.5,kp:t("tv_kp",ya.kp),ffLow:t("tv_ff_low",ya.ffLow),ffHigh:t("tv_ff_high",ya.ffHigh),vLow:t("tv_v_low",ya.vLow),vHigh:t("tv_v_high",ya.vHigh)}}var uk=[10,25,50,100,200,300];function ob(e,t,r,n,o){let s=uk.map(i=>Math.round(i<=25?r*i:r*25+n*(i-25)));return{id:e,label:t,speedMmS:[...uk],reboundN:s,bumpN:s.map(i=>Math.round(i*o))}}var yu={name:"Generic FS damper",curves:[ob("c1","Soft",1.6,1,.65),ob("c2","Medium",3,1.6,.65),ob("c3","Firm",8,2.4,.65)]};function xu(e){let t=e.curves.length;return t>0?e.curves[Math.floor((t-1)/2)].id:""}var bn=25;function xa(e,t){let r=e.speedMmS,n=e.forceN,o=Math.min(r.length,n.length);if(o===0||!(t>0))return 0;let a=0,s=0;for(let i=0;i<o;i++){let c=r[i],l=n[i];if(t<=c)return s+(l-s)*(t-a)/(c-a);if(i===o-1)return l+Math.max(0,(l-s)/(c-a))*(t-c);a=c,s=l}return 0}function mk(e,t){return t>=0?xa(e.rebound,t):-xa(e.bump,-t)}function pk(e,t,r){return t*mk(e,t*r)}var ab=(e,t)=>e.curves.find(r=>r.id===t);function mi(e,t){let r=ab(e,xu(e)),n=(t&&ab(e,t.bump))??r,o=(t&&ab(e,t.rebound))??r;return{bump:{speedMmS:n?.speedMmS??[],forceN:n?.bumpN??[]},rebound:{speedMmS:o?.speedMmS??[],forceN:o?.reboundN??[]}}}var Ru=5e3;function pi(e,t){let r=t>0?t:1,n=[],o=[],a=e.bump.speedMmS.map(c=>c/r).filter(c=>c<Ru),s=e.rebound.speedMmS.map(c=>c/r).filter(c=>c<Ru),i=c=>{n.push(c),o.push(pk(e,r,c))};i(-Ru);for(let c=a.length-1;c>=0;c--)i(-a[c]);i(0);for(let c of s)i(c);return i(Ru),{kind:"map",input:"velocity",x:n,y:o}}var sb=64;function di(e,t,r){let n=t>0?t:1,o=Math.max(r,1e-6),a=0;for(let s=0;s<sb;s++){let i=Math.sin((s+.5)*Math.PI/sb),c=n*o*i;a+=n*(xa(e.rebound,c)+xa(e.bump,c))*i}return a*(Math.PI/sb)/(Math.PI*o)}function qn(e,t,r,n,o=e){let a=(c,l,u)=>{if(!c||c.curves.length===0)return;let m=mi(c,l);return{law:m,curve:pi(m,u),rate:di(m,u,bn)}},s=a(e,t?.front,r),i=a(o??e,t?.rear,n);return!s&&!i?null:{...s?{front:s}:{},...i?{rear:i}:{}}}var dk=(e,t)=>({...e,y:e.y.map(r=>r*t)}),fE=e=>({...e,x:e.x.map(t=>-t).reverse(),y:e.y.map(t=>-t).reverse()});function ib(e,t,r){let n=Math.abs(r)>0?Math.abs(r):1,o=mi(e,t);return{law:o,curve:dk(pi(o,n),.5),rate:di(o,n,bn)/2,mr:n,ratio:n,share:.5}}function cb(e,t,r,n,o){let a=n*(Math.abs(r)>0?Math.abs(r):1),s=mi(e,t),i=dk(pi(s,a),1/n);return{law:s,curve:o?fE(i):i,rate:di(s,a,bn)/n,mr:a/n,ratio:a,share:1/n}}function fi(e,t){let r=e.damperModelIdRear?t(e.damperModelIdRear):void 0,n=e.heaveDamperModelId?t(e.heaveDamperModelId):void 0,o=e.rollDamperModelId?t(e.rollDamperModelId):void 0;return{...r?{damperModelRear:r}:{},...n?{heaveDamperModel:n}:{},...o?{rollDamperModel:o}:{}}}var vu=["front","rear","heaveFront","heaveRear","rollFront","rollRear"];function hi(e,t){if(t?.body){let{extended:n,stroke:o,...a}=e??{},{extended:s,stroke:i}=t.body;return{coilover:{...a,extended:s,...i!==void 0?{stroke:i}:{}},source:"part",part:t}}let r=e?.extended!==void 0&&e.extended>0;return{...e?{coilover:e}:{},source:r?"suspension":"none"}}function Vr(e,t){if(typeof e=="number")return e;let{x:r,y:n}=e,o=r.length;if(o===0)return 0;if(o===1||t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}function gi(e){return e.kind==="coil"?2:1}function bi(e){let t=Math.max(0,e.od),r=Math.max(0,Math.min(e.id,t));return Math.PI*(t**4-r**4)/32}function hk(e){return bi(e)/2}function bk(e){let t=Math.max(0,e.width),r=Math.max(0,e.thickness),n=t*r**3/12,o=r*t**3/12,a=e.angleDeg*Math.PI/180;return n*Math.cos(a)**2+o*Math.sin(a)**2}function fk(e){let t=0;for(let r of e)if(Number.isFinite(r)){if(r<=0)return 0;t+=1/r}return t>0?1/t:1/0}function hE(e,t,r){let n=Math.min(e.length,t.length);if(n<2)return 0;let o=Math.abs(r);if(o<=e[0])return(t[1]-t[0])/(e[1]-e[0]);for(let a=1;a<n;a++)if(o<=e[a])return(t[a]-t[a-1])/(e[a]-e[a-1]);return(t[n-1]-t[n-2])/(e[n-1]-e[n-2])}function yi(e,t=0){let r={rateAtLink:0,contributions:{},torsional:0};switch(e.kind){case"none":return r;case"ubar":{let n=e.armLength;if(n<=0||e.barLength<=0)return r;let o=e.G*bi(e.section)/e.barLength,a=2*o/(n*n),s=hk(e.armSection??e.section),i=3*e.E*s/n**3,c=e.dropLinkRate??1/0;return{rateAtLink:fk([a,i,c]),contributions:{barTwist:a,armBending:i,dropLink:c},torsional:o}}case"blade":{let n=e.armLength;if(n<=0||e.barLength<=0)return r;let o=e.G*bi(e.section)/e.barLength,a=2*o/(n*n),s=3*e.E*bk(e.blade)/n**3,i=e.dropLinkRate??1/0;return{rateAtLink:fk([a,s,i]),contributions:{barTwist:a,armBending:s,dropLink:i},torsional:o}}case"torsionTube":{let n=e.leverArm;if(n<=0||e.length<=0)return r;let o=e.G*bi(e.section)/e.length,a=2*o/(n*n);return{rateAtLink:a,contributions:{barTwist:a},torsional:o}}case"coil":{let n=Vr(e.rate,2*Math.abs(t)),o=2*Math.max(0,n);return{rateAtLink:o,contributions:{spring:o},torsional:0}}case"direct":return{rateAtLink:e.wheelRate,contributions:{},torsional:0};case"tabulated":{let n=hE(e.linkTravel,e.force,t);return{rateAtLink:Math.max(0,n),contributions:{},torsional:0}}}}function ku(e,t,r=0){if(e.kind==="none")return{wheelRate:0,motionRatio:0,rateAtLink:0};if(e.kind==="direct")return{wheelRate:Math.max(0,e.wheelRate),motionRatio:1,rateAtLink:0};let n=t?zd(t,r):1,o=t?Yd(t,r):0,a=yi(e,o).rateAtLink;return{wheelRate:Math.max(0,a*n*n),motionRatio:n,rateAtLink:a}}function xi(e,t){let r=e.damper??0;return!r||e.design.kind==="none"?0:gi(e.design)*r*t*t}var bE=150;function gE(e){return X(e,[0,-.5,1])<-1e-9?U(e,-1):e}function gk(e){let t=e.hardpoints,r=H(t.rockerPivotB,t.rockerPivotA),n=ee(t.rockerPivotA,U(H(t.rockerToDamper,t.rockerPivotA),.6)),o=gE(q(ae(r,H(t.rockerToDamper,t.rockerPivotA))));return{outer:n,inner:ee(n,U(o,bE)),attach:"rocker"}}function Ct(e,t){let r={};for(let o of er)r[o]=tt(Ge(e,o));let n={vehicle:e,ctx:r};return t&&(n.kc=fl(n,t)),n}var Mu=.5;function yE(e,t){let r=([i,c,l])=>{let u=q(H(c,i)),m=H(l,i),f=q(H(m,U(u,X(m,u))));return[u,f,ae(u,f)]},n=r(e),o=r(t),a=[0,1,2].map(i=>[0,1,2].map(c=>o[0][i]*n[0][c]+o[1][i]*n[1][c]+o[2][i]*n[2][c]));return{rot:a,move:i=>{let c=H(i,e[0]);return ee(t[0],[0,1,2].map(l=>a[l][0]*c[0]+a[l][1]*c[1]+a[l][2]*c[2]))}}}var yk=e=>[(e[2][1]-e[1][2])/2,(e[0][2]-e[2][0])/2,(e[1][0]-e[0][1])/2];function Su(e,t,r){let n=Ze(t,e.vehicle.config),o=e.ctx[t],a=r.rigid?void 0:{loadedRadius:r.loadedRadius},s=r.state?null:ye(o,r.travel,r.steer,void 0,a),i=r.state??at(s),c=ye(o,r.travel+Mu,r.steer,void 0,a),l=ye(o,r.travel-Mu,r.steer,void 0,a),u=(s?s.ok:r.converged)&&c.ok&&l.ok,m=at(c),f=at(l),p=(C,T)=>Ot(C.points[T],n),d=o.inv.strut?"pushrodOuter":"uprightUpper",h=p(i,d),b=p(i,"uprightLower"),g=C=>{let T=H(b,h);return Math.hypot(...ae(T,H(p(i,C),h)))/Math.hypot(...T)},y=g("tieOuter")>=g("wheelCenter")?"tieOuter":"wheelCenter",R=[h,b,p(i,y)],k=C=>yE(R,[p(C,d),p(C,"uprightLower"),p(C,y)]),v=k(m),x=k(f),M=yk(v.rot),F=yk(x.rot),w=[NaN,NaN,NaN];return{solved:u,state:i,at:C=>p(i,C),velocity:C=>u?U(H(v.move(C),x.move(C)),1/(2*Mu)):w,omega:u?U(H(M,F),1/(2*Mu)):w}}function lb(e,t,r,n){let o=t[0]*-n[1]-t[1]*-n[0];if(Math.abs(o)<1e-9)return null;let a=r[0]-e[0],s=r[1]-e[1],i=(a*-n[1]-s*-n[0])/o;return[e[0]+i*t[0],e[1]+i*t[1]]}function xk(e,t,r){let n=Su(e,t,gt(e,r)[t]),o=n.at("contactPatch"),a=n.velocity(o);return{solved:n.solved,cp:[o[1],o[2]],vCp:[a[1],a[2]],wx:n.omega[0]}}function Rk(e){let t=Math.hypot(e.vCp[0],e.vCp[1]);return Math.abs(e.wx)*1e9>t?[e.cp[0]-e.vCp[1]/e.wx,e.cp[1]+e.vCp[0]/e.wx]:null}function vk(e,t){let r=Math.hypot(e.vCp[0],e.vCp[1]);if(!(r>1e-9))return null;let n=[-e.vCp[1]/r,e.vCp[0]/r],o=t?[t[0]-e.cp[0],t[1]-e.cp[1]]:[e.cp[0]>0?-1:1,0];return n[0]*o[0]+n[1]*o[1]<0?[-n[0],-n[1]]:n}function xE(e,t,r){return Math.abs(t[0]*(r[1]-e[1])-t[1]*(r[0]-e[0]))<=1e-6*Math.max(1,Math.hypot(r[0]-e[0],r[1]-e[1]))?[(e[0]+r[0])/2,(e[1]+r[1])/2]:null}var RE=.1*Math.PI/180;function kk(e,t,r,n,o){return Math.max(Math.hypot(e[0]-t[0],e[1]-t[1]),Math.hypot(e[0]-r[0],e[1]-r[1]))*RE<=o*n}function Au(e,t){return!e.valid||!e.cpLeft||!e.cpRight?!1:kk([e.lateral,e.height],e.cpLeft,e.cpRight,e.sinAngle,t)}function Ri(e){let t=(o,a,s)=>{let i=o&&a?[a[0]-o[0],a[1]-o[1]]:s;return!o||!i||!(Math.abs(i[0])>1e-9)?Number.NaN:o[1]-o[0]*i[1]/i[0]},r=t(e.cpLeft,e.icLeft,e.lineLeft),n=t(e.cpRight,e.icRight,e.lineRight);return Number.isFinite(r)&&Number.isFinite(n)?{left:r,right:n}:null}var vE=1;function Mk(e){let t=Ri(e);if(!t||!e.cpLeft||!e.cpRight||Math.abs(t.left-t.right)>vE)return null;let r=(t.left+t.right)/2,n=e.cpRight[0]-e.cpLeft[0],o=e.cpRight[1]-e.cpLeft[1],a=Math.hypot(n,o)||1;return{height:r,heightAboveGround:(0-e.cpLeft[0])*(-o/a)+(r-e.cpLeft[1])*(n/a)}}function Ra(e){let t=(n,o,a)=>{if(!n)return Number.NaN;if(!o)return a?0:Number.NaN;let s=n[0]-o[0];return Math.abs(s)>1e-9?n[0]/s:Number.NaN},r=(t(e.cpLeft,e.icLeft,e.lineLeft)+t(e.cpRight,e.icRight,e.lineRight))/2;return e.valid&&Number.isFinite(r)?r:0}function lr(e,t,r){let n=r==="front"?"FL":"RL",o=r==="front"?"FR":"RR",a=xk(e,n,t),s=xk(e,o,t);if(!a.solved||!s.solved)return{height:0,lateral:0,heightAboveGround:0,lateralAlongGround:0,valid:!1,unsolved:!0,icLeft:null,icRight:null,lineLeft:null,lineRight:null,sinAngle:0,cpLeft:a.cp,cpRight:s.cp};let i=Rk(a),c=Rk(s),l=vk(a,i),u=vk(s,c),m={height:0,lateral:0,heightAboveGround:0,lateralAlongGround:0,valid:!1,icLeft:i,icRight:c,lineLeft:l,lineRight:u,sinAngle:0,cpLeft:a.cp,cpRight:s.cp};if(!l||!u)return m;let f=i?[i[0]-a.cp[0],i[1]-a.cp[1]]:l,p=c?[c[0]-s.cp[0],c[1]-s.cp[1]]:u,d=Math.hypot(f[0],f[1]),h=Math.hypot(p[0],p[1]),b=d>0&&h>0?Math.abs(f[0]*p[1]-f[1]*p[0])/(d*h):0,g=lb(a.cp,f,s.cp,p)??xE(a.cp,l,s.cp);if(!g)return{...m,sinAngle:b};let y=s.cp[0]-a.cp[0],R=s.cp[1]-a.cp[1],k=Math.hypot(y,R)||1,v=y/k,x=R/k,M=(a.cp[0]+s.cp[0])/2,F=(a.cp[1]+s.cp[1])/2,w=(g[0]-a.cp[0])*-x+(g[1]-a.cp[1])*v,C=(g[0]-M)*v+(g[1]-F)*x;return{lateral:g[0],height:g[1],heightAboveGround:w,lateralAlongGround:C,valid:!0,icLeft:i,icRight:c,lineLeft:l,lineRight:u,sinAngle:b,cpLeft:a.cp,cpRight:s.cp}}function Br(e,t){return{front:lr(e,t,"front"),rear:lr(e,t,"rear")}}function Fu(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function kE(e,t){return{camber:Fu(e.travel,e.camber,t),toe:Fu(e.travel,e.toe,t),motionRatio:Fu(e.travel,e.motionRatio,t),damperLen:e.damperLen?Fu(e.travel,e.damperLen,t):0}}var Sk=e=>kE(e,0).motionRatio;function ub(e,t){if(e.kind!=="coil")return null;let r=t??e.motionRatio,n=Vr(e.rate,0)*r*r/2;return n>0&&Number.isFinite(n)?{rate:n,gap:Math.max(0,e.gap??0),bothWays:!!e.bothWays}:null}function wu(e,t){if(e.kind==="none")return 0;if(e.kind==="tabulated"){let n=a=>ME(e,a);return(n(.5)-n(-.5))/(2*.5)/2}if((e.gap??0)>0)return 0;let r=t??e.motionRatio;return Vr(e.rate,0)*r*r/2}function vi(e,t){let r=e.damper??0;if(!r||e.design.kind==="none"||e.design.kind==="coil"&&(e.design.gap??0)>0)return 0;let n=t??(e.design.kind==="coil"?e.design.motionRatio:1);return r*n*n/2}function ME(e,t){let{travel:r,force:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}var mb={kind:"coil",rate:120,motionRatio:.7,gap:5,bothWays:!1};var Ak=new WeakMap;function Tu(e,t){let r=Ak.get(e);r||(r=new Map,Ak.set(e,r));let n=`${t.attach}|${t.outer.join(",")}|${JSON.stringify(t.mount??null)}`,o=r.get(n);if(o)return o;let a=En(e,t);return r.set(n,a),a}var SE=32,ki=new Map,Fk=new WeakMap,AE=1;function FE(e){let t=Fk.get(e);return t===void 0&&(t=AE++,Fk.set(e,t)),t}function pb(e,t){if(!t.linkage)return null;let r=an(e,t.linkage,t.design.kind),n=`${FE(e)}|${r?"unit":"bar"}|${JSON.stringify(t.linkage)}`,o=ki.get(n);if(o)return o;let a=jo(e,t.linkage,{kind:t.design.kind});return ki.size>=SE&&ki.delete(ki.keys().next().value),ki.set(n,a),a}function Zn(e,t,r=0){let n=(o,a)=>{if(!(!o||o.design.kind==="none"))return ku(o.design,pb(a,o),r).wheelRate};return{front:n(t.arbFrontDesign,e.front),rear:n(t.arbRearDesign,e.rear)}}function va(e,t){let r=(n,o)=>{if(!n||n.design.kind==="none")return;let a=n.linkage?Tu(o,n.linkage).atDesign:void 0;return wu(n.design,a)};return{front:r(t.heaveFrontDesign,e.front),rear:r(t.heaveRearDesign,e.rear)}}function Lk(e,t){let r=(a,s)=>{if(!a||a.design.kind!=="coil")return;let i=a.linkage?Tu(s,a.linkage).atDesign:void 0;return ub(a.design,i)??void 0},n=r(t.heaveFrontDesign,e.front),o=r(t.heaveRearDesign,e.rear);return{...n?{front:n}:{},...o?{rear:o}:{}}}function Pu(e,t){let r=(o,a)=>o?vi(o,db(o,a)):0,n=(o,a)=>o?xi(o,fb(o,a)):0;return{heaveFront:r(t.heaveFrontDesign,e.front),heaveRear:r(t.heaveRearDesign,e.rear),rollFront:n(t.arbFrontDesign,e.front),rollRear:n(t.arbRearDesign,e.rear)}}var db=(e,t)=>e.linkage?Tu(t,e.linkage).atDesign:void 0,fb=(e,t)=>ku(e.design,pb(t,e),0).motionRatio;function Dk(e,t){let r=t.damperSetup,n=t.heaveDamperModel??t.damperModel,o=t.rollDamperModel??t.damperModel,a=(f,p,d)=>{if(!f||!n?.curves.length)return;let h=db(f,p);if(vi(f,h)>0)return ib(n,r?.[d],h??(f.design.kind==="coil"?f.design.motionRatio:1))},s=(f,p,d)=>{if(!f||!o?.curves.length)return;let h=fb(f,p);if(!(xi(f,h)>0))return;let b=pb(p,f)!==null;return cb(o,r?.[d],h,gi(f.design),b&&h>0)},i={},c=a(t.heaveFrontDesign,e.front,"heaveFront"),l=a(t.heaveRearDesign,e.rear,"heaveRear"),u=s(t.arbFrontDesign,e.front,"rollFront"),m=s(t.arbRearDesign,e.rear,"rollRear");return c&&(i.heaveFront=c),l&&(i.heaveRear=l),u&&(i.rollFront=u),m&&(i.rollRear=m),i}function Lu(e,t){let r=t.heaveDamperModel??t.damperModel,n=t.rollDamperModel??t.damperModel,o=(i,c)=>Qn(i)?{source:"none"}:hi(i.config.coilover,c),a=(i,c)=>{if(!i)return{source:"none"};let l=vi(i,db(i,c))>0;return hi(i.coilover,l?r:void 0)},s=(i,c)=>{if(!i||i.design.kind!=="coil")return{source:"none"};let l=xi(i,fb(i,c))>0;return hi(i.coilover,l?n:void 0)};return{front:o(e.front,t.damperModel),rear:o(e.rear,t.damperModelRear??t.damperModel),heaveFront:a(t.heaveFrontDesign,e.front),heaveRear:a(t.heaveRearDesign,e.rear),rollFront:s(t.arbFrontDesign,e.front),rollRear:s(t.arbRearDesign,e.rear)}}function Ek(e){let t=(r,n)=>{let o={};return r?.linkage&&r.design.kind==="coil"&&(o.heave=r.linkage),n?.linkage&&n.design.kind!=="none"&&n.design.kind!=="direct"&&(o.roll=n.linkage,o.rollKind=n.design.kind),o.heave||o.roll?o:void 0};return{front:t(e.heaveFrontDesign,e.arbFrontDesign),rear:t(e.heaveRearDesign,e.arbRearDesign)}}var Qn=e=>e.config.actuation==="decoupled",Jn="a decoupled axle damps in its heave and roll elements, set below";function Ik(e,t,r={}){let n={...t},o=(m,f)=>{let p=n[m];p&&typeof p=="object"&&"value"in p&&(n[m]={...p,value:f})},{front:a,rear:s}=Zn(e,t);a!==void 0&&o("arb_front",a),s!==void 0&&o("arb_rear",s);for(let[m,f,p]of[[t.heaveFrontDesign,e.front,"heave_spring_front"],[t.heaveRearDesign,e.rear,"heave_spring_rear"]]){if(!m||m.design.kind==="none")continue;let d=m.linkage?Tu(f,m.linkage).atDesign:void 0;o(p,wu(m.design,d))}let i=CE(e,t,r),c=wE(e,i);n.kinFront=c.kinFront,n.kinRear=c.kinRear;let l=LE(e,i);n.steerFront=c.steerFront,Number.isFinite(l.ackermannPct)&&o("ackermann_pct",l.ackermannPct);let u=m=>Qn(m)?0:m.measured?.springRate??m.config.springRate;o("spring_front",u(e.front)),o("spring_rear",u(e.rear));for(let[m,f]of[[e.front,"spring_front"],[e.rear,"spring_rear"]])Qn(m)&&(n.readouts={...n.readouts,[f]:"a decoupled axle has no corner spring; its heave and roll elements carry the car"});for(let[m,f]of[[e.front,"damper_front"],[e.rear,"damper_rear"]])Qn(m)&&(o(f,0),n.readouts={...n.readouts,[f]:Jn});return o("mr_front",l.mrFront),o("mr_rear",l.mrRear),o("wheelbase",l.wheelbase),o("track_front",l.trackFront),o("track_rear",l.trackRear),o("rc_front",l.rcFront),o("rc_rear",l.rcRear),n.surveyedRadiusFront=e.front.config.loadedRadius,n.surveyedRadiusRear=e.rear.config.loadedRadius,n.rcRoad={radiusFront:e.front.config.loadedRadius,radiusRear:e.rear.config.loadedRadius,gainFront:l.rcGainFront,gainRear:l.rcGainRear},n}function wE(e,t){return{kinFront:Ck(e.front),kinRear:Ck(e.rear),steerFront:e.front.measured?void 0:Du(e.front,t)}}var wk=new WeakMap;function Ck(e){let t=wk.get(e);return t||wk.set(e,t=oa(e)),t}function CE(e,t,r={}){return TE(e,t,r.front,r.rear)}function TE(e,t,r,n){let o=e.front.config.loadedRadius;if(!((ar(r??t.tireModel)??0)>0))return o;let a={...t,surveyedRadiusFront:o,surveyedRadiusRear:e.rear.config.loadedRadius};return Eu(a,r,n).front??o}var Tk=new WeakMap;function Du(e,t=e.config.loadedRadius){let r=Tk.get(e);r||(r=new Map,Tk.set(e,r));let n=r.get(t);if(n)return n;let o=t===e.config.loadedRadius?void 0:{loadedRadius:t},a=mf(e,Vt(e.config),void 0,void 0,void 0,void 0,o);return r.size>=4&&r.clear(),r.set(t,a),a}var Pk=new WeakMap;function PE(e){return Ke(e,{travelMin:-1,travelMax:1,steps:3}).samples[1].metrics.motionRatio??1}var Cu=e=>e.measured?Sk(e.measured):PE(e);function LE(e,t=e.front.config.loadedRadius){let r=()=>e.front.measured?void 0:Du(e.front,t);return{...DE(e),get steerFront(){return r()},get ackermannPct(){let n=r();return n?pf(n,bt(e.front),e.config.wheelbase):Number.NaN}}}function DE(e){let t=Pk.get(e);if(t)return t;let r=e.front.measured,n=e.rear.measured,a=!r||!n?Br(Ct(e),{heave:0,pitch:0,roll:0,steer:0}):null,s={wheelbase:e.config.wheelbase,trackFront:r?r.track:bt(e.front),trackRear:n?n.track:bt(e.rear),mrFront:Cu(e.front),mrRear:Cu(e.rear),rcFront:r?r.rollCentreHeight:a&&a.front.valid?a.front.heightAboveGround:0,rcRear:n?n.rollCentreHeight:a&&a.rear.valid?a.rear.heightAboveGround:0,rcGainFront:r||!a?0:Ra(a.front),rcGainRear:n||!a?0:Ra(a.rear),rcFrontValid:r?!0:!!a?.front.valid,rcRearValid:n?!0:!!a?.rear.valid};return Pk.set(e,s),s}var xt={open:{kind:"open"},spool:{kind:"spool"},clutch:{kind:"clutch",preloadNm:30,rampDriveDeg:40,rampCoastDeg:50,faces:6,muClutch:.1,rFrictionMm:30.4,rRampMm:36},torsen:{kind:"torsen",tbrDrive:3,tbrCoast:3}},Ok=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),ur=(e,t,r,n=1/0)=>typeof e=="number"&&Number.isFinite(e)?Math.min(n,Math.max(r,e)):t;function eo(e){if(Ok(e))switch(e.kind){case"open":case"spool":return{kind:e.kind};case"clutch":{let t=xt.clutch;return{kind:"clutch",preloadNm:ur(e.preloadNm,t.preloadNm,0),rampDriveDeg:ur(e.rampDriveDeg,t.rampDriveDeg,1,90),rampCoastDeg:ur(e.rampCoastDeg,t.rampCoastDeg,1,90),faces:Math.round(ur(e.faces,t.faces,0)),muClutch:ur(e.muClutch,t.muClutch,0,1),rFrictionMm:ur(e.rFrictionMm,t.rFrictionMm,1),rRampMm:ur(e.rRampMm,t.rRampMm,1)}}case"torsen":{let t=xt.torsen,r=ur(e.preloadNm,0,0);return{kind:"torsen",tbrDrive:ur(e.tbrDrive,t.tbrDrive,1),tbrCoast:ur(e.tbrCoast,t.tbrCoast,1),...r>0?{preloadNm:r}:{}}}default:return}}function Iu(e){if(!Ok(e))return;let t=eo(e.front),r=eo(e.rear);return t||r?{...t?{front:t}:{},...r?{rear:r}:{}}:void 0}function Mi(e){let t=mn(e),r=n=>n>=2?"independent":n===1?"diff":"none";return{front:r(t.front),rear:r(t.rear)}}function Si(e){if(!e.driveline)return;let t=Mi(e),r=e.r_dyn.value,n=s=>{if(t[s]!=="diff")return;let i=eo(e.driveline?.[s]);if(!(!i||i.kind==="independent"))return{kind:i.kind,drive:ri(i,"drive",r),coast:ri(i,"coast",r),hubs:ri(i,"hubs",r)}},o=n("front"),a=n("rear");return o||a?{...o?{front:o}:{},...a?{rear:a}:{}}:void 0}var EE={kind:{label:"Differential"},preloadNm:{label:"Preload",unit:"N\xB7m"},rampDriveDeg:{label:"Drive ramp",unit:"\xB0"},rampCoastDeg:{label:"Coast ramp",unit:"\xB0"},faces:{label:"Friction faces"},muClutch:{label:"Clutch friction \u03BC"},rFrictionMm:{label:"Friction radius",unit:"mm"},rRampMm:{label:"Ramp radius",unit:"mm"},tbrDrive:{label:"Drive bias ratio",unit:": 1"},tbrCoast:{label:"Coast bias ratio",unit:": 1"}},_k=e=>{let t=e==="front"?"Front":"Rear";return Object.fromEntries(Object.entries(EE).map(([r,n])=>[`${e}.${r}`,{section:t,...n}]))},_u={..._k("front"),..._k("rear")},Nk=e=>e.motorModel?.kind==="ice"?e.motorPlacement==="front"?"front":"rear":null;function Vk(e,t){let r=Nk(t);if(!(!r||Nk(e)===r||t.driveline?.[r]))return{...t.driveline,[r]:{...xt.clutch}}}function Gt(e,t,r,n){return e>0?!(r>0)||!Number.isFinite(r)?e:Math.max(1,e-t/r):n}function Nu(e,t,r){let n=Math.max(0,Math.min(1,r)),o=Gt(e.freeRadius,e.staticLoad,e.tyreRate,e.surveyed),a=Gt(t.freeRadius,t.staticLoad,t.tyreRate,t.surveyed);return n*o+(1-n)*a}function ka(e,t,r){if(t===void 0||r===void 0||!Number.isFinite(t)||!Number.isFinite(r))return e;let n=r-t;return n===0?e:Math.max(1,e+n)}function $r(e,t,r,n){if(!t||r===void 0||n===void 0||!Number.isFinite(r)||!Number.isFinite(n))return e;let o=n-r;return o===0?e:e+t*o}function Ai(e,t){if(!e)return _E(t);let r=t-cn(e,0).camber;return r?{...e,camber:e.camber.map(n=>n+r)}:e}function IE(e){return{kinFront:Ai(e.kinFront,Q(e,"camber_front_deg")),kinRear:Ai(e.kinRear,Q(e,"camber_rear_deg"))}}function _E(e){let t=[-40,0,40];return{travel:t,motionRatio:t.map(()=>1),camber:t.map(()=>e),toe:t.map(()=>0),damperLen:t.map(()=>0)}}var Bk=9.81,$k=e=>e>1?e/100:e;function Ma(e,t,r){let n=t??e.tireModel??Gs(),o=r??e.tireModelRear??n,a={grip:Q(e,"grip_scale"),stiffness:Q(e,"stiffness_scale")},s=Gl(n,a);return{front:s,rear:o===n?s:Gl(o,a)}}function mr(e,t,r){let n=Ma(e,t,r),o=Pe(n.front);return ut(n.rear===n.front?o:Ll(o,Pe(n.rear)))}function hb(e,t,r){let n=$k(e.front_mass_diss.value),o=Ma(e,t,r),a=Pe(o.front),s=o.rear===o.front?a:Pe(o.rear),i=t??e.tireModel,c=r??e.tireModelRear??i,l=e.m.value*Bk*n/2,u=e.m.value*Bk*(1-n)/2,m=(i?a.verticalStiffness():0)||Q(e,"tire_vertical_rate"),f=(c?s.verticalStiffness():0)||Q(e,"tire_vertical_rate"),p=ar(i)??0,d=ar(c)??0,h=e.surveyedRadiusFront&&e.surveyedRadiusRear?Nu({freeRadius:p,staticLoad:l,tyreRate:m,surveyed:e.surveyedRadiusFront},{freeRadius:d,staticLoad:u,tyreRate:f,surveyed:e.surveyedRadiusRear},n):void 0,b=e.surveyedRadiusFront?Gt(p,l,m,e.surveyedRadiusFront):void 0,g=e.surveyedRadiusRear?Gt(d,u,f,e.surveyedRadiusRear):void 0;return{ev:a,evR:s,Wf:l,Wr:u,tireRate:m,tireRateRear:f,tyreFreeRadius:p,tyreFreeRadiusRear:d,cgStandingRadius:h,standingFront:b,standingRear:g}}function Eu(e,t,r){let n=hb(e,t,r);return{front:n.standingFront,rear:n.standingRear}}function Gk(e,t,r){return hb(e,t,r).cgStandingRadius}function dt(e,t,r){let n=$k(e.front_mass_diss.value),o=Q(e,"mr_front")||1,a=Q(e,"mr_rear")||1,{ev:s,evR:i,Wf:c,Wr:l,tireRate:u,tireRateRear:m,tyreFreeRadius:f,tyreFreeRadiusRear:p,cgStandingRadius:d,standingFront:h,standingRear:b}=hb(e,t,r),g=ei(e),y=Si(e),R=qn(e.damperModel,e.damperSetup,o,a,e.damperModelRear??e.damperModel),k=e.readouts?.damper_front===Jn,v=e.readouts?.damper_rear===Jn,x={rho:e.rho.value,area:e.A.value,cl:e.c_l.value,cw:e.c_w.value,copLongFront:1-Math.max(0,Math.min(1,Q(e,"cop_long"))),copHeight:Q(e,"cop_height"),...e.aeroModel?{model:e.aeroModel}:{},rideHeightFront:Q(e,"ride_height_front"),rideHeightRear:Q(e,"ride_height_rear")};return{massTotal:e.m.value,frontMassFrac:n,steeringSystem:e.steeringSystem,tv:gu(e),cgHeight:ka(Q(e,"cg_height"),e.cgReference?.standingRadius,d),...d!==void 0?{cgStandingRadius:d}:{},wheelbase:Q(e,"wheelbase"),trackFront:Q(e,"track_front"),trackRear:Q(e,"track_rear"),wheelRateFront:Q(e,"spring_front")*o*o,wheelRateRear:Q(e,"spring_rear")*a*a,tireRate:u,...m!==u?{tireRateRear:m}:{},tireDamping:Q(e,"tire_vertical_damping"),arbFront:Q(e,"arb_front"),arbRear:Q(e,"arb_rear"),brakeBalanceFront:g.balanceFront,brakes:g,...y?{driveline:y}:{},heaveSpringFront:Q(e,"heave_spring_front"),heaveSpringRear:Q(e,"heave_spring_rear"),unsprungPerCorner:Q(e,"unsprung_mass"),unsprungCgHeight:NE(e,{Wf:c,Wr:l,tireRate:u,tireRateRear:m,tyreFreeRadius:f,tyreFreeRadiusRear:p,standingFront:h,standingRear:b}),tyreFreeRadius:f,...p!==f?{tyreFreeRadiusRear:p}:{},rcHeightFront:$r(Q(e,"rc_front"),e.rcRoad?.gainFront,e.rcRoad?.radiusFront,h),rcHeightRear:$r(Q(e,"rc_rear"),e.rcRoad?.gainRear,e.rcRoad?.radiusRear,b),corneringStiffnessFront:s.corneringStiffness(c),corneringStiffnessRear:i.corneringStiffness(l),damperFront:R?.front&&!k?R.front.rate:Q(e,"damper_front")*o*o,damperRear:R?.rear&&!v?R.rear.rate:Q(e,"damper_rear")*a*a,...R?.front&&!k?{damperCurveFront:R.front.curve}:{},...R?.rear&&!v?{damperCurveRear:R.rear.curve}:{},aero:x,ackermannPct:Q(e,"ackermann_pct"),toeFrontDeg:Q(e,"toe_front_deg"),toeRearDeg:Q(e,"toe_rear_deg"),yawInertia:Q(e,"I_yaw"),steerFront:e.steerFront,...IE(e)}}function NE(e,t){let r=(a,s,i,c)=>a??(s>0?Gt(s,i,c,s):void 0),n=r(t.standingFront,t.tyreFreeRadius,t.Wf,t.tireRate),o=r(t.standingRear,t.tyreFreeRadiusRear,t.Wr,t.tireRateRear);return n!==void 0&&o!==void 0?.5*(n+o):n??o??e.r_dyn.value*1e3}var Ou={capacity:"the battery model\u2019s pack charge \u2014 cells in parallel \xD7 cell capacity",ocv:"the battery model\u2019s pack voltage at full charge"};function Kk(e,t=e.batteryModel){if(!t)return e;let r=xr(t),n=(o,a)=>({...o,value:a});return{...e,capacity:n(e.capacity,r.capacityAh),ocv:n(e.ocv,r.voltageAtFull)}}var zk={damper_front:`the damper part sets it: its front curve at ${bn} mm/s`,damper_rear:`the damper part sets it (the rear's own, where the car names one): its rear curve at ${bn} mm/s`};function Vu(e){let t=!!(e.damperModelId||e.damperModel),r=t||!!(e.damperModelIdRear||e.damperModelRear);return{...t?{damper_front:zk.damper_front}:{},...r?{damper_rear:zk.damper_rear}:{}}}function Yk(e,t=e.damperModel,r=e.damperModelRear??t){if(!t&&!r)return e;let n=Q(e,"mr_front")||1,o=Q(e,"mr_rear")||1,a=qn(t,e.damperSetup,n,o,r);if(!a)return e;let s=(c,l,u)=>({...c??{label:l,unit:"N\xB7s/mm"},value:u}),i={...e};return a.front&&e.readouts?.damper_front!==Jn&&(i.damper_front=s(e.damper_front,"damper front",a.front.rate/(n*n))),a.rear&&e.readouts?.damper_rear!==Jn&&(i.damper_rear=s(e.damper_rear,"damper rear",a.rear.rate/(o*o))),i}var Wk={how:"scripts/paramTiers.ts: each row \xB120 % (switches flipped, springs on the suspension), first car of every gallery template, largest change to any event time, % of it",templates:["fs-ev-comparison","fs-ev-single","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor","formula-1","touring-car","street-car","cup-car","stock-car","hill-climb","suspension","direct-coilover","pushrod","pullrod","third-spring","mcpherson-strut","tyre-study"],rows:{endurance_reserve:{group:"Powertrain",score:"infinite",byTemplate:{"fs-ev-comparison":"infinite","fs-ev-single":"infinite","fs-combustion":null,"fs-ev-awd":0,"fs-ev-rwd-hubs":"infinite","fs-ev-one-motor":"infinite","formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:0,"direct-coilover":null,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":null,"tyre-study":"infinite"}},gear_ratio:{group:"Powertrain",score:11.9893,byTemplate:{"fs-ev-comparison":11.9893,"fs-ev-single":11.9893,"fs-combustion":5.6255,"fs-ev-awd":5.8819,"fs-ev-rwd-hubs":11.5358,"fs-ev-one-motor":7.2758,"formula-1":.2473,"touring-car":.2195,"street-car":.0998,"cup-car":.2431,"stock-car":.0645,"hill-climb":3.1703,suspension:1.8984,"direct-coilover":.2195,pushrod:1.9001,pullrod:1.9126,"third-spring":1.9001,"mcpherson-strut":.111,"tyre-study":11.9893}},driven_wheels:{group:"Powertrain",score:11.9893,byTemplate:{"fs-ev-comparison":11.9893,"fs-ev-single":11.9893,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:1.9216,"direct-coilover":0,pushrod:1.9171,pullrod:1.919,"third-spring":1.9171,"mcpherson-strut":0,"tyre-study":11.9893}},power_scale:{group:"Powertrain",score:11.9893,byTemplate:{"fs-ev-comparison":11.9893,"fs-ev-single":11.9893,"fs-combustion":10.2883,"fs-ev-awd":4.2843,"fs-ev-rwd-hubs":11.6138,"fs-ev-one-motor":7.2758,"formula-1":2.6682,"touring-car":2.5337,"street-car":1.938,"cup-car":2.6155,"stock-car":1.2193,"hill-climb":1.869,suspension:1.9216,"direct-coilover":2.5337,pushrod:1.9171,pullrod:1.919,"third-spring":1.9171,"mcpherson-strut":1.9778,"tyre-study":11.9893}},grip_scale:{group:"Tyres",score:11.4886,byTemplate:{"fs-ev-comparison":10.9135,"fs-ev-single":10.9135,"fs-combustion":11.4886,"fs-ev-awd":11.3513,"fs-ev-rwd-hubs":11.3513,"fs-ev-one-motor":11.3905,"formula-1":10.9225,"touring-car":7.4484,"street-car":7.2578,"cup-car":7.1946,"stock-car":10.4642,"hill-climb":9.5384,suspension:8.3679,"direct-coilover":7.4484,pushrod:8.3929,pullrod:8.3807,"third-spring":8.3929,"mcpherson-strut":7.35,"tyre-study":10.9135}},front_mass_diss:{group:"Mass & chassis",score:10.3816,byTemplate:{"fs-ev-comparison":1.1854,"fs-ev-single":1.1854,"fs-combustion":1.5398,"fs-ev-awd":1.9682,"fs-ev-rwd-hubs":1.9682,"fs-ev-one-motor":4.5048,"formula-1":5.2182,"touring-car":1.241,"street-car":3.5067,"cup-car":.7277,"stock-car":2.2367,"hill-climb":10.3816,suspension:.5046,"direct-coilover":1.241,pushrod:.4796,pullrod:.4587,"third-spring":.4796,"mcpherson-strut":3.4131,"tyre-study":1.1854}},m:{group:"Mass & chassis",score:9.7815,byTemplate:{"fs-ev-comparison":9.7815,"fs-ev-single":9.7815,"fs-combustion":7.2245,"fs-ev-awd":5.6765,"fs-ev-rwd-hubs":9.2239,"fs-ev-one-motor":7.0296,"formula-1":5.3736,"touring-car":3.7044,"street-car":1.9146,"cup-car":2.6724,"stock-car":3.7623,"hill-climb":5.4157,suspension:3.8549,"direct-coilover":3.7044,pushrod:3.8507,pullrod:3.8527,"third-spring":3.8507,"mcpherson-strut":1.9399,"tyre-study":9.7815}},cop_long:{group:"Aerodynamics",score:6.6543,byTemplate:{"fs-ev-comparison":1.032,"fs-ev-single":1.032,"fs-combustion":1.0669,"fs-ev-awd":1.0452,"fs-ev-rwd-hubs":1.0452,"fs-ev-one-motor":1.0521,"formula-1":5.9878,"touring-car":.1327,"street-car":.0018,"cup-car":.2696,"stock-car":.6469,"hill-climb":6.6543,suspension:.3644,"direct-coilover":.1327,pushrod:.3575,pullrod:.355,"third-spring":.3575,"mcpherson-strut":.0072,"tyre-study":1.032}},front_aero_diss:{group:"Aerodynamics",score:5.2168,byTemplate:{"fs-ev-comparison":.9064,"fs-ev-single":.9064,"fs-combustion":.8657,"fs-ev-awd":.8967,"fs-ev-rwd-hubs":.8967,"fs-ev-one-motor":.8574,"formula-1":4.2912,"touring-car":.0708,"street-car":.0018,"cup-car":.2207,"stock-car":.5291,"hill-climb":5.2168,suspension:.2835,"direct-coilover":.0708,pushrod:.2831,pullrod:.2823,"third-spring":.2831,"mcpherson-strut":.0072,"tyre-study":.9064}},power_limit_kw:{group:"Powertrain",score:4.5916,byTemplate:{"fs-ev-comparison":.4828,"fs-ev-single":.4828,"fs-combustion":null,"fs-ev-awd":4.5916,"fs-ev-rwd-hubs":.5453,"fs-ev-one-motor":3.6198,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:.0626,"direct-coilover":null,pushrod:.0625,pullrod:.0626,"third-spring":.0625,"mcpherson-strut":null,"tyre-study":.4828}},soc:{group:"Powertrain",score:3.5618,byTemplate:{"fs-ev-comparison":3.2245,"fs-ev-single":3.2245,"fs-combustion":0,"fs-ev-awd":1.6179,"fs-ev-rwd-hubs":3.3095,"fs-ev-one-motor":3.5618,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":3.2245}},effi_pgb:{group:"Powertrain",score:3.5269,byTemplate:{"fs-ev-comparison":3.5269,"fs-ev-single":3.5269,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:.0626,"direct-coilover":0,pushrod:.0625,pullrod:.0626,"third-spring":.0625,"mcpherson-strut":0,"tyre-study":3.5269}},c_l:{group:"Aerodynamics",score:3.4342,byTemplate:{"fs-ev-comparison":.9751,"fs-ev-single":.9751,"fs-combustion":.9539,"fs-ev-awd":1.0777,"fs-ev-rwd-hubs":.9886,"fs-ev-one-motor":1.0797,"formula-1":3.4342,"touring-car":.8979,"street-car":.0715,"cup-car":.2158,"stock-car":.5467,"hill-climb":1.2705,suspension:.9751,"direct-coilover":.8979,pushrod:.9734,pullrod:.9708,"third-spring":.9734,"mcpherson-strut":.0704,"tyre-study":.9751}},ocv:{group:"Powertrain",score:3.3244,byTemplate:{"fs-ev-comparison":3.0446,"fs-ev-single":3.0446,"fs-combustion":0,"fs-ev-awd":1.4595,"fs-ev-rwd-hubs":3.1854,"fs-ev-one-motor":3.3244,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":3.0446}},capacity:{group:"Powertrain",score:3.3244,byTemplate:{"fs-ev-comparison":3.0446,"fs-ev-single":3.0446,"fs-combustion":0,"fs-ev-awd":1.4595,"fs-ev-rwd-hubs":3.1854,"fs-ev-one-motor":3.3244,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":3.0446}},A:{group:"Aerodynamics",score:2.3707,byTemplate:{"fs-ev-comparison":.802,"fs-ev-single":.802,"fs-combustion":.7928,"fs-ev-awd":.9333,"fs-ev-rwd-hubs":.7926,"fs-ev-one-motor":.961,"formula-1":2.3707,"touring-car":.6374,"street-car":.4904,"cup-car":.2428,"stock-car":.1932,"hill-climb":1.1486,suspension:.802,"direct-coilover":.6374,pushrod:.7991,pullrod:.7982,"third-spring":.7991,"mcpherson-strut":.4873,"tyre-study":.802}},rho:{group:"Aerodynamics",score:2.3707,byTemplate:{"fs-ev-comparison":.802,"fs-ev-single":.802,"fs-combustion":.7928,"fs-ev-awd":.9333,"fs-ev-rwd-hubs":.7926,"fs-ev-one-motor":.961,"formula-1":2.3707,"touring-car":.6374,"street-car":.4904,"cup-car":.2428,"stock-car":.1932,"hill-climb":0,suspension:.802,"direct-coilover":.6374,pushrod:.7991,pullrod:.7982,"third-spring":.7991,"mcpherson-strut":.4873,"tyre-study":.802}},cg_height:{group:"Mass & chassis",score:2.2005,byTemplate:{"fs-ev-comparison":1.8282,"fs-ev-single":1.8282,"fs-combustion":1.6978,"fs-ev-awd":2.2005,"fs-ev-rwd-hubs":1.8919,"fs-ev-one-motor":1.9269,"formula-1":.6248,"touring-car":1.2858,"street-car":1.4681,"cup-car":.992,"stock-car":1.2052,"hill-climb":.6037,suspension:1.8282,"direct-coilover":1.2858,pushrod:1.8142,pullrod:1.8229,"third-spring":1.8142,"mcpherson-strut":1.7176,"tyre-study":1.8282}},l_to_d_ratio:{group:"Aerodynamics",score:1.4351,byTemplate:{"fs-ev-comparison":.7905,"fs-ev-single":.7905,"fs-combustion":.6962,"fs-ev-awd":.5843,"fs-ev-rwd-hubs":.8444,"fs-ev-one-motor":.9611,"formula-1":1.4351,"touring-car":.3671,"street-car":.528,"cup-car":.5631,"stock-car":.4634,"hill-climb":.2349,suspension:.2456,"direct-coilover":.3671,pushrod:.2491,pullrod:.2456,"third-spring":.2491,"mcpherson-strut":.5265,"tyre-study":.7905}},tv_enabled:{group:"Torque vectoring",score:1.2381,byTemplate:{"fs-ev-comparison":1.2381,"fs-ev-single":1.2381,"fs-combustion":0,"fs-ev-awd":1.2293,"fs-ev-rwd-hubs":1.2293,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":.1209,"cup-car":.1617,"stock-car":0,"hill-climb":9e-4,suspension:.3086,"direct-coilover":0,pushrod:.2933,pullrod:.3089,"third-spring":.2933,"mcpherson-strut":.1326,"tyre-study":1.2381}},c_w:{group:"Aerodynamics",score:1.1499,byTemplate:{"fs-ev-comparison":.6319,"fs-ev-single":.6319,"fs-combustion":.5577,"fs-ev-awd":.462,"fs-ev-rwd-hubs":.6559,"fs-ev-one-motor":.7504,"formula-1":1.1499,"touring-car":.2914,"street-car":.4211,"cup-car":.4486,"stock-car":.3694,"hill-climb":.1625,suspension:.1945,"direct-coilover":.2914,pushrod:.1979,pullrod:.1948,"third-spring":.1979,"mcpherson-strut":.4196,"tyre-study":.6319}},brake_balance:{group:"Brakes",score:1.0132,byTemplate:{"fs-ev-comparison":.8303,"fs-ev-single":.8303,"fs-combustion":.6932,"fs-ev-awd":.9772,"fs-ev-rwd-hubs":.8148,"fs-ev-one-motor":1.0132,"formula-1":.97,"touring-car":.9585,"street-car":.7184,"cup-car":.1468,"stock-car":.0764,"hill-climb":.9096,suspension:.8303,"direct-coilover":.9585,pushrod:.8578,pullrod:.8454,"third-spring":.8578,"mcpherson-strut":.7099,"tyre-study":.8303}},stiffness_scale:{group:"Tyres",score:.871,byTemplate:{"fs-ev-comparison":.5088,"fs-ev-single":.5088,"fs-combustion":.4874,"fs-ev-awd":.3745,"fs-ev-rwd-hubs":.4753,"fs-ev-one-motor":.5706,"formula-1":.5776,"touring-car":.4346,"street-car":.1077,"cup-car":.4012,"stock-car":.1613,"hill-climb":.871,suspension:.5088,"direct-coilover":.4346,pushrod:.5253,pullrod:.5172,"third-spring":.5253,"mcpherson-strut":.1518,"tyre-study":.5088}},cop_height:{group:"Aerodynamics",score:.2837,byTemplate:{"fs-ev-comparison":.155,"fs-ev-single":.155,"fs-combustion":.1546,"fs-ev-awd":.1557,"fs-ev-rwd-hubs":.1557,"fs-ev-one-motor":.1542,"formula-1":.1173,"touring-car":.0072,"street-car":.0023,"cup-car":.0745,"stock-car":.1568,"hill-climb":.2837,suspension:.0421,"direct-coilover":.0072,pushrod:.0437,pullrod:.04,"third-spring":.0437,"mcpherson-strut":.0076,"tyre-study":.155}},spring_rear:{group:"Suspension",score:.2822,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":.0355,"touring-car":.1169,"street-car":.2242,"cup-car":.0902,"stock-car":.2822,"hill-climb":.1929,suspension:0,"direct-coilover":.1169,pushrod:.1142,pullrod:.2148,"third-spring":.1142,"mcpherson-strut":.1786,"tyre-study":0}},spring_front:{group:"Suspension",score:.2388,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":.0189,"touring-car":.0958,"street-car":.2388,"cup-car":.1462,"stock-car":.1719,"hill-climb":.1873,suspension:0,"direct-coilover":.0958,pushrod:.1257,pullrod:.0612,"third-spring":.1257,"mcpherson-strut":.1911,"tyre-study":0}},arb_front:{group:"Suspension",score:.1792,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":.0235,"touring-car":.0589,"street-car":.1792,"cup-car":.0215,"stock-car":.0926,"hill-climb":.1095,suspension:null,"direct-coilover":.0589,pushrod:.0455,pullrod:.049,"third-spring":.0455,"mcpherson-strut":.1435,"tyre-study":null}},fr_0:{group:"Tyres",score:.158,byTemplate:{"fs-ev-comparison":.158,"fs-ev-single":.158,"fs-combustion":.1097,"fs-ev-awd":.0708,"fs-ev-rwd-hubs":.1442,"fs-ev-one-motor":.1168,"formula-1":.07,"touring-car":.0492,"street-car":.1006,"cup-car":.065,"stock-car":.0262,"hill-climb":.0334,suspension:.0217,"direct-coilover":.0492,pushrod:.0229,pullrod:.0223,"third-spring":.0229,"mcpherson-strut":.0989,"tyre-study":.158}},arb_rear:{group:"Suspension",score:.1047,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":.0224,"touring-car":.0365,"street-car":.0832,"cup-car":.1047,"stock-car":.0436,"hill-climb":.0734,suspension:null,"direct-coilover":.0365,pushrod:.0411,pullrod:.0332,"third-spring":.0411,"mcpherson-strut":.0643,"tyre-study":null}},unsprung_mass:{group:"Mass & chassis",score:.102,byTemplate:{"fs-ev-comparison":.0477,"fs-ev-single":.0477,"fs-combustion":.0512,"fs-ev-awd":.0545,"fs-ev-rwd-hubs":.0514,"fs-ev-one-motor":.0799,"formula-1":.0313,"touring-car":.0471,"street-car":.102,"cup-car":.0315,"stock-car":.042,"hill-climb":.0278,suspension:.0477,"direct-coilover":.0471,pushrod:.0452,pullrod:.0468,"third-spring":.0452,"mcpherson-strut":.0876,"tyre-study":.0477}},camber_front_deg:{group:"Steering & alignment",score:.0576,byTemplate:{"fs-ev-comparison":.0065,"fs-ev-single":.0065,"fs-combustion":.008,"fs-ev-awd":.0075,"fs-ev-rwd-hubs":.0075,"fs-ev-one-motor":.0098,"formula-1":.0358,"touring-car":.0272,"street-car":.0025,"cup-car":.0191,"stock-car":.0576,"hill-climb":.0389,suspension:.0019,"direct-coilover":.0272,pushrod:.0017,pullrod:.0016,"third-spring":.0017,"mcpherson-strut":.002,"tyre-study":.0065}},camber_rear_deg:{group:"Steering & alignment",score:.0262,byTemplate:{"fs-ev-comparison":.0081,"fs-ev-single":.0081,"fs-combustion":.0085,"fs-ev-awd":.0054,"fs-ev-rwd-hubs":.0096,"fs-ev-one-motor":.0097,"formula-1":.0028,"touring-car":.0106,"street-car":8e-4,"cup-car":5e-4,"stock-car":.0035,"hill-climb":.0262,suspension:.0081,"direct-coilover":.0106,pushrod:.0082,pullrod:.0083,"third-spring":.0082,"mcpherson-strut":3e-4,"tyre-study":.0081}},I_yaw:{group:"Mass & chassis",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},I_roll:{group:"Mass & chassis",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},I_pitch:{group:"Mass & chassis",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},ride_height_front:{group:"Aerodynamics",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},ride_height_rear:{group:"Aerodynamics",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tire_vertical_rate:{group:"Tyres",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tire_vertical_damping:{group:"Tyres",score:0,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":0,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},r_dyn:{group:"Tyres",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},damper_front:{group:"Suspension",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},damper_rear:{group:"Suspension",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_kp:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_ff_low:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_ff_high:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_v_low:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_v_high:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},wheelbase:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},track_front:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},track_rear:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},rc_front:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},rc_rear:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},I_wheel:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},I_rotor:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},v_limit_endurance:{group:"Powertrain",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},mr_front:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},mr_rear:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},heave_spring_front:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},heave_spring_rear:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},toe_front_deg:{group:"Steering & alignment",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},toe_rear_deg:{group:"Steering & alignment",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},ackermann_pct:{group:"Steering & alignment",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}}}};function Gr(e){return!!e&&typeof e=="object"&&"value"in e&&"label"in e}var $E={Batteriekapazit\u00E4t:"pack capacity",Rollwiderstandsbeiwert:"rolling-resistance coefficient"},Uk=e=>$E[e]??e;function Bu(e){let t=[];for(let r of Object.keys(e)){if(r==="motor"||r==="name")continue;let n=e[r];Gr(n)&&t.push({key:r,label:Uk(n.label),value:n.value,unit:n.unit})}return t}var GE=[{title:"Mass & chassis",keys:["m","front_mass_diss","cg_height","unsprung_mass","wheelbase","track_front","track_rear","rc_front","rc_rear","I_yaw","I_roll","I_pitch","I_wheel","I_rotor"]},{title:"Aerodynamics",keys:["A","c_l","c_w","l_to_d_ratio","front_aero_diss","cop_long","cop_height","ride_height_front","ride_height_rear","rho"]},{title:"Tyres",keys:["grip_scale","stiffness_scale","tire_vertical_rate","tire_vertical_damping","fr_0","r_dyn"]},{title:"Powertrain",keys:["gear_ratio","driven_wheels","effi_pgb","power_scale","power_limit_kw","v_limit_endurance","endurance_reserve","capacity","ocv","soc"]},{title:"Suspension",keys:["spring_front","spring_rear","mr_front","mr_rear","arb_front","arb_rear","heave_spring_front","heave_spring_rear","damper_front","damper_rear"]},{title:"Steering & alignment",keys:["camber_front_deg","camber_rear_deg","toe_front_deg","toe_rear_deg","ackermann_pct"]},{title:"Brakes",keys:["brake_balance"]},{title:"Torque vectoring",keys:["tv_enabled","tv_kp","tv_ff_low","tv_ff_high","tv_v_low","tv_v_high"]}],KE=.5,jk=e=>e==="infinite"?1/0:typeof e=="number"?e:null,HE=e=>/front/.test(e)?e.replace("front","rear"):/rear/.test(e)?e.replace("rear","front"):null,zX=(()=>{let e=Wk.rows,t=o=>{let a=HE(o),s=jk(e[o]?.score),i=a&&e[a]?jk(e[a].score):null;return s==null?i:i==null?s:Math.max(s,i)},r=new Set,n=new Map;for(let[o,a]of Object.entries(e)){let s=t(o);s!=null&&(s>=KE&&r.add(o),n.set(a.group,Math.max(n.get(a.group)??0,s)))}for(let[o,a]of Object.entries(e)){let s=t(o);s!=null&&s>0&&s===n.get(a.group)&&r.add(o)}return r})();var bb={wheelbase:"set by the axle positions in Kinematics",track_front:"twice the front wheel-centre Y",track_rear:"twice the rear wheel-centre Y",rc_front:"solved from the front wishbones, on the fitted tyre",rc_rear:"solved from the rear wishbones, on the fitted tyre",mr_front:"damper travel per mm of front wheel travel, from the linkage",mr_rear:"damper travel per mm of rear wheel travel, from the linkage",spring_front:"the front corner spring rate, stored on the suspension the car runs",spring_rear:"the rear corner spring rate, stored on the suspension the car runs",ackermann_pct:"solved from the rack and tie rods, read near centre"};function Xk(e){let t=new Map;for(let a of Bu(e))t.set(a.key,a);let r=new Set,n=[];for(let a of GE){let s=[];for(let i of a.keys){let c=t.get(i);c&&(s.push(c),r.add(i))}s.length&&n.push({title:a.title,rows:s})}let o=Bu(e).filter(a=>!r.has(a.key));return o.length&&n.push({title:"Other",rows:o}),n}var gb={A:"the aero model's reference area",c_l:"read off the aero model at the ride heights",c_w:"read off the aero model at the ride heights",l_to_d_ratio:"read off the aero model at the ride heights",front_aero_diss:"the aero model's front and rear coefficients set the balance",cop_long:"the aero model's front and rear coefficients set the balance"},yb={ride_height_front:"reaches nothing until an aero model is attached at the head of the Aerodynamics group",ride_height_rear:"reaches nothing until an aero model is attached at the head of the Aerodynamics group"},qk=e=>!!(e.aeroModelId||e.aeroModel);function zE(e){let t=n=>n!=null&&n.design.kind!=="none",r={};return t(e.arbFrontDesign)&&(r.arb_front="the front anti-roll bar design sets it"),t(e.arbRearDesign)&&(r.arb_rear="the rear anti-roll bar design sets it"),t(e.heaveFrontDesign)&&(r.heave_spring_front="the front third-spring design sets it"),t(e.heaveRearDesign)&&(r.heave_spring_rear="the rear third-spring design sets it"),r}var YE=e=>!!(e.batteryModelId||e.batteryModel);function WE(e,t){let r={};return t.geometry&&Object.assign(r,bb,zE(e)),qk(e)&&Object.assign(r,gb),YE(e)&&Object.assign(r,Ou),Object.assign(r,Vu(e)),e.readouts&&Object.assign(r,e.readouts),r}function Qk(e,t){let r=WE(e,t);return qk(e)||Object.assign(r,yb),r}function xb(e){let t=e.cop_long;return Gr(t)?1-t.value:.5}function jE(e,t){let r=e.front_aero_diss,n=e.cop_long;!Gr(r)||!Gr(n)||(t===r.label?n.value=1-r.value:t===n.label&&(r.value=1-n.value))}function UE(e,t){jE(e,t);let r=e.c_l,n=e.c_w,o=e.l_to_d_ratio;!Gr(r)||!Gr(n)||(t===r.label||t===n.label?Gr(o)&&n.value!==0&&(o.value=r.value/n.value):Gr(o)&&t===o.label&&o.value!==0&&(n.value=r.value/o.value))}function $u(e,t,r){let n=!1;for(let o of Object.keys(e)){if(o==="motor"||o==="name")continue;let a=e[o];if(Gr(a)&&Uk(a.label)===t){a.value=r,n=!0;break}}return n&&UE(e,t),n}function Gu(e,t,r=0,n,o){let a=()=>({cl:e.c_l.value,cw:e.c_w.value,frontShare:xb(e),A:e.A.value,platform:null});if(!e.aeroModel)return a();let s=vr(n??dt(e),t,r,o);if(!s)return a();let i=s.clFront+s.clRear;return{cl:i,cw:s.cd,frontShare:i!==0?s.clFront/i:xb(e),A:s.area,platform:s}}var Zk=e=>typeof e=="object"&&e!==null&&typeof e.value=="number"&&typeof e.label=="string";function Jk(e,t=e.aeroModel){if(!t)return e;let r=Zr(t,{wheelbase:Q(e,"wheelbase")}).at(Q(e,"ride_height_front"),Q(e,"ride_height_rear")),{cl:n,balanceFront:o}=pd(r),a=(i,c,l)=>({...i??c,value:l}),s={...e,A:a(e.A,e.A,t.area),c_l:a(e.c_l,e.c_l,n),c_w:a(e.c_w,e.c_w,r.cd),front_aero_diss:a(e.front_aero_diss,e.front_aero_diss,o),cop_long:a(Zk(e.cop_long)?e.cop_long:void 0,cr.cop_long,1-o)};return Zk(e.l_to_d_ratio)&&(s.l_to_d_ratio={...e.l_to_d_ratio,value:r.cd!==0?n/r.cd:0}),s}var Fi={dsTarget:.25,accelStep:.25,vTol:.002,scanSteps:24,seamIters:8,fitSpacing:1},XE=32;function eM(e,t,r){let n=Math.round(e/t);return Math.max(1,Math.min(Number.isFinite(n)?n:1,Math.floor(r/XE)||1))}function st(e){let t=Fi,r=(n,o,a)=>{let s=Number(n);return Number.isFinite(s)&&s>=a?s:o};return{dsTarget:r(e?.dsTarget,t.dsTarget,.001),accelStep:r(e?.accelStep,t.accelStep,.001),vTol:r(e?.vTol,t.vTol,1e-6),scanSteps:Math.max(4,Math.round(r(e?.scanSteps,t.scanSteps,4))),seamIters:Math.max(1,Math.round(r(e?.seamIters,t.seamIters,1))),fitSpacing:r(e?.fitSpacing,t.fitSpacing,0)}}var tM=Math.PI/180,Ku=.02,rM=new WeakMap;function wi(e){let t=rM.get(e);if(t!==void 0)return t;let r=e.npts,n=new Array(r),o=new Array(r),a=!1;for(let i=0;i<r;i++){let c=(e.gradient?.[i]??0)*tM,l=(e.bank?.[i]??0)*tM,u=e.verticalCurvature?.[i]??0;n[i]=c===0&&l===0?1:Math.cos(c)*Math.cos(l),o[i]=(u-e.curvature[i]*Math.sin(l))/9.81,(n[i]!==1||o[i]!==0)&&(a=!0)}let s=a?{n0:n,k:o}:null;return rM.set(e,s),s}function Hu(e,t,r){return e.n0[t]+e.k[t]*r*r}function nM(e,t){return e.k[t]<0?Math.sqrt(Math.max(0,e.n0[t])/-e.k[t]):1/0}function oM(e,t){if(!e)return null;let r=1/0,n=-1/0;for(let o=0;o<e.n0.length;o++){let a=Hu(e,o,t[o]??0);a<r&&(r=a),a>n&&(n=a)}return r>=1-Ku&&n<=1+Ku?null:{lo:r,hi:n}}var Sa=[.1,.25,.5,.75,1,1.25,1.5,2,2.5];function aM(e){let t=e.lo>=1-Ku?1:1-1.25*(1-e.lo)-.05,r=e.hi<=1+Ku?1:1+1.25*(e.hi-1)+.05,n=[...Sa].reverse().find(a=>a<=t)??Sa[0],o=Sa.find(a=>a>=r)??Sa[Sa.length-1];return Sa.filter(a=>a>=n&&a<=o)}function Rb(e,t,r){return r<1?Math.max(e,t):Math.min(e,t)}function sM(e,t,r,n){let o=e.n0.length;return a=>{let s=n?n(a):r,i=a%o;if(e.n0[i]===1&&e.k[i]===0)return s;let c=e.n0[i],l=e.k[i],u=m=>c+l*m*m;return n?{vMax:s.vMax,axAccel:(m,f,p=1,d=1)=>s.axAccel(m,f,p,d)+t.axAccel(u(m),m,f,p,d)-r.axAccel(m,f,p,d),axDecel:(m,f,p=1,d=1)=>{let h=b=>s.axDecel(m,f,p,b)+t.axDecel(u(m),m,f,p,b)-r.axDecel(m,f,p,b);return d===1?h(1):Rb(h(d),h(1),d)},ay:(m,f,p=1)=>Math.max(0,s.ay(m,f,p)+t.ay(u(m),m,f,p)-r.ay(m,f,p)),scrub:(m,f,p=1)=>(s.scrub?.(m,f,p)??0)+t.scrub(u(m),m,f,p)-(r.scrub?.(m,f,p)??0)}:{vMax:s.vMax,axAccel:(m,f,p=1,d=1)=>t.axAccel(u(m),m,f,p,d),axDecel:(m,f,p=1,d=1)=>t.axDecel(u(m),m,f,p,d),ay:(m,f,p=1)=>t.ay(u(m),m,f,p),scrub:(m,f,p=1)=>t.scrub(u(m),m,f,p)}}}function zu(e,t,r,n,o){let a=e.length,s=r?a:a-1,i=F=>r?(F+1)%a:F+1,{brakeAhead:c,apexAhead:l}=qE(e,t,r),u=new Array(a),m=new Array(a),f=new Array(a),p=new Array(a).fill(0),d=0,h=0,b=0,g=Math.max(0,Math.min(1,n.kept)),y=g>=1?0:n.up,R=g>=1?0:n.down,k=4*y*(1-g),v=F=>{let{v:w,gear:C,tau:T,target:S}=F;d=0,h=0,b=0;for(let A=0;A<s;A++){let P=i(A),L=e[P];for(let V=0;T<=0&&V<n.count;V++){let N=C;if(w<L-1e-9?n.best(w)>C&&(n.rpm(w,C)>=n.limitRpm||c[A]>=w*k)?N=C+1:C>0&&w<n.vIdle(C)&&(N=C-1):L<w-1e-9&&C>0&&n.best(l[A])<C&&n.rpm(w,C-1)<=n.limitRpm&&(N=C-1),N===C)break;S=N,N>C?d++:h++,T=N>C?y:R,T<=0&&(C=S)}u[A]=w,m[A]=C+1,f[A]=n.rpm(w,C);let D=T>0;p[A]=D?1:0;let E=L;if(!D)w<L&&(E=Math.min(L,Math.sqrt(Math.max(0,w*w+2*o(A,w,n.share(w,C))*t[A]))));else if(w<L){let V=o(A,w,g>0?g*n.share(w,C):0),N=Math.min(L,Math.sqrt(Math.max(0,w*w+2*V*t[A]))),z=w+N>0?2*t[A]/(w+N):1/0;if(z<=T)E=N,b+=z,T-=z;else{let I=Math.min(L,Math.max(0,w+V*T)),_=Math.max(0,t[A]-(w+I)*.5*T);b+=T,T=0,C=S,E=Math.min(L,Math.sqrt(Math.max(0,I*I+2*o(A,I,n.share(I,C))*_)))}}else{let V=w+E>0?2*t[A]/(w+E):0;b+=Math.min(V,T),T-=V,T<=0&&(C=S)}w=E}return{v:w,gear:C,tau:T,target:S}},x=n.best(e[0]),M={v:e[0],gear:x,tau:0,target:x};if(r)for(let F=0;F<6;F++){let w=v(M),C=Math.abs(w.v-M.v)<=1e-9&&w.gear===M.gear&&w.target===M.target&&Math.abs(w.tau-M.tau)<=1e-12;if(M=w,C)break}else{let F=v(M);u[a-1]=F.v,m[a-1]=F.gear+1,f[a-1]=n.rpm(F.v,F.gear),p[a-1]=F.tau>0?1:0}return{v:u,gear:m,rpm:f,shifting:p,upshifts:d,downshifts:h,gapTime:b}}function qE(e,t,r){let n=e.length,o=new Array(n).fill(1/0),a=e.slice(),s=1/0,i=e[n-1],c=r?2*n-1:n-2;for(let l=c;l>=0;l--){let u=l%n,m=r?(u+1)%n:u+1,f=e[m]<e[u]-1e-9;s=f?0:s+t[u],i=f?Math.min(i,e[m]):e[u],l<n&&(o[u]=s,a[u]=i)}return{brakeAhead:o,apexAhead:a}}var vb=.001,kb=9.81,Ci=(e,t)=>Yu(e?.gradient?.[t]??0);function Yu(e){return e===0?0:-kb*Math.sin(e*Math.PI/180)}function yn(e,t){let r=new Array(t);for(let n=0;n<t;n++)r[n]=Yu(e?.[n]??0);return r}var gn=(e,t)=>{let r=e?.mu?.[t];return r!=null&&r>0?r:1},to=(e,t)=>e?.bank?.[t]??0;function QE(e,t,r,n,o,a){let s=e.ay(t,r,gn(o,a)),i=to(o,a);if(!i)return s;let c=i*Math.PI/180,l=n===0?0:-Math.sign(n)*kb*Math.sin(c);return Math.max(0,(s+l)/Math.cos(c))}function He(e,t){if(!t)return e;let r=t*Math.PI/180;return e*Math.cos(r)+kb*Math.sin(r)}function Mb(e,t,r,n,o){if(r<=t)return t;if(e(r)<=0)return r;let a=(r-t)/n,s=r,i=t,c=!1;for(let l=1;l<=n;l++){let u=r-l*a;if(e(u)<=0){i=u,s=u+a,c=!0;break}}if(!c)return t;for(;s-i>o;){let l=.5*(i+s);e(l)<=0?i=l:s=l}return i}var ro=(e,t,r)=>t?t(r):e,ZE=1e-4;function Aa(e,t,r,n,o,a,s){let i=st(r),c=[];for(let l=0;l<t.length;l++){let u=t[l],m=Math.abs(u),f=ro(e,o,l),p=a!==void 0&&a>0?Math.min(f.vMax,a):f.vMax,d=s?Math.min(p,s(l)):p,h=m<=0?d:Mb(b=>b*b*m-QE(f,b,0,u,n,l),vb,d,i.scanSteps,Math.min(i.vTol,ZE));c.push({v:h,ax:0,ay:h*h*u})}return c}function JE(e,t,r,n,o,a,s=1,i=0,c=0,l){if(r.v<=t.v)return 0;let u=p=>{let d=He(p*p*n,c),h=(l?e.axDecel(p,Math.abs(d),s,l(p)):e.axDecel(p,Math.abs(d),s))+i;return Math.sqrt(Math.max(0,p*p+2*h*o))},m=r.v;r.v=Mb(p=>u(p)-t.v,vb,r.v,a.scanSteps,a.vTol),r.ay=r.v*r.v*n;let f=Math.abs(He(r.ay,c));return r.ax=(l?e.axDecel(r.v,f,s,l(r.v)):e.axDecel(r.v,f,s))+i,m-r.v}function eI(e,t,r,n,o,a=1,s=0,i=0,c=1){if(r.v>=t.v)return 0;r.ay=r.v*r.v*n,r.ax=e.axAccel(r.v,Math.abs(He(r.ay,i)),a,c)+s;let l=t.v;return t.v=Math.min(t.v,Math.sqrt(Math.max(0,r.v*r.v+2*r.ax*o))),l-t.v}function iM(e,t,r,n,o,a){let s=st(n),i=r.npts,c=0;for(let l=0;l<s.seamIters;l++){let u=0;c++;for(let m=i-1;m>=0;m--){let f=(m+1)%i;u=Math.max(u,JE(ro(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],s,gn(r,m),Ci(r,m),to(r,m),a?p=>a(m,p):void 0))}if(u<=s.vTol)break}return c}function cM(e,t,r,n,o,a){let s=st(n),i=r.npts,c=0;for(let l=0;l<s.seamIters;l++){let u=0;c++;for(let m=0;m<i;m++){let f=(m+1)%i;u=Math.max(u,eI(ro(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],gn(r,m),Ci(r,m),to(r,m),a?a[m]:1))}if(u<=s.vTol)break}return c}function tI(e,t,r){let n=r.load?wi(t):null;if(!n||!r.load)return{pick:r.envelope};let o=t.npts;return{pick:sM(n,r.load,e,r.envelope),cap:a=>nM(n,a%o),n:(a,s)=>Hu(n,a,s)}}function lM(e,t,r,n,o,a,s){return zu(n,r.ds,o,a,(i,c,l)=>{let u=c*c*r.curvature[i];return ro(e,t,i).axAccel(c,Math.abs(He(u,to(r,i))),gn(r,i),s?l*s[i]:l)+Ci(r,i)})}function uM(e,t){return{gear:e.gear.slice(0,t),engineRpm:e.rpm.slice(0,t),shifting:e.shifting.slice(0,t)}}function mM(e,t,r,n){if(!e.scrub)return{};let o=!1,a=n.map((s,i)=>{let c=ro(e,t,i),l=He(s*s*r.curvature[i],to(r,i)),u=c.scrub?c.scrub(s,Math.abs(l),gn(r,i)):0;return u!==0&&(o=!0),u});return o?{axScrub:a}:{}}function Rt(e,t,r,n={}){let o=st(r),a=t.npts,s=t.closed&&!n.standingStart,{pick:i,cap:c,n:l}=tI(e,t,n),u=n.driveDerate,m=n.brakeFade;if(!s)return rI(e,t,o,n.standingStart===!0,i,u,n.vCeiling,m,c,l,n.shifts);let f=Aa(e,t.curvature,o,t,i,n.vCeiling,c),p=iM(e,f,t,o,i,m),d=cM(e,f,t,o,i,u),h=n.shifts?lM(e,i,t,f.map(k=>k.v),!0,n.shifts,u):void 0;if(h)for(let k=0;k<a;k++)f[k].v=h.v[k];for(let k=0;k<a;k++){let v=f[k];v.ay=v.v*v.v*t.curvature[k];let x=f[(k+1)%a].v;v.ax=(x*x-v.v*v.v)/(2*t.ds[k])}let b=f.map(k=>k.v),g=f.map(k=>k.ax),y=f.map(k=>k.ay),R=0;for(let k=0;k<a;k++){let v=b[k]+b[(k+1)%a];v>0&&(R+=2*t.ds[k]/v)}return{states:f,v:b,ax:g,ay:y,laptime:R,sweeps:{backward:p,forward:d},...l?{loadFactor:b.map((k,v)=>l(v,k))}:{},...mM(e,i,t,b),...h?uM(h,a):{}}}function rI(e,t,r,n,o,a,s,i,c,l,u){let m=t.npts,f=t.closed?m:m-1,p=f+1,d=new Array(p);for(let R=0;R<p;R++)d[R]=t.curvature[R%m];let h=Aa(e,d,r,t,o,s,c);n&&(h[0].v=0);for(let R=f-1;R>=0;R--){let k=h[R],v=h[R+1];if(k.v<=v.v)continue;let x=ro(e,o,R),M=w=>{let C=He(w*w*t.curvature[R],to(t,R)),T=(i?x.axDecel(w,Math.abs(C),gn(t,R),i(R,w)):x.axDecel(w,Math.abs(C),gn(t,R)))+Ci(t,R);return Math.sqrt(Math.max(0,w*w+2*T*t.ds[R]))},F=n&&R===0?k.v:vb;k.v=Mb(w=>M(w)-v.v,F,k.v,r.scanSteps,r.vTol)}for(let R=0;R<f;R++){let k=h[R],v=h[R+1];k.ay=k.v*k.v*t.curvature[R];let x=He(k.ay,to(t,R));k.ax=ro(e,o,R).axAccel(k.v,Math.abs(x),gn(t,R),a?a[R]:1)+Ci(t,R),v.v=Math.min(v.v,Math.sqrt(Math.max(0,k.v*k.v+2*k.ax*t.ds[R])))}let b=u?lM(e,o,t,h.map(R=>R.v),!1,u,a):void 0;if(b)for(let R=0;R<p;R++)h[R].v=b.v[R];let g=0;for(let R=0;R<f;R++){let k=h[R].v+h[R+1].v;k>0&&(g+=2*t.ds[R]/k)}let y=h.slice(0,m);for(let R=0;R<m;R++){let k=y[R];k.ay=k.v*k.v*t.curvature[R];let v=R<f?h[R+1].v:k.v;k.ax=t.ds[R]>0?(v*v-k.v*k.v)/(2*t.ds[R]):0}return{states:y,v:y.map(R=>R.v),ax:y.map(R=>R.ax),ay:y.map(R=>R.ay),laptime:g,sweeps:{backward:1,forward:1},...l?{loadFactor:y.map((R,k)=>l(k,R.v))}:{},...mM(e,o,t,y.map(R=>R.v)),...b?uM(b,m):{}}}var pM=(e,t)=>{let r=e[t]?.value;return Number.isFinite(r)&&r>0?r:0};function no(e,t,r){let n=e.m.value,o=e.r_dyn?.value??0,a=pM(e,"I_wheel"),s=e.motorModel?.kind==="ice"?0:pM(e,"I_rotor"),i=e.gear_ratio?.value??1;if(!(o>0)||a===0&&s===0)return{mass:n,driven:0,undriven:0,effective:n,powerFactor:1,tractionFactor:1};let c=o*o,l=(t?2:0)+(r?2:0),u=4-l,m=(l*a+s*i*i)/c,f=u*a/c,p=n+m+f;return{mass:n,driven:m,undriven:f,effective:p,powerFactor:n/p,tractionFactor:n/(n+f)}}function oo(e){let t=e.fAxle;return{drivenFront:t?t.fFront.some(r=>r>0):!1,drivenRear:t?t.fRear.some(r=>r>0):!0}}var Ti=36e5,bM=Math.PI*2,Sb=e=>Math.max(0,Math.min(1,e));function Ab(e){let t=e.motorModel;if(!t){let s=e.effi_pgb?.value??.9;return()=>s}if(t.kind==="simple"){let s=t.efficiency>.01?t.efficiency:.9;return()=>s}if(t.kind==="ice"){let s=t.gearbox.efficiency>.01?t.gearbox.efficiency:.9;return()=>s}let r=Wc(t),n=e.gear_ratio.value,o=e.r_dyn.value,a=Math.max(1,Math.round(e.motorCount??e.driven_wheels.value));return(s,i)=>{let c=s*n/o*(60/bM),l=Math.max(0,i*o/(n*a)),u=r.efficiency(c,l);return u>.01?u:.5}}var dM=new WeakMap;function Fa(e){if(e.batteryModel)return e.batteryModel;let t=e.capacity.value,r=e.ocv.value,n=dM.get(e);if(n&&n.capacityAh===t&&n.ocv===r)return n.model;let o=td(t,r);return dM.set(e,{capacityAh:t,ocv:r,model:o}),o}function Fb(e){let t=e.params,r=Fh(t,ru(e));if(ft(t.motorModel)||pt(t).mode!=="hydraulic")return r;let n;return(o,a,s,i=0)=>{if(!(o>0))return 0;n??=nI(e);let c=lu(n.inp,n.ev,o,a,i);return c?Math.min(o,c.regenFront+c.regenRear):r(o,a,s)}}var fM=new WeakMap;function nI(e){let t=e.params,r=fM.get(t);if(!r){let n=Dr(t);r={inp:dt(n.regen?t:{...t,energy:{...n,regen:!0}}),ev:mr(t)},fM.set(t,r)}return r}var Pi=e=>e.airTempC??At;function Wu(e,t){return e.thermal?e.thermal.startC??t:_o}function hM(e,t,r,n,o,a){let s=e.thermal;if(!s||!(o>0)||!(s.heatCapacityJPerK>0))return t;let i=s.coolingWPerK*(t-a)*o,c=s.entropicVPerK!==0?-r*(t+273.15)*s.entropicVPerK*o:0;return t+(n+c-i)/s.heatCapacityJPerK}var gM=()=>({windingC:[],derate:[],lossW:[],torqueNm:[],ampsRms:[]});function oI(e){let t=e.motorModel;if(!t?.thermal)return;let r=rd(t.thermal),n=Wc(t),o=e.gear_ratio.value,a=e.r_dyn.value,s=Math.max(1,Math.round(e.motorCount??e.driven_wheels.value));return{th:r,rpm:i=>i*o/a*(60/bM),peak:i=>n.maxTorque(i),amps:i=>t.thermal.torqueConstant>0?Math.abs(i)/t.thermal.torqueConstant:0,torque:(i,c,l)=>Math.min(Math.abs(i)*a/(o*s),l*n.maxTorque(c))}}function aI(e,t,r,n,o){let a=e.ocv(n);if(!(r>0))return{dq:t/a,lossJ:0,energyJ:t,short:!1,cutoff:!1,seconds:r};let s=e.maxPower(n,o),i=s.watts,c=t/r,l=Math.min(c,i),u=c>s.voltageFloor;if(u&&!(l>0))return{dq:1/0,lossJ:0,energyJ:0,short:!0,cutoff:u,seconds:1/0};let m=e.currentFor(l,n,o),f=u?c/l:1,p=r*f;return{dq:m*p,lossJ:m*m*e.resistance(n,o)*p,energyJ:l*p,short:c>i,cutoff:u,seconds:p}}function sI(e,t,r,n,o){let a=e.ocv(n);if(!(r>0))return{dq:t/a,lossJ:0,energyJ:t,short:!1,cutoff:!1,seconds:r};let s=e.resistance(n,o),i=e.chargeCurrentFor(t/r,n,o),c=Math.min(i,e.chargeCurrentCeiling),l=c===i?t:c*(a+c*s)*r;return{dq:c*r,lossJ:c*c*s*r,energyJ:l,short:c<i,cutoff:!1,seconds:r}}function iI(e){let{drivenFront:t,drivenRear:r}=oo(e);return no(e.params,t,r)}function wa(e,t,r,n,o=Lr,a,s,i,c,l,u){let m=e.params,f=m.rho.value,p=m.fr_0.value,d=m.m.value,h=e.FG,b=m.aeroModel?dt(m):void 0,g=Ab(m),y=xr(Fa(m)),R=y.chargeC,k=Sb(a??m.soc.value),v=Pi(m),x=s??Wu(y,v),M=x,F=0,w=0,C=0,T=0,S=-1,A=-1,P=-1,L=oI(m),D=L?L.th.startC:0,E=D,V=0,N=1,z=-1,I=0,_=0,B=Fb(e),O=m.motorModel?.kind==="ice",G=u?.scrub,K=G?d/iI(e).tractionFactor:0,Y=Math.min(t.length,r.length);for(let j=0;j<Y;j++){let Z=r[j],ne=Z*Z,te=n[j]-(c?.[j]??0),{cl:fe,cw:W,A:J}=Gu(m,Z,te/9.81,b),re=.5*f*fe*J*ne,pe=.5*f*W*J*ne,de=(h+re)*-p,ie=G?-K*(G[j]??0):0,oe=de+pe+ie+d*te,ue=oe*t[j],Be=j+1<r.length?r[j+1]:Z,Ae=.5*(Z+Be),le=Ae>0?t[j]/Ae:0,Re=0,Te=k,ze=x,je=0,be=0,Fe=le;if(O){oe>0&&(be=ue/g(Z,oe),F+=be/Ti),l?.netKwh.push(F-w),l?.powerKw?.push(le>0?be/le/1e3:0);continue}if(oe>0){let xe=ue/g(Z,oe),me=aI(y,xe,le,k,x);me.short&&S<0&&(S=j),me.cutoff&&A<0&&(A=j);let Le=k*R,Se=Math.min(me.dq,Le),Ye=me.dq>0?Se/me.dq:1;Se>=Le&&P<0&&(P=j),F+=me.energyJ*Ye/Ti,be=me.energyJ*Ye,Fe=me.seconds,C+=me.lossJ*Ye,T+=Se,le>0&&(je=Se/me.seconds),k=Sb(k-Se/R),x=hM(y,x,me.dq>0&&le>0?Se/le:0,me.lossJ*Ye,le,v),x>M&&(M=x),Re=oe}else if(o.regen){let xe=u?He(u.ay[j],u.bank?.[j]??0)/9.81:0,me=B(-oe,Z,te/9.81,xe),Le=o.regenEfficiency*me*t[j],Se=sI(y,Le,le,k,x),Ye=(1-k)*R,Ue=Math.min(Se.dq,Ye),zt=Se.dq>0?Ue/Se.dq:1;w+=Se.energyJ*zt/Ti,be=-Se.energyJ*zt,C+=Se.lossJ*zt,T-=Ue,le>0&&(je=-Ue/le),k=Sb(k+Ue/R),x=hM(y,x,Ue>0&&le>0?-Ue/le:0,Se.lossJ*zt,le,v),x>M&&(M=x),Re=-me*zt}if(l?.netKwh.push(F-w),l?.powerKw?.push(le>0?be/Fe/1e3:0),l?.pack){let xe=l.pack;xe.soc.push(Te),xe.amps.push(je),xe.volts.push(y.ocv(Te)-je*y.resistance(Te,ze)),xe.cellC.push(ze)}if(L){let xe=L.rpm(Z),me=L.th.derate(xe,D,L.peak(xe));me<N&&(N=me),me<1&&z<0&&(z=j),_+=le,me<1&&(I+=le);let Le=L.torque(Re,xe,me),Se=L.th.lossW(xe,Le,D);V+=Se*le,i&&(i.windingC.push(D),i.derate.push(me),i.lossW.push(Se),i.torqueNm.push(Le),i.ampsRms.push(L.amps(Le))),D=L.th.step(D,Se,le),D>E&&(E=D)}}return{drive:F,regen:w,net:F-w,chargeAh:T/3600,loss:C/Ti,socEnd:k,shortAt:S,cutoffAt:A,emptyAt:P,tempEndC:x,tempMaxC:M,...L?{motorTempEndC:D,motorTempMaxC:E,motorLossKwh:V/Ti,motorDerateMin:N,motorDerateAt:z,motorDerateTimeFrac:_>0?I/_:0}:{}}}var cI=.5,lI=.02,uI=6;function yM(e,t,r,n,o,a,s,i){let c=n(),l=1,u=d=>{let h=gM(),b=wa(e,t,d.v,d.ax,r,o,a,h,s,void 0,{ay:d.ay,bank:i,...d.axScrub?{scrub:d.axScrub}:{}});return{trace:h,peak:b.motorTempMaxC??0,frac:b.motorDerateTimeFrac??0}},m=u(c);if(!m.trace.derate.length||m.frac===0)return{lap:c,solves:l,converged:!0,peakWindingC:m.peak,derateTimeFrac:m.frac};let f=m.trace.derate.slice(),p=!1;for(let d=0;d<uI;d++){let h=n(f);l++;let b=Math.abs(h.laptime-c.laptime);if(c=h,m=u(c),b<lI){p=!0;break}let g=m.trace.derate,y=new Array(f.length);for(let R=0;R<f.length;R++)y[R]=f[R]+cI*((g[R]??1)-f[R]);f=y}return{lap:c,derate:f,solves:l,converged:p,peakWindingC:m.peak,derateTimeFrac:m.frac}}var mI=.1;function xM(e){let t=e.power_limit_kw?.value??0;return t>0?t*1e3:0}function wb(e,t,r){return e.motorModel?.kind==="ice"?1/0:xr(Fa(e)).maxPower(t??e.soc.value,r,xM(e)).watts}function ju(e,t,r,n){let o=wb(e,r,n);if(!Number.isFinite(o))return 1/0;if(o<=0)return 0;let a=Math.max(mI,t),s=Ab(e),i=o*(e.effi_pgb?.value??.9)/a;return o*s(t,i)/a}var pI=180/Math.PI;function Uu(e,t,r,n){let o=e*t,a=e*(1-t);return o/r-a/n}var Xu=e=>e*9.81*pI;var T7=Math.PI/180;function qu(e,t,r,n=0){let o=Ce(e,t,0,n),a=typeof r=="function"?r:r.front,s=typeof r=="function"?r:r.rear,i=.5*(a(Math.max(0,o.FL))+a(Math.max(0,o.FR))),c=.5*(s(Math.max(0,o.RL))+s(Math.max(0,o.RR))),l=i>0&&c>0?Uu(e.massTotal,e.frontMassFrac,2*i,2*c):0,u=Xu(l),m=u>.15?"understeer":u<-.15?"oversteer":"neutral";return{gradient:u,balance:m,cAlphaFront:i,cAlphaRear:c}}var O7=Math.PI/180,V7=180/Math.PI;var RM=2220446049250313e-31;function hI(e){let t=e.length,r=2,n=r*r,o=!1;for(;!o;){o=!0;for(let a=0;a<t;a++){let s=0,i=0;for(let c=0;c<t;c++)c!==a&&(i+=Math.abs(e[c][a]),s+=Math.abs(e[a][c]));if(i!==0&&s!==0){let c=s/r,l=1,u=i+s;for(;i<c;)l*=r,i*=n;for(c=s*r;i>c;)l/=r,i/=n;if((i+s)/l<.95*u){o=!1;let m=1/l;for(let f=0;f<t;f++)e[a][f]*=m;for(let f=0;f<t;f++)e[f][a]*=l}}}}}function bI(e){let t=e.length;for(let r=1;r<t-1;r++){let n=0,o=r;for(let a=r;a<t;a++)Math.abs(e[a][r-1])>Math.abs(n)&&(n=e[a][r-1],o=a);if(o!==r){for(let a=r-1;a<t;a++){let s=e[o][a];e[o][a]=e[r][a],e[r][a]=s}for(let a=0;a<t;a++){let s=e[a][o];e[a][o]=e[a][r],e[a][r]=s}}if(n!==0)for(let a=r+1;a<t;a++){let s=e[a][r-1];if(s!==0){s/=n,e[a][r-1]=s;for(let i=r;i<t;i++)e[a][i]-=s*e[r][i];for(let i=0;i<t;i++)e[i][r]+=s*e[i][a]}}}for(let r=2;r<t;r++)for(let n=0;n<r-1;n++)e[r][n]=0}function gI(e){let t=e.length,r=new Array(t).fill(0),n=new Array(t).fill(0),o=0;for(let i=0;i<t;i++)for(let c=Math.max(i-1,0);c<t;c++)o+=Math.abs(e[i][c]);let a=t-1,s=0;for(;a>=0;){let i=0,c=0;do{for(c=a;c>=1;c--){let u=Math.abs(e[c-1][c-1])+Math.abs(e[c][c]);if(u===0&&(u=o),Math.abs(e[c][c-1])<=RM*u){e[c][c-1]=0;break}}let l=e[a][a];if(c===a)r[a]=l+s,n[a]=0,a--;else{let u=e[a-1][a-1],m=e[a][a-1]*e[a-1][a];if(c===a-1){let f=.5*(u-l),p=f*f+m,d=Math.sqrt(Math.abs(p));l+=s,p>=0?(d=f+(f>=0?Math.abs(d):-Math.abs(d)),r[a-1]=r[a]=l+d,d!==0&&(r[a]=l-m/d),n[a-1]=n[a]=0):(r[a-1]=r[a]=l+f,n[a]=d,n[a-1]=-d),a-=2}else{if(i===60)throw new Error("eigenvalues: QR iteration did not converge");if(i===10||i===20||i===30||i===40||i===50){s+=l;for(let g=0;g<=a;g++)e[g][g]-=l;let b=Math.abs(e[a][a-1])+Math.abs(e[a-1][a-2]);u=l=.75*b,m=-.4375*b*b}i++;let f=a-2,p=0,d=0,h=0;for(;f>=c;f--){let b=e[f][f],g=l-b,y=u-b;p=(g*y-m)/e[f+1][f]+e[f][f+1],d=e[f+1][f+1]-b-g-y,h=e[f+2][f+1];let R=Math.abs(p)+Math.abs(d)+Math.abs(h);if(p/=R,d/=R,h/=R,f===c)break;let k=Math.abs(e[f][f-1])*(Math.abs(d)+Math.abs(h)),v=Math.abs(p)*(Math.abs(e[f-1][f-1])+Math.abs(b)+Math.abs(e[f+1][f+1]));if(k<=RM*v)break}for(let b=f+2;b<=a;b++)e[b][b-2]=0,b!==f+2&&(e[b][b-3]=0);for(let b=f;b<=a-1;b++){b!==f&&(p=e[b][b-1],d=e[b+1][b-1],h=b!==a-1?e[b+2][b-1]:0,l=Math.abs(p)+Math.abs(d)+Math.abs(h),l!==0&&(p/=l,d/=l,h/=l));let g=Math.sqrt(p*p+d*d+h*h),y=p>=0?g:-g;if(y!==0){b===f?c!==f&&(e[b][b-1]=-e[b][b-1]):e[b][b-1]=-y*l,p+=y,l=p/y,u=d/y;let R=h/y;d/=p,h/=p;for(let v=b;v<=a;v++){let x=e[b][v]+d*e[b+1][v];b!==a-1&&(x+=h*e[b+2][v],e[b+2][v]-=x*R),e[b+1][v]-=x*u,e[b][v]-=x*l}let k=a<b+3?a:b+3;for(let v=c;v<=k;v++){let x=l*e[v][b]+u*e[v][b+1];b!==a-1&&(x+=R*e[v][b+2],e[v][b+2]-=x*h),e[v][b+1]-=x*d,e[v][b]-=x}}}}}}while(c<a-1&&a>=0)}return r.map((i,c)=>({re:i,im:n[c]}))}function vM(e){let t=e.length;if(t===0)return[];for(let n of e)if(n.length!==t)throw new Error("eigenvalues: matrix must be square");for(let n of e)for(let o of n)if(!Number.isFinite(o))throw new Error("eigenvalues: matrix has non-finite entries");if(t===1)return[{re:e[0][0],im:0}];let r=e.map(n=>n.slice());return hI(r),bI(r),gI(r)}function kM(e){let t=[],r=new Array(e.length).fill(!1),n=vM(e);for(let o=0;o<n.length;o++){if(r[o])continue;let{re:a,im:s}=n[o];if(s<0)continue;let i=Math.hypot(a,s);t.push({freq:i/(2*Math.PI),dampedFreq:Math.abs(s)/(2*Math.PI),dampingRatio:i>0?-a/i:0,eigenvalue:n[o]})}return t.sort((o,a)=>a.freq-o.freq)}function Cb(e,t){let r=e.length,n=Array.from({length:r},(c,l)=>l);for(let c=0;c<r-1;c++){let l=c,u=c,m=-1;for(let h=c;h<r;h++)for(let b=c;b<r;b++){let g=e[h][b]*e[h][b]+t[h][b]*t[h][b];g>m&&(m=g,l=h,u=b)}if(!(m>0))break;if([e[c],e[l]]=[e[l],e[c]],[t[c],t[l]]=[t[l],t[c]],u!==c){for(let h=0;h<r;h++)[e[h][c],e[h][u]]=[e[h][u],e[h][c]],[t[h][c],t[h][u]]=[t[h][u],t[h][c]];[n[c],n[u]]=[n[u],n[c]]}let f=e[c][c],p=t[c][c],d=f*f+p*p;for(let h=c+1;h<r;h++){let b=(e[h][c]*f+t[h][c]*p)/d,g=(t[h][c]*f-e[h][c]*p)/d;if(!(b===0&&g===0))for(let y=c;y<r;y++)e[h][y]-=b*e[c][y]-g*t[c][y],t[h][y]-=b*t[c][y]+g*e[c][y]}}let o=new Array(r).fill(0),a=new Array(r).fill(0);o[r-1]=1;for(let c=r-2;c>=0;c--){let l=e[c][c],u=t[c][c],m=l*l+u*u;if(!(m>0))continue;let f=0,p=0;for(let d=c+1;d<r;d++)f+=e[c][d]*o[d]-t[c][d]*a[d],p+=e[c][d]*a[d]+t[c][d]*o[d];o[c]=-(f*l+p*u)/m,a[c]=-(p*l-f*u)/m}let s=Math.sqrt(o.reduce((c,l,u)=>c+l*l+a[u]*a[u],0)),i=new Array(r);for(let c=0;c<r;c++)i[n[c]]={re:o[c]/s,im:a[c]/s};return i}function yI(e,t){let r=e.map((o,a)=>o.map((s,i)=>a===i?s-t.re:s)),n=e.map((o,a)=>o.map((s,i)=>a===i?-t.im:0));return Cb(r,n)}function Qu(e,t=r=>yI(e,r)){return kM(e).map(r=>({...r,vector:t(r.eigenvalue)}))}function Ca(e,t,r){let n,o=-1,a,s=-1;for(let i of e){let c=t(i.vector),l=c[r];i.eigenvalue.im===0?l>s&&(a=i,s=l):l>=Math.max(...c)&&l>o&&(n=i,o=l)}return n??a}function MM(e){let t=e.sprungMass;if(!(t>0))return;let r=Math.max(.1,e.unsprungMass),n=e.springRate*1e3,o=e.damperRate*1e3,a=e.tireRate*1e3,s=(e.tireDamping??0)*1e3,i=[[0,1,0,0],[-n/t,-o/t,n/t,o/t],[0,0,0,1],[n/r,o/r,-(n+a)/r,-(o+s)/r]];if(!i.every(l=>l.every(Number.isFinite)))return;let c=l=>{let u=t*(l[0].re**2+l[0].im**2),m=r*(l[2].re**2+l[2].im**2);return u+m>0?[u/(u+m),m/(u+m)]:[0,0]};return Ca(Qu(i),c,0)}function SM(e,t,r,n){let o=(r==="front"?t.sprungFront:t.sprungRear)/2;if(o<=0)return{dampingRatio:0,criticalDamping:0,naturalFreqDamped:0};let a=r==="front"?t.rideRateFront:t.rideRateRear,s=r==="front"?e.wheelRateFront+(e.heaveSpringFront??0):e.wheelRateRear+(e.heaveSpringRear??0),i=MM({sprungMass:o,unsprungMass:e.unsprungCornerMass??e.unsprungPerCorner,springRate:s,damperRate:n,tireRate:Xe(e,r),tireDamping:e.tireDamping}),c=2*Math.sqrt(a*1e3*o);return{dampingRatio:i?.dampingRatio??0,criticalDamping:c/1e3,naturalFreqDamped:i?.dampedFreq??0}}function Zu(e,t,r){let n=we(e);return{front:SM(e,n,"front",t??n.rideDampingFront),rear:SM(e,n,"rear",r??n.rideDampingRear)}}var Q7=180/Math.PI;var Tb=["FL","FR","RL","RR"],ce={zFL:0,vzFL:1,zFR:2,vzFR:3,zRL:4,vzRL:5,zRR:6,vzRR:7,zBody:8,vzBody:9,pitch:10,pitchRate:11,roll:12,rollRate:13,x:14,vx:15,y:16,vy:17,yaw:18,yawRate:19},Ta=20,AM=[ce.zFL,ce.zFR,ce.zRL,ce.zRR],FM=[ce.vzFL,ce.vzFR,ce.vzRL,ce.vzRR],Kr={fzFL:0,fzFR:1,fzRL:2,fzRR:3,fzBody:4,myBody:5,mxBody:6,fx:7,fy:8,mz:9},Pb=10;function Ju(e){let t=Array.from({length:Ta},()=>new Array(Ta).fill(0)),r=Array.from({length:Ta},()=>new Array(Pb).fill(0));t[ce.zFL][ce.vzFL]=1,t[ce.zFR][ce.vzFR]=1,t[ce.zRL][ce.vzRL]=1,t[ce.zRR][ce.vzRR]=1,t[ce.zBody][ce.vzBody]=1,t[ce.pitch][ce.pitchRate]=1,t[ce.roll][ce.rollRate]=1,t[ce.x][ce.vx]=1,t[ce.y][ce.vy]=1,t[ce.yaw][ce.yawRate]=1;let{inertia:n}=e,o=[1,0,3,2],a=(s,i,c,l)=>{s[AM[i]]-=c,s[FM[i]]-=l,s[ce.zBody]+=c,s[ce.vzBody]+=l,s[ce.pitch]-=c*e.leverX[i],s[ce.pitchRate]-=l*e.leverX[i],s[ce.roll]+=c*e.leverY[i],s[ce.rollRate]+=l*e.leverY[i]};for(let s=0;s<4;s++){let i=s<2,c=M=>M?i?M.front:M.rear:0,l=e.springRate[s]+c(e.heaveSpring),u=e.springRate[s]+c(e.arb),m=e.damperRate[s]+c(e.heaveDamper),f=e.damperRate[s]+c(e.rollDamper),p=(l+u)/2,d=(l-u)/2,h=(m+f)/2,b=(m-f)/2,g=new Array(Ta).fill(0);a(g,s,p,h),(d!==0||b!==0)&&a(g,o[s],d,b);let y=e.wheelMass[s],R=e.leverX[s],k=e.leverY[s],v=AM[s],x=FM[s];for(let M=0;M<Ta;M++){let F=g[M];F!==0&&(t[x][M]+=F/y,t[ce.vzBody][M]-=F/e.bodyMass,t[ce.pitchRate][M]+=R*F/n.yy,t[ce.rollRate][M]-=k*F/n.xx)}t[x][v]-=e.tyreRate[s]/y,t[x][x]-=e.tyreDamping[s]/y,r[x][Kr.fzFL+s]=1/y}return r[ce.vzBody][Kr.fzBody]=1/e.bodyMass,r[ce.pitchRate][Kr.myBody]=1/n.yy,r[ce.rollRate][Kr.mxBody]=1/n.xx,r[ce.vx][Kr.fx]=1/e.totalMass,r[ce.vy][Kr.fy]=1/e.totalMass,r[ce.yawRate][Kr.mz]=1/n.zz,{A:t,B:r,params:e}}function Lb(e){let t=e.wheelbase/1e3,r=t*(1-e.frontMassFrac),n=t*e.frontMassFrac,o=e.trackFront/2e3,a=e.trackRear/2e3,s=e.unsprungCornerMass??e.unsprungPerCorner,i=Math.max(0,e.massTotal-4*s),c=e.wheelRateFront*1e3,l=e.wheelRateRear*1e3,u=(e.damperFront??2.5)*1e3,m=(e.damperRear??2.5)*1e3,f=Xe(e,"front")*1e3,p=Xe(e,"rear")*1e3,d=(e.tireDamping??0)*1e3;return{bodyMass:i,totalMass:e.massTotal,wheelMass:[s,s,s,s],inertia:{xx:e.rollInertia??i*.6*.6,yy:e.pitchInertia??i*1.2*1.2,zz:e.yawInertia??e.massTotal*1.2*1.2},leverX:[r,r,-n,-n],leverY:[o,-o,a,-a],springRate:[c,c,l,l],damperRate:[u,u,m,m],tyreRate:[f,f,p,p],tyreDamping:[d,d,d,d],arb:{front:e.arbFront*1e3,rear:e.arbRear*1e3},heaveSpring:{front:(e.heaveSpringFront??0)*1e3,rear:(e.heaveSpringRear??0)*1e3},rollDamper:{front:(e.rollDamperFront??0)*1e3,rear:(e.rollDamperRear??0)*1e3},heaveDamper:{front:(e.heaveDamperFront??0)*1e3,rear:(e.heaveDamperRear??0)*1e3}}}var wM=ce.rollRate+1;function CM(e){let t=e.params,r=[...t.wheelMass,t.bodyMass,t.inertia.yy,t.inertia.xx];if(!r.every(i=>i>0))return{};let n=e.A.slice(0,wM).map(i=>i.slice(0,wM));if(!n.every(i=>i.every(Number.isFinite)))return{};let a=Qu(n,i=>{let c=i.re*i.re-i.im*i.im,l=2*i.re*i.im,u=r.map((f,p)=>r.map((d,h)=>(p===h?c:0)-i.re*n[2*p+1][2*h+1]-n[2*p+1][2*h])),m=r.map((f,p)=>r.map((d,h)=>(p===h?l:0)-i.im*n[2*p+1][2*h+1]));return Cb(u,m)}),s=i=>{let c=r.map((u,m)=>u*(i[m].re**2+i[m].im**2)),l=c.reduce((u,m)=>u+m,0)||1;return[c[0]+c[1]+c[2]+c[3],c[4],c[5],c[6]].map(u=>u/l)};return{heave:Ca(a,s,1),pitch:Ca(a,s,2),roll:Ca(a,s,3)}}function TM(e,t,r){let n=e?2*Math.PI*e.freq:0,o=e&&n>0?e.dampingRatio:0,a=o>0&&o<1?Math.exp(-Math.PI*o/Math.sqrt(1-o*o))*100:0,s=o>0&&n>0?4/(o*n):1/0;return{freq:n/(2*Math.PI),dampedFreq:e&&n>0?e.dampedFreq:0,dampingRatio:o,stiffness:t,inertia:r,overshoot:a,settlingTime:s}}function em(e){let t=we(e),r=e.wheelbase/1e3,n=r*(1-e.frontMassFrac),o=r*e.frontMassFrac,a=t.rollRateTotal*(180/Math.PI),s=e.rollInertia??t.sprungMass*.6*.6,i=2*t.rideRateFront*1e3,c=2*t.rideRateRear*1e3,l=i*n*n+c*o*o,u=e.pitchInertia??t.sprungMass*1.2*1.2,m=CM(Ju(Lb(e)));return{roll:TM(m.roll,a,s),pitch:TM(m.pitch,l,u)}}var tm=9.81,Hr=Math.PI/180;function PM(e){let t=e.wheelbase/1e3,r=t*(1-e.frontMassFrac),n=t*e.frontMassFrac;return{wb:t,lf:r,lr:n,m:e.massTotal}}function Pa(e,t,r,n,o){let{wb:a,lf:s,lr:i,m:c}=PM(e),l=0;for(let R=0;R<16;R++){let k=l/r,v=o-n-s*k/r,x=-n+i*k/r,M=Ce(e,l/tm,0,r),F=Math.max(0,M.FL+M.FR),w=Math.max(0,M.RL+M.RR),C=t(v,F),T=t(x,w),S=(C*Math.cos(o)+T)/c;if(l=.5*(l+S),Math.abs(S-l)<1e-4)break}let u=l/r,m=o-n-s*u/r,f=-n+i*u/r,p=Ce(e,l/tm,0,r),d=Math.max(0,p.FL+p.FR),h=Math.max(0,p.RL+p.RR),b=t(m,d),g=t(f,h),y=s*b*Math.cos(o)-i*g;return{ay:l/tm,cn:y/(c*tm*a)}}function Db(e,t,r,n={}){let o=Math.max(8,r),a=(n.betaMaxDeg??10)*Hr,s=(n.deltaMaxDeg??10)*Hr,i=n.nLines??9,c=n.nPts??21,l=(g,y,R,k)=>R===1?g:g+(y-g)*k/(R-1),u=[],m={ay:[],cn:[]},f=0;for(let g=0;g<i;g++){let y=l(-s,s,i,g),R=[],k=[],v=[],x=[];for(let M=0;M<c;M++){let F=l(-a,a,c,M),w=Pa(e,t,o,F,y);R.push(w.ay),k.push(w.cn),v.push(F/Hr),x.push(y/Hr),Math.abs(w.ay)>f&&(f=Math.abs(w.ay))}u.push({label:`\u03B4 ${(y/Hr).toFixed(0)}\xB0`,ay:R,cn:k,betaDeg:v,deltaDeg:x});for(let M=1;M<k.length;M++)if(k[M-1]===0||k[M-1]<0!=k[M]<0){let F=k[M-1]===k[M]?0:k[M-1]/(k[M-1]-k[M]);m.ay.push(R[M-1]+F*(R[M]-R[M-1])),m.cn.push(0);break}}let p=[];for(let g=0;g<i;g++){let y=l(-a,a,i,g),R=[],k=[],v=[],x=[];for(let M=0;M<c;M++){let F=l(-s,s,c,M),w=Pa(e,t,o,y,F);R.push(w.ay),k.push(w.cn),v.push(y/Hr),x.push(F/Hr)}p.push({label:`\u03B2 ${(y/Hr).toFixed(0)}\xB0`,ay:R,cn:k,betaDeg:v,deltaDeg:x})}let d=.5*Hr,h=(Pa(e,t,o,d,0).cn-Pa(e,t,o,-d,0).cn)/(2*d),b=(Pa(e,t,o,0,d).cn-Pa(e,t,o,0,-d).cn)/(2*d);return{isoBeta:p,isoDelta:u,trim:m,maxAy:f,stability:h,control:b,speed:o}}function xI(e){return!e.corneringStiffnessFront||!e.corneringStiffnessRear?null:{Cf:2*e.corneringStiffnessFront,Cr:2*e.corneringStiffnessRear}}function Li(e,t){let r=xI(e);if(!r)return null;let{Cf:n,Cr:o}=r,{wb:a,lf:s,lr:i,m:c}=PM(e),l=e.yawInertia??c*1*1,u=Math.max(3,t),m=-(n+o)/(c*u),f=(-s*n+i*o)/(c*u)-u,p=(-s*n+i*o)/(l*u),d=-(s*s*n+i*i*o)/(l*u),h=m+d,b=m*d-f*p,g=h*h-4*b,y,R,k;if(g<0)y=h/2,R=Math.sqrt(Math.max(0,b)),k=R>0?-h/(2*R):1;else{let P=Math.sqrt(g);y=Math.max((h+P)/2,(h-P)/2),R=Math.sqrt(Math.abs(b)),k=R>0?-h/(2*R):1}let v=h<0&&b>0,x=Uu(c,e.frontMassFrac,n,o),M=Xu(x),F=M>.15?"understeer":M<-.15?"oversteer":"neutral",w=s*n-i*o,C=P=>P*3.6,T=null,S=null;w>1e-6?S=C(Math.sqrt(n*o*a*a/(c*w))):w<-1e-6&&(T=C(Math.sqrt(n*o*a*a/(c*-w))));let A=u/(a+x*u*u);return{stable:v,yawFreq:R/(2*Math.PI),dampingRatio:k,eigReal:y,understeerGradient:M,balance:F,characteristicSpeed:T,criticalSpeed:S,yawRateGain:A}}var LM=Math.PI/180;function IM(e,t){let r=Math.abs(e);return r<.15?"no measurable body slip \u2014 the car is travelling along its own centreline":Math.abs(t)<1e-6?`${r.toFixed(1)}\xB0 of body slip (not cornering, so there is no inside or outside yet)`:e*Math.sign(t)>0?`${r.toFixed(1)}\xB0 of body slip, nose pointing OUT of the corner \u2014 running wide of the path it is on`:`${r.toFixed(1)}\xB0 of body slip, nose pointing INTO the corner \u2014 rotated inside the path it is on`}function DM(e,t,r){return e.length<2?0:t<=0?(e[1]-e[0])/r:t>=e.length-1?(e[e.length-1]-e[e.length-2])/r:(e[t+1]-e[t-1])/(2*r)}function _M(e,t,r,n){let o=e.isoDelta.length,a=e.isoDelta[0]?.ay.length??0,s=Math.max(0,Math.min(o-1,Math.floor(t))),i=Math.max(0,Math.min(a-1,Math.floor(r))),c=Math.max(0,Math.min(1,t-s)),l=Math.max(0,Math.min(1,r-i)),u=0;for(let[m,f]of[[s,1-c],[Math.min(o-1,s+1),c]])if(!(f<=0))for(let[p,d]of[[i,1-l],[Math.min(a-1,i+1),l]])d<=0||(u+=f*d*n(e.isoDelta[m],p,m));return u}function NM(e,t,r){let n=e.isoDelta[0],o=(n.betaDeg[1]-n.betaDeg[0])*LM||1,a=e.isoDelta.length>1?(e.isoDelta[1].deltaDeg[0]-e.isoDelta[0].deltaDeg[0])*LM:1,s=x=>_M(e,t,r,x),i=s((x,M)=>x.ay[M]),c=s((x,M)=>x.cn[M]),l=s((x,M)=>x.betaDeg[M]),u=s((x,M)=>x.deltaDeg[M]),m=s((x,M)=>DM(x.cn,M,o)),f=s((x,M,F)=>DM(e.isoDelta.map(w=>w.cn[M]),F,a||1)),p=Math.max(1e-6,e.maxAy),d=Math.abs(i)/p,h=Math.max(1e-6,...e.isoDelta.flatMap(x=>x.cn.filter(Number.isFinite).map(Math.abs))),b=Math.abs(c)/h,g=i===0?c:c*Math.sign(i),y=[];y.push(`${IM(l,i)}.`),b<.03?y.push("On the trim line: yaw moments balance, so this is a steady corner the car can actually hold. Only points on this line are real cornering states \u2014 everywhere else the car is still rotating."):g>0?y.push(`Not a steady state: there is a surplus yaw moment turning the car further into the corner, so it would keep rotating from here. To hold ${Math.abs(i).toFixed(2)} g the driver would have to wind ${u>=0?"off":"on"} steer until the point reaches the trim line.`):y.push("Not a steady state: the yaw moment is straightening the car out, so it would run wide from here. The car needs more steer, or more front grip, to reach the trim line at this slip angle.");let R=Math.abs(e.stability)>1e-9?m/e.stability:1;R<.15?y.push("Yaw stiffness has collapsed here: the moment resisting a change in body slip is essentially gone, so the car will not gather itself up if it steps out. Both axles are close to saturation."):R<.85?y.push(`Yaw stiffness is down to about ${(100*R).toFixed(0)} % of its straight-ahead value \u2014 the car resists a change in body slip less firmly here than it does in the linear range.`):y.push(`Yaw stiffness is near its straight-ahead value (${(100*R).toFixed(0)} %), so the car still opposes a change in body slip about as firmly as it does in a straight line.`);let k=Math.abs(e.control),v=k>1e-9?Math.abs(f)/k:1;return v<.15?y.push("The steering has stopped working here: another degree of lock buys almost no yaw moment, which is what a saturated front axle looks like. This is understeer in its literal sense \u2014 the front tyres are already at their limit."):v<.5&&y.push(`Steering response is down to about ${(100*v).toFixed(0)} % of its straight-ahead value \u2014 the front is well into the non-linear part of its curve.`),d>.97?y.push(`At the edge of the diagram: ${Math.abs(i).toFixed(2)} g is essentially all this car has at this speed.`):d<.25&&y.push("Well inside the limit \u2014 this is the linear region the handling balance is measured in."),{ay:i,cn:c,betaDeg:l,deltaDeg:u,stability:m,control:f,gripUsed:d,notes:y}}var EM=1e-4;function Eb(e){let t=null,r=f=>{if(!t)return!0;let p=Math.abs(f),d=Math.abs(t.ay);return p>d*(1+EM)?!0:p<d*(1-EM)?!1:f>0&&t.ay<0};for(let f=0;f<e.isoDelta.length;f++){let p=e.isoDelta[f];for(let d=1;d<p.cn.length;d++){if(!(p.cn[d-1]===0||p.cn[d-1]<0!=p.cn[d]<0))continue;let b=p.cn[d-1]===p.cn[d]?0:p.cn[d-1]/(p.cn[d-1]-p.cn[d]),g=p.ay[d-1]+b*(p.ay[d]-p.ay[d-1]);r(g)&&(t={ay:g,d:f,b:b<.5?d-1:d})}}if(!t)return null;let n=NM(e,t.d,t.b),o=Math.abs(e.control)>1e-9?Math.abs(n.control/e.control):1,a=Math.abs(e.stability)>1e-9?n.stability/e.stability:1,s=o<.35,i=a<.35,c=s&&i?"both":s?"front":i?"rear":o<a?"front":"rear",l=e.isoDelta[t.d].betaDeg.length,u=t.b===0||t.b===l-1||t.d===0||t.d===e.isoDelta.length-1,m=t.ay<0?-1:1;return{ay:Math.abs(t.ay),turn:m,betaDeg:e.isoDelta[t.d].betaDeg[t.b]*m,deltaDeg:e.isoDelta[t.d].deltaDeg[t.b]*m,d:t.d,b:t.b,limitedBy:c,controlFrac:o,stiffnessFrac:a,onGridEdge:u}}var RI=["tv_kp"];function OM(e=0){let t=e<0,r=e>0,n=t||r,o=[{key:"damper_front",why:"dampers act on velocity; every point here is at constant attitude"},{key:"damper_rear",why:"dampers act on velocity; every point here is at constant attitude"},{key:"tire_vertical_damping",why:"tyre damping acts on velocity; every point here is at constant attitude"},{key:"I_yaw",why:"inertia resists change; a steady corner has none"},{key:"I_roll",why:"inertia resists change; a steady corner has none"},{key:"I_pitch",why:"inertia resists change; a steady corner has none"},{key:"capacity",why:"energy does not enter a single steady-state point"},{key:"ocv",why:"energy does not enter a single steady-state point"},{key:"soc",why:"energy does not enter a single steady-state point"},...RI.map(s=>({key:s,why:"the feedback gain multiplies a yaw error, and a trimmed point has none \u2014 the feedforward does move this diagram"}))];t||o.push({key:"brake_balance",why:r?"the diagram is drawn under acceleration, not braking":"no braking: the diagram is drawn at constant speed"});let a=n?"the longitudinal condition is set directly; what a motor could deliver is the lap solver\u2019s question":"no tractive force is applied at a constant speed";for(let s of["gear_ratio","power_scale","power_limit_kw","driven_wheels","effi_pgb"])o.push({key:s,why:a});for(let s of["I_wheel","I_rotor"])o.push({key:s,why:n?"rotating inertia is longitudinal, and `ax` is set here rather than solved \u2014 nothing in this picture spins a wheel up":"rotating inertia only acts where the car changes speed"});return o.push({key:"v_limit_endurance",why:"a limiter constrains a lap\u2019s speed profile; this diagram is drawn at one imposed speed"}),o.push({key:"endurance_reserve",why:"an energy budget sets the long event\u2019s speed ceiling; this diagram is drawn at one imposed speed"}),o.push({key:"fr_0",why:n?"rolling resistance is a drag term; `ax` is what the car does, not what the tyres are handed":"rolling resistance is longitudinal"}),o.push({key:"r_dyn",why:n?"the force each tyre carries is set here in newtons; a radius would only convert it to a torque":"the rolling radius only matters where a wheel is driven or braked"}),o}var vI=OM(0);function VM(e=0){let t="Springs and bars act through the roll-stiffness split and the camber the wheels take in roll; a heave spring reaches it too, but only faintly, through how far aero pushes the car down onto its camber curve.";if(!e)return"Steady state, lateral only: every point is a car in equilibrium at constant speed. Dampers, inertias, brake balance and the whole powertrain therefore cannot appear here \u2014 not because they are ignored, but because nothing in this picture accelerates. "+t;let r=e<0?`braking at ${Math.abs(e).toFixed(2)} g`:`accelerating at ${e.toFixed(2)} g`,n=e<0?"the brake balance decides which axle pays for it":"the driven axle pays for it";return`Steady state, ${r}: the load has moved ${e<0?"forward":"rearward"} and every tyre is spending part of its grip longitudinally, so ${n}. Dampers and inertias still cannot appear \u2014 the attitude is constant, it is simply not level. `+t}var kI=VM(0);var MI=9.81;function SI(e){let t=e.wheelbase/1e3;return{lf:t*(1-e.frontMassFrac),lr:t*e.frontMassFrac}}function Di(e,t,r,n){let o=t.tire;if(!o)return null;let s=(r==="limit"?tb(e,o,t.speed):hn(e,o,t.speed,t.ayG)).wheels;return Sr(n??jn(o,e.massTotal*MI*1.2),{FL:s.FL,FR:s.FR,RL:s.RL,RR:s.RR},SI(e))}function AI(e){if(!e.tire)return e.cornerStiffness;let t=ge(e.tire,"front"),r=ge(e.tire,"rear");return{front:n=>t.corneringStiffness(n),rear:n=>r.corneringStiffness(n)}}var BM=[{key:"understeer",label:"Understeer gradient",unit:"\xB0/g",compute:(e,t)=>qu(e,t.ayG,AI(t),t.speed).gradient},{key:"rollGradient",label:"Roll gradient",unit:"\xB0/g",compute:e=>we(e).rollGradient},{key:"pitchGradient",label:"Pitch gradient",unit:"\xB0/g",compute:e=>we(e).pitchGradient},{key:"tlltdFront",label:"TLLTD front",unit:"%",compute:e=>100*ff(e)},{key:"rollStiffFront",label:"Front roll-stiffness",unit:"%",compute:e=>100*we(e).frontRollStiffFrac},{key:"rideFreqFront",label:"Ride freq front",unit:"Hz",compute:e=>we(e).rideFreqFront},{key:"rideFreqRear",label:"Ride freq rear",unit:"Hz",compute:e=>we(e).rideFreqRear},{key:"rollFreq",label:"Roll-mode freq",unit:"Hz",compute:e=>em(e).roll.freq},{key:"pitchFreq",label:"Pitch-mode freq",unit:"Hz",compute:e=>em(e).pitch.freq},{key:"zetaFront",label:"Damping \u03B6 front",unit:"-",compute:e=>Zu(e).front.dampingRatio},{key:"zetaRear",label:"Damping \u03B6 rear",unit:"-",compute:e=>Zu(e).rear.dampingRatio},{key:"yawFreq",label:"Yaw natural freq",unit:"Hz",compute:(e,t)=>Li(e,t.speed)?.yawFreq??NaN},{key:"yawZeta",label:"Yaw damping \u03B6",unit:"-",compute:(e,t)=>Li(e,t.speed)?.dampingRatio??NaN},{key:"stabilitySpeed",label:"Char./critical speed",unit:"km/h",compute:(e,t)=>{let r=Li(e,t.speed);return r?r.criticalSpeed??r.characteristicSpeed??NaN:NaN}},{key:"maxAy",label:"Max lateral accel",unit:"g",compute:(e,t)=>t.fyAxle?Db(e,t.fyAxle,t.speed,{betaMaxDeg:12,deltaMaxDeg:12}).maxAy:NaN},{key:"yawReserveRear",label:"Yaw stability reserve",unit:"N\xB7m",compute:(e,t)=>Di(e,t,"operating")?.stabil??NaN},{key:"yawReserveFront",label:"Yaw agility reserve",unit:"N\xB7m",compute:(e,t)=>Di(e,t,"operating")?.agil??NaN},{key:"limitBalance",label:"Limit balance (+US / \u2212OS)",unit:"-",compute:(e,t)=>Di(e,t,"limit")?.rel??NaN},{key:"yawStiffness",label:"Yaw stiffness N_\u03B2",unit:"N\xB7m/rad",compute:(e,t)=>t.tire?eb(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorque",label:"Steering holding torque",unit:"N\xB7m",compute:(e,t)=>t.tire?Zh(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorqueGradient",label:"Steering feedback gradient",unit:"N\xB7m/g",compute:(e,t)=>t.tire?Jh(e,t.tire,t.speed,t.ayG):NaN}],Ib=Object.fromEntries(BM.map(e=>[e.key,e]));var zr=9.81;function FI(e,t,r){let n=Math.abs(e);return n>0?t>0&&(n<=t||t>=r)?n/t:r>0?1+(n-t)/r:2:0}var wI={front:!1,rear:!0};function La(e,t,r){let n=e.muX(t)*t,o=e.muY(t)*t;if(!(n>0))return 0;let a=o>0?Math.min(1,r/o):1;return n*Math.sqrt(1-a*a)}function $M(e,t,r,n,o,a){let s=e[t]+e[r];if(!(s>0))return;let i=La(n,o[t],a[t]),c=La(n,o[r],a[r]);i+c>0||(i=n.muX(o[t])*o[t],c=n.muX(o[r])*o[r]),i+c>0&&(e[t]=s*i/(i+c),e[r]=s-e[t])}function GM(e,t,r,n,o,a={},s="open"){if(!e.rear)return 1;if(!e.front)return 0;let i=(f,p,d)=>d?ti(f,p,d):s==="own"?f+p:2*Math.min(f,p),c=i(La(n,t.FL,r.FL),La(n,t.FR,r.FR),a.front),l=i(La(o,t.RL,r.RL),La(o,t.RR,r.RR),a.rear);if(c+l>0)return c/(c+l);let u=n.muX(t.FL)*t.FL+n.muX(t.FR)*t.FR,m=o.muX(t.RL)*t.RL+o.muX(t.RR)*t.RR;return u+m>0?u/(u+m):.5}function _b(e,t,r,n){return{car:t?zM(t,r.loadFactor[n]):e,ayTyre:He(r.ay[n],r.bank?.[n]??0),axCar:r.ax[n]-(r.axGrade?.[n]??0)}}function KM(e,t){if(!e.aero?.model)return 0;let r=Math.min(t.v.length,t.ax.length,t.ay.length),n=t.loadFactor?nm(e):void 0,o=0,a=0;for(let s=0;s<r;s++){let i=t.ds?.[s]??1,c=_b(e,n,t,s);o+=i,df(c.car,t.v[s],c.axCar/zr,c.ayTyre/zr)&&(a+=i)}return o>0?a/o:0}function HM(e,t,r){let n=Wt(ge(t,"front")),o=Wt(ge(t,"rear")),a=Math.min(r.v.length,r.ax.length,r.ay.length),s=r.loadFactor?nm(e):void 0,i=0,c=0;for(let l=0;l<a;l++){let u=r.ds?.[l]??1,m=_b(e,s,r,l);i+=u;let f=Ce(m.car,m.ayTyre/zr,m.axCar/zr,r.v[l]);(f.FL>n||f.FR>n||f.RL>o||f.RR>o)&&(c+=u)}return i>0?c/i:0}function rm(e,t,r,n={}){let o=Math.min(r.v.length,r.ax.length,r.ay.length),a=e.wheelbase/1e3,s=a*(1-e.frontMassFrac),i=a*e.frontMassFrac,c=ci(t,e.massTotal*zr*1.2),l=aa(c,"front"),u=aa(c,"rear"),m=ut(ge(t,"front")),f=ut(ge(t,"rear")),p=n.perWheel?yf(m,l):null,d=n.perWheel?f===m?p:yf(f,u):null,h=n.driven??wI,b={front:$t(e,"front",1),rear:$t(e,"rear",1)},g={front:0,rear:0},y=new Array(o),R=new Array(o),k=new Array(o),v=1/0,x=0,M=0,F=Wt(m),w=Wt(f),C=0,T=0,S=0,A=0,P=0,L=0,D=["FL","FR","RL","RR"],E=n.perWheel?Object.fromEntries(D.map(N=>[N,{Fz:new Array(o),alpha:new Array(o),Fy:new Array(o),Fx:new Array(o),Mz:new Array(o),used:new Array(o),FxCap:new Array(o),FyCap:new Array(o)}])):void 0,V=r.loadFactor?nm(e):void 0;for(let N=0;N<o;N++){let z=_b(e,V,r,N),{ayTyre:I,axCar:_}=z,B=I/zr,O=Ce(z.car,B,_/zr,r.v[N]),G=e.massTotal*I,K=G*i/a,Y=G*s/a,j=_s(m,K,O.FL,O.FR,P),Z=_s(f,Y,O.RL,O.RR,L);P=j,L=Z;let ne={FL:Math.abs(m.Fy(j,O.FL,0)),FR:Math.abs(m.Fy(j,O.FR,0)),RL:Math.abs(f.Fy(Z,O.RL,0)),RR:Math.abs(f.Fy(Z,O.RR,0))},te=(_-(r.axDrag?.[N]??0)-(r.axScrub?.[N]??0))/zr,fe=te>0&&h.front?GM(h,O,ne,l,u,b,"own"):0,W=r.v[N]*r.v[N],J=e.driveline?{Fz:O,alpha:{front:j,rear:Z},curvature:W>1?r.ay[N]/W:0,seed:g}:void 0,re={...Uh(e,te,r.v[N],t,B,fe,J)};te>0&&(b.front||$M(re,"FL","FR",l,O,ne),b.rear||$M(re,"RL","RR",u,O,ne));let pe=!1,de=!1;for(let ue of["FL","FR","RL","RR"]){let Be=(ue==="FL"||ue==="FR"?l:u).muX(O[ue])*O[ue];Math.abs(re[ue])>Be&&(pe=!0),O[ue]>(ue==="FL"||ue==="FR"?F:w)&&(de=!0)}de&&(M+=r.ds?.[N]??1);let ie=Sr(c,{FL:{Fz:O.FL,Fy:ne.FL,Fx:re.FL},FR:{Fz:O.FR,Fy:ne.FR,Fx:re.FR},RL:{Fz:O.RL,Fy:ne.RL,Fx:re.RL},RR:{Fz:O.RR,Fy:ne.RR,Fx:re.RR}},{lf:s,lr:i});if(y[N]=ie.stabil,R[N]=ie.agil,k[N]=ie.rel,E){let ue=.5*(O.FL+O.FR),Be=.5*(O.RL+O.RR),Ae=l.muX(ue)*ue,le=u.muX(Be)*Be;for(let Re of D){let Te=O[Re],ze=Re==="FL"||Re==="FR",je=ze?l:u,be=je.muY(Te)*Te,Fe=je.muX(Te)*Te,xe=E[Re],me=ze?j:Z;xe.Fz[N]=Te,xe.alpha[N]=me,xe.Fy[N]=ne[Re],xe.Fx[N]=re[Re],xe.Mz[N]=Te>0?(ze?m:f).Mz(me,Te,0):0,xe.FxCap[N]=Fe,xe.FyCap[N]=be;let Le=be>0?Math.min(1,Math.abs(ne[Re])/be):0,Se=FI(re[Re],Fe,ze?Ae:le),Ye=ze?p:d,Ue=Ye&&Te>0?Ye.reach(Te,Math.sign(re[Re])*Se,Le):1;xe.used[N]=Math.hypot(Le,Se)/Ue}}ie.stabil<v&&(v=ie.stabil,x=N);let oe=r.ds?.[N]??1;A+=oe,ie.diff>0&&(C+=oe),pe&&(T+=oe),df(z.car,r.v[N],_/zr,B)&&(S+=oe)}return{stabil:y,agil:R,rel:k,minStabil:Number.isFinite(v)?v:0,minStabilAt:x,pastTurnoverFrac:A>0?M/A:0,understeerFrac:A>0?C/A:0,beyondFrac:A>0?T/A:0,aeroOutsideFrac:A>0?S/A:0,wheels:E}}function nm(e){return Object.create(e,{loadFactor:{value:1,writable:!0,enumerable:!0}})}function zM(e,t){return e.loadFactor=t,e}var Nb=9.81;function Ob(e,t,r,n={}){let o=r.v.length,a=e.massTotal,s=Ir(e),i=s.mode==="hydraulic",c={front:new Array(o).fill(0),rear:new Array(o).fill(0),...n.regen?{regen:new Array(o).fill(0)}:{},...i?{pFront:new Array(o).fill(0),pRear:new Array(o).fill(0),pedalN:new Array(o).fill(0)}:{}};for(let l=0;l<o;l++){let u=r.v[l],m=r.ax[l]-(r.axGrade?.[l]??0),f=m-(r.axDrag?.[l]??0)-(r.axScrub?.[l]??0),p=-a*f;if(!(p>0))continue;let d=He(r.ay[l],r.bank?.[l]??0)/Nb,h=Math.min(.99,Math.max(.01,fa(e,f/Nb,u,t,d)));c.front[l]=p*h,c.rear[l]=p*(1-h);let b=i?lu(e,t,p,u,d):void 0;if(c.regen&&n.regen&&(c.regen[l]=b?Math.min(p,b.regenFront+b.regenRear):n.regen(p,u,m/Nb)),c.regen&&b){let g=b.regenFront+b.regenRear,y=g>0?c.regen[l]/g:0;(c.regenFront??=new Array(o).fill(0))[l]=b.regenFront*y,(c.regenRear??=new Array(o).fill(0))[l]=b.regenRear*y}if(i){let g=b?b.demand:s.demand(s.controlFor(p,u),u);c.pFront[l]=g.pFront,c.pRear[l]=g.pRear,c.pedalN[l]=g.pedalN}}return c}var iQ=Math.PI/180;var cQ=Tb.map(li);var lQ=[ce.zFL,ce.zFR,ce.zRL,ce.zRR];var uQ=Array.from({length:ce.rollRate+1},(e,t)=>t);var $I=9.81,GI=.001,KI=.6,HI=2,UM=4;function XM(e,t,r,n=UM){let o=Math.min(e.v.length,t.npts),{ds:a,closed:s}=t,i=r.massTotal*$I*r.wheelbase,c=zI(e.ay.slice(0,o).map((m,f)=>m/Math.max(GI,e.v[f])),a,s,n),l=new Array(o).fill(0),u=new Array(o).fill(0);if(!(i>0))return{demand:l,rdot:u};for(let m=0;m<o;m++){let f=m===0?s?o-1:-1:m-1,p=m===o-1?s?0:-1:m+1;if(f<0||p<0)continue;let d=a[f]+a[m];if(!(d>0))continue;u[m]=e.v[m]*(c[p]-c[f])/d;let h=Math.sign(c[m]);l[m]=h===0?0:h*r.yawInertia*u[m]/i}return{demand:l,rdot:u}}function zI(e,t,r,n){let o=e.length;if(!(n>0)||o<3)return e;let a=new Array(o);a[0]=0;for(let c=1;c<o;c++)a[c]=a[c-1]+t[c-1];let s=r?Math.floor((o-1)/2):o-1,i=new Array(o);for(let c=0;c<o;c++){let l=r?n:Math.min(n,a[c],a[o-1]-a[c]),u=e[c],m=1,f=0;for(let p=1;p<=s&&!(!r&&c+p>=o||(f+=t[(c+p-1)%o],!(f<l)));p++){let d=1-f/l;u+=d*e[(c+p)%o],m+=d}f=0;for(let p=1;p<=s&&!(!r&&c-p<0);p++){let d=(c-p+o)%o;if(f+=t[d],!(f<l))break;let h=1-f/l;u+=h*e[d],m+=h}i[c]=u/m}return i}function qM(e,t,r,n,o={}){let a=o.maxIter??20,s=o.tol??.001,i=Math.min(1,Math.max(.001,o.relax??KI)),c=o.smoothM??UM,l={standingStart:o.standingStart,...o.driveDerate?{driveDerate:o.driveDerate}:{},...o.brakeFade?{brakeFade:o.brakeFade}:{},...o.vCeiling?{vCeiling:o.vCeiling}:{},...o.load?{load:o.load}:{},...o.shifts?{shifts:o.shifts}:{}},u=Rt(e.steady,t,n,l),m=[u.laptime],f=new Array(t.npts).fill(0),p=f.slice(),d=u,h=0,b=!1,g=0;for(let k=0;k<a;k++){h=k+1;let v=XM(d,t,r,c);f=v.demand.map((F,w)=>f[w]+i*(F-f[w])),p=v.rdot;let x=Rt(e.steady,t,n,{...l,envelope:F=>e.at(f[F]??0)});m.push(x.laptime);let M=Math.abs(x.laptime-d.laptime);if(d=x,g=M<=s?g+1:0,g>=HI){b=!0;break}}let y=0,R=0;for(let k=0;k<t.npts;k++)R+=t.ds[k],e.clamps(f[k]??0)&&(y+=t.ds[k]);return{...d,steady:u,demand:f,rdot:p,history:m,iterations:h,converged:b,clampedFrac:R>0?y/R:0}}var xQ=Math.PI/180;var QQ=180/Math.PI;function Da(e,t,r){let n=e.length;if(n===1||r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0;for(;o<n-2&&e[o+1]<=r;)o++;let a=e[o],s=e[o+1],i=t[o],c=t[o+1];if(n===2)return i+(r-a)/(s-a)*(c-i);let l=f=>{let p=e[f];return i*(r-s)*(r-p)/((a-s)*(a-p))+c*(r-a)*(r-p)/((s-a)*(s-p))+t[f]*(r-a)*(r-s)/((p-a)*(p-s))},u=(r-a)/(s-a),m=o===0?l(2):o+1===n-1?l(o-1):(1-u)*l(o-1)+u*l(o+2);return Math.min(Math.max(i,c),Math.max(Math.min(i,c),m))}function ZM(e,t){let r=e.filter(p=>p.atLock),n=e.filter(p=>!p.atLock),o=r.length>0&&n.length>0&&r[r.length-1].v<n[0].v,a=p=>({vs:p.map(h=>h.v),ayMax:p.map(h=>h.ayMax),radius:p.map(h=>Math.max(h.v,t)**2/h.ayMax),accel:p[0].axAccelN.map((h,b)=>p.map(g=>g.axAccelN[b])),decel:p[0].axDecelN.map((h,b)=>p.map(g=>g.axDecelN[b])),scrub:p[0].axScrubN.map((h,b)=>p.map(g=>g.axScrubN[b]))}),s=(p,d)=>({axAccelN:p.accel.map(h=>Da(p.vs,h,d)),axDecelN:p.decel.map(h=>Da(p.vs,h,d)),axScrubN:p.scrub.map(h=>Da(p.vs,h,d))});if(!o){let p=a(e);return d=>({ayMax:Da(p.vs,p.ayMax,d),...s(p,d)})}let i=a(r),c=a(n),l=i.vs[i.vs.length-1],u=c.vs[0],m=p=>Math.max(p,t)**2/Da(i.vs,i.radius,p),f=p=>p>=u||c.vs.length<2?Da(c.vs,c.ayMax,p):c.ayMax[0]+(c.ayMax[1]-c.ayMax[0])/(c.vs[1]-c.vs[0])*(p-u);return p=>{if(p<=l)return{ayMax:m(p),...s(i,p)};if(p>=u)return{ayMax:f(p),...s(c,p)};let d=m(p),h=f(p);return d<h?{ayMax:d,...s(i,p)}:{ayMax:h,...s(c,p)}}}function i2(e,t){let r=Math.abs(e.ayMax-t.ayMax)/Math.max(t.ayMax,1),n=Math.max(Math.abs(t.axAccelN[0]),1),o=Math.max(Math.abs(t.axDecelN[0]),1);for(let a=0;a<t.axAccelN.length;a++)r=Math.max(r,Math.abs(e.axAccelN[a]-t.axAccelN[a])/n,Math.abs(e.axDecelN[a]-t.axDecelN[a])/o,Math.abs(e.axScrubN[a]-t.axScrubN[a])/n);return r}function JM(e,t,r,n,o){let a=r>t?Math.max(2,Math.min(5,Math.floor(n))):1,s=[];for(let f=0;f<a;f++)s.push(e(a===1?t:t+(r-t)*f/(a-1)));let i=ZM(s,t),c=[],l=a,u=(f,p)=>{let d=.5*(f+p),h=e(d);l++;let b=i2(i(d),h);s.splice(s.findIndex(g=>g.v>d),0,h),i=ZM(s,t),b>o&&c.push({lo:f,hi:d,misfit:b},{lo:d,hi:p,misfit:b})},m=s.map(f=>f.v);for(let f=0;f+1<m.length&&l<n;f++)m[f+1]-m[f]>=1&&u(m[f],m[f+1]);if(m.length>1){let f=.5*(m[0]+m[1]);if(s.some(p=>p.v===f))for(let[p,d]of[[m[0],f],[f,m[1]]]){if(l>=n||d-p<1)break;let h=c.findIndex(b=>b.lo===p&&b.hi===d);h>=0&&c.splice(h,1),u(p,d)}}for(;l<n&&c.length>0;){let f=0;for(let b=1;b<c.length;b++)c[b].misfit>c[f].misfit&&(f=b);let{lo:p,hi:d,misfit:h}=c.splice(f,1)[0];if(h<=o)break;d-p<1||u(p,d)}return{anchors:s,at:i}}var c2=2,l2=.5,Ei=Math.PI/180,eS=21,u2={nCoarse:11,nSteer:13,nNorm:41,nAngle:45},m2={nCoarse:11,nSteer:13,nNorm:41,nAngle:61},p2=.005,d2=.05,Vb=e=>e<0?0:e>1?1:e;function f2(e,t,r,n){let o=e.massTotal,a=n.nSteer??7,s=(n.drivenFront?2:0)+(n.drivenRear?2:0),i=Ce(e,0,0,r),c=Math.max(1,(i.FL+i.FR+i.RL+i.RR)/4),l=8*Ei,u=0,m=(b,g,y)=>{for(let R=b;R<=g;R+=y){let k=Math.abs(t.Fy(R*Ei,c,0));k>u&&(u=k,l=R*Ei)}};m(1,45,1),m(Math.max(.1,l/Ei-1),l/Ei+1,.1);let f=[],p=[],d=[],h=[];for(let b=0;b<a;b++){let g=b/(a-1),y=l*(g+Math.sin(Math.PI/2*g))/2,R=Math.abs(t.Fy(y,c,0));f.push(4*R/o),p.push(s*St(t,c,R,!1)/o),d.push(4*St(t,c,R,!0)/o),h.push(-4*R*Math.sin(y)/o)}return f[0]=0,{ayMax:4*u/o,ay:f,axAccel:p,axDecel:d,axScrub:h,rollover:!1}}function pr(e,t=!1,r="twoTrack",n,o,a=0,s=1){if(a!==0&&r==="fast")throw new Error('the fast (point-mass) envelope has no yaw balance to shift; use mode "twoTrack" for a yaw-inertia demand');let i=n??(t?m2:u2),{nCoarse:c,nSteer:l,nAngle:u}=i,m=Er(0,1,i.nNorm).map(B=>Math.sin(Math.PI/2*B)),f=e.params,p=f.m.value,d=f.rho.value,h=f.fr_0.value,b=f.driven_wheels.value,g=f.power_scale.value,y=e.FG,R=dt(f);s!==1&&(R.loadFactor=s);let k=mr(f),v=m1(0,n?.vRes??(e.engine?l2:c2),e.vMax);v[v.length-1]<e.vMax&&v.push(e.vMax);let x=e.fRad.map(B=>B*b),M=e.fAxle,{drivenFront:F,drivenRear:w}=oo(e),C=no(f,F,w),T=(B,O)=>{let G=M?mt(M.vVehicle,B,O):NaN;return Number.isFinite(G)?G:1/0},S=B=>{let O=B*B,{cl:G,cw:K,A:Y}=Gu(f,B,0,R),j=.5*d*-K*Y*O,Z=.5*d*-G*Y*O,ne=h*(-Z+y);return j+ne},A=B=>{let O=S(B)/p*C.powerFactor,G=S(B)/p*C.tractionFactor,K;if(e.engine){let j=S(B);K=ma(e.engine,B,C.effective,j,g).accel-O}else if(M){let j=0;F&&(j+=T(M.fFront,B)),w&&(j+=T(M.fRear,B)),K=g*j/p*C.powerFactor}else{let j=mt(e.vVehicle,x,B),Z=g*j/p*C.powerFactor;K=Number.isFinite(Z)?Z:1/0}let Y=ju(f,B,o)/p*C.powerFactor;return{axDrag:O,axDragTyre:G,axDrive:K,axPackCap:Y,axPower:Math.min(K,Y)}},P=v.map(A),L=e.vMax;for(let B=1;B<v.length;B++){let O=P[B].axDrive+P[B].axDrag;if(O>0)continue;let G=P[B-1].axDrive+P[B-1].axDrag;L=G>0?v[B-1]+(v[B]-v[B-1])*G/(G-O):v[B-1];break}let D=Math.min(e.vMax,(1+d2)*L),E=r==="fast"?f2:nb,V=B=>{let O=E(R,k,B,{drivenFront:F,drivenRear:w,nSteer:l,yawDemandCn:a,axDrag:S(B)/p,...f.diffYaw?{diffYaw:!0}:{}}),G=O.ay[0],K=O.ay[O.ay.length-1],Y=te=>Math.min(Math.max(te*O.ayMax,G),K),j=m.map(te=>eu(O.ay,O.axAccel,Y(te))*C.tractionFactor),Z=m.map(te=>eu(O.ay,O.axDecel,Y(te))),ne=m.map(te=>eu(O.ay,O.axScrub,Y(te))*C.tractionFactor);return{v:B,ayMax:O.ayMax,axAccelN:j,axDecelN:Z,axScrubN:ne,atLock:O.atLock===!0}},N=r==="fast"?0:Math.min(bu,D),z=JM(V,N,D,c,i.anchorTol??p2),I=[],_=[];for(let B=0;B<v.length;B++){let O=v[B],{axDrag:G,axDragTyre:K,axDrive:Y,axPackCap:j,axPower:Z}=P[B],{ayMax:ne,axAccelN:te,axDecelN:fe,axScrubN:W}=z.at(O);I.push({v:O,ayMax:ne,axTyreAcc:te[0],axTyreDec:fe[0],axDrive:Y,axPackCap:j,axPower:Z,axDrag:G,axDragTyre:K,axAccelN:te,axDecelN:fe,axScrubN:W});let J=[],re=[];for(let de=0;de<u;de++){let ie=Math.PI*de/(u-1),oe=ne*Math.cos(ie),ue=Vb(Math.abs(Math.cos(ie)));J.push({ax:Math.min(mt(m,te,ue)+K,Z+G)+mt(m,W,ue),ay:oe,v:O})}for(let de=u-1;de>=0;de--){let ie=Math.PI*de/(u-1),oe=ne*Math.cos(ie),ue=Vb(Math.abs(Math.cos(ie)));re.push({ax:mt(m,fe,ue)+G+mt(m,W,ue),ay:oe,v:O})}let pe=(de,ie,oe)=>Array.from({length:eS},(ue,Be)=>({ax:ie+(oe-ie)*(Be+1)/(eS+1),ay:de,v:O}));_.push([...J,...pe(-ne,J[J.length-1].ax,re[0].ax),...re,...pe(ne,re[re.length-1].ax,J[0].ax)])}return{...rS(I,m),rows:I,norm:m,surf:_}}function Ea(e,t){return e?.length?t.map(r=>am(e,r)):t.map(()=>0)}function am(e,t){let r=e.length-1;if(!(t>e[0].v))return e[0].axDrag;if(t>=e[r].v)return e[r].axDrag;let n=0,o=r;for(;o-n>1;){let s=n+o>>1;e[s].v<=t?n=s:o=s}let a=(t-e[n].v)/(e[o].v-e[n].v);return e[n].axDrag+a*(e[o].axDrag-e[n].axDrag)}function rS(e,t){let r=e[e.length-1].v,n=d=>{if(d<=e[0].v)return{i0:0,i1:0,t:0};if(d>=r)return{i0:e.length-1,i1:e.length-1,t:0};let h=0,b=e.length-1;for(;b-h>1;){let g=h+b>>1;e[g].v<=d?h=g:b=g}return{i0:h,i1:b,t:(d-e[h].v)/(e[b].v-e[h].v)}},o=d=>{let{i0:h,i1:b,t:g}=n(d);return{a:e[h],b:e[b],t:h===b?0:g}},a=(d,h,b)=>d===0||h===b?h:h+d*(b-h),s=(d,h,b,g)=>d===0?mt(t,h,g):a(d,mt(t,h,g),mt(t,b,g)),i=(d,h)=>h>=1?d.axPower:Math.min(h*d.axDrive,d.axPackCap),c=({a:d,b:h,t:b},g,y)=>d.axScrubN?y*s(b,d.axScrubN,h.axScrubN,g):0,l=d=>d.axDragTyre??d.axDrag,u=({a:d,b:h,t:b},g,y)=>{let R=y*a(b,d.ayMax,h.ayMax);return R>0?Vb(g/R):1},m=(d,h,b=1,g=1)=>{let{a:y,b:R,t:k}=d,v=u(d,h,b),x=b*s(k,y.axAccelN,R.axAccelN,v)+a(k,l(y),l(R)),M=a(k,i(y,g),k===0?0:i(R,g))+a(k,y.axDrag,R.axDrag);return Math.min(x,M)+c(d,v,b)},f=(d,h,b=1,g=1)=>{let{a:y,b:R,t:k}=d,v=u(d,h,b),x=s(k,y.axDecelN,R.axDecelN,v);return(g===1||x>0?b*x:g*b*x)+a(k,y.axDrag,R.axDrag)+c(d,v,b)},p=({a:d,b:h,t:b},g,y=1)=>{let R=t.length-1,k=d.axAccelN,v=h.axAccelN,x=d.axDecelN,M=h.axDecelN,F=d.axScrubN,w=h.axScrubN,C=E=>k[E]+b*(v[E]-k[E]),T=E=>x[E]+b*(M[E]-x[E]),S=E=>F?y*(F[E]+b*(w[E]-F[E])):0,A=a(b,d.ayMax,h.ayMax),P=a(b,d.axDrag,h.axDrag),L=a(b,l(d),l(h)),D=a(b,d.axPower,h.axPower);for(let E=R;E>=0;E--){let V=Math.min(y*C(E)+L,D+P)+S(E),N=y*T(E)+P+S(E);if(!(g<=V+1e-6&&g>=N-1e-6))continue;if(E===R)return t[E]*y*A;let z=(O,G,K)=>{if(K(G))return 1;let Y=(O-g)/(O-G);return Y>0?Math.min(Y,1):0},I=O=>g<=O+1e-6,_=O=>g>=O-1e-6,B=Math.min(z(y*C(E)+L+S(E),y*C(E+1)+L+S(E+1),I),z(D+P+S(E),D+P+S(E+1),I),z(y*T(E)+P+S(E),y*T(E+1)+P+S(E+1),_));return(t[E]+B*(t[E+1]-t[E]))*y*A}return 0};return{vMax:r,axAccel:(d,h,b=1,g=1)=>m(o(d),h,b,g),axDecel:(d,h,b=1,g=1)=>f(o(d),h,b,g),ay:(d,h,b=1)=>p(o(d),h,b),scrub:(d,h,b=1)=>{let g=o(d);return c(g,u(g,h,b),b)}}}function h2(e,t,r){let n=e.params,o=n.m.value,{drivenFront:a,drivenRear:s}=oo(e),i=no(n,a,s);return c=>ju(n,c,t,r)/o*i.powerFactor}function Ii(e,t,r,n){let o=h2(t,r,n),a=e.rows.map(s=>{let i=o(s.v),c=Math.min(s.axDrive,i);return c===s.axPower&&i===s.axPackCap?s:{...s,axPackCap:i,axPower:c}});return{...rS(a,e.norm),rows:a,norm:e.norm}}var b2=[-.2,-.08,0,.06,.12,.2,.3];function nS(e,t=!1,r="twoTrack",n,o,a=b2){let s=[...new Set([...a,0])].sort((d,h)=>d-h),i=s.map(d=>pr(e,t,r,n,o,d)),c=i[s.indexOf(0)],l=s[0],u=s[s.length-1],m=d=>{if(d<=l)return{i:0,t:0};if(d>=u)return{i:s.length-1,t:0};let h=0;for(;h<s.length-2&&s[h+1]<=d;)h++;return{i:h,t:(d-s[h])/(s[h+1]-s[h])}},f=d=>{let h=b=>{let{i:g,t:y}=m(b);return{a:d[g],b:d[Math.min(d.length-1,g+1)],t:y}};return b=>{let{a:g,b:y,t:R}=h(b);if(R===0)return g;let k=(v,x)=>v+R*(x-v);return{vMax:g.vMax,axAccel:(v,x,M=1,F=1)=>k(g.axAccel(v,x,M,F),y.axAccel(v,x,M,F)),axDecel:(v,x,M=1,F=1)=>k(g.axDecel(v,x,M,F),y.axDecel(v,x,M,F)),ay:(v,x,M=1)=>k(g.ay(v,x,M),y.ay(v,x,M)),scrub:(v,x,M=1)=>k(g.scrub?.(v,x,M)??0,y.scrub?.(v,x,M)??0)}}},p=d=>d<l||d>u;return{anchors:s,steady:c,clamps:p,at:f(i),atSoc(d,h,b){let g=i.map(y=>Ii(y,d,h,b));return{anchors:s,steady:g[s.indexOf(0)],clamps:p,at:f(g)}}}}function oS(e,t,r,n="twoTrack",o){let a=[...new Set([...t,1])].sort((i,c)=>i-c),s=a.map(i=>i===1?r:pr(e,!1,n,o,void 0,0,i));return{...tS(a,s),atSoc:(i,c,l)=>tS(a,s.map(u=>Ii(u,i,c,l)))}}function tS(e,t){let r=e.length-1,n=1,o=0,a=0,s=0,i=1,c=0,l=0,u=p=>{if(n=1,!(p>e[0]))return void(o=0);if(p>=e[r])return void(o=r);let d=0;for(;d<r-1&&e[d+1]<=p;)d++;if(o=d,p===e[d])return;a=d+1;let h=e[d],b=e[d+1];if(r<2){n=2,c=(p-h)/(b-h),i=1-c;return}s=d===0?2:d+1===r||p-e[d-1]<e[d+2]-p?d-1:d+2;let g=e[s];n=3,i=(p-b)*(p-g)/((h-b)*(h-g)),c=(p-h)*(p-g)/((b-h)*(b-g)),l=(p-h)*(p-b)/((g-h)*(g-b))},m=p=>{let d=p(t[o]);if(n===1)return d;let h=p(t[a]);if(n===2)return i*d+c*h;let b=i*d+c*h+l*p(t[s]);return Math.min(Math.max(d,h),Math.max(Math.min(d,h),b))},f=(p,d,h,b,g)=>{if(u(p),n===1||h===0)return m(k=>g(k,h));let y=m(k=>k.ay(d,0,b));if(!(y>0))return m(k=>g(k,h));let R=h/y;return m(k=>g(k,R*k.ay(d,0,b)))};return{anchors:e,axAccel:(p,d,h,b=1,g=1)=>f(p,d,h,b,(y,R)=>y.axAccel(d,R,b,g)),axDecel:(p,d,h,b=1,g=1)=>{let y=R=>f(p,d,h,b,(k,v)=>k.axDecel(d,v,b,R));return g===1?y(1):Rb(y(g),y(1),g)},scrub:(p,d,h,b=1)=>f(p,d,h,b,(g,y)=>g.scrub?.(d,y,b)??0),ay:(p,d,h,b=1)=>{if(u(p),n===1||h===0)return m(k=>k.ay(d,h,b));let g=k=>h>0?k.axAccel(d,0,b):-k.axDecel(d,0,b),y=m(g);if(!(y>0))return m(k=>k.ay(d,h,b));let R=h/y;return m(k=>k.ay(d,R*g(k),b))}}}var aS=new WeakMap;function Bb(e,t){let r=aS.get(e);if(!r){let n=Dr(e).regen?Fb(t??Ft(e)):void 0;r={inp:dt(e),ev:mr(e),...n?{regen:n}:{}},aS.set(e,r)}return r}function $b(e,t,r){let n=Bb(e,r);return Ob(n.inp,n.ev,t,n.regen?{regen:n.regen}:{})}function Gb(e){let t=pt(e);if(t.mode!=="hydraulic")return null;let r=a=>a.heat?{heat:rh(a.heat,a.ratio),discs:a.discs}:void 0,n=r(t.hydraulic.front),o=r(t.hydraulic.rear);return n||o?{...n?{front:n}:{},...o?{rear:o}:{}}:null}function g2(e){let t=(r,n)=>n?r.map((o,a)=>Math.max(0,o-n[a])):r;return{front:t(e.front,e.regenFront),rear:t(e.rear,e.regenRear)}}function Kb(e,t,r,n,o,a=At){if(!e)return null;let s=g2(t);return{...e.front?{front:Xl(e.front.heat,e.front.discs,s.front,r,n,o.front,a)}:{},...e.rear?{rear:Xl(e.rear.heat,e.rear.discs,s.rear,r,n,o.rear,a)}:{}}}var y2=.5,x2=.02,R2=6,sm=9,sS=1e-9,v2={FL:0,FR:0,RL:0,RR:0};function Hb(e){return e?[...new Set([...e.padCurve.factor,1])].sort((t,r)=>t-r):[1]}function k2(e,t,r){let n=ir(e),o=n.hydraulic;return n.mode!=="hydraulic"||!o?e:{...e,brakes:{...n,hydraulic:{...o,front:{...o.front,padMu:o.front.padMu*t},rear:{...o.rear,padMu:o.rear.padMu*r}}}}}function iS(e,t){let r=e.length;if(r===1||t<=e[0])return{i:0,t:0};if(t>=e[r-1])return{i:r-2,t:1};let n=0;for(;n<r-2&&e[n+1]<=t;)n++;return{i:n,t:(t-e[n])/(e[n+1]-e[n])}}function cS(e,t,r,n,o=()=>0){let a=Array.from({length:sm},(m,f)=>r*f/(sm-1)),s=si(),{front:i,rear:c}=n,l=a.map(m=>{let f=o(m),p=h=>_r(h,t,m,s).limitAt(0,0,v2,f).ax,d=p(e);return i.map(h=>c.map(b=>{if(h===1&&b===1)return 1;let g=d<0?p(k2(e,h,b))/d:1;return Math.abs(g-1)<sS?1:g}))}),u=a[1]-a[0];return{share(m,f,p){if(f===1&&p===1)return 1;let d=u>0?Math.min(sm-2,Math.max(0,Math.floor(m/u))):0,h=u>0?Math.min(1,Math.max(0,(m-a[d])/u)):0,b=iS(i,f),g=iS(c,p),y=k=>{let v=l[k],x=Math.min(i.length-1,b.i+1),M=Math.min(c.length-1,g.i+1),F=v[b.i][g.i]+g.t*(v[b.i][M]-v[b.i][g.i]),w=v[x][g.i]+g.t*(v[x][M]-v[x][g.i]);return F+b.t*(w-F)},R=y(d)+h*(y(Math.min(sm-1,d+1))-y(d));return Math.abs(R-1)<sS?1:R}}}function M2(e,t){let{front:r,rear:n}=t;return(o,a)=>e.share(a,r?.[o]??1,n?.[o]??1)}var S2=e=>(e.front??[]).every(t=>t===1)&&(e.rear??[]).every(t=>t===1);function lS(e,t,r){let n=e(),o=1,a=t(n);if(S2(a))return{lap:n,solves:o,converged:!0};let s={...a.front?{front:a.front.slice()}:{},...a.rear?{rear:a.rear.slice()}:{}},i=!1;for(let c=0;c<R2;c++){let l=e(M2(r,s));o++;let u=Math.abs(l.laptime-n.laptime);if(n=l,u<x2){i=!0;break}a=t(n);let m=(d,h)=>d&&h?d.map((b,g)=>b+y2*((h[g]??1)-b)):d,f=m(s.front,a.front),p=m(s.rear,a.rear);s={...f?{front:f}:{},...p?{rear:p}:{}}}return{lap:n,pads:s,solves:o,converged:i}}function xn(e,t){let r=e.engine;if(!r||r.gears.length===0||t.length===0)return;let n=e.params,{drivenFront:o,drivenRear:a}=oo(e),s=no(n,o,a).effective,i=n.power_scale.value,{up:c,down:l}=gh(r.engine.gearbox),u=r.engine.idleRpm,m=(f,p,d)=>(i*r.force(f,p)+d)/(s+r.inertiaMass(f,p));return{count:r.gears.length,up:c,down:l,kept:yh(r.engine.gearbox),limitRpm:r.engine.limitRpm,best:f=>ma(r,f,s,am(t,f)*s,i).gear,share:(f,p)=>{let d=am(t,f),h=d*s,b=ma(r,f,s,h,i);if(p===b.gear)return 1;let g=b.accel-d;return g>0?Math.min(1,Math.max(0,(m(f,p,h)-d)/g)):0},rpm:(f,p)=>r.slipping(f,p)?u:r.rpm(f,p),vIdle:f=>r.gears[f]?.vIdle??0}}var uS=new WeakMap;function Yb(e){let t=uS.get(e.ggv);return t===void 0&&(t=xn(e.vehicle,e.ggv.rows)??null,uS.set(e.ggv,t)),t??void 0}function A2(e){return e.gear&&e.engineRpm&&e.shifting?{gear:e.gear,rpm:e.engineRpm,shifting:e.shifting}:{}}var cm=class extends Error{constructor(t){super(t),this.name="EventError"}};function F2(e,t){let{ggv:r}=t,n=st(t.numerics),o=n.accelStep,a=Math.max(1,Math.round(e.distance/o)),s=Aa(r,new Array(a+1).fill(0),n);s[0].v=e.vStart??0;for(let d=0;d<s.length-1;d++){let h=s[d],b=s[d+1];h.v>=b.v||(h.ax=r.axAccel(h.v,0),b.v=Math.min(r.vMax,Math.sqrt(Math.max(0,h.v*h.v+2*h.ax*o))))}let i=Yb(t),c=i?zu(s.map(d=>d.v),new Array(a).fill(o),!1,i,(d,h,b)=>r.axAccel(h,0,1,b)):void 0;if(c){for(let d=0;d<=a;d++)s[d].v=c.v[d];for(let d=0;d<a;d++)s[d].ax=(s[d+1].v*s[d+1].v-s[d].v*s[d].v)/(2*o)}let l=0;for(let d=0;d<a;d++){let h=s[d].v+s[d+1].v;h>0&&(l+=2*o/h)}let u=s.slice(0,a).map(d=>d.v),m=s.slice(0,a).map(d=>d.ax),f=new Array(a).fill(o),p=f.map((d,h)=>h*o);return{id:e.id,label:e.label,kind:e.kind,time:l,distance:a*o,laps:1,lapTime:l,trace:{v:u,ax:m,ay:new Array(a).fill(0),s:p,x:p,y:new Array(a).fill(0),...c?{gear:c.gear.slice(0,a),rpm:c.rpm.slice(0,a),shifting:c.shifting.slice(0,a)}:{}},energy:xS(t,f,[...u,s[a].v],m,1)}}function w2(e,t){let r=Math.max(1,Math.round(e.laps??1)),[n]=Aa(t.ggv,[1/e.radius],t.numerics),o=2*Math.PI*e.radius,a=n.v>0?o/n.v:1/0,s=t.ggv.scrub?.(n.v,Math.abs(n.ay))??0,i=xS(t,[o],[n.v,n.v],[0],r,s!==0?{ay:[n.ay],scrub:[s]}:void 0);return{id:e.id,label:e.label,kind:e.kind,time:a*r,distance:o*r,laps:r,lapTime:a,energy:i}}function lm(e,t){return e.laps!=null?Math.max(1,Math.round(e.laps)):e.distance!=null?Math.max(1,Math.ceil(e.distance/t.length)):1}function C2(e,t){let r=e.distance!=null?t.v_limit_endurance?.value??0:0;return r>0?r/3.6:void 0}function T2(e,t){if(e.distance==null||ft(t.motorModel))return 0;let r=t.endurance_reserve?.value??0;return r>0?Math.min(r,95)/100:0}var mS=1;function bS(e,t,r,n){return{v:r.v,ax:r.ax,ay:r.ay,ds:t.ds,axDrag:Ea(e.ggv.rows,r.v),...r.axScrub?{axScrub:r.axScrub}:{},axGrade:n,...t.bank?{bank:t.bank}:{}}}var pS=new WeakMap;function gS(e){let t=e.vehicle.params;if(!t.brakeFade)return null;let r=pS.get(t);if(r===void 0){let n=Gb(t),o=n?pt(t):null;if(!n||!o||o.mode!=="hydraulic")r=null;else{let a=Bb(t,e.vehicle),s=e.ggv.rows,i=cS(a.inp,a.ev,e.vehicle.vMax,{front:Hb(o.hydraulic.front.heat),rear:Hb(o.hydraulic.rear.heat)},c=>Ea(s,[c])[0]);r={discs:n,table:i}}pS.set(t,r)}return r}function P2(e,t,r){let n=e.vehicle.params,{soc:o,packTempC:a,launched:s,vCeiling:i}=r,c=e.load?.atSoc(e.vehicle,o,a),l=Yb(e),u=(g,y)=>e.yaw?qM(e.yaw.family.atSoc(e.vehicle,o,a),t,e.yaw.car,e.numerics,{standingStart:s,...g?{driveDerate:g}:{},...y?{brakeFade:y}:{},...i?{vCeiling:i}:{},...c?{load:c}:{},...l?{shifts:l}:{}}):Rt(Ii(e.ggv,e.vehicle,o,a),t,e.numerics,{standingStart:s,...g?{driveDerate:g}:{},...y?{brakeFade:y}:{},...i?{vCeiling:i}:{},...c?{load:c}:{},...l?{shifts:l}:{}}),m=yn(t.gradient,t.npts),f=g=>n.motorThermal?yM(e.vehicle,t.ds,e.energyOpts??Lr,y=>u(y,g),o,a,m,t.bank).lap:u(void 0,g),p=gS(e);if(!p)return f();let d=Pi(n),h=r.discC??{front:d,rear:d};return lS(f,g=>{let y=Kb(p.discs,$b(n,bS(e,t,g,m),e.vehicle),g.v,t.ds,h,d);return{...y?.front?{front:y.front.padFactor}:{},...y?.rear?{rear:y.rear.padFactor}:{}}},p.table).lap}function L2(e,t){let r=C2(e,t.vehicle.params),n=T2(e,t.vehicle.params);return n>0?I2(e,t,n,r):_i(e,t,r)}function im(e,t){let r=e.energy?.remainingFraction??0;return e.incomplete?-t-(1-e.incomplete.lapsCompleted/Math.max(1,e.incomplete.lapsAsked)):r-t}var dS=5,D2=.1,E2=.005,fS=12;function I2(e,t,r,n){let o=_i(e,t,n),a=1,s=(d,h,b)=>({...d,energyTarget:{reserve:r,capKmh:h===void 0?null:h*3.6,met:b,solves:a}}),i=im(o,r);if(i>=0)return s(o,n,!0);let c=Math.min(n??1/0,t.ggv.vMax),l=c/2,u=_i(e,t,l);a++;let m=im(u,r);for(;m<0&&l>dS&&a<fS;)c=l,i=m,l=Math.max(dS,l/2),u=_i(e,t,l),a++,m=im(u,r);if(m<0)return s(u,l,!1);let f=l,p=0;for(;a<fS&&c-l>D2&&m>E2;){let d=c-l,h=Math.min(c-.05*d,Math.max(l+.05*d,l+m*d/(m-i))),b=_i(e,t,h);a++;let g=im(b,r);g>=0?(l=h,m=g,u=b,f=h,p===1&&(i/=2),p=1):(c=h,i=g,p===-1&&(m/=2),p=-1)}return s(u,f,!0)}function yS(e,t,r){return r===0?e:e&&!t}function _i(e,t,r){let n=t.track;if(!n)throw new cm(`Event "${e.id}" needs a track.`);let o=lm(e,n),a=e.standingStart??t.standingStart??!1,s=K=>yS(a,n.closed,K),i=t.vehicle.params,c=xr(Fa(i)),l=c.capacityAh,u=i.soc.value,m=Pi(i),f=Wu(c,m),p=0,d=0,h=0,b=0,g=[],y=!1,R=-1/0,k=0,v=0,x=!1,M=-1/0,F=0,w=0,C=-1/0,T=(K,Y,j=1)=>{K.tempMaxC>C&&(C=K.tempMaxC),K.motorTempMaxC!==void 0&&(y=!0,x=!0,K.motorTempMaxC>R&&(R=K.motorTempMaxC),K.motorTempMaxC>M&&(M=K.motorTempMaxC),k+=(K.motorDerateTimeFrac??0)*Y,F+=(K.motorDerateTimeFrac??0)*Y,v+=(K.motorLossKwh??0)/j,w+=(K.motorLossKwh??0)/j)},S=null,A,P=Gb(i),L={front:m,rear:m},D=null,E=gS(t)!==null,V=(K,Y)=>E&&(Math.abs(K.front-Y.front)>mS||Math.abs(K.rear-Y.rear)>mS),N=(K,Y,j)=>{let Z=wb(i,K,Y);if(D&&D.launch===j&&!O2(Z,D.pw)&&!V(L,D.discC))return D.lap;let ne=P2(t,n,{soc:K,packTempC:Y,launched:j,...r?{vCeiling:r}:{},...E?{discC:L}:{}});return D={pw:Z,launch:j,discC:L,lap:ne},ne},z=yn(n.gradient,n.npts),I=(K,Y,j)=>wa(t.vehicle,n.ds,K.v,K.ax,t.energyOpts,Y,j,void 0,z,void 0,{ay:K.ay,bank:n.bank,...K.axScrub?{scrub:K.axScrub}:{}}),_=new WeakMap,B=(K,Y)=>{let j=_.get(K);return j||(j=$b(i,bS(t,n,K,z),t.vehicle),_.set(K,j)),Kb(P,j,K.v,n.ds,Y,m)},O=(K,Y,j)=>{let Z=`${(100*j/n.npts).toFixed(0)} % of the way through lap ${K+1}`,ne=Y.cutoffAt>=0&&Y.cutoffAt<=Y.emptyAt;return{lapsCompleted:K,lapsAsked:o,why:ne?`the pack reached its ${c.voltageFloor.toFixed(0)} V cut-off ${Z}`:`the pack ran out ${Z}`}};for(let K=0;K<o;K++){if(u<=0){A={lapsCompleted:K,lapsAsked:o,why:"the pack was empty"};break}let Y=s(K),j=u,Z=f;x=!1,M=-1/0,F=0,w=0,C=-1/0;let ne=N(u,f,Y),te=I(ne,u,f);if(te.emptyAt>=0){A=O(K,te,te.emptyAt);break}let W=N(te.socEnd,te.tempEndC,Y).laptime-ne.laptime,J,re,pe,de,ie=f,oe=-1,ue=null,Be=1;if(W<=zb)J=ne.laptime,re=te.net,pe=te.loss,de=te.chargeAh,ie=te.tempEndC,T(te,J),Be=1;else{let le=Math.min(_2,Math.max(2,Math.ceil(W/(2*zb))));Be=le;let Re=u,Te=f;J=0,re=0,pe=0,de=0;for(let ze=0;ze<le;ze++){let je=N(Re,Te,Y),be=I(je,Re,Te),Fe=be.emptyAt>=0?be.emptyAt/n.npts:1;if(Fe*le<1){oe=Math.round(n.npts*(ze/le+Fe)),ue=be;break}if(J+=je.laptime/le,T(be,je.laptime/le,le),re+=be.net/le/Fe,pe+=be.loss/le/Fe,de+=be.chargeAh/le/Fe,Re-=be.chargeAh/le/Fe/l,Te+=(be.tempEndC-Te)/le,Re<=0){oe=Math.round(n.npts*(ze+1)/le),ue=be;break}}if(ie=Te,oe>=0&&ue){A=O(K,ue,oe);break}u=Re}p+=J,d+=re,h+=pe,b+=de,W<=zb&&(u=te.socEnd),f=ie;let Ae=P?B(ne,L):null;Ae&&(L={front:Ae.front?.endC??L.front,rear:Ae.rear?.endC??L.rear}),g.push({lap:K+1,time:J,elapsed:p,entryTime:ne.laptime,socStart:j,socEnd:u,packTempStartC:Z,packTempEndC:f,packTempMaxC:Number.isFinite(C)?C:Z,energyKwh:re,lossKwh:pe,chargeAh:de,launched:Y,substeps:Be,...r?{vCeiling:r}:{},...x?{motor:{peakWindingC:M,derateTimeFrac:J>0?F/J:0,lossKwh:w}}:{},...Ae?{brakes:{...Ae.front?{front:hS(Ae.front)}:{},...Ae.rear?{rear:hS(Ae.rear)}:{}}}:{}}),S=ne}if(!S){let K=Yb(t);S=Rt(Ii(t.ggv,t.vehicle,u),n,t.numerics,{standingStart:a,...t.load?{load:t.load.atSoc(t.vehicle,u)}:{},...K?{shifts:K}:{}}),A=A??{lapsCompleted:0,lapsAsked:o,why:"the pack was empty"}}let G=g.length;return{id:e.id,label:e.label,kind:e.kind,time:p,distance:n.length*G,laps:G,lapTime:S.laptime,trace:{v:S.v,ax:S.ax,ay:S.ay,s:n.s,x:n.x,y:n.y,...n.gradient.some(K=>K!==0)?{gradient:n.gradient}:{},...n.bank.some(K=>K!==0)?{bank:n.bank}:{},...n.z.some(K=>K!==0)?{z:n.z}:{},...n.mu.some(K=>K!==1)?{mu:n.mu}:{},...S.loadFactor?{loadFactor:S.loadFactor}:{},...S.axScrub?{axScrub:S.axScrub}:{},...A2(S)},energy:{consumed:d,loss:h,...ft(i.motorModel)?{}:{native:{value:b,unit:"Ah"}},remainingFraction:ft(i.motorModel)?1:u,...y?{motor:{peakWindingC:R,derateTimeFrac:p>0?k/p:0,lossKwh:v}}:{}},lapLog:g,...A?{incomplete:A}:{}}}var zb=.05;function hS(e){let t=r=>e.workJ>0?r/e.workJ:0;return{startC:e.startC,endC:e.endC,maxC:e.maxC,workKj:e.workJ/1e3,coldShare:t(e.coldWorkJ),hotShare:t(e.hotWorkJ)}}var _2=4,N2=.001;function O2(e,t){return e===t?!1:!Number.isFinite(e)||!Number.isFinite(t)?!0:Math.abs(e-t)>N2*Math.max(1,Math.abs(t))}function xS(e,t,r,n,o,a){return V2(e,t,o,()=>({v:r,ax:n,...a?{lateral:a}:{}}))}function V2(e,t,r,n){let o=e.energyOpts,a=e.vehicle.params.soc.value,s=0,i=0,c=0;for(let l=0;l<r;l++){let u=n(l),m=wa(e.vehicle,t,u.v,u.ax,o,a,void 0,void 0,void 0,void 0,u.lateral);s+=m.net,i+=m.loss,c+=m.chargeAh,a=m.socEnd}return ft(e.vehicle.params.motorModel)?{consumed:s,loss:i,remainingFraction:1}:{consumed:s,loss:i,native:{value:c,unit:"Ah"},remainingFraction:a}}function RS(e,t){switch(e.kind){case"straightLineAccel":return F2(e,t);case"constantRadius":return w2(e,t);case"trackLap":return L2(e,t)}}function Wb(e,t){let r={};for(let n of e)r[n.id]=RS(n,t);return r}function vS(e,t){if(e.kind!=="trackLap")return e;let{distance:r,...n}=e;return{...n,laps:Math.max(1,Math.round(t))}}function ao(e,t,r,n,o="twoTrack",a){let s=1/0,i=-1/0;for(let f of r){let p=wi(f);if(!p)continue;let d=oM(p,Rt(t,f,n).v);d&&(s=Math.min(s,d.lo),i=Math.max(i,d.hi))}if(!(i>=s))return;let c=aM({lo:s,hi:i}),l=c.join(","),u=a?.get(l);if(u)return u;let m=oS(e,c,t,o);return a?.set(l,m),m}var Ni=e=>e.distance/Math.max(1,e.laps);function Oi(e){let t=e.s.length,r=new Array(t);for(let n=0;n<t;n++)r[n]=(n<t-1?e.s[n+1]:e.length)-e.s[n];return r}var B2=e=>e.v.map(t=>t*3.6),$2=e=>e.ax.map(t=>t/9.81),G2=e=>e.ay.map(t=>t/9.81),K2=e=>e.ay.map((t,r)=>e.v[r]>1e-6?t/(e.v[r]*e.v[r]):0),um=(e,t,r)=>e?.slice()??new Array(t.s.length).fill(r),H2=e=>um(e.z,e,0),z2=e=>e.gradient?e.gradient.map(t=>100*Math.tan(t*Math.PI/180)):um(void 0,e,0),Y2=e=>um(e.bank,e,0),W2=e=>um(e.mu,e,1);function j2(e){let t=e.s.length,r=Oi(e),n=new Array(t);n[0]=0;for(let o=1;o<t;o++)n[o]=n[o-1]+2*r[o-1]/(e.v[o-1]+e.v[o]);return n}var jb=[{name:"s",unit:"m",what:"distance along the lap"},{name:"ds",unit:"m",what:"length of the segment starting at this sample"},{name:"t",unit:"s",what:"elapsed time"},{name:"v",unit:"m/s",what:"speed"},{name:"speed",unit:"km/h",what:"speed"},{name:"ax",unit:"m/s\xB2",what:"longitudinal acceleration"},{name:"ay",unit:"m/s\xB2",what:"lateral acceleration"},{name:"axg",unit:"g",what:"longitudinal acceleration"},{name:"ayg",unit:"g",what:"lateral acceleration"},{name:"curv",unit:"1/m",what:"signed curvature, ay/v\xB2"},{name:"z",unit:"m",what:"elevation of the road"},{name:"grade",unit:"%",what:"grade of the road, uphill +"},{name:"bank",unit:"\xB0",what:"bank of the road, left side up +"},{name:"grip",unit:"-",what:"grip scale of the road, 1 = the tyre\u2019s own"}];function kS(e){let t=Oi(e);return{ds:t,vars:{s:e.s,ds:t,t:j2(e),v:e.v,speed:B2(e),ax:e.ax,ay:e.ay,axg:$2(e),ayg:G2(e),curv:K2(e),z:H2(e),grade:z2(e),bank:Y2(e),grip:W2(e)}}}function MS(e,t){return{v:e.v,ax:e.ax,ay:e.ay,ds:Oi({s:e.s,length:t}),axGrade:yn(e.gradient,e.v.length),...e.bank?{bank:e.bank}:{},...e.loadFactor?{loadFactor:e.loadFactor}:{}}}function SS(e,t){let r=dt(e);return{pastTurnover:HM(r,mr(e),t),...e.aeroModel?{aeroOutside:KM(r,t)}:{}}}var mm="Flying lap";function Ub(e,t){return e.kind!=="trackLap"||e.label!==mm?e.label:e.standingStart??t?"Run":e.label}function U2(e){let t=dt(e);return{yawInertia:t.yawInertia??0,massTotal:t.massTotal,wheelbase:t.wheelbase/1e3}}function X2(e,t,r){let n=e.params,o=n.ggvMode??"twoTrack",a=n.quasiTransient?nS(e,!1,o):null,s=a?a.steady:pr(e,!1,o),i=t?ao(e,s,[t],r,o):void 0;return{ggv:s,...a?{yaw:{family:a,car:U2(n)}}:{},...i?{load:i}:{}}}function q2(e,t){let r=t.lapCounts,n=t.standingStart??!1,o=!1,a=e.events.map(s=>{let i=r?.[s.id]!=null?vS(s,r[s.id]):s,c=Ub(i,n),l=c===i.label?i:{...i,label:c};return l!==s&&(o=!0),l});return o?a:e.events}function Q2(e,t,r){let n=r.lapCounts;if(!(!n||!r.track))for(let o of t.events){let a=n[o.id];if(o.kind!=="trackLap"||a==null)continue;let s=lm(o,r.track),i=Math.max(1,Math.round(a));i!==s&&e[o.id]&&(e[o.id]={...e[o.id],lapsOverridden:{asked:i,defined:s}})}}function Z2(e,t){for(let[r,n]of Object.entries(e))n.trace&&(e[r]={...n,...SS(t,MS(n.trace,Ni(n)))})}function Vi(e,t,r={}){let n=Ft(e),o=X2(n,r.track,r.numerics),{ggv:a}=o,s=Wb(q2(t,r),{vehicle:n,...o,track:r.track,energyOpts:Dr(e,r.energyOpts),numerics:r.numerics,standingStart:r.standingStart});return Q2(s,t,r),Z2(s,n.params),{name:e.name,rulesetId:t.id,events:s,ggv:a}}function Xb(e){return{...e,ggv:{rows:e.ggv.rows,vMax:e.ggv.vMax,surf:e.ggv.surf}}}var qb=["<","<=",">",">=","==","!="],Ne=class extends Error{at;constructor(t,r){super(t),this.name="ExprError",this.at=r}},Bi=e=>e>="0"&&e<="9",AS=e=>/[A-Za-z_]/.test(e),J2=e=>/[A-Za-z0-9_]/.test(e);function e_(e){let t=[],r=0;for(;r<e.length;){let n=e[r];if(n===" "||n===" "||n===`
224
- `||n==="\r"){r++;continue}if(Bi(n)||n==="."&&Bi(e[r+1]??"")){let o=r;for(;r<e.length&&(Bi(e[r])||e[r]===".");)r++;if(e[r]==="e"||e[r]==="E"){let i=r;if(r++,(e[r]==="+"||e[r]==="-")&&r++,Bi(e[r]??""))for(;r<e.length&&Bi(e[r]);)r++;else r=i}let a=e.slice(o,r),s=Number(a);if(!Number.isFinite(s))throw new Ne(`"${a}" is not a number`,o);t.push({t:"num",value:s,at:o});continue}if(AS(n)){let o=r;for(;;){for(;r<e.length&&J2(e[r]);)r++;if(e[r]==="."&&AS(e[r+1]??""))r++;else break}t.push({t:"name",value:e.slice(o,r),at:o});continue}if("<>=!".includes(n)){let o=e.slice(r,r+2);if(qb.includes(o)){t.push({t:"op",value:o,at:r}),r+=2;continue}if(n==="<"||n===">"){t.push({t:"op",value:n,at:r}),r++;continue}throw new Ne(n==="="?'Compare with "==", not "="':'Write not(x) rather than "!x"',r)}if("+-*/^(),".includes(n)){t.push({t:"op",value:n,at:r}),r++;continue}throw new Ne(`"${n}" is not something this expression can contain`,r)}return t.push({t:"end",at:e.length}),t}function Qb(e){let t=e_(e),r=0,n=()=>t[r],o=h=>{let b=n();return b.t==="op"&&b.value===h},a=h=>o(h)?(r++,!0):!1,s=(h,b)=>{if(!a(h))throw new Ne(`Expected ${b} here`,n().at)};function i(){let h=c(),b=n();if(b.t!=="op"||!qb.includes(b.value))return h;r++;let g={kind:"binary",op:b.value,left:h,right:c(),at:b.at},y=n();if(y.t==="op"&&qb.includes(y.value))throw new Ne("Comparisons do not chain \u2014 write and(a < b, b < c)",y.at);return g}function c(){let h=l();for(;;){let b=n().at;if(a("+"))h={kind:"binary",op:"+",left:h,right:l(),at:b};else if(a("-"))h={kind:"binary",op:"-",left:h,right:l(),at:b};else return h}}function l(){let h=u();for(;;){let b=n().at;if(a("*"))h={kind:"binary",op:"*",left:h,right:u(),at:b};else if(a("/"))h={kind:"binary",op:"/",left:h,right:u(),at:b};else return h}}function u(){return a("-")?{kind:"unary",op:"-",arg:u()}:a("+")?u():m()}function m(){let h=f(),b=n().at;return a("^")?{kind:"binary",op:"^",left:h,right:u(),at:b}:h}function f(){let h=n();if(h.t==="num")return r++,{kind:"num",value:h.value};if(h.t==="name"){if(r++,a("(")){let b=[];if(!o(")"))do b.push(i());while(a(","));return s(")","a closing bracket"),{kind:"call",name:h.value,args:b,at:h.at}}return{kind:"var",name:h.value,at:h.at}}if(a("(")){let b=i();return s(")","a closing bracket"),b}throw h.t==="end"?new Ne("The expression ends before it is finished",h.at):new Ne(`"${h.value}" cannot start a value`,h.at)}let p=i(),d=n();if(d.t!=="end")throw new Ne(`"${d.value}" is left over \u2014 check for a missing operator`,d.at);return p}function Zb(e){let t=new Set,r=n=>{n.kind==="var"?t.add(n.name):n.kind==="call"?n.args.forEach(r):n.kind==="unary"?r(n.arg):n.kind==="binary"&&(r(n.left),r(n.right))};return r(e),t}var $i=(e,t)=>typeof e=="number"?new Array(t).fill(e):e;function t_(e){let t=1;for(let r of e)Array.isArray(r)&&(t=Math.max(t,r.length));return t}function Tt(e,t){if(e.every(a=>typeof a=="number"))return t(...e);let r=t_(e),n=e.map(a=>$i(a,r)),o=new Array(r);for(let a=0;a<r;a++)o[a]=t(...n.map(s=>s[Math.min(a,s.length-1)]));return o}var Oe=(e,t)=>({arity:e,call:r=>Tt(r,t)}),so=e=>e!==0&&!Number.isNaN(e),dr=e=>e?1:0;function FS(e,t,r){let n=wS(t,r,"integrate"),o=n.length,a=$i(e,o),s=new Array(o),i=0;for(let c=0;c<o;c++){s[c]=i;let l=a[Math.min(c,a.length-1)],u=a[Math.min(c+1,a.length-1)];i+=(l+u)/2*n[c]}return s}function wS(e,t,r){if(!e.ds||e.ds.length===0)throw new Ne(`${r}() needs to know the sample spacing, and this context has none`,t);return e.ds}var pm={abs:Oe(1,Math.abs),sqrt:Oe(1,Math.sqrt),sign:Oe(1,Math.sign),floor:Oe(1,Math.floor),ceil:Oe(1,Math.ceil),round:Oe(1,Math.round),exp:Oe(1,Math.exp),log:Oe(1,Math.log),sin:Oe(1,Math.sin),cos:Oe(1,Math.cos),tan:Oe(1,Math.tan),atan:Oe(1,Math.atan),atan2:Oe(2,Math.atan2),hypot:Oe(2,Math.hypot),min:Oe(2,Math.min),max:Oe(2,Math.max),clamp:Oe(3,(e,t,r)=>Math.min(r,Math.max(t,e))),if:Oe(3,(e,t,r)=>so(e)?t:r),and:Oe(2,(e,t)=>dr(so(e)&&so(t))),or:Oe(2,(e,t)=>dr(so(e)||so(t))),not:Oe(1,e=>dr(!so(e))),finite:Oe(1,e=>dr(Number.isFinite(e))),peak:{arity:1,call:([e])=>{let t=Array.isArray(e)?e:[e],r=0;for(let n of t)r=Math.max(r,Math.abs(n));return r}},mean:{arity:1,call:([e])=>{let t=Array.isArray(e)?e:[e];return t.length?t.reduce((r,n)=>r+n,0)/t.length:0}},total:{arity:1,call:([e],t)=>{let r=FS(e,t,0),n=t.ds,o=$i(e,n.length),a=n.length-1;return r[a]+(o[a]+o[0])/2*n[a]}},integrate:{arity:1,call:([e],t)=>FS(e,t,0)},cum:{arity:1,call:([e],t)=>{let r=t.ds?.length??(Array.isArray(e)?e.length:1),n=$i(e,r),o=new Array(r),a=0;for(let s=0;s<r;s++)a+=n[Math.min(s,n.length-1)],o[s]=a;return o}},deriv:{arity:1,call:([e],t)=>{let r=wS(t,0,"deriv"),n=r.length,o=$i(e,n),a=new Array(n);for(let s=0;s<n;s++){let i=Math.max(0,s-1),c=Math.min(n-1,s+1),l=0;for(let u=i;u<c;u++)l+=r[u];a[s]=l>0?(o[c]-o[i])/l:0}return a}}},Ia={g:9.81,pi:Math.PI,e:Math.E,nan:NaN,inf:1/0},Gi={fleetmin:"min",fleetmax:"max"};function io(e){switch(e.kind){case"call":return Object.hasOwn(Gi,e.name)||e.args.some(io);case"unary":return io(e.arg);case"binary":return io(e.left)||io(e.right);default:return!1}}var r_=e=>typeof e=="number"?`${e}`:`between ${e[0]} and ${e[1]}`;function n_(e,t){let r=Array.from({length:t.length+1},(n,o)=>o);for(let n=1;n<=e.length;n++){let o=[n];for(let a=1;a<=t.length;a++)o[a]=Math.min(r[a]+1,o[a-1]+1,r[a-1]+(e[n-1]===t[a-1]?0:1));r=o}return r[t.length]}function o_(e,t){let r=t.map(c=>({k:c,d:n_(c,e)})).filter(c=>c.d<=Math.max(1,Math.floor(e.length/4))),n=Math.min(...r.map(c=>c.d)),o=r.filter(c=>c.d===n).map(c=>c.k).slice(0,3);if(o.length)return`"${e}" is not a name here \u2014 did you mean ${o.join(" or ")}?`;let a=e.indexOf(".");if(a>0){let c=t.filter(l=>l.startsWith(e.slice(0,a+1)));if(c.length)return`"${e}" is not a name here. ${e.slice(0,a)} has ${c.join(", ")}`}let s=new Set,i=[];for(let c of t){let l=c.indexOf(".");l>0?s.add(`${c.slice(0,l)}.\u2026`):i.push(c)}return`"${e}" is not a name here. Available: ${[...s,...i].join(", ")}`}function fr(e,t){switch(e.kind){case"num":return e.value;case"var":{if(Object.hasOwn(t.vars,e.name))return t.vars[e.name];if(Object.hasOwn(Ia,e.name))return Ia[e.name];let r=[...Object.keys(t.vars),...Object.keys(Ia)].sort();throw new Ne(o_(e.name,r),e.at)}case"unary":return Tt([fr(e.arg,t)],r=>-r);case"binary":{let r=fr(e.left,t),n=fr(e.right,t);switch(e.op){case"+":return Tt([r,n],(o,a)=>o+a);case"-":return Tt([r,n],(o,a)=>o-a);case"*":return Tt([r,n],(o,a)=>o*a);case"/":return Tt([r,n],(o,a)=>a===0?0:o/a);case"^":return Tt([r,n],(o,a)=>o**a);case"<":return Tt([r,n],(o,a)=>dr(o<a));case"<=":return Tt([r,n],(o,a)=>dr(o<=a));case">":return Tt([r,n],(o,a)=>dr(o>a));case">=":return Tt([r,n],(o,a)=>dr(o>=a));case"==":return Tt([r,n],(o,a)=>dr(o===a));case"!=":return Tt([r,n],(o,a)=>dr(o!==a))}break}case"call":{let r=Object.hasOwn(Gi,e.name)?Gi[e.name]:void 0;if(r){if(!t.fleet)throw new Ne(`${e.name}() compares the cars in a field, so it belongs in a ruleset's KPIs, not in a channel`,e.at);if(e.args.length!==1)throw new Ne(`${e.name}() takes 1 argument, not ${e.args.length}`,e.at);return t.fleet(e.args[0],r,e.at)}let n=Object.hasOwn(pm,e.name)?pm[e.name]:void 0;if(!n){let s=[...Object.keys(pm),...t.fleet?Object.keys(Gi):[]];throw new Ne(`There is no function called "${e.name}". Available: ${s.sort().join(", ")}`,e.at)}let o=typeof n.arity=="number"?n.arity:n.arity[0],a=typeof n.arity=="number"?n.arity:n.arity[1];if(e.args.length<o||e.args.length>a)throw new Ne(`${e.name}() takes ${r_(n.arity)} argument${o===1&&a===1?"":"s"}, not ${e.args.length}`,e.at);return n.call(e.args.map(s=>fr(s,t)),t)}}throw new Ne("Unreachable node",0)}var _a=e=>Number.isFinite(e)?e:NaN,Jb=[{name:"time",unit:"s",what:"the whole event, every lap",read:e=>_a(e?.time)},{name:"lapTime",unit:"s",what:"one lap \u2014 the last one completed",read:e=>_a(e?.lapTime)},{name:"distance",unit:"m",what:"distance covered",read:e=>_a(e?.distance)},{name:"laps",unit:"-",what:"laps completed",read:e=>_a(e?.laps)},{name:"energy",unit:"kWh",what:"energy drawn over the event",read:e=>_a(e?.energy?.consumed)},{name:"remaining",unit:"-",what:"share of the pack or tank left afterwards",read:e=>_a(e?.energy?.remainingFraction)},{name:"finished",unit:"-",what:"1 when the car ran the whole event, else 0",read:e=>e&&!e.incomplete?1:0}],CS=/^[A-Za-z_][A-Za-z0-9_]*$/,a_=new Set([...Object.keys(Ia),...jb.map(e=>e.name)]);function dm(e,t,r=[]){let n=[],o=new Set(r),a=t.map(b=>b.id),s=new Set;for(let b of a)CS.test(b)?s.has(b)&&n.push({key:null,message:`Two events are called "${b}"`}):n.push({key:null,message:`Event id "${b}" must be one word to be read as ${b}.time`}),s.add(b);let i=new Map,c=new Map;for(let b of e){if(!CS.test(b.key)){n.push({key:b.key,message:`"${b.key}" must be one word \u2014 letters, digits and _`});continue}if(a_.has(b.key)||o.has(b.key)){n.push({key:b.key,message:`"${b.key}" already means something in a formula \u2014 choose another key`});continue}if(i.has(b.key)){n.push({key:b.key,message:`Two KPIs are called "${b.key}"`});continue}i.set(b.key,b),b.over!=null&&!a.includes(b.over)&&n.push({key:b.key,message:`There is no event "${b.over}" to read the lap of. Events: ${a.join(", ")}`});try{c.set(b.key,Qb(b.expr))}catch(g){let y=g;n.push({key:b.key,message:y.message,at:y.at})}}let l=new Map;for(let[b,g]of c)l.set(b,[...Zb(g)].filter(y=>i.has(y)));let u=new Set,m=[];for(;;){let b=[...c.keys()].find(g=>!u.has(g)&&l.get(g).every(y=>u.has(y)||!c.has(y)));if(!b)break;u.add(b),m.push(b)}for(let b of c.keys()){if(u.has(b))continue;let g=s_(b,l);n.push({key:b,message:g?`"${b}" depends on itself, through ${g.join(" \u2192 ")}`:`"${b}" reads a KPI that depends on itself`})}let f=(b,g,y)=>{throw new Ne("fleetmin() and fleetmax() cannot sit inside one another",y)},p=new Set,d={};for(let b of a)for(let g of Jb)d[`${b}.${g.name}`]=1;for(let b of o)d[b]=1;for(let b of i.keys())d[b]=1;let h={};for(let b of jb)h[b.name]=[1,1];for(let b of m){let g=i.get(b),y=c.get(b);(io(y)||l.get(b).some(x=>p.has(x)))&&p.add(b);let R=g.over!=null?{...d,...h}:d,k=g.over!=null?[1,1]:void 0,v=(x,M,F)=>{let w=fr(x,{vars:R,ds:k,fleet:f});if(Array.isArray(w))throw new Ne("fleetmin() and fleetmax() compare one number per car \u2014 reduce the channel first, e.g. peak(v)",F);return w};try{let x=fr(y,{vars:R,ds:k,fleet:v});Array.isArray(x)&&n.push({key:b,message:"A KPI is one number per car \u2014 reduce the channel, e.g. peak(v) or mean(v)",at:0})}catch(x){let M=x;n.push({key:b,message:M.message,at:M.at})}}return n.length?{plan:null,problems:n}:{plan:{order:m.map(b=>({def:i.get(b),node:c.get(b)})),field:p,eventIds:a},problems:n}}function s_(e,t){let r=[e],n=o=>{for(let a of t.get(o)??[]){if(a===e)return!0;if(!r.includes(a)){if(r.push(a),n(a))return!0;r.pop()}}return!1};return n(e)?[...r,e]:null}function i_(e,t,r={}){let n={...r};for(let o of e.eventIds){let a=t.events[o];for(let s of Jb)n[`${o}.${s.name}`]=s.read(a)}return{vars:n,laps:new Map,events:t.events}}function TS(e,t){if(t.over==null)return{vars:e.vars};let r=e.laps.get(t.over);if(r===void 0){let n=e.events[t.over];r=n?.trace?kS({...n.trace,length:Ni(n)}):null,e.laps.set(t.over,r)}return r?{vars:{...e.vars,...r.vars},ds:r.ds}:null}var PS=e=>Array.isArray(e)?NaN:e;function LS(e,t,r,n={}){let o=Object.keys(t),a=o.map(i=>i_(e,t[i],n[i]));for(let{def:i,node:c}of e.order){let l=e.field.has(i.key);if(l&&!r){for(let f of a)f.vars[i.key]=NaN;continue}let u=new Map,m=(f,p)=>{let d=u.get(f);if(d!==void 0)return d;let h=NaN;for(let b of a){let g=TS(b,i);if(!g)continue;let y=PS(fr(f,g));Number.isFinite(y)&&(Number.isNaN(h)||(p==="min"?y<h:y>h))&&(h=y)}return u.set(f,h),h};for(let f of a){let p=TS(f,i);f.vars[i.key]=p?PS(fr(c,l?{...p,fleet:m}:p)):NaN}}let s={};return o.forEach((i,c)=>{let l={};for(let{def:u}of e.order)l[u.key]=a[c].vars[u.key];s[i]=l}),s}function Ki(e,t,r){return LS(e,t,!0,r)}function eg(e,t,r){return LS(e,{car:t},!1,r?{car:r}:void 0).car}var fm=class extends Error{problems;constructor(t,r){super(`Ruleset "${t}" does not compile:
223
+ `}function Fr(e){let t=$s(Tv(e),e.name);return{...t,missing:[...t.missing??[],"a particular tyre \u2014 every coefficient is derived from class-level targets stated in generic.ts, on the road; run it with grip_scale = stiffness_scale = 1"]}}var Pv={name:"Formula Student 18x6-10",R0:.228,width:.1524,Fz0:950,Kz:110,pressure:83,muY:1.8,muX:1.7,muYLoad:-.2,muXLoad:-.15,corneringStiffness:26e3,slipStiffnessPerLoad:32,camberStiffness:45,Cy:1.5,Cx:1.6,RBY1:12,RBY2:12,RBX1:13,RBX2:10,trail:.08},Lv={name:"Formula 1 slick 18in",R0:.36,width:.305,Fz0:5e3,Kz:300,pressure:150,muY:1.8,muX:1.7,muYLoad:-.15,muXLoad:-.12,corneringStiffness:15e4,slipStiffnessPerLoad:28,camberStiffness:260,Cy:1.45,Cx:1.6,RBY1:12,RBY2:12,RBX1:13,RBX2:10,trail:.09},Dv={name:"GT slick 18in",R0:.33,width:.3,Fz0:4e3,Kz:280,pressure:180,muY:1.45,muX:1.4,muYLoad:-.12,muXLoad:-.1,corneringStiffness:11e4,slipStiffnessPerLoad:24,camberStiffness:190,Cy:1.4,Cx:1.6,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.09},Ev={name:"Street tyre 245/40 R18",R0:.325,width:.245,Fz0:4e3,Kz:220,pressure:240,muY:1.05,muX:1,muYLoad:-.1,muXLoad:-.08,corneringStiffness:75e3,slipStiffnessPerLoad:20,camberStiffness:100,Cy:1.3,Cx:1.55,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.12},Iv={name:"Cup slick 18in",R0:.32,width:.25,Fz0:3500,Kz:280,pressure:180,muY:1.42,muX:1.38,muYLoad:-.12,muXLoad:-.1,corneringStiffness:9e4,slipStiffnessPerLoad:24,camberStiffness:160,Cy:1.4,Cx:1.6,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.09},_v={name:"Stock car slick 18in",R0:.357,width:.32,Fz0:4500,Kz:320,pressure:200,muY:1.35,muX:1.3,muYLoad:-.12,muXLoad:-.1,corneringStiffness:125e3,slipStiffnessPerLoad:22,camberStiffness:170,Cy:1.4,Cx:1.6,RBY1:11,RBY2:11,RBX1:12,RBX2:10,trail:.09},Nv={name:"Hill-climb slick 13in",R0:.3,width:.3,Fz0:2e3,Kz:200,pressure:150,muY:1.75,muX:1.65,muYLoad:-.18,muXLoad:-.14,corneringStiffness:6e4,slipStiffnessPerLoad:28,camberStiffness:90,Cy:1.45,Cx:1.6,RBY1:12,RBY2:12,RBX1:13,RBX2:10,trail:.085},Ov={name:"Race truck tyre 315/70 R22.5",R0:.506,width:.315,Fz0:13e3,Kz:1e3,pressure:800,muY:1.1,muX:1.05,muYLoad:-.1,muXLoad:-.08,corneringStiffness:15e4,slipStiffnessPerLoad:14,camberStiffness:200,Cy:1.3,Cx:1.55,RBY1:10,RBY2:10,RBX1:11,RBX2:10,trail:.1},Nf=()=>Fr(Pv),Of=()=>Fr(Lv),Vf=()=>Fr(Dv),Bf=()=>Fr(Ev),$f=()=>Fr(Iv),Gf=()=>Fr(_v),Kf=()=>Fr(Nv),Hf=()=>Fr(Ov);var Vv=e=>Number.isFinite(e)&&e>0;function Kl(e,t){let r=Vv(t.grip)?t.grip:1,n=Vv(t.stiffness)?t.stiffness:1;if(r===1&&n===1)return e;if(e.kind==="simple"){let o=n/r;return{...e,muX0:e.muX0*r,muY0:e.muY0*r,loadSensX:e.loadSensX*r,loadSensY:e.loadSensY*r,Bx:e.Bx*o,By:e.By*o}}return{...e,coeffs:{...e.coeffs,LMUX:(e.coeffs.LMUX??1)*r,LMUY:(e.coeffs.LMUY??1)*r,LKX:(e.coeffs.LKX??1)*n,LKY:(e.coeffs.LKY??1)*n}}}var Ks={ok:!0,violation:0},Gn=1e7;function wr(e,t){let r;try{r=e.build(t)}catch(s){return{total:Gn*2,feasible:!1,terms:[],reason:`build failed: ${String(s)}`}}let n=e.feasible(r);if(!n.ok)return{total:Gn+Math.max(0,n.violation),feasible:!1,terms:[],reason:n.reason};let o;try{o=e.terms(r)}catch(s){return{total:Gn*2,feasible:!1,terms:[],reason:`objective threw: ${String(s)}`}}let a=0;for(let s of o)a+=s.contribution;return Number.isFinite(a)?{total:a,feasible:!0,terms:o}:{total:Gn*2,feasible:!1,terms:o,reason:"objective was not finite"}}var Hs=(e,t)=>!t||(e.feasible!==t.feasible?e.feasible:e.total<t.total);function zf(e,t){return t.map((r,n)=>Math.min(e[n].hi,Math.max(e[n].lo,r)))}var Cr=e=>e.map(t=>t.start);function Hl(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 bL(e){let t=0;for(;t===0;)t=e();return Math.sqrt(-2*Math.log(t))*Math.cos(2*Math.PI*e())}function Yf(e,t){let{budget:r}=t,n=Math.max(1,Math.floor(t.progressEvery??1)),o=e.variables,a=p=>zf(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=wr(e,a(d));h.feasible||c++;let b=Hs(h,l)?h:l;return b===h&&(l=h,u=d),m.push(b.total),t.onProgress&&(i%n===0||i===r)&&t.onProgress({evaluations:i,budget:r,x:a(u),score:b,infeasible:c}),h.total},left:()=>r-i,result:p=>({method:p,x:u?a(u):Cr(o),score:l??wr(e,Cr(o)),evaluations:i,history:m,infeasible:c})}}var Wf=(e,t,r,n=0,o)=>{let a=t?r.norm(Cr(e.variables)):e.variables.map(()=>.5);return!(n>0)||!o?a:a.map(s=>Math.min(1,Math.max(0,s+n*2*(o()-.5))))};function Bv(e,t){let r=Yf(e,t),n=Hl(t.seed??1),o=e.variables.length;for(r.evaluate(Wf(e,t.warmStart!==!1,r,t.startJitter,n));r.left()>0;){let a=[];for(let s=0;s<o;s++)a.push(n());r.evaluate(a)}return r.result("random")}function sa(e,t){let r=Yf(e,t),n=e.variables.length,o=Hl(t.seed??1),a=1,s=2,i=.5,c=.5,l=Wf(e,t.warmStart!==!1,r,t.startJitter,o),u=.25;for(;r.left()>0;){let m=[{u:l,f:r.evaluate(l)}];for(let f=0;f<n&&r.left()>0;f++){let p=l.slice();p[f]+=p[f]+u>1?-u:u,m.push({u:p,f:r.evaluate(p)})}for(;r.left()>0;){m.sort((g,y)=>g.f-y.f);let f=m[n],p=new Array(n).fill(0);for(let g=0;g<n;g++)for(let y=0;y<n;y++)p[y]+=m[g].u[y]/n;let d=g=>p.map((y,R)=>y+g*(y-f.u[R])),h=d(a),b=r.evaluate(h);if(b<m[0].f){let g=d(s),y=r.evaluate(g);m[n]=y<b?{u:g,f:y}:{u:h,f:b}}else if(b<m[n-1].f)m[n]={u:h,f:b};else{let g=d(-i),y=r.evaluate(g);if(y<f.f)m[n]={u:g,f:y};else{let R=m[0],k=0;for(let v=1;v<=n;v++)for(let x=0;x<n;x++)k=Math.max(k,Math.abs(m[v].u[x]-R.u[x]));if(k<1e-4)break;for(let v=1;v<=n&&r.left()>0;v++){let x=m[v].u.map((M,F)=>R.u[F]+c*(M-R.u[F]));m[v]={u:x,f:r.evaluate(x)}}}}}m.sort((f,p)=>f.f-p.f),l=m[0].u.map(f=>Math.min(1,Math.max(0,f+.05*(o()-.5)))),u=Math.max(.02,u*.5)}return r.result("nelder-mead")}function $v(e,t){let r=Yf(e,t),n=e.variables.length,o=Hl(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=Wf(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(bL(o));let P=g.map((L,D)=>L+y*R[D]*A[D]);M.push({z:A,u:P,f:r.evaluate(P)})}if(M.length<s)break;M.sort((S,A)=>S.f-A.f);let F=g.slice(),w=new Array(n).fill(0);g=new Array(n).fill(0);for(let S=0;S<s;S++)for(let A=0;A<n;A++)g[A]+=i[S]*M[S].u[A],w[A]+=i[S]*M[S].z[A];g=g.map(S=>Math.min(1,Math.max(0,S)));for(let S=0;S<n;S++)k[S]=(1-u)*k[S]+Math.sqrt(u*(2-u)*l)*w[S];let C=Math.sqrt(k.reduce((S,A)=>S+A*A,0)),T=C/Math.sqrt(1-(1-u)**(2*x))/b<1.4+2/(n+1)?1:0;for(let S=0;S<n;S++){let A=(g[S]-F[S])/(y*R[S]);v[S]=(1-f)*v[S]+T*Math.sqrt(f*(2-f)*l)*A}for(let S=0;S<n;S++){let A=0;for(let D=0;D<s;D++)A+=i[D]*M[D].z[S]*M[D].z[S];let P=R[S]*R[S],L=(1-d-h)*P+d*(v[S]*v[S]+(1-T)*f*(2-f)*P)+h*A*P;R[S]=Math.sqrt(Math.max(1e-12,L))}if(y*=Math.exp(u/m*(C/b-1)),y<1e-6||y>10)break}return r.result("sep-cma-es")}var ia=[{name:"random",run:Bv},{name:"nelder-mead",run:sa},{name:"sep-cma-es",run:$v}];var VH=Math.PI/180;var zl=Math.PI/180;var KH={Fz:100,alpha:.25*zl,kappa:.005,gamma:.5*zl,p:6900},Gv={Fz:100,alpha:1*zl,kappa:.02,gamma:.5*zl,p:6900};var Kv=Math.PI/180,UH={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 JH=Math.PI/180;var CL=Math.PI/180;var sz=3*CL;var mz=Math.PI/180;var Mz=Math.PI/180;var NL={RCX1:1,RCY1:1,REX1:0,REY1:0,RBY3:0,RHX1:0,RHY1:0},Yv={RBX1:15,RBX2:15,RBY1:18,RBY2:19,...NL};var Iz=Math.PI/180;var KL=Math.PI/180,Yl=[{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"}],Xz=new Map(Yl.map(e=>[e.id,e]));var Qz=.01*KL;var We=Math.PI/180;var Uv=new Set(Yl.filter(e=>e.group!=="inputs"&&(e.unit==="N"||e.unit==="N\xB7m"||e.unit==="N/rad")).map(e=>e.id)),Xv={alpha:{from:-15*We,to:15*We,n:61},kappa:{from:-.25,to:.25,n:61},gamma:{from:-6*We,to:6*We,n:49},Fz:{from:200,to:3e3,n:40,follow:!0},p:{from:5e4,to:15e4,n:21},V:{from:0,to:40,n:41,follow:!0}},qf={alpha:{from:0,to:12*We,n:7},kappa:{from:-.2,to:.2,n:9},gamma:{from:-4*We,to:4*We,n:5},Fz:{from:400,to:1600,n:5},p:{from:6e4,to:12e4,n:4},V:{from:5,to:35,n:4}};var Zf={alpha:{from:0,to:12*We,n:25},kappa:{from:-.2,to:.2,n:25},gamma:{from:-4*We,to:4*We,n:17},Fz:{from:300,to:1800,n:16},p:{from:6e4,to:12e4,n:13},V:{from:5,to:35,n:13}};var ke=(e,t,r,n={},o={})=>({id:e,form:"curves",sweep:[{input:t,...Xv[t],...o}],x:t,y:r,...n}),Wl=(e,[t,r],n,o,a={})=>({id:e,form:"carpet",sweep:[{input:t,...qf[t]},{input:r,...qf[r]}],x:n,y:[o],...a}),Tr=(e,t)=>({id:e,fixed:t}),Bt={input:"Fz",values:"car"},Qf={alpha:0,kappa:0},yt={kappa:0},Wv={alpha:0},zL={input:"Fz",values:[500,1e3,1500]},YL=[{id:"overview",name:"Overview",cards:[Tr("tyre","tyre"),ke("fy","alpha",["Fy"],{title:"Lateral force",hold:yt}),ke("mz","alpha",["Mz"],{title:"Aligning moment",hold:yt}),ke("fx","kappa",["Fx"],{title:"Longitudinal force",hold:Wv}),Wl("combined-carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Tr("ellipse","ellipse")]},{id:"lateral",name:"Lateral",cards:[ke("fy-load","alpha",["Fy"],{title:"Lateral force per wheel load",series:Bt,hold:yt}),ke("muy-load","alpha",["muY"],{title:"Lateral force per unit load",series:Bt,hold:yt}),ke("fy-peak","alpha",["Fy"],{title:"Lateral force over its peak",series:Bt,hold:yt,scale:{per:"peak"}},{from:0,to:15*We,n:61}),ke("muy-peak","Fz",["muYPeak"],{title:"Peak lateral \u03BC over load"}),ke("calpha","Fz",["Calpha"],{title:"Cornering stiffness over load"}),ke("alpha-peak","Fz",["alphaPeak"],{title:"Slip angle at the peak over load"})]},{id:"aligning",name:"Aligning",cards:[ke("mz-load","alpha",["Mz"],{title:"Aligning moment per wheel load",series:Bt,hold:yt}),ke("trail","alpha",["t"],{title:"Pneumatic trail",series:Bt,hold:yt},{from:0,to:12*We,n:49}),ke("mzr","alpha",["Mzr"],{title:"Residual aligning moment",series:Bt,hold:yt},{from:0,to:12*We,n:49}),Wl("gough",["alpha","Fz"],"Fy","Mz",{title:"Gough plot",hold:yt}),ke("steering-feel","alpha",["t"],{title:"Steering feel",x:"FyRel",series:Bt,hold:yt},{from:0,to:12*We,n:49})]},{id:"longitudinal",name:"Longitudinal",cards:[ke("fx-load","kappa",["Fx"],{title:"Longitudinal force per wheel load",series:Bt,hold:Wv}),ke("mux-peak","Fz",["muXPeak"],{title:"Peak longitudinal \u03BC over load"}),ke("kx","Fz",["dFxdk"],{title:"Slip stiffness at zero slip over load",hold:Qf}),ke("kappa-peak","Fz",["kappaPeak"],{title:"Slip ratio at the peak over load"})]},{id:"combined",name:"Combined",cards:[Wl("carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Wl("envelope-load",["kappa","alpha"],"Fy","Fx",{title:"Friction envelope per load",scale:{per:"Fz"},facet:zL}),ke("fy-kappa","kappa",["Fy"],{title:"Side force while driving or braking",series:{input:"alpha",values:[2*We,4*We,8*We]}}),ke("fx-kappa","kappa",["Fx"],{title:"Driving force while cornering",series:{input:"alpha",values:[0,4*We,8*We]}}),Tr("ellipse","ellipse")]},{id:"camber",name:"Camber",cards:[ke("fy-gamma","alpha",["Fy"],{title:"Lateral force per inclination",series:{input:"gamma",values:[-4,-2,0,2,4].map(e=>e*We)},hold:yt}),ke("camber-sweep","gamma",["FyPeak","Fy"],{title:"Peak, and camber thrust at zero slip",hold:{alpha:0}}),{id:"camber-map",title:"Camber map",form:"map",sweep:[{input:"gamma",...Zf.gamma},{input:"Fz",...Zf.Fz,follow:!0}],x:"gamma",y:["Fz"],z:"muYPeak"},ke("camber-stiffness","alpha",["dFydg"],{title:"Camber stiffness at the point",series:Bt,hold:yt}),ke("mx","alpha",["Mx"],{title:"Overturning moment",series:Bt,hold:yt})]},{id:"rolling",name:"Rolling and radius",cards:[ke("my","V",["My"],{title:"Rolling-resistance moment",series:Bt,hold:Qf}),ke("radius","Fz",["R0","Rl","Re"],{title:"Radius over load"},{from:0}),ke("p-roll","V",["Proll"],{title:"Rolling power",series:Bt,hold:Qf})]},{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:[Tr("operating","operating"),Tr("wheels","wheels")]},{id:"fit",name:"Fit check",cards:[Tr("fitLateral","fitLateral"),Tr("fitLongitudinal","fitLongitudinal"),Tr("fitCoupling","fitCoupling"),Tr("fitEnvelope","fitEnvelope")]}];var ZL=5670374e-14,Jf=273.15,Zv=.95,Jv=60,jl=10,JL=.55,Ft=25,eh=-20,th=50,Ys={tempC:[20,100,200,550,650,750],factor:[.8,.92,1,1,.85,.65]},Ws={discMassKg:.5,discOuterMm:220,specificHeatJPerKgK:460,emissivity:.6,coolingWPerM2K:200,padCurve:{tempC:[...Ys.tempC],factor:[...Ys.factor]}},Ul={...Ws,discMassKg:.4,discOuterMm:200,padCurve:{tempC:[...Ys.tempC],factor:[...Ys.factor]}};function rh(e,t){let r=t==="front"?Ws:Ul,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 eD=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},zs=(e,t,r,n)=>Math.min(r,Math.max(t,eD(e,n)));function tD(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 nh(e,t){return{discMassKg:zs(e?.discMassKg,.05,20,t.discMassKg),discOuterMm:zs(e?.discOuterMm,50,600,t.discOuterMm),specificHeatJPerKgK:zs(e?.specificHeatJPerKgK,100,3e3,t.specificHeatJPerKgK),emissivity:zs(e?.emissivity,.02,1,t.emissivity),coolingWPerM2K:zs(e?.coolingWPerM2K,jl,5e3,t.coolingWPerM2K),padCurve:tD(e?.padCurve,t.padCurve)}}function Xl(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 oh(e,t=1){let r=e.discMassKg*e.specificHeatJPerKgK,n=e.discOuterMm*.001/2,o=2*Math.PI*n*n,a=Jv/3.6,s=e.emissivity*ZL*o,i=m=>jl+(e.coolingWPerM2K-jl)*Math.pow(Math.max(0,m)*t/a,JL),c=(m,f,p)=>{let d=m+Jf,h=p+Jf;return i(f)*o*(m-p)+s*(d**4-h**4)},l=(m,f)=>i(f)*o+4*s*Math.max(0,m+Jf)**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=>Xl(e.padCurve,m),window:e1(e.padCurve)}}function Ql(e,t,r,n,o,a,s=Ft){let i=n.length,c=new Array(i),l=new Array(i),u=new Array(i),m=Zv/Math.max(1,t),f=a,p=f,d=0,h=0,b=0;for(let g=0;g<i;g++){let y=Math.max(0,r[g]??0);c[g]=f,l[g]=y*n[g],u[g]=e.padFactor(f);let R=y*(o[g]??0);d+=R,f<e.window.fromC?h+=R:f>e.window.toC&&(b+=R);let k=g+1<i?n[g+1]:n[g],v=.5*(n[g]+k),x=v>0?(o[g]??0)/v:0;f=e.step(f,m*R,v,x,s),f>p&&(p=f)}return{tempC:c,heatW:l,padFactor:u,startC:a,endC:f,maxC:p,workJ:d,coldWorkJ:h,hotWorkJ:b}}function e1(e){let t=e.tempC,r=Math.min(t.length,e.factor.length);if(r===0)return{fromC:-1/0,toC:1/0};let n=Math.max(...e.factor.slice(0,r)),o=null;for(let c=0;c<r;c++){if(e.factor[c]<n-1e-9)continue;let l=c;for(;l+1<r&&e.factor[l+1]>=n-1e-9;)l++;l>c&&(!o||t[l]-t[c]>o.toC-o.fromC)&&(o={fromC:t[c],toC:t[l]}),c=l}if(o)return o;let a=NaN,s=NaN,i=NaN;for(let c=Math.floor(t[0]);c<=Math.ceil(t[r-1])+1;c++){let l=c<=Math.ceil(t[r-1])&&Xl(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 ah=1e5,o1=.001,Kn={pedalRatio:4,pedalForceMaxN:0,barFront:.5,masterFrontMm:15.875,masterRearMm:15.875,valve:"none",valveKneeBar:20,valveSlope:.3,front:{location:"outboard",discs:2,pistonsPerSide:2,pistonDiaMm:25.4,padMu:.45,effRadiusMm:90,ratio:1},rear:{location:"outboard",discs:2,pistonsPerSide:1,pistonDiaMm:25.4,padMu:.45,effRadiusMm:80,ratio:1},adjusterPitchMm:1,barLengthMm:0},ih={fullAtBar:10,maxPowerKw:0,fadeBelowKmh:0,distribution:"equal"};var ch=s1(Zl(Kn,"Formula Student brakes")),lh=40,a1={ideal:!1,barFront:Kn.barFront,pedalForceMaxN:0,testSpeedKmh:lh,regen:ih};function t1(e){let{heat:t,...r}=e;return t?{...r,heat:{...t,padCurve:{tempC:[...t.padCurve.tempC],factor:[...t.padCurve.factor]}}}:r}function s1(e){let t=(r,n)=>r.heat?r:{...r,heat:rh(r,n)};return{...e,front:t(e.front,"front"),rear:t(e.rear,"rear")}}function Zl(e,t){return{name:t,pedalRatio:e.pedalRatio,masterFrontMm:e.masterFrontMm,masterRearMm:e.masterRearMm,valve:e.valve,valveKneeBar:e.valveKneeBar,valveSlope:e.valveSlope,front:t1(e.front),rear:t1(e.rear),adjusterPitchMm:e.adjusterPitchMm,barLengthMm:e.barLengthMm}}function uh(e,t){return i1({...e,barFront:t.barFront,pedalForceMaxN:t.pedalForceMaxN})}function mh(e,t){let r=Lr(t),n=e?sr(e):void 0;return{mode:r.ideal?"tyre":n?"hydraulic":"balance",hydraulic:n?uh(n,r):Kn,regen:r.regen}}var rD=["none","proportioning","limiter"],ql=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},Je=(e,t,r,n)=>Math.min(r,Math.max(t,ql(e,n))),nD=(e,t)=>{let r=ql(e,t);return r>0?r:t};function r1(e,t,r){let n=e?.location==="inboard"?"inboard":e?.location==="outboard"?"outboard":t.location;return{location:n,discs:Math.max(1,Math.min(4,Math.round(ql(e?.discs,n==="inboard"?1:t.discs)))),pistonsPerSide:Math.max(1,Math.min(6,Math.round(ql(e?.pistonsPerSide,t.pistonsPerSide)))),pistonDiaMm:Je(e?.pistonDiaMm,5,80,t.pistonDiaMm),padMu:Je(e?.padMu,.05,1.5,t.padMu),effRadiusMm:Je(e?.effRadiusMm,20,300,t.effRadiusMm),ratio:n==="inboard"?Je(e?.ratio,1,20,t.ratio):1,...e?.heat&&typeof e.heat=="object"?{heat:nh(e.heat,t.heat??r)}:{}}}function i1(e){let t=Kn;return{pedalRatio:Je(e?.pedalRatio,.5,15,t.pedalRatio),pedalForceMaxN:Je(e?.pedalForceMaxN,0,5e3,t.pedalForceMaxN),barFront:Je(e?.barFront,.05,.95,t.barFront),masterFrontMm:Je(e?.masterFrontMm,8,40,t.masterFrontMm),masterRearMm:Je(e?.masterRearMm,8,40,t.masterRearMm),valve:rD.includes(e?.valve)?e?.valve:t.valve,valveKneeBar:Je(e?.valveKneeBar,0,200,t.valveKneeBar),valveSlope:Je(e?.valveSlope,0,1,t.valveSlope),front:r1(e?.front,t.front,Ws),rear:r1(e?.rear,t.rear,Ul),adjusterPitchMm:nD(e?.adjusterPitchMm,t.adjusterPitchMm),barLengthMm:Je(e?.barLengthMm,0,500,t.barLengthMm)}}function oD(e){let t=ih;return{fullAtBar:Je(e?.fullAtBar,0,200,t.fullAtBar),maxPowerKw:Je(e?.maxPowerKw,0,1e3,t.maxPowerKw),fadeBelowKmh:Je(e?.fadeBelowKmh,0,100,t.fadeBelowKmh),distribution:e?.distribution==="wheel"?"wheel":"equal"}}function sr(e){let t=i1(e??void 0),r=typeof e?.name=="string"&&e.name.trim()?e.name:aD;return Zl(t,r)}function Lr(e){return{ideal:e?.ideal===!0,barFront:Je(e?.barFront,.05,.95,Kn.barFront),pedalForceMaxN:Je(e?.pedalForceMaxN,0,5e3,0),testSpeedKmh:Je(e?.testSpeedKmh,5,150,lh),regen:oD(e?.regen)}}var aD="Formula Student brakes";var sh=e=>Math.PI/4*(e*o1)**2;function un(e,t){let r=e.pistonsPerSide*sh(e.pistonDiaMm)*ah;return e.discs*2*e.padMu*r*e.effRadiusMm*o1*e.ratio/Math.max(.05,t)}function c1(e,t){if(e.valve==="none"||t<=e.valveKneeBar)return t;let r=e.valve==="limiter"?0:e.valveSlope;return e.valveKneeBar+r*(t-e.valveKneeBar)}function js(e,t){let r=Math.max(0,t)*e.pedalRatio,n=e.barFront*r/sh(e.masterFrontMm)/ah,o=(1-e.barFront)*r/sh(e.masterRearMm)/ah;return{front:n,rearIn:o,rear:c1(e,o)}}function sD(e,t){let r=js(e,1);return{front:un(e.front,t)*r.front,rear:un(e.rear,t)*r.rearIn}}function Us(e,t){let r=sD(e,t);return r.front/Math.max(1e-12,r.front+r.rear)}function Xs(e,t){let r=[],n=[],o=[],a=e.vVehicle.length,s=Math.max(1,Math.floor(a/60));for(let c=0;c<a;c+=s)i(c);return(a-1)%s!==0&&i(a-1),{v:r,front:n,rear:o};function i(c){let l=e.vVehicle[c],u=l1(t,l),m=t.maxPowerKw>0&&l>0?t.maxPowerKw*1e3/l:1/0,f=Math.max(0,e.fFront[c]),p=Math.max(0,e.fRear[c]),d=f+p>0?Math.min(1,m/(f+p)):1;r.push(l),n.push(f*d*u),o.push(p*d*u)}}function l1(e,t){let r=e.fadeBelowKmh/3.6;return r>0?Math.max(0,Math.min(1,t/r)):1}function Pr(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]||1);return t[o]+s*(t[a]-t[o])}var n1=new WeakMap;function Hn(e){let t=n1.get(e);return t||(t=e.mode==="hydraulic"&&e.hydraulic?cD(e,e.hydraulic):iD(e),n1.set(e,t)),t}function iD(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 cD(e,t){let r=un(t.front,e.tyreRadiusM),n=un(t.rear,e.tyreRadiusM),o=e.regen,a=(c,l)=>{let u=js(t,c),m=0,f=0;if(o&&u.front>0){let p=o.fullAtBar>0?Math.min(1,u.front/o.fullAtBar):1;m=p*Pr(o.v,o.front,l),f=p*Pr(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 ph(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 Jl=Fs,lD=.1,zn=(e,t)=>e.a*Math.sqrt(Math.max(0,1-(t/Math.max(1e-9,e.b))**2));function eu(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 hh(e,t,r){let n=Math.max(0,r-Jl*t.b),o=Math.min(r,Jl*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 bh(e,t,r,n,o=0){let a=Math.max(0,r),s=hh(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/lD)),d=p>0&&a<Jl*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=eu(T=>{let S=zn(e,T),A=zn(t,a-T);return Math.min(S+A,2*Math.min(S,A)+y)},R,k),x=e.cap(v),M=t.cap(a-v),F=Math.max(2*l,Math.min(x+M,2*Math.min(x,M)+y)),w=(T,S,A)=>Math.min(y,Math.max(0,T-A))+Math.min(y,Math.max(0,S-A));return{...g,regenWheel:y,mixedMax:F,regenRoom:T=>{let S=w(i,c,T);if(!(a>0))return S;let A=E=>Jl*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=eu(E=>Math.min(y,zn(e,E)-T)+Math.min(y,zn(t,a-E)-T),P,L);return Math.max(S,w(e.cap(D),t.cap(a-D),T))}}}var dh=e=>Math.max(e.xNoLock,e.xLock),fh=e=>Math.max(e.mixedMax,2*e.xLock);function ca(e,t,r=0){let n=1e-9*Math.max(1,t),o=Math.max(0,r);if(t<=e.xNoLock+n)return Math.min(2*t+(o>0?Math.min(o,e.regenRoom(t)):0),e.ceiling);if(t<=e.xLock+n){let a=o>0?Math.min(e.regenWheel>0?Math.min(o,e.regenWheel):o/2,Math.max(0,e.xLock-t)):0;return Math.min(t+e.slide+a,e.ceiling)}return NaN}function la(e,t){let r=t/2,n=1e-9*Math.max(1,r);return r<=e.mixedMax/2+n?Math.min(t,e.ceiling):r<=e.xLock+n?Math.min(r+e.slide,e.ceiling):NaN}function Qs(e,t,r,n){return e.shares?uD(e,e.shares,t,r,n):mD(e,t,r,n)}function u1(e,t){let r=e[0],n=t(r.u);for(let o of e.slice(1)){let a=t(o.u);a>n&&(r=o,n=a)}return{cand:r,force:n}}function uD(e,t,r,n,o){let a=fh(r),s=fh(n),i=Math.min(t.front>0?a/t.front:1/0,t.rear>0?s/t.rear:1/0,e.uMax),c=Number.isFinite(e.uMax)&&i>=e.uMax,l=b=>{let g=la(r,t.front*b),y=la(n,t.rear*b);return Number.isFinite(g)&&Number.isFinite(y)?g+y:-1/0},u=a>0?t.front*i/a:1/0,m=s>0?t.rear*i/s:1/0,f=[{u:i,by:c?"pedal":u>=m?"front":"rear"}];if(r.xLock>r.xNoLock){let b=t.front>0?r.mixedMax/t.front:1/0;b<i&&f.push({u:b,by:"front"})}if(n.xLock>n.xNoLock){let b=t.rear>0?n.mixedMax/t.rear:1/0;b<i&&f.push({u:b,by:"rear"})}let{cand:p,force:d}=u1(f,l),h=e.demand(p.u,o);return{force:Math.max(0,Number.isFinite(d)?d:0),control:p.u,demand:h,limitedBy:p.by,lockFront:h.front/2>r.mixedMax/2*(1+1e-9),lockRear:h.rear/2>n.mixedMax/2*(1+1e-9)}}function mD(e,t,r,n){let o=dh(t),a=dh(r),s=v=>(v.front-v.regenFront)/2,i=v=>(v.rear-v.regenRear)/2,c=v=>{let x=e.demand(v,n);return s(x)<=o*(1+1e-12)&&i(x)<=a*(1+1e-12)},l=(v,x)=>{if(v(e.demand(x,n)))return x;let M=0,F=x;for(let w=0;w<60;w++){let C=.5*(M+F);v(e.demand(C,n))?M=C:F=C}return M},u=Number.isFinite(e.uMax)?e.uMax:100;if(!Number.isFinite(e.uMax))for(;c(u)&&u<1e7;)u*=2;let m=c(u)?u:l(v=>s(v)<=o&&i(v)<=a,u),f=Number.isFinite(e.uMax)&&m>=e.uMax,p=v=>{let x=e.demand(v,n),M=ca(t,s(x),x.regenFront),F=ca(r,i(x),x.regenRear);return Number.isFinite(M)&&Number.isFinite(F)?M+F:-1/0},d=e.demand(m,n),h=o>0?s(d)/o:1/0,b=a>0?i(d)/a:1/0,g=[{u:m,by:f?"pedal":h>=b?"front":"rear"}];if(t.xLock>t.xNoLock){let v=l(x=>s(x)<=t.xNoLock,m);v<m&&g.push({u:v,by:"front"})}if(r.xLock>r.xNoLock){let v=l(x=>i(x)<=r.xNoLock,m);v<m&&g.push({u:v,by:"rear"})}let{cand:y,force:R}=u1(g,p),k=e.demand(y.u,n);return{force:Math.max(0,Number.isFinite(R)?R:0),control:y.u,demand:k,limitedBy:y.by,lockFront:s(k)>t.xNoLock*(1+1e-9),lockRear:i(k)>r.xNoLock*(1+1e-9)}}var Dr={regen:!0,regenEfficiency:.6};function Er(e,t){let r=e.energy??t??Dr;return{regen:r.regen===!0,regenEfficiency:Math.min(1,Math.max(0,Number.isFinite(r.regenEfficiency)?r.regenEfficiency:0))}}function Ir(e,t,r){let n=Math.max(0,Math.floor(r));if(n===0)return[];if(n===1)return[e];let o=new Array(n),a=(t-e)/(n-1);for(let s=0;s<n;s++)o[s]=e+a*s;return o[n-1]=t,o}function m1(e,t,r){let n=[],o=Math.floor((r-e)/t+1e-9);for(let a=0;a<=o;a++)n.push(e+t*a);return n}function mt(e,t,r){let n=e.length;if(r<e[0]||r>e[n-1])return NaN;if(r===e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function tu(e,t,r){let n=e.length;if(!(r>=e[0]&&r<=e[n-1]))return NaN;if(n<3)return n===1?t[0]:t[0]+(r-e[0])/(e[1]-e[0])*(t[1]-t[0]);let o=0,a=n-1;for(;a-o>1;){let d=o+a>>1;e[d]<=r?o=d:a=d}if(o===n-1)return t[n-1];let s=d=>e[d+1]-e[d],i=d=>(t[d+1]-t[d])/s(d),c=d=>{if(d===0||d===n-1){let[y,R]=d===0?[0,1]:[n-2,n-3],k=i(y)*(1+s(y)/(s(y)+s(R)))-i(R)*(s(y)/(s(y)+s(R)));return k*i(y)<=0?0:Math.abs(k)>2*Math.abs(i(y))?2*i(y):k}let h=i(d-1),b=i(d),g=(h*s(d)+b*s(d-1))/(s(d-1)+s(d));return(Math.sign(h)+Math.sign(b))*Math.min(Math.abs(h),Math.abs(b),.5*Math.abs(g))},l=s(o),u=i(o),m=c(o),f=c(o+1),p=r-e[o];return t[o]+p*(m+p*((3*u-2*m-f)/l+p*(m+f-2*u)/(l*l)))}function qs(e,t,r){return r.map(n=>mt(e,t,n))}var Zs=e=>e.reduce((t,r)=>r>t?r:t,-1/0),ua=e=>e.reduce((t,r)=>r<t?r:t,1/0);var pD=[-.906179845938664,-.538469310105683,0,.538469310105683,.906179845938664],dD=[.236926885056189,.478628670499366,.568888888888889,.478628670499366,.236926885056189];function gh(e,t,r){let n=.5*(r-t),o=.5*(t+r),a=0;for(let s=0;s<5;s++)a+=dD[s]*e(n*pD[s]+o);return n*a}var fD=Math.PI*2,hD=.5/3.6;function Js(e,t){let r=Math.max(0,Math.round(e));if(t==="front")return{front:r,rear:0};if(t==="rear")return{front:0,rear:r};let n=Math.floor(r/2);return{front:n,rear:r-n}}function yh(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*fD;c[g]=y*o/n,l[g]=s[g]*n/o}let u=Zs(c),m=Ir(ua(c),u,u/hD),f=qs(c,l,m),{front:p,rear:d}=Js(t,r),h=f.map(g=>g*p),b=f.map(g=>g*d);return{vVehicle:m,fFront:h,fRear:b,vMax:u}}var p1=60/(2*Math.PI),d1=.1,f1=.08,h1=0;function xh(e){let t=(r,n)=>r===void 0||!Number.isFinite(r)?n:Math.max(0,r);return{up:t(e.upshiftTime,d1),down:t(e.downshiftTime,f1)}}function Rh(e){let t=e.driveKept;return t===void 0||!Number.isFinite(t)?h1:Math.max(0,Math.min(1,t))}function vh(e,t,r){let{primary:n,ratios:o,efficiency:a}=e.gearbox,s=t>0&&r>0&&n>0,i=(b,g)=>b/p1*r/g,c=s?o.filter(b=>b>0).map(b=>{let g=n*b*t;return{ratio:g,vIdle:i(e.idleRpm,g),vLimit:i(e.limitRpm,g)}}):[],l=Math.max(0,Math.min(1,a)),u=Math.max(0,e.inertia),m=b=>b>e.limitRpm?0:Math.max(0,$e(e.rpm,e.torque,b)),f=(b,g)=>{let y=c[g];return y?b*y.ratio/r*p1:0},p=(b,g)=>g===0&&c.length>0&&b<c[0].vIdle,d=(b,g)=>{let y=c[g];return y?p(b,g)?m(e.idleRpm)*y.ratio*l/r:b<y.vIdle||b>y.vLimit?0:m(f(b,g))*y.ratio*l/r:0},h=(b,g)=>{let y=c[g];return!y||p(b,g)?0:u*y.ratio*y.ratio/(r*r)};return{engine:e,gears:c,efficiency:l,rDyn:r,vMax:c.length?c[c.length-1].vLimit:0,rpm:f,torque:m,force:d,inertiaMass:h,slipping:p}}function ma(e,t,r,n=0,o=1){let a=-1,s=-1/0;for(let i=0;i<e.gears.length;i++){let c=(o*e.force(t,i)+n)/(r+e.inertiaMass(t,i));c>=s&&(s=c,a=i)}return{gear:a,accel:s}}function kh(e,t){let r=0;for(let n=0;n<e.gears.length;n++)r=Math.max(r,e.force(t,n));return r}var b1=9.81,g1=Math.PI*2;function wt(e){let t=e.motor.rpm,r=e.motor.torque,n=t.length,o=new Array(n),a=new Array(n),s=new Array(n),i=new Array(n),c=new Array(n),l=e.gear_ratio.value,u=e.r_dyn.value;for(let v=0;v<n;v++)o[v]=r[v]*t[v]*(g1/60),a[v]=t[v]/60*g1,s[v]=a[v]*u/l,i[v]=r[v]*l,c[v]=i[v]/u;let m=Zs(s),f=m,p=.5/3.6,d=Ir(ua(s),m,m/p),h=qs(s,c,d),b=Ir(ua(t),Zs(t),250),g=qs(t,o,b).map(v=>v*e.power_scale.value),y,R=f,k;if(e.motorModel?.kind==="ice"){k=vh(e.motorModel,l,u);let v=Ir(0,k.vMax,Math.max(2,Math.ceil(k.vMax/p)+1)),x=v.map(w=>kh(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=yh(e.motorModel,Math.max(1,Math.round(e.motorCount??e.driven_wheels.value)),e.motorPlacement??"rear",l,u),R=y.vMax);return{params:e,g:b1,FG:e.m.value*b1,vMax:R,vVehicle:d,fRad:h,uMotor:b,pMotor:g,vRad:s,fAxle:y,...k?{engine:k}:{}}}var mn=e=>e.motorModel?.kind==="ice"?Js(1,e.motorPlacement==="front"?"front":"rear"):Js(Math.max(1,Math.round(e.motorCount??e.driven_wheels?.value??2)),e.motorPlacement??"rear");function y1(e){let t=mn(e);return t.front>=2||t.rear>=2}function x1(e){return y1(e)?e.motorMount??"hub":"chassis"}function Mh(e){if(!e.motorModel)return{front:!1,rear:!0};let t=mn(e);return{front:t.front>0,rear:t.rear>0}}function Sh(e){let t=mn(e),r=t.front>0,n=t.rear>0,o=e.front_mass_diss?.value??.5,a=Math.max(0,Math.min(1,o>1?o/100:o)),s=x1(e)==="chassis",i=c=>c===1||c>1&&s;return{front:r&&n?a:r?1:0,inboard:{front:i(t.front),rear:i(t.rear)}}}function pt(e){return mh(e.brakeModel,e.brakeSetup)}function ru(e){return Lr(e.brakeSetup).ideal?"tyre":e.brakeModel||e.brakeModelId?"hydraulic":"balance"}function R1(e,t){if(!(ft(e.motorModel)||!Er(e).regen))return Xs(nu(wt(e)),t??pt(e).regen)}function nu(e){return e.fAxle??{vVehicle:e.vVehicle,fFront:e.vVehicle.map(()=>0),fRear:e.fRad.map(t=>t*e.params.driven_wheels.value)}}function Ah(e,t=pt(e)){if(t.mode==="hydraulic")return Us(t.hydraulic,e.r_dyn.value);if(t.mode==="tyre"){let r=e.front_mass_diss.value>1?e.front_mass_diss.value/100:e.front_mass_diss.value;return Math.min(.95,Math.max(.05,r+q(e,"cg_height")/Math.max(1,q(e,"wheelbase"))))}return q(e,"brake_balance")}function Fh(e,t=pt(e)){return{front:t.hydraulic.front.location==="inboard",rear:t.hydraulic.rear.location==="inboard"}}function wh(e){let t=pt(e);return{brakeBalanceFront:Ah(e,t),brakeInboard:Fh(e,t)}}function v1(e,t=pt(e)){if(t.mode==="tyre"||t.regen.distribution!=="wheel"||ft(e.motorModel))return;let r=mn(e),n={front:r.front>=2,rear:r.rear>=2};return n.front||n.rear?n:void 0}function ei(e){let t=pt(e),r=e.r_dyn.value,n=Fh(e,t),o=Ah(e,t),a=v1(e,t),s=t.mode==="hydraulic"||a?R1(e,t.regen):void 0;return{mode:t.mode,balanceFront:o,...t.mode==="hydraulic"?{hydraulic:t.hydraulic}:{},tyreRadiusM:r,inboard:n,...s?{regen:{...s,fullAtBar:t.regen.fullAtBar}}:{},...s&&a?{regenPerWheel:a}:{}}}var gD=9.81;function Ch(e,t){if(ft(e.motorModel))return()=>0;let r=pt(e),n=Xs(t,r.regen);if(r.mode==="hydraulic"){let a=Hn({mode:"hydraulic",balanceFront:Us(r.hydraulic,e.r_dyn.value),hydraulic:r.hydraulic,tyreRadiusM:e.r_dyn.value,regen:{...n,fullAtBar:r.regen.fullAtBar}});return(s,i)=>{if(!(s>0))return 0;let c=a.demand(a.controlFor(s,i),i);return Math.min(s,c.regenFront+c.regenRear)}}let o=r.mode==="tyre"?yD(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,Pr(n.v,n.front,s))+Math.min((1-c)*a,Pr(n.v,n.rear,s))}}function yD(e){let t=e.m.value*gD,r=e.front_mass_diss.value>1?e.front_mass_diss.value/100:e.front_mass_diss.value,n=q(e,"cg_height")/Math.max(1,q(e,"wheelbase")),o=1-Math.max(0,Math.min(1,q(e,"cop_long"))),a=.5*e.rho.value*e.c_l.value*e.A.value;return(s,i)=>{let c=Math.max(0,a*s*s),l=t*(r+Math.abs(i)*n)+c*o;return Math.min(.99,Math.max(.01,l/(t+c)))}}function k1(e){let t=e==="front"?"Front axle":"Rear axle";return{[`${e}.location`]:{section:t,label:"Disc location",control:"Mounting"},[`${e}.discs`]:{section:t,label:"Discs",control:"Mounting"},[`${e}.ratio`]:{section:t,label:"Reduction to the wheel",unit:": 1"},[`${e}.pistonsPerSide`]:{section:t,label:"Pistons a side"},[`${e}.pistonDiaMm`]:{section:t,label:"Piston bore",unit:"mm"},[`${e}.padMu`]:{section:t,label:"Pad friction \u03BC"},[`${e}.effRadiusMm`]:{section:t,label:"Effective radius",unit:"mm"},[`${e}.heat.discMassKg`]:{section:t,label:"Disc mass",unit:"kg"},[`${e}.heat.discOuterMm`]:{section:t,label:"Disc diameter",unit:"mm"},[`${e}.heat.specificHeatJPerKgK`]:{section:t,label:"Specific heat",unit:"J/(kg\xB7K)"},[`${e}.heat.emissivity`]:{section:t,label:"Emissivity"},[`${e}.heat.coolingWPerM2K`]:{section:t,label:"Cooling at 60 km/h",unit:"W/(m\xB2\xB7K)"},[`${e}.heat.padCurve.tempC`]:{section:t,label:"Pad curve temperature",unit:"\xB0C"},[`${e}.heat.padCurve.factor`]:{section:t,label:"Pad curve friction"}}}var Th={pedalRatio:{section:"Pedal box & bar",label:"Pedal ratio",unit:": 1"},barLengthMm:{section:"Pedal box & bar",label:"Bar length, clevis to clevis",unit:"mm"},adjusterPitchMm:{section:"Pedal box & bar",label:"Adjuster pitch",unit:"mm/turn"},masterFrontMm:{section:"Master cylinders",label:"Front bore",unit:"mm"},masterRearMm:{section:"Master cylinders",label:"Rear bore",unit:"mm"},valve:{section:"Rear valve",label:"Valve"},valveKneeBar:{section:"Rear valve",label:"Knee",unit:"bar"},valveSlope:{section:"Rear valve",label:"Gain above the knee"},...k1("front"),...k1("rear")},Ph={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 Lh(e){let t=Th[e];return`${t.label}, ${t.section}`.toLowerCase()}function Dh(e){let t=Ph[e];return t.section?`${t.section} ${t.label.charAt(0).toLowerCase()}${t.label.slice(1)}`:t.label}var M1=new WeakMap;function ir(e){if(e.brakes)return e.brakes;let t=M1.get(e);if(!t){let r=Math.max(.05,(e.unsprungCgHeight||230)/1e3);t=e.brakeBalanceFront!=null?{mode:"balance",balanceFront:e.brakeBalanceFront,tyreRadiusM:r}:{mode:"tyre",balanceFront:e.frontMassFrac,tyreRadiusM:r},M1.set(e,t)}return t}var _r=e=>Hn(ir(e));var kD=Math.PI/180,pa=Object.freeze({tbr:1,preloadN:0}),ou=Object.freeze({tbr:1/0,preloadN:0}),Ih=e=>e.faces*e.muClutch*e.rFrictionMm/e.rRampMm;function _h(e,t){if(!(e>0)||Number.isNaN(t))return 0;let r=Math.tan(Math.min(90,t)*kD);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 au(e){return e===1/0?1:e>1?(e-1)/(e+1):0}function da(e,t){return e.tbr===1/0?1/0:(e.preloadN>0?e.preloadN:0)+au(e.tbr)*Math.abs(t)}function ri(e,t,r){let n=o=>o!==void 0&&o>0&&r>0?o/r:0;switch(e.kind){case"open":return pa;case"spool":return ou;case"independent":return t==="hubs"?pa:ou;case"clutch":{let o=n(e.preloadNm);return t==="hubs"?{tbr:1,preloadN:o}:{tbr:A1(_h(Ih(e),t==="drive"?e.rampDriveDeg:e.rampCoastDeg)),preloadN:o}}case"torsen":{let o=n(e.preloadNm);if(t==="hubs")return{tbr:1,preloadN:o};let a=t==="drive"?e.tbrDrive:e.tbrCoast;return{tbr:a>1?a:1,preloadN:o}}}}function ti(e,t,r){let n=Math.max(0,Math.min(e,t)),o=Math.max(0,Math.max(e,t)),a=r.tbr>1?r.tbr:1,s=r.preloadN>0?r.preloadN:0;return a===1/0||s===1/0?n+o:n+Math.min(o,a*n+s*(1+a)/2)}var S1=4;function Eh(e,t){let r=0;for(let a of e)r=Math.max(r,ti(a.m1,a.m2,t));let n=t.tbr>1?t.tbr:1,o=(t.preloadN>0?t.preloadN:0)*(1+n)/2;if(n===1/0||o===1/0)return r;for(let a=0;a+1<e.length;a++){let s=e[a],i=e[a+1].m1-s.m1,c=e[a+1].m2-s.m2,l=f=>{f>0&&f<1&&(r=Math.max(r,ti(s.m1+f*i,s.m2+f*c,t)))};i!==c&&l((s.m2-s.m1)/(i-c));let u=i+c-(1+n)*i,m=i+c-(1+n)*c;u!==0&&l(((1+n)*s.m1+o-s.m1-s.m2)/u),m!==0&&l(((1+n)*s.m2+o-s.m1-s.m2)/m)}return r}function ni(e,t,r,n,o){let a=Math.max(0,o),s=n.tbr>1?n.tbr:1,i=n.preloadN>0?n.preloadN:0;if(s===1/0||i===1/0)return a;let c=Math.max(0,r),l=hh(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=eu(b=>zn(e,b)+zn(t,c-b),l.lo,l.hi),f=[{m1:l.c1,m2:l.c2}];for(let b=1;b<=S1&&m!==l.y1;b++){let g=l.y1+(m-l.y1)*b/S1;f.push({m1:e.cap(g),m2:t.cap(c-g)})}let p=Eh(f,pa),d=Eh(f,ou);if(!(d>p))return u;let h=(Eh(f,{tbr:s,preloadN:i})-p)/(d-p);return Math.min(a,u+(a-u)*Math.min(1,Math.max(0,h)))}function F1(e,t,r,n,o,a){return Nh(e,o,ni(t,r,n,o,a))}function Nh(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 Oh(e,t,r,n=30){let o=t,a=e(o),s=a-o;if(!(Math.abs(s)>r))return{x:o,fx:a,evals:1};let i=a,c=e(i),l=c-i,u=2;for(;Math.abs(l)>r&&u<n;){let m=s<0!=l<0,f=l-s,p=f!==0?i-l*(i-o)/f:NaN;m?p>Math.min(o,i)&&p<Math.max(o,i)||(p=.5*(o+i)):Number.isFinite(p)?Math.abs(p-i)>10*Math.abs(l)&&(p=i+Math.sign(p-i)*10*Math.abs(l)):p=c;let d=e(p),h=d-p;if(u++,m&&h<0==l<0?s*=.5:(o=i,s=l),i=p,c=d,l=h,s<0!=l<0&&Math.abs(i-o)<=r)break}return{x:i,fx:c,evals:u}}function w1(e,t,r,n,o,a=60){let s=t,i=e(s),c=i-s,l=1;if(!(Math.abs(c)>n))return{x:s,fx:i,evals:l};let u=Math.sign(r-t),m=Math.abs(r-t),f=0;for(let p=o;l<a;p*=2){if(f=Math.min(f+p,m),f>m-n)return null;let d=t+u*f,h=e(d),b=h-d;if(l++,!(Math.abs(b)>n))return{x:d,fx:h,evals:l};if(c<0!=b<0)return T1(e,s,c,d,h,b,n,l,a);s=d,c=b}return null}function C1(e,t,r,n=60){let o=t,a=e(o),s=a-o;if(!(Math.abs(s)>r))return{x:o,fx:a,evals:1};let i=Math.sign(s),c=a;for(let l=2;;l++){let u=e(c),m=u-c;if(!(Math.abs(m)>r))return{x:c,fx:u,evals:l};if(s<0!=m<0)return T1(e,o,s,c,u,m,r,l,n);if(l>=n)return{x:c,fx:u,evals:l};let f=Math.abs(c-o),p=s!==m?m*(c-o)/(s-m):NaN,d=p*i>0?Math.min(Math.abs(p),10*Math.abs(m),2*f):2*f;o=c,s=m,c+=i*d}}function T1(e,t,r,n,o,a,s,i,c){let l=t,u=r,m=n,f=a,p=n,d=o,h=0;for(;i<c&&Math.abs(m-l)>s;){p=(l*f-m*u)/(f-u),d=e(p);let b=d-p;if(i++,!(Math.abs(b)>s))break;b<0==u<0?(l=p,u=b,h===-1&&(f*=.5),h=-1):(m=p,f=b,h===1&&(u*=.5),h=1)}return{x:p,fx:d,evals:i}}function su(e,t){return Math.abs(e.fx-e.x)>t?e.x:e.fx}var MD=(e,t)=>{let r=e.brakes?.hydraulic?.[t];return!!r&&r.location==="inboard"&&r.discs===1};function $t(e,t,r){let n=e.driveline?.[t];if(n)return r>=0?n.drive:MD(e,t)?n.coast:n.hubs}var P1=e=>e.tbr>1||e.preloadN>0;var SD=9.81,L1=["FL","FR","RL","RR"],Vh=e=>e==="FL"||e==="FR",iu=e=>Vh(e)?"front":"rear",D1={front:["FL","FR"],rear:["RL","RR"]},si=()=>({peak:new Map,freeBrake:new Map}),ai=25;function oi(e,t){let r=Math.max(0,e)/ai,n=Math.floor(r),o=r-n,a=t(n);return o>0?a+o*(t(n+1)-a):a}var pn=1e-4,AD=.05;function Nr(e,t,r,n=si(),o=!1){let a=r,s=e.massTotal,i=n.peak,c=(S,A)=>{let P=`${S}:${A}`,L=i.get(P);return L||(L=Rl(ge(t,S),Math.max(1,A*ai)),i.set(P,L)),L},l=(S,A)=>({aPeak:oi(A,P=>c(S,P).aPeak),fyPeak:oi(A,P=>c(S,P).fyPeak)}),u=n.freeBrake,m=(S,A)=>{let P=`${S}:${A}`,L=u.get(P);if(L===void 0){let D=Math.max(1,A*ai);L=At(ge(t,S),D,0,!0,c(S,A)),u.set(P,L)}return L},f=(S,A)=>A>0?oi(A,P=>m(S,P)):0,p=_r(e),d=ir(e),h=S=>d.regen&&d.regenPerWheel?.[S]?Pr(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(iu(S),L);return At(ge(t,iu(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(At(W,fe,re,!0,J))}},V=te=>Math.abs(P[te])*l(iu(te),Math.max(0,A[te])).fyPeak,[N,z]=D1[S],I=E(N),_=E(z),B=V(N)+V(z),O=bh(I,_,B,L,S==="front"?b:g),G=D?O:{...O,xLock:0},K=$t(e,S,-1),Y=K&&P1(K)?K:void 0;if(!Y)return{axle:S,eq:G,cap:G};let j=Number.isFinite(L)?L:I.cap(V(N))+_.cap(V(z)),Z=F1(G,I,_,B,Y,j);return{axle:S,eq:G,cap:Z,law:Y,strong:()=>I.cap(V(N))>=_.cap(V(z))?N:z}},k=(S,A,P,L)=>R(S,A,P,L).cap,v=(S,A,P)=>{let L=S.demand,D=p.shares?la(A,L.front):ca(A,(L.front-L.regenFront)/2,L.regenFront),E=p.shares?la(P,L.rear):ca(P,(L.rear-L.regenRear)/2,L.regenRear);return{front:Number.isFinite(D)?D:0,rear:Number.isFinite(E)?E:0}},x=S=>({muX:A=>A>0?Math.abs(f(S,A))/A:0,muY:A=>A>0?l(S,A).fyPeak/A:0}),M={front:x("front"),rear:x("rear")},F={lf:e.wheelbase/1e3*(1-e.frontMassFrac),lr:e.wheelbase/1e3*e.frontMassFrac},w={front:e.trackFront/2e3,rear:e.trackRear/2e3},C=(S,A,P,L,D)=>{let E=L.cap,V=D.cap,N=Qs(p,E,V,a),z={arms:F,halfTrack:w,ayDir:Math.sign(S)};for(let I=0;I<2;I++){let _=v(N,E,V),B={};for(let G of L1){let K=Math.max(0,A[G]);B[G]={Fz:K,Fy:Math.abs(P[G])*l(iu(G),K).fyPeak,Fx:-(Vh(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 Nh(G.eq,G.law,Gl(K,B,M,z))};E=O(L),V=O(D),N=Qs(p,E,V,a)}return{limit:N,front:E,rear:V}};return{peakAt:l,axle:k,ceiling:(S,A,P)=>{let[L,D]=D1[S];return Math.abs(y(L,A,P)+y(D,A,P))},limitAt:(S,A,P,L=0)=>{let D={FL:0,FR:0,RL:0,RR:0},E=Ce(e,S,0,a,0,A),V,N=fe=>(V?.ax!==fe&&(V={ax:fe,loads:Ce(e,S,(fe+L)/SD,a,0,A)}),V.loads),z=vl(fe=>ea(P,N(fe),E,l).short,-L,-1),I=P,_={front:0,rear:0},B,O,G=(fe,W=!0)=>{let J=z.at(fe);D=N(J),I=ea(P,D,E,l).util;let re=0,pe=0,de=0;for(let ie of L1){let oe=y(ie,D,I);re+=oe,Vh(ie)?pe+=oe:de+=oe}if(_={front:Math.abs(pe),rear:Math.abs(de)},p.mode!=="tyre"){let ie=R("front",D,I,Math.abs(pe),W),oe=R("rear",D,I,Math.abs(de),W);if(o&&(ie.law||oe.law)){let ue=C(S,D,I,ie,oe);B=ue.limit,O={front:ue.front,rear:ue.rear}}else B=Qs(p,ie.cap,oe.cap,a),O={front:ie.cap,rear:oe.cap};re=-B.force}return re/s},K=Oh(G,0,pn),Y=su(K,pn),j=Y;if(B?.lockFront||B?.lockRear){let fe=Oh(J=>G(J,!1),0,pn);j=su(fe,pn);let W=w1(G,fe.x,K.x,pn,AD);W||G(K.x),Y=su(W??K,pn)}let Z=z.edge(),ne=Z!==void 0&&Y<Z;ne&&(Y=Math.min(0,Z),G(Y),j=Math.max(j,Y));let te={loads:D,ceiling:_,limit:B,axles:O};return{ax:Y,axUnlocked:j,...ne?{edge:Z}:{},...te,split:()=>te.limit&&te.axles?v(te.limit,te.axles.front,te.axles.rear):{...te.ceiling}}}}}var lu=9.81;function FD(e,t,r){let n=Ce(e,0,t,r),o=Math.max(0,n.FL)+Math.max(0,n.FR),a=Math.max(0,n.RL)+Math.max(0,n.RR);return o+a>0?o/(o+a):e.frontMassFrac}var _1=(e,t)=>t.mode==="hydraulic"&&!!ir(e).regen;function fa(e,t,r=0,n,o=0){if(!e.brakes&&e.brakeBalanceFront==null)return e.frontMassFrac;let a=_r(e);if(a.shares&&a.mode!=="tyre")return a.shares.front;let s=n&&_1(e,a)?N1(e,n):void 0,i=s?.shares??E1.get(e);i||E1.set(e,i=new Map);let c=Math.round(Math.abs(t)/.005),l=Math.round(Math.max(0,r)/.25),u=s?Math.round(o/.01):0,m=O1(c,l,u),f=i.get(m);if(f===void 0){let p=-c*.005,d=l*.25,h=e.massTotal*Math.abs(p)*lu;if(s){let b=B1(a,V1(e,s,c,l,u),h,d);f=b.front+b.rear>0?b.front/(b.front+b.rear):.5}else f=a.mode==="tyre"?FD(e,p,d):ph(a,h,d);i.size>5e4&&i.clear(),i.set(m,f)}return f}var E1=new WeakMap;function uu(e,t,r,n,o=0){let a=_r(e);if(!_1(e,a))return;let s=Math.round(Math.max(0,r)/(e.massTotal*lu)/.005),i=Math.round(Math.max(0,n)/.25);return B1(a,V1(e,N1(e,t),s,i,Math.round(o/.01)),Math.max(0,r),n)}var I1=new WeakMap;function N1(e,t){let r=I1.get(e);r||I1.set(e,r=new WeakMap);let n=r.get(t);return n||r.set(t,n={ev:t,tyres:si(),shares:new Map,rooms:new Map,speeds:new Map}),n}var O1=(e,t,r)=>(r*1001+e)*100003+t;function V1(e,t,r,n,o){let a=O1(r,n,o),s=t.rooms.get(a);if(!s){let i=n*.25,c=o*.01,l=t.speeds.get(n);l||(l={cap:Nr(e,t.ev,i,t.tyres),dragG:-Math.max(0,ss(e,i).drag)/(e.massTotal*lu)},t.speeds.set(n,l));let{cap:u}=l,m=Ce(e,c,-r*.005+l.dragG,i),f=Math.abs(c)*e.massTotal*lu,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 cu(e,t,r,n){let o=e.demand(r,n),a=o.front-o.regenFront,s=o.rear-o.regenRear,i=o.regenFront>0?Math.min(o.regenFront,t("front",a/2)):0,c=o.regenRear>0?Math.min(o.regenRear,t("rear",s/2)):0;return{front:i===o.regenFront?o.front:a+i,rear:c===o.regenRear?o.rear:s+c,regenFront:i,regenRear:c,demand:o}}function B1(e,t,r,n){if(!(r>0))return cu(e,t,1,n);let o=c=>c.front+c.rear,a=e.controlFor(r,n),s=cu(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=cu(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=cu(e,t,l,n);o(u)<r?a=l:(i=l,s=u)}return s}var ha={rel:.003,abs:2,kappa:1e-5,iters:12},Bh={rel:1e-6,abs:.001,kappa:1e-12,iters:40};function Yn(e,t,r,n=ha){let o=t>=0?1:-1,a=Math.abs(t),s=Math.max(n.abs,n.rel*a),i=e(0);if(Math.abs(i.Fx)-a>=0)return{kappa:0,forces:i};let c=0,l=i,u=Math.abs(i.Fx)-a,m=Math.min(.3,Math.max(.004,Math.abs(r)||.02)),f=e(o*m),p=Math.abs(f.Fx)-a,d=null;for(;p<0&&m<.3;){let g=Math.min(.3,m*1.9),y=e(o*g),R=Math.abs(y.Fx);if(R<Math.abs(f.Fx)){d={kappa:g,forces:y};break}c=m,l=f,u=p,m=g,f=y,p=R-a}if(p<0){let g=TD(e,o,c,l,m,f,d),y=Math.abs(g.forces.Fx);if(y<a)return{kappa:o*g.kappa,forces:g.forces};m=g.kappa,f=g.forces,p=y-a}let h=f,b=o*m;for(let g=0;g<n.iters&&m-c>n.kappa;g++){let y=p-u,R=Math.abs(y)>1e-12?(c*p-m*u)/y:.5*(c+m);R>c&&R<m||(R=.5*(c+m));let k=e(o*R),v=Math.abs(k.Fx)-a;if(h=k,b=o*R,Math.abs(v)<s)break;v<0?(c=R,u=v,p*=.5):(m=R,p=v,u*=.5)}return{kappa:b,forces:h}}var $1=1e-6,wD=40,CD=(3-Math.sqrt(5))/2;function TD(e,t,r,n,o,a,s){let i=a,c,l,u,m=-Math.abs(a.Fx),f,p,d=-Math.abs(n.Fx);if(s){c=s.kappa;let g=-Math.abs(s.forces.Fx);[l,f,u,p]=g<=d?[c,g,r,d]:[r,d,c,g]}else{c=.3;let g=.3*(1-$1),y=e(t*g),R=-Math.abs(y.Fx);if(R>=m)return{kappa:o,forces:a};[l,f,u,p]=[o,m,r,d],o=g,m=R,i=y}d<m&&([l,f]=[o,m],o=r,m=d,i=n);let h=c-r,b=0;for(let g=0;g<wD;g++){let y=$1*Math.abs(o)+1e-10,R=.5*(r+c);if(Math.abs(o-R)<=2*y-.5*(c-r))break;let k=!0;if(Math.abs(h)>y){let F=(o-l)*(m-p),w=(o-u)*(m-f),C=(o-u)*w-(o-l)*F;w=2*(w-F),w>0&&(C=-C),w=Math.abs(w);let T=h;if(h=b,Math.abs(C)<Math.abs(.5*w*T)&&C>w*(r-o)&&C<w*(c-o)){b=C/w;let S=o+b;(S-r<2*y||c-S<2*y)&&(b=R>=o?y:-y),k=!1}}k&&(h=o>=R?r-o:c-o,b=CD*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 mu=e=>Math.max(2,.003*Math.abs(e)),PD=(e,t)=>Math.max(t.abs,t.rel*Math.abs(e)),$h=.5,LD=.03;function DD(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=PD(r,o),c=Math.max(-$h,Math.min($h,n)),l=s(c);if(Math.abs(c)>LD){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)>$h)break;let M=s(x);if(Math.abs(M.g)<i)return M;if(Math.abs(M.g)<Math.abs(d.g)&&(d=M),Math.sign(M.g)!==Math.sign(m.g)){f=M;break}if(u*(M.g-m.g)<=0)return d;m=M,p*=1.9}if(f===l)return d;let h=m,b=f,g=h.g,y=b.g,R=Math.abs(g)<Math.abs(y)?h:b,k=Math.min(1e-7,o.kappa);for(let v=0;v<30&&Math.abs(b.kappaM-h.kappaM)>k;v++){let x=y-g,M=Math.abs(x)>1e-12?(h.kappaM*y-b.kappaM*g)/x:.5*(h.kappaM+b.kappaM),F=Math.min(h.kappaM,b.kappaM),w=Math.max(h.kappaM,b.kappaM);M>F&&M<w||(M=.5*(F+w));let C=s(M);if(R=C,Math.abs(C.g)<i)break;Math.sign(C.g)===Math.sign(g)?(h=C,g=C.g,y*=.5):(b=C,y=C.g,g*=.5)}return R}function G1(e,t,r,n){let o=(e*(1+t*n)+t*r)/(1-t*n);return e+o>=0?o:(e*(1-t*n)+t*r)/(1+t*n)}function Gh(e,t,r,n,o,a=ha){let s=DD(e,t,r,o,a),i=s.fr.Fx-s.fl.Fx,c=da(n,r);if(Math.abs(i)<=c){let R=r-(s.fl.Fx+s.fr.Fx),k=Math.max(0,Math.abs(R)-mu(r))/2;return{left:{kappa:s.kl,forces:s.fl,want:s.fl.Fx+R/2,short:k},right:{kappa:s.kr,forces:s.fr,want:s.fr.Fx+R/2,short:k},locked:!0,spoolKappa:s.kappaM}}let l=Math.sign(i),u=r/2-l*c/2,m=r/2+l*c/2,f=Yn(e.at,u,e.seed||s.kl,a),p=Yn(t.at,m,t.seed||s.kr,a),d=Math.abs(u-f.forces.Fx)>mu(u),h=Math.abs(m-p.forces.Fx)>mu(m),b=Math.max(0,n.preloadN),g=au(n.tbr);d&&!h?p=Yn(t.at,G1(f.forces.Fx,l,b,g),p.kappa,a):h&&!d&&(f=Yn(e.at,G1(p.forces.Fx,-l,b,g),f.kappa,a));let y=(R,k)=>({kappa:R.kappa,forces:R.forces,want:k,short:Math.max(0,Math.abs(k-R.forces.Fx)-mu(k))});return{left:y(f,u),right:y(p,m),locked:!1,spoolKappa:s.kappaM}}var ED={front:["FL","FR"],rear:["RL","RR"]},ID=Object.freeze({Fx:0,Fy:0,Mz:0});function pu(e,t,r,n){let o=r;for(let a of["front","rear"]){let[s,i]=ED[a],c=r[s]+r[i],l=$t(e,a,c);if(!l||!(da(l,c)>0))continue;let u=ge(t,a),m=n.alpha[a],f=(a==="front"?e.trackFront:e.trackRear)/2e3,p=(h,b)=>{let g=Math.max(0,n.Fz[h]);return{at:g>0?y=>u.forces({Fz:g,kappa:y,alpha:m,gamma:0}):()=>ID,vx:Math.max(.05,1-b*n.curvature),seed:0}},d=Gh(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,_D=8,ND=1e-6,fn=["FL","FR","RL","RR"],jt=e=>e==="FL"||e==="FR",dn=e=>jt(e)?"front":"rear";function ci(e,t){let r=ge(e,"front"),n=ge(e,"rear");return r===n?jn(r,t):{front:jn(r,t),rear:jn(n,t)}}function jn(e,t){return Ef(e,Math.min(t,Wt(e)))}var fu=e=>e==="FL"||e==="RL";function ga(e,t,r=0,n,o=0){let a=t?.axG??0,s=Number.isFinite(t?.tvRearDiffN)?t?.tvRearDiffN:0;if(!(!!a&&Number.isFinite(a))&&!s)return null;let c=e.massTotal*a*Me,l=a>=0?Math.min(1,Math.max(0,t?.driveFrontFrac??0)):Math.min(.99,Math.max(.01,fa(e,a,r,n,o))),u=c*l/2,m=c*(1-l)/2;return{axG:a,fx:{FL:u,FR:u,RL:m-s/2,RR:m+s/2}}}function Uh(e,t,r,n){return Math.abs(Un(e,t,r,n!==void 0?{steerMaxDeg:n}:{}).peak.steerDeg)}function Xh(e,t,r,n){let o=e.tv;if(!o?.enabled)return 0;let a=ck(o)(t,Math.abs(r),n);return r<0?-a:a}function Qh(e,t,r=0,n,o=0,a=0,s){let i=ga(e,{axG:t,driveFrontFrac:a},r,n,o),c=i?i.fx:{FL:0,FR:0,RL:0,RR:0};return i&&s&&n?pu(e,n,c,s):c}var li=e=>fu(e)?-1:1,qh=(e,t,r,n,o)=>t*e.Fy(t*r,n,t*o);function Wh(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 OD(e,t,r){let n=Math.abs(t),o=e.steerFront;if(o&&o.meanDeg.length>1){let u=t>=0,m=r&&o.travelSurface?Qo(o,n/se,u?r.FL:r.FR,u?r.FR:r.FL):qo(o,n/se);return{innerMag:m.innerDeg*se,outerMag:m.outerDeg*se,innerCamber:m.innerCamber,outerCamber:m.outerCamber,atLock:m.atLock}}let a=e.trackFront/1e3,s=e.wheelbase/1e3,i=(e.ackermannPct??0)/100,c=n,l=n;if(n>1e-4){let u=s/Math.tan(n),m=Math.atan(s/Math.max(.05,u-a/2)),f=Math.atan(s/(u+a/2));c=n+i*(m-n),l=n+i*(f-n)}return{innerMag:c,outerMag:l,innerCamber:0,outerCamber:0,atLock:!1}}function Xn(e,t,r){let n=(e.toeFrontDeg??0)*se,o=(e.toeRearDeg??0)*se,a=OD(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 Zh(e,t,r){if(r.Fz<=0)return 0;let n=ut(ge(e,dn(t))),o=li(t),a=Math.abs(r.kappa)<1e-12?n.Mz(o*r.slipRad,r.Fz,o*r.camberRad):n.forces({Fz:r.Fz,kappa:r.kappa,alpha:o*r.slipRad,gamma:o*r.camberRad}).Mz;return o*a}function K1(e,t,r,n){if(!$n(e))return null;let o=ut(ge(t,"front")),a={};for(let s of["FL","FR"]){let i=n[s];a[s]={Fz:i.Fz,Fx:i.Fx,Fy:i.Fy,Mz:Zh(o,s,i)}}return Vs(e,r/se,a,sn(o.model),{FL:n.FL.travelMm,FR:n.FR.travelMm})}var H1=()=>({totalNm:[],aligningNm:[],lateralNm:[],longitudinalNm:[],jackingNm:[]});function z1(e,t){e.totalNm.push(t.totalNm),e.aligningNm.push(t.aligningNm),e.lateralNm.push(t.lateralNm),e.longitudinalNm.push(t.longitudinalNm),e.jackingNm.push(t.jackingNm)}var VD=Object.freeze({Fx:0,Fy:0,Mz:0});function Y1(e,t,r){let n=t==="front"?(r?.FL??0)+(r?.FR??0):(r?.RL??0)+(r?.RR??0),o=$t(e,t,n);return o&&da(o,n)>0?{F:n,law:o}:null}function Ct(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}=Wh(e),h=Y1(e,"front",l),b=Y1(e,"rear",l),g={front:0,rear:0},y=i!==void 0&&i>0&&Number.isFinite(i)?i:null,R=W=>y===null?r:Math.sqrt(Math.max(0,W)*y),k=ut(ge(t,"front")),v=ut(ge(t,"rear")),x=e.trackFront/2e3,M=e.trackRear/2e3,F=!!(e.kinFront&&e.kinRear),w=F&&y===null?ln(e,e.kinFront,e.kinRear,r):null,C=NaN,T=null,S=W=>{if(!F)return null;if(y===null)return w;let J=R(W);return J!==C&&(C=J,T=ln(e,e.kinFront,e.kinRear,J)),T},A={},P={FL:0,FR:0,RL:0,RR:0},L=e.kinFront?.compliance,D=e.kinRear?.compliance,E=!!(L||D),V=!!(L?.toePerMz||D?.toePerMz),N=W=>jt(W)?L:D,z={FL:{fy:0,fx:0,mz:0},FR:{fy:0,fx:0,mz:0},RL:{fy:0,fx:0,mz:0},RR:{fy:0,fx:0,mz:0}},I=!1,_=W=>{let J=W/r,re=y===null?n+f*J/r:n+f/y,pe=y===null?n-p*J/r:n-p/y,de=S(W),ie=R(W),oe=de?de(W/Me,u,n/se,o/se):null,ue=oe?{FL:oe.FL.travel,FR:oe.FR.travel}:void 0,Be=yl(e,W/Me,u,ie,n/se,o/se,ue,oe?.steeringJacking),Ae=Be.loads;I=Be.overturned;let le=Xn(e,o,ue),Re=le.steer,Te=0,ze=be=>{let Fe=Math.max(0,Ae[be]),xe=li(be),me=jt(be)?k:v,Le=N(be),Se=0,Ye=0;if(Le){let Pn=z[be];Se=Le.toePerFy*Pn.fy+Le.toePerFx*Pn.fx+Le.toePerMz*Pn.mz,Ye=Le.camberPerFy*Pn.fy+Le.camberPerFx*Pn.fx}let Ue=Re[be]+(oe?xe*oe[be].bumpToe*se:0)+xe*Se*se,zt=Ue-(jt(be)?re:pe),Tn=(oe?oe[be].camberRoad:0)*se+xe*(le.camber[be]+Ye)*se;return{Fz:Fe,mir:xe,t:me,gains:Le,complianceToe:Se,steerK:Ue,slip:zt,camberRad:Tn}},je=(be,Fe)=>{let xe=y===null?J/r:1/y,me=jt(be)?f:-p,Le=(fu(be)?1:-1)*(jt(be)?x:M),Se=(Math.cos(n)-Le*xe)*Math.cos(Fe.steerK)+(Math.sin(n)+me*xe)*Math.sin(Fe.steerK);return{at:Fe.Fz>0?Ye=>Fe.t.forces({Fz:Fe.Fz,kappa:Ye,alpha:Fe.mir*Fe.slip,gamma:Fe.mir*Fe.camberRad}):()=>VD,vx:Math.max(.05,Se),seed:P[be]}};for(let be=0;be<(E?_D:1);be++){Te=0;let Fe=0,xe={};for(let me of fn){let Le=jt(me)?h:b;if(Le&&!xe[me]){let[Eo,Et]=jt(me)?["FL","FR"]:["RL","RR"],Hc=ze(Eo),Uy=ze(Et),Xy=dn(me),Up=Gh(je(Eo,Hc),je(Et,Uy),Le.F,Le.law,g[Xy],Bh);g[Xy]=Up.spoolKappa,xe[Eo]={w:Hc,share:Up.left},xe[Et]={w:Uy,share:Up.right}}let Se=xe[me]?.w??ze(me),{Fz:Ye,mir:Ue,t:zt,gains:Tn,complianceToe:Pn,steerK:zp,slip:Yp,camberRad:Wp}=Se,rs=l?.[me]??0,Po,Lo=0,jp=0,Kc=0,Do=xe[me]?.share;if(Do)P[me]=Do.kappa,jp=Do.kappa,Lo=Do.forces.Fx,Kc=Do.short,Po=Ue*Do.forces.Fy;else if(rs===0||Ye<=0)Po=qh(zt,Ue,Yp,Ye,Wp),Kc=Ye<=0?Math.abs(rs):0;else{let Et=Yn(Hc=>zt.forces({Fz:Ye,kappa:Hc,alpha:Ue*Yp,gamma:Ue*Wp}),rs,P[me],Bh);P[me]=Et.kappa,jp=Et.kappa,Lo=Et.forces.Fx,Kc=Math.max(0,Math.abs(rs-Lo)-Math.max(ha.abs,ha.rel*Math.abs(rs))),Po=Ue*Et.forces.Fy}if(A[me]={Fz:Ye,travelMm:oe?.[me].travel??0,steerRad:zp,slipRad:Yp,camberRad:Wp,Fy:Po,Fx:Lo,kappa:jp,fxShort:Kc,lifted:Be.lifted[me]},Tn){let Eo=V&&Tn.toePerMz?Zh(zt,me,A[me]):0;z[me]={fy:-Ue*Po,fx:Lo,mz:-Ue*Eo*1e3};let Et=z[me];Fe=Math.max(Fe,Math.abs(Tn.toePerFy*Et.fy+Tn.toePerFx*Et.fx+Tn.toePerMz*Et.mz-Pn))}Te+=Po*Math.cos(zp)+Lo*Math.sin(zp)}if(Fe<ND)break}return Te/d},B=W=>{let J=Ce(e,0,u,W,0,o/se);return J.FL+J.FR+J.RL+J.RR},O=Math.max(20,3.5*B(r)/d);if(y!==null){O=4*Me;for(let W=0;W<8;W++){let J=Math.min(40*Me,3.5*B(R(O))/d);if(J<=O)break;O=J}O=Math.max(20,O)}let G=W=>_(W)-W,K=Math.max(.001,O*1e-4),Y=(W,J,re,pe)=>{let de=W,ie=re,oe=J,ue=pe,Be=de;for(let Ae=0;Ae<40;Ae++){let le=ue-oe,Re=Math.abs(le)>1e-12?(de*ue-ie*oe)/le:.5*(de+ie),Te=Math.min(de,ie),ze=Math.max(de,ie);Re>Te&&Re<ze||(Re=.5*(de+ie));let je=G(Re);if(Be=Re,Math.abs(je)<1e-4||ze-Te<1e-6)break;je<0==oe<0?(de=Re,oe=je,ue*=.5):(ie=Re,ue=je,oe*=.5)}return Be},j=(W,J,re,pe=!1)=>{let de=(Ae,le)=>re>0?Ae>0&&le<0:le>0&&Ae<0,ie=W,oe=J,ue=W+re*Math.min(Math.abs(J),O);if(!pe&&Math.abs(ue-W)>K){let Ae=G(ue);if(de(oe,Ae))return{root:Y(ie,oe,ue,Ae),last:ie};ie=ue,oe=Ae}let Be=pe?O/24:Math.max(O/24,Math.abs(ue-W)/4);for(let Ae=1;Ae<=24;Ae++){let le=ie+re*Be;if(Math.abs(le)>O)break;let Re=G(le);if(de(oe,Re))return{root:Y(ie,oe,le,Re),last:ie};if(pe&&Re*re<0&&(Re-oe)*re<0)break;ie=le,oe=Re}return{root:null,last:ie}},Z=c??null;if(c===void 0&&a!==void 0&&Number.isFinite(a)&&Math.abs(a)<=O){let W=G(a);if(Math.abs(W)<=1e-4)G(a+K)<0&&G(a-K)>0&&(Z=a);else{let J=j(a,W,Math.sign(W)).root;Z=J!==null&&(J===0||Math.sign(J)===Math.sign(a))?J:null}}let ne=Z===null;if(Z===null){let W=G(0),J=G(K),re=Math.abs(W)<=1e-4,pe=re?y!==null?1:o!==0?Math.sign(o):J>0?1:-1:Math.sign(W),de=re?pe*K:0,ie=re?pe>0?J:G(-K):W,oe=j(de,ie,pe);Z=oe.root??(re?0:oe.last)}let te=_(Z);if(ne&&o!==0&&y===null){let W=Math.sign(o);if(Z*W<=0||(A.RL.Fy+A.RR.Fy)*W<0){let J={...A},re=I,pe=W*Math.max(Z*W+K,n*W*r*r/p),de=null;if(pe*W<O){let ie=G(pe);if(ie*W>0)de=j(pe,ie,W).root;else{let oe=pe+W*O/24,ue=G(oe);(ue-ie)*W>0&&(de=j(oe,ue,W,ue*W<=0).root)}}de!==null&&de*W>0?(Z=de,te=_(Z)):(Object.assign(A,J),I=re)}}let fe=f*(A.FL.Fy*Math.cos(A.FL.steerRad)+A.FR.Fy*Math.cos(A.FR.steerRad))-p*(A.RL.Fy+A.RR.Fy);if(s||h||b){let W=J=>(fu(J)?1:-1)*(jt(J)?x:M);for(let J of fn){let re=A[J],pe=jt(J)?f:-p;fe+=pe*re.Fx*Math.sin(re.steerRad)-W(J)*re.Fx*Math.cos(re.steerRad)}}return y!==null&&Z<-1e-6?{ay:NaN,cn:NaN,wheels:A,overturned:I,res:NaN}:{ay:Z/Me,cn:fe/(d*Me*m),wheels:A,overturned:I,res:te-Z}}function BD(e,t,r,n,o,a,s,i=0){let c=20*se,l=.001,u=(h,b)=>{let g=Ct(e,t,r,h,n,b,s);return{cn:g.cn-i,ay:g.ay*Me}},m=h=>n===0||i!==0||Math.abs(h)<.05||Math.sign(h)===Math.sign(n),f=(h,b,g,y)=>{let R=u(h,y);if(Math.abs(R.cn)<1e-5)return{beta:h,trimmed:!0};let k=y===void 0?void 0:R.ay,v={pos:{b:h,cn:R.cn,ay:k},neg:{b:h,cn:R.cn,ay:k}},x=null,M=h,F=Math.abs(R.cn);for(let w=0;w<b.length&&!x;w++)for(let C of[v.pos,v.neg]){let T=C===v.pos?1:-1,S=h+T*b[w];if(Math.abs(S)>c)continue;let A=u(S,C.ay);if(Math.abs(A.cn)<F&&m(A.ay)&&(F=Math.abs(A.cn),M=S),A.cn===0&&m(A.ay))return{beta:S,trimmed:!0};if(A.cn<0!=C.cn<0){let P={lo:C.b,hi:S,ayLo:C.ay},L=W1(u,P),D=u(L,C.ay);if(Math.abs(D.cn)<l&&m(D.ay))return x=P,{beta:L,trimmed:!0}}C.b=S,C.cn=A.cn,y!==void 0&&(C.ay=A.ay)}return x?{beta:W1(u,x),trimmed:!0}:g?{beta:M,trimmed:!1}:null},p=[.25,.75,2,5].map(h=>h*se);if(o!==void 0&&Number.isFinite(o)&&Math.abs(o)<=c){let h=f(o,p,!1,a);if(h)return h;if(!s&&i===0&&a!==void 0&&Number.isFinite(a)){let b=$D(e,t,r,n,o,a,c);if(b&&m(b.ay))return{beta:b.beta,trimmed:!0,ay:b.ay}}}let d=[1,3,7,15,20].map(h=>h*se).filter(h=>h<=c);return f(0,d,!0)??{beta:0,trimmed:!1}}function W1(e,t){let{lo:r,hi:n}=t,o=t.ayLo,a=e(r,o).cn,s=e(n,o).cn,i=r;for(let c=0;c<40;c++){let l=s-a,u=Math.abs(l)>1e-12?(r*s-n*a)/l:.5*(r+n);u>Math.min(r,n)&&u<Math.max(r,n)||(u=.5*(r+n));let m=e(u,o),f=m.cn;if(o!==void 0&&(o=m.ay),i=u,Math.abs(f)<1e-5||Math.abs(n-r)<1e-5)break;f<0==a<0?(r=u,a=f,s*=.5):(n=u,s=f,a*=.5)}return i}function $D(e,t,r,n,o,a,s){let i=(f,p)=>{let d=Ct(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<GD;f++){let p=i(c+Kh,l),d=i(c,l+Hh),h=(p.r-u.r)/Kh,b=(d.r-u.r)/Hh,g=(p.c-u.c)/Kh,y=(d.c-u.c)/Hh,R=h*y-b*g;if(!Number.isFinite(R)||R===0||Math.abs(R)<YD*(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,KD/Math.max(Math.abs(k),1e-300),HD/Math.max(Math.abs(v),1e-300));if(c+=x*k,l+=x*v,Math.abs(c-o)>zD||Math.abs(c)>s||l*a<0)return null;u=i(c,l)}return null}var GD=8,Kh=1e-5,Hh=.001,KD=1*se,HD=2,zD=5*se,YD=.5;function J1(e,t,r,n,o,a,s,i){let c=Ct(e,t,r,n,o,a,s,void 0,i),l=c.ay*Me/r,u={},m=0;for(let d of fn){let h=c.wheels[d],b=ge(t,dn(d)),g=Wt(b),y=b.muY(Math.min(h.Fz,g)),R=b.muX(Math.min(h.Fz,g));m+=h.fxShort,u[d]={Fz:h.Fz,steerDeg:h.steerRad/se,slipDeg:h.slipRad/se,camberDeg:h.camberRad/se,Fy:h.Fy,Fx:h.Fx,Mz:Zh(b,d,h),gripUtil:y*h.Fz>0?Math.hypot(h.Fy/(y*h.Fz),R*h.Fz>0?h.Fx/(R*h.Fz):0):0,...h.Fz>g?{pastTurnover:!0}:{},lifted:h.lifted}}let f=Vs(e,o/se,u,sn(ge(t,"front").model),{FL:c.wheels.FL.travelMm,FR:c.wheels.FR.travelMm}),p=Xn(e,o,e.kinFront&&e.kinRear?{FL:c.wheels.FL.travelMm,FR:c.wheels.FR.travelMm}:void 0);return{wheels:u,ay:c.ay,ax:s?.axG??0,beta:n/se,yawRate:l*180/Math.PI,steerDeg:o/se,...p.atLock?{lockDeg:(p.steer.FL+p.steer.FR)/2/se}:{},converged:!0,trimmed:!c.overturned,overturned:c.overturned,driving:!1,fxShortfall:m,...f?{steering:f}:{}}}function Vr(e,t,r,n,o,a,s=0){let i=Math.max(8,r),c=Wn(e,t,i,n,o,a,s);return n!==0&&o?.driving===void 0&&(c.driving=sE(e,t,i,c,a,s)),c}function Wn(e,t,r,n,o,a,s){let i=n*se,c=ga(e,a,r,t),l=o&&Number.isFinite(o.ay)?o.ay*Me:void 0,u=o&&Number.isFinite(o.beta)?o.beta*se:void 0,{beta:m,trimmed:f,ay:p}=BD(e,t,r,i,u,l,c,s),d=J1(e,t,r,m,i,l,c,p),h={...d,trimmed:f&&!d.overturned};return h.driving=n===0?h.trimmed:o?.driving!==void 0&&o.driving&&h.trimmed&&Math.abs(h.beta-o.beta)<=WD,h}var WD=3;function Un(e,t,r,n={}){let o=Math.max(8,r),a=n.direction??1,s=n.yawDemandCn??0,i=n.steerMaxDeg??jD,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=zh.get(e)?.get(t)?.get(l);if(x)return x}let u=(x,M)=>M.trimmed&&Math.abs(M.beta-x.beta)<=hu&&Math.abs(M.ay-x.ay)*Me<=bu,m=!1,f=(x,M)=>{let F=Wn(e,t,o,a*x,M,c(a*x),s);return u(M,F)?(F.driving=!0,F):(m=F.overturned,null)},p=[Wn(e,t,o,0,void 0,c(0),s)],d=null,h=!1,b,g=x=>{let M=p.length-1;for(;M>1&&x.sb*(p[M].beta-p[M-1].beta)>=0;)M--;let F=a*(x.state.ay-p[M].ay)>0,w=C=>x.sb*(C.beta-x.state.beta)>0||a*C.steerDeg>=a*x.state.steerDeg||F&&a*C.ay>=a*x.state.ay;for(;p.length>Math.max(2,M)&&w(p[p.length-1]);)p.pop();b={state:x.state,stall:p[p.length-1]},p.push(x.state),d=Math.abs(x.state.steerDeg)},y=(x,M=!1)=>M||nE(p[p.length-1],x)?oE(e,t,o,a,p,x,c,s):null,R=p[0].trimmed?p[0]:null;if(!R){let x=0;for(let M=j1;M<=i&&!R;M+=j1){let F=Wn(e,t,o,a*M,void 0,c(a*M),s);if(F.trimmed){let w=M;R=F;for(let C=0;C<6;C++){let T=.5*(x+w),S=Wn(e,t,o,a*T,void 0,c(a*T),s);S.trimmed?(w=T,R=S):x=T}}else x=M}R&&(R.driving=!0,p.push(R))}if(R){let x=Math.abs(R.steerDeg),M=Math.min(Yh,100/(o*o)),F=R;for(;x<i;){let w=Math.min(i,x+M),C=f(w,F);if(C){let L=y(C);if(L){g(L);break}if(p.push(C),w>=i||ik(e,a*w))break;Math.abs(C.beta-F.beta)<.5*hu&&Math.abs(C.ay-F.ay)*Me<.5*bu&&(M=Math.min(Yh,1.5*M)),x=w,F=C;continue}if(M>UD){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(Yh,100/(o*o)),S=!0;break}}if(S)continue;if(A){g(A);break}d=x,h=T;let P=T?null:rE(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=zh.get(e);x||(x=new WeakMap,zh.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 zh=new WeakMap,jD=90,hu=1.5,bu=2.5,Yh=5,UD=.002,XD=[.5,1],j1=2.5,ek=.01,Or=.001,QD=.05,qD=.25,ZD=5,JD=2,U1=1e-8,eE=1e-7,tE=1e-6;function tk(e,t,r,n,o,a,s){let i=n*se,c=o.ay*Me,l=b=>{let g=Ct(e,t,r,i,b*se,c,ga(e,a(b),r,t));return{g:g.cn-s,ay:g.ay}},u=o.steerDeg,m=l(u),f=u+(u<0?-.001:.001),p=l(f),d=()=>p.g===0||Math.abs(f-u)<U1;for(let b=0;b<40&&Math.sign(m.g)===Math.sign(p.g)&&!d();b++){let g=(p.g-m.g)/(f-u),y=g!==0?f-p.g/g:f+2*(f-u);if(!Number.isFinite(y))return null;let R=2*Math.abs(f-u)+.001;if(y=f+Math.max(-R,Math.min(R,y-f)),u=f,m=p,f=y,p=l(f),Math.abs(f-o.steerDeg)>JD)return null}let h={x:f,ay:p.ay};if(Math.sign(m.g)!==Math.sign(p.g)){let b=u,g=m.g,y=f,R=p.g;for(let k=0;k<60&&R!==0&&Math.abs(y-b)>U1;k++){let v=(b*R-y*g)/(R-g),x=l(v);if(h={x:v,ay:x.ay},x.g===0)break;Math.sign(x.g)===Math.sign(g)?(b=v,g=x.g,R*=.5):(y=v,R=x.g,g*=.5)}}else if(!d())return null;return Math.abs(h.ay-o.ay)*Me>bu?null:{steerDeg:h.x,ay:h.ay}}function ii(e,t,r,n,o){let a=J1(e,t,r,n.beta*se,n.steerDeg*se,n.ay*Me,ga(e,o(n.steerDeg),r,t));return{...a,trimmed:!a.overturned,driving:!a.overturned}}function rE(e,t,r,n,o,a,s){let i=o.length;if(i<3)return null;let c=o[i-1],l=i-2;for(;l>1&&o[l].beta===c.beta;)l--;let u=o[l],m=Math.sign(c.beta-u.beta);if(m===0||!u.driving)return null;let f=rk(e,t,r,a,s),p=f(u.beta,u),d=f(c.beta,c);if(!p||!d)return null;let h=n*d.steerDeg>=n*p.steerDeg,b=h?p:d,g=h?d:p,y=h?m:-m,R=null;for(let x=ek;Math.abs(g.beta-c.beta)<=hu;x*=1.5){let M=f(g.beta+y*x);if(!M)return null;if(n*M.steerDeg<=n*g.steerDeg){R=M;break}b=g,g=M}if(!R)return null;let k=nk(f,n,b,g,R);if(!k)return null;let v=ii(e,t,r,k,a);return!v.trimmed||Math.abs(v.beta-c.beta)>hu||Math.abs(v.ay-c.ay)*Me>bu?null:{state:v,sb:m}}function rk(e,t,r,n,o){let a=[];return(s,i)=>{if(!i){i=a[0];for(let u of a)Math.abs(u.beta-s)<Math.abs(i.beta-s)&&(i=u)}let c=tk(e,t,r,s,i,n,o);if(!c)return null;let l={beta:s,...c};return a.push(l),l}}function nE(e,t){let r=Math.abs(t.beta-e.beta);return r>qD&&r>ZD*Math.abs(t.steerDeg-e.steerDeg)}function oE(e,t,r,n,o,a,s,i){let c=o.length;if(c<2)return null;let l=o[c-1],u=c-2;for(;u>0&&o[u].beta===l.beta;)u--;let m=o[u],f=Math.sign(a.beta-l.beta);if(f===0||Math.sign(l.beta-m.beta)!==f||!m.driving)return null;let p=rk(e,t,r,s,i),d=p(m.beta,m),h=p(l.beta,l);if(!d||!h||n*h.steerDeg<n*d.steerDeg)return null;let b=d,g=h,y=null;for(let R=ek;f*(a.beta-g.beta)>0;R=Math.min(QD,1.5*R)){let k=p(f*(a.beta-g.beta)>R?g.beta+f*R:a.beta);if(!k)return null;let v=n*k.steerDeg<=n*g.steerDeg;if(!y)v&&(y=[b,g,k]);else if(!v){let x=nk(p,n,...y);if(!x)return null;let M=ii(e,t,r,x,s);return M.trimmed?{state:M,sb:f}:null}b=g,g=k}return null}function nk(e,t,r,n,o){let a=p=>-t*p.steerDeg,s=Math.min(r.beta,o.beta),i=Math.max(r.beta,o.beta),c=n,l=a(r)<=a(o)?r:o,u=l===r?o:r,m=i-s,f=0;for(let p=0;p<100;p++){let d=.5*(s+i);if(Math.abs(c.beta-d)<=2*Or-.5*(i-s))break;let h=!0;if(Math.abs(m)>Or){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*Or||i-v<2*Or)&&(f=d>=c.beta?Or:-Or),h=!1}}h&&(m=c.beta>=d?s-c.beta:i-c.beta,f=ak*m);let b=e(Math.abs(f)>=Or?c.beta+f:c.beta+(f>=0?Or:-Or));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 Jh(e,t,r,n,o,a,s=[n.stall]){let i=typeof o.op=="function"?o.op:()=>o.op,c=o.yawDemandCn??0,l="steerDeg"in a?b=>Math.abs(b.steerDeg)-Math.abs(a.steerDeg):b=>Math.abs(b.ay)-Math.abs(a.ayG),u=[...s,n.state].map(b=>({beta:b.beta,steerDeg:b.steerDeg,ay:b.ay})),m=u[0],f=u[u.length-1],p=l(m),d=l(f);if(p>0||d<0)return null;if(d===0)return ii(e,t,r,f,i);let h=m;for(let b=0;b<60&&Math.abs(f.beta-m.beta)>1e-9;b++){let g=(m.beta*d-f.beta*p)/(d-p),y=u[0];for(let x of u)Math.abs(x.beta-g)<Math.abs(y.beta-g)&&(y=x);let R=tk(e,t,r,g,y,i,c);if(!R)return null;let k={beta:g,...R};u.push(k),h=k;let v=l(k);if(Math.abs(v)<("steerDeg"in a?eE:tE))break;v<0?(m=k,p=v,d*=.5):(f=k,d=v,p*=.5)}return ii(e,t,r,h,i)}function aE(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 Jh(e,t,r,n.fold,a,{steerDeg:o});let u=typeof a.op=="function"?a.op(o):a.op,m=Wn(e,t,r,o,l,u,a.yawDemandCn??0);return m.driving?m:null}function sE(e,t,r,n,o,a){if(!n.trimmed)return!1;let s=n.steerDeg<0?-1:1,{states:i}=Un(e,t,r,{direction:s,op:o,yawDemandCn:a}),c=Math.abs(n.steerDeg);if(c>Math.abs(i[i.length-1].steerDeg)+1e-9)return!1;let l=0;for(;l<i.length-2&&Math.abs(i[l+1].steerDeg)<c;)l++;let u=i[l],m=i[Math.min(l+1,i.length-1)],f=Math.abs(m.steerDeg)-Math.abs(u.steerDeg),p=f>0?Math.min(1,Math.max(0,(c-Math.abs(u.steerDeg))/f)):0,d=u.beta+p*(m.beta-u.beta),h=u.ay+p*(m.ay-u.ay);return Math.abs(n.beta-d)<=1&&Math.abs(n.ay-h)<=.05}function hn(e,t,r,n,o){let a=Math.max(8,r),s=n>=0?1:-1,i=Math.abs(n),c=(b,g)=>Vr(e,t,a,s*b,g,o),l=Un(e,t,a,{direction:s,op:o}),{fold:u}=l;if(u&&Math.abs(u.state.steerDeg)<=ba){if(i>Math.abs(u.state.ay))return Q1(e,t,a,s,i,o);if(i>Math.abs(u.stall.ay)){let b=Jh(e,t,a,u,{direction:s,op:o},{ayG:i});if(b)return b}}let m=l.states.filter(b=>Math.abs(b.steerDeg)<=ba),f=m[m.length-1],p=l.states.length>m.length;p&&Math.abs(f.steerDeg)<ba&&m.push(c(ba,f));let d=m.findIndex(b=>Math.abs(b.ay)>=i);if(d===0)return Vr(e,t,a,0,void 0,o);if(d>0)return X1(m[d-1],m[d],i,c);let h=ok(m,c,void 0,p||l.foldDeg===null);return h.ay>=i?X1(h.below,h.state,i,c):l.foldDeg!==null&&l.foldDeg<ba?Q1(e,t,a,s,i,o):h.state}var ba=20;function X1(e,t,r,n){let o={steer:Math.abs(e.steerDeg),f:Math.abs(e.ay)-r},a={steer:Math.abs(t.steerDeg),f:Math.abs(t.ay)-r},s=a.f===o.f?.5:-o.f/(a.f-o.f),i={ay:e.ay+s*(t.ay-e.ay),beta:e.beta+s*(t.beta-e.beta),driving:e.driving},c=0,l=null,u=1/0;for(let m=0;m<60;m++){let f=a.f===o.f?.5*(o.steer+a.steer):o.steer-o.f*(a.steer-o.steer)/(a.f-o.f),p=n(f,i),d=Math.abs(p.ay)-r;if(Math.abs(d)<u&&(l=p,u=Math.abs(d)),Math.abs(d)<=iE||a.steer-o.steer<=cE)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 iE=1e-9,cE=1e-7;function ok(e,t,r,n=!1){let o=r??0;if(r===void 0)for(let x=1;x<e.length;x++)Math.abs(e[x].ay)>Math.abs(e[o].ay)&&(o=x);let a=e[Math.max(0,o-1)],s=Math.abs(e[o].steerDeg),i=lE/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-uE,F=o>0&&n&&M>Math.abs(a.steerDeg)?t(M,a):null;if(!F||Math.abs(F.ay)<=Math.abs(e[o].ay)){let w=t(s,a);return{state:w,below:a,ay:Math.abs(w.ay)}}g=w=>t(w,a),c=Math.abs(a.steerDeg),l=x,u=M,m=-Math.abs(F.ay),b=F,f=x,p=-Math.abs(e[o].ay),d=c,h=-Math.abs(a.ay)}let y=l-c,R=0;for(let x=0;x<100;x++){let M=.5*(c+l);if(Math.abs(u-M)<=2*i-.5*(l-c))break;let F=!0;if(Math.abs(y)>i){let S=(u-f)*(m-h),A=(u-d)*(m-p),P=(u-d)*A-(u-f)*S;A=2*(A-S),A>0&&(P=-P),A=Math.abs(A);let L=y;if(y=R,Math.abs(P)<Math.abs(.5*A*L)&&P>A*(c-u)&&P<A*(l-u)){R=P/A;let D=u+R;(D-c<2*i||l-D<2*i)&&(R=M>=u?i:-i),F=!1}}F&&(y=u>=M?c-u:l-u,R=ak*y);let w=Math.abs(R)>=i?u+R:u+(R>=0?i:-i),C=g(w),T=-Math.abs(C.ay);T<=m?(w>=u?c=u:l=u,d=f,h=p,f=u,p=m,u=w,m=T,b=C):(w<u?c=w:l=w,T<=p||f===u?(d=f,h=p,f=w,p=T):(T<=h||d===u||d===f)&&(d=w,h=T))}let k=b??t(s,a),v=Math.abs(k.steerDeg)>s?e[o]:a;return{state:k,below:v,ay:Math.abs(k.ay)}}var lE=.001,uE=.01,ak=(3-Math.sqrt(5))/2;function Q1(e,t,r,n,o,a){let s=l=>Math.abs(Vr(e,t,r,n*l,void 0,a).ay),i=0,c=ba;if(s(c)<o)return Vr(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 Vr(e,t,r,n*.5*(i+c),void 0,a)}function eb(e,t,r,n,o){let a=hn(e,t,r,n,o);return a.steering?Math.abs(a.steering.totalNm):NaN}function tb(e,t,r,n,o){if(!$n(e))return NaN;let a=n<0?-1:1,s=Math.abs(n),i=hn(e,t,r,a*s,o);if(!i.steering)return NaN;let c=Math.abs(i.steerDeg);for(let l of[.05,.1,.2,.4]){let u=Math.max(0,c-l),m=c+l,f=Vr(e,t,r,a*u,void 0,o),p=Vr(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 jh(e,t,r,n,o,a){let s=Math.max(8,r),i=Ct(e,t,s,n*se,o*se,void 0,ga(e,a,s,t));return{ay:i.ay,cn:i.cn}}function rb(e,t,r,n,o){let a=Math.max(8,r),s=hn(e,t,a,n,o),i=.5,c=jh(e,t,a,s.beta+i,s.steerDeg,o).cn,l=jh(e,t,a,s.beta-i,s.steerDeg,o).cn;return(c-l)/(2*i*se)*e.massTotal*Me*(e.wheelbase/1e3)}function nb(e,t,r,n){let o=Math.max(8,r),{branch:a,opts:s}=mE(e,t,o,n);return sk(e,t,o,a,s)}function mE(e,t,r,n){if(!e.tv?.enabled){let s=n?{op:n}:{};return{branch:Un(e,t,r,s),opts:s}}let o=Uh(e,t,r),a={op:s=>{let i=Xh(e,r,s,o);return i===0?n:{axG:n?.axG??0,driveFrontFrac:n?.driveFrontFrac,tvRearDiffN:i}}};return{branch:Un(e,t,r,a),opts:a}}function sk(e,t,r,n,o){let a=typeof o.op=="function"?o.op:()=>o.op,s=o.yawDemandCn??0;if(n.fold&&n.peak===n.fold.state)return ii(e,t,r,n.peak,a);let i=(l,u)=>Wn(e,t,r,l,u,a(l),s),c=n.states[0].driving||!n.peak.driving?n.states:n.states.slice(1);return ok(c,i,c.indexOf(n.peak),n.foldDeg===null).state}function ob(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}=Wh(e),d=o===void 0?0:p/o,h=o===void 0?0:(f+p)/o,b=n.nLines??9,g=n.nPts??21,y=n.steering!==!1&&$n(e),R=y?sn(ge(t,"front").model):void 0,k=(I,_,B,O)=>B===1?I:I+(_-I)*O/(B-1),v=e.tv?.enabled?Uh(e,t,a):0,x=I=>{let _=Xh(e,a,I/se,v);return!n.axG&&_===0?null:ga(e,{axG:n.axG??0,driveFrontFrac:n.driveFrontFrac,tvRearDiffN:_},a,t)},{lf:M,lr:F}=Wh(e),w=n.reserves?ci(t,e.massTotal*Me*1.2):null,C=I=>w?Ar(w,{FL:I.FL,FR:I.FR,RL:I.RL,RR:I.RR},{lf:M,lr:F}):null,T=[],S={ay:[],cn:[]},A=0;for(let I=0;I<b;I++){let _=k(u,m,b,I),B=x(_),O=[],G=[],K=[],Y=[],j=w?{stabil:[],agil:[]}:void 0,Z=y?H1():void 0,ne;for(let W=0;W<g;W++){let J=k(c,l,g,W),re=Ct(e,t,a,J,_,ne,B,o);if(ne=Number.isFinite(re.ay)?re.ay*Me:void 0,O.push(re.ay),G.push(re.cn),K.push(J/se),Y.push(_/se),j){let pe=C(re.wheels);j.stabil.push(pe.stabil),j.agil.push(pe.agil)}Z&&z1(Z,K1(e,t,_,re.wheels)),Math.abs(re.ay)>A&&(A=Math.abs(re.ay))}T.push({label:`\u03B4 ${(_/se).toFixed(0)}\xB0`,ay:O,cn:G,betaDeg:K,deltaDeg:Y,reserve:j,steering:Z});let te=null,fe=1/0;for(let W=1;W<G.length;W++){if(!Number.isFinite(G[W-1])||!Number.isFinite(G[W])||G[W-1]!==0&&G[W-1]<0==G[W]<0)continue;let J=G[W-1]===G[W]?0:G[W-1]/(G[W-1]-G[W]),re=O[W-1]+J*(O[W]-O[W-1]);if(o===void 0&&_!==0&&Math.abs(re)>=.05&&Math.sign(re)!==Math.sign(_))continue;let pe=Math.abs(K[W-1]+J*(K[W]-K[W-1])-d/se);pe<fe&&(fe=pe,te=re)}te!==null&&(S.ay.push(te),S.cn.push(0))}let P=[];for(let I=0;I<b;I++){let _=k(c,l,b,I),B=[],O=[],G=[],K=[],Y=w?{stabil:[],agil:[]}:void 0,j=y?H1():void 0,Z;for(let ne=0;ne<g;ne++){let te=k(u,m,g,ne),fe=Ct(e,t,a,_,te,Z,x(te),o);if(Z=Number.isFinite(fe.ay)?fe.ay*Me:void 0,B.push(fe.ay),O.push(fe.cn),G.push(_/se),K.push(te/se),Y){let W=C(fe.wheels);Y.stabil.push(W.stabil),Y.agil.push(W.agil)}j&&z1(j,K1(e,t,te,fe.wheels))}P.push({label:`\u03B2 ${(_/se).toFixed(0)}\xB0`,ay:B,cn:O,betaDeg:G,deltaDeg:K,reserve:Y,steering:j})}let L=.5*se,D=x(h),E,V;if(o===void 0)E=(Ct(e,t,a,d+L,h,void 0,D,o).cn-Ct(e,t,a,d-L,h,void 0,D,o).cn)/(2*L),V=(Ct(e,t,a,d,h+L,void 0,x(h+L),o).cn-Ct(e,t,a,d,h-L,void 0,x(h-L),o).cn)/(2*L);else{let I=(O,G)=>Ct(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=Ct(e,t,a,d,h,void 0,D,o),_=0;for(let B of fn)_+=I.wheels[B].fxShort;N=_/Math.abs(e.massTotal*D.axG*Me)}let z=S.ay.reduce((I,_)=>Math.max(I,Math.abs(_)),0);return{isoBeta:P,isoDelta:T,trim:S,maxAy:A,stability:E,control:V,speed:o===void 0?a:Math.sqrt(z*Me*o),...o!==void 0?{radius:o}:{},axG:D?.axG??0,axShortfall:N,...R?{steeringAligningSource:R}:{}}}function ik(e,t){return Xn(e,t*se).atLock}function pE(e,t,r,n,o=Nr(e,t,r)){let a=r,s=e.massTotal,i=fn.filter(g=>jt(g)?n.drivenFront:n.drivenRear),c=o.peakAt,l={front:n.drivenFront?$t(e,"front",1):void 0,rear:n.drivenRear?$t(e,"rear",1):void 0},u=new Map,m=(g,y)=>{let R=`${g}:${y}`,k=u.get(R);if(k===void 0){let v=Math.max(1,y*ai);k=At(ge(t,g),v,0,!1,c(g,v)),u.set(R,k)}return k},f=(g,y)=>y>0?oi(y,R=>m(g,R)):0,p=(g,y,R,k)=>{let v=ge(t,g),x=D=>{let E=Math.max(0,R[D]),V=c(g,E);return{Fz:E,a:f(g,E),b:V.fyPeak,slide:0,cap:N=>E>0?At(v,E,N,!1,V):0}},[M,F]=g==="front"?["FL","FR"]:["RL","RR"],w=x(M),C=x(F),T=k[M]*w.b,S=k[F]*C.b,A=w.cap(T)+C.cap(S),P=ni(w,C,T+S,y,A);return{l:M,r:F,full:P,asHeld:()=>({axle:g,strong:w.cap(T)>=C.cap(S)?M:F,full:P,open:ni(w,C,T+S,pa,A),sense:1})}},d=g=>({muX:y=>y>0?f(g,y)/y:0,muY:y=>y>0?c(g,y).fyPeak/y:0}),h={front:d("front"),rear:d("rear")},b=g=>({arms:{lf:e.wheelbase/1e3*(1-e.frontMassFrac),lr:e.wheelbase/1e3*e.frontMassFrac},halfTrack:{front:e.trackFront/2e3,rear:e.trackRear/2e3},ayDir:Math.sign(g)});return{limitAt:(g,y,R,k=0)=>{let v={FL:0,FR:0,RL:0,RR:0},x=Ce(e,g,0,a,0,y),M,F=P=>(M?.ax!==P&&(M={ax:P,loads:Ce(e,g,(P+k)/Me,a,0,y)}),M.loads),w=vl(P=>ea(R,F(P),x,c).short,-k,1),C=R,T=P=>{let L=w.at(P);v=F(L),C=ea(R,v,x,c).util;let D=0,E=n.diffYaw?{fx:{FL:0,FR:0,RL:0,RR:0},axles:[]}:null;for(let V of i){let N=l[dn(V)];if(N){if(fu(V)){let B=p(dn(V),N,v,C);D+=B.full,E&&(E.fx[B.l]=E.fx[B.r]=B.full/2,E.axles.push(B.asHeld()))}continue}let z=Math.max(0,v[V]),I=c(dn(V),z),_=At(ge(t,dn(V)),z,C[V]*I.fyPeak,!1,I);D+=_,E&&(E.fx[V]=_)}if(E){let V={};for(let N of fn){let z=Math.max(0,v[N]);V[N]={Fz:z,Fy:C[N]*c(dn(N),z).fyPeak,Fx:E.fx[N]}}for(let N of E.axles)D+=Gl(N,V,h,b(g))-N.full}return D/s},S=C1(T,-k,pn).fx,A=w.edge();return A!==void 0&&S>A&&(S=A,T(S)),{ax:S,loads:v}}}}var du=.05,q1=.001,Z1=16,gu=8;function ab(e,t,r,n){let o=Math.max(gu,r),a=n.nSteer??7,s=e.tv?.enabled?Uh(e,t,o,n.steerMaxDeg):0,i=I=>{let _=Xh(e,o,I,s);return _===0?void 0:{axG:0,tvRearDiffN:_}},c=n.yawDemandCn??0,l={op:i,yawDemandCn:c,...n.steerMaxDeg!==void 0?{steerMaxDeg:n.steerMaxDeg}:{}},u=Un(e,t,o,l),m=I=>{let _={},B={};for(let O of fn)_[O]=I.wheels[O].slipDeg*se,B[O]=Math.min(1,I.wheels[O].gripUtil);return{steerDeg:I.steerDeg,ayMs:Math.max(0,I.ay*Me),ayG:I.ay,slip:_,util:B,scrub:I.ay>0?dE(I,e.massTotal):0}},f=null,p=I=>{if(f&&I===f.steerDeg)return m(f);let _=aE(e,t,o,u,I,l);if(_)return m(_);let B=u.states[0];for(let O of u.states)O.steerDeg<=I&&(B=O);return m(B)},d=u.peak.driving&&u.peak.ay>0?sk(e,t,o,u,l):null,h=d?Math.max(0,d.ay*Me):0,b=d?[...u.states.filter(I=>I.steerDeg<d.steerDeg),d]:u.states,g=d?b.findIndex(I=>I.ay*Me>=.995*h):0,y=b[g].steerDeg,{fold:R}=u;if(d&&R&&u.peak===R.state){let I=.995*h/Me,_=u.states.indexOf(R.stall),B=_-1;for(;B>0&&u.states[B].beta===R.stall.beta;)B--;let O=Math.sign(R.stall.beta-u.states[B].beta),G=_;for(;G>0&&u.states[G].ay>=I&&Math.sign(u.states[G].beta-u.states[G-1].beta)!==-O;)G--;u.states[G].ay<I&&(f=Jh(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=Nr(e,t,o,void 0,n.diffYaw===!0),C=pE(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>du}},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+du&&O.push({read:G=>({axA:A(G)}),past:G=>(G.axA??-1/0)>_.axA}),-B.axD>-_.axD+du&&O.push({read:S,past:G=>-(G.axD??0)>-_.axD}));for(let{read:G,past:K,braking:Y}of O){let j=_.p.steerDeg,Z=B.p.steerDeg,ne=null,te=_.axD,fe=B.axD;for(let W=0;W<Z1&&Z-j>q1&&!(Y&&Math.abs(fe-te)<=du);W++){let J=.5*(j+Z),re=p(J),pe=G(re);K(pe)?(Z=J,ne={p:re,r:pe},fe=pe.axD??fe):(j=J,te=pe.axD??te)}if(ne){let{p:W,r:J}=ne,re=J.axD!==void 0&&J.locked!==void 0?{axD:J.axD,locked:J.locked}:S(W);L.push({p:W,axA:J.axA??A(W),...re})}}}P.push(...L),P.sort((I,_)=>I.p.steerDeg-_.p.steerDeg);let D=I=>I.axA+T+I.p.scrub,E=.001*Math.max(1,k[k.length-1].ayMs),V=[];for(let I=0;I+1<P.length;I++){let _=P[I],B=P[I+1];if(!(D(_)>=0&&D(B)<0))continue;let O=_.p.steerDeg,G=B.p.steerDeg,K=null,Y=null;for(let Z=0;Z<Z1&&G-O>q1;Z++){let ne=.5*(O+G),te=p(ne);D({p:te,axA:A(te)})>=0?(O=ne,K=te):(G=ne,Y=te)}let j=K??Y;j&&j.ayMs>_.p.ayMs&&j.ayMs<B.p.ayMs&&V.push({p:j,axA:-(T+j.scrub),steady:!0,...S(j)})}P.push(...V),P.sort((I,_)=>I.p.steerDeg-_.p.steerDeg);let N=!1;for(let{p:I,axA:_,axD:B,steady:O}of P){let G=v.length-1,K=G>=0&&(O||N?!(I.ayMs>v[G]):I.ayMs-v[G]<E);N=O===!0&&!K,K?(x[G]=Math.max(x[G],_),M[G]=Math.min(M[G],B)):(v.push(I.ayMs),x.push(_),M.push(B),F.push(I.scrub))}for(let I=v.length-2;I>=0;I--)x[I]=Math.max(x[I],x[I+1]),M[I]=Math.min(M[I],M[I+1]);return{ayMax:v[v.length-1],ay:v,axAccel:x,axDecel:M,axScrub:F,rollover:u.rollover,atLock:d!==null&&ik(e,d.steerDeg)}}function dE(e,t){let r=e.beta*se,n=0;for(let o of fn){let a=e.wheels[o],s=a.steerDeg*se-r;n+=a.Fx*(Math.cos(s)-1)-a.Fy*Math.sin(s)}return n/t}var dU=Math.PI/180,fU={speeds:Array.from({length:23},(e,t)=>8+t),steerMaxDeg:14,steerSteps:29};function lk(e=150,t=300,r=18,n=25){return(o,a,s)=>{let i=Math.min(1,Math.max(0,(o-r)/(n-r))),c=s>0?Math.min(1,a/s):0;return(e+i*(t-e))*c}}var ya={enabled:!1,kp:3e3,ffLow:150,ffHigh:300,vLow:18,vHigh:25},ck=e=>lk(e.ffLow,e.ffHigh,e.vLow,e.vHigh);var cr={power_limit_kw:{value:0,label:"battery power limit (0 = none)",unit:"kW"},v_limit_endurance:{value:0,label:"endurance speed limit (0 = none)",unit:"km/h"},endurance_reserve:{value:0,label:"endurance energy reserve (0 = flat out)",unit:"%"},grip_scale:{value:1,label:"grip scale (rig \u2192 road)",unit:"-"},stiffness_scale:{value:1,label:"stiffness scale (rig \u2192 road)",unit:"-"},camber_front_deg:{value:0,label:"static camber front (\u2212 top in)",unit:"\xB0"},camber_rear_deg:{value:0,label:"static camber rear (\u2212 top in)",unit:"\xB0"},cg_height:{value:300,label:"CG height",unit:"mm"},tire_vertical_rate:{value:100,label:"tyre vertical rate",unit:"N/mm"},tire_vertical_damping:{value:0,label:"tyre vertical damping",unit:"N\xB7s/mm"},arb_front:{value:20,label:"ARB front (@wheel)",unit:"N/mm"},arb_rear:{value:15,label:"ARB rear (@wheel)",unit:"N/mm"},heave_spring_front:{value:0,label:"Heave spring front (@wheel)",unit:"N/mm"},heave_spring_rear:{value:0,label:"Heave spring rear (@wheel)",unit:"N/mm"},unsprung_mass:{value:8,label:"unsprung mass/corner",unit:"kg"},brake_balance:{value:.6,label:"brake balance (front)",unit:"-"},damper_front:{value:2.5,label:"damper front",unit:"N\xB7s/mm"},damper_rear:{value:2.5,label:"damper rear",unit:"N\xB7s/mm"},cop_long:{value:.5,label:"CoP aft of front",unit:"\xB7wb"},cop_height:{value:300,label:"CoP height",unit:"mm"},ride_height_front:{value:30,label:"static ride height front (laden)",unit:"mm"},ride_height_rear:{value:35,label:"static ride height rear (laden)",unit:"mm"},I_yaw:{value:295,label:"yaw inertia Izz",unit:"kg\xB7m\xB2"},I_roll:{value:95,label:"roll inertia Ixx",unit:"kg\xB7m\xB2"},I_pitch:{value:380,label:"pitch inertia Iyy",unit:"kg\xB7m\xB2"},I_wheel:{value:0,label:"rotating inertia per wheel",unit:"kg\xB7m\xB2"},I_rotor:{value:0,label:"driveline inertia at the motor",unit:"kg\xB7m\xB2"},ackermann_pct:{value:50,label:"Ackermann",unit:"%"},toe_front_deg:{value:0,label:"static toe front (+ in)",unit:"\xB0"},toe_rear_deg:{value:0,label:"static toe rear (+ in)",unit:"\xB0"},spring_front:{value:35,label:"spring front (@spring)",unit:"N/mm"},spring_rear:{value:40,label:"spring rear (@spring)",unit:"N/mm"},mr_front:{value:1,label:"motion ratio front",unit:"-"},mr_rear:{value:1,label:"motion ratio rear",unit:"-"},track_front:{value:1200,label:"track front",unit:"mm"},track_rear:{value:1200,label:"track rear",unit:"mm"},wheelbase:{value:1535,label:"wheelbase",unit:"mm"},rc_front:{value:30,label:"roll centre front",unit:"mm"},rc_rear:{value:40,label:"roll centre rear",unit:"mm"},tv_enabled:{value:0,label:"torque vectoring",unit:"0/1"},tv_kp:{value:3e3,label:"TV yaw-rate gain",unit:"N per rad/s"},tv_ff_low:{value:150,label:"TV feedforward, low speed",unit:"N"},tv_ff_high:{value:300,label:"TV feedforward, high speed",unit:"N"},tv_v_low:{value:18,label:"TV feedforward ramp start",unit:"m/s"},tv_v_high:{value:25,label:"TV feedforward ramp end",unit:"m/s"}},fE=["k_yaw","k_roll","k_pitch"];function ui(e){for(let t of fE)delete e[t];for(let t of Object.keys(cr)){let r=e[t];if(!r){e[t]={...cr[t]};continue}e[t]={...r,label:cr[t].label,unit:cr[t].unit}}return e}function q(e,t){return e[t]?.value??cr[t].value}function yu(e){let t=(r,n)=>e[r]?.value??n;return{enabled:t("tv_enabled",0)>=.5,kp:t("tv_kp",ya.kp),ffLow:t("tv_ff_low",ya.ffLow),ffHigh:t("tv_ff_high",ya.ffHigh),vLow:t("tv_v_low",ya.vLow),vHigh:t("tv_v_high",ya.vHigh)}}var uk=[10,25,50,100,200,300];function sb(e,t,r,n,o){let s=uk.map(i=>Math.round(i<=25?r*i:r*25+n*(i-25)));return{id:e,label:t,speedMmS:[...uk],reboundN:s,bumpN:s.map(i=>Math.round(i*o))}}var xu={name:"Generic FS damper",curves:[sb("c1","Soft",1.6,1,.65),sb("c2","Medium",3,1.6,.65),sb("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 bn=25;function xa(e,t){let r=e.speedMmS,n=e.forceN,o=Math.min(r.length,n.length);if(o===0||!(t>0))return 0;let a=0,s=0;for(let i=0;i<o;i++){let c=r[i],l=n[i];if(t<=c)return s+(l-s)*(t-a)/(c-a);if(i===o-1)return l+Math.max(0,(l-s)/(c-a))*(t-c);a=c,s=l}return 0}function mk(e,t){return t>=0?xa(e.rebound,t):-xa(e.bump,-t)}function pk(e,t,r){return t*mk(e,t*r)}var ib=(e,t)=>e.curves.find(r=>r.id===t);function mi(e,t){let r=ib(e,Ru(e)),n=(t&&ib(e,t.bump))??r,o=(t&&ib(e,t.rebound))??r;return{bump:{speedMmS:n?.speedMmS??[],forceN:n?.bumpN??[]},rebound:{speedMmS:o?.speedMmS??[],forceN:o?.reboundN??[]}}}var vu=5e3;function pi(e,t){let r=t>0?t:1,n=[],o=[],a=e.bump.speedMmS.map(c=>c/r).filter(c=>c<vu),s=e.rebound.speedMmS.map(c=>c/r).filter(c=>c<vu),i=c=>{n.push(c),o.push(pk(e,r,c))};i(-vu);for(let c=a.length-1;c>=0;c--)i(-a[c]);i(0);for(let c of s)i(c);return i(vu),{kind:"map",input:"velocity",x:n,y:o}}var cb=64;function di(e,t,r){let n=t>0?t:1,o=Math.max(r,1e-6),a=0;for(let s=0;s<cb;s++){let i=Math.sin((s+.5)*Math.PI/cb),c=n*o*i;a+=n*(xa(e.rebound,c)+xa(e.bump,c))*i}return a*(Math.PI/cb)/(Math.PI*o)}function Qn(e,t,r,n,o=e){let a=(c,l,u)=>{if(!c||c.curves.length===0)return;let m=mi(c,l);return{law:m,curve:pi(m,u),rate:di(m,u,bn)}},s=a(e,t?.front,r),i=a(o??e,t?.rear,n);return!s&&!i?null:{...s?{front:s}:{},...i?{rear:i}:{}}}var dk=(e,t)=>({...e,y:e.y.map(r=>r*t)}),hE=e=>({...e,x:e.x.map(t=>-t).reverse(),y:e.y.map(t=>-t).reverse()});function lb(e,t,r){let n=Math.abs(r)>0?Math.abs(r):1,o=mi(e,t);return{law:o,curve:dk(pi(o,n),.5),rate:di(o,n,bn)/2,mr:n,ratio:n,share:.5}}function ub(e,t,r,n,o){let a=n*(Math.abs(r)>0?Math.abs(r):1),s=mi(e,t),i=dk(pi(s,a),1/n);return{law:s,curve:o?hE(i):i,rate:di(s,a,bn)/n,mr:a/n,ratio:a,share:1/n}}function fi(e,t){let r=e.damperModelIdRear?t(e.damperModelIdRear):void 0,n=e.heaveDamperModelId?t(e.heaveDamperModelId):void 0,o=e.rollDamperModelId?t(e.rollDamperModelId):void 0;return{...r?{damperModelRear:r}:{},...n?{heaveDamperModel:n}:{},...o?{rollDamperModel:o}:{}}}var ku=["front","rear","heaveFront","heaveRear","rollFront","rollRear"];function hi(e,t){if(t?.body){let{extended:n,stroke:o,...a}=e??{},{extended:s,stroke:i}=t.body;return{coilover:{...a,extended:s,...i!==void 0?{stroke:i}:{}},source:"part",part:t}}let r=e?.extended!==void 0&&e.extended>0;return{...e?{coilover:e}:{},source:r?"suspension":"none"}}function Br(e,t){if(typeof e=="number")return e;let{x:r,y:n}=e,o=r.length;if(o===0)return 0;if(o===1||t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}function gi(e){return e.kind==="coil"?2:1}function bi(e){let t=Math.max(0,e.od),r=Math.max(0,Math.min(e.id,t));return Math.PI*(t**4-r**4)/32}function hk(e){return bi(e)/2}function bk(e){let t=Math.max(0,e.width),r=Math.max(0,e.thickness),n=t*r**3/12,o=r*t**3/12,a=e.angleDeg*Math.PI/180;return n*Math.cos(a)**2+o*Math.sin(a)**2}function fk(e){let t=0;for(let r of e)if(Number.isFinite(r)){if(r<=0)return 0;t+=1/r}return t>0?1/t:1/0}function bE(e,t,r){let n=Math.min(e.length,t.length);if(n<2)return 0;let o=Math.abs(r);if(o<=e[0])return(t[1]-t[0])/(e[1]-e[0]);for(let a=1;a<n;a++)if(o<=e[a])return(t[a]-t[a-1])/(e[a]-e[a-1]);return(t[n-1]-t[n-2])/(e[n-1]-e[n-2])}function yi(e,t=0){let r={rateAtLink:0,contributions:{},torsional:0};switch(e.kind){case"none":return r;case"ubar":{let n=e.armLength;if(n<=0||e.barLength<=0)return r;let o=e.G*bi(e.section)/e.barLength,a=2*o/(n*n),s=hk(e.armSection??e.section),i=3*e.E*s/n**3,c=e.dropLinkRate??1/0;return{rateAtLink:fk([a,i,c]),contributions:{barTwist:a,armBending:i,dropLink:c},torsional:o}}case"blade":{let n=e.armLength;if(n<=0||e.barLength<=0)return r;let o=e.G*bi(e.section)/e.barLength,a=2*o/(n*n),s=3*e.E*bk(e.blade)/n**3,i=e.dropLinkRate??1/0;return{rateAtLink:fk([a,s,i]),contributions:{barTwist:a,armBending:s,dropLink:i},torsional:o}}case"torsionTube":{let n=e.leverArm;if(n<=0||e.length<=0)return r;let o=e.G*bi(e.section)/e.length,a=2*o/(n*n);return{rateAtLink:a,contributions:{barTwist:a},torsional:o}}case"coil":{let n=Br(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=bE(e.linkTravel,e.force,t);return{rateAtLink:Math.max(0,n),contributions:{},torsional:0}}}}function Mu(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?Wd(t,r):1,o=t?jd(t,r):0,a=yi(e,o).rateAtLink;return{wheelRate:Math.max(0,a*n*n),motionRatio:n,rateAtLink:a}}function xi(e,t){let r=e.damper??0;return!r||e.design.kind==="none"?0:gi(e.design)*r*t*t}var gE=150;function yE(e){return X(e,[0,-.5,1])<-1e-9?U(e,-1):e}function gk(e){let t=e.hardpoints,r=H(t.rockerPivotB,t.rockerPivotA),n=ee(t.rockerPivotA,U(H(t.rockerToDamper,t.rockerPivotA),.6)),o=yE(Q(ae(r,H(t.rockerToDamper,t.rockerPivotA))));return{outer:n,inner:ee(n,U(o,gE)),attach:"rocker"}}function Tt(e,t){let r={};for(let o of er)r[o]=tt(Ge(e,o));let n={vehicle:e,ctx:r};return t&&(n.kc=hl(n,t)),n}var Su=.5;function xE(e,t){let r=([i,c,l])=>{let u=Q(H(c,i)),m=H(l,i),f=Q(H(m,U(u,X(m,u))));return[u,f,ae(u,f)]},n=r(e),o=r(t),a=[0,1,2].map(i=>[0,1,2].map(c=>o[0][i]*n[0][c]+o[1][i]*n[1][c]+o[2][i]*n[2][c]));return{rot:a,move:i=>{let c=H(i,e[0]);return ee(t[0],[0,1,2].map(l=>a[l][0]*c[0]+a[l][1]*c[1]+a[l][2]*c[2]))}}}var yk=e=>[(e[2][1]-e[1][2])/2,(e[0][2]-e[2][0])/2,(e[1][0]-e[0][1])/2];function Au(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+Su,r.steer,void 0,a),l=ye(o,r.travel-Su,r.steer,void 0,a),u=(s?s.ok:r.converged)&&c.ok&&l.ok,m=at(c),f=at(l),p=(C,T)=>Ot(C.points[T],n),d=o.inv.strut?"pushrodOuter":"uprightUpper",h=p(i,d),b=p(i,"uprightLower"),g=C=>{let T=H(b,h);return Math.hypot(...ae(T,H(p(i,C),h)))/Math.hypot(...T)},y=g("tieOuter")>=g("wheelCenter")?"tieOuter":"wheelCenter",R=[h,b,p(i,y)],k=C=>xE(R,[p(C,d),p(C,"uprightLower"),p(C,y)]),v=k(m),x=k(f),M=yk(v.rot),F=yk(x.rot),w=[NaN,NaN,NaN];return{solved:u,state:i,at:C=>p(i,C),velocity:C=>u?U(H(v.move(C),x.move(C)),1/(2*Su)):w,omega:u?U(H(M,F),1/(2*Su)):w}}function mb(e,t,r,n){let o=t[0]*-n[1]-t[1]*-n[0];if(Math.abs(o)<1e-9)return null;let a=r[0]-e[0],s=r[1]-e[1],i=(a*-n[1]-s*-n[0])/o;return[e[0]+i*t[0],e[1]+i*t[1]]}function xk(e,t,r){let n=Au(e,t,gt(e,r)[t]),o=n.at("contactPatch"),a=n.velocity(o);return{solved:n.solved,cp:[o[1],o[2]],vCp:[a[1],a[2]],wx:n.omega[0]}}function Rk(e){let t=Math.hypot(e.vCp[0],e.vCp[1]);return Math.abs(e.wx)*1e9>t?[e.cp[0]-e.vCp[1]/e.wx,e.cp[1]+e.vCp[0]/e.wx]:null}function vk(e,t){let r=Math.hypot(e.vCp[0],e.vCp[1]);if(!(r>1e-9))return null;let n=[-e.vCp[1]/r,e.vCp[0]/r],o=t?[t[0]-e.cp[0],t[1]-e.cp[1]]:[e.cp[0]>0?-1:1,0];return n[0]*o[0]+n[1]*o[1]<0?[-n[0],-n[1]]:n}function RE(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 vE=.1*Math.PI/180;function kk(e,t,r,n,o){return Math.max(Math.hypot(e[0]-t[0],e[1]-t[1]),Math.hypot(e[0]-r[0],e[1]-r[1]))*vE<=o*n}function Fu(e,t){return!e.valid||!e.cpLeft||!e.cpRight?!1:kk([e.lateral,e.height],e.cpLeft,e.cpRight,e.sinAngle,t)}function Ri(e){let t=(o,a,s)=>{let i=o&&a?[a[0]-o[0],a[1]-o[1]]:s;return!o||!i||!(Math.abs(i[0])>1e-9)?Number.NaN:o[1]-o[0]*i[1]/i[0]},r=t(e.cpLeft,e.icLeft,e.lineLeft),n=t(e.cpRight,e.icRight,e.lineRight);return Number.isFinite(r)&&Number.isFinite(n)?{left:r,right:n}:null}var kE=1;function Mk(e){let t=Ri(e);if(!t||!e.cpLeft||!e.cpRight||Math.abs(t.left-t.right)>kE)return null;let r=(t.left+t.right)/2,n=e.cpRight[0]-e.cpLeft[0],o=e.cpRight[1]-e.cpLeft[1],a=Math.hypot(n,o)||1;return{height:r,heightAboveGround:(0-e.cpLeft[0])*(-o/a)+(r-e.cpLeft[1])*(n/a)}}function Ra(e){let t=(n,o,a)=>{if(!n)return Number.NaN;if(!o)return a?0:Number.NaN;let s=n[0]-o[0];return Math.abs(s)>1e-9?n[0]/s:Number.NaN},r=(t(e.cpLeft,e.icLeft,e.lineLeft)+t(e.cpRight,e.icRight,e.lineRight))/2;return e.valid&&Number.isFinite(r)?r:0}function lr(e,t,r){let n=r==="front"?"FL":"RL",o=r==="front"?"FR":"RR",a=xk(e,n,t),s=xk(e,o,t);if(!a.solved||!s.solved)return{height:0,lateral:0,heightAboveGround:0,lateralAlongGround:0,valid:!1,unsolved:!0,icLeft:null,icRight:null,lineLeft:null,lineRight:null,sinAngle:0,cpLeft:a.cp,cpRight:s.cp};let i=Rk(a),c=Rk(s),l=vk(a,i),u=vk(s,c),m={height:0,lateral:0,heightAboveGround:0,lateralAlongGround:0,valid:!1,icLeft:i,icRight:c,lineLeft:l,lineRight:u,sinAngle:0,cpLeft:a.cp,cpRight:s.cp};if(!l||!u)return m;let f=i?[i[0]-a.cp[0],i[1]-a.cp[1]]:l,p=c?[c[0]-s.cp[0],c[1]-s.cp[1]]:u,d=Math.hypot(f[0],f[1]),h=Math.hypot(p[0],p[1]),b=d>0&&h>0?Math.abs(f[0]*p[1]-f[1]*p[0])/(d*h):0,g=mb(a.cp,f,s.cp,p)??RE(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:lr(e,t,"front"),rear:lr(e,t,"rear")}}function wu(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 ME(e,t){return{camber:wu(e.travel,e.camber,t),toe:wu(e.travel,e.toe,t),motionRatio:wu(e.travel,e.motionRatio,t),damperLen:e.damperLen?wu(e.travel,e.damperLen,t):0}}var Sk=e=>ME(e,0).motionRatio;function pb(e,t){if(e.kind!=="coil")return null;let r=t??e.motionRatio,n=Br(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 Cu(e,t){if(e.kind==="none")return 0;if(e.kind==="tabulated"){let n=a=>SE(e,a);return(n(.5)-n(-.5))/(2*.5)/2}if((e.gap??0)>0)return 0;let r=t??e.motionRatio;return Br(e.rate,0)*r*r/2}function vi(e,t){let r=e.damper??0;if(!r||e.design.kind==="none"||e.design.kind==="coil"&&(e.design.gap??0)>0)return 0;let n=t??(e.design.kind==="coil"?e.design.motionRatio:1);return r*n*n/2}function SE(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 db={kind:"coil",rate:120,motionRatio:.7,gap:5,bothWays:!1};var Ak=new WeakMap;function Pu(e,t){let r=Ak.get(e);r||(r=new Map,Ak.set(e,r));let n=`${t.attach}|${t.outer.join(",")}|${JSON.stringify(t.mount??null)}`,o=r.get(n);if(o)return o;let a=En(e,t);return r.set(n,a),a}var AE=32,ki=new Map,Fk=new WeakMap,FE=1;function wE(e){let t=Fk.get(e);return t===void 0&&(t=FE++,Fk.set(e,t)),t}function fb(e,t){if(!t.linkage)return null;let r=an(e,t.linkage,t.design.kind),n=`${wE(e)}|${r?"unit":"bar"}|${JSON.stringify(t.linkage)}`,o=ki.get(n);if(o)return o;let a=jo(e,t.linkage,{kind:t.design.kind});return ki.size>=AE&&ki.delete(ki.keys().next().value),ki.set(n,a),a}function Zn(e,t,r=0){let n=(o,a)=>{if(!(!o||o.design.kind==="none"))return Mu(o.design,fb(a,o),r).wheelRate};return{front:n(t.arbFrontDesign,e.front),rear:n(t.arbRearDesign,e.rear)}}function va(e,t){let r=(n,o)=>{if(!n||n.design.kind==="none")return;let a=n.linkage?Pu(o,n.linkage).atDesign:void 0;return Cu(n.design,a)};return{front:r(t.heaveFrontDesign,e.front),rear:r(t.heaveRearDesign,e.rear)}}function Lk(e,t){let r=(a,s)=>{if(!a||a.design.kind!=="coil")return;let i=a.linkage?Pu(s,a.linkage).atDesign:void 0;return pb(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 Lu(e,t){let r=(o,a)=>o?vi(o,hb(o,a)):0,n=(o,a)=>o?xi(o,bb(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 hb=(e,t)=>e.linkage?Pu(t,e.linkage).atDesign:void 0,bb=(e,t)=>Mu(e.design,fb(t,e),0).motionRatio;function Dk(e,t){let r=t.damperSetup,n=t.heaveDamperModel??t.damperModel,o=t.rollDamperModel??t.damperModel,a=(f,p,d)=>{if(!f||!n?.curves.length)return;let h=hb(f,p);if(vi(f,h)>0)return lb(n,r?.[d],h??(f.design.kind==="coil"?f.design.motionRatio:1))},s=(f,p,d)=>{if(!f||!o?.curves.length)return;let h=bb(f,p);if(!(xi(f,h)>0))return;let b=fb(p,f)!==null;return ub(o,r?.[d],h,gi(f.design),b&&h>0)},i={},c=a(t.heaveFrontDesign,e.front,"heaveFront"),l=a(t.heaveRearDesign,e.rear,"heaveRear"),u=s(t.arbFrontDesign,e.front,"rollFront"),m=s(t.arbRearDesign,e.rear,"rollRear");return c&&(i.heaveFront=c),l&&(i.heaveRear=l),u&&(i.rollFront=u),m&&(i.rollRear=m),i}function Du(e,t){let r=t.heaveDamperModel??t.damperModel,n=t.rollDamperModel??t.damperModel,o=(i,c)=>qn(i)?{source:"none"}:hi(i.config.coilover,c),a=(i,c)=>{if(!i)return{source:"none"};let l=vi(i,hb(i,c))>0;return hi(i.coilover,l?r:void 0)},s=(i,c)=>{if(!i||i.design.kind!=="coil")return{source:"none"};let l=xi(i,bb(i,c))>0;return hi(i.coilover,l?n:void 0)};return{front:o(e.front,t.damperModel),rear:o(e.rear,t.damperModelRear??t.damperModel),heaveFront:a(t.heaveFrontDesign,e.front),heaveRear:a(t.heaveRearDesign,e.rear),rollFront:s(t.arbFrontDesign,e.front),rollRear:s(t.arbRearDesign,e.rear)}}function Ek(e){let t=(r,n)=>{let o={};return r?.linkage&&r.design.kind==="coil"&&(o.heave=r.linkage),n?.linkage&&n.design.kind!=="none"&&n.design.kind!=="direct"&&(o.roll=n.linkage,o.rollKind=n.design.kind),o.heave||o.roll?o:void 0};return{front:t(e.heaveFrontDesign,e.arbFrontDesign),rear:t(e.heaveRearDesign,e.arbRearDesign)}}var qn=e=>e.config.actuation==="decoupled",Jn="a decoupled axle damps in its heave and roll elements, set below";function Ik(e,t,r={}){let n={...t},o=(m,f)=>{let p=n[m];p&&typeof p=="object"&&"value"in p&&(n[m]={...p,value:f})},{front:a,rear:s}=Zn(e,t);a!==void 0&&o("arb_front",a),s!==void 0&&o("arb_rear",s);for(let[m,f,p]of[[t.heaveFrontDesign,e.front,"heave_spring_front"],[t.heaveRearDesign,e.rear,"heave_spring_rear"]]){if(!m||m.design.kind==="none")continue;let d=m.linkage?Pu(f,m.linkage).atDesign:void 0;o(p,Cu(m.design,d))}let i=TE(e,t,r),c=CE(e,i);n.kinFront=c.kinFront,n.kinRear=c.kinRear;let l=DE(e,i);n.steerFront=c.steerFront,Number.isFinite(l.ackermannPct)&&o("ackermann_pct",l.ackermannPct);let u=m=>qn(m)?0:m.measured?.springRate??m.config.springRate;o("spring_front",u(e.front)),o("spring_rear",u(e.rear));for(let[m,f]of[[e.front,"spring_front"],[e.rear,"spring_rear"]])qn(m)&&(n.readouts={...n.readouts,[f]:"a decoupled axle has no corner spring; its heave and roll elements carry the car"});for(let[m,f]of[[e.front,"damper_front"],[e.rear,"damper_rear"]])qn(m)&&(o(f,0),n.readouts={...n.readouts,[f]:Jn});return o("mr_front",l.mrFront),o("mr_rear",l.mrRear),o("wheelbase",l.wheelbase),o("track_front",l.trackFront),o("track_rear",l.trackRear),o("rc_front",l.rcFront),o("rc_rear",l.rcRear),n.surveyedRadiusFront=e.front.config.loadedRadius,n.surveyedRadiusRear=e.rear.config.loadedRadius,n.rcRoad={radiusFront:e.front.config.loadedRadius,radiusRear:e.rear.config.loadedRadius,gainFront:l.rcGainFront,gainRear:l.rcGainRear},n}function CE(e,t){return{kinFront:Ck(e.front),kinRear:Ck(e.rear),steerFront:e.front.measured?void 0:Eu(e.front,t)}}var wk=new WeakMap;function Ck(e){let t=wk.get(e);return t||wk.set(e,t=oa(e)),t}function TE(e,t,r={}){return PE(e,t,r.front,r.rear)}function PE(e,t,r,n){let o=e.front.config.loadedRadius;if(!((ar(r??t.tireModel)??0)>0))return o;let a={...t,surveyedRadiusFront:o,surveyedRadiusRear:e.rear.config.loadedRadius};return Iu(a,r,n).front??o}var Tk=new WeakMap;function Eu(e,t=e.config.loadedRadius){let r=Tk.get(e);r||(r=new Map,Tk.set(e,r));let n=r.get(t);if(n)return n;let o=t===e.config.loadedRadius?void 0:{loadedRadius:t},a=df(e,Vt(e.config),void 0,void 0,void 0,void 0,o);return r.size>=4&&r.clear(),r.set(t,a),a}var Pk=new WeakMap;function LE(e){return Ke(e,{travelMin:-1,travelMax:1,steps:3}).samples[1].metrics.motionRatio??1}var Tu=e=>e.measured?Sk(e.measured):LE(e);function DE(e,t=e.front.config.loadedRadius){let r=()=>e.front.measured?void 0:Eu(e.front,t);return{...EE(e),get steerFront(){return r()},get ackermannPct(){let n=r();return n?ff(n,bt(e.front),e.config.wheelbase):Number.NaN}}}function EE(e){let t=Pk.get(e);if(t)return t;let r=e.front.measured,n=e.rear.measured,a=!r||!n?$r(Tt(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:Tu(e.front),mrRear:Tu(e.rear),rcFront:r?r.rollCentreHeight:a&&a.front.valid?a.front.heightAboveGround:0,rcRear:n?n.rollCentreHeight:a&&a.rear.valid?a.rear.heightAboveGround:0,rcGainFront:r||!a?0:Ra(a.front),rcGainRear:n||!a?0:Ra(a.rear),rcFrontValid:r?!0:!!a?.front.valid,rcRearValid:n?!0:!!a?.rear.valid};return Pk.set(e,s),s}var xt={open:{kind:"open"},spool:{kind:"spool"},clutch:{kind:"clutch",preloadNm:30,rampDriveDeg:40,rampCoastDeg:50,faces:6,muClutch:.1,rFrictionMm:30.4,rRampMm:36},torsen:{kind:"torsen",tbrDrive:3,tbrCoast:3}},Ok=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),ur=(e,t,r,n=1/0)=>typeof e=="number"&&Number.isFinite(e)?Math.min(n,Math.max(r,e)):t;function eo(e){if(Ok(e))switch(e.kind){case"open":case"spool":return{kind:e.kind};case"clutch":{let t=xt.clutch;return{kind:"clutch",preloadNm:ur(e.preloadNm,t.preloadNm,0),rampDriveDeg:ur(e.rampDriveDeg,t.rampDriveDeg,1,90),rampCoastDeg:ur(e.rampCoastDeg,t.rampCoastDeg,1,90),faces:Math.round(ur(e.faces,t.faces,0)),muClutch:ur(e.muClutch,t.muClutch,0,1),rFrictionMm:ur(e.rFrictionMm,t.rFrictionMm,1),rRampMm:ur(e.rRampMm,t.rRampMm,1)}}case"torsen":{let t=xt.torsen,r=ur(e.preloadNm,0,0);return{kind:"torsen",tbrDrive:ur(e.tbrDrive,t.tbrDrive,1),tbrCoast:ur(e.tbrCoast,t.tbrCoast,1),...r>0?{preloadNm:r}:{}}}default:return}}function _u(e){if(!Ok(e))return;let t=eo(e.front),r=eo(e.rear);return t||r?{...t?{front:t}:{},...r?{rear:r}:{}}:void 0}function Mi(e){let t=mn(e),r=n=>n>=2?"independent":n===1?"diff":"none";return{front:r(t.front),rear:r(t.rear)}}function Si(e){if(!e.driveline)return;let t=Mi(e),r=e.r_dyn.value,n=s=>{if(t[s]!=="diff")return;let i=eo(e.driveline?.[s]);if(!(!i||i.kind==="independent"))return{kind:i.kind,drive:ri(i,"drive",r),coast:ri(i,"coast",r),hubs:ri(i,"hubs",r)}},o=n("front"),a=n("rear");return o||a?{...o?{front:o}:{},...a?{rear:a}:{}}:void 0}var IE={kind:{label:"Differential"},preloadNm:{label:"Preload",unit:"N\xB7m"},rampDriveDeg:{label:"Drive ramp",unit:"\xB0"},rampCoastDeg:{label:"Coast ramp",unit:"\xB0"},faces:{label:"Friction faces"},muClutch:{label:"Clutch friction \u03BC"},rFrictionMm:{label:"Friction radius",unit:"mm"},rRampMm:{label:"Ramp radius",unit:"mm"},tbrDrive:{label:"Drive bias ratio",unit:": 1"},tbrCoast:{label:"Coast bias ratio",unit:": 1"}},_k=e=>{let t=e==="front"?"Front":"Rear";return Object.fromEntries(Object.entries(IE).map(([r,n])=>[`${e}.${r}`,{section:t,...n}]))},Nu={..._k("front"),..._k("rear")},Nk=e=>e.motorModel?.kind==="ice"?e.motorPlacement==="front"?"front":"rear":null;function Vk(e,t){let r=Nk(t);if(!(!r||Nk(e)===r||t.driveline?.[r]))return{...t.driveline,[r]:{...xt.clutch}}}function Gt(e,t,r,n){return e>0?!(r>0)||!Number.isFinite(r)?e:Math.max(1,e-t/r):n}function Ou(e,t,r){let n=Math.max(0,Math.min(1,r)),o=Gt(e.freeRadius,e.staticLoad,e.tyreRate,e.surveyed),a=Gt(t.freeRadius,t.staticLoad,t.tyreRate,t.surveyed);return n*o+(1-n)*a}function ka(e,t,r){if(t===void 0||r===void 0||!Number.isFinite(t)||!Number.isFinite(r))return e;let n=r-t;return n===0?e:Math.max(1,e+n)}function Gr(e,t,r,n){if(!t||r===void 0||n===void 0||!Number.isFinite(r)||!Number.isFinite(n))return e;let o=n-r;return o===0?e:e+t*o}function Ai(e,t){if(!e)return NE(t);let r=t-cn(e,0).camber;return r?{...e,camber:e.camber.map(n=>n+r)}:e}function _E(e){return{kinFront:Ai(e.kinFront,q(e,"camber_front_deg")),kinRear:Ai(e.kinRear,q(e,"camber_rear_deg"))}}function NE(e){let t=[-40,0,40];return{travel:t,motionRatio:t.map(()=>1),camber:t.map(()=>e),toe:t.map(()=>0),damperLen:t.map(()=>0)}}var Bk=9.81,$k=e=>e>1?e/100:e;function Ma(e,t,r){let n=t??e.tireModel??Gs(),o=r??e.tireModelRear??n,a={grip:q(e,"grip_scale"),stiffness:q(e,"stiffness_scale")},s=Kl(n,a);return{front:s,rear:o===n?s:Kl(o,a)}}function mr(e,t,r){let n=Ma(e,t,r),o=Pe(n.front);return ut(n.rear===n.front?o:Dl(o,Pe(n.rear)))}function gb(e,t,r){let n=$k(e.front_mass_diss.value),o=Ma(e,t,r),a=Pe(o.front),s=o.rear===o.front?a:Pe(o.rear),i=t??e.tireModel,c=r??e.tireModelRear??i,l=e.m.value*Bk*n/2,u=e.m.value*Bk*(1-n)/2,m=(i?a.verticalStiffness():0)||q(e,"tire_vertical_rate"),f=(c?s.verticalStiffness():0)||q(e,"tire_vertical_rate"),p=ar(i)??0,d=ar(c)??0,h=e.surveyedRadiusFront&&e.surveyedRadiusRear?Ou({freeRadius:p,staticLoad:l,tyreRate:m,surveyed:e.surveyedRadiusFront},{freeRadius:d,staticLoad:u,tyreRate:f,surveyed:e.surveyedRadiusRear},n):void 0,b=e.surveyedRadiusFront?Gt(p,l,m,e.surveyedRadiusFront):void 0,g=e.surveyedRadiusRear?Gt(d,u,f,e.surveyedRadiusRear):void 0;return{ev:a,evR:s,Wf:l,Wr:u,tireRate:m,tireRateRear:f,tyreFreeRadius:p,tyreFreeRadiusRear:d,cgStandingRadius:h,standingFront:b,standingRear:g}}function Iu(e,t,r){let n=gb(e,t,r);return{front:n.standingFront,rear:n.standingRear}}function Gk(e,t,r){return gb(e,t,r).cgStandingRadius}function dt(e,t,r){let n=$k(e.front_mass_diss.value),o=q(e,"mr_front")||1,a=q(e,"mr_rear")||1,{ev:s,evR:i,Wf:c,Wr:l,tireRate:u,tireRateRear:m,tyreFreeRadius:f,tyreFreeRadiusRear:p,cgStandingRadius:d,standingFront:h,standingRear:b}=gb(e,t,r),g=ei(e),y=Si(e),R=Qn(e.damperModel,e.damperSetup,o,a,e.damperModelRear??e.damperModel),k=e.readouts?.damper_front===Jn,v=e.readouts?.damper_rear===Jn,x={rho:e.rho.value,area:e.A.value,cl:e.c_l.value,cw:e.c_w.value,copLongFront:1-Math.max(0,Math.min(1,q(e,"cop_long"))),copHeight:q(e,"cop_height"),...e.aeroModel?{model:e.aeroModel}:{},rideHeightFront:q(e,"ride_height_front"),rideHeightRear:q(e,"ride_height_rear")};return{massTotal:e.m.value,frontMassFrac:n,steeringSystem:e.steeringSystem,tv:yu(e),cgHeight:ka(q(e,"cg_height"),e.cgReference?.standingRadius,d),...d!==void 0?{cgStandingRadius:d}:{},wheelbase:q(e,"wheelbase"),trackFront:q(e,"track_front"),trackRear:q(e,"track_rear"),wheelRateFront:q(e,"spring_front")*o*o,wheelRateRear:q(e,"spring_rear")*a*a,tireRate:u,...m!==u?{tireRateRear:m}:{},tireDamping:q(e,"tire_vertical_damping"),arbFront:q(e,"arb_front"),arbRear:q(e,"arb_rear"),brakeBalanceFront:g.balanceFront,brakes:g,...y?{driveline:y}:{},heaveSpringFront:q(e,"heave_spring_front"),heaveSpringRear:q(e,"heave_spring_rear"),unsprungPerCorner:q(e,"unsprung_mass"),unsprungCgHeight:OE(e,{Wf:c,Wr:l,tireRate:u,tireRateRear:m,tyreFreeRadius:f,tyreFreeRadiusRear:p,standingFront:h,standingRear:b}),tyreFreeRadius:f,...p!==f?{tyreFreeRadiusRear:p}:{},rcHeightFront:Gr(q(e,"rc_front"),e.rcRoad?.gainFront,e.rcRoad?.radiusFront,h),rcHeightRear:Gr(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,..._E(e)}}function OE(e,t){let r=(a,s,i,c)=>a??(s>0?Gt(s,i,c,s):void 0),n=r(t.standingFront,t.tyreFreeRadius,t.Wf,t.tireRate),o=r(t.standingRear,t.tyreFreeRadiusRear,t.Wr,t.tireRateRear);return n!==void 0&&o!==void 0?.5*(n+o):n??o??e.r_dyn.value*1e3}var Vu={capacity:"the battery model\u2019s pack charge \u2014 cells in parallel \xD7 cell capacity",ocv:"the battery model\u2019s pack voltage at full charge"};function Kk(e,t=e.batteryModel){if(!t)return e;let r=Rr(t),n=(o,a)=>({...o,value:a});return{...e,capacity:n(e.capacity,r.capacityAh),ocv:n(e.ocv,r.voltageAtFull)}}var zk={damper_front:`the damper part sets it: its front curve at ${bn} mm/s`,damper_rear:`the damper part sets it (the rear's own, where the car names one): its rear curve at ${bn} mm/s`};function Bu(e){let t=!!(e.damperModelId||e.damperModel),r=t||!!(e.damperModelIdRear||e.damperModelRear);return{...t?{damper_front:zk.damper_front}:{},...r?{damper_rear:zk.damper_rear}:{}}}function Yk(e,t=e.damperModel,r=e.damperModelRear??t){if(!t&&!r)return e;let n=q(e,"mr_front")||1,o=q(e,"mr_rear")||1,a=Qn(t,e.damperSetup,n,o,r);if(!a)return e;let s=(c,l,u)=>({...c??{label:l,unit:"N\xB7s/mm"},value:u}),i={...e};return a.front&&e.readouts?.damper_front!==Jn&&(i.damper_front=s(e.damper_front,"damper front",a.front.rate/(n*n))),a.rear&&e.readouts?.damper_rear!==Jn&&(i.damper_rear=s(e.damper_rear,"damper rear",a.rear.rate/(o*o))),i}var Wk={how:"scripts/paramTiers.ts: each row \xB120 % (switches flipped, springs on the suspension), first car of every gallery template, largest change to any event time, % of it",templates:["fs-ev-comparison","fs-ev-single","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor","formula-1","touring-car","street-car","cup-car","stock-car","hill-climb","suspension","direct-coilover","pushrod","pullrod","third-spring","mcpherson-strut","tyre-study"],rows:{endurance_reserve:{group:"Powertrain",score:"infinite",byTemplate:{"fs-ev-comparison":"infinite","fs-ev-single":"infinite","fs-combustion":null,"fs-ev-awd":0,"fs-ev-rwd-hubs":"infinite","fs-ev-one-motor":"infinite","formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:0,"direct-coilover":null,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":null,"tyre-study":"infinite"}},gear_ratio:{group:"Powertrain",score:11.9893,byTemplate:{"fs-ev-comparison":11.9893,"fs-ev-single":11.9893,"fs-combustion":5.6255,"fs-ev-awd":5.8819,"fs-ev-rwd-hubs":11.5358,"fs-ev-one-motor":7.2758,"formula-1":.2473,"touring-car":.2195,"street-car":.0998,"cup-car":.2431,"stock-car":.0645,"hill-climb":3.1703,suspension:1.8984,"direct-coilover":.2195,pushrod:1.9001,pullrod:1.9126,"third-spring":1.9001,"mcpherson-strut":.111,"tyre-study":11.9893}},driven_wheels:{group:"Powertrain",score:11.9893,byTemplate:{"fs-ev-comparison":11.9893,"fs-ev-single":11.9893,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:1.9216,"direct-coilover":0,pushrod:1.9171,pullrod:1.919,"third-spring":1.9171,"mcpherson-strut":0,"tyre-study":11.9893}},power_scale:{group:"Powertrain",score:11.9893,byTemplate:{"fs-ev-comparison":11.9893,"fs-ev-single":11.9893,"fs-combustion":10.2883,"fs-ev-awd":4.2843,"fs-ev-rwd-hubs":11.6138,"fs-ev-one-motor":7.2758,"formula-1":2.6682,"touring-car":2.5337,"street-car":1.938,"cup-car":2.6155,"stock-car":1.2193,"hill-climb":1.869,suspension:1.9216,"direct-coilover":2.5337,pushrod:1.9171,pullrod:1.919,"third-spring":1.9171,"mcpherson-strut":1.9778,"tyre-study":11.9893}},grip_scale:{group:"Tyres",score:11.4886,byTemplate:{"fs-ev-comparison":10.9135,"fs-ev-single":10.9135,"fs-combustion":11.4886,"fs-ev-awd":11.3513,"fs-ev-rwd-hubs":11.3513,"fs-ev-one-motor":11.3905,"formula-1":10.9225,"touring-car":7.4484,"street-car":7.2578,"cup-car":7.1946,"stock-car":10.4642,"hill-climb":9.5384,suspension:8.3679,"direct-coilover":7.4484,pushrod:8.3929,pullrod:8.3807,"third-spring":8.3929,"mcpherson-strut":7.35,"tyre-study":10.9135}},front_mass_diss:{group:"Mass & chassis",score:10.3816,byTemplate:{"fs-ev-comparison":1.1854,"fs-ev-single":1.1854,"fs-combustion":1.5398,"fs-ev-awd":1.9682,"fs-ev-rwd-hubs":1.9682,"fs-ev-one-motor":4.5048,"formula-1":5.2182,"touring-car":1.241,"street-car":3.5067,"cup-car":.7277,"stock-car":2.2367,"hill-climb":10.3816,suspension:.5046,"direct-coilover":1.241,pushrod:.4796,pullrod:.4587,"third-spring":.4796,"mcpherson-strut":3.4131,"tyre-study":1.1854}},m:{group:"Mass & chassis",score:9.7815,byTemplate:{"fs-ev-comparison":9.7815,"fs-ev-single":9.7815,"fs-combustion":7.2245,"fs-ev-awd":5.6765,"fs-ev-rwd-hubs":9.2239,"fs-ev-one-motor":7.0296,"formula-1":5.3736,"touring-car":3.7044,"street-car":1.9146,"cup-car":2.6724,"stock-car":3.7623,"hill-climb":5.4157,suspension:3.8549,"direct-coilover":3.7044,pushrod:3.8507,pullrod:3.8527,"third-spring":3.8507,"mcpherson-strut":1.9399,"tyre-study":9.7815}},cop_long:{group:"Aerodynamics",score:6.6543,byTemplate:{"fs-ev-comparison":1.032,"fs-ev-single":1.032,"fs-combustion":1.0669,"fs-ev-awd":1.0452,"fs-ev-rwd-hubs":1.0452,"fs-ev-one-motor":1.0521,"formula-1":5.9878,"touring-car":.1327,"street-car":.0018,"cup-car":.2696,"stock-car":.6469,"hill-climb":6.6543,suspension:.3644,"direct-coilover":.1327,pushrod:.3575,pullrod:.355,"third-spring":.3575,"mcpherson-strut":.0072,"tyre-study":1.032}},front_aero_diss:{group:"Aerodynamics",score:5.2168,byTemplate:{"fs-ev-comparison":.9064,"fs-ev-single":.9064,"fs-combustion":.8657,"fs-ev-awd":.8967,"fs-ev-rwd-hubs":.8967,"fs-ev-one-motor":.8574,"formula-1":4.2912,"touring-car":.0708,"street-car":.0018,"cup-car":.2207,"stock-car":.5291,"hill-climb":5.2168,suspension:.2835,"direct-coilover":.0708,pushrod:.2831,pullrod:.2823,"third-spring":.2831,"mcpherson-strut":.0072,"tyre-study":.9064}},power_limit_kw:{group:"Powertrain",score:4.5916,byTemplate:{"fs-ev-comparison":.4828,"fs-ev-single":.4828,"fs-combustion":null,"fs-ev-awd":4.5916,"fs-ev-rwd-hubs":.5453,"fs-ev-one-motor":3.6198,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:.0626,"direct-coilover":null,pushrod:.0625,pullrod:.0626,"third-spring":.0625,"mcpherson-strut":null,"tyre-study":.4828}},soc:{group:"Powertrain",score:3.5618,byTemplate:{"fs-ev-comparison":3.2245,"fs-ev-single":3.2245,"fs-combustion":0,"fs-ev-awd":1.6179,"fs-ev-rwd-hubs":3.3095,"fs-ev-one-motor":3.5618,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":3.2245}},effi_pgb:{group:"Powertrain",score:3.5269,byTemplate:{"fs-ev-comparison":3.5269,"fs-ev-single":3.5269,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:.0626,"direct-coilover":0,pushrod:.0625,pullrod:.0626,"third-spring":.0625,"mcpherson-strut":0,"tyre-study":3.5269}},c_l:{group:"Aerodynamics",score:3.4342,byTemplate:{"fs-ev-comparison":.9751,"fs-ev-single":.9751,"fs-combustion":.9539,"fs-ev-awd":1.0777,"fs-ev-rwd-hubs":.9886,"fs-ev-one-motor":1.0797,"formula-1":3.4342,"touring-car":.8979,"street-car":.0715,"cup-car":.2158,"stock-car":.5467,"hill-climb":1.2705,suspension:.9751,"direct-coilover":.8979,pushrod:.9734,pullrod:.9708,"third-spring":.9734,"mcpherson-strut":.0704,"tyre-study":.9751}},ocv:{group:"Powertrain",score:3.3244,byTemplate:{"fs-ev-comparison":3.0446,"fs-ev-single":3.0446,"fs-combustion":0,"fs-ev-awd":1.4595,"fs-ev-rwd-hubs":3.1854,"fs-ev-one-motor":3.3244,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":3.0446}},capacity:{group:"Powertrain",score:3.3244,byTemplate:{"fs-ev-comparison":3.0446,"fs-ev-single":3.0446,"fs-combustion":0,"fs-ev-awd":1.4595,"fs-ev-rwd-hubs":3.1854,"fs-ev-one-motor":3.3244,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":3.0446}},A:{group:"Aerodynamics",score:2.3707,byTemplate:{"fs-ev-comparison":.802,"fs-ev-single":.802,"fs-combustion":.7928,"fs-ev-awd":.9333,"fs-ev-rwd-hubs":.7926,"fs-ev-one-motor":.961,"formula-1":2.3707,"touring-car":.6374,"street-car":.4904,"cup-car":.2428,"stock-car":.1932,"hill-climb":1.1486,suspension:.802,"direct-coilover":.6374,pushrod:.7991,pullrod:.7982,"third-spring":.7991,"mcpherson-strut":.4873,"tyre-study":.802}},rho:{group:"Aerodynamics",score:2.3707,byTemplate:{"fs-ev-comparison":.802,"fs-ev-single":.802,"fs-combustion":.7928,"fs-ev-awd":.9333,"fs-ev-rwd-hubs":.7926,"fs-ev-one-motor":.961,"formula-1":2.3707,"touring-car":.6374,"street-car":.4904,"cup-car":.2428,"stock-car":.1932,"hill-climb":0,suspension:.802,"direct-coilover":.6374,pushrod:.7991,pullrod:.7982,"third-spring":.7991,"mcpherson-strut":.4873,"tyre-study":.802}},cg_height:{group:"Mass & chassis",score:2.2005,byTemplate:{"fs-ev-comparison":1.8282,"fs-ev-single":1.8282,"fs-combustion":1.6978,"fs-ev-awd":2.2005,"fs-ev-rwd-hubs":1.8919,"fs-ev-one-motor":1.9269,"formula-1":.6248,"touring-car":1.2858,"street-car":1.4681,"cup-car":.992,"stock-car":1.2052,"hill-climb":.6037,suspension:1.8282,"direct-coilover":1.2858,pushrod:1.8142,pullrod:1.8229,"third-spring":1.8142,"mcpherson-strut":1.7176,"tyre-study":1.8282}},l_to_d_ratio:{group:"Aerodynamics",score:1.4351,byTemplate:{"fs-ev-comparison":.7905,"fs-ev-single":.7905,"fs-combustion":.6962,"fs-ev-awd":.5843,"fs-ev-rwd-hubs":.8444,"fs-ev-one-motor":.9611,"formula-1":1.4351,"touring-car":.3671,"street-car":.528,"cup-car":.5631,"stock-car":.4634,"hill-climb":.2349,suspension:.2456,"direct-coilover":.3671,pushrod:.2491,pullrod:.2456,"third-spring":.2491,"mcpherson-strut":.5265,"tyre-study":.7905}},tv_enabled:{group:"Torque vectoring",score:1.2381,byTemplate:{"fs-ev-comparison":1.2381,"fs-ev-single":1.2381,"fs-combustion":0,"fs-ev-awd":1.2293,"fs-ev-rwd-hubs":1.2293,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":.1209,"cup-car":.1617,"stock-car":0,"hill-climb":9e-4,suspension:.3086,"direct-coilover":0,pushrod:.2933,pullrod:.3089,"third-spring":.2933,"mcpherson-strut":.1326,"tyre-study":1.2381}},c_w:{group:"Aerodynamics",score:1.1499,byTemplate:{"fs-ev-comparison":.6319,"fs-ev-single":.6319,"fs-combustion":.5577,"fs-ev-awd":.462,"fs-ev-rwd-hubs":.6559,"fs-ev-one-motor":.7504,"formula-1":1.1499,"touring-car":.2914,"street-car":.4211,"cup-car":.4486,"stock-car":.3694,"hill-climb":.1625,suspension:.1945,"direct-coilover":.2914,pushrod:.1979,pullrod:.1948,"third-spring":.1979,"mcpherson-strut":.4196,"tyre-study":.6319}},brake_balance:{group:"Brakes",score:1.0132,byTemplate:{"fs-ev-comparison":.8303,"fs-ev-single":.8303,"fs-combustion":.6932,"fs-ev-awd":.9772,"fs-ev-rwd-hubs":.8148,"fs-ev-one-motor":1.0132,"formula-1":.97,"touring-car":.9585,"street-car":.7184,"cup-car":.1468,"stock-car":.0764,"hill-climb":.9096,suspension:.8303,"direct-coilover":.9585,pushrod:.8578,pullrod:.8454,"third-spring":.8578,"mcpherson-strut":.7099,"tyre-study":.8303}},stiffness_scale:{group:"Tyres",score:.871,byTemplate:{"fs-ev-comparison":.5088,"fs-ev-single":.5088,"fs-combustion":.4874,"fs-ev-awd":.3745,"fs-ev-rwd-hubs":.4753,"fs-ev-one-motor":.5706,"formula-1":.5776,"touring-car":.4346,"street-car":.1077,"cup-car":.4012,"stock-car":.1613,"hill-climb":.871,suspension:.5088,"direct-coilover":.4346,pushrod:.5253,pullrod:.5172,"third-spring":.5253,"mcpherson-strut":.1518,"tyre-study":.5088}},cop_height:{group:"Aerodynamics",score:.2837,byTemplate:{"fs-ev-comparison":.155,"fs-ev-single":.155,"fs-combustion":.1546,"fs-ev-awd":.1557,"fs-ev-rwd-hubs":.1557,"fs-ev-one-motor":.1542,"formula-1":.1173,"touring-car":.0072,"street-car":.0023,"cup-car":.0745,"stock-car":.1568,"hill-climb":.2837,suspension:.0421,"direct-coilover":.0072,pushrod:.0437,pullrod:.04,"third-spring":.0437,"mcpherson-strut":.0076,"tyre-study":.155}},spring_rear:{group:"Suspension",score:.2822,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":.0355,"touring-car":.1169,"street-car":.2242,"cup-car":.0902,"stock-car":.2822,"hill-climb":.1929,suspension:0,"direct-coilover":.1169,pushrod:.1142,pullrod:.2148,"third-spring":.1142,"mcpherson-strut":.1786,"tyre-study":0}},spring_front:{group:"Suspension",score:.2388,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":.0189,"touring-car":.0958,"street-car":.2388,"cup-car":.1462,"stock-car":.1719,"hill-climb":.1873,suspension:0,"direct-coilover":.0958,pushrod:.1257,pullrod:.0612,"third-spring":.1257,"mcpherson-strut":.1911,"tyre-study":0}},arb_front:{group:"Suspension",score:.1792,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":.0235,"touring-car":.0589,"street-car":.1792,"cup-car":.0215,"stock-car":.0926,"hill-climb":.1095,suspension:null,"direct-coilover":.0589,pushrod:.0455,pullrod:.049,"third-spring":.0455,"mcpherson-strut":.1435,"tyre-study":null}},fr_0:{group:"Tyres",score:.158,byTemplate:{"fs-ev-comparison":.158,"fs-ev-single":.158,"fs-combustion":.1097,"fs-ev-awd":.0708,"fs-ev-rwd-hubs":.1442,"fs-ev-one-motor":.1168,"formula-1":.07,"touring-car":.0492,"street-car":.1006,"cup-car":.065,"stock-car":.0262,"hill-climb":.0334,suspension:.0217,"direct-coilover":.0492,pushrod:.0229,pullrod:.0223,"third-spring":.0229,"mcpherson-strut":.0989,"tyre-study":.158}},arb_rear:{group:"Suspension",score:.1047,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":.0224,"touring-car":.0365,"street-car":.0832,"cup-car":.1047,"stock-car":.0436,"hill-climb":.0734,suspension:null,"direct-coilover":.0365,pushrod:.0411,pullrod:.0332,"third-spring":.0411,"mcpherson-strut":.0643,"tyre-study":null}},unsprung_mass:{group:"Mass & chassis",score:.102,byTemplate:{"fs-ev-comparison":.0477,"fs-ev-single":.0477,"fs-combustion":.0512,"fs-ev-awd":.0545,"fs-ev-rwd-hubs":.0514,"fs-ev-one-motor":.0799,"formula-1":.0313,"touring-car":.0471,"street-car":.102,"cup-car":.0315,"stock-car":.042,"hill-climb":.0278,suspension:.0477,"direct-coilover":.0471,pushrod:.0452,pullrod:.0468,"third-spring":.0452,"mcpherson-strut":.0876,"tyre-study":.0477}},camber_front_deg:{group:"Steering & alignment",score:.0576,byTemplate:{"fs-ev-comparison":.0065,"fs-ev-single":.0065,"fs-combustion":.008,"fs-ev-awd":.0075,"fs-ev-rwd-hubs":.0075,"fs-ev-one-motor":.0098,"formula-1":.0358,"touring-car":.0272,"street-car":.0025,"cup-car":.0191,"stock-car":.0576,"hill-climb":.0389,suspension:.0019,"direct-coilover":.0272,pushrod:.0017,pullrod:.0016,"third-spring":.0017,"mcpherson-strut":.002,"tyre-study":.0065}},camber_rear_deg:{group:"Steering & alignment",score:.0262,byTemplate:{"fs-ev-comparison":.0081,"fs-ev-single":.0081,"fs-combustion":.0085,"fs-ev-awd":.0054,"fs-ev-rwd-hubs":.0096,"fs-ev-one-motor":.0097,"formula-1":.0028,"touring-car":.0106,"street-car":8e-4,"cup-car":5e-4,"stock-car":.0035,"hill-climb":.0262,suspension:.0081,"direct-coilover":.0106,pushrod:.0082,pullrod:.0083,"third-spring":.0082,"mcpherson-strut":3e-4,"tyre-study":.0081}},I_yaw:{group:"Mass & chassis",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},I_roll:{group:"Mass & chassis",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},I_pitch:{group:"Mass & chassis",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},ride_height_front:{group:"Aerodynamics",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},ride_height_rear:{group:"Aerodynamics",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tire_vertical_rate:{group:"Tyres",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tire_vertical_damping:{group:"Tyres",score:0,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":0,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},r_dyn:{group:"Tyres",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},damper_front:{group:"Suspension",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},damper_rear:{group:"Suspension",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_kp:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_ff_low:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_ff_high:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_v_low:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},tv_v_high:{group:"Torque vectoring",score:0,byTemplate:{"fs-ev-comparison":0,"fs-ev-single":0,"fs-combustion":0,"fs-ev-awd":0,"fs-ev-rwd-hubs":0,"fs-ev-one-motor":0,"formula-1":0,"touring-car":0,"street-car":0,"cup-car":0,"stock-car":0,"hill-climb":0,suspension:0,"direct-coilover":0,pushrod:0,pullrod:0,"third-spring":0,"mcpherson-strut":0,"tyre-study":0}},wheelbase:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},track_front:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},track_rear:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},rc_front:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},rc_rear:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},I_wheel:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},I_rotor:{group:"Mass & chassis",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},v_limit_endurance:{group:"Powertrain",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},mr_front:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},mr_rear:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},heave_spring_front:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},heave_spring_rear:{group:"Suspension",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},toe_front_deg:{group:"Steering & alignment",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},toe_rear_deg:{group:"Steering & alignment",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}},ackermann_pct:{group:"Steering & alignment",score:null,byTemplate:{"fs-ev-comparison":null,"fs-ev-single":null,"fs-combustion":null,"fs-ev-awd":null,"fs-ev-rwd-hubs":null,"fs-ev-one-motor":null,"formula-1":null,"touring-car":null,"street-car":null,"cup-car":null,"stock-car":null,"hill-climb":null,suspension:null,"direct-coilover":null,pushrod:null,pullrod:null,"third-spring":null,"mcpherson-strut":null,"tyre-study":null}}}};function Kr(e){return!!e&&typeof e=="object"&&"value"in e&&"label"in e}var GE={Batteriekapazit\u00E4t:"pack capacity",Rollwiderstandsbeiwert:"rolling-resistance coefficient"},Uk=e=>GE[e]??e;function $u(e){let t=[];for(let r of Object.keys(e)){if(r==="motor"||r==="name")continue;let n=e[r];Kr(n)&&t.push({key:r,label:Uk(n.label),value:n.value,unit:n.unit})}return t}var KE=[{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"]}],HE=.5,jk=e=>e==="infinite"?1/0:typeof e=="number"?e:null,zE=e=>/front/.test(e)?e.replace("front","rear"):/rear/.test(e)?e.replace("rear","front"):null,YX=(()=>{let e=Wk.rows,t=o=>{let a=zE(o),s=jk(e[o]?.score),i=a&&e[a]?jk(e[a].score):null;return s==null?i:i==null?s:Math.max(s,i)},r=new Set,n=new Map;for(let[o,a]of Object.entries(e)){let s=t(o);s!=null&&(s>=HE&&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 yb={wheelbase:"set by the axle positions in Kinematics",track_front:"twice the front wheel-centre Y",track_rear:"twice the rear wheel-centre Y",rc_front:"solved from the front wishbones, on the fitted tyre",rc_rear:"solved from the rear wishbones, on the fitted tyre",mr_front:"damper travel per mm of front wheel travel, from the linkage",mr_rear:"damper travel per mm of rear wheel travel, from the linkage",spring_front:"the front corner spring rate, stored on the suspension the car runs",spring_rear:"the rear corner spring rate, stored on the suspension the car runs",ackermann_pct:"solved from the rack and tie rods, read near centre"};function Xk(e){let t=new Map;for(let a of $u(e))t.set(a.key,a);let r=new Set,n=[];for(let a of KE){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=$u(e).filter(a=>!r.has(a.key));return o.length&&n.push({title:"Other",rows:o}),n}var xb={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"},Rb={ride_height_front:"reaches nothing until an aero model is attached at the head of the Aerodynamics group",ride_height_rear:"reaches nothing until an aero model is attached at the head of the Aerodynamics group"},Qk=e=>!!(e.aeroModelId||e.aeroModel);function YE(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 WE=e=>!!(e.batteryModelId||e.batteryModel);function jE(e,t){let r={};return t.geometry&&Object.assign(r,yb,YE(e)),Qk(e)&&Object.assign(r,xb),WE(e)&&Object.assign(r,Vu),Object.assign(r,Bu(e)),e.readouts&&Object.assign(r,e.readouts),r}function qk(e,t){let r=jE(e,t);return Qk(e)||Object.assign(r,Rb),r}function vb(e){let t=e.cop_long;return Kr(t)?1-t.value:.5}function UE(e,t){let r=e.front_aero_diss,n=e.cop_long;!Kr(r)||!Kr(n)||(t===r.label?n.value=1-r.value:t===n.label&&(r.value=1-n.value))}function XE(e,t){UE(e,t);let r=e.c_l,n=e.c_w,o=e.l_to_d_ratio;!Kr(r)||!Kr(n)||(t===r.label||t===n.label?Kr(o)&&n.value!==0&&(o.value=r.value/n.value):Kr(o)&&t===o.label&&o.value!==0&&(n.value=r.value/o.value))}function Gu(e,t,r){let n=!1;for(let o of Object.keys(e)){if(o==="motor"||o==="name")continue;let a=e[o];if(Kr(a)&&Uk(a.label)===t){a.value=r,n=!0;break}}return n&&XE(e,t),n}function Ku(e,t,r=0,n,o){let a=()=>({cl:e.c_l.value,cw:e.c_w.value,frontShare:vb(e),A:e.A.value,platform:null});if(!e.aeroModel)return a();let s=kr(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:vb(e),A:s.area,platform:s}}var Zk=e=>typeof e=="object"&&e!==null&&typeof e.value=="number"&&typeof e.label=="string";function Jk(e,t=e.aeroModel){if(!t)return e;let r=Zr(t,{wheelbase:q(e,"wheelbase")}).at(q(e,"ride_height_front"),q(e,"ride_height_rear")),{cl:n,balanceFront:o}=fd(r),a=(i,c,l)=>({...i??c,value:l}),s={...e,A:a(e.A,e.A,t.area),c_l:a(e.c_l,e.c_l,n),c_w:a(e.c_w,e.c_w,r.cd),front_aero_diss:a(e.front_aero_diss,e.front_aero_diss,o),cop_long:a(Zk(e.cop_long)?e.cop_long:void 0,cr.cop_long,1-o)};return Zk(e.l_to_d_ratio)&&(s.l_to_d_ratio={...e.l_to_d_ratio,value:r.cd!==0?n/r.cd:0}),s}var Fi={dsTarget:.25,accelStep:.25,vTol:.002,scanSteps:24,seamIters:8,fitSpacing:1},QE=32;function eM(e,t,r){let n=Math.round(e/t);return Math.max(1,Math.min(Number.isFinite(n)?n:1,Math.floor(r/QE)||1))}function st(e){let t=Fi,r=(n,o,a)=>{let s=Number(n);return Number.isFinite(s)&&s>=a?s:o};return{dsTarget:r(e?.dsTarget,t.dsTarget,.001),accelStep:r(e?.accelStep,t.accelStep,.001),vTol:r(e?.vTol,t.vTol,1e-6),scanSteps:Math.max(4,Math.round(r(e?.scanSteps,t.scanSteps,4))),seamIters:Math.max(1,Math.round(r(e?.seamIters,t.seamIters,1))),fitSpacing:r(e?.fitSpacing,t.fitSpacing,0)}}var tM=Math.PI/180,Hu=.02,rM=new WeakMap;function wi(e){let t=rM.get(e);if(t!==void 0)return t;let r=e.npts,n=new Array(r),o=new Array(r),a=!1;for(let i=0;i<r;i++){let c=(e.gradient?.[i]??0)*tM,l=(e.bank?.[i]??0)*tM,u=e.verticalCurvature?.[i]??0;n[i]=c===0&&l===0?1:Math.cos(c)*Math.cos(l),o[i]=(u-e.curvature[i]*Math.sin(l))/9.81,(n[i]!==1||o[i]!==0)&&(a=!0)}let s=a?{n0:n,k:o}:null;return rM.set(e,s),s}function zu(e,t,r){return e.n0[t]+e.k[t]*r*r}function nM(e,t){return e.k[t]<0?Math.sqrt(Math.max(0,e.n0[t])/-e.k[t]):1/0}function oM(e,t){if(!e)return null;let r=1/0,n=-1/0;for(let o=0;o<e.n0.length;o++){let a=zu(e,o,t[o]??0);a<r&&(r=a),a>n&&(n=a)}return r>=1-Hu&&n<=1+Hu?null:{lo:r,hi:n}}var Sa=[.1,.25,.5,.75,1,1.25,1.5,2,2.5];function aM(e){let t=e.lo>=1-Hu?1:1-1.25*(1-e.lo)-.05,r=e.hi<=1+Hu?1:1+1.25*(e.hi-1)+.05,n=[...Sa].reverse().find(a=>a<=t)??Sa[0],o=Sa.find(a=>a>=r)??Sa[Sa.length-1];return Sa.filter(a=>a>=n&&a<=o)}function kb(e,t,r){return r<1?Math.max(e,t):Math.min(e,t)}function sM(e,t,r,n){let o=e.n0.length;return a=>{let s=n?n(a):r,i=a%o;if(e.n0[i]===1&&e.k[i]===0)return s;let c=e.n0[i],l=e.k[i],u=m=>c+l*m*m;return n?{vMax:s.vMax,axAccel:(m,f,p=1,d=1)=>s.axAccel(m,f,p,d)+t.axAccel(u(m),m,f,p,d)-r.axAccel(m,f,p,d),axDecel:(m,f,p=1,d=1)=>{let h=b=>s.axDecel(m,f,p,b)+t.axDecel(u(m),m,f,p,b)-r.axDecel(m,f,p,b);return d===1?h(1):kb(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 Yu(e,t,r,n,o){let a=e.length,s=r?a:a-1,i=F=>r?(F+1)%a:F+1,{brakeAhead:c,apexAhead:l}=qE(e,t,r),u=new Array(a),m=new Array(a),f=new Array(a),p=new Array(a).fill(0),d=0,h=0,b=0,g=Math.max(0,Math.min(1,n.kept)),y=g>=1?0:n.up,R=g>=1?0:n.down,k=4*y*(1-g),v=F=>{let{v:w,gear:C,tau:T,target:S}=F;d=0,h=0,b=0;for(let A=0;A<s;A++){let P=i(A),L=e[P];for(let V=0;T<=0&&V<n.count;V++){let N=C;if(w<L-1e-9?n.best(w)>C&&(n.rpm(w,C)>=n.limitRpm||c[A]>=w*k)?N=C+1:C>0&&w<n.vIdle(C)&&(N=C-1):L<w-1e-9&&C>0&&n.best(l[A])<C&&n.rpm(w,C-1)<=n.limitRpm&&(N=C-1),N===C)break;S=N,N>C?d++:h++,T=N>C?y:R,T<=0&&(C=S)}u[A]=w,m[A]=C+1,f[A]=n.rpm(w,C);let D=T>0;p[A]=D?1:0;let E=L;if(!D)w<L&&(E=Math.min(L,Math.sqrt(Math.max(0,w*w+2*o(A,w,n.share(w,C))*t[A]))));else if(w<L){let V=o(A,w,g>0?g*n.share(w,C):0),N=Math.min(L,Math.sqrt(Math.max(0,w*w+2*V*t[A]))),z=w+N>0?2*t[A]/(w+N):1/0;if(z<=T)E=N,b+=z,T-=z;else{let I=Math.min(L,Math.max(0,w+V*T)),_=Math.max(0,t[A]-(w+I)*.5*T);b+=T,T=0,C=S,E=Math.min(L,Math.sqrt(Math.max(0,I*I+2*o(A,I,n.share(I,C))*_)))}}else{let V=w+E>0?2*t[A]/(w+E):0;b+=Math.min(V,T),T-=V,T<=0&&(C=S)}w=E}return{v:w,gear:C,tau:T,target:S}},x=n.best(e[0]),M={v:e[0],gear:x,tau:0,target:x};if(r)for(let F=0;F<6;F++){let w=v(M),C=Math.abs(w.v-M.v)<=1e-9&&w.gear===M.gear&&w.target===M.target&&Math.abs(w.tau-M.tau)<=1e-12;if(M=w,C)break}else{let F=v(M);u[a-1]=F.v,m[a-1]=F.gear+1,f[a-1]=n.rpm(F.v,F.gear),p[a-1]=F.tau>0?1:0}return{v:u,gear:m,rpm:f,shifting:p,upshifts:d,downshifts:h,gapTime:b}}function qE(e,t,r){let n=e.length,o=new Array(n).fill(1/0),a=e.slice(),s=1/0,i=e[n-1],c=r?2*n-1:n-2;for(let l=c;l>=0;l--){let u=l%n,m=r?(u+1)%n:u+1,f=e[m]<e[u]-1e-9;s=f?0:s+t[u],i=f?Math.min(i,e[m]):e[u],l<n&&(o[u]=s,a[u]=i)}return{brakeAhead:o,apexAhead:a}}var Mb=.001,Sb=9.81,Ci=(e,t)=>Wu(e?.gradient?.[t]??0);function Wu(e){return e===0?0:-Sb*Math.sin(e*Math.PI/180)}function yn(e,t){let r=new Array(t);for(let n=0;n<t;n++)r[n]=Wu(e?.[n]??0);return r}var gn=(e,t)=>{let r=e?.mu?.[t];return r!=null&&r>0?r:1},to=(e,t)=>e?.bank?.[t]??0;function ZE(e,t,r,n,o,a){let s=e.ay(t,r,gn(o,a)),i=to(o,a);if(!i)return s;let c=i*Math.PI/180,l=n===0?0:-Math.sign(n)*Sb*Math.sin(c);return Math.max(0,(s+l)/Math.cos(c))}function He(e,t){if(!t)return e;let r=t*Math.PI/180;return e*Math.cos(r)+Sb*Math.sin(r)}function Ab(e,t,r,n,o){if(r<=t)return t;if(e(r)<=0)return r;let a=(r-t)/n,s=r,i=t,c=!1;for(let l=1;l<=n;l++){let u=r-l*a;if(e(u)<=0){i=u,s=u+a,c=!0;break}}if(!c)return t;for(;s-i>o;){let l=.5*(i+s);e(l)<=0?i=l:s=l}return i}var ro=(e,t,r)=>t?t(r):e,JE=1e-4;function Aa(e,t,r,n,o,a,s){let i=st(r),c=[];for(let l=0;l<t.length;l++){let u=t[l],m=Math.abs(u),f=ro(e,o,l),p=a!==void 0&&a>0?Math.min(f.vMax,a):f.vMax,d=s?Math.min(p,s(l)):p,h=m<=0?d:Ab(b=>b*b*m-ZE(f,b,0,u,n,l),Mb,d,i.scanSteps,Math.min(i.vTol,JE));c.push({v:h,ax:0,ay:h*h*u})}return c}function eI(e,t,r,n,o,a,s=1,i=0,c=0,l){if(r.v<=t.v)return 0;let u=p=>{let d=He(p*p*n,c),h=(l?e.axDecel(p,Math.abs(d),s,l(p)):e.axDecel(p,Math.abs(d),s))+i;return Math.sqrt(Math.max(0,p*p+2*h*o))},m=r.v;r.v=Ab(p=>u(p)-t.v,Mb,r.v,a.scanSteps,a.vTol),r.ay=r.v*r.v*n;let f=Math.abs(He(r.ay,c));return r.ax=(l?e.axDecel(r.v,f,s,l(r.v)):e.axDecel(r.v,f,s))+i,m-r.v}function tI(e,t,r,n,o,a=1,s=0,i=0,c=1){if(r.v>=t.v)return 0;r.ay=r.v*r.v*n,r.ax=e.axAccel(r.v,Math.abs(He(r.ay,i)),a,c)+s;let l=t.v;return t.v=Math.min(t.v,Math.sqrt(Math.max(0,r.v*r.v+2*r.ax*o))),l-t.v}function iM(e,t,r,n,o,a){let s=st(n),i=r.npts,c=0;for(let l=0;l<s.seamIters;l++){let u=0;c++;for(let m=i-1;m>=0;m--){let f=(m+1)%i;u=Math.max(u,eI(ro(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],s,gn(r,m),Ci(r,m),to(r,m),a?p=>a(m,p):void 0))}if(u<=s.vTol)break}return c}function cM(e,t,r,n,o,a){let s=st(n),i=r.npts,c=0;for(let l=0;l<s.seamIters;l++){let u=0;c++;for(let m=0;m<i;m++){let f=(m+1)%i;u=Math.max(u,tI(ro(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],gn(r,m),Ci(r,m),to(r,m),a?a[m]:1))}if(u<=s.vTol)break}return c}function rI(e,t,r){let n=r.load?wi(t):null;if(!n||!r.load)return{pick:r.envelope};let o=t.npts;return{pick:sM(n,r.load,e,r.envelope),cap:a=>nM(n,a%o),n:(a,s)=>zu(n,a,s)}}function lM(e,t,r,n,o,a,s){return Yu(n,r.ds,o,a,(i,c,l)=>{let u=c*c*r.curvature[i];return ro(e,t,i).axAccel(c,Math.abs(He(u,to(r,i))),gn(r,i),s?l*s[i]:l)+Ci(r,i)})}function uM(e,t){return{gear:e.gear.slice(0,t),engineRpm:e.rpm.slice(0,t),shifting:e.shifting.slice(0,t)}}function mM(e,t,r,n){if(!e.scrub)return{};let o=!1,a=n.map((s,i)=>{let c=ro(e,t,i),l=He(s*s*r.curvature[i],to(r,i)),u=c.scrub?c.scrub(s,Math.abs(l),gn(r,i)):0;return u!==0&&(o=!0),u});return o?{axScrub:a}:{}}function Rt(e,t,r,n={}){let o=st(r),a=t.npts,s=t.closed&&!n.standingStart,{pick:i,cap:c,n:l}=rI(e,t,n),u=n.driveDerate,m=n.brakeFade;if(!s)return nI(e,t,o,n.standingStart===!0,i,u,n.vCeiling,m,c,l,n.shifts);let f=Aa(e,t.curvature,o,t,i,n.vCeiling,c),p=iM(e,f,t,o,i,m),d=cM(e,f,t,o,i,u),h=n.shifts?lM(e,i,t,f.map(k=>k.v),!0,n.shifts,u):void 0;if(h)for(let k=0;k<a;k++)f[k].v=h.v[k];for(let k=0;k<a;k++){let v=f[k];v.ay=v.v*v.v*t.curvature[k];let x=f[(k+1)%a].v;v.ax=(x*x-v.v*v.v)/(2*t.ds[k])}let b=f.map(k=>k.v),g=f.map(k=>k.ax),y=f.map(k=>k.ay),R=0;for(let k=0;k<a;k++){let v=b[k]+b[(k+1)%a];v>0&&(R+=2*t.ds[k]/v)}return{states:f,v:b,ax:g,ay:y,laptime:R,sweeps:{backward:p,forward:d},...l?{loadFactor:b.map((k,v)=>l(v,k))}:{},...mM(e,i,t,b),...h?uM(h,a):{}}}function nI(e,t,r,n,o,a,s,i,c,l,u){let m=t.npts,f=t.closed?m:m-1,p=f+1,d=new Array(p);for(let R=0;R<p;R++)d[R]=t.curvature[R%m];let h=Aa(e,d,r,t,o,s,c);n&&(h[0].v=0);for(let R=f-1;R>=0;R--){let k=h[R],v=h[R+1];if(k.v<=v.v)continue;let x=ro(e,o,R),M=w=>{let C=He(w*w*t.curvature[R],to(t,R)),T=(i?x.axDecel(w,Math.abs(C),gn(t,R),i(R,w)):x.axDecel(w,Math.abs(C),gn(t,R)))+Ci(t,R);return Math.sqrt(Math.max(0,w*w+2*T*t.ds[R]))},F=n&&R===0?k.v:Mb;k.v=Ab(w=>M(w)-v.v,F,k.v,r.scanSteps,r.vTol)}for(let R=0;R<f;R++){let k=h[R],v=h[R+1];k.ay=k.v*k.v*t.curvature[R];let x=He(k.ay,to(t,R));k.ax=ro(e,o,R).axAccel(k.v,Math.abs(x),gn(t,R),a?a[R]:1)+Ci(t,R),v.v=Math.min(v.v,Math.sqrt(Math.max(0,k.v*k.v+2*k.ax*t.ds[R])))}let b=u?lM(e,o,t,h.map(R=>R.v),!1,u,a):void 0;if(b)for(let R=0;R<p;R++)h[R].v=b.v[R];let g=0;for(let R=0;R<f;R++){let k=h[R].v+h[R+1].v;k>0&&(g+=2*t.ds[R]/k)}let y=h.slice(0,m);for(let R=0;R<m;R++){let k=y[R];k.ay=k.v*k.v*t.curvature[R];let v=R<f?h[R+1].v:k.v;k.ax=t.ds[R]>0?(v*v-k.v*k.v)/(2*t.ds[R]):0}return{states:y,v:y.map(R=>R.v),ax:y.map(R=>R.ax),ay:y.map(R=>R.ay),laptime:g,sweeps:{backward:1,forward:1},...l?{loadFactor:y.map((R,k)=>l(k,R.v))}:{},...mM(e,o,t,y.map(R=>R.v)),...b?uM(b,m):{}}}var pM=(e,t)=>{let r=e[t]?.value;return Number.isFinite(r)&&r>0?r:0};function no(e,t,r){let n=e.m.value,o=e.r_dyn?.value??0,a=pM(e,"I_wheel"),s=e.motorModel?.kind==="ice"?0:pM(e,"I_rotor"),i=e.gear_ratio?.value??1;if(!(o>0)||a===0&&s===0)return{mass:n,driven:0,undriven:0,effective:n,powerFactor:1,tractionFactor:1};let c=o*o,l=(t?2:0)+(r?2:0),u=4-l,m=(l*a+s*i*i)/c,f=u*a/c,p=n+m+f;return{mass:n,driven:m,undriven:f,effective:p,powerFactor:n/p,tractionFactor:n/(n+f)}}function oo(e){let t=e.fAxle;return{drivenFront:t?t.fFront.some(r=>r>0):!1,drivenRear:t?t.fRear.some(r=>r>0):!0}}var Ti=36e5,bM=Math.PI*2,Fb=e=>Math.max(0,Math.min(1,e));function wb(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=jc(t),n=e.gear_ratio.value,o=e.r_dyn.value,a=Math.max(1,Math.round(e.motorCount??e.driven_wheels.value));return(s,i)=>{let c=s*n/o*(60/bM),l=Math.max(0,i*o/(n*a)),u=r.efficiency(c,l);return u>.01?u:.5}}var dM=new WeakMap;function Fa(e){if(e.batteryModel)return e.batteryModel;let t=e.capacity.value,r=e.ocv.value,n=dM.get(e);if(n&&n.capacityAh===t&&n.ocv===r)return n.model;let o=nd(t,r);return dM.set(e,{capacityAh:t,ocv:r,model:o}),o}function Cb(e){let t=e.params,r=Ch(t,nu(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??=oI(e);let c=uu(n.inp,n.ev,o,a,i);return c?Math.min(o,c.regenFront+c.regenRear):r(o,a,s)}}var fM=new WeakMap;function oI(e){let t=e.params,r=fM.get(t);if(!r){let n=Er(t);r={inp:dt(n.regen?t:{...t,energy:{...n,regen:!0}}),ev:mr(t)},fM.set(t,r)}return r}var Pi=e=>e.airTempC??Ft;function ju(e,t){return e.thermal?e.thermal.startC??t:_o}function hM(e,t,r,n,o,a){let s=e.thermal;if(!s||!(o>0)||!(s.heatCapacityJPerK>0))return t;let i=s.coolingWPerK*(t-a)*o,c=s.entropicVPerK!==0?-r*(t+273.15)*s.entropicVPerK*o:0;return t+(n+c-i)/s.heatCapacityJPerK}var gM=()=>({windingC:[],derate:[],lossW:[],torqueNm:[],ampsRms:[]});function aI(e){let t=e.motorModel;if(!t?.thermal)return;let r=od(t.thermal),n=jc(t),o=e.gear_ratio.value,a=e.r_dyn.value,s=Math.max(1,Math.round(e.motorCount??e.driven_wheels.value));return{th:r,rpm:i=>i*o/a*(60/bM),peak:i=>n.maxTorque(i),amps:i=>t.thermal.torqueConstant>0?Math.abs(i)/t.thermal.torqueConstant:0,torque:(i,c,l)=>Math.min(Math.abs(i)*a/(o*s),l*n.maxTorque(c))}}function sI(e,t,r,n,o){let a=e.ocv(n);if(!(r>0))return{dq:t/a,lossJ:0,energyJ:t,short:!1,cutoff:!1,seconds:r};let s=e.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 iI(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 cI(e){let{drivenFront:t,drivenRear:r}=oo(e);return no(e.params,t,r)}function wa(e,t,r,n,o=Dr,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=wb(m),y=Rr(Fa(m)),R=y.chargeC,k=Fb(a??m.soc.value),v=Pi(m),x=s??ju(y,v),M=x,F=0,w=0,C=0,T=0,S=-1,A=-1,P=-1,L=aI(m),D=L?L.th.startC:0,E=D,V=0,N=1,z=-1,I=0,_=0,B=Cb(e),O=m.motorModel?.kind==="ice",G=u?.scrub,K=G?d/cI(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}=Ku(m,Z,te/9.81,b),re=.5*f*fe*J*ne,pe=.5*f*W*J*ne,de=(h+re)*-p,ie=G?-K*(G[j]??0):0,oe=de+pe+ie+d*te,ue=oe*t[j],Be=j+1<r.length?r[j+1]:Z,Ae=.5*(Z+Be),le=Ae>0?t[j]/Ae:0,Re=0,Te=k,ze=x,je=0,be=0,Fe=le;if(O){oe>0&&(be=ue/g(Z,oe),F+=be/Ti),l?.netKwh.push(F-w),l?.powerKw?.push(le>0?be/le/1e3:0);continue}if(oe>0){let xe=ue/g(Z,oe),me=sI(y,xe,le,k,x);me.short&&S<0&&(S=j),me.cutoff&&A<0&&(A=j);let Le=k*R,Se=Math.min(me.dq,Le),Ye=me.dq>0?Se/me.dq:1;Se>=Le&&P<0&&(P=j),F+=me.energyJ*Ye/Ti,be=me.energyJ*Ye,Fe=me.seconds,C+=me.lossJ*Ye,T+=Se,le>0&&(je=Se/me.seconds),k=Fb(k-Se/R),x=hM(y,x,me.dq>0&&le>0?Se/le:0,me.lossJ*Ye,le,v),x>M&&(M=x),Re=oe}else if(o.regen){let xe=u?He(u.ay[j],u.bank?.[j]??0)/9.81:0,me=B(-oe,Z,te/9.81,xe),Le=o.regenEfficiency*me*t[j],Se=iI(y,Le,le,k,x),Ye=(1-k)*R,Ue=Math.min(Se.dq,Ye),zt=Se.dq>0?Ue/Se.dq:1;w+=Se.energyJ*zt/Ti,be=-Se.energyJ*zt,C+=Se.lossJ*zt,T-=Ue,le>0&&(je=-Ue/le),k=Fb(k+Ue/R),x=hM(y,x,Ue>0&&le>0?-Ue/le:0,Se.lossJ*zt,le,v),x>M&&(M=x),Re=-me*zt}if(l?.netKwh.push(F-w),l?.powerKw?.push(le>0?be/Fe/1e3:0),l?.pack){let xe=l.pack;xe.soc.push(Te),xe.amps.push(je),xe.volts.push(y.ocv(Te)-je*y.resistance(Te,ze)),xe.cellC.push(ze)}if(L){let xe=L.rpm(Z),me=L.th.derate(xe,D,L.peak(xe));me<N&&(N=me),me<1&&z<0&&(z=j),_+=le,me<1&&(I+=le);let Le=L.torque(Re,xe,me),Se=L.th.lossW(xe,Le,D);V+=Se*le,i&&(i.windingC.push(D),i.derate.push(me),i.lossW.push(Se),i.torqueNm.push(Le),i.ampsRms.push(L.amps(Le))),D=L.th.step(D,Se,le),D>E&&(E=D)}}return{drive:F,regen:w,net:F-w,chargeAh:T/3600,loss:C/Ti,socEnd:k,shortAt:S,cutoffAt:A,emptyAt:P,tempEndC:x,tempMaxC:M,...L?{motorTempEndC:D,motorTempMaxC:E,motorLossKwh:V/Ti,motorDerateMin:N,motorDerateAt:z,motorDerateTimeFrac:_>0?I/_:0}:{}}}var lI=.5,uI=.02,mI=6;function yM(e,t,r,n,o,a,s,i){let c=n(),l=1,u=d=>{let h=gM(),b=wa(e,t,d.v,d.ax,r,o,a,h,s,void 0,{ay:d.ay,bank:i,...d.axScrub?{scrub:d.axScrub}:{}});return{trace:h,peak:b.motorTempMaxC??0,frac:b.motorDerateTimeFrac??0}},m=u(c);if(!m.trace.derate.length||m.frac===0)return{lap:c,solves:l,converged:!0,peakWindingC:m.peak,derateTimeFrac:m.frac};let f=m.trace.derate.slice(),p=!1;for(let d=0;d<mI;d++){let h=n(f);l++;let b=Math.abs(h.laptime-c.laptime);if(c=h,m=u(c),b<uI){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]+lI*((g[R]??1)-f[R]);f=y}return{lap:c,derate:f,solves:l,converged:p,peakWindingC:m.peak,derateTimeFrac:m.frac}}var pI=.1;function xM(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:Rr(Fa(e)).maxPower(t??e.soc.value,r,xM(e)).watts}function Uu(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(pI,t),s=wb(e),i=o*(e.effi_pgb?.value??.9)/a;return o*s(t,i)/a}var dI=180/Math.PI;function Xu(e,t,r,n){let o=e*t,a=e*(1-t);return o/r-a/n}var Qu=e=>e*9.81*dI;var P7=Math.PI/180;function qu(e,t,r,n=0){let o=Ce(e,t,0,n),a=typeof r=="function"?r:r.front,s=typeof r=="function"?r:r.rear,i=.5*(a(Math.max(0,o.FL))+a(Math.max(0,o.FR))),c=.5*(s(Math.max(0,o.RL))+s(Math.max(0,o.RR))),l=i>0&&c>0?Xu(e.massTotal,e.frontMassFrac,2*i,2*c):0,u=Qu(l),m=u>.15?"understeer":u<-.15?"oversteer":"neutral";return{gradient:u,balance:m,cAlphaFront:i,cAlphaRear:c}}var V7=Math.PI/180,B7=180/Math.PI;var RM=2220446049250313e-31;function bI(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 gI(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 yI(e){let t=e.length,r=new Array(t).fill(0),n=new Array(t).fill(0),o=0;for(let i=0;i<t;i++)for(let c=Math.max(i-1,0);c<t;c++)o+=Math.abs(e[i][c]);let a=t-1,s=0;for(;a>=0;){let i=0,c=0;do{for(c=a;c>=1;c--){let u=Math.abs(e[c-1][c-1])+Math.abs(e[c][c]);if(u===0&&(u=o),Math.abs(e[c][c-1])<=RM*u){e[c][c-1]=0;break}}let l=e[a][a];if(c===a)r[a]=l+s,n[a]=0,a--;else{let u=e[a-1][a-1],m=e[a][a-1]*e[a-1][a];if(c===a-1){let f=.5*(u-l),p=f*f+m,d=Math.sqrt(Math.abs(p));l+=s,p>=0?(d=f+(f>=0?Math.abs(d):-Math.abs(d)),r[a-1]=r[a]=l+d,d!==0&&(r[a]=l-m/d),n[a-1]=n[a]=0):(r[a-1]=r[a]=l+f,n[a]=d,n[a-1]=-d),a-=2}else{if(i===60)throw new Error("eigenvalues: QR iteration did not converge");if(i===10||i===20||i===30||i===40||i===50){s+=l;for(let g=0;g<=a;g++)e[g][g]-=l;let b=Math.abs(e[a][a-1])+Math.abs(e[a-1][a-2]);u=l=.75*b,m=-.4375*b*b}i++;let f=a-2,p=0,d=0,h=0;for(;f>=c;f--){let b=e[f][f],g=l-b,y=u-b;p=(g*y-m)/e[f+1][f]+e[f][f+1],d=e[f+1][f+1]-b-g-y,h=e[f+2][f+1];let R=Math.abs(p)+Math.abs(d)+Math.abs(h);if(p/=R,d/=R,h/=R,f===c)break;let k=Math.abs(e[f][f-1])*(Math.abs(d)+Math.abs(h)),v=Math.abs(p)*(Math.abs(e[f-1][f-1])+Math.abs(b)+Math.abs(e[f+1][f+1]));if(k<=RM*v)break}for(let b=f+2;b<=a;b++)e[b][b-2]=0,b!==f+2&&(e[b][b-3]=0);for(let b=f;b<=a-1;b++){b!==f&&(p=e[b][b-1],d=e[b+1][b-1],h=b!==a-1?e[b+2][b-1]:0,l=Math.abs(p)+Math.abs(d)+Math.abs(h),l!==0&&(p/=l,d/=l,h/=l));let g=Math.sqrt(p*p+d*d+h*h),y=p>=0?g:-g;if(y!==0){b===f?c!==f&&(e[b][b-1]=-e[b][b-1]):e[b][b-1]=-y*l,p+=y,l=p/y,u=d/y;let R=h/y;d/=p,h/=p;for(let v=b;v<=a;v++){let x=e[b][v]+d*e[b+1][v];b!==a-1&&(x+=h*e[b+2][v],e[b+2][v]-=x*R),e[b+1][v]-=x*u,e[b][v]-=x*l}let k=a<b+3?a:b+3;for(let v=c;v<=k;v++){let x=l*e[v][b]+u*e[v][b+1];b!==a-1&&(x+=R*e[v][b+2],e[v][b+2]-=x*h),e[v][b+1]-=x*d,e[v][b]-=x}}}}}}while(c<a-1&&a>=0)}return r.map((i,c)=>({re:i,im:n[c]}))}function vM(e){let t=e.length;if(t===0)return[];for(let n of e)if(n.length!==t)throw new Error("eigenvalues: matrix must be square");for(let n of e)for(let o of n)if(!Number.isFinite(o))throw new Error("eigenvalues: matrix has non-finite entries");if(t===1)return[{re:e[0][0],im:0}];let r=e.map(n=>n.slice());return bI(r),gI(r),yI(r)}function kM(e){let t=[],r=new Array(e.length).fill(!1),n=vM(e);for(let o=0;o<n.length;o++){if(r[o])continue;let{re:a,im:s}=n[o];if(s<0)continue;let i=Math.hypot(a,s);t.push({freq:i/(2*Math.PI),dampedFreq:Math.abs(s)/(2*Math.PI),dampingRatio:i>0?-a/i:0,eigenvalue:n[o]})}return t.sort((o,a)=>a.freq-o.freq)}function Pb(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 xI(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 Pb(r,n)}function Zu(e,t=r=>xI(e,r)){return kM(e).map(r=>({...r,vector:t(r.eigenvalue)}))}function Ca(e,t,r){let n,o=-1,a,s=-1;for(let i of e){let c=t(i.vector),l=c[r];i.eigenvalue.im===0?l>s&&(a=i,s=l):l>=Math.max(...c)&&l>o&&(n=i,o=l)}return n??a}function MM(e){let t=e.sprungMass;if(!(t>0))return;let r=Math.max(.1,e.unsprungMass),n=e.springRate*1e3,o=e.damperRate*1e3,a=e.tireRate*1e3,s=(e.tireDamping??0)*1e3,i=[[0,1,0,0],[-n/t,-o/t,n/t,o/t],[0,0,0,1],[n/r,o/r,-(n+a)/r,-(o+s)/r]];if(!i.every(l=>l.every(Number.isFinite)))return;let c=l=>{let u=t*(l[0].re**2+l[0].im**2),m=r*(l[2].re**2+l[2].im**2);return u+m>0?[u/(u+m),m/(u+m)]:[0,0]};return Ca(Zu(i),c,0)}function SM(e,t,r,n){let o=(r==="front"?t.sprungFront:t.sprungRear)/2;if(o<=0)return{dampingRatio:0,criticalDamping:0,naturalFreqDamped:0};let a=r==="front"?t.rideRateFront:t.rideRateRear,s=r==="front"?e.wheelRateFront+(e.heaveSpringFront??0):e.wheelRateRear+(e.heaveSpringRear??0),i=MM({sprungMass:o,unsprungMass:e.unsprungCornerMass??e.unsprungPerCorner,springRate:s,damperRate:n,tireRate:Xe(e,r),tireDamping:e.tireDamping}),c=2*Math.sqrt(a*1e3*o);return{dampingRatio:i?.dampingRatio??0,criticalDamping:c/1e3,naturalFreqDamped:i?.dampedFreq??0}}function Ju(e,t,r){let n=we(e);return{front:SM(e,n,"front",t??n.rideDampingFront),rear:SM(e,n,"rear",r??n.rideDampingRear)}}var Z7=180/Math.PI;var Lb=["FL","FR","RL","RR"],ce={zFL:0,vzFL:1,zFR:2,vzFR:3,zRL:4,vzRL:5,zRR:6,vzRR:7,zBody:8,vzBody:9,pitch:10,pitchRate:11,roll:12,rollRate:13,x:14,vx:15,y:16,vy:17,yaw:18,yawRate:19},Ta=20,AM=[ce.zFL,ce.zFR,ce.zRL,ce.zRR],FM=[ce.vzFL,ce.vzFR,ce.vzRL,ce.vzRR],Hr={fzFL:0,fzFR:1,fzRL:2,fzRR:3,fzBody:4,myBody:5,mxBody:6,fx:7,fy:8,mz:9},Db=10;function em(e){let t=Array.from({length:Ta},()=>new Array(Ta).fill(0)),r=Array.from({length:Ta},()=>new Array(Db).fill(0));t[ce.zFL][ce.vzFL]=1,t[ce.zFR][ce.vzFR]=1,t[ce.zRL][ce.vzRL]=1,t[ce.zRR][ce.vzRR]=1,t[ce.zBody][ce.vzBody]=1,t[ce.pitch][ce.pitchRate]=1,t[ce.roll][ce.rollRate]=1,t[ce.x][ce.vx]=1,t[ce.y][ce.vy]=1,t[ce.yaw][ce.yawRate]=1;let{inertia:n}=e,o=[1,0,3,2],a=(s,i,c,l)=>{s[AM[i]]-=c,s[FM[i]]-=l,s[ce.zBody]+=c,s[ce.vzBody]+=l,s[ce.pitch]-=c*e.leverX[i],s[ce.pitchRate]-=l*e.leverX[i],s[ce.roll]+=c*e.leverY[i],s[ce.rollRate]+=l*e.leverY[i]};for(let s=0;s<4;s++){let i=s<2,c=M=>M?i?M.front:M.rear:0,l=e.springRate[s]+c(e.heaveSpring),u=e.springRate[s]+c(e.arb),m=e.damperRate[s]+c(e.heaveDamper),f=e.damperRate[s]+c(e.rollDamper),p=(l+u)/2,d=(l-u)/2,h=(m+f)/2,b=(m-f)/2,g=new Array(Ta).fill(0);a(g,s,p,h),(d!==0||b!==0)&&a(g,o[s],d,b);let y=e.wheelMass[s],R=e.leverX[s],k=e.leverY[s],v=AM[s],x=FM[s];for(let M=0;M<Ta;M++){let F=g[M];F!==0&&(t[x][M]+=F/y,t[ce.vzBody][M]-=F/e.bodyMass,t[ce.pitchRate][M]+=R*F/n.yy,t[ce.rollRate][M]-=k*F/n.xx)}t[x][v]-=e.tyreRate[s]/y,t[x][x]-=e.tyreDamping[s]/y,r[x][Hr.fzFL+s]=1/y}return r[ce.vzBody][Hr.fzBody]=1/e.bodyMass,r[ce.pitchRate][Hr.myBody]=1/n.yy,r[ce.rollRate][Hr.mxBody]=1/n.xx,r[ce.vx][Hr.fx]=1/e.totalMass,r[ce.vy][Hr.fy]=1/e.totalMass,r[ce.yawRate][Hr.mz]=1/n.zz,{A:t,B:r,params:e}}function Eb(e){let t=e.wheelbase/1e3,r=t*(1-e.frontMassFrac),n=t*e.frontMassFrac,o=e.trackFront/2e3,a=e.trackRear/2e3,s=e.unsprungCornerMass??e.unsprungPerCorner,i=Math.max(0,e.massTotal-4*s),c=e.wheelRateFront*1e3,l=e.wheelRateRear*1e3,u=(e.damperFront??2.5)*1e3,m=(e.damperRear??2.5)*1e3,f=Xe(e,"front")*1e3,p=Xe(e,"rear")*1e3,d=(e.tireDamping??0)*1e3;return{bodyMass:i,totalMass:e.massTotal,wheelMass:[s,s,s,s],inertia:{xx:e.rollInertia??i*.6*.6,yy:e.pitchInertia??i*1.2*1.2,zz:e.yawInertia??e.massTotal*1.2*1.2},leverX:[r,r,-n,-n],leverY:[o,-o,a,-a],springRate:[c,c,l,l],damperRate:[u,u,m,m],tyreRate:[f,f,p,p],tyreDamping:[d,d,d,d],arb:{front:e.arbFront*1e3,rear:e.arbRear*1e3},heaveSpring:{front:(e.heaveSpringFront??0)*1e3,rear:(e.heaveSpringRear??0)*1e3},rollDamper:{front:(e.rollDamperFront??0)*1e3,rear:(e.rollDamperRear??0)*1e3},heaveDamper:{front:(e.heaveDamperFront??0)*1e3,rear:(e.heaveDamperRear??0)*1e3}}}var wM=ce.rollRate+1;function CM(e){let t=e.params,r=[...t.wheelMass,t.bodyMass,t.inertia.yy,t.inertia.xx];if(!r.every(i=>i>0))return{};let n=e.A.slice(0,wM).map(i=>i.slice(0,wM));if(!n.every(i=>i.every(Number.isFinite)))return{};let a=Zu(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 Pb(u,m)}),s=i=>{let c=r.map((u,m)=>u*(i[m].re**2+i[m].im**2)),l=c.reduce((u,m)=>u+m,0)||1;return[c[0]+c[1]+c[2]+c[3],c[4],c[5],c[6]].map(u=>u/l)};return{heave:Ca(a,s,1),pitch:Ca(a,s,2),roll:Ca(a,s,3)}}function TM(e,t,r){let n=e?2*Math.PI*e.freq:0,o=e&&n>0?e.dampingRatio:0,a=o>0&&o<1?Math.exp(-Math.PI*o/Math.sqrt(1-o*o))*100:0,s=o>0&&n>0?4/(o*n):1/0;return{freq:n/(2*Math.PI),dampedFreq:e&&n>0?e.dampedFreq:0,dampingRatio:o,stiffness:t,inertia:r,overshoot:a,settlingTime:s}}function tm(e){let t=we(e),r=e.wheelbase/1e3,n=r*(1-e.frontMassFrac),o=r*e.frontMassFrac,a=t.rollRateTotal*(180/Math.PI),s=e.rollInertia??t.sprungMass*.6*.6,i=2*t.rideRateFront*1e3,c=2*t.rideRateRear*1e3,l=i*n*n+c*o*o,u=e.pitchInertia??t.sprungMass*1.2*1.2,m=CM(em(Eb(e)));return{roll:TM(m.roll,a,s),pitch:TM(m.pitch,l,u)}}var rm=9.81,zr=Math.PI/180;function PM(e){let t=e.wheelbase/1e3,r=t*(1-e.frontMassFrac),n=t*e.frontMassFrac;return{wb:t,lf:r,lr:n,m:e.massTotal}}function Pa(e,t,r,n,o){let{wb:a,lf:s,lr:i,m:c}=PM(e),l=0;for(let R=0;R<16;R++){let k=l/r,v=o-n-s*k/r,x=-n+i*k/r,M=Ce(e,l/rm,0,r),F=Math.max(0,M.FL+M.FR),w=Math.max(0,M.RL+M.RR),C=t(v,F),T=t(x,w),S=(C*Math.cos(o)+T)/c;if(l=.5*(l+S),Math.abs(S-l)<1e-4)break}let u=l/r,m=o-n-s*u/r,f=-n+i*u/r,p=Ce(e,l/rm,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/rm,cn:y/(c*rm*a)}}function Ib(e,t,r,n={}){let o=Math.max(8,r),a=(n.betaMaxDeg??10)*zr,s=(n.deltaMaxDeg??10)*zr,i=n.nLines??9,c=n.nPts??21,l=(g,y,R,k)=>R===1?g:g+(y-g)*k/(R-1),u=[],m={ay:[],cn:[]},f=0;for(let g=0;g<i;g++){let y=l(-s,s,i,g),R=[],k=[],v=[],x=[];for(let M=0;M<c;M++){let F=l(-a,a,c,M),w=Pa(e,t,o,F,y);R.push(w.ay),k.push(w.cn),v.push(F/zr),x.push(y/zr),Math.abs(w.ay)>f&&(f=Math.abs(w.ay))}u.push({label:`\u03B4 ${(y/zr).toFixed(0)}\xB0`,ay:R,cn:k,betaDeg:v,deltaDeg:x});for(let M=1;M<k.length;M++)if(k[M-1]===0||k[M-1]<0!=k[M]<0){let F=k[M-1]===k[M]?0:k[M-1]/(k[M-1]-k[M]);m.ay.push(R[M-1]+F*(R[M]-R[M-1])),m.cn.push(0);break}}let p=[];for(let g=0;g<i;g++){let y=l(-a,a,i,g),R=[],k=[],v=[],x=[];for(let M=0;M<c;M++){let F=l(-s,s,c,M),w=Pa(e,t,o,y,F);R.push(w.ay),k.push(w.cn),v.push(y/zr),x.push(F/zr)}p.push({label:`\u03B2 ${(y/zr).toFixed(0)}\xB0`,ay:R,cn:k,betaDeg:v,deltaDeg:x})}let d=.5*zr,h=(Pa(e,t,o,d,0).cn-Pa(e,t,o,-d,0).cn)/(2*d),b=(Pa(e,t,o,0,d).cn-Pa(e,t,o,0,-d).cn)/(2*d);return{isoBeta:p,isoDelta:u,trim:m,maxAy:f,stability:h,control:b,speed:o}}function RI(e){return!e.corneringStiffnessFront||!e.corneringStiffnessRear?null:{Cf:2*e.corneringStiffnessFront,Cr:2*e.corneringStiffnessRear}}function Li(e,t){let r=RI(e);if(!r)return null;let{Cf:n,Cr:o}=r,{wb:a,lf:s,lr:i,m:c}=PM(e),l=e.yawInertia??c*1*1,u=Math.max(3,t),m=-(n+o)/(c*u),f=(-s*n+i*o)/(c*u)-u,p=(-s*n+i*o)/(l*u),d=-(s*s*n+i*i*o)/(l*u),h=m+d,b=m*d-f*p,g=h*h-4*b,y,R,k;if(g<0)y=h/2,R=Math.sqrt(Math.max(0,b)),k=R>0?-h/(2*R):1;else{let P=Math.sqrt(g);y=Math.max((h+P)/2,(h-P)/2),R=Math.sqrt(Math.abs(b)),k=R>0?-h/(2*R):1}let v=h<0&&b>0,x=Xu(c,e.frontMassFrac,n,o),M=Qu(x),F=M>.15?"understeer":M<-.15?"oversteer":"neutral",w=s*n-i*o,C=P=>P*3.6,T=null,S=null;w>1e-6?S=C(Math.sqrt(n*o*a*a/(c*w))):w<-1e-6&&(T=C(Math.sqrt(n*o*a*a/(c*-w))));let A=u/(a+x*u*u);return{stable:v,yawFreq:R/(2*Math.PI),dampingRatio:k,eigReal:y,understeerGradient:M,balance:F,characteristicSpeed:T,criticalSpeed:S,yawRateGain:A}}var LM=Math.PI/180;function IM(e,t){let r=Math.abs(e);return r<.15?"no measurable body slip \u2014 the car is travelling along its own centreline":Math.abs(t)<1e-6?`${r.toFixed(1)}\xB0 of body slip (not cornering, so there is no inside or outside yet)`:e*Math.sign(t)>0?`${r.toFixed(1)}\xB0 of body slip, nose pointing OUT of the corner \u2014 running wide of the path it is on`:`${r.toFixed(1)}\xB0 of body slip, nose pointing INTO the corner \u2014 rotated inside the path it is on`}function DM(e,t,r){return e.length<2?0:t<=0?(e[1]-e[0])/r:t>=e.length-1?(e[e.length-1]-e[e.length-2])/r:(e[t+1]-e[t-1])/(2*r)}function _M(e,t,r,n){let o=e.isoDelta.length,a=e.isoDelta[0]?.ay.length??0,s=Math.max(0,Math.min(o-1,Math.floor(t))),i=Math.max(0,Math.min(a-1,Math.floor(r))),c=Math.max(0,Math.min(1,t-s)),l=Math.max(0,Math.min(1,r-i)),u=0;for(let[m,f]of[[s,1-c],[Math.min(o-1,s+1),c]])if(!(f<=0))for(let[p,d]of[[i,1-l],[Math.min(a-1,i+1),l]])d<=0||(u+=f*d*n(e.isoDelta[m],p,m));return u}function NM(e,t,r){let n=e.isoDelta[0],o=(n.betaDeg[1]-n.betaDeg[0])*LM||1,a=e.isoDelta.length>1?(e.isoDelta[1].deltaDeg[0]-e.isoDelta[0].deltaDeg[0])*LM:1,s=x=>_M(e,t,r,x),i=s((x,M)=>x.ay[M]),c=s((x,M)=>x.cn[M]),l=s((x,M)=>x.betaDeg[M]),u=s((x,M)=>x.deltaDeg[M]),m=s((x,M)=>DM(x.cn,M,o)),f=s((x,M,F)=>DM(e.isoDelta.map(w=>w.cn[M]),F,a||1)),p=Math.max(1e-6,e.maxAy),d=Math.abs(i)/p,h=Math.max(1e-6,...e.isoDelta.flatMap(x=>x.cn.filter(Number.isFinite).map(Math.abs))),b=Math.abs(c)/h,g=i===0?c:c*Math.sign(i),y=[];y.push(`${IM(l,i)}.`),b<.03?y.push("On the trim line: yaw moments balance, so this is a steady corner the car can actually hold. Only points on this line are real cornering states \u2014 everywhere else the car is still rotating."):g>0?y.push(`Not a steady state: there is a surplus yaw moment turning the car further into the corner, so it would keep rotating from here. To hold ${Math.abs(i).toFixed(2)} g the driver would have to wind ${u>=0?"off":"on"} steer until the point reaches the trim line.`):y.push("Not a steady state: the yaw moment is straightening the car out, so it would run wide from here. The car needs more steer, or more front grip, to reach the trim line at this slip angle.");let R=Math.abs(e.stability)>1e-9?m/e.stability:1;R<.15?y.push("Yaw stiffness has collapsed here: the moment resisting a change in body slip is essentially gone, so the car will not gather itself up if it steps out. Both axles are close to saturation."):R<.85?y.push(`Yaw stiffness is down to about ${(100*R).toFixed(0)} % of its straight-ahead value \u2014 the car resists a change in body slip less firmly here than it does in the linear range.`):y.push(`Yaw stiffness is near its straight-ahead value (${(100*R).toFixed(0)} %), so the car still opposes a change in body slip about as firmly as it does in a straight line.`);let k=Math.abs(e.control),v=k>1e-9?Math.abs(f)/k:1;return v<.15?y.push("The steering has stopped working here: another degree of lock buys almost no yaw moment, which is what a saturated front axle looks like. This is understeer in its literal sense \u2014 the front tyres are already at their limit."):v<.5&&y.push(`Steering response is down to about ${(100*v).toFixed(0)} % of its straight-ahead value \u2014 the front is well into the non-linear part of its curve.`),d>.97?y.push(`At the edge of the diagram: ${Math.abs(i).toFixed(2)} g is essentially all this car has at this speed.`):d<.25&&y.push("Well inside the limit \u2014 this is the linear region the handling balance is measured in."),{ay:i,cn:c,betaDeg:l,deltaDeg:u,stability:m,control:f,gripUsed:d,notes:y}}var EM=1e-4;function _b(e){let t=null,r=f=>{if(!t)return!0;let p=Math.abs(f),d=Math.abs(t.ay);return p>d*(1+EM)?!0:p<d*(1-EM)?!1:f>0&&t.ay<0};for(let f=0;f<e.isoDelta.length;f++){let p=e.isoDelta[f];for(let d=1;d<p.cn.length;d++){if(!(p.cn[d-1]===0||p.cn[d-1]<0!=p.cn[d]<0))continue;let b=p.cn[d-1]===p.cn[d]?0:p.cn[d-1]/(p.cn[d-1]-p.cn[d]),g=p.ay[d-1]+b*(p.ay[d]-p.ay[d-1]);r(g)&&(t={ay:g,d:f,b:b<.5?d-1:d})}}if(!t)return null;let n=NM(e,t.d,t.b),o=Math.abs(e.control)>1e-9?Math.abs(n.control/e.control):1,a=Math.abs(e.stability)>1e-9?n.stability/e.stability:1,s=o<.35,i=a<.35,c=s&&i?"both":s?"front":i?"rear":o<a?"front":"rear",l=e.isoDelta[t.d].betaDeg.length,u=t.b===0||t.b===l-1||t.d===0||t.d===e.isoDelta.length-1,m=t.ay<0?-1:1;return{ay:Math.abs(t.ay),turn:m,betaDeg:e.isoDelta[t.d].betaDeg[t.b]*m,deltaDeg:e.isoDelta[t.d].deltaDeg[t.b]*m,d:t.d,b:t.b,limitedBy:c,controlFrac:o,stiffnessFrac:a,onGridEdge:u}}var vI=["tv_kp"];function OM(e=0){let t=e<0,r=e>0,n=t||r,o=[{key:"damper_front",why:"dampers act on velocity; every point here is at constant attitude"},{key:"damper_rear",why:"dampers act on velocity; every point here is at constant attitude"},{key:"tire_vertical_damping",why:"tyre damping acts on velocity; every point here is at constant attitude"},{key:"I_yaw",why:"inertia resists change; a steady corner has none"},{key:"I_roll",why:"inertia resists change; a steady corner has none"},{key:"I_pitch",why:"inertia resists change; a steady corner has none"},{key:"capacity",why:"energy does not enter a single steady-state point"},{key:"ocv",why:"energy does not enter a single steady-state point"},{key:"soc",why:"energy does not enter a single steady-state point"},...vI.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 kI=OM(0);function VM(e=0){let t="Springs and bars act through the roll-stiffness split and the camber the wheels take in roll; a heave spring reaches it too, but only faintly, through how far aero pushes the car down onto its camber curve.";if(!e)return"Steady state, lateral only: every point is a car in equilibrium at constant speed. Dampers, inertias, brake balance and the whole powertrain therefore cannot appear here \u2014 not because they are ignored, but because nothing in this picture accelerates. "+t;let r=e<0?`braking at ${Math.abs(e).toFixed(2)} g`:`accelerating at ${e.toFixed(2)} g`,n=e<0?"the brake balance decides which axle pays for it":"the driven axle pays for it";return`Steady state, ${r}: the load has moved ${e<0?"forward":"rearward"} and every tyre is spending part of its grip longitudinally, so ${n}. Dampers and inertias still cannot appear \u2014 the attitude is constant, it is simply not level. `+t}var MI=VM(0);var SI=9.81;function AI(e){let t=e.wheelbase/1e3;return{lf:t*(1-e.frontMassFrac),lr:t*e.frontMassFrac}}function Di(e,t,r,n){let o=t.tire;if(!o)return null;let s=(r==="limit"?nb(e,o,t.speed):hn(e,o,t.speed,t.ayG)).wheels;return Ar(n??jn(o,e.massTotal*SI*1.2),{FL:s.FL,FR:s.FR,RL:s.RL,RR:s.RR},AI(e))}function FI(e){if(!e.tire)return e.cornerStiffness;let t=ge(e.tire,"front"),r=ge(e.tire,"rear");return{front:n=>t.corneringStiffness(n),rear:n=>r.corneringStiffness(n)}}var BM=[{key:"understeer",label:"Understeer gradient",unit:"\xB0/g",compute:(e,t)=>qu(e,t.ayG,FI(t),t.speed).gradient},{key:"rollGradient",label:"Roll gradient",unit:"\xB0/g",compute:e=>we(e).rollGradient},{key:"pitchGradient",label:"Pitch gradient",unit:"\xB0/g",compute:e=>we(e).pitchGradient},{key:"tlltdFront",label:"TLLTD front",unit:"%",compute:e=>100*bf(e)},{key:"rollStiffFront",label:"Front roll-stiffness",unit:"%",compute:e=>100*we(e).frontRollStiffFrac},{key:"rideFreqFront",label:"Ride freq front",unit:"Hz",compute:e=>we(e).rideFreqFront},{key:"rideFreqRear",label:"Ride freq rear",unit:"Hz",compute:e=>we(e).rideFreqRear},{key:"rollFreq",label:"Roll-mode freq",unit:"Hz",compute:e=>tm(e).roll.freq},{key:"pitchFreq",label:"Pitch-mode freq",unit:"Hz",compute:e=>tm(e).pitch.freq},{key:"zetaFront",label:"Damping \u03B6 front",unit:"-",compute:e=>Ju(e).front.dampingRatio},{key:"zetaRear",label:"Damping \u03B6 rear",unit:"-",compute:e=>Ju(e).rear.dampingRatio},{key:"yawFreq",label:"Yaw natural freq",unit:"Hz",compute:(e,t)=>Li(e,t.speed)?.yawFreq??NaN},{key:"yawZeta",label:"Yaw damping \u03B6",unit:"-",compute:(e,t)=>Li(e,t.speed)?.dampingRatio??NaN},{key:"stabilitySpeed",label:"Char./critical speed",unit:"km/h",compute:(e,t)=>{let r=Li(e,t.speed);return r?r.criticalSpeed??r.characteristicSpeed??NaN:NaN}},{key:"maxAy",label:"Max lateral accel",unit:"g",compute:(e,t)=>t.fyAxle?Ib(e,t.fyAxle,t.speed,{betaMaxDeg:12,deltaMaxDeg:12}).maxAy:NaN},{key:"yawReserveRear",label:"Yaw stability reserve",unit:"N\xB7m",compute:(e,t)=>Di(e,t,"operating")?.stabil??NaN},{key:"yawReserveFront",label:"Yaw agility reserve",unit:"N\xB7m",compute:(e,t)=>Di(e,t,"operating")?.agil??NaN},{key:"limitBalance",label:"Limit balance (+US / \u2212OS)",unit:"-",compute:(e,t)=>Di(e,t,"limit")?.rel??NaN},{key:"yawStiffness",label:"Yaw stiffness N_\u03B2",unit:"N\xB7m/rad",compute:(e,t)=>t.tire?rb(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorque",label:"Steering holding torque",unit:"N\xB7m",compute:(e,t)=>t.tire?eb(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorqueGradient",label:"Steering feedback gradient",unit:"N\xB7m/g",compute:(e,t)=>t.tire?tb(e,t.tire,t.speed,t.ayG):NaN}],Nb=Object.fromEntries(BM.map(e=>[e.key,e]));var Yr=9.81;function wI(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 CI={front:!1,rear:!0};function La(e,t,r){let n=e.muX(t)*t,o=e.muY(t)*t;if(!(n>0))return 0;let a=o>0?Math.min(1,r/o):1;return n*Math.sqrt(1-a*a)}function $M(e,t,r,n,o,a){let s=e[t]+e[r];if(!(s>0))return;let i=La(n,o[t],a[t]),c=La(n,o[r],a[r]);i+c>0||(i=n.muX(o[t])*o[t],c=n.muX(o[r])*o[r]),i+c>0&&(e[t]=s*i/(i+c),e[r]=s-e[t])}function GM(e,t,r,n,o,a={},s="open"){if(!e.rear)return 1;if(!e.front)return 0;let i=(f,p,d)=>d?ti(f,p,d):s==="own"?f+p:2*Math.min(f,p),c=i(La(n,t.FL,r.FL),La(n,t.FR,r.FR),a.front),l=i(La(o,t.RL,r.RL),La(o,t.RR,r.RR),a.rear);if(c+l>0)return c/(c+l);let u=n.muX(t.FL)*t.FL+n.muX(t.FR)*t.FR,m=o.muX(t.RL)*t.RL+o.muX(t.RR)*t.RR;return u+m>0?u/(u+m):.5}function Ob(e,t,r,n){return{car:t?zM(t,r.loadFactor[n]):e,ayTyre:He(r.ay[n],r.bank?.[n]??0),axCar:r.ax[n]-(r.axGrade?.[n]??0)}}function KM(e,t){if(!e.aero?.model)return 0;let r=Math.min(t.v.length,t.ax.length,t.ay.length),n=t.loadFactor?om(e):void 0,o=0,a=0;for(let s=0;s<r;s++){let i=t.ds?.[s]??1,c=Ob(e,n,t,s);o+=i,hf(c.car,t.v[s],c.axCar/Yr,c.ayTyre/Yr)&&(a+=i)}return o>0?a/o:0}function HM(e,t,r){let n=Wt(ge(t,"front")),o=Wt(ge(t,"rear")),a=Math.min(r.v.length,r.ax.length,r.ay.length),s=r.loadFactor?om(e):void 0,i=0,c=0;for(let l=0;l<a;l++){let u=r.ds?.[l]??1,m=Ob(e,s,r,l);i+=u;let f=Ce(m.car,m.ayTyre/Yr,m.axCar/Yr,r.v[l]);(f.FL>n||f.FR>n||f.RL>o||f.RR>o)&&(c+=u)}return i>0?c/i:0}function nm(e,t,r,n={}){let o=Math.min(r.v.length,r.ax.length,r.ay.length),a=e.wheelbase/1e3,s=a*(1-e.frontMassFrac),i=a*e.frontMassFrac,c=ci(t,e.massTotal*Yr*1.2),l=aa(c,"front"),u=aa(c,"rear"),m=ut(ge(t,"front")),f=ut(ge(t,"rear")),p=n.perWheel?Rf(m,l):null,d=n.perWheel?f===m?p:Rf(f,u):null,h=n.driven??CI,b={front:$t(e,"front",1),rear:$t(e,"rear",1)},g={front:0,rear:0},y=new Array(o),R=new Array(o),k=new Array(o),v=1/0,x=0,M=0,F=Wt(m),w=Wt(f),C=0,T=0,S=0,A=0,P=0,L=0,D=["FL","FR","RL","RR"],E=n.perWheel?Object.fromEntries(D.map(N=>[N,{Fz:new Array(o),alpha:new Array(o),Fy:new Array(o),Fx:new Array(o),Mz:new Array(o),used:new Array(o),FxCap:new Array(o),FyCap:new Array(o)}])):void 0,V=r.loadFactor?om(e):void 0;for(let N=0;N<o;N++){let z=Ob(e,V,r,N),{ayTyre:I,axCar:_}=z,B=I/Yr,O=Ce(z.car,B,_/Yr,r.v[N]),G=e.massTotal*I,K=G*i/a,Y=G*s/a,j=_s(m,K,O.FL,O.FR,P),Z=_s(f,Y,O.RL,O.RR,L);P=j,L=Z;let ne={FL:Math.abs(m.Fy(j,O.FL,0)),FR:Math.abs(m.Fy(j,O.FR,0)),RL:Math.abs(f.Fy(Z,O.RL,0)),RR:Math.abs(f.Fy(Z,O.RR,0))},te=(_-(r.axDrag?.[N]??0)-(r.axScrub?.[N]??0))/Yr,fe=te>0&&h.front?GM(h,O,ne,l,u,b,"own"):0,W=r.v[N]*r.v[N],J=e.driveline?{Fz:O,alpha:{front:j,rear:Z},curvature:W>1?r.ay[N]/W:0,seed:g}:void 0,re={...Qh(e,te,r.v[N],t,B,fe,J)};te>0&&(b.front||$M(re,"FL","FR",l,O,ne),b.rear||$M(re,"RL","RR",u,O,ne));let pe=!1,de=!1;for(let ue of["FL","FR","RL","RR"]){let Be=(ue==="FL"||ue==="FR"?l:u).muX(O[ue])*O[ue];Math.abs(re[ue])>Be&&(pe=!0),O[ue]>(ue==="FL"||ue==="FR"?F:w)&&(de=!0)}de&&(M+=r.ds?.[N]??1);let ie=Ar(c,{FL:{Fz:O.FL,Fy:ne.FL,Fx:re.FL},FR:{Fz:O.FR,Fy:ne.FR,Fx:re.FR},RL:{Fz:O.RL,Fy:ne.RL,Fx:re.RL},RR:{Fz:O.RR,Fy:ne.RR,Fx:re.RR}},{lf:s,lr:i});if(y[N]=ie.stabil,R[N]=ie.agil,k[N]=ie.rel,E){let ue=.5*(O.FL+O.FR),Be=.5*(O.RL+O.RR),Ae=l.muX(ue)*ue,le=u.muX(Be)*Be;for(let Re of D){let Te=O[Re],ze=Re==="FL"||Re==="FR",je=ze?l:u,be=je.muY(Te)*Te,Fe=je.muX(Te)*Te,xe=E[Re],me=ze?j:Z;xe.Fz[N]=Te,xe.alpha[N]=me,xe.Fy[N]=ne[Re],xe.Fx[N]=re[Re],xe.Mz[N]=Te>0?(ze?m:f).Mz(me,Te,0):0,xe.FxCap[N]=Fe,xe.FyCap[N]=be;let Le=be>0?Math.min(1,Math.abs(ne[Re])/be):0,Se=wI(re[Re],Fe,ze?Ae:le),Ye=ze?p:d,Ue=Ye&&Te>0?Ye.reach(Te,Math.sign(re[Re])*Se,Le):1;xe.used[N]=Math.hypot(Le,Se)/Ue}}ie.stabil<v&&(v=ie.stabil,x=N);let oe=r.ds?.[N]??1;A+=oe,ie.diff>0&&(C+=oe),pe&&(T+=oe),hf(z.car,r.v[N],_/Yr,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 om(e){return Object.create(e,{loadFactor:{value:1,writable:!0,enumerable:!0}})}function zM(e,t){return e.loadFactor=t,e}var Vb=9.81;function Bb(e,t,r,n={}){let o=r.v.length,a=e.massTotal,s=_r(e),i=s.mode==="hydraulic",c={front:new Array(o).fill(0),rear:new Array(o).fill(0),...n.regen?{regen:new Array(o).fill(0)}:{},...i?{pFront:new Array(o).fill(0),pRear:new Array(o).fill(0),pedalN:new Array(o).fill(0)}:{}};for(let l=0;l<o;l++){let u=r.v[l],m=r.ax[l]-(r.axGrade?.[l]??0),f=m-(r.axDrag?.[l]??0)-(r.axScrub?.[l]??0),p=-a*f;if(!(p>0))continue;let d=He(r.ay[l],r.bank?.[l]??0)/Vb,h=Math.min(.99,Math.max(.01,fa(e,f/Vb,u,t,d)));c.front[l]=p*h,c.rear[l]=p*(1-h);let b=i?uu(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/Vb)),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 cq=Math.PI/180;var lq=Lb.map(li);var uq=[ce.zFL,ce.zFR,ce.zRL,ce.zRR];var mq=Array.from({length:ce.rollRate+1},(e,t)=>t);var GI=9.81,KI=.001,HI=.6,zI=2,UM=4;function XM(e,t,r,n=UM){let o=Math.min(e.v.length,t.npts),{ds:a,closed:s}=t,i=r.massTotal*GI*r.wheelbase,c=YI(e.ay.slice(0,o).map((m,f)=>m/Math.max(KI,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 YI(e,t,r,n){let o=e.length;if(!(n>0)||o<3)return e;let a=new Array(o);a[0]=0;for(let c=1;c<o;c++)a[c]=a[c-1]+t[c-1];let s=r?Math.floor((o-1)/2):o-1,i=new Array(o);for(let c=0;c<o;c++){let l=r?n:Math.min(n,a[c],a[o-1]-a[c]),u=e[c],m=1,f=0;for(let p=1;p<=s&&!(!r&&c+p>=o||(f+=t[(c+p-1)%o],!(f<l)));p++){let d=1-f/l;u+=d*e[(c+p)%o],m+=d}f=0;for(let p=1;p<=s&&!(!r&&c-p<0);p++){let d=(c-p+o)%o;if(f+=t[d],!(f<l))break;let h=1-f/l;u+=h*e[d],m+=h}i[c]=u/m}return i}function QM(e,t,r,n,o={}){let a=o.maxIter??20,s=o.tol??.001,i=Math.min(1,Math.max(.001,o.relax??HI)),c=o.smoothM??UM,l={standingStart:o.standingStart,...o.driveDerate?{driveDerate:o.driveDerate}:{},...o.brakeFade?{brakeFade:o.brakeFade}:{},...o.vCeiling?{vCeiling:o.vCeiling}:{},...o.load?{load:o.load}:{},...o.shifts?{shifts:o.shifts}:{}},u=Rt(e.steady,t,n,l),m=[u.laptime],f=new Array(t.npts).fill(0),p=f.slice(),d=u,h=0,b=!1,g=0;for(let k=0;k<a;k++){h=k+1;let v=XM(d,t,r,c);f=v.demand.map((F,w)=>f[w]+i*(F-f[w])),p=v.rdot;let x=Rt(e.steady,t,n,{...l,envelope:F=>e.at(f[F]??0)});m.push(x.laptime);let M=Math.abs(x.laptime-d.laptime);if(d=x,g=M<=s?g+1:0,g>=zI){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 Rq=Math.PI/180;var Zq=180/Math.PI;function Da(e,t,r){let n=e.length;if(n===1||r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0;for(;o<n-2&&e[o+1]<=r;)o++;let a=e[o],s=e[o+1],i=t[o],c=t[o+1];if(n===2)return i+(r-a)/(s-a)*(c-i);let l=f=>{let p=e[f];return i*(r-s)*(r-p)/((a-s)*(a-p))+c*(r-a)*(r-p)/((s-a)*(s-p))+t[f]*(r-a)*(r-s)/((p-a)*(p-s))},u=(r-a)/(s-a),m=o===0?l(2):o+1===n-1?l(o-1):(1-u)*l(o-1)+u*l(o+2);return Math.min(Math.max(i,c),Math.max(Math.min(i,c),m))}function ZM(e,t){let r=e.filter(p=>p.atLock),n=e.filter(p=>!p.atLock),o=r.length>0&&n.length>0&&r[r.length-1].v<n[0].v,a=p=>({vs:p.map(h=>h.v),ayMax:p.map(h=>h.ayMax),radius:p.map(h=>Math.max(h.v,t)**2/h.ayMax),accel:p[0].axAccelN.map((h,b)=>p.map(g=>g.axAccelN[b])),decel:p[0].axDecelN.map((h,b)=>p.map(g=>g.axDecelN[b])),scrub:p[0].axScrubN.map((h,b)=>p.map(g=>g.axScrubN[b]))}),s=(p,d)=>({axAccelN:p.accel.map(h=>Da(p.vs,h,d)),axDecelN:p.decel.map(h=>Da(p.vs,h,d)),axScrubN:p.scrub.map(h=>Da(p.vs,h,d))});if(!o){let p=a(e);return d=>({ayMax:Da(p.vs,p.ayMax,d),...s(p,d)})}let i=a(r),c=a(n),l=i.vs[i.vs.length-1],u=c.vs[0],m=p=>Math.max(p,t)**2/Da(i.vs,i.radius,p),f=p=>p>=u||c.vs.length<2?Da(c.vs,c.ayMax,p):c.ayMax[0]+(c.ayMax[1]-c.ayMax[0])/(c.vs[1]-c.vs[0])*(p-u);return p=>{if(p<=l)return{ayMax:m(p),...s(i,p)};if(p>=u)return{ayMax:f(p),...s(c,p)};let d=m(p),h=f(p);return d<h?{ayMax:d,...s(i,p)}:{ayMax:h,...s(c,p)}}}function c2(e,t){let r=Math.abs(e.ayMax-t.ayMax)/Math.max(t.ayMax,1),n=Math.max(Math.abs(t.axAccelN[0]),1),o=Math.max(Math.abs(t.axDecelN[0]),1);for(let a=0;a<t.axAccelN.length;a++)r=Math.max(r,Math.abs(e.axAccelN[a]-t.axAccelN[a])/n,Math.abs(e.axDecelN[a]-t.axDecelN[a])/o,Math.abs(e.axScrubN[a]-t.axScrubN[a])/n);return r}function JM(e,t,r,n,o){let a=r>t?Math.max(2,Math.min(5,Math.floor(n))):1,s=[];for(let f=0;f<a;f++)s.push(e(a===1?t:t+(r-t)*f/(a-1)));let i=ZM(s,t),c=[],l=a,u=(f,p)=>{let d=.5*(f+p),h=e(d);l++;let b=c2(i(d),h);s.splice(s.findIndex(g=>g.v>d),0,h),i=ZM(s,t),b>o&&c.push({lo:f,hi:d,misfit:b},{lo:d,hi:p,misfit:b})},m=s.map(f=>f.v);for(let f=0;f+1<m.length&&l<n;f++)m[f+1]-m[f]>=1&&u(m[f],m[f+1]);if(m.length>1){let f=.5*(m[0]+m[1]);if(s.some(p=>p.v===f))for(let[p,d]of[[m[0],f],[f,m[1]]]){if(l>=n||d-p<1)break;let h=c.findIndex(b=>b.lo===p&&b.hi===d);h>=0&&c.splice(h,1),u(p,d)}}for(;l<n&&c.length>0;){let f=0;for(let b=1;b<c.length;b++)c[b].misfit>c[f].misfit&&(f=b);let{lo:p,hi:d,misfit:h}=c.splice(f,1)[0];if(h<=o)break;d-p<1||u(p,d)}return{anchors:s,at:i}}var l2=2,u2=.5,Ei=Math.PI/180,eS=21,m2={nCoarse:11,nSteer:13,nNorm:41,nAngle:45},p2={nCoarse:11,nSteer:13,nNorm:41,nAngle:61},d2=.005,f2=.05,$b=e=>e<0?0:e>1?1:e;function h2(e,t,r,n){let o=e.massTotal,a=n.nSteer??7,s=(n.drivenFront?2:0)+(n.drivenRear?2:0),i=Ce(e,0,0,r),c=Math.max(1,(i.FL+i.FR+i.RL+i.RR)/4),l=8*Ei,u=0,m=(b,g,y)=>{for(let R=b;R<=g;R+=y){let k=Math.abs(t.Fy(R*Ei,c,0));k>u&&(u=k,l=R*Ei)}};m(1,45,1),m(Math.max(.1,l/Ei-1),l/Ei+1,.1);let f=[],p=[],d=[],h=[];for(let b=0;b<a;b++){let g=b/(a-1),y=l*(g+Math.sin(Math.PI/2*g))/2,R=Math.abs(t.Fy(y,c,0));f.push(4*R/o),p.push(s*At(t,c,R,!1)/o),d.push(4*At(t,c,R,!0)/o),h.push(-4*R*Math.sin(y)/o)}return f[0]=0,{ayMax:4*u/o,ay:f,axAccel:p,axDecel:d,axScrub:h,rollover:!1}}function pr(e,t=!1,r="twoTrack",n,o,a=0,s=1){if(a!==0&&r==="fast")throw new Error('the fast (point-mass) envelope has no yaw balance to shift; use mode "twoTrack" for a yaw-inertia demand');let i=n??(t?p2:m2),{nCoarse:c,nSteer:l,nAngle:u}=i,m=Ir(0,1,i.nNorm).map(B=>Math.sin(Math.PI/2*B)),f=e.params,p=f.m.value,d=f.rho.value,h=f.fr_0.value,b=f.driven_wheels.value,g=f.power_scale.value,y=e.FG,R=dt(f);s!==1&&(R.loadFactor=s);let k=mr(f),v=m1(0,n?.vRes??(e.engine?u2:l2),e.vMax);v[v.length-1]<e.vMax&&v.push(e.vMax);let x=e.fRad.map(B=>B*b),M=e.fAxle,{drivenFront:F,drivenRear:w}=oo(e),C=no(f,F,w),T=(B,O)=>{let G=M?mt(M.vVehicle,B,O):NaN;return Number.isFinite(G)?G:1/0},S=B=>{let O=B*B,{cl:G,cw:K,A:Y}=Ku(f,B,0,R),j=.5*d*-K*Y*O,Z=.5*d*-G*Y*O,ne=h*(-Z+y);return j+ne},A=B=>{let O=S(B)/p*C.powerFactor,G=S(B)/p*C.tractionFactor,K;if(e.engine){let j=S(B);K=ma(e.engine,B,C.effective,j,g).accel-O}else if(M){let j=0;F&&(j+=T(M.fFront,B)),w&&(j+=T(M.fRear,B)),K=g*j/p*C.powerFactor}else{let j=mt(e.vVehicle,x,B),Z=g*j/p*C.powerFactor;K=Number.isFinite(Z)?Z:1/0}let Y=Uu(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+f2)*L),E=r==="fast"?h2:ab,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=>tu(O.ay,O.axAccel,Y(te))*C.tractionFactor),Z=m.map(te=>tu(O.ay,O.axDecel,Y(te))),ne=m.map(te=>tu(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(gu,D),z=JM(V,N,D,c,i.anchorTol??d2),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=$b(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=$b(Math.abs(Math.cos(ie)));re.push({ax:mt(m,fe,ue)+G+mt(m,W,ue),ay:oe,v:O})}let pe=(de,ie,oe)=>Array.from({length:eS},(ue,Be)=>({ax:ie+(oe-ie)*(Be+1)/(eS+1),ay:de,v:O}));_.push([...J,...pe(-ne,J[J.length-1].ax,re[0].ax),...re,...pe(ne,re[re.length-1].ax,J[0].ax)])}return{...rS(I,m),rows:I,norm:m,surf:_}}function Ea(e,t){return e?.length?t.map(r=>sm(e,r)):t.map(()=>0)}function sm(e,t){let r=e.length-1;if(!(t>e[0].v))return e[0].axDrag;if(t>=e[r].v)return e[r].axDrag;let n=0,o=r;for(;o-n>1;){let s=n+o>>1;e[s].v<=t?n=s:o=s}let a=(t-e[n].v)/(e[o].v-e[n].v);return e[n].axDrag+a*(e[o].axDrag-e[n].axDrag)}function rS(e,t){let r=e[e.length-1].v,n=d=>{if(d<=e[0].v)return{i0:0,i1:0,t:0};if(d>=r)return{i0:e.length-1,i1:e.length-1,t:0};let h=0,b=e.length-1;for(;b-h>1;){let g=h+b>>1;e[g].v<=d?h=g:b=g}return{i0:h,i1:b,t:(d-e[h].v)/(e[b].v-e[h].v)}},o=d=>{let{i0:h,i1:b,t:g}=n(d);return{a:e[h],b:e[b],t:h===b?0:g}},a=(d,h,b)=>d===0||h===b?h:h+d*(b-h),s=(d,h,b,g)=>d===0?mt(t,h,g):a(d,mt(t,h,g),mt(t,b,g)),i=(d,h)=>h>=1?d.axPower:Math.min(h*d.axDrive,d.axPackCap),c=({a:d,b:h,t:b},g,y)=>d.axScrubN?y*s(b,d.axScrubN,h.axScrubN,g):0,l=d=>d.axDragTyre??d.axDrag,u=({a:d,b:h,t:b},g,y)=>{let R=y*a(b,d.ayMax,h.ayMax);return R>0?$b(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 b2(e,t,r){let n=e.params,o=n.m.value,{drivenFront:a,drivenRear:s}=oo(e),i=no(n,a,s);return c=>Uu(n,c,t,r)/o*i.powerFactor}function Ii(e,t,r,n){let o=b2(t,r,n),a=e.rows.map(s=>{let i=o(s.v),c=Math.min(s.axDrive,i);return c===s.axPower&&i===s.axPackCap?s:{...s,axPackCap:i,axPower:c}});return{...rS(a,e.norm),rows:a,norm:e.norm}}var g2=[-.2,-.08,0,.06,.12,.2,.3];function nS(e,t=!1,r="twoTrack",n,o,a=g2){let s=[...new Set([...a,0])].sort((d,h)=>d-h),i=s.map(d=>pr(e,t,r,n,o,d)),c=i[s.indexOf(0)],l=s[0],u=s[s.length-1],m=d=>{if(d<=l)return{i:0,t:0};if(d>=u)return{i:s.length-1,t:0};let h=0;for(;h<s.length-2&&s[h+1]<=d;)h++;return{i:h,t:(d-s[h])/(s[h+1]-s[h])}},f=d=>{let h=b=>{let{i:g,t:y}=m(b);return{a:d[g],b:d[Math.min(d.length-1,g+1)],t:y}};return b=>{let{a:g,b:y,t:R}=h(b);if(R===0)return g;let k=(v,x)=>v+R*(x-v);return{vMax:g.vMax,axAccel:(v,x,M=1,F=1)=>k(g.axAccel(v,x,M,F),y.axAccel(v,x,M,F)),axDecel:(v,x,M=1,F=1)=>k(g.axDecel(v,x,M,F),y.axDecel(v,x,M,F)),ay:(v,x,M=1)=>k(g.ay(v,x,M),y.ay(v,x,M)),scrub:(v,x,M=1)=>k(g.scrub?.(v,x,M)??0,y.scrub?.(v,x,M)??0)}}},p=d=>d<l||d>u;return{anchors:s,steady:c,clamps:p,at:f(i),atSoc(d,h,b){let g=i.map(y=>Ii(y,d,h,b));return{anchors:s,steady:g[s.indexOf(0)],clamps:p,at:f(g)}}}}function oS(e,t,r,n="twoTrack",o){let a=[...new Set([...t,1])].sort((i,c)=>i-c),s=a.map(i=>i===1?r:pr(e,!1,n,o,void 0,0,i));return{...tS(a,s),atSoc:(i,c,l)=>tS(a,s.map(u=>Ii(u,i,c,l)))}}function tS(e,t){let r=e.length-1,n=1,o=0,a=0,s=0,i=1,c=0,l=0,u=p=>{if(n=1,!(p>e[0]))return void(o=0);if(p>=e[r])return void(o=r);let d=0;for(;d<r-1&&e[d+1]<=p;)d++;if(o=d,p===e[d])return;a=d+1;let h=e[d],b=e[d+1];if(r<2){n=2,c=(p-h)/(b-h),i=1-c;return}s=d===0?2:d+1===r||p-e[d-1]<e[d+2]-p?d-1:d+2;let g=e[s];n=3,i=(p-b)*(p-g)/((h-b)*(h-g)),c=(p-h)*(p-g)/((b-h)*(b-g)),l=(p-h)*(p-b)/((g-h)*(g-b))},m=p=>{let d=p(t[o]);if(n===1)return d;let h=p(t[a]);if(n===2)return i*d+c*h;let b=i*d+c*h+l*p(t[s]);return Math.min(Math.max(d,h),Math.max(Math.min(d,h),b))},f=(p,d,h,b,g)=>{if(u(p),n===1||h===0)return m(k=>g(k,h));let y=m(k=>k.ay(d,0,b));if(!(y>0))return m(k=>g(k,h));let R=h/y;return m(k=>g(k,R*k.ay(d,0,b)))};return{anchors:e,axAccel:(p,d,h,b=1,g=1)=>f(p,d,h,b,(y,R)=>y.axAccel(d,R,b,g)),axDecel:(p,d,h,b=1,g=1)=>{let y=R=>f(p,d,h,b,(k,v)=>k.axDecel(d,v,b,R));return g===1?y(1):kb(y(g),y(1),g)},scrub:(p,d,h,b=1)=>f(p,d,h,b,(g,y)=>g.scrub?.(d,y,b)??0),ay:(p,d,h,b=1)=>{if(u(p),n===1||h===0)return m(k=>k.ay(d,h,b));let g=k=>h>0?k.axAccel(d,0,b):-k.axDecel(d,0,b),y=m(g);if(!(y>0))return m(k=>k.ay(d,h,b));let R=h/y;return m(k=>k.ay(d,R*g(k),b))}}}var aS=new WeakMap;function Gb(e,t){let r=aS.get(e);if(!r){let n=Er(e).regen?Cb(t??wt(e)):void 0;r={inp:dt(e),ev:mr(e),...n?{regen:n}:{}},aS.set(e,r)}return r}function Kb(e,t,r){let n=Gb(e,r);return Bb(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:oh(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 y2(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 zb(e,t,r,n,o,a=Ft){if(!e)return null;let s=y2(t);return{...e.front?{front:Ql(e.front.heat,e.front.discs,s.front,r,n,o.front,a)}:{},...e.rear?{rear:Ql(e.rear.heat,e.rear.discs,s.rear,r,n,o.rear,a)}:{}}}var x2=.5,R2=.02,v2=6,im=9,sS=1e-9,k2={FL:0,FR:0,RL:0,RR:0};function Yb(e){return e?[...new Set([...e.padCurve.factor,1])].sort((t,r)=>t-r):[1]}function M2(e,t,r){let n=ir(e),o=n.hydraulic;return n.mode!=="hydraulic"||!o?e:{...e,brakes:{...n,hydraulic:{...o,front:{...o.front,padMu:o.front.padMu*t},rear:{...o.rear,padMu:o.rear.padMu*r}}}}}function iS(e,t){let r=e.length;if(r===1||t<=e[0])return{i:0,t:0};if(t>=e[r-1])return{i:r-2,t:1};let n=0;for(;n<r-2&&e[n+1]<=t;)n++;return{i:n,t:(t-e[n])/(e[n+1]-e[n])}}function cS(e,t,r,n,o=()=>0){let a=Array.from({length:im},(m,f)=>r*f/(im-1)),s=si(),{front:i,rear:c}=n,l=a.map(m=>{let f=o(m),p=h=>Nr(h,t,m,s).limitAt(0,0,k2,f).ax,d=p(e);return i.map(h=>c.map(b=>{if(h===1&&b===1)return 1;let g=d<0?p(M2(e,h,b))/d:1;return Math.abs(g-1)<sS?1:g}))}),u=a[1]-a[0];return{share(m,f,p){if(f===1&&p===1)return 1;let d=u>0?Math.min(im-2,Math.max(0,Math.floor(m/u))):0,h=u>0?Math.min(1,Math.max(0,(m-a[d])/u)):0,b=iS(i,f),g=iS(c,p),y=k=>{let v=l[k],x=Math.min(i.length-1,b.i+1),M=Math.min(c.length-1,g.i+1),F=v[b.i][g.i]+g.t*(v[b.i][M]-v[b.i][g.i]),w=v[x][g.i]+g.t*(v[x][M]-v[x][g.i]);return F+b.t*(w-F)},R=y(d)+h*(y(Math.min(im-1,d+1))-y(d));return Math.abs(R-1)<sS?1:R}}}function S2(e,t){let{front:r,rear:n}=t;return(o,a)=>e.share(a,r?.[o]??1,n?.[o]??1)}var A2=e=>(e.front??[]).every(t=>t===1)&&(e.rear??[]).every(t=>t===1);function lS(e,t,r){let n=e(),o=1,a=t(n);if(A2(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<v2;c++){let l=e(S2(r,s));o++;let u=Math.abs(l.laptime-n.laptime);if(n=l,u<R2){i=!0;break}a=t(n);let m=(d,h)=>d&&h?d.map((b,g)=>b+x2*((h[g]??1)-b)):d,f=m(s.front,a.front),p=m(s.rear,a.rear);s={...f?{front:f}:{},...p?{rear:p}:{}}}return{lap:n,pads:s,solves:o,converged:i}}function xn(e,t){let r=e.engine;if(!r||r.gears.length===0||t.length===0)return;let n=e.params,{drivenFront:o,drivenRear:a}=oo(e),s=no(n,o,a).effective,i=n.power_scale.value,{up:c,down:l}=xh(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:Rh(r.engine.gearbox),limitRpm:r.engine.limitRpm,best:f=>ma(r,f,s,sm(t,f)*s,i).gear,share:(f,p)=>{let d=sm(t,f),h=d*s,b=ma(r,f,s,h,i);if(p===b.gear)return 1;let g=b.accel-d;return g>0?Math.min(1,Math.max(0,(m(f,p,h)-d)/g)):0},rpm:(f,p)=>r.slipping(f,p)?u:r.rpm(f,p),vIdle:f=>r.gears[f]?.vIdle??0}}var uS=new WeakMap;function jb(e){let t=uS.get(e.ggv);return t===void 0&&(t=xn(e.vehicle,e.ggv.rows)??null,uS.set(e.ggv,t)),t??void 0}function F2(e){return e.gear&&e.engineRpm&&e.shifting?{gear:e.gear,rpm:e.engineRpm,shifting:e.shifting}:{}}var lm=class extends Error{constructor(t){super(t),this.name="EventError"}};function w2(e,t){let{ggv:r}=t,n=st(t.numerics),o=n.accelStep,a=Math.max(1,Math.round(e.distance/o)),s=Aa(r,new Array(a+1).fill(0),n);s[0].v=e.vStart??0;for(let d=0;d<s.length-1;d++){let h=s[d],b=s[d+1];h.v>=b.v||(h.ax=r.axAccel(h.v,0),b.v=Math.min(r.vMax,Math.sqrt(Math.max(0,h.v*h.v+2*h.ax*o))))}let i=jb(t),c=i?Yu(s.map(d=>d.v),new Array(a).fill(o),!1,i,(d,h,b)=>r.axAccel(h,0,1,b)):void 0;if(c){for(let d=0;d<=a;d++)s[d].v=c.v[d];for(let d=0;d<a;d++)s[d].ax=(s[d+1].v*s[d+1].v-s[d].v*s[d].v)/(2*o)}let l=0;for(let d=0;d<a;d++){let h=s[d].v+s[d+1].v;h>0&&(l+=2*o/h)}let u=s.slice(0,a).map(d=>d.v),m=s.slice(0,a).map(d=>d.ax),f=new Array(a).fill(o),p=f.map((d,h)=>h*o);return{id:e.id,label:e.label,kind:e.kind,time:l,distance:a*o,laps:1,lapTime:l,trace:{v:u,ax:m,ay:new Array(a).fill(0),s:p,x:p,y:new Array(a).fill(0),...c?{gear:c.gear.slice(0,a),rpm:c.rpm.slice(0,a),shifting:c.shifting.slice(0,a)}:{}},energy:xS(t,f,[...u,s[a].v],m,1)}}function C2(e,t){let r=Math.max(1,Math.round(e.laps??1)),[n]=Aa(t.ggv,[1/e.radius],t.numerics),o=2*Math.PI*e.radius,a=n.v>0?o/n.v:1/0,s=t.ggv.scrub?.(n.v,Math.abs(n.ay))??0,i=xS(t,[o],[n.v,n.v],[0],r,s!==0?{ay:[n.ay],scrub:[s]}:void 0);return{id:e.id,label:e.label,kind:e.kind,time:a*r,distance:o*r,laps:r,lapTime:a,energy:i}}function um(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 T2(e,t){let r=e.distance!=null?t.v_limit_endurance?.value??0:0;return r>0?r/3.6:void 0}function P2(e,t){if(e.distance==null||ft(t.motorModel))return 0;let r=t.endurance_reserve?.value??0;return r>0?Math.min(r,95)/100:0}var mS=1;function bS(e,t,r,n){return{v:r.v,ax:r.ax,ay:r.ay,ds:t.ds,axDrag:Ea(e.ggv.rows,r.v),...r.axScrub?{axScrub:r.axScrub}:{},axGrade:n,...t.bank?{bank:t.bank}:{}}}var pS=new WeakMap;function gS(e){let t=e.vehicle.params;if(!t.brakeFade)return null;let r=pS.get(t);if(r===void 0){let n=Hb(t),o=n?pt(t):null;if(!n||!o||o.mode!=="hydraulic")r=null;else{let a=Gb(t,e.vehicle),s=e.ggv.rows,i=cS(a.inp,a.ev,e.vehicle.vMax,{front:Yb(o.hydraulic.front.heat),rear:Yb(o.hydraulic.rear.heat)},c=>Ea(s,[c])[0]);r={discs:n,table:i}}pS.set(t,r)}return r}function L2(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=jb(e),u=(g,y)=>e.yaw?QM(e.yaw.family.atSoc(e.vehicle,o,a),t,e.yaw.car,e.numerics,{standingStart:s,...g?{driveDerate:g}:{},...y?{brakeFade:y}:{},...i?{vCeiling:i}:{},...c?{load:c}:{},...l?{shifts:l}:{}}):Rt(Ii(e.ggv,e.vehicle,o,a),t,e.numerics,{standingStart:s,...g?{driveDerate:g}:{},...y?{brakeFade:y}:{},...i?{vCeiling:i}:{},...c?{load:c}:{},...l?{shifts:l}:{}}),m=yn(t.gradient,t.npts),f=g=>n.motorThermal?yM(e.vehicle,t.ds,e.energyOpts??Dr,y=>u(y,g),o,a,m,t.bank).lap:u(void 0,g),p=gS(e);if(!p)return f();let d=Pi(n),h=r.discC??{front:d,rear:d};return lS(f,g=>{let y=zb(p.discs,Kb(n,bS(e,t,g,m),e.vehicle),g.v,t.ds,h,d);return{...y?.front?{front:y.front.padFactor}:{},...y?.rear?{rear:y.rear.padFactor}:{}}},p.table).lap}function D2(e,t){let r=T2(e,t.vehicle.params),n=P2(e,t.vehicle.params);return n>0?_2(e,t,n,r):_i(e,t,r)}function cm(e,t){let r=e.energy?.remainingFraction??0;return e.incomplete?-t-(1-e.incomplete.lapsCompleted/Math.max(1,e.incomplete.lapsAsked)):r-t}var dS=5,E2=.1,I2=.005,fS=12;function _2(e,t,r,n){let o=_i(e,t,n),a=1,s=(d,h,b)=>({...d,energyTarget:{reserve:r,capKmh:h===void 0?null:h*3.6,met:b,solves:a}}),i=cm(o,r);if(i>=0)return s(o,n,!0);let c=Math.min(n??1/0,t.ggv.vMax),l=c/2,u=_i(e,t,l);a++;let m=cm(u,r);for(;m<0&&l>dS&&a<fS;)c=l,i=m,l=Math.max(dS,l/2),u=_i(e,t,l),a++,m=cm(u,r);if(m<0)return s(u,l,!1);let f=l,p=0;for(;a<fS&&c-l>E2&&m>I2;){let d=c-l,h=Math.min(c-.05*d,Math.max(l+.05*d,l+m*d/(m-i))),b=_i(e,t,h);a++;let g=cm(b,r);g>=0?(l=h,m=g,u=b,f=h,p===1&&(i/=2),p=1):(c=h,i=g,p===-1&&(m/=2),p=-1)}return s(u,f,!0)}function yS(e,t,r){return r===0?e:e&&!t}function _i(e,t,r){let n=t.track;if(!n)throw new lm(`Event "${e.id}" needs a track.`);let o=um(e,n),a=e.standingStart??t.standingStart??!1,s=K=>yS(a,n.closed,K),i=t.vehicle.params,c=Rr(Fa(i)),l=c.capacityAh,u=i.soc.value,m=Pi(i),f=ju(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=Hb(i),L={front:m,rear:m},D=null,E=gS(t)!==null,V=(K,Y)=>E&&(Math.abs(K.front-Y.front)>mS||Math.abs(K.rear-Y.rear)>mS),N=(K,Y,j)=>{let Z=Tb(i,K,Y);if(D&&D.launch===j&&!V2(Z,D.pw)&&!V(L,D.discC))return D.lap;let ne=L2(t,n,{soc:K,packTempC:Y,launched:j,...r?{vCeiling:r}:{},...E?{discC:L}:{}});return D={pw:Z,launch:j,discC:L,lap:ne},ne},z=yn(n.gradient,n.npts),I=(K,Y,j)=>wa(t.vehicle,n.ds,K.v,K.ax,t.energyOpts,Y,j,void 0,z,void 0,{ay:K.ay,bank:n.bank,...K.axScrub?{scrub:K.axScrub}:{}}),_=new WeakMap,B=(K,Y)=>{let j=_.get(K);return j||(j=Kb(i,bS(t,n,K,z),t.vehicle),_.set(K,j)),zb(P,j,K.v,n.ds,Y,m)},O=(K,Y,j)=>{let Z=`${(100*j/n.npts).toFixed(0)} % of the way through lap ${K+1}`,ne=Y.cutoffAt>=0&&Y.cutoffAt<=Y.emptyAt;return{lapsCompleted:K,lapsAsked:o,why:ne?`the pack reached its ${c.voltageFloor.toFixed(0)} V cut-off ${Z}`:`the pack ran out ${Z}`}};for(let K=0;K<o;K++){if(u<=0){A={lapsCompleted:K,lapsAsked:o,why:"the pack was empty"};break}let Y=s(K),j=u,Z=f;x=!1,M=-1/0,F=0,w=0,C=-1/0;let ne=N(u,f,Y),te=I(ne,u,f);if(te.emptyAt>=0){A=O(K,te,te.emptyAt);break}let W=N(te.socEnd,te.tempEndC,Y).laptime-ne.laptime,J,re,pe,de,ie=f,oe=-1,ue=null,Be=1;if(W<=Wb)J=ne.laptime,re=te.net,pe=te.loss,de=te.chargeAh,ie=te.tempEndC,T(te,J),Be=1;else{let le=Math.min(N2,Math.max(2,Math.ceil(W/(2*Wb))));Be=le;let Re=u,Te=f;J=0,re=0,pe=0,de=0;for(let ze=0;ze<le;ze++){let je=N(Re,Te,Y),be=I(je,Re,Te),Fe=be.emptyAt>=0?be.emptyAt/n.npts:1;if(Fe*le<1){oe=Math.round(n.npts*(ze/le+Fe)),ue=be;break}if(J+=je.laptime/le,T(be,je.laptime/le,le),re+=be.net/le/Fe,pe+=be.loss/le/Fe,de+=be.chargeAh/le/Fe,Re-=be.chargeAh/le/Fe/l,Te+=(be.tempEndC-Te)/le,Re<=0){oe=Math.round(n.npts*(ze+1)/le),ue=be;break}}if(ie=Te,oe>=0&&ue){A=O(K,ue,oe);break}u=Re}p+=J,d+=re,h+=pe,b+=de,W<=Wb&&(u=te.socEnd),f=ie;let Ae=P?B(ne,L):null;Ae&&(L={front:Ae.front?.endC??L.front,rear:Ae.rear?.endC??L.rear}),g.push({lap:K+1,time:J,elapsed:p,entryTime:ne.laptime,socStart:j,socEnd:u,packTempStartC:Z,packTempEndC:f,packTempMaxC:Number.isFinite(C)?C:Z,energyKwh:re,lossKwh:pe,chargeAh:de,launched:Y,substeps:Be,...r?{vCeiling:r}:{},...x?{motor:{peakWindingC:M,derateTimeFrac:J>0?F/J:0,lossKwh:w}}:{},...Ae?{brakes:{...Ae.front?{front:hS(Ae.front)}:{},...Ae.rear?{rear:hS(Ae.rear)}:{}}}:{}}),S=ne}if(!S){let K=jb(t);S=Rt(Ii(t.ggv,t.vehicle,u),n,t.numerics,{standingStart:a,...t.load?{load:t.load.atSoc(t.vehicle,u)}:{},...K?{shifts:K}:{}}),A=A??{lapsCompleted:0,lapsAsked:o,why:"the pack was empty"}}let G=g.length;return{id:e.id,label:e.label,kind:e.kind,time:p,distance:n.length*G,laps:G,lapTime:S.laptime,trace:{v:S.v,ax:S.ax,ay:S.ay,s:n.s,x:n.x,y:n.y,...n.gradient.some(K=>K!==0)?{gradient:n.gradient}:{},...n.bank.some(K=>K!==0)?{bank:n.bank}:{},...n.z.some(K=>K!==0)?{z:n.z}:{},...n.mu.some(K=>K!==1)?{mu:n.mu}:{},...S.loadFactor?{loadFactor:S.loadFactor}:{},...S.axScrub?{axScrub:S.axScrub}:{},...F2(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 Wb=.05;function hS(e){let t=r=>e.workJ>0?r/e.workJ:0;return{startC:e.startC,endC:e.endC,maxC:e.maxC,workKj:e.workJ/1e3,coldShare:t(e.coldWorkJ),hotShare:t(e.hotWorkJ)}}var N2=4,O2=.001;function V2(e,t){return e===t?!1:!Number.isFinite(e)||!Number.isFinite(t)?!0:Math.abs(e-t)>O2*Math.max(1,Math.abs(t))}function xS(e,t,r,n,o,a){return B2(e,t,o,()=>({v:r,ax:n,...a?{lateral:a}:{}}))}function B2(e,t,r,n){let o=e.energyOpts,a=e.vehicle.params.soc.value,s=0,i=0,c=0;for(let l=0;l<r;l++){let u=n(l),m=wa(e.vehicle,t,u.v,u.ax,o,a,void 0,void 0,void 0,void 0,u.lateral);s+=m.net,i+=m.loss,c+=m.chargeAh,a=m.socEnd}return ft(e.vehicle.params.motorModel)?{consumed:s,loss:i,remainingFraction:1}:{consumed:s,loss:i,native:{value:c,unit:"Ah"},remainingFraction:a}}function RS(e,t){switch(e.kind){case"straightLineAccel":return w2(e,t);case"constantRadius":return C2(e,t);case"trackLap":return D2(e,t)}}function Ub(e,t){let r={};for(let n of e)r[n.id]=RS(n,t);return r}function vS(e,t){if(e.kind!=="trackLap")return e;let{distance:r,...n}=e;return{...n,laps:Math.max(1,Math.round(t))}}function ao(e,t,r,n,o="twoTrack",a){let s=1/0,i=-1/0;for(let f of r){let p=wi(f);if(!p)continue;let d=oM(p,Rt(t,f,n).v);d&&(s=Math.min(s,d.lo),i=Math.max(i,d.hi))}if(!(i>=s))return;let c=aM({lo:s,hi:i}),l=c.join(","),u=a?.get(l);if(u)return u;let m=oS(e,c,t,o);return a?.set(l,m),m}var Ni=e=>e.distance/Math.max(1,e.laps);function Oi(e){let t=e.s.length,r=new Array(t);for(let n=0;n<t;n++)r[n]=(n<t-1?e.s[n+1]:e.length)-e.s[n];return r}var $2=e=>e.v.map(t=>t*3.6),G2=e=>e.ax.map(t=>t/9.81),K2=e=>e.ay.map(t=>t/9.81),H2=e=>e.ay.map((t,r)=>e.v[r]>1e-6?t/(e.v[r]*e.v[r]):0),mm=(e,t,r)=>e?.slice()??new Array(t.s.length).fill(r),z2=e=>mm(e.z,e,0),Y2=e=>e.gradient?e.gradient.map(t=>100*Math.tan(t*Math.PI/180)):mm(void 0,e,0),W2=e=>mm(e.bank,e,0),j2=e=>mm(e.mu,e,1);function U2(e){let t=e.s.length,r=Oi(e),n=new Array(t);n[0]=0;for(let o=1;o<t;o++)n[o]=n[o-1]+2*r[o-1]/(e.v[o-1]+e.v[o]);return n}var Xb=[{name:"s",unit:"m",what:"distance along the lap"},{name:"ds",unit:"m",what:"length of the segment starting at this sample"},{name:"t",unit:"s",what:"elapsed time"},{name:"v",unit:"m/s",what:"speed"},{name:"speed",unit:"km/h",what:"speed"},{name:"ax",unit:"m/s\xB2",what:"longitudinal acceleration"},{name:"ay",unit:"m/s\xB2",what:"lateral acceleration"},{name:"axg",unit:"g",what:"longitudinal acceleration"},{name:"ayg",unit:"g",what:"lateral acceleration"},{name:"curv",unit:"1/m",what:"signed curvature, ay/v\xB2"},{name:"z",unit:"m",what:"elevation of the road"},{name:"grade",unit:"%",what:"grade of the road, uphill +"},{name:"bank",unit:"\xB0",what:"bank of the road, left side up +"},{name:"grip",unit:"-",what:"grip scale of the road, 1 = the tyre\u2019s own"}];function kS(e){let t=Oi(e);return{ds:t,vars:{s:e.s,ds:t,t:U2(e),v:e.v,speed:$2(e),ax:e.ax,ay:e.ay,axg:G2(e),ayg:K2(e),curv:H2(e),z:z2(e),grade:Y2(e),bank:W2(e),grip:j2(e)}}}function MS(e,t){return{v:e.v,ax:e.ax,ay:e.ay,ds:Oi({s:e.s,length:t}),axGrade:yn(e.gradient,e.v.length),...e.bank?{bank:e.bank}:{},...e.loadFactor?{loadFactor:e.loadFactor}:{}}}function SS(e,t){let r=dt(e);return{pastTurnover:HM(r,mr(e),t),...e.aeroModel?{aeroOutside:KM(r,t)}:{}}}var pm="Flying lap";function Qb(e,t){return e.kind!=="trackLap"||e.label!==pm?e.label:e.standingStart??t?"Run":e.label}function X2(e){let t=dt(e);return{yawInertia:t.yawInertia??0,massTotal:t.massTotal,wheelbase:t.wheelbase/1e3}}function Q2(e,t,r){let n=e.params,o=n.ggvMode??"twoTrack",a=n.quasiTransient?nS(e,!1,o):null,s=a?a.steady:pr(e,!1,o),i=t?ao(e,s,[t],r,o):void 0;return{ggv:s,...a?{yaw:{family:a,car:X2(n)}}:{},...i?{load:i}:{}}}function q2(e,t){let r=t.lapCounts,n=t.standingStart??!1,o=!1,a=e.events.map(s=>{let i=r?.[s.id]!=null?vS(s,r[s.id]):s,c=Qb(i,n),l=c===i.label?i:{...i,label:c};return l!==s&&(o=!0),l});return o?a:e.events}function Z2(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=um(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 J2(e,t){for(let[r,n]of Object.entries(e))n.trace&&(e[r]={...n,...SS(t,MS(n.trace,Ni(n)))})}function Vi(e,t,r={}){let n=wt(e),o=Q2(n,r.track,r.numerics),{ggv:a}=o,s=Ub(q2(t,r),{vehicle:n,...o,track:r.track,energyOpts:Er(e,r.energyOpts),numerics:r.numerics,standingStart:r.standingStart});return Z2(s,t,r),J2(s,n.params),{name:e.name,rulesetId:t.id,events:s,ggv:a}}function qb(e){return{...e,ggv:{rows:e.ggv.rows,vMax:e.ggv.vMax,surf:e.ggv.surf}}}var Zb=["<","<=",">",">=","==","!="],Ne=class extends Error{at;constructor(t,r){super(t),this.name="ExprError",this.at=r}},Bi=e=>e>="0"&&e<="9",AS=e=>/[A-Za-z_]/.test(e),e_=e=>/[A-Za-z0-9_]/.test(e);function t_(e){let t=[],r=0;for(;r<e.length;){let n=e[r];if(n===" "||n===" "||n===`
224
+ `||n==="\r"){r++;continue}if(Bi(n)||n==="."&&Bi(e[r+1]??"")){let o=r;for(;r<e.length&&(Bi(e[r])||e[r]===".");)r++;if(e[r]==="e"||e[r]==="E"){let i=r;if(r++,(e[r]==="+"||e[r]==="-")&&r++,Bi(e[r]??""))for(;r<e.length&&Bi(e[r]);)r++;else r=i}let a=e.slice(o,r),s=Number(a);if(!Number.isFinite(s))throw new Ne(`"${a}" is not a number`,o);t.push({t:"num",value:s,at:o});continue}if(AS(n)){let o=r;for(;;){for(;r<e.length&&e_(e[r]);)r++;if(e[r]==="."&&AS(e[r+1]??""))r++;else break}t.push({t:"name",value:e.slice(o,r),at:o});continue}if("<>=!".includes(n)){let o=e.slice(r,r+2);if(Zb.includes(o)){t.push({t:"op",value:o,at:r}),r+=2;continue}if(n==="<"||n===">"){t.push({t:"op",value:n,at:r}),r++;continue}throw new Ne(n==="="?'Compare with "==", not "="':'Write not(x) rather than "!x"',r)}if("+-*/^(),".includes(n)){t.push({t:"op",value:n,at:r}),r++;continue}throw new Ne(`"${n}" is not something this expression can contain`,r)}return t.push({t:"end",at:e.length}),t}function Jb(e){let t=t_(e),r=0,n=()=>t[r],o=h=>{let b=n();return b.t==="op"&&b.value===h},a=h=>o(h)?(r++,!0):!1,s=(h,b)=>{if(!a(h))throw new Ne(`Expected ${b} here`,n().at)};function i(){let h=c(),b=n();if(b.t!=="op"||!Zb.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"&&Zb.includes(y.value))throw new Ne("Comparisons do not chain \u2014 write and(a < b, b < c)",y.at);return g}function c(){let h=l();for(;;){let b=n().at;if(a("+"))h={kind:"binary",op:"+",left:h,right:l(),at:b};else if(a("-"))h={kind:"binary",op:"-",left:h,right:l(),at:b};else return h}}function l(){let h=u();for(;;){let b=n().at;if(a("*"))h={kind:"binary",op:"*",left:h,right:u(),at:b};else if(a("/"))h={kind:"binary",op:"/",left:h,right:u(),at:b};else return h}}function u(){return a("-")?{kind:"unary",op:"-",arg:u()}:a("+")?u():m()}function m(){let h=f(),b=n().at;return a("^")?{kind:"binary",op:"^",left:h,right:u(),at:b}:h}function f(){let h=n();if(h.t==="num")return r++,{kind:"num",value:h.value};if(h.t==="name"){if(r++,a("(")){let b=[];if(!o(")"))do b.push(i());while(a(","));return s(")","a closing bracket"),{kind:"call",name:h.value,args:b,at:h.at}}return{kind:"var",name:h.value,at:h.at}}if(a("(")){let b=i();return s(")","a closing bracket"),b}throw h.t==="end"?new Ne("The expression ends before it is finished",h.at):new Ne(`"${h.value}" cannot start a value`,h.at)}let p=i(),d=n();if(d.t!=="end")throw new Ne(`"${d.value}" is left over \u2014 check for a missing operator`,d.at);return p}function eg(e){let t=new Set,r=n=>{n.kind==="var"?t.add(n.name):n.kind==="call"?n.args.forEach(r):n.kind==="unary"?r(n.arg):n.kind==="binary"&&(r(n.left),r(n.right))};return r(e),t}var $i=(e,t)=>typeof e=="number"?new Array(t).fill(e):e;function r_(e){let t=1;for(let r of e)Array.isArray(r)&&(t=Math.max(t,r.length));return t}function Pt(e,t){if(e.every(a=>typeof a=="number"))return t(...e);let r=r_(e),n=e.map(a=>$i(a,r)),o=new Array(r);for(let a=0;a<r;a++)o[a]=t(...n.map(s=>s[Math.min(a,s.length-1)]));return o}var Oe=(e,t)=>({arity:e,call:r=>Pt(r,t)}),so=e=>e!==0&&!Number.isNaN(e),dr=e=>e?1:0;function FS(e,t,r){let n=wS(t,r,"integrate"),o=n.length,a=$i(e,o),s=new Array(o),i=0;for(let c=0;c<o;c++){s[c]=i;let l=a[Math.min(c,a.length-1)],u=a[Math.min(c+1,a.length-1)];i+=(l+u)/2*n[c]}return s}function wS(e,t,r){if(!e.ds||e.ds.length===0)throw new Ne(`${r}() needs to know the sample spacing, and this context has none`,t);return e.ds}var dm={abs:Oe(1,Math.abs),sqrt:Oe(1,Math.sqrt),sign:Oe(1,Math.sign),floor:Oe(1,Math.floor),ceil:Oe(1,Math.ceil),round:Oe(1,Math.round),exp:Oe(1,Math.exp),log:Oe(1,Math.log),sin:Oe(1,Math.sin),cos:Oe(1,Math.cos),tan:Oe(1,Math.tan),atan:Oe(1,Math.atan),atan2:Oe(2,Math.atan2),hypot:Oe(2,Math.hypot),min:Oe(2,Math.min),max:Oe(2,Math.max),clamp:Oe(3,(e,t,r)=>Math.min(r,Math.max(t,e))),if:Oe(3,(e,t,r)=>so(e)?t:r),and:Oe(2,(e,t)=>dr(so(e)&&so(t))),or:Oe(2,(e,t)=>dr(so(e)||so(t))),not:Oe(1,e=>dr(!so(e))),finite:Oe(1,e=>dr(Number.isFinite(e))),peak:{arity:1,call:([e])=>{let t=Array.isArray(e)?e:[e],r=0;for(let n of t)r=Math.max(r,Math.abs(n));return r}},mean:{arity:1,call:([e])=>{let t=Array.isArray(e)?e:[e];return t.length?t.reduce((r,n)=>r+n,0)/t.length:0}},total:{arity:1,call:([e],t)=>{let r=FS(e,t,0),n=t.ds,o=$i(e,n.length),a=n.length-1;return r[a]+(o[a]+o[0])/2*n[a]}},integrate:{arity:1,call:([e],t)=>FS(e,t,0)},cum:{arity:1,call:([e],t)=>{let r=t.ds?.length??(Array.isArray(e)?e.length:1),n=$i(e,r),o=new Array(r),a=0;for(let s=0;s<r;s++)a+=n[Math.min(s,n.length-1)],o[s]=a;return o}},deriv:{arity:1,call:([e],t)=>{let r=wS(t,0,"deriv"),n=r.length,o=$i(e,n),a=new Array(n);for(let s=0;s<n;s++){let i=Math.max(0,s-1),c=Math.min(n-1,s+1),l=0;for(let u=i;u<c;u++)l+=r[u];a[s]=l>0?(o[c]-o[i])/l:0}return a}}},Ia={g:9.81,pi:Math.PI,e:Math.E,nan:NaN,inf:1/0},Gi={fleetmin:"min",fleetmax:"max"};function io(e){switch(e.kind){case"call":return Object.hasOwn(Gi,e.name)||e.args.some(io);case"unary":return io(e.arg);case"binary":return io(e.left)||io(e.right);default:return!1}}var n_=e=>typeof e=="number"?`${e}`:`between ${e[0]} and ${e[1]}`;function o_(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 a_(e,t){let r=t.map(c=>({k:c,d:o_(c,e)})).filter(c=>c.d<=Math.max(1,Math.floor(e.length/4))),n=Math.min(...r.map(c=>c.d)),o=r.filter(c=>c.d===n).map(c=>c.k).slice(0,3);if(o.length)return`"${e}" is not a name here \u2014 did you mean ${o.join(" or ")}?`;let a=e.indexOf(".");if(a>0){let c=t.filter(l=>l.startsWith(e.slice(0,a+1)));if(c.length)return`"${e}" is not a name here. ${e.slice(0,a)} has ${c.join(", ")}`}let s=new Set,i=[];for(let c of t){let l=c.indexOf(".");l>0?s.add(`${c.slice(0,l)}.\u2026`):i.push(c)}return`"${e}" is not a name here. Available: ${[...s,...i].join(", ")}`}function fr(e,t){switch(e.kind){case"num":return e.value;case"var":{if(Object.hasOwn(t.vars,e.name))return t.vars[e.name];if(Object.hasOwn(Ia,e.name))return Ia[e.name];let r=[...Object.keys(t.vars),...Object.keys(Ia)].sort();throw new Ne(a_(e.name,r),e.at)}case"unary":return Pt([fr(e.arg,t)],r=>-r);case"binary":{let r=fr(e.left,t),n=fr(e.right,t);switch(e.op){case"+":return Pt([r,n],(o,a)=>o+a);case"-":return Pt([r,n],(o,a)=>o-a);case"*":return Pt([r,n],(o,a)=>o*a);case"/":return Pt([r,n],(o,a)=>a===0?0:o/a);case"^":return Pt([r,n],(o,a)=>o**a);case"<":return Pt([r,n],(o,a)=>dr(o<a));case"<=":return Pt([r,n],(o,a)=>dr(o<=a));case">":return Pt([r,n],(o,a)=>dr(o>a));case">=":return Pt([r,n],(o,a)=>dr(o>=a));case"==":return Pt([r,n],(o,a)=>dr(o===a));case"!=":return Pt([r,n],(o,a)=>dr(o!==a))}break}case"call":{let r=Object.hasOwn(Gi,e.name)?Gi[e.name]:void 0;if(r){if(!t.fleet)throw new Ne(`${e.name}() compares the cars in a field, so it belongs in a ruleset's KPIs, not in a channel`,e.at);if(e.args.length!==1)throw new Ne(`${e.name}() takes 1 argument, not ${e.args.length}`,e.at);return t.fleet(e.args[0],r,e.at)}let n=Object.hasOwn(dm,e.name)?dm[e.name]:void 0;if(!n){let s=[...Object.keys(dm),...t.fleet?Object.keys(Gi):[]];throw new Ne(`There is no function called "${e.name}". Available: ${s.sort().join(", ")}`,e.at)}let o=typeof n.arity=="number"?n.arity:n.arity[0],a=typeof n.arity=="number"?n.arity:n.arity[1];if(e.args.length<o||e.args.length>a)throw new Ne(`${e.name}() takes ${n_(n.arity)} argument${o===1&&a===1?"":"s"}, not ${e.args.length}`,e.at);return n.call(e.args.map(s=>fr(s,t)),t)}}throw new Ne("Unreachable node",0)}var _a=e=>Number.isFinite(e)?e:NaN,tg=[{name:"time",unit:"s",what:"the whole event, every lap",read:e=>_a(e?.time)},{name:"lapTime",unit:"s",what:"one lap \u2014 the last one completed",read:e=>_a(e?.lapTime)},{name:"distance",unit:"m",what:"distance covered",read:e=>_a(e?.distance)},{name:"laps",unit:"-",what:"laps completed",read:e=>_a(e?.laps)},{name:"energy",unit:"kWh",what:"energy drawn over the event",read:e=>_a(e?.energy?.consumed)},{name:"remaining",unit:"-",what:"share of the pack or tank left afterwards",read:e=>_a(e?.energy?.remainingFraction)},{name:"finished",unit:"-",what:"1 when the car ran the whole event, else 0",read:e=>e&&!e.incomplete?1:0}],CS=/^[A-Za-z_][A-Za-z0-9_]*$/,s_=new Set([...Object.keys(Ia),...Xb.map(e=>e.name)]);function fm(e,t,r=[]){let n=[],o=new Set(r),a=t.map(b=>b.id),s=new Set;for(let b of a)CS.test(b)?s.has(b)&&n.push({key:null,message:`Two events are called "${b}"`}):n.push({key:null,message:`Event id "${b}" must be one word to be read as ${b}.time`}),s.add(b);let i=new Map,c=new Map;for(let b of e){if(!CS.test(b.key)){n.push({key:b.key,message:`"${b.key}" must be one word \u2014 letters, digits and _`});continue}if(s_.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,Jb(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,[...eg(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=i_(b,l);n.push({key:b,message:g?`"${b}" depends on itself, through ${g.join(" \u2192 ")}`:`"${b}" reads a KPI that depends on itself`})}let f=(b,g,y)=>{throw new Ne("fleetmin() and fleetmax() cannot sit inside one another",y)},p=new Set,d={};for(let b of a)for(let g of tg)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 Xb)h[b.name]=[1,1];for(let b of m){let g=i.get(b),y=c.get(b);(io(y)||l.get(b).some(x=>p.has(x)))&&p.add(b);let R=g.over!=null?{...d,...h}:d,k=g.over!=null?[1,1]:void 0,v=(x,M,F)=>{let w=fr(x,{vars:R,ds:k,fleet:f});if(Array.isArray(w))throw new Ne("fleetmin() and fleetmax() compare one number per car \u2014 reduce the channel first, e.g. peak(v)",F);return w};try{let x=fr(y,{vars:R,ds:k,fleet:v});Array.isArray(x)&&n.push({key:b,message:"A KPI is one number per car \u2014 reduce the channel, e.g. peak(v) or mean(v)",at:0})}catch(x){let M=x;n.push({key:b,message:M.message,at:M.at})}}return n.length?{plan:null,problems:n}:{plan:{order:m.map(b=>({def:i.get(b),node:c.get(b)})),field:p,eventIds:a},problems:n}}function i_(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 c_(e,t,r={}){let n={...r};for(let o of e.eventIds){let a=t.events[o];for(let s of tg)n[`${o}.${s.name}`]=s.read(a)}return{vars:n,laps:new Map,events:t.events}}function TS(e,t){if(t.over==null)return{vars:e.vars};let r=e.laps.get(t.over);if(r===void 0){let n=e.events[t.over];r=n?.trace?kS({...n.trace,length:Ni(n)}):null,e.laps.set(t.over,r)}return r?{vars:{...e.vars,...r.vars},ds:r.ds}:null}var PS=e=>Array.isArray(e)?NaN:e;function LS(e,t,r,n={}){let o=Object.keys(t),a=o.map(i=>c_(e,t[i],n[i]));for(let{def:i,node:c}of e.order){let l=e.field.has(i.key);if(l&&!r){for(let f of a)f.vars[i.key]=NaN;continue}let u=new Map,m=(f,p)=>{let d=u.get(f);if(d!==void 0)return d;let h=NaN;for(let b of a){let g=TS(b,i);if(!g)continue;let y=PS(fr(f,g));Number.isFinite(y)&&(Number.isNaN(h)||(p==="min"?y<h:y>h))&&(h=y)}return u.set(f,h),h};for(let f of a){let p=TS(f,i);f.vars[i.key]=p?PS(fr(c,l?{...p,fleet:m}:p)):NaN}}let s={};return o.forEach((i,c)=>{let l={};for(let{def:u}of e.order)l[u.key]=a[c].vars[u.key];s[i]=l}),s}function Ki(e,t,r){return LS(e,t,!0,r)}function rg(e,t,r){return LS(e,{car:t},!1,r?{car:r}:void 0).car}var hm=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}},zi=e=>typeof e=="number"&&Number.isFinite(e),Hi=e=>zi(e)&&e>0,Pt=(e,t)=>e===void 0||t(e);function c_(e){let t=[],r=(o,a=null)=>t.push({key:a,message:o});if(typeof e.id!="string"||e.id===""?r("A ruleset needs an id"):/^[A-Za-z0-9_-]+$/.test(e.id)||r(`The id "${e.id}" is letters, digits, "-" and "_" only`),typeof e.label!="string"&&r("A ruleset needs a label"),typeof e.description!="string"&&r("A ruleset needs a description, even an empty one"),Array.isArray(e.events)||r("A ruleset\u2019s events are a list"),Array.isArray(e.kpis)||r("A ruleset\u2019s KPIs are a list"),t.length)return t;for(let o of e.events){let a=o,s=typeof a?.id=="string"?`Event "${a.id}"`:"An event";if(typeof a!="object"||a===null||typeof a.id!="string"||typeof a.label!="string"){r(`${s} needs an id and a label`);continue}switch(a.kind){case"straightLineAccel":Hi(a.distance)||r(`${s} needs a distance above zero, in metres`),Pt(a.vStart,i=>zi(i)&&i>=0)||r(`${s}'s entry speed must be zero or more`);break;case"constantRadius":Hi(a.radius)||r(`${s} needs a radius above zero, in metres`),Pt(a.laps,i=>zi(i)&&i>=1)||r(`${s} runs at least one lap`);break;case"trackLap":Pt(a.laps,i=>zi(i)&&i>=1)||r(`${s} runs at least one lap`),Pt(a.distance,Hi)||r(`${s}'s distance must be above zero, in metres`),Pt(a.standingStart,i=>typeof i=="boolean")||r(`${s}'s standing start is yes or no`);break;default:r(`${s} is of a kind this build does not run: ${String(a.kind)}`)}}for(let o of e.kpis){let a=o;if(typeof a!="object"||a===null||typeof a.key!="string"){r("A KPI needs a key");continue}let s=a.key;typeof a.expr!="string"&&r("Needs a formula",s),typeof a.label!="string"&&r("Needs a label",s),Pt(a.unit,i=>typeof i=="string")||r("Its unit is text",s),Pt(a.over,i=>typeof i=="string")||r("Names its event by id",s),Pt(a.format,i=>i==="time"||i==="points")||r("Is shown as a time, as points, or as a number",s),Pt(a.max,zi)||r("Its maximum is a number",s),Pt(a.lowerBetter,i=>typeof i=="boolean")||r("Lower is better, or it is not",s),Pt(a.hidden,i=>typeof i=="boolean")||r("Is hidden, or it is not",s)}Pt(e.track?.minTurnRadius,Hi)||r("The tightest turn the rules allow is a radius above zero");let n=e.battery;for(let o of["packVoltageMax","segmentVoltageMax","powerLimitKw"])Pt(n?.[o],Hi)||r(`The pack's ${o} must be above zero`);if(e.score!==void 0){let o=e.score?.parts;typeof e.score?.total!="string"||typeof o!="object"||o===null||Array.isArray(o)?r("The score names its total and its parts"):Object.values(o).every(a=>typeof a=="string")||r("Each part of the score names a KPI")}return t}function DS(e){let t=c_(e);if(t.length)return{plan:null,problems:t};let r=[];e.events.length===0&&r.push({key:null,message:"A ruleset runs at least one event"});let n=e.events.map(i=>i.id);e.traceEventId!=null&&!n.includes(e.traceEventId)&&r.push({key:null,message:`The plotted event "${e.traceEventId}" is not one of this ruleset's events`});let{plan:o,problems:a}=dm(e.kpis,e.events);r.push(...a);let s=new Set(e.kpis.map(i=>i.key));if(e.score){s.has(e.score.total)||r.push({key:null,message:`The total "${e.score.total}" is not one of this ruleset's KPIs`});let i=Object.entries(e.score.parts);i.length===0&&r.push({key:null,message:"A ruleset that awards points names at least one part"});for(let[c,l]of i)s.has(l)||r.push({key:null,message:`The part "${c}" reads "${l}", which is not one of this ruleset's KPIs`})}return{plan:r.length?null:o,problems:r}}function hm(e){return DS(e).problems}var tg=e=>Number.isFinite(e)?e:NaN;function l_(e){return e.unit&&e.format!=="time"?`${e.label} (${e.unit})`:e.label}function Rn(e){let t=structuredClone(e),{plan:r,problems:n}=DS(t);if(!r)throw new fm(t.id,n);let o=new WeakMap,a=p=>{let d=o.get(p);return d||(d=eg(r,p),o.set(p,d)),d},s=new Map(t.kpis.map(p=>[p.key,p])),i=new Map;for(let[p,d]of Object.entries(t.score?.parts??{}))i.has(d)||i.set(d,p);let c=p=>(d,h)=>{if(!h)return NaN;let b=h.kpis?.[p];if(b!==void 0)return tg(b);let g=h,y=i.get(p);return y!==void 0?tg(g.parts?.[y]):p===t.score?.total?tg(g.total):NaN},l=t.kpis.filter(p=>!p.hidden).map(p=>{let d=r.field.has(p.key);return{key:p.key,label:l_(p),lowerBetter:p.lowerBetter??!1,...p.format?{format:p.format}:{},...d?{field:!0}:{},value:d?c(p.key):h=>a(h)[p.key]}}),u=t.score,m=u?p=>{let d=Ki(r,p),h={};for(let[b,g]of Object.entries(d)){let y={},R={};for(let[k,v]of Object.entries(u.parts)){y[k]=g[v];let x=s.get(v)?.max;x!=null&&(R[k]=x)}h[b]={total:g[u.total],parts:y,...Object.keys(R).length?{maxima:R}:{},kpis:Object.fromEntries(t.kpis.map(k=>[k.key,g[k.key]]))}}return h}:void 0,f=m||(r.field.size>0?p=>{let d=Ki(r,p),h={};for(let[b,g]of Object.entries(d))h[b]={kpis:Object.fromEntries(t.kpis.map(y=>[y.key,g[y.key]]))};return h}:void 0);return{id:t.id,label:t.label,description:t.description,events:t.events,metrics:l,...t.track?{track:t.track}:{},...t.battery?{battery:t.battery}:{},...t.traceEventId?{traceEventId:t.traceEventId}:{},...m?{score:m}:{},...f?{field:f}:{},definition:t}}var Ut={accel:"accel",skidpad:"skidpad",autocross:"autocross",endurance:"endurance"},ES=[{kind:"straightLineAccel",id:Ut.accel,label:"Acceleration (75 m)",distance:75},{kind:"constantRadius",id:Ut.skidpad,label:"Skidpad",radius:8.375},{kind:"trackLap",id:Ut.autocross,label:"Autocross (1 lap)",laps:1},{kind:"trackLap",id:Ut.endurance,label:"Endurance (22 km)",distance:22e3}],IS=[{key:"autocross",label:"Autocross lap",format:"time",lowerBetter:!0,expr:"autocross.time"},{key:"accel",label:"Acceleration",format:"time",lowerBetter:!0,expr:"accel.time"},{key:"skidpad",label:"Skidpad lap",format:"time",lowerBetter:!0,expr:"skidpad.lapTime"},{key:"endurance",label:"Endurance",format:"time",lowerBetter:!0,expr:"endurance.time"},{key:"energy",label:"Energy",unit:"kWh",lowerBetter:!0,expr:"endurance.energy"},{key:"overall",label:"Overall",unit:"pts",format:"points",expr:"accelPts + skidpadPts + autocrossPts + endurancePts + efficiencyPts"},{key:"endurancePts",label:"Endurance",unit:"pts",format:"points",max:250,expr:"if(finite(finishedEndurance), 0.9 * 250 * ((1.333 * fleetmin(finishedEndurance) / min(finishedEndurance, 1.333 * fleetmin(finishedEndurance)) - 1) / 0.333) + 0.1 * 250, 0)"},{key:"efficiencyPts",label:"Efficiency",unit:"pts",format:"points",max:100,expr:"if(and(finite(finishedEndurance), finishedEndurance <= 1.333 * fleetmin(finishedEndurance)), 100 * ((1.5 * fleetmin(efficiencyFactor) - min(1.5 * fleetmin(efficiencyFactor), efficiencyFactor)) / (1.5 * fleetmin(efficiencyFactor) - fleetmin(efficiencyFactor))), 0)"},{key:"finishedEndurance",label:"Endurance, if finished",unit:"s",hidden:!0,expr:"if(endurance.finished, endurance.time, nan)"},{key:"efficiencyFactor",label:"Efficiency factor",unit:"s\xB2\xB7kWh",hidden:!0,expr:"finishedEndurance ^ 2 * endurance.energy"},{key:"accelPts",label:"Acceleration",unit:"pts",format:"points",max:75,hidden:!0,expr:"0.95 * 75 * ((1.5 * fleetmin(accel) / min(accel, 1.5 * fleetmin(accel)) - 1) / 0.5) + 0.05 * 75"},{key:"skidpadPts",label:"Skidpad",unit:"pts",format:"points",max:75,hidden:!0,expr:"0.95 * 75 * (((1.25 * fleetmin(skidpad) / min(skidpad, 1.25 * fleetmin(skidpad))) ^ 2 - 1) / 0.5625) + 0.05 * 75"},{key:"autocrossPts",label:"Autocross",unit:"pts",format:"points",max:100,hidden:!0,expr:"0.95 * 100 * ((1.25 * fleetmin(autocross) / min(autocross, 1.25 * fleetmin(autocross)) - 1) / 0.25) + 0.05 * 100"}],_S={total:"overall",parts:{[Ut.accel]:"accelPts",[Ut.skidpad]:"skidpadPts",[Ut.autocross]:"autocrossPts",[Ut.endurance]:"endurancePts",efficiency:"efficiencyPts"}},NS={id:"fs-ev",label:"Formula Student \u2014 Electric",description:"The four dynamic events (acceleration, skidpad, autocross, endurance) scored on the Formula Student point table, with efficiency from battery energy.",events:ES,kpis:IS,score:_S,track:{minTurnRadius:4.5},battery:qy,traceEventId:Ut.autocross},OS={id:"fs-cv",label:"Formula Student \u2014 Combustion",description:"Same events and point table as the electric class. An engine car\u2019s efficiency is scored on the work at its crankshaft until its fuel is modelled; an electric car\u2019s on its pack.",events:ES,kpis:IS,score:_S,track:{minTurnRadius:4.5},traceEventId:Ut.autocross},Yi=Rn(NS),rg=Rn(OS);var ng="lap",u_=[{kind:"trackLap",id:ng,label:mm,laps:1}],VS={id:"trackday",label:"Track day",description:"One flying lap of the selected track. Times and traces only \u2014 no scoring.",events:u_,kpis:[{key:"lap",label:"Lap time",format:"time",lowerBetter:!0,expr:"lap.time"},{key:"topSpeed",label:"Top speed",unit:"km/h",over:ng,expr:"peak(speed)"},{key:"energy",label:"Energy / lap",unit:"kWh",lowerBetter:!0,expr:"lap.energy"}],traceEventId:ng},og=Rn(VS);function vn(e){if(e===null||typeof e!="object")return JSON.stringify(e)??"null";if(Array.isArray(e))return`[${e.map(vn).join(",")}]`;let t=e,r=Object.keys(t).sort(),n=[];for(let o of r)t[o]!==void 0&&n.push(`${JSON.stringify(o)}:${vn(t[o])}`);return`{${n.join(",")}}`}function co(e){let t=vn(e),r=2166136261;for(let n=0;n<t.length;n++)r^=t.charCodeAt(n),r=r+((r<<1)+(r<<4)+(r<<7)+(r<<8)+(r<<24))>>>0;return r.toString(16).padStart(8,"0").slice(-6)}var Na=[Yi,rg,og],lo=Yi.id,Oa=e=>Na.some(t=>t.id===e),BS=new WeakMap,Wi=new Map,m_=64;function bm(e){let t=BS.get(e);if(t!==void 0)return t;let r=vn(e),n=Wi.get(r);return n===void 0&&(n=hm(e).length?null:Rn(e),Wi.size>=m_&&Wi.delete(Wi.keys().next().value),Wi.set(r,n)),BS.set(e,n),n}function gm(e,t=[]){if(e==null)return;if(typeof e!="string")return bm(e)??void 0;let r=Na.find(o=>o.id===e);if(r)return r;let n=t.find(o=>o.id===e);return n?bm(n)??void 0:void 0}function uo(e,t=[]){return gm(e,t)??Yi}function ag(e=[]){let t=e.filter(r=>!Oa(r.id)).map(r=>bm(r)).filter(r=>r!==null);return[...Na,...t]}var ji=e=>e.definition??e.id;function ym(e,t,r){let n=e.length,o=new Array(n);for(let d=0;d<n;d++){let h=d+1<n?e[d+1]:r;o[d]=h-e[d]}let a=new Array(n).fill(0),s=new Array(n).fill(0),i=new Array(n).fill(0),c=new Array(n).fill(0);for(let d=0;d<n;d++){let h=o[(d-1+n)%n],b=o[d];a[d]=h,s[d]=2*(h+b),i[d]=b;let g=t[(d+1)%n],y=t[(d-1+n)%n];c[d]=6*((g-t[d])/b-(t[d]-y)/h)}let l=p_(a,s,i,c),u=new Array(n),m=new Array(n),f=new Array(n),p=new Array(n);for(let d=0;d<n;d++){let h=o[d],b=l[d],g=l[(d+1)%n],y=t[d],R=t[(d+1)%n];u[d]=y,f[d]=b/2,p[d]=(g-b)/(6*h),m[d]=(R-y)/h-h*(2*b+g)/6}return{n,eval:(d,h)=>u[d]+h*(m[d]+h*(f[d]+h*p[d])),d1:(d,h)=>m[d]+h*(2*f[d]+h*3*p[d]),d2:(d,h)=>2*f[d]+h*6*p[d]}}function ig(e,t){let r=e.length,n=r-1,o=new Array(n);for(let u=0;u<n;u++)o[u]=e[u+1]-e[u];let a=new Array(r).fill(0);if(r>2){let u=r-2,m=new Array(u).fill(0),f=new Array(u).fill(0),p=new Array(u).fill(0),d=new Array(u).fill(0);for(let g=0;g<u;g++){let y=g+1;m[g]=o[y-1],f[g]=2*(o[y-1]+o[y]),p[g]=o[y],d[g]=6*((t[y+1]-t[y])/o[y]-(t[y]-t[y-1])/o[y-1])}let h=n>=3;if(h){let g=o[0]/o[1];f[0]+=o[0]*(1+g),p[0]-=o[0]*g;let y=o[n-1]/o[n-2];f[u-1]+=o[n-1]*(1+y),m[u-1]-=o[n-1]*y}let b=sg(m,f,p,d);for(let g=0;g<u;g++)a[g+1]=b[g];h&&(a[0]=(1+o[0]/o[1])*a[1]-o[0]/o[1]*a[2],a[r-1]=(1+o[n-1]/o[n-2])*a[r-2]-o[n-1]/o[n-2]*a[r-3])}let s=new Array(n),i=new Array(n),c=new Array(n),l=new Array(n);for(let u=0;u<n;u++)s[u]=t[u],c[u]=a[u]/2,l[u]=(a[u+1]-a[u])/(6*o[u]),i[u]=(t[u+1]-t[u])/o[u]-o[u]*(2*a[u]+a[u+1])/6;return{n,eval:(u,m)=>s[u]+m*(i[u]+m*(c[u]+m*l[u])),d1:(u,m)=>i[u]+m*(2*c[u]+m*3*l[u]),d2:(u,m)=>2*c[u]+m*6*l[u]}}function p_(e,t,r,n){let o=t.length;if(o===1)return[n[0]/(t[0]+e[0]+r[0])];if(o===2){let d=t[0],h=r[0]+e[0],b=e[1]+r[1],g=t[1],y=d*g-h*b;return[(n[0]*g-h*n[1])/y,(d*n[1]-n[0]*b)/y]}let a=e[0],s=r[o-1],i=-t[0]||1e-30,c=t.slice();c[0]=t[0]-i,c[o-1]=t[o-1]-a*s/i;let l=sg(e,c,r,n),u=new Array(o).fill(0);u[0]=i,u[o-1]=s;let m=sg(e,c,r,u),f=(l[0]+a*l[o-1]/i)/(1+m[0]+a*m[o-1]/i),p=new Array(o);for(let d=0;d<o;d++)p[d]=l[d]-f*m[d];return p}function sg(e,t,r,n){let o=t.length,a=new Array(o),s=new Array(o);a[0]=r[0]/t[0],s[0]=n[0]/t[0];for(let c=1;c<o;c++){let l=t[c]-e[c]*a[c-1];a[c]=r[c]/l,s[c]=(n[c]-e[c]*s[c-1])/l}let i=new Array(o);i[o-1]=s[o-1];for(let c=o-2;c>=0;c--)i[c]=s[c]-a[c]*i[c+1];return i}function Ui(e){let t=e.z;if(!Array.isArray(t)||t.length<2)return null;let r=e.closed!==!1,n=e.x.length,o=r?n:n-1,a=[0];for(let l=0;l<o;l++){let u=(l+1)%n;a.push(a[l]+Math.hypot(e.x[u]-e.x[l],e.y[u]-e.y[l]))}let s=a[o],i=t.length,c=i===n?a.slice(0,n):Array.from({length:i},(l,u)=>r?u/i*s:u/(i-1)*s);return{z:t,pos:c,length:s,closed:r}}function $S(e,t,r){let n=e.pos[r]-e.pos[t];return e.closed?n>e.length/2?n-e.length:n<-e.length/2?n+e.length:n:n}function GS(e,t){let[r,n,o,a,s,i]=e,c=a*i-s*s,l=o*s-n*i,u=n*s-o*a,m=r*c+n*l+o*u;if(!(Math.abs(m)>1e-12*Math.max(1,Math.abs(r*a*i))))return null;let f=r*i-o*o,p=n*o-r*s,d=r*a-n*n;return[(c*t[0]+l*t[1]+u*t[2])/m,(l*t[0]+f*t[1]+p*t[2])/m,(u*t[0]+p*t[1]+d*t[2])/m]}function KS(e){let t=e.z.length;if(t<5)return 0;let r=[];for(let a=0;a<t;a++){let s=[a-2,a-1,a+1,a+2].map(h=>e.closed?(h+t)%t:h);if(s.some(h=>h<0||h>=t))continue;let i=s.map(h=>$S(e,a,h)),c=Math.max(...i.map(Math.abs));if(!(c>0))continue;let l=i.map(h=>h/c),u=[0,0,0,0,0];for(let h of l)for(let b=0;b<5;b++)u[b]+=h**b;let m=GS([u[0],u[1],u[2],u[2],u[3],u[4]],[1,0,0]);if(!m)continue;let f=l.map(h=>m[0]+m[1]*h+m[2]*h*h),p=0,d=1;f.forEach((h,b)=>{p+=h*e.z[s[b]],d+=h*h}),r.push(Math.abs(e.z[a]-p)/Math.sqrt(d))}if(!r.length)return 0;r.sort((a,s)=>a-s);let n=r.length>>1;return 1.4826*(r.length%2?r[n]:(r[n-1]+r[n])/2)}function d_(e,t,r){let n=e.z.length,o=[t],a=[0];for(let s of[-1,1])for(let i=1;i<n;i++){let c=e.closed?((t+s*i)%n+n)%n:t+s*i;if(c<0||c>=n)break;let l=$S(e,t,c);if(Math.abs(l)>=r||Math.sign(l)!==s)break;o.push(c),a.push(l)}return{j:o,t:a}}function f_(e,t,r){let{j:n,t:o}=d_(e,t,r);if(n.length<4)return null;let a=o.map(l=>(1-Math.abs(l/r)**3)**3),s=o.map(l=>l/r),i=[0,0,0,0,0];s.forEach((l,u)=>{let m=a[u];for(let f=0;f<5;f++)i[f]+=m,m*=l});let c=GS([i[0],i[1],i[2],i[2],i[3],i[4]],[1,0,0]);return c?{j:n,value:s.map((l,u)=>a[u]*(c[0]+c[1]*l+c[2]*l*l))}:null}function cg(e,t){return t>0?e.z.map((r,n)=>{let o=f_(e,n,t/2);return o?o.value.reduce((a,s,i)=>a+s*e.z[o.j[i]],0):r}):[...e.z]}function h_(e,t){if(!(e>0)||!(t>0))return 0;let r=(22.5*t*e*e/1e-4**2)**.2;return Math.min(100/2,r)}function xm(e){let t=Ui(e);if(!t)return 0;let r=KS(t);return r>1e-6?Math.max(10,h_(r,b_(t))):0}function b_(e){let t=[];for(let r=1;r<e.pos.length;r++)t.push(e.pos[r]-e.pos[r-1]);return e.closed&&e.pos.length&&t.push(e.length-e.pos[e.pos.length-1]+e.pos[0]),t.sort((r,n)=>r-n),t.length?t[t.length>>1]:0}function hr(e,t,r){let n=e.n;if(e.closed===!1){let a=r-t;return a===0?e.diag[t]:a===1?e.off1[t]:a===2?e.off2[t]:a===-1?e.off1[r]:a===-2?e.off2[r]:0}let o=((r-t)%n+n)%n;return o===0?e.diag[t]:o===1?e.off1[t]:o===2?e.off2[t]:o===n-1?e.off1[r]:o===n-2?e.off2[r]:0}function vm(e,t){let r=e.n,n=new Array(r).fill(0);for(let o=0;o<r;o++){let a=e.diag[o]*t[o];for(let[s,i]of[[1,e.off1],[2,e.off2]]){(o+s<r||e.closed!==!1)&&(a+=i[o]*t[(o+s)%r]);let c=(o-s+r)%r;(o-s>=0||e.closed!==!1)&&(a+=i[c]*t[c])}n[o]=a}return n}function HS(e,t){let r=new Array(e).fill(0),n=new Array(e).fill(0),o=new Array(e).fill(0);for(let a=0;a<e;a++){a>=2&&(o[a]=r[a-2]!==0?t(a,a-2)/r[a-2]:0),a>=1&&(n[a]=r[a-1]!==0?(t(a,a-1)-o[a]*n[a-1])/r[a-1]:0);let s=t(a,a)-n[a]*n[a]-o[a]*o[a];if(!(s>0)||!Number.isFinite(s))return null;r[a]=Math.sqrt(s)}return{d:r,l1:n,l2:o}}function Rm(e,t){let r=t.length,n=new Array(r).fill(0);for(let a=0;a<r;a++){let s=t[a];a>=1&&(s-=e.l1[a]*n[a-1]),a>=2&&(s-=e.l2[a]*n[a-2]),n[a]=s/e.d[a]}let o=new Array(r).fill(0);for(let a=r-1;a>=0;a--){let s=n[a];a+1<r&&(s-=e.l1[a+1]*o[a+1]),a+2<r&&(s-=e.l2[a+2]*o[a+2]),o[a]=s/e.d[a]}return o}function g_(e,t){let r=e[0][0]*e[1][1]-e[0][1]*e[1][0],n=Math.max(Math.abs(e[0][0]*e[1][1]),Math.abs(e[0][1]*e[1][0]),Number.MIN_VALUE);return!Number.isFinite(r)||Math.abs(r)<1e-12*n?null:[(t[0]*e[1][1]-e[0][1]*t[1])/r,(e[0][0]*t[1]-t[0]*e[1][0])/r]}function lg(e,t){let r=e.n;if(r<7)throw new Error(`periodic band solver needs n >= 7, got ${r}`);if(e.closed===!1){let b=HS(r,(y,R)=>hr(e,y,R));if(!b)return null;let g=Rm(b,t);return g.every(Number.isFinite)?g:null}let n=r-2,a=HS(n,(b,g)=>hr(e,b,g));if(!a)return null;let s=new Array(n).fill(0),i=new Array(n).fill(0);for(let b=0;b<n;b++)s[b]=hr(e,b,r-2),i[b]=hr(e,b,r-1);let c=Rm(a,t.slice(0,n)),l=Rm(a,s),u=Rm(a,i),m=(b,g)=>{let y=0;for(let R=0;R<b.length;R++)y+=b[R]*g[R];return y},f=[[hr(e,r-2,r-2)-m(s,l),hr(e,r-2,r-1)-m(s,u)],[hr(e,r-1,r-2)-m(i,l),hr(e,r-1,r-1)-m(i,u)]],p=[t[r-2]-m(s,c),t[r-1]-m(i,c)],d=g_(f,p);if(!d)return null;let h=new Array(r).fill(0);for(let b=0;b<n;b++)h[b]=c[b]-l[b]*d[0]-u[b]*d[1];return h[r-2]=d[0],h[r-1]=d[1],h.every(Number.isFinite)?h:null}function zS(e,t,r=0){let n=Math.max(...e.diag.map(Math.abs),1e-30),o=r>0?r:n*1e-12,a=Math.sqrt(t.reduce((s,i)=>s+i*i,0));for(let s=0;s<40;s++){let i={...e,diag:e.diag.map(l=>l+o)},c=lg(i,t);if(c){let l=vm(i,c).map((m,f)=>m-t[f]);if(Math.sqrt(l.reduce((m,f)=>m+f*f,0))<=1e-6*Math.max(a,1e-12))return c}o=o===0?n*1e-12:o*10}return null}var YS=4,y_=8,ug=.001;function x_(e,t,r){let n=[];for(let c=1;c<e.length;c++){let l=e[c]-e[c-1];l>=ug&&n.push(l)}let o=Float64Array.from(n).sort(),a=o.length>>1,s=o.length?o.length%2?o[a]:.5*(o[a-1]+o[a]):0,i=t?n.length:n.length+1;return Math.max(3,Math.round(i/eM(r,s,i)))}function R_(e,t){let r=e.closed!==!1,n=[],o=[],a=(F,w)=>{let C=n.length-1;C>=0&&Math.hypot(F-n[C],w-o[C])<ug||(n.push(F),o.push(w))},s=e.x.length,i=r?s:s-1,c=new Array(i+1);c[0]=0;for(let F=0;F<i;F++){let w=(F+1)%s;c[F+1]=c[F]+Math.hypot(e.x[w]-e.x[F],e.y[w]-e.y[F])}let l=c[i],u=e.fit==="interpolate",m=u?s:x_(c,r,t),f=r?m:m-1,p=0;for(let F=0;F<=f&&!(r&&F===f);F++){if(u){a(e.x[F],e.y[F]);continue}let w=F*l/f;for(;p<i-1&&c[p+1]<w;)p++;let C=c[p+1]-c[p],T=C>0?(w-c[p])/C:0,S=(p+1)%s;a(e.x[p]+T*(e.x[S]-e.x[p]),e.y[p]+T*(e.y[S]-e.y[p]))}if(r)for(;n.length>2&&Math.hypot(n[n.length-1]-n[0],o[o.length-1]-o[0])<ug;)n.pop(),o.pop();let d=n.length,h=r?d:d-1,b=new Array(h+1);b[0]=0;for(let F=1;F<=h;F++){let w=F%d,C=n[w]-n[F-1],T=o[w]-o[F-1],S=Math.sqrt(Math.hypot(C,T))||1e-9;b[F]=b[F-1]+S}let g=r?ym(b.slice(0,d),n,b[d]):ig(b,n),y=r?ym(b.slice(0,d),o,b[d]):ig(b,o),R=new Array(h);for(let F=0;F<h;F++)R[F]=b[F+1]-b[F];let k=[0],v=[0],x=[0],M=0;for(let F=0;F<h;F++){let w=R[F]/YS;for(let C=0;C<YS;C++){let T=C*w;M+=hh(S=>Math.hypot(g.d1(F,S),y.d1(F,S)),T,T+w),k.push(M),v.push(F),x.push(T+w)}}return{closed:r,sx:g,sy:y,h:R,sTable:k,segTable:v,uTable:x,length:M,rawCum:c,rawLength:l}}function Xi(e,t,r,n){if(e===void 0)return r.map(()=>t);if(typeof e=="number")return r.map(()=>e);let o=e.length;if(o===0)return r.map(()=>t);if(o===1)return r.map(()=>e[0]);let a=n.rawCum.length-1,s=o===(n.closed?a:a+1);return r.map(i=>{let c;if(s){let f=i*n.rawLength,p=0,d=a;for(;p<d;){let b=p+d+1>>1;n.rawCum[b]<=f?p=b:d=b-1}let h=p<a?n.rawCum[p+1]-n.rawCum[p]:0;c=p+(h>0?(f-n.rawCum[p])/h:0)}else c=n.closed?i*o:i*(o-1);let l=Math.min(Math.floor(c),o-1)%o,u=c-Math.floor(c),m=n.closed?(l+1)%o:Math.min(l+1,o-1);return e[l]+u*(e[m]-e[l])})}var v_=.01,k_=3,WS=10;function M_(e,t,r,n=WS){let o={step:0,uncertainty:1/0},a=e.length;if(a<8||!(r>0))return o;let s=Math.max(WS,n,6*r/a),i=(r-t[a-1])/2,c=0;for(;c<a/2&&t[c]+i<=s;)c++;let l=0;for(;l<a/2&&r-t[a-1-l]-i<=s;)l++;let u=Math.min(c,l);if(u<3)return o;let m=[],f=[],p=(R,k,v)=>{let x=R/s;m.push([1,x,x*x,x*x*x,k]),f.push(v)};for(let R=0;R<u;R++)p(t[R]+i,1,e[R]);for(let R=0;R<u;R++)p(t[a-1-R]-r+i,0,e[a-1-R]);let d=Array.from({length:5},()=>new Array(5).fill(0)),h=new Array(5).fill(0);m.forEach((R,k)=>{for(let v=0;v<5;v++){h[v]+=R[v]*f[k];for(let x=0;x<5;x++)d[v][x]+=R[v]*R[x]}});let b=Jt(d,h),g=Jt(d,[0,0,0,0,1]);if(b.singular||g.singular)return o;let y=0;return m.forEach((R,k)=>{let v=0;for(let x=0;x<5;x++)v+=R[x]*b.x[x];y+=(f[k]-v)**2}),{step:b.x[4],uncertainty:Math.sqrt(y/(m.length-5)*g.x[4])}}function S_(e,t){let r=t[t.length-1];return{pos:e===t.length-1?t.slice(0,e):Array.from({length:e},(o,a)=>a/e*r),loop:r}}function A_(e,t,r){let{pos:n,loop:o}=S_(e.length,t),{step:a,uncertainty:s}=M_(e,n,o,r);return Math.abs(a)>Math.max(v_,k_*s)?{z:e.map((i,c)=>i+a*n[c]/o),drift:-a}:{z:e,drift:0}}function F_(e,t){let{sTable:r,segTable:n,uTable:o,h:a,sx:s,sy:i}=e,c=0,l=r.length-1;for(;c<l;){let y=c+l+1>>1;r[y]<=t?c=y:l=y-1}let u=Math.min(c,r.length-2),m=r[u],f=r[u+1],p=n[u+1],d=o[u+1],h=n[u]===p?o[u]:0,b=f-m,g=b>0?h+(t-m)/b*(d-h):h;for(let y=0;y<2;y++){let R=m+hh(v=>Math.hypot(s.d1(p,v),i.d1(p,v)),h,g),k=Math.hypot(s.d1(p,g),i.d1(p,g));if(k<1e-12)break;g-=(R-t)/k}return{seg:p,du:Math.min(Math.max(g,0),a[p])}}var w_=3,mg=5;function C_(e,t,r,n=mg){return Mm(e,t,r,n)}function Mm(e,t,r,n,o=!1){let a=e.length;if(!(t>0)||!(n>0)||a<7)return[...e];let s=(n/(2*Math.PI*t))**4,i=new Array(a).fill(1+6*s),c=new Array(a).fill(-4*s),l=new Array(a).fill(s),u=[...e];if(!r&&(i[0]=i[a-1]=1+s,i[1]=i[a-2]=1+5*s,c[0]=c[a-2]=-2*s,o)){let m=1e9*(1+s);for(let f of[0,a-1])i[f]+=m,u[f]*=1+m}return lg({n:a,diag:i,off1:c,off2:l,closed:r},u)??[...e]}function it(e,t){let r=st(t),n=R_(e,r.fitSpacing),o=n.length,a=Math.max(y_,Math.round(o/r.dsTarget)),s=n.closed?a:a+1,i=o/a,c=new Array(s),l=new Array(s),u=new Array(s),m=new Array(s).fill(i);n.closed||(m[s-1]=0);let f=new Array(s),p=new Array(s),d=new Array(s);for(let C=0;C<s;C++){let T=C*i,{seg:S,du:A}=F_(n,T);c[C]=n.sx.eval(S,A),l[C]=n.sy.eval(S,A),u[C]=T;let P=n.sx.d1(S,A),L=n.sy.d1(S,A),D=n.sx.d2(S,A),E=n.sy.d2(S,A),V=Math.hypot(P,L),N=Math.pow(P*P+L*L,1.5);f[C]=N>0?(P*E-L*D)/N:0,p[C]=V>0?-L/V:0,d[C]=V>0?P/V:0}let h=u.map(C=>o>0?Math.min(1,C/o):0),b=Array.isArray(e.z)&&e.z.length>1,g=b&&(e.zSmoothing??0)>0?e.zSmoothing:0,y=b&&n.closed?A_(e.z,n.rawCum,g):null,R=y?y.z:e.z,k=g>0?Ui(e):null,v=k?cg({...k,z:R},g):R,x=Xi(v,0,h,n),M=new Array(s).fill(0);if(b){for(let T=0;T<s;T++){let S=n.closed?(T+1)%s:Math.min(T+1,s-1),A=n.closed?(T-1+s)%s:Math.max(T-1,0),P=n.closed?2:S-A,L=x[S]-x[A];M[T]=P>0?Math.atan2(L,P*i)*180/Math.PI:0}for(let T=0;T<s;T++){if(m[T]===0)continue;let S=n.closed?(T+1)%s:T+1,A=x[S]-x[T];m[T]=Math.hypot(i,A)}let C=0;for(let T=0;T<s;T++)u[T]=C,C+=m[T]}let F=b?m.reduce((C,T)=>C+T,0):o,w;if(b){w=new Array(s).fill(0);let C=Math.max(w_,e.zReach??xm(e)),T=Math.max(2,Math.round(C/i));if(n.closed?s>2*T:s>2*T+1){let S=0,A=0;for(let D=-T;D<=T;D++)S+=D*D,A+=D*D*D*D;let P=2*T+1,L=A-S*S/P;for(let D=0;D<s;D++){let E=n.closed?D:Math.min(Math.max(D,T),s-1-T),V=0,N=0;for(let _=-T;_<=T;_++){let B=x[n.closed?(E+_+s)%s:E+_];V+=(_*_-S/P)*B,N+=_*B}let z=2*V/L/(i*i),I=N/S/i;w[D]=z/Math.pow(1+I*I,1.5)}}}return{name:e.name,closed:n.closed,x:c,y:l,s:u,ds:m,curvature:e.turnReach?C_(f,i,n.closed,e.turnReach):f,npts:s,length:F,nx:p,ny:d,z:x,gradient:M,...w?{verticalCurvature:w}:{},widthLeft:Xi(e.widthLeft,1.5,h,n),widthRight:Xi(e.widthRight,1.5,h,n),bank:Xi(e.bank,0,h,n),mu:Xi(e.mu,1,h,n),...y?.drift?{elevationDrift:y.drift}:{}}}function jS(e,t,r){let n=vm(e,r),o=0;for(let a=0;a<r.length;a++)o+=.5*r[a]*n[a]-t[a]*r[a];return o}function T_(e,t,r,n){let o=e.n,a=e.closed!==!1,s=(l,u)=>{let m=l+u;return a?(m%o+o)%o:m>=0&&m<o?m:null},i=[...t];for(let l=0;l<o;l++){if(r[l]==="free")continue;let u=n(l);if(u!==0)for(let m of[-2,-1,1,2]){let f=s(l,m);f!=null&&(i[f]-=hr(e,f,l)*u)}}let c={n:o,closed:e.closed,diag:[...e.diag],off1:[...e.off1],off2:[...e.off2]};for(let l=0;l<o;l++){if(r[l]==="free")continue;c.diag[l]=1,c.off1[l]=0,c.off2[l]=0;let u=s(l,-1),m=s(l,-2);u!=null&&(c.off1[u]=0),m!=null&&(c.off2[m]=0),i[l]=n(l)}return zS(c,i)}var P_=1e-4;function US(e,t,r,n,o={}){let a=e.n,s=o.maxIter??60,i=o.tol??1e-9,c=o.bounds,l=(d,h)=>Math.min(n[h],Math.max(r[h],d)),u=r.map((d,h)=>c?.[h]==="hi"?n[h]:c?.[h]==="lo"?r[h]:l(0,h)),m=jS(e,t,u),f=new Array(a).fill("free"),p=!1;for(let d=0;d<s;d++){let h=vm(e,u).map((R,k)=>R-t[k]),b=!1;for(let R=0;R<a;R++){let k=u[R]<=r[R]+i&&h[R]>=-i?"lo":u[R]>=n[R]-i&&h[R]<=i?"hi":"free";k!==f[R]&&(f[R]=k,b=!0)}if(p&&!b)return{x:u,iterations:d+1,converged:!0,bounds:f};let g=T_(e,t,f,R=>u[R]);if(!g)return{x:u,iterations:d+1,converged:!1,bounds:f};let y=!1;for(let R=1;R>1e-12;R*=.5){let k=!1,v=u.map((F,w)=>{if(f[w]!=="free")return F;let C=F+R*(g[w]-F),T=l(C,w);return T!==C&&(k=!0),T}),x=jS(e,t,v),M=0;for(let F=0;F<a;F++)M+=h[F]*(v[F]-u[F]);if(R===1&&!k||x<m&&x<=m+P_*M){u=v,m=x,p=R===1&&!k,y=!0;break}}if(!y)return{x:u,iterations:d+1,converged:!1,bounds:f}}return{x:u,iterations:s,converged:!1,bounds:f}}var pg={lineStep:2,carHalfWidth:.75,margin:.1,foldMargin:.25,referenceReach:5,passes:40,iterations:400},L_=[1,.5,.25,.125,.0625,.03125,.015625,.0078125,.00390625,.001953125,.0009765625],D_=e=>Math.sqrt(e.reduce((t,r)=>t+r*r,0)/(e.length||1));function qi(e,t,r=!0){let n=e.length,o=new Array(n).fill(0);for(let a=0;a<n;a++){if(!r&&(a===0||a===n-1))continue;let s=(a-1+n)%n,i=(a+1)%n,c=e[a]-e[s],l=t[a]-t[s],u=e[i]-e[a],m=t[i]-t[a],f=e[i]-e[s],p=t[i]-t[s],d=Math.hypot(c,l),h=Math.hypot(u,m),b=Math.hypot(f,p),g=d*h*b;o[a]=g>1e-12?2*(c*m-l*u)/g:0}return o}var E_=Math.PI/180,XS=20;function I_(e,t){let r=e.npts,n=e.closed,o=e.x.map((p,d)=>p+t[d]*e.nx[d]),a=e.y.map((p,d)=>p+t[d]*e.ny[d]),s=[0];for(let p=1;p<r;p++)s.push(s[p-1]+Math.hypot(o[p]-o[p-1],a[p]-a[p-1]));let i=n?s[r-1]+Math.hypot(o[0]-o[r-1],a[0]-a[r-1]):s[r-1],c=n?[-1,0,1]:[0],l=[],u=[];for(let p of c)for(let d=0;d<r;d++)l.push(s[d]+p*i),u.push(d+p*r);n&&(l.push(2*i),u.push(2*r));let m=[0];for(let p=1;p<l.length;p++)m.push(m[p-1]+.5*(u[p]+u[p-1])*(l[p]-l[p-1]));let f=p=>{let d=0,h=l.length-1;for(;h-d>1;){let g=d+h>>1;l[g]<=p?d=g:h=g}let b=l[h]>l[d]?(p-l[d])/(l[h]-l[d]):0;return m[d]+(l[h]-l[d])*b*(u[d]+.5*b*(u[h]-u[d]))};return s.map((p,d)=>{let h=n?XS:Math.min(XS,p,i-p);if(!(h>0))return e.z[d];let b=(f(p+h)-f(p-h))/(2*h),g=n?(b%r+r)%r:Math.min(Math.max(b,0),r-1),y=Math.min(Math.floor(g),r-1),R=n?(y+1)%r:Math.min(y+1,r-1);return e.z[y]+(g-y)*(e.z[R]-e.z[y])})}function __(e,t,r){let n=Array.isArray(e.z)&&e.z.length>1,o=t.bank.some(i=>i!==0),a=t.mu.some(i=>i!==1),s=n?I_(t,r):t.z;return{...n||o?{z:s.map((i,c)=>i+r[c]*Math.tan(t.bank[c]*E_))}:{},...n?{zReach:e.zReach??xm(e)}:{},...o?{bank:[...t.bank]}:{},...a?{mu:[...t.mu]}:{}}}function qS(e,t,r=!0){let n=e.length,o=new Array(n).fill(0);for(let a=0;a<n;a++){if(!r&&(a===0||a===n-1))continue;let s=(a-1+n)%n,i=(a+1)%n;o[a]=.5*(Math.hypot(e[a]-e[s],t[a]-t[s])+Math.hypot(e[i]-e[a],t[i]-t[a]))}return o}function N_(e,t,r,n,o){let a=e.length,s=new Array(a).fill(0),i={l:new Array(a).fill(0),d:new Array(a).fill(0),r:new Array(a).fill(0)},c=(l,u,m,f)=>l*f-u*m;for(let l=0;l<a;l++){if(!o&&(l===0||l===a-1))continue;let u=(l-1+a)%a,m=(l+1)%a,f=e[l]-e[u],p=t[l]-t[u],d=e[m]-e[l],h=t[m]-t[l],b=e[m]-e[u],g=t[m]-t[u],y=Math.hypot(f,p),R=Math.hypot(d,h),k=Math.hypot(b,g),v=y*R*k;if(!(v>1e-12))continue;let x=2*c(f,p,d,h)/v,M=Math.sqrt(.5*(y+R)),F=x/(2*M),w=(f*r[u]+p*n[u])/y,C=(b*r[u]+g*n[u])/k,T=(f*r[l]+p*n[l])/y,S=(d*r[l]+h*n[l])/R,A=(d*r[m]+h*n[m])/R,P=(b*r[m]+g*n[m])/k,L=-2*c(r[u],n[u],d,h)/v+x*(w/y+C/k),D=2*c(r[l],n[l],b,g)/v-x*(T/y-S/R),E=2*c(f,p,r[m],n[m])/v-x*(A/R+P/k);s[l]=x*M,i.l[l]=M*L-F*.5*w,i.d[l]=M*D+F*.5*(T-S),i.r[l]=M*E+F*.5*A}return{res:s,jac:i}}function O_(e,t,r,n,o){let a=n-r+1,s=e.l.slice(r,n+1),i=e.d.slice(r,n+1),c=e.r.slice(r,n+1),l=t.slice(r,n+1);o||(i[0]+=s[0],s[0]=0,i[a-1]+=c[a-1],c[a-1]=0);let u=(h,b)=>o?h[(b+a)%a]:b>=0&&b<a?h[b]:0,m=new Array(a),f=new Array(a),p=new Array(a),d=new Array(a);for(let h=0;h<a;h++){let b=u(c,h-1),g=u(s,h+1);m[h]=b*b+i[h]*i[h]+g*g,f[h]=i[h]*c[h]+g*u(i,h+1),p[h]=g*u(c,h+1),d[h]=-(b*u(l,h-1)+i[h]*l[h]+g*u(l,h+1))}return{M:{n:a,closed:o,diag:m,off1:f,off2:p},b:d}}function V_(e,t){let r=e.npts,n=e.closed;if(!(t>0)||r<7)return e;let o=n?r:r-1,a=0;for(let f=0;f<o;f++){let p=(f+1)%r;a+=Math.hypot(e.x[p]-e.x[f],e.y[p]-e.y[f])}let s=a/o,i=Mm(e.x,s,n,t,!0),c=Mm(e.y,s,n,t,!0),l=new Array(r),u=new Array(r);for(let f=0;f<r;f++){let p=n?(f-1+r)%r:Math.max(f-1,0),d=n?(f+1)%r:Math.min(f+1,r-1),h=i[d]-i[p],b=c[d]-c[p],g=Math.hypot(h,b)||1;l[f]=-b/g,u[f]=h/g}let m=qi(i,c,n);return n||(m[0]=m[1],m[r-1]=m[r-2]),{...e,x:i,y:c,nx:l,ny:u,curvature:m}}var B_=6;function $_(e,t,r,n){let o=e.npts,a=e.closed?o:o-1,s=new Array(a);for(let l=0;l<a;l++){let u=(l+1)%o,m=Math.atan2(e.nx[l]*e.ny[u]-e.ny[l]*e.nx[u],e.nx[l]*e.nx[u]+e.ny[l]*e.ny[u]),f=Math.hypot(e.x[u]-e.x[l],e.y[u]-e.y[l]);s[l]=f>1e-9?m/f:0}let i=Math.max(0,Math.round(B_/(e.ds[0]||1))),c=1-n;for(let l=0;l<o;l++){let u=0,m=0;for(let f=-i-1;f<=i;f++){let p=e.closed?((l+f)%o+o)%o:l+f;p<0||p>=a||(u=Math.max(u,s[p]),m=Math.max(m,-s[p]))}u>0&&(t[l]=Math.max(r[l],Math.min(t[l],c/u))),m>0&&(r[l]=Math.min(t[l],Math.max(r[l],-c/m)))}}function dg(e,t={}){let r={...pg,...t},n=it(e,{dsTarget:r.lineStep}),o=V_(n,r.referenceReach),a=o.npts,s=T=>({x:o.x.map((S,A)=>S+o.nx[A]*T[A]),y:o.y.map((S,A)=>S+o.ny[A]*T[A])}),i=T=>{let S=qi(T.x,T.y,o.closed),A=qS(T.x,T.y,o.closed),P=0;for(let L=0;L<S.length;L++)P+=S[L]*S[L]*A[L];return P},c=D_(n.curvature),l=qS(n.x,n.y,n.closed).reduce((T,S)=>T+S,0),u=new Array(a).fill(0),m=r.carHalfWidth+r.margin,f=new Array(a),p=new Array(a),d=0;for(let T=0;T<a;T++){let S=o.widthLeft[T]-m,A=-(o.widthRight[T]-m);if(S<A){d++;let P=(o.widthLeft[T]-o.widthRight[T])/2;f[T]=P,p[T]=P}else f[T]=S,p[T]=A}let h=[...f],b=[...p];$_(o,f,p,r.foldMargin);let g=T=>{let S=s(T),A=__(e,o,T),P={name:`${e.name} \u2014 racing line`,x:S.x,y:S.y,closed:o.closed,widthLeft:h.map((I,_)=>Math.max(0,I-T[_])),widthRight:b.map((I,_)=>Math.max(0,T[_]-I)),...A,fit:"interpolate",turnReach:mg},L=1e-6,D=T.filter((I,_)=>I>=f[_]-L||I<=p[_]+L).length,E=qi(S.x,S.y,o.closed),V=I=>1/Math.max(...I.map(Math.abs),1e-9),N=0,z=o.closed?S.x.length:S.x.length-1;for(let I=0;I<z;I++){let _=(I+1)%S.x.length,B=S.x[_]-S.x[I],O=S.y[_]-S.y[I];N+=A.z?Math.hypot(B,O,A.z[_]-A.z[I]):Math.hypot(B,O)}return{offset:T,s:[...o.s],asset:P,curvatureRms:{centreLine:c,racingLine:Math.sqrt(i(S)/(l||1))},infeasibleSamples:d,atBoundary:a?D/a:0,length:{centreLine:n.length,racingLine:N},worstRadius:{centreLine:V(n.curvature),racingLine:V(E)}}},y=o.closed?0:1,R=o.closed?a-1:a-2,k=R-y+1,v=new Array(k),x=new Array(k);for(let T=0;T<k;T++)v[T]=p[y+T],x[T]=f[y+T];if(!o.closed&&k>0){let T=(S,A)=>{if(v[S]=Math.max(v[S],p[A]),x[S]=Math.min(x[S],f[A]),v[S]>x[S]){let P=.5*(v[S]+x[S]);v[S]=P,x[S]=P}};T(0,0),T(k-1,a-1),v[0]=x[0]=Math.min(x[0],Math.max(v[0],0))}if(k<7)return g(u);let M=T=>{let S=s(T),P=[...qi(S.x,S.y,o.closed).map(Math.abs)].sort((L,D)=>L-D);return{integral:i(S),tail:P[Math.floor(.99*(P.length-1))]}},F=[...u],w=M(u),C;for(let T=0;T<r.passes;T++){let S=s(F),{res:A,jac:P}=N_(S.x,S.y,o.nx,o.ny,o.closed),{M:L,b:D}=O_(P,A,y,R,o.closed),E=US(L,D,v.map((z,I)=>z-F[y+I]),x.map((z,I)=>z-F[y+I]),{maxIter:r.iterations,bounds:C});C=E.bounds;let V=new Array(a).fill(0);for(let z=0;z<k;z++)V[y+z]=E.x[z];o.closed||(V[0]=V[1],V[a-1]=V[a-2]);let N=!1;for(let z of L_){let I=F.map((B,O)=>B+z*V[O]),_=M(I);if(_.integral<w.integral*(1-1e-6)){F=I,w=_,N=!0;break}}if(!N)break}return g(F)}function fg(e){let t=Math.max(Q(e,"track_front"),Q(e,"track_rear"));return(t>0?t/2e3:.6)+.1}function Sm(e,t,r={}){if(!r.racingLine)return{asset:e,numerics:t,line:null};let n=r.params?fg(r.params):void 0,o=dg(e,{...r.line,...n?{carHalfWidth:n}:{}});return{asset:o.asset,numerics:{...t,fitSpacing:0},line:o}}function Qi(e,t,r={}){let n=Sm(e,t,r);return{track:it(n.asset,n.numerics),line:n.line}}function hg(e=4,t=Qi){let r=new WeakMap;return(n,o,a={})=>{let s=a.racingLine===!0,i=s?[a.params?fg(a.params):null,a.line??null]:null,c=JSON.stringify([o,s,i]),l=r.get(n);l||(l=new Map,r.set(n,l));let u=l.get(c);if(u)return l.delete(c),l.set(c,u),u;let m=t(n,o,a);return l.set(c,m),l.size>e&&l.delete(l.keys().next().value),m}}var QS={racingLine:!1,standingStart:!1},Am=256;function Zi(e,t,r,n,o=QS,a=Qi){let s=uo(n),{racingLine:i,standingStart:c,lapCounts:l}=o;return e.map(u=>{let{track:m}=a(t,r,{racingLine:i,params:u});return Xb(Vi(u,s,{track:m,numerics:r,standingStart:c,lapCounts:l}))})}function bg(e,t){let r=uo(e),n=r.score?r.score(t):null,o=r.field===r.score?n:r.field?r.field(t):null;return{scores:n,field:o}}function gg(e,t,r){let n={};for(let o of uo(e).metrics)n[o.key]=o.value(t,r);return n}var Fm=36;var Rg=287.05287,K_=461.495,wm=9.80665/(Rg*.0065),H_=101325/(Rg*288.15),z_=273.15,Y_=-500,W_=6e3,j_=400,U_=1100,Cm={source:"car",altitudeM:0,pressure:{kind:"standard"},humidityPct:0};function X_(e){return 101325*Math.pow(1-.0065*e/288.15,wm)}function q_(e){return 288.15/.0065*(1-Math.pow(e/H_,1/(wm-1)))}function Q_(e){return 288.15/.0065*(1-Math.pow(e/101325,1/wm))}function Z_(e,t){return e*Math.pow(1-.0065*t/288.15,wm)}function J_(e){return 611.21*Math.exp((18.678-e/234.5)*(e/(257.14+e)))}function eN(e,t){switch(e.kind){case"standard":return X_(t);case"qnh":return Z_(e.hPa*100,t);case"station":return e.hPa*100}}function Ji(e,t,r=0,n=Q_(e)){let o=t+z_,a=Math.min(.5*e,Math.max(0,Math.min(100,r))/100*J_(t)),s=e-a,i=s/(Rg*o)+a/(K_*o);return{altitudeM:n,p:e,pDry:s,T:o,rho:i,densityAltitudeM:q_(i)}}function ZS(e,t){return Ji(eN(e.pressure,e.altitudeM),t,e.humidityPct,e.altitudeM)}var yg=(e,t,r)=>Math.min(r,Math.max(t,e)),xg=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function Tm(e){if(!e||typeof e!="object")return structuredClone(Cm);let t=e,r=t.pressure??{},n=yg(xg(r.hPa,1013.25),j_,U_),o=r.kind==="qnh"?{kind:"qnh",hPa:n}:r.kind==="station"?{kind:"station",hPa:n}:{kind:"standard"};return{source:t.source==="venue"?"venue":"car",altitudeM:yg(xg(t.altitudeM,0),Y_,W_),pressure:o,humidityPct:yg(xg(t.humidityPct,0),0,100)}}var ec=e=>e?.source==="venue";var tN=Math.PI/180;function rN(){return{ucaFront:[110,245,330],ucaRear:[-110,258,335],lcaFront:[130,185,112],lcaRear:[-130,205,116],tieInner:[-92,210,132],uprightUpper:[-6,542,352],uprightLower:[4,560,120],tieOuter:[-78,556,146],wheelCenter:[0,600,230],pushrodOuter:[8,520,128],rockerPivotA:[70,380,440],rockerPivotB:[-50,383,442],rockerToPushrod:[10,480,420],rockerToDamper:[10,280,440],damperChassis:[10,275,245]}}function nN(){return{ucaFront:[120,250,340],ucaRear:[-120,262,345],lcaFront:[140,190,118],lcaRear:[-140,210,122],tieInner:[120,215,150],uprightUpper:[-4,548,360],uprightLower:[6,566,126],tieOuter:[108,560,158],wheelCenter:[0,610,232],pushrodOuter:[10,526,132],rockerPivotA:[70,385,450],rockerPivotB:[-50,388,452],rockerToPushrod:[12,486,430],rockerToDamper:[12,286,450],damperChassis:[12,281,255]}}function vg(e){let t=-e*tN;return q([0,Math.cos(t),Math.sin(t)])}function Pm(){let e={rodType:"push",pushrodAttach:"lowerArm",steerMode:"rack",spinAxis:vg(-1),loadedRadius:230,springRate:35,rackAxis:[0,1,0]};return{hardpoints:rN(),config:e}}function tc(){let e={rodType:"pull",pushrodAttach:"lowerArm",steerMode:"fixed",spinAxis:vg(-1.5),loadedRadius:232,springRate:40,rackAxis:[0,1,0]};return{hardpoints:nN(),config:e}}function Lm(){let e=[-25,635,460],t=[-40,600,710],r={layout:"mcpherson",actuation:"direct",rodType:"push",pushrodAttach:"upright",steerMode:"rack",spinAxis:vg(-.5),loadedRadius:320,springRate:38,rackAxis:[0,1,0],rackTravel:70};return{hardpoints:{ucaFront:[49,426,430],ucaRear:[-99,425,431],lcaFront:[60,395,180],lcaRear:[-280,415,185],tieInner:[-150,375,256],uprightUpper:[...e],uprightLower:[0,720,145],tieOuter:[-140,705,230],wheelCenter:[0,775,320],pushrodOuter:[...e],damperChassis:[...t],rockerPivotA:[...t],rockerPivotB:[...t],rockerToPushrod:[...e],rockerToDamper:[...t]},config:r}}function kg(){return{front:Pm(),rear:tc(),config:{wheelbase:1600,trackFront:1200,trackRear:1220,frontAxleX:800}}}var oN=Math.PI/180;function JS(e){let t=-e*oN;return q([0,Math.cos(t),Math.sin(t)])}function Mg(e,t){let r=([l,u,m])=>[l*t.kx,u*t.ky,m*t.kz],n=e.hardpoints,o=Object.fromEntries(Object.entries(n).map(([l,u])=>[l,r(u)])),a=(l,u)=>{o[l]=[o[l][0],o[l][1],o[l][2]+u]},s=t.lowerInnerDz??0,i=t.upperInnerDz??0;a("lcaFront",s),a("lcaRear",s),a("tieInner",s),a("ucaFront",i),a("ucaRear",i);let c={...e.config,spinAxis:JS(t.camberDeg),loadedRadius:t.loadedRadius,springRate:t.springRate};if(t.actuation==="direct"){let l=o.pushrodOuter,u=[l[0],l[1]*.7,l[2]+1.3*t.loadedRadius];o.damperChassis=u,o.rockerPivotA=u,o.rockerPivotB=u,o.rockerToPushrod=l,o.rockerToDamper=u,c={...c,actuation:"direct",rodType:"push",pushrodAttach:"lowerArm"}}else c={...c,actuation:"rocker"};for(let l of Object.keys(o))o[l]=aN(o[l]);return{hardpoints:o,config:c}}function aN(e){return e.map(t=>Math.round(t*10)/10+0)}function po(e){return{name:e.name,front:Mg(Pm(),e.front),rear:Mg(tc(),e.rear),config:{wheelbase:e.wheelbase,trackFront:e.trackFront,trackRear:e.trackRear,frontAxleX:e.wheelbase/2}}}function Va(e,t,r){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:t}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:r}}}}var Ba=600,fo=610,$a=230,ho=232;function bo(){let e=kg();return{...e,name:"Formula Student",front:{...e.front,config:{...e.front.config,actuation:"rocker"}},rear:{...e.rear,config:{...e.rear.config,actuation:"rocker"}}}}function Sg(){return po({name:"Formula 1",wheelbase:3600,trackFront:1600,trackRear:1600,front:{kx:1.3,ky:800/Ba,kz:355/$a,lowerInnerDz:-5,upperInnerDz:0,camberDeg:-3,loadedRadius:355,springRate:200},rear:{kx:1.3,ky:800/fo,kz:355/ho,lowerInnerDz:35,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:220}})}function rc(){return Va(po({name:"GT car",wheelbase:2700,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/Ba,kz:325/$a,lowerInnerDz:18,upperInnerDz:5,camberDeg:-3.5,loadedRadius:325,springRate:110,actuation:"direct"},rear:{kx:1.2,ky:825/fo,kz:325/ho,lowerInnerDz:36,upperInnerDz:15,camberDeg:-2,loadedRadius:325,springRate:120,actuation:"direct"}}),318.6,318.6)}function nc(){return Va(po({name:"Sports car",wheelbase:2750,trackFront:1550,trackRear:1550,front:{kx:1.15,ky:775/Ba,kz:320/$a,lowerInnerDz:36,upperInnerDz:15,camberDeg:-.5,loadedRadius:320,springRate:55,actuation:"direct"},rear:{kx:1.15,ky:775/fo,kz:320/ho,lowerInnerDz:57,upperInnerDz:25,camberDeg:-1,loadedRadius:320,springRate:60,actuation:"direct"}}),305.4,309)}function sN(e,t,r,n,o,a){let s=Lm(),i=Object.fromEntries(Object.entries(s.hardpoints).map(([l,[u,m,f]])=>[l,[u,m+e,f]])),c=(l,u)=>{i[l]=[i[l][0],i[l][1],i[l][2]+u]};return c("lcaFront",t),c("lcaRear",t),c("tieInner",r),{hardpoints:i,config:{...s.config,spinAxis:JS(n),springRate:o,rackTravel:a}}}function eA(){return Va({name:"Cup car",front:sN(55,-25,-23,-3.5,150,55),rear:Mg(tc(),{kx:1.15,ky:820/fo,kz:320/ho,lowerInnerDz:37,upperInnerDz:12,camberDeg:-2,loadedRadius:320,springRate:130,actuation:"direct"}),config:{wheelbase:2650,trackFront:1660,trackRear:1640,frontAxleX:2650/2},chassis:{boxes:[],body:"cup"}},306.3,311.6)}function tA(){return{...Va(po({name:"Stock car",wheelbase:2794,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/Ba,kz:355/$a,lowerInnerDz:20,upperInnerDz:5,camberDeg:-2.5,loadedRadius:355,springRate:175,actuation:"direct"},rear:{kx:1.2,ky:825/fo,kz:355/ho,lowerInnerDz:40,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:150,actuation:"direct"}}),343.8,345.3),chassis:{boxes:[],body:"nascar"}}}function rA(){let e=Va(po({name:"Hill-climb prototype",wheelbase:2550,trackFront:1580,trackRear:1540,front:{kx:1.1,ky:790/Ba,kz:300/$a,lowerInnerDz:10,upperInnerDz:5,camberDeg:-2.5,loadedRadius:300,springRate:90},rear:{kx:1.1,ky:770/fo,kz:300/ho,lowerInnerDz:30,upperInnerDz:15,camberDeg:-1.5,loadedRadius:300,springRate:120}}),293.3,290.8);return{...e,front:{...e.front,config:{...e.front.config,rackTravel:45}},chassis:{boxes:[],body:"hillclimb"}}}function nA(){let e=Va(po({name:"Race truck",wheelbase:3700,trackFront:2050,trackRear:1950,front:{kx:1.5,ky:1025/Ba,kz:506/$a,lowerInnerDz:40,upperInnerDz:10,camberDeg:-.5,loadedRadius:506,springRate:200,actuation:"direct"},rear:{kx:1.5,ky:975/fo,kz:506/ho,lowerInnerDz:60,upperInnerDz:20,camberDeg:-.25,loadedRadius:506,springRate:160,actuation:"direct"}}),490.4,495.6);return{...e,front:{...e.front,config:{...e.front.config,rackTravel:60}},chassis:{boxes:[],body:"truck"}}}var rt=(e,t,r)=>({value:e,label:t,unit:r}),oA=(e,t)=>({...cr[e],value:t});function aA(e,t,r){let n=[],o=[];for(let a=0;a<=r;a+=500)n.push(a),o.push(a<=t?e:e*t/a);return{rpm:n,torque:o}}function go(e,t,r,n,o){let a=[],s=[];for(let i=0;i<=r;i+=500){a.push(i);let c=i<=t?n:Math.min(n,9549*e/i);s.push(c/o)}return{rpm:a,torque:s}}function Yr(e){let t={name:e.name,m:rt(e.m,"vehicle mass (with driver)","kg"),A:rt(e.A,"frontal area","m^2"),c_l:rt(e.cl,"downforce coefficient","-"),c_w:rt(e.cw,"drag coefficient","-"),l_to_d_ratio:rt(e.cw>0?e.cl/e.cw:0,"lift-to-drag ratio","-"),driven_wheels:rt(e.drivenWheels,"driven wheels","-"),fr_0:rt(-.012,"rolling-resistance coefficient","-"),front_aero_diss:rt(e.frontAero,"front aero distribution","-"),front_mass_diss:rt(e.frontMass,"front mass distribution","-"),r_dyn:rt(e.rDyn,"dynamic tyre radius","m"),rho:rt(1.2,"air density","kg/m^3"),gear_ratio:rt(e.gearRatio,"gear ratio","-"),effi_pgb:rt(e.drivetrainEfficiency,"drivetrain efficiency","-"),capacity:rt(e.capacityAh,"pack capacity","Ah"),soc:rt(1,"state of charge","-"),ocv:rt(e.ocv,"pack open-circuit voltage","V"),power_scale:rt(1,"power scaling factor","-"),power_limit_kw:oA("power_limit_kw",e.powerLimitKw),motor:e.motor,tireModelId:e.tireModelId};e.motorCount!==void 0&&(t.motorCount=e.motorCount),e.driveline&&(t.driveline=structuredClone(e.driveline)),e.motorPlacement&&(t.motorPlacement=e.motorPlacement);for(let[r,n]of Object.entries(e.dynamics))t[r]=oA(r,n);return t}var Ga={name:"Formula Student",m:300,A:1,cl:3,cw:1.3,frontMass:.47,frontAero:.45,rDyn:.222,drivenWheels:2,gearRatio:11.5,motor:aA(25,15e3,2e4),capacityAh:12,ocv:550,drivetrainEfficiency:.95,powerLimitKw:80,tireModelId:"t3",dynamics:{grip_scale:1,stiffness_scale:1,endurance_reserve:5,cg_height:300,tire_vertical_rate:110,unsprung_mass:8,brake_balance:.62,arb_front:20,arb_rear:15,damper_front:2.5,damper_rear:2.5,spring_front:35,spring_rear:40,mr_front:.94,mr_rear:.92,cop_long:.55,cop_height:300,ride_height_front:30,ride_height_rear:35,I_yaw:140,I_roll:45,I_pitch:130,camber_front_deg:-1,camber_rear_deg:-1.5,track_front:1200,track_rear:1220,wheelbase:1600,rc_front:5,rc_rear:4}},Fg={name:"Formula 1",m:798,A:1.5,cl:3,cw:.9,frontMass:.46,frontAero:.44,rDyn:.35,drivenWheels:2,gearRatio:4.9,motor:go(735,2e3,12500,2500,2),motorCount:1,driveline:{rear:xt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t4",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:290,tire_vertical_rate:300,unsprung_mass:30,brake_balance:.58,arb_front:250,arb_rear:150,damper_front:6,damper_rear:6,spring_front:200,spring_rear:220,mr_front:.95,mr_rear:.91,heave_spring_front:800,heave_spring_rear:800,tire_vertical_damping:.5,cop_long:.56,cop_height:400,ride_height_front:35,ride_height_rear:70,I_yaw:800,I_roll:150,I_pitch:800,camber_front_deg:-3,camber_rear_deg:-1.5,track_front:1600,track_rear:1600,wheelbase:3600,rc_front:-4,rc_rear:78}},Dm={name:"GT car",m:1300,A:2,cl:1.4,cw:.42,frontMass:.5,frontAero:.42,rDyn:.33,drivenWheels:2,gearRatio:3.43,motor:go(410,2e3,8e3,2e3,2),motorCount:1,driveline:{rear:xt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t5",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:450,tire_vertical_rate:280,unsprung_mass:45,brake_balance:.6,arb_front:40,arb_rear:25,damper_front:4.5,damper_rear:4.5,spring_front:110,spring_rear:120,mr_front:.79,mr_rear:.77,cop_long:.58,cop_height:500,ride_height_front:55,ride_height_rear:75,I_yaw:1800,I_roll:450,I_pitch:1800,camber_front_deg:-3.5,camber_rear_deg:-2,track_front:1650,track_rear:1650,wheelbase:2700,rc_front:48,rc_rear:80}},Em={name:"Sports car",m:1600,A:2.2,cl:-.1,cw:.3,frontMass:.55,frontAero:.5,rDyn:.32,drivenWheels:2,gearRatio:3.14,motor:go(220,1500,6500,1400,2),motorCount:1,driveline:{rear:xt.open},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t6",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:520,tire_vertical_rate:220,unsprung_mass:50,brake_balance:.65,arb_front:25,arb_rear:12,damper_front:2.4,damper_rear:2.4,spring_front:55,spring_rear:60,mr_front:.78,mr_rear:.75,cop_long:.5,cop_height:500,ride_height_front:130,ride_height_rear:140,I_yaw:2600,I_roll:550,I_pitch:2500,camber_front_deg:-.5,camber_rear_deg:-1,track_front:1550,track_rear:1550,wheelbase:2750,rc_front:80,rc_rear:122}},wg={name:"Cup car",m:1265,A:2.1,cl:.45,cw:.4,frontMass:.62,frontAero:.45,rDyn:.31,drivenWheels:2,gearRatio:3.5,motor:go(250,2e3,7e3,1190,2),motorCount:1,motorPlacement:"front",driveline:{front:xt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t7",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:480,tire_vertical_rate:280,unsprung_mass:40,brake_balance:.68,arb_front:20,arb_rear:90,damper_front:4,damper_rear:3.5,spring_front:150,spring_rear:130,mr_front:.95,mr_rear:.76,cop_long:.55,cop_height:450,ride_height_front:64,ride_height_rear:78,I_yaw:1700,I_roll:400,I_pitch:1700,camber_front_deg:-3.5,camber_rear_deg:-2,track_front:1660,track_rear:1640,wheelbase:2650,rc_front:60,rc_rear:84}},Cg={name:"Stock car",m:1620,A:2.2,cl:.6,cw:.45,frontMass:.53,frontAero:.45,rDyn:.35,drivenWheels:2,gearRatio:4.1,motor:go(500,2500,9e3,1680,2),motorCount:1,driveline:{rear:xt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t8",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:430,tire_vertical_rate:320,unsprung_mass:55,brake_balance:.6,arb_front:60,arb_rear:15,damper_front:7.5,damper_rear:6.75,spring_front:175,spring_rear:150,mr_front:.8,mr_rear:.78,cop_long:.55,cop_height:500,ride_height_front:75,ride_height_rear:90,I_yaw:2500,I_roll:550,I_pitch:2500,camber_front_deg:-2.5,camber_rear_deg:-1.5,track_front:1650,track_rear:1650,wheelbase:2794,rc_front:53,rc_rear:91}},Tg={name:"Hill-climb prototype",m:650,A:1.2,cl:2.5,cw:.9,frontMass:.42,frontAero:.42,rDyn:.29,drivenWheels:2,gearRatio:4,motor:go(330,3e3,8500,1240,2),motorCount:1,driveline:{rear:xt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t9",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:280,tire_vertical_rate:200,unsprung_mass:25,brake_balance:.58,arb_front:40,arb_rear:30,damper_front:3,damper_rear:3.5,spring_front:90,spring_rear:120,mr_front:.94,mr_rear:.91,cop_long:.58,cop_height:350,ride_height_front:45,ride_height_rear:55,I_yaw:550,I_roll:120,I_pitch:550,camber_front_deg:-2.5,camber_rear_deg:-1.5,track_front:1580,track_rear:1540,wheelbase:2550,rc_front:27,rc_rear:65}},Pg={name:"Race truck",m:5300,A:6.2,cl:-.1,cw:.65,frontMass:.6,frontAero:.6,rDyn:.502,drivenWheels:2,gearRatio:3.55,motor:go(880,100,3e3,88e3,2),motorCount:1,driveline:{rear:xt.spool},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t10",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:950,tire_vertical_rate:1e3,unsprung_mass:350,brake_balance:.75,arb_front:350,arb_rear:150,damper_front:12,damper_rear:8.5,spring_front:200,spring_rear:160,mr_front:.81,mr_rear:.8,cop_long:.4,cop_height:1500,ride_height_front:110,ride_height_rear:240,I_yaw:16e3,I_roll:3500,I_pitch:16e3,camber_front_deg:-.5,camber_rear_deg:-.25,track_front:2050,track_rear:1950,wheelbase:3700,rc_front:95,rc_rear:134}};function Ag(e,t,r){return Yr(r({...structuredClone(e),name:t}))}var Im={[Ga.name]:Yr(Ga),"Formula Student +15% downforce":Ag(Ga,"Formula Student +15% downforce",e=>({...e,cl:e.cl*1.15,cw:e.cw*1.08})),"Formula Student -15 kg":Ag(Ga,"Formula Student -15 kg",e=>({...e,m:e.m-15})),"Formula Student +15% power":Ag(Ga,"Formula Student +15% power",e=>({...e,motor:aA(25*1.15,15e3,2e4),powerLimitKw:80*1.15})),[Fg.name]:Yr(Fg),[Dm.name]:Yr(Dm),[Em.name]:Yr(Em),[wg.name]:Yr(wg),[Cg.name]:Yr(Cg),[Tg.name]:Yr(Tg),[Pg.name]:Yr(Pg)},sA=Object.keys(Im),Lg=sA.slice(0,4),Dg=[Ga.name,Fg.name,Dm.name,Em.name,wg.name,Cg.name,Tg.name,Pg.name];var Yre={"Touring car":Dm.name,"Street car":Em.name};var iN={bg:"#0e1116",panel:"#161b22",panel2:"#1c232d",border:"#2a323d",borderBright:"#39424e",sunken:"#11161c",ink:"#06090d"},cN={normal:"#d6dde6",dim:"#8b96a3",bright:"#e7ecf3",white:"#ffffff"},lN={label:"#c8d2dc",grid:"#39424e",gridFaint:"#232b35",empty:"#1a2028"},uN={accent:"#4aa3ff",accentInk:"#04121f",warn:"#ffb454",good:"#4ec9a0",bad:"#ff6b6b",badSoft:"#ff8f8f"},mN=["#f0e442","#7b68ee","#f7a8b8","#d55e00","#d8b4fe","#b5e48c"],_m={front:"#a6e22e",rear:"#00b4d8"},iA=["#5b4bd6","#4aa3ff","#4ec9a0","#f0e442"],Eg={power:"#ffb454",traction:"#f0845c",front:_m.front,rear:_m.rear,grip:"#73c9b3",braking:"#b48aff",crest:"#e88fd0",below:"rgba(214, 221, 230, 0.32)"},pN={chassis:"#4aa3ff",ballJoint:"#ffb454",arm:"#b8c3cf",tie:"#73c9b3",pushrod:"#e5c65f",rocker:"#9f91d4",kingpin:"#d8c968",arbBar:"#cf7898",arbArm:"#b96b86",arbLink:"#ffb454",heaveSpring:"#7ad7f0",wheelCentre:"#e7ecf3",contactPatch:"#ff6b6b",ground:"#15222e",groundFaint:"#0b151f"},dN={x:"#ff6b6b",y:"#57c75a",z:"#4aa3ff"},fN={line:"#b4bfcb"},hN={compression:"#b48aff",tension:"#ff6b6b"},bN={fz:"#e7ecf3",fx:"#7ad7f0",fy:"#ff54c8"},gN={drivenLine:"#4d7cff",axis:"#eef3fa",slip:"#ffe81a",drive:Eg.power,brake:Eg.braking},yN={ground:"#101920",grid:"#1a2630",gridMajor:"#26343f",horizon:"#1d2833",bridge:"#6f7a86",coneLeft:"#2f63c9",coneRight:"#d9b51f",coneStart:"#ee7a2c"},xN={chassis:"#435160",volume:"#303b47",tyre:"#435160",tyreLine:"#39424e",tyreFace:"#1c232d"},RN={centreLine:"#4aa3ff",corridorFill:"rgba(74,163,255,0.10)",boundary:"#3d4956",racingLine:"#ffb454",start:"#e7ecf3",finish:"#ff6b6b",direction:"#8b96a3"},vN={SURFACE:iN,TEXT:cN,CHART:lN,ROLE:uN,SERIES:mN,AXLE:_m,LAP_SPEED:iA,LIMITER:Eg,RIG:pN,AXIS:dN,CONSTRUCTION:fN,FORCE:hN,TYRE_FORCE:bN,REPLAY:gN,SCENERY:yN,BODY:xN,TRACK:RN},cA=e=>Object.fromEntries(Object.entries(e).map(([t,r])=>[t,Array.isArray(r)?Object.freeze([...r]):Object.freeze({...r})])),Nm=cA(vN),vt=Nm.SERIES,lA=(()=>{let e="#b06400",t="#d1343a",r={front:"#70bf03",rear:"#3392d0"},n={power:e,traction:"#d05a2a",front:r.front,rear:r.rear,grip:"#2a9a83",braking:"#7b55d0",crest:"#c2479f",below:"rgba(34, 39, 45, 0.28)"};return cA({SURFACE:{bg:"#f4f5f3",panel:"#fbfbfa",panel2:"#ffffff",border:"#d6dadd",borderBright:"#b7bec4",sunken:"#eceeeb",ink:"#ffffff"},TEXT:{normal:"#22272d",dim:"#5c6570",bright:"#0f1215",white:"#000000"},CHART:{label:"#3a424b",grid:"#c2c8cd",gridFaint:"#e2e5e7",empty:"#e8eae7"},ROLE:{accent:"#1a64c2",accentInk:"#ffffff",warn:e,good:"#0f8a66",bad:t,badSoft:"#e2696d"},SERIES:["#b5a11a","#2844e3","#f47ec1","#9b3a1b","#764299","#58b977"],AXLE:r,LAP_SPEED:["#4b3bc4","#1a64c2","#0f8a66","#a87e00"],LIMITER:n,RIG:{chassis:"#1a64c2",ballJoint:"#c27200",arm:"#56616d",tie:"#24907b",pushrod:"#a3820f",rocker:"#6656b8",kingpin:"#8f7f10",arbBar:"#b04d77",arbArm:"#9a4767",arbLink:"#c27200",heaveSpring:"#1688ad",wheelCentre:"#15181c",contactPatch:t,ground:"#e2e6e8",groundFaint:"#edf0f1"},AXIS:{x:"#d93a3a",y:"#2f9d34",z:"#1a64c2"},CONSTRUCTION:{line:"#5a6570"},FORCE:{compression:"#7b55d0",tension:t},TYRE_FORCE:{fz:"#15181c",fx:"#0f8fb0",fy:"#c8198f"},REPLAY:{drivenLine:"#2f5be0",axis:"#15181c",slip:"#c79a00",drive:n.power,brake:n.braking},SCENERY:{ground:"#dde3e1",grid:"#ccd3d1",gridMajor:"#b5bfbc",horizon:"#e8edf0",bridge:"#9aa3ab",coneLeft:"#2f63c9",coneRight:"#d9b51f",coneStart:"#ee7a2c"},BODY:{chassis:"#a9b3bd",volume:"#c7ced5",tyre:"#24282c",tyreLine:"#2c333a",tyreFace:"#c3cad0"},TRACK:{centreLine:"#1a64c2",corridorFill:"rgba(26,100,194,0.10)",boundary:"#a3acb4",racingLine:e,start:"#15181c",finish:t,direction:"#5c6570"}})})();var uA=e=>{let t=/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(e.trim());return t?`#${(t[1].length===3?t[1].replace(/./g,n=>n+n):t[1]).toLowerCase()}`:null},jre=(()=>{let e=new Map,t=["SERIES","AXLE","LAP_SPEED","LIMITER","ROLE","RIG","FORCE","TYRE_FORCE","REPLAY","AXIS","TRACK","CONSTRUCTION","TEXT","CHART","SCENERY","BODY","SURFACE"];for(let r of t){let n=Nm[r],o=lA[r];for(let a of Object.keys(n)){let s=uA(n[a]);s&&!e.has(s)&&e.set(s,o[a])}}return e})();var mA=(e,t)=>new Set(t.flatMap(r=>{let n=e[r];return Array.isArray(n)?[...n]:Object.values(n)}).map(uA).filter(r=>r!==null)),Ure=mA(lA,["SERIES","AXLE","LAP_SPEED","LIMITER","ROLE","RIG","FORCE","TYRE_FORCE","REPLAY","AXIS","TRACK","CONSTRUCTION"]),Xre=mA(Nm,Object.keys(Nm).filter(e=>e!=="SURFACE"));function Ig(){return{kind:"simple",name:"Simple motor",rpm:[0,16e3,2e4],torque:[21,21,14],efficiency:.95}}function _g(){return{kind:"map",name:"Mapped motor",rpm:[0,8e3,16e3,2e4],torque:[24,24,21,16],effRpm:[1e3,5e3,9e3,13e3,17e3,2e4],effTorque:[4,8,12,16,21],effGrid:[[.78,.84,.86,.85,.82,.79],[.83,.9,.93,.92,.89,.86],[.85,.93,.96,.95,.92,.89],[.84,.92,.95,.94,.91,.88],[.82,.89,.92,.9,.87,.84]]}}function Ng(){return{kind:"simple",name:"Inboard motor, axial flux (example)",rpm:[0,4e3,4500,5e3,5500,6e3],torque:[230,230,204,184,167,153],efficiency:.95}}function Og(){return{kind:"ice",name:"600 cc four, restricted (example)",rpm:[3e3,4e3,5e3,6e3,7e3,8e3,9e3,1e4,11e3,12e3,12500],torque:[40,46,52,56,59,61,62,60,56,49,45],idleRpm:3e3,limitRpm:12500,inertia:.012,gearbox:{primary:76/36,ratios:[33/12,32/16,30/18,26/18,30/23,29/24],efficiency:.9,upshiftTime:.1,downshiftTime:.08},breathing:{induction:{kind:"natural"}}}}function Vg(){return{kind:"ice",name:"Formula 1 power unit (example)",rpm:[4e3,5e3,6e3,7e3,8e3,9e3,1e4,10500,11e3,11500,12e3,12500],torque:[896,822,773,738,712,692,675,668,638,610,585,545],idleRpm:4e3,limitRpm:12500,inertia:.02,gearbox:{primary:1,ratios:[4,3.15,2.575,2.175,1.85,1.6,1.375,1.18],efficiency:.94,upshiftTime:0,downshiftTime:0,driveKept:1},breathing:{induction:{kind:"boosted",boostKPa:350,maxPressureRatio:5}}}}function pA(){return{kind:"ice",name:"GT race engine, 4.0 l (example)",rpm:[2500,3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3,7500,8e3],torque:[380,410,440,465,485,500,515,525,530,540,522,480],idleRpm:2500,limitRpm:8e3,inertia:.15,gearbox:{primary:1,ratios:[3,2.15,1.7,1.4,1.17,.98],efficiency:.93,upshiftTime:.05,downshiftTime:.08},breathing:{induction:{kind:"natural"}}}}function dA(){return{kind:"ice",name:"Turbocharged 3.0 l six (example)",rpm:[1e3,1500,1800,2500,3500,4500,5e3,5500,6e3,6500,7e3],torque:[230,340,400,400,400,400,400,382,350,315,280],idleRpm:1e3,limitRpm:7e3,inertia:.2,gearbox:{primary:1,ratios:[3.6,2.19,1.54,1.21,1,.83],efficiency:.92,upshiftTime:.2,downshiftTime:.2,driveKept:.8},breathing:{induction:{kind:"boosted",boostKPa:220,maxPressureRatio:3}}}}function fA(){return{kind:"ice",name:"Turbocharged 2.0 l four (example)",rpm:[2e3,2500,3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3],torque:[330,400,420,420,420,420,415,410,398,365,330],idleRpm:2e3,limitRpm:7e3,inertia:.15,gearbox:{primary:1,ratios:[2.92,2.05,1.61,1.32,1.12,.97],efficiency:.93,upshiftTime:.07,downshiftTime:.08},breathing:{induction:{kind:"boosted",boostKPa:250,maxPressureRatio:3.2}}}}function hA(){return{kind:"ice",name:"Stock car V8, 5.9 l (example)",rpm:[2500,3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3,7500,8e3,8500,9e3],torque:[450,480,510,535,555,570,585,595,600,598,590,578,562,525],idleRpm:2500,limitRpm:9e3,inertia:.18,gearbox:{primary:1,ratios:[2.8,2,1.55,1.24,1],efficiency:.93,upshiftTime:.1,downshiftTime:.1},breathing:{induction:{kind:"natural"}}}}function bA(){return{kind:"ice",name:"Turbocharged 2.0 l four, hill climb (example)",rpm:[3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3,7500,8e3,8500],torque:[314,380,446,462,462,462,458,450,437,420,388,347],idleRpm:3e3,limitRpm:8500,inertia:.1,gearbox:{primary:1,ratios:[2.69,2,1.6,1.33,1.14,1],efficiency:.93,upshiftTime:.05,downshiftTime:.08},breathing:{induction:{kind:"boosted",boostKPa:250,maxPressureRatio:4.5}}}}function gA(){return{kind:"ice",name:"Race truck diesel six, 13 l (example)",rpm:[800,1e3,1200,1400,1600,1800,2e3,2200,2400,2600,2800,3e3],torque:[3e3,4e3,4900,5500,5250,4670,4200,3820,3500,3230,3e3,2700],idleRpm:800,limitRpm:3e3,inertia:1.5,gearbox:{primary:1,ratios:[16,12.44,9.67,7.51,5.84,4.54,3.53,2.74,2.13,1.66,1.29,1],efficiency:.92,upshiftTime:.35,downshiftTime:.35},breathing:{induction:{kind:"boosted",boostKPa:350,maxPressureRatio:4.3}}}}function yA(e){return co(kN(e))}function kN(e){if(e===null||typeof e!="object"||Array.isArray(e))return e;let t={...e};return delete t.name,Array.isArray(t.vehicles)&&(t.vehicles=t.vehicles.map(r=>{if(r===null||typeof r!="object"||Array.isArray(r))return r;let n={...r};return delete n.name,n})),t}function oc(e,t){return{...t,fingerprint:yA(e)}}var xA="CC-BY-4.0",MN={title:"PaceDynamics built-in library",url:"https://pacedyn.dev/",licence:xA},RA={fidelity:"generic",licence:xA,sources:[MN]};var Om=e=>oc(e,RA);var vA=["raw.githubusercontent.com"],kA=["tum-csv"],AN=/^[0-9a-f]{64}$/;function sc(e){if(typeof e!="object"||e===null||Array.isArray(e))return!1;let{url:t,sha256:r,format:n}=e;if(typeof t!="string"||t.length>500||typeof r!="string"||!AN.test(r)||!kA.includes(n))return!1;try{let o=new URL(t);return o.protocol==="https:"&&vA.includes(o.hostname)&&!o.username&&!o.password&&!o.port}catch{return!1}}var Vm=e=>new URL(e.url).hostname;async function MA(e){let t=await globalThis.crypto.subtle.digest("SHA-256",e);return[...new Uint8Array(t)].map(r=>r.toString(16).padStart(2,"0")).join("")}function FN(e){let t=new URL(e).pathname.split("/").pop()??"";return decodeURIComponent(t).replace(/\.[^.]*$/,"")||"Linked track"}function wN(e,t){let r=[],n=[],o=[],a=[];for(let[s,i]of e.split(/\r?\n/).entries()){let c=i.trim();if(!c||c.startsWith("#"))continue;let l=c.split(",").map(u=>Number(u.trim()));if(l.length!==4||!l.every(Number.isFinite))throw new Error(`Line ${s+1} of ${t} is not four numbers.`);r.push(l[0]),n.push(l[1]),o.push(l[2]),a.push(l[3])}if(r.length<3)throw new Error(`${t} has ${r.length} points; a track needs at least 3.`);return{name:t,x:r,y:n,widthLeft:a,widthRight:o,closed:!0,fit:"interpolate"}}var CN={"tum-csv":wN};function SA(e,t){return CN[t.format](e,FN(t.url))}async function Bg(e,t,r){let n=await MA(e);if(n!==t.sha256)throw new Error(`${Vm(t)} did not return the file that was reviewed (its SHA-256 is ${n.slice(0,12)}\u2026, not ${t.sha256.slice(0,12)}\u2026).`);let o=SA(new TextDecoder().decode(e),t),a=await Bm(o);if(a!==r)throw new Error(`Linked track ${r} does not convert to its name (it is ${a}).`);return o}var $g=20,PN=new RegExp(`^[0-9a-f]{${$g}}$`),ic=e=>typeof e=="string"&&PN.test(e);async function Bm(e){let t=new TextEncoder().encode(vn(e)),r=await globalThis.crypto.subtle.digest("SHA-256",t);return[...new Uint8Array(r)].map(n=>n.toString(16).padStart(2,"0")).join("").slice(0,$g)}var Gg=e=>`tracks/${e}.json`;var LN=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function Kg(e){return{model:{name:e.name,source:e.source},...e.provenance?{provenance:e.provenance}:{}}}async function Hg(e,t){if(!LN(e)||typeof e.name!="string"||!Array.isArray(e.x)||!Array.isArray(e.y)||e.x.length!==e.y.length||e.x.length<2)throw new Error(`Catalogue track ${t} is not a track.`);let r=await Bm(e);if(r!==t)throw new Error(`Catalogue track ${t} does not match its name (it is ${r}).`);return e}var yo=(e,t,r,n=[])=>({doc:e,ref:t,refs:[t,...n.map(o=>o.ref)],slots:[{key:e,ref:t,label:r},...n],label:r}),kn=[yo("suspensions","suspensionId","suspension"),yo("tires","tireModelId","tyre",[{key:"tiresRear",ref:"tireModelIdRear",label:"rear tyre"}]),yo("motors","motorModelId","motor"),yo("aeros","aeroModelId","aero map"),yo("batteries","batteryModelId","battery"),yo("brakes","brakeModelId","brakes"),yo("dampers","damperModelId","dampers",[{key:"dampersRear",ref:"damperModelIdRear",label:"rear dampers"},{key:"dampersHeave",ref:"heaveDamperModelId",label:"heave dampers"},{key:"dampersRoll",ref:"rollDamperModelId",label:"roll dampers"}])];function $m(e){let t={...e};for(let r of kn)for(let n of r.refs)delete t[n];return t}var Gm=vt,cc=Gm,zg=Gm,Mn=[...vt.slice(3),...vt.slice(0,3)],jg=[...vt.slice(1),vt[0]],Yg=[...vt.slice(2),...vt.slice(0,2)],Wg=[...vt.slice(4),...vt.slice(0,4)],Ug=[...vt.slice(5),...vt.slice(0,5)],lc=[...vt.slice(2),...vt.slice(0,2)];function Xg(){let e=globalThis.crypto;return e&&typeof e.randomUUID=="function"?e.randomUUID():`p-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}function qg(e,t,r){let n=Im[e];if(!n)throw new Error(`no preset vehicle named "${e}"`);return{id:t,params:{...ui(structuredClone(n)),energy:{...Lr},suspensionId:"sus1"},visible:!0,color:cc[r%cc.length]}}function IN(){return Lg.map((e,t)=>qg(e,`v${t+1}`,t))}function _N(){return[Gs(),Ef(),If(),_f(),Nf(),Of(),Vf(),Bf(),$f(),Gf()].map((t,r)=>({id:`t${r+1}`,color:zg[r%zg.length],model:t}))}function NN(){return[dd(),fd(),hd(),bd(),gd(),yd(),xd(),Rd()].map((t,r)=>({id:`a${r+1}`,color:Yg[r%Yg.length],model:t}))}function ON(){return[Zp(),Jp(),ed()].map((t,r)=>({id:`b${r+1}`,color:Wg[r%Wg.length],model:t}))}function VN(){return[{id:"brk1",color:Ug[0],model:structuredClone(sh)}]}function BN(){return[{id:"dmp1",color:lc[0],model:structuredClone(yu)}]}function $N(){return[Ig(),_g()].map((t,r)=>({id:`m${r+1}`,color:Mn[r%Mn.length],model:t}))}function Qg(e){let t=r=>({...r,provenance:Om(r.model)});return{...e,suspensions:e.suspensions.map(t),vehicles:e.vehicles.map(r=>({...r,provenance:Om($m(r.params))})),tires:e.tires.map(t),motors:e.motors.map(t),aeros:e.aeros.map(t),batteries:e.batteries.map(t),brakes:e.brakes.map(t),dampers:e.dampers.map(t)}}function uc(e="Untitled project"){let t=new Date().toISOString(),r=IN();return Qg({schemaVersion:Fm,meta:{id:Xg(),name:e,domain:"racecar",rulesetId:lo,createdAt:t,updatedAt:t},suspensions:[{id:"sus1",color:jg[0],model:bo()}],activeSuspensionId:"sus1",vehicles:r,activeVehicleId:r[0]?.id??null,tires:_N(),motors:$N(),aeros:NN(),batteries:ON(),brakes:VN(),dampers:BN(),tracks:[],activeTrackId:null,mathChannels:[],rulesets:[],studies:[],activeStudyId:null,loadCases:[],reportLayouts:[],tyreSheets:[],kinSheets:[],plans:[],results:[],settings:{numerics:{...Fi},ggvMode:"twoTrack",quasiTransient:!1,motorThermal:!1,brakeFade:!1,airTempC:At,air:structuredClone(Cm),diffYaw:!1,lapCounts:{},pathPlanId:null,useRacingLine:!0,standingStart:!1}})}var GN=["front","rear"],Zg=9.81,KN=Math.PI/180;var Wr="*",Jg=40,AA=.8;function e0(e){let{s:t,curvature:r}=e;if(!t?.length||t.length!==r?.length)return null;let n=0,o=0,a=0,s=0;for(let i=0;i<t.length;i++){for(;a<t.length&&t[a]<=t[i]+2.5;)s+=Math.abs(r[a++]);for(;t[o]<t[i]-2.5;)s-=Math.abs(r[o++]);let c=s/Math.max(1,a-o);c>n&&(n=c)}return n>1e-6?1/n:null}function FA(e,t,r){let n=t.rows.map(c=>c.v),o=c=>mt(n,t.rows.map(l=>l.ayMax),Math.min(n[n.length-1],Math.max(n[0],c))),a=(c,l,u)=>({speedKmh:Math.round(c*36)/10,ayG:Math.round(l/Zg*100)/100+0,axG:Math.round(u/Zg*100)/100+0}),s=t.vMax,i=Array.from({length:41},(c,l)=>20/3.6+l*Math.max(0,s-20/3.6)/40);switch(e){case"slowCorner":{if(r===null)return a(Jg/3.6,o(Jg/3.6),0);let c=10;for(let l=0;l<30;l++)c=Math.min(s,Math.sqrt(r*o(c)));return a(c,o(c),0)}case"fastCorner":return a(AA*s,o(AA*s),0);case"braking":{let c=i.reduce((l,u)=>t.axDecel(u,0)<t.axDecel(l,0)?u:l);return a(c,0,t.axDecel(c,0))}case"traction":{let c=i.reduce((l,u)=>t.axAccel(u,0)>t.axAccel(l,0)?u:l);return a(c,0,t.axAccel(c,0))}case"topSpeed":return a(s,0,0)}}function t0(e,t,r){let n=!1,o=e.map(a=>{if(!a.follows)return a;let s=FA(a.follows,t,r);return![s.speedKmh,s.ayG,s.axG].every(Number.isFinite)||!t.rows.some(i=>i.ayMax>0)||s.speedKmh===a.speedKmh&&s.ayG===a.ayG&&s.axG===a.axG?a:(n=!0,{...a,...s})});return n?o:e}function r0(e,t){let r=e.speedKmh/3.6,n=e.ayG*Zg;if(!(Math.abs(n)>1e-6)||!(r>.1))return 0;let o=r*r/Math.abs(n);return Math.sign(n)*Math.atan(t/1e3/o)/KN}var wA=e=>e.ayG<0?"L":"R";function n0(e,t=GN){if(!e.length||!t.length)return null;let r=t.flatMap(i=>i==="front"?["FL","FR"]:["RL","RR"]),n=0,o=0,a=0;for(let i of e){for(let c of r){let l=i.corners[c].travel;if(!Number.isFinite(l))return null;n=Math.min(n,l),o=Math.max(o,l)}a=Math.max(a,Math.abs(i.rollDeg))}let s=5;return{travelMin:Math.min(-1,Math.floor(n-s)),travelMax:Math.max(1,Math.ceil(o+s)),rollMaxDeg:Math.max(.5,Math.ceil((a+.5)*10)/10),rollAtLimitDeg:Math.ceil(a*10)/10}}var o0=(e,t)=>e.travelMin===t.travelMin&&e.travelMax===t.travelMax&&e.rollMaxDeg===t.rollMaxDeg&&e.rollAtLimitDeg===t.rollAtLimitDeg;var jr=Math.PI/180,HN=9.81,mc=.1,a0=20,CA=6,DA=50;function TA(e,t,r){let n=e(0),o=0;for(let f=t;f<=r+1e-9;f+=t){let p=e(f);if(p>n)n=p,o=f;else if(f>o+3*t)break}let a=Math.max(0,o-t),s=Math.min(r,o+t),i=.6180339887498949,c=s-i*(s-a),l=a+i*(s-a),u=e(c),m=e(l);for(let f=0;f<14;f++)u>m?(s=l,l=c,m=u,c=s-i*(s-a),u=e(c)):(a=c,c=l,u=m,l=a+i*(s-a),m=e(l));return u>n?u>=m?{force:u,at:c}:{force:m,at:l}:m>n?{force:m,at:l}:{force:n,at:o}}function s0(e,t,r,n,o){let a=o*jr;if(t==="side")return TA(i=>r*e.Fy(r*i*jr,n,a),1,45);let s=t==="drive"?1:-1;return TA(i=>s*e.Fx(s*i,n,a),.02,.6)}function Hm(e){let t=e?Vl(e)?.gamma:void 0,r=[t?.min,t?.max].filter(o=>o!==void 0&&Number.isFinite(o));if(!r.length)return{lo:-CA,hi:CA,stated:!1};let n=Math.max(...r.map(Math.abs))/jr;return{lo:-n,hi:n,stated:!0}}function zN(e,t,r){if(!(r>t))return t;let n=Math.max(2,Math.ceil(r-t)+1),o=(r-t)/(n-1),a=t,s=-1/0;for(let h=0;h<n;h++){let b=t+h*o,g=e(b);g>s&&(s=g,a=b)}let i=Math.max(t,a-o),c=Math.min(r,a+o),l=.6180339887498949,u=c-l*(c-i),m=i+l*(c-i),f=e(u),p=e(m);for(let h=0;h<12;h++)f>p?(c=m,m=u,p=f,u=c-l*(c-i),f=e(u)):(i=u,u=m,f=p,m=i+l*(c-i),p=e(m));let d=f>=p?{g:u,v:f}:{g:m,v:p};return d.v>s?d.g:a}var PA=250,LA=new WeakMap;function YN(e,t,r,n,o,a,s){let i=LA.get(e);i||LA.set(e,i=new Map);let c=`${t}|${n}|${o}|${s.lo}|${s.hi}`,l=i.get(c);l||i.set(c,l=new Map);let u=d=>{let h=l.get(d);if(h===void 0){let b=Math.max(50,d*PA);h=zN(g=>s0(r,n,o,b,g).force,s.lo,s.hi),l.set(d,h)}return h},m=Math.max(0,a)/PA,f=Math.floor(m),p=m-f;return p<1e-9?u(f):u(f)*(1-p)+u(f+1)*p}function Ka(e,t){return t==="front"?e.tireModel:e.tireModelRear??e.tireModel}var WN=new WeakMap,jN=new WeakMap,UN=new WeakMap,i0=(e,t,r)=>{let n=e.get(t);return n===void 0&&e.set(t,n=r()),n};function c0(e,t){let r=Ka(e,t);return r?i0(WN,r,()=>Is(r))?null:"This tyre\u2019s side force does not change with camber, so it wants no camber.":"The car runs the built-in simple tyre, which has no camber term."}function l0(e,t){let r=Ka(e,t);return r?i0(UN,r,()=>Bl(r).none)?"This tyre file has no drive or brake grip.":i0(jN,r,()=>{let n=Pe(r),o=r.kind==="magic"?r.fnomin:r.nominalLoad,a=n.Fx(.1,o,0),s=n.Fx(.1,o,3*jr);return Number.isFinite(a)&&Number.isFinite(s)&&Math.abs(s-a)>1})?null:"This tyre\u2019s drive and brake grip does not change with camber.":"The car runs the built-in simple tyre, which has no camber term."}function xo(e,t){return e==="side"||e==="ackermann"?Math.abs(t.ayG)>=mc?e==="ackermann"&&!(EA(t)<=a0)?`is a corner wider than ${a0} m`:null:"does not corner":(e==="drive"?t.axG:-t.axG)>=mc?null:e==="drive"?"does not drive":"does not brake"}var XN=e=>e.axG>=mc?"drive":e.axG<=-mc?"brake":null;function EA(e){let t=e.speedKmh/3.6,r=Math.abs(e.ayG)*HN;return r>1e-9?t*t/r:1/0}var Km=(e,t)=>`${e==="front"?"F":"R"}${t}`,qN=e=>e==="L"?"R":"L",QN=(e,t,r)=>Math.min(r,Math.max(t,e));function u0({ev:e,params:t,input:r,state:n,pose:o}){let a=`${Q(t,"grip_scale")}|${Q(t,"stiffness_scale")}`,s=EA(n),i=r.wheelbase*(1-r.frontMassFrac)/1e3,c=r.wheelbase*r.frontMassFrac/1e3,l=r.wheelbase/1e3,u=k=>(k==="front"?r.trackFront:r.trackRear)/2e3,m=(k,v,x,M,F)=>{let w=ge(e,k),C=Ka(t,k),T=Math.max(0,o.loads[v]),S=o.camber[v],A=QN(S,F.lo,F.hi),P=s0(w,x,M,T,A),L=T<DA,D=C&&!L?YN(C,a,w,x,M,T,F):A,E=L?P.force:s0(w,x,M,T,D).force,V=.05;return{corner:v,Fz:T,lifted:L,camber:S,read:A,outside:A!==S,wants:D,atEdge:!L&&(D-F.lo<V||F.hi-D<V),peak:P.force,slip:P.at,best:E}},f=(k,v,x)=>{let M=v[0].best+v[1].best,F=v[0].peak+v[1].peak;return{kind:k,wheels:v,lossCamber:M>0?Math.max(0,1-F/M):NaN,range:x}},p=new Map,d=k=>{if(p.has(k))return p.get(k)??null;let v=null;if(!xo("side",n)){let x=Hm(Ka(t,k));v=[m(k,Km(k,o.outer),"side",1,x),m(k,Km(k,qN(o.outer)),"side",-1,x)]}return p.set(k,v),v},h=new Map,b=new Map,g=new Map,y=(k,v,x)=>{let M=k==="front"?i:-c,F=(v?1:-1)*u(k),w=x*jr;return Math.atan2(M+s*Math.sin(w),s*Math.cos(w)-F)/jr},R=k=>(n.ayG<0?-1:1)*o.steer[k];return{side(k){if(h.has(k))return h.get(k)??null;let v=c0(t,k)?null:d(k),x=v?f("side",v,Hm(Ka(t,k))):null;return h.set(k,x),x},long(k){if(b.has(k))return b.get(k)??null;let v=XN(n),x=null;if(v&&!l0(t,k)){let M=Hm(Ka(t,k));x=f(v,[m(k,Km(k,"L"),v,1,M),m(k,Km(k,"R"),v,1,M)],M)}return b.set(k,x),x},toeLoss(k){let v=g.get(k);if(v!==void 0)return v;let x=d(k),M=NaN;if(x&&x[0].peak+x[1].peak>0){let F=ge(e,k),[w,C]=x,T=[{g:w,dt:1,inner:!1,steer:R(w.corner)},{g:C,dt:-1,inner:!0,steer:R(C.corner)}],S=E=>T.reduce((V,N)=>{let z=N.steer-y(k,N.inner,E);return V+N.dt*F.Fy(N.dt*z*jr,N.g.Fz,N.g.read*jr)},0),A=T.map(E=>E.steer-E.g.slip-y(k,E.inner,0)),P=Math.min(...A)-2,L=Math.max(...A)+2,D=ZN(S,P,L,.25);M=Math.max(0,1-D/(w.peak+C.peak))}return g.set(k,M),M},ackermann(){if(xo("ackermann",n))return NaN;let k=d("front");if(!k||k[0].lifted||k[1].lifted)return NaN;let[v,x]=k,M=Math.sqrt(Math.max(s*s-c*c,1e-6)),F=u("front"),w=(Math.atan(l/(M-F))-Math.atan(l/(M+F)))/jr;if(!(w>.001))return NaN;let C=R(x.corner)-R(v.corner),T=w+(x.slip-v.slip);return 100*(C-T)/w}}}function ZN(e,t,r,n){let o=-1/0,a=t;for(let p=t;p<=r+1e-9;p+=n){let d=e(p);d>o&&(o=d,a=p)}let s=a-n,i=a+n,c=.6180339887498949,l=i-c*(i-s),u=s+c*(i-s),m=e(l),f=e(u);for(let p=0;p<14;p++)m>f?(i=u,u=l,f=m,l=i-c*(i-s),m=e(l)):(s=l,l=u,m=f,u=s+c*(i-s),f=e(u));return Math.max(o,m,f)}var JN=9.81,IA=Math.PI/180,pc={speed:20,ayG:1.2};function m0(e,t={}){let r=t.operating??pc,n=t.assemble,o,a,s,i=new Map,c=new Map,l=new Map,u=new Map,m=new Map,f=v=>({speed:v?.speed!==void 0&&Number.isFinite(v.speed)&&v.speed>0?v.speed:r.speed,ayG:v?.ayG!==void 0&&Number.isFinite(v.ayG)?v.ayG:r.ayG}),p=()=>{if(o!==void 0)return o;if(!n)return o=null;try{o=n(e)}catch{o=null}return o},d=()=>{if(a!==void 0)return a;try{a=mr(e.params)}catch{a=null}return a},h=v=>{let x=f(v),M=`${x.speed}|${x.ayG}`,F=i.get(M);if(F!==void 0)return F;let w=d();if(!w)return i.set(M,null),null;let C={cornerStiffness:T=>w.corneringStiffness(T),ayG:x.ayG,speed:x.speed,fyAxle:(T,S)=>2*w.Fy(T,S/2),tire:w};return i.set(M,C),C},b=()=>{if(s!==void 0)return s;let v=p(),x=d();if(!v||!x)return s=null;try{s=jn(x,v.massTotal*JN*1.2)}catch{s=null}return s},g=v=>{let x=f(v).speed,M=`${x}`,F=c.get(M);if(F!==void 0)return F;let w=p(),C=d(),T=null;if(w&&C)try{T=rb(w,C,x,{steering:!1})}catch{T=null}return c.set(M,T),T},y=v=>{let x=`${v.speedKmh}|${v.ayG}|${v.axG}`,M=m.get(x);if(M!==void 0)return M;let F=null,w=p();try{let C=w?.kinFront,T=w?.kinRear;if(w&&C&&T){let S=r0(v,w.wheelbase),A=v.speedKmh/3.6,P=ln(w,C,T,A)(v.ayG,v.axG,0,S),L={FL:P.FL.travel,FR:P.FR.travel},D=Xn(w,S*IA,L),E=S?D.camber:null,V={},N={};for(let I of["FL","FR","RL","RR"]){let _=I[1]==="R"?P[I].camberRoad:0-P[I].camberRoad;V[I]=_+(E?.[I]??0),N[I]=D.steer[I]/IA+(I[1]==="R"?1:-1)*P[I].bumpToe}let z=Ce(w,v.ayG,v.axG,A,0,S,L,P.steeringJacking);F={corners:P,rollDeg:P.FL.camberRoad-P.FL.camber,steerDeg:S,camber:V,outer:wA(v),loads:z,steer:N}}}catch{F=null}return m.set(x,F),F},R=new Map;return{operating:r,dynAvailable:!!n,poseAt:y,tyreAt:v=>{let x=`${v.speedKmh}|${v.ayG}|${v.axG}`,M=R.get(x);if(M!==void 0)return M;let F=y(v),w=p(),C=d(),T=F&&w&&C?u0({ev:C,params:e.params,input:w,state:v,pose:F}):null;return R.set(x,T),T},operatingAt:f,dynInput:p,tyre:d,dynCtx:h,grip:b,ymd:g,ymdLimit:v=>{let x=`${f(v).speed}`,M=l.get(x);if(M!==void 0)return M;let F=g(v),w=F?Eb(F):null;return l.set(x,w),w},reserves:(v,x)=>{let M=f(x),F=`${v}|${M.speed}|${M.ayG}`,w=u.get(F);if(w!==void 0)return w;let C=p(),T=h(x),S=null;if(C&&T)try{S=Di(C,T,v,b()??void 0)}catch{S=null}return u.set(F,S),S}}}var _A=["widthLeft","widthRight","bank","mu"];function dc(e){let t=e.x.length,r=new Array(t).fill(0);for(let n=1;n<t;n++)r[n]=r[n-1]+Math.hypot(e.x[n]-e.x[n-1],e.y[n]-e.y[n-1]);return r}function p0(e){let t=dc(e),r=e.x.length;return r===0?0:e.closed===!1||r<2?t[r-1]:t[r-1]+Math.hypot(e.x[0]-e.x[r-1],e.y[0]-e.y[r-1])}function Ym(e,t,r,n={}){let o=t.length,a=l=>{let u=n[l];return u&&u.length===o?u.slice():new Array(o).fill(r[l])},s={widthLeft:a("widthLeft"),widthRight:a("widthRight"),bank:a("bank"),mu:a("mu")};if(!e.length)return s;let i=[...e].sort((l,u)=>l.from-u.from),c=o?t[o-1]:0;for(let l of i){if(!(l.to>l.from))continue;let u=Math.max(0,l.ramp??0),m=l.to>=c-1e-9;for(let f of _A){let p=l[f];if(p===void 0)continue;let d=s[f],h=r[f];for(let b=0;b<o&&t[b]<l.from;b++)h=d[b];for(let b=0;b<o;b++){let g=t[b];if(g<l.from||g>=l.to&&!(m&&g>=c-1e-9))continue;let y=g-l.from;d[b]=u>0&&y<u?h+(p-h)*(y/u):p}}}return s}function Wm(e,t,r){if(!t.length)return e;let n=dc(e),o=n.length,a={widthLeft:zm(e.widthLeft,r.widthLeft),widthRight:zm(e.widthRight,r.widthRight),bank:zm(e.bank,r.bank),mu:zm(e.mu,r.mu)},s={};for(let c of _A){let l=e[c];Array.isArray(l)&&l.length===o&&(s[c]=l)}let i=Ym(t,n,a,s);return{...e,...i}}function zm(e,t){return typeof e=="number"?e:t}var VA=1,NA=4,Um=Math.PI/180,d0=e=>e===null||!Number.isFinite(e)||e===0?0:1/e;function f0(e){return e.kind==="arc"?Math.abs(e.radius)*Math.abs(e.angle)*Um:e.length}function jm(e,t){return e.kind==="straight"?0:e.kind==="arc"?d0(e.radius):t}function OA(e){return e.kind==="straight"?0:e.kind==="arc"?d0(e.radius):d0(e.endRadius)}var fc=(e,t,r,n,o)=>e+t*o+(n>0?(r-t)*o*o/(2*n):0);function hc(e,t={}){let r=Math.max(.05,t.spacing??VA),n=t.closed!==!1,o=t.start??{x:0,y:0,heading:0},a=t.base??{widthLeft:1.5,widthRight:1.5,bank:0,mu:1},s=[],i=[],c=[],l=[],u=e.reduce((S,A)=>S+f0(A),0),m=Math.max(n?3:2,Math.round(u/r)),f=u>0?u/m:r,p=o.x,d=o.y,h=o.heading*Um,b=e.length?jm(e[0],0):0,g=0,y=f,R=(S,A,P)=>{s.push(S),i.push(A),c.push(P)};R(p,d,0);let k=(S,A,P,L,D)=>{let E=D-L;if(E<=0)return;if(Math.abs(A-S)<1e-12){let N=fc(h,S,S,P,L);if(Math.abs(S)<1e-12)p+=E*Math.cos(N),d+=E*Math.sin(N);else{let z=N+S*E;p+=(Math.sin(z)-Math.sin(N))/S,d+=-(Math.cos(z)-Math.cos(N))/S}return}let V=E/NA;for(let N=0;N<NA;N++){let z=L+N*V,I=fc(h,S,A,P,z),_=fc(h,S,A,P,z+V/2),B=fc(h,S,A,P,z+V);p+=V/6*(Math.cos(I)+4*Math.cos(_)+Math.cos(B)),d+=V/6*(Math.sin(I)+4*Math.sin(_)+Math.sin(B))}};for(let S of e){let A=f0(S),P=jm(S,b),L=OA(S);if(l.push({from:g,to:g+A,...S.widthLeft!==void 0?{widthLeft:S.widthLeft}:{},...S.widthRight!==void 0?{widthRight:S.widthRight}:{},...S.bank!==void 0?{bank:S.bank}:{},...S.mu!==void 0?{mu:S.mu}:{},...S.ramp!==void 0?{ramp:S.ramp}:{}}),A<=0){b=L;continue}let D=0;for(;y<=g+A+1e-9;){let E=Math.min(A,y-g);k(P,L,A,D,E),D=E,R(p,d,g+E),y+=f}k(P,L,A,D,A),h=fc(h,P,L,A,A),b=L,g+=A}let v=s.length>1?Math.hypot(s[0]-s[s.length-1],i[0]-i[i.length-1]):0,x=g;n&&s.length>1&&(s.pop(),i.pop(),c.pop());let M=e.length?jm(e[0],b):0,F={gap:v,headingError:eO((h-o.heading*Um)/Um),curvatureError:b-M},w=[];for(let S=0;S<e.length;S++){let A=OA(e[S]),P=S+1<e.length?e[S+1]:n?e[0]:null;if(!P)continue;let L=jm(P,A);w.push({index:S,before:A,after:L,jump:Math.abs(L-A)})}let C=Ym(l,c,a);return{asset:{name:t.name??"Track",x:s,y:i,fit:"interpolate",...n?{}:{closed:!1},...C},sections:l,joints:w,closure:F,length:x}}function eO(e){let t=e%360;return t>180&&(t-=360),t<-180&&(t+=360),t}var tO={halfWidthM:1.5,spacingM:.5};function bc(e){switch(e.kind){case"skidpad":return`${e.radiusM.toFixed(2)} m constant-radius circle`;case"acceleration":return`${e.distanceM.toFixed(0)} m straight from rest`;case"slalom":return`${e.gates} gates at ${e.pitchM.toFixed(1)} m, \xB1${e.offsetM.toFixed(2)} m`;case"curves":{let t=e.segments.filter(r=>r.kind==="arc").length;return`${t} ${t===1?"curve":"curves"} over ${$A(e).toFixed(0)} m`}}}function $A(e){switch(e.kind){case"skidpad":return 2*Math.PI*e.radiusM;case"acceleration":return e.distanceM;case"slalom":return e.leadInM+Math.max(1,e.gates)*e.pitchM;case"curves":return e.segments.reduce((t,r)=>t+(r.kind==="arc"?Math.abs(r.angle)*Math.PI*Math.abs(r.radius)/180:r.length),0)}}var GA=e=>e.kind==="skidpad"||e.kind==="curves"&&e.closed===!0,KA=e=>e.kind==="acceleration",HA=1.5,zA=3;function rO(e,t){let r=e.offsetM,n=e.pitchM,o=Math.max(1,e.gates)*n,a=Math.max(0,e.leadInM),s=HA*n,i=h=>{let b=Math.min(1,Math.max(0,h));return b*b*b*(b*(b*6-15)+10)},c=h=>Math.min(i(h/s),i((o-h)/s)),l=r*(Math.PI/n)**2,u=l>0?Math.max(.05,Math.min(t.spacingM,1/l*(zA*Math.PI/180))):t.spacingM,m=[],f=[],p=Math.max(1,Math.round(a/u));for(let h=0;h<p;h++)m.push(-a+a*h/p),f.push(0);let d=Math.max(8,Math.round(o/u));for(let h=0;h<=d;h++){let b=o*h/d;m.push(b),f.push(r*c(b)*Math.sin(Math.PI*b/n))}return{name:bc(e),x:m,y:f,closed:!1,widthLeft:t.halfWidthM,widthRight:t.halfWidthM,fit:"interpolate"}}function nO(e){switch(e.kind){case"skidpad":return[{kind:"arc",radius:e.radiusM,angle:360}];case"acceleration":return[{kind:"straight",length:e.distanceM}];case"curves":return e.segments;case"slalom":return null}}function h0(e,t={}){let r={...tO,...t},n=KA(e),o=nO(e);if(!o){let u=rO(e,r);return{asset:u,peakCurvature:BA(u),worstJoint:0,standingStart:n}}let a=GA(e),s=o.reduce((u,m)=>m.kind==="arc"?Math.min(u,Math.abs(m.radius)):u,1/0),i=Number.isFinite(s)?Math.max(.05,Math.min(r.spacingM,s*(zA*Math.PI/180))):r.spacingM,c=hc(o,{name:bc(e),spacing:i,closed:a,base:{widthLeft:r.halfWidthM,widthRight:r.halfWidthM,bank:0,mu:1}}),l=a?c.joints:c.joints.filter(u=>u.index<o.length-1);return{asset:c.asset,peakCurvature:BA(c.asset),worstJoint:l.reduce((u,m)=>Math.max(u,m.jump),0),standingStart:n}}function BA(e){try{return Math.max(...it(e).curvature.map(Math.abs))}catch{return NaN}}var qm={courses:[{id:"c1",course:{kind:"manoeuvre",spec:{kind:"skidpad",radiusM:8.375}}}],ggvMode:"twoTrack"};function b0(e){return e.course.kind==="project"?"the project\u2019s track":e.course.kind==="track"?e.course.name:bc(e.course.spec)}var YA=new WeakMap,Xm=new Map;function WA(e,t,r){if(e.kind==="project"||e.kind==="track"){let i=(e.kind==="project"?t.projectTrack?.():t.libraryTrack?.(e.trackId))??null;return i?{asset:i.asset,standingStart:i.standingStart,numerics:i.numerics}:null}let n=JSON.stringify(e.spec),o=Xm.get(n);if(o)return{...o,numerics:r};let a=h0(e.spec),s={asset:a.asset,standingStart:a.standingStart};return Xm.size>64&&Xm.clear(),Xm.set(n,s),{...s,numerics:r}}function g0(e,t,r={}){let n=r.lap??qm,o=r.simParams,a=r.numerics??{},s=n.courses.length?n.courses:qm.courses,i,c,l,u=new Map,m=new Map,f=new Map,p=new Map,d=k=>(k?.courseId?s.find(v=>v.id===k.courseId):void 0)??s[0],h=()=>{if(i!==void 0)return i;if(!o)return i=null;try{i={...o(e),ggvMode:n.ggvMode}}catch{i=null}return i},b=k=>{let v=d(k);if(!v)return null;let x=m.get(v.id);if(x!==void 0)return x;let M=WA(v.course,r,a),F=null;if(M)try{let w=JSON.stringify(M.numerics),C=YA.get(M.asset);C||(C=new Map,YA.set(M.asset,C));let T=C.get(w);T||(T=it(M.asset,M.numerics),C.set(w,T)),F={id:v.id,track:T,standingStart:M.standingStart,numerics:M.numerics,name:M.asset.name}}catch{F=null}return m.set(v.id,F),F},g=()=>{if(c!==void 0)return c;let k=h();if(!k)return c=null;try{l=Ft(k),c=pr(l,!1,n.ggvMode)}catch{c=null}return c},y=k=>{let v=b(k);if(!v)return null;let x=f.get(v.id);if(x!==void 0)return x;let M=g(),F=null;if(M)try{let w=l?ao(l,M,[v.track],v.numerics,n.ggvMode,u):void 0,C=l?xn(l,M.rows):void 0;F=Rt(M,v.track,v.numerics,{standingStart:v.standingStart,...w?{load:w}:{},...C?{shifts:C}:{}})}catch{F=null}return f.set(v.id,F),F};return{lapSettings:n,get lapAvailable(){return!!o&&s.some(k=>!!WA(k.course,r,a))},lapParams:h,courses:()=>s,course:b,ggv:g,lap:y,lapReserve:k=>{let v=b(k);if(!v)return null;let x=p.get(v.id);if(x!==void 0)return x;let M=y(k),F=t.dynInput(),w=t.tyre(),C=null;if(M&&F&&w)try{let T=h();C=rm(F,w,{v:M.v,ax:M.ax,ay:M.ay,ds:v.track.ds,axDrag:Ea(g()?.rows,M.v),...M.axScrub?{axScrub:M.axScrub}:{},axGrade:yn(v.track.gradient,M.v.length),bank:v.track.bank,...M.loadFactor?{loadFactor:M.loadFactor}:{}},T?{driven:vh(T)}:{})}catch{C=null}return p.set(v.id,C),C}}}var jA=180/Math.PI,y0={rise:0,sinPitch:0,sinRoll:0};function UA(e){let t=e.kc;return t?XA(e.vehicle,r=>t.ground0[r]):y0}function XA(e,t){let r=e.config,n=nn(r),o=0,a=0,s=0,i=0,c=0,l=0,u=0,m=0,f=0;for(let g of er){let y=Ze(g,r),R=y.axleX-n,k=y.sideSign*Nt(e,y.isFront)/2,v=t(g);if(!Number.isFinite(v))return y0;o++,a+=R,s+=k,i+=v,c+=R*R,l+=k*k,u+=R*k,m+=R*v,f+=k*v}let p=o*(c*l-u*u)-a*(a*l-u*s)+s*(a*u-c*s);if(!(Math.abs(p)>1e-9))return{rise:i/o,sinPitch:0,sinRoll:0};let d=(i*(c*l-u*u)-a*(m*l-u*f)+s*(m*u-c*f))/p,h=(o*(m*l-u*f)-i*(a*l-u*s)+s*(a*f-m*s))/p,b=(o*(c*f-m*u)-a*(a*f-m*s)+i*(a*u-c*s))/p;return{rise:d,sinPitch:h,sinRoll:-b}}function gc(e,t){let r=e.kc,n=XA(e.vehicle,o=>(r?r.ground0[o]:0)+t[o]);return q([-n.sinPitch,n.sinRoll,1])}function x0(e,t,r,n){let o=q(rn(e,Ze(t,r)));return-Math.asin(Math.max(-1,Math.min(1,X(o,n))))*jA}function Qm(e,t,r,n,o){let a=q(rn(n,Ze(t,r))),s=q([1-a[0]*a[0],-a[0]*a[1],-a[0]*a[2]]),i=ae(a,s),c=p=>[X(p,s),X(p,i),X(p,a)],l=p=>ee(ee(U(s,p[0]),U(i,p[1])),U(a,p[2])),u=e.points,m=c(u.spinAxis),f=ms({uprightUpper:c(u.uprightUpper),uprightLower:c(u.uprightLower),wheelCenter:c(u.wheelCenter),spinAxis:m,tieOuter:c(u.tieOuter),loadedRadius:o.loadedRadius,patchShift:o.patchShift&&oO(o.patchShift,e.metrics.toe/jA,Math.atan2(m[0],m[1]))});return{caster:f.caster,kpi:f.kpi,scrubRadius:f.scrubRadius,mechanicalTrail:f.mechanicalTrail,scrubAtWheel:f.scrubAtWheel,trailAtWheel:f.trailAtWheel,kingpinOffset:f.kingpinOffset,casterOffset:f.casterOffset,kingpinGround:l(f.kingpinGround),contactPatch:l(f.contactPatch),elbow:l([f.contactPatch[0],f.kingpinGround[1],f.kingpinGround[2]]),kingpinAtHub:l(f.kingpinAtHub)}}function oO(e,t,r){if(r===t)return e;let n=e.x*Math.cos(t)-e.y*Math.sin(t),o=e.x*Math.sin(t)+e.y*Math.cos(t);return{x:n*Math.cos(r)+o*Math.sin(r),y:o*Math.cos(r)-n*Math.sin(r)}}function Zm(e,t){let r=UA(t);if(r===y0)return e;let n=o=>Math.max(-1,Math.min(1,o));return{...e,heave:e.heave-r.rise,pitch:Math.asin(n(Math.sin(e.pitch)-r.sinPitch)),roll:Math.asin(n(Math.sin(e.roll)-r.sinRoll))}}function Ha(e,t,r){let n=Zm({heave:0,pitch:0,roll:0,steer:0},r);return e-Id(n,[t,0,0],nn(r.vehicle.config))}var aO=180/Math.PI;function R0(e,t){return!e.valid||!e.ic?!1:Math.hypot(e.ic[0]-e.cp[0],e.ic[1]-e.cp[1])<=t}function Jm(e,t,r){let n=Ze(t,e.vehicle.config),o=gt(e,r),a=Su(e,t,o[t]),s=a.at("uprightUpper"),i=a.at("uprightLower"),c=a.at("contactPatch"),l=a.at("wheelCenter"),u=A=>{let P=a.velocity(A);return[P[0],P[2]]},m=u(c),f=u(l),p=[c[0],c[2]],d=[l[0],l[2]];if(!a.solved)return{ic:null,line:null,cp:p,wc:d,road:[1,0],swingArmAngleDeg:NaN,tanTheta:NaN,tanThetaHub:NaN,valid:!1,unsolved:!0,sinAngle:0};let h=gc(e,{FL:o.FL.ground,FR:o.FR.ground,RL:o.RL.ground,RR:o.RR.ground}),b=Math.hypot(h[0],h[2]),g=[h[0]/b,h[2]/b],y=[g[1],-g[0]],R=A=>{let P=A[0]*g[0]+A[1]*g[1];return Math.abs(P)>1e-9?-(A[0]*y[0]+A[1]*y[1])/P:0},k=a.omega[1],v=Math.hypot(m[0],m[1]),x=Math.abs(k)*1e9>v?[p[0]+m[1]/k,p[1]-m[0]/k]:null,F=x?(A=>{let P=[s[0]-A[0],s[2]-A[1]],L=[i[0]-A[0],i[2]-A[1]];return Math.abs(P[0]*L[1]-P[1]*L[0])/(Math.hypot(...P)*Math.hypot(...L))})(x):0;if(!(Math.abs(m[0]*g[0]+m[1]*g[1])>1e-9))return{ic:x,line:null,cp:p,wc:d,road:y,swingArmAngleDeg:0,tanTheta:0,tanThetaHub:0,valid:!1,sinAngle:F};let w=[m[1]/v,-m[0]/v],C=x?[x[0]-p[0],x[1]-p[1]]:[n.isFront?-1:1,0],T=w[0]*C[0]+w[1]*C[1]<0?[-w[0],-w[1]]:w,S=R(m);return{ic:x,line:T,cp:p,wc:d,road:y,swingArmAngleDeg:Math.atan(S)*aO,tanTheta:S,tanThetaHub:R(f),valid:!0,sinAngle:F}}function qA(e,t,r,n){let o=r/Math.max(1e-6,n.cgHeight),a=t==="front",s=a?n.drive.front:1-n.drive.front,i=a?n.brakeBalanceFront:1-n.brakeBalanceFront,c=(a?n.drive.inboard.front:n.drive.inboard.rear)?e.tanThetaHub:e.tanTheta,l=(a?n.brakeInboard?.front:n.brakeInboard?.rear)?e.tanThetaHub:e.tanTheta,u=a?-1:1;return{brake:u*100*l*o*i,drive:u*100*c*o*s}}var iO=180/Math.PI,cO=Math.PI/180,v0=.5,ep=2,k0=.25,lO={heave:0,pitch:0,roll:0,steer:0},uO={FL:"FR",FR:"FL",RL:"RR",RR:"RL"},tp=e=>e.ok?e.state:{...e.nearest,converged:!1};function M0(e,t,r){return t.state?t.solved===!1?{...t.state,converged:!1}:t.state:tp(ye(e,t.travel,t.steer,void 0,r))}var QA=new WeakMap;function ZA(e,t){let r=e.ctx[t],n=Ge(e.vehicle,t).config.loadedRadius,o=rr(n,e.kc,t),a=QA.get(r);a||(a=new Map,QA.set(r,a));let s=a.get(o);if(!s){let i=on(t,e.vehicle.config,lO,e.vehicle);s=tp(ye(r,i.travel,i.steer,void 0,o===n?void 0:{loadedRadius:o})),a.set(o,s)}return s}var br=(e,t)=>!e||!e.lo.converged||!e.hi.converged?NaN:(t(e.hi)-t(e.lo))/(2*e.step),JA=(e,t,r)=>{if(!e||!e.lo.converged||!e.hi.converged)return NaN;let n=r(e.hi)-r(e.lo);return Math.abs(n)<1e-9?NaN:(t(e.hi)-t(e.lo))/n};function tF(e,t,r,n,o){let a=e.vehicle.config,s=Ko(r),i=Ge(e.vehicle,r),c=Ze(r,a),l=e.ctx[r],u=gt(e,t),m=u[r],f={travel:m.travel,steer:m.steer},p=m.rigid?void 0:{loadedRadius:m.loadedRadius},d=M0(l,m,p),h=ZA(e,r),b={lo:tp(ye(l,f.travel-v0,f.steer,void 0,p)),hi:tp(ye(l,f.travel+v0,f.steer,void 0,p)),step:v0},g=c.isFront?{lo:Ie(l,d.beta,f.steer-ep,void 0,p),hi:Ie(l,d.beta,f.steer+ep,void 0,p),step:ep}:null,y=Y=>{let j=gt(e,{...t,roll:t.roll+Y*cO})[r];return M0(l,j,j.rigid?void 0:{loadedRadius:j.loadedRadius})},R={lo:y(-k0),hi:y(k0),step:k0},k=pO(e,t,r,c.isFront,u,g),v=Ot(d.points.contactPatch,c),x=Ot(h.points.contactPatch,c),M=Math.abs(v[1])-Math.abs(x[1]),F=uO[r],w=u[F],C=M0(e.ctx[F],w,w.rigid?void 0:{loadedRadius:w.loadedRadius}),T=C.converged?M+Math.abs(C.points.contactPatch[1])-Math.abs(ZA(e,F).points.contactPatch[1]):NaN,S=o??lr(e,t,s),A=Au(S,bt(i)),P=A?null:Mk(S),L=c.sideSign>0?S.icRight:S.icLeft,D=L?Math.hypot(L[0]-v[1],L[1]-v[2]):1/0,E=Jm(e,r,t),V=E.ic?Math.hypot(E.ic[0]-E.cp[0],E.ic[1]-E.cp[1]):1/0,N=qA(E,s,a.wheelbase,n),z=-br(b,Y=>Y.points.damperLength),I=i.config.springRate,_=br(R,Y=>Y.metrics.camber),B=gc(e,{FL:u.FL.ground,FR:u.FR.ground,RL:u.RL.ground,RR:u.RR.ground}),O=e.kc?.loadCase,G=Y=>O?Qm(Y,r,a,B,{loadedRadius:m.loadedRadius,patchShift:O.patchShift[r]}):Y.metrics,K=G(d);return{id:r,converged:d.converged,travel:d.travel,camber:d.metrics.camber,camberRoad:x0(d.points.spinAxis,r,a,B),toe:d.metrics.toe,caster:K.caster,kpi:K.kpi,scrubRadius:K.scrubRadius,mechanicalTrail:K.mechanicalTrail,scrubAtWheel:K.scrubAtWheel,trailAtWheel:K.trailAtWheel,kingpinOffset:K.kingpinOffset,casterOffset:K.casterOffset,steeringArm:d.metrics.steeringArm,camberGain:br(b,Y=>Y.metrics.camber),bumpSteer:br(b,Y=>Y.metrics.toe),trackScrubRate:br(b,Y=>Math.abs(Ot(Y.points.contactPatch,c)[1])),casterGain:br(b,Y=>G(Y).caster),kpiGain:br(b,Y=>G(Y).kpi),scrubGain:br(b,Y=>G(Y).scrubRadius),trailGain:br(b,Y=>G(Y).mechanicalTrail),...c.isFront?{camberPerSteer:JA(g,Y=>Y.metrics.camber,Y=>Y.metrics.toe),steerJacking:-JA(g,Y=>Y.points.contactPatch[2],Y=>Y.metrics.toe),...k!==void 0?{steerLoad:k}:{}}:{},rollCamber:_,camberRecovery:-100*c.sideSign*_,rollSteer:c.sideSign*br(R,Y=>Y.metrics.toe),halfTrackChange:M,trackChange:T,longitudinal:v[0]-x[0],rollCentreHeight:P?P.heightAboveGround:S.heightAboveGround,rollCentreHeightChassis:(P?P.height:S.height)-Ha(0,c.axleX,e),rollCentreLateral:S.lateralAlongGround,rollCentreValid:S.valid,rollCentreUsable:A,rollCentreHeightUsable:A||P!==null,rollCentreSinAngle:S.sinAngle,fvsaLength:D,svsaLength:V,swingArmAngle:E.swingArmAngleDeg,svsaUsable:R0(E,a.wheelbase),svsaSinAngle:E.sinAngle,...s==="front"?{antiDive:N.brake,antiLift:N.drive}:{antiSquat:N.drive,antiLift:N.brake},decoupled:i.config.actuation==="decoupled",mcpherson:i.config.layout==="mcpherson",springRate:I,motionRatio:z,wheelRate:I*z*z,damperLength:d.points.damperLength,damperTravel:h.points.damperLength-d.points.damperLength,...mO(i,h.points.damperLength,d.points.damperLength,e.kc?.curve[r].spring?.law),rockerAngle:i.config.actuation==="direct"?0:(d.points.rockerAngle-h.points.rockerAngle)*iO,groundDisplacement:m.rigid?d.travel:m.ground,tyreDeflection:m.tyreDeflection,wheelLoad:m.load,loadedRadiusAt:m.loadedRadius,rideRate:m.rideRate,wheelRateAtLoad:m.wheelRateAtLoad,lifted:m.lifted,clearance:m.clearance??0,tyreRigid:m.rigid}}function mO(e,t,r,n){if(e.config.actuation==="decoupled")return{};let o=n?{droop:n.droopStated?n.droop:null,bump:n.bump}:zo(t,e.config.coilover),a=t-r;return{...o.droop!==null?{damperToExtended:a-o.droop}:{},...o.bump!==null?{damperToClosed:o.bump-a}:{}}}function pO(e,t,r,n,o,a){if(!a||!n)return;let s=hl(e,t,"front"),i=e.kc;if(!s||!i)return;let c=["FL","FR"],l=[0,0],u=[0,0],m={lo:[],hi:[]},f=0;for(let h=0;h<2;h++){let b=c[h],g=o[b],y=e.ctx[b],R=g.rigid?void 0:{loadedRadius:g.loadedRadius},x=(b==="FR"?1:-1)*(r==="FR"?1:-1)*ep,M=g.state?{q:[...g.state.pose.t,...g.state.pose.omega],phi:g.state.points.rockerAngle}:void 0,F=ht(ye(y,g.travel,g.steer-x,M,R)),w=ht(ye(y,g.travel,g.steer+x,M,R));if(!F||!w)return NaN;l[h]=w.points.contactPatch[2]-F.points.contactPatch[2],u[h]=kr(i.curve[b],g.travel,w.points.damperLength)-kr(i.curve[b],g.travel,F.points.damperLength),m.lo.push(F),m.hi.push(w),b===r&&(f=w.metrics.toe-F.metrics.toe)}let p=i.elements?.front;if(p){let h=[o.FL.travel,o.FR.travel],b=ks(p,h,[m.hi[0],m.hi[1]]),g=ks(p,h,[m.lo[0],m.lo[1]]);u[0]+=b[0]-g[0],u[1]+=b[1]-g[1]}return Math.abs(f)>1e-9?s([0,0],l,u)[r==="FL"?0:1]/f:NaN}function yc(e,t,r,n,o){return tF(e,t,r==="front"?"FL":"RL",n,o)}function S0(e,t,r,n){let o=yc(e,t,"front",r,n?.front),a=yc(e,t,"rear",r,n?.rear);return{front:o,rear:a,wheelbaseChange:o.longitudinal-a.longitudinal}}var rp=Math.PI/180,xc={travelSteps:9,heaveSteps:5,rollSteps:4,rackSteps:6},np={travelMin:-25,travelMax:25,rollMaxDeg:3,rollAtLimitDeg:2.5};function dO(e){let t=e.params;return{cgHeight:t.cg_height?dt({...t,surveyedRadiusFront:e.vehicle.front.config.loadedRadius,surveyedRadiusRear:e.vehicle.rear.config.loadedRadius}).cgHeight:300,...Ah(t),drive:kh(t)}}function rF(e,t){for(let r=1;r<e.length;r++){let n=3*t(r)+10;for(let o of["cpLeft","cpRight"]){let a=e[r-1][o],s=e[r][o];if(a&&s&&Math.hypot(s[0]-a[0],s[1]-a[1])>n)return r}}return-1}function A0(e,t=xc,r=np,n){let o=null,a=(S,A)=>(o||(o={violation:S,reason:A}),null),s=e.vehicle,i=S=>S==="front"?s.front:s.rear,c=null,l=null,u=()=>{if(c)return c;if(n)try{let S=n();if(S)return c=Ct(s,S.kc),l=S.cgHeight,c}catch{a(500,"the car could not be stood on its tyre: its rates did not assemble")}return c=Ct(s)},m=S=>S==="front"?"FL":"RL",f=S=>{let A=u();if(!A.kc)return;let P=i(S).config.loadedRadius,L=rr(P,A.kc,m(S));return L===P?void 0:{loadedRadius:L}},p=(S,A)=>-Ms(u(),m(S),A),d=new Map,h=new Map,b=new Map,g=new Map,y=new Map,R=new Map,k=new Map,v=null,x=()=>{if(v)return v;u();let S=dO(e);return v=l!==null&&Number.isFinite(l)?{...S,cgHeight:l}:S},M,F,w=()=>{if(F!==void 0)return F;let S=vl(u().ctx.FL,Vt(s.front.config));return F=S?kl(S):null,F},C=(S,A,P)=>{if(S.has(A))return S.get(A)??null;let L=P();return S.set(A,L),L};return{car:e,density:t,envelope:r,get failure(){return o},axisLength:(S,A)=>{let P=i(S),L=P.hardpoints;return A==="uca"&&P.config.layout==="mcpherson"?NaN:A==="uca"?ve(L.ucaFront,L.ucaRear):ve(L.lcaFront,L.lcaRear)},linkLength:S=>{let A=i(S).hardpoints;return ve(A.tieInner,A.tieOuter)},compliance:S=>C(h,S,()=>wf(i(S))??null),sweep:S=>C(d,S,()=>{let A;try{A=Ke(i(S),{travelMin:r.travelMin,travelMax:r.travelMax,steps:t.travelSteps})}catch{return a(500,`the ${S} travel sweep threw`)}if(!A.covered){let L=A.samples.map(V=>V.travel),D=Math.max(...L)-Math.min(...L),E=r.travelMax-r.travelMin;return a(Math.max(0,E-D),`the ${S} linkage reaches only ${D.toFixed(0)} mm of the ${E.toFixed(0)} mm travel range`)}if(A.fold)return a(200,`the ${S} travel(beta) folds \u2014 the suspension goes over centre in range`);let P=A.samples.filter(L=>!L.converged).length;if(P>0)return a(100+10*P,`${P} of ${A.samples.length} ${S} travel solves did not converge`);if(S==="front"&&i("front").config.steerMode==="rack"){let L=w();if(L)return a(L.violation,L.reason)}return A}),rcHeave:S=>C(b,S,()=>{let A=[],P=[],L=Math.max(2,t.heaveSteps);try{for(let E=0;E<L;E++){let V=r.travelMin+(r.travelMax-r.travelMin)*E/(L-1);A.push(V),P.push(lr(u(),{heave:p(S,V),pitch:0,roll:0,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in heave`)}let D=rF(P,E=>Math.abs(A[E]-A[E-1]));return D>0?a(300,`the ${S} roll-centre construction lands on another branch at ${A[D].toFixed(0)} mm of travel`):{at:A,rc:P}}),rcRoll:S=>C(g,S,()=>{let A=[],P=[],L=Math.max(2,t.rollSteps);try{for(let E=0;E<L;E++){let V=r.rollMaxDeg*E/(L-1);A.push(V),P.push(lr(u(),{heave:0,pitch:0,roll:V*rp,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in roll`)}let D=rF(P,E=>Math.abs(P[E].cpLeft?.[0]??0)*Math.abs(A[E]-A[E-1])*rp);return D>0?a(300,`the ${S} roll-centre construction lands on another branch at ${A[D].toFixed(1)}\xB0 of roll`):{at:A,rc:P}}),steer:()=>{if(M!==void 0)return M;try{M=cf(u(),{steerMax:Vt(s.front.config),steps:t.rackSteps})}catch{M=a(500,"the steering sweep threw")}let S=M?.filter(A=>!A.converged).length??0;if(M&&S>0){let A=w();M=A?a(A.violation,A.reason):a(100+10*S,`${S} of ${M.length} steering solves did not converge`)}return M??null},solveAt:(S,A,P=0)=>C(y,`${S}:${A}:${P}`,()=>{try{let L=ye(u().ctx[m(S)],A,P,void 0,f(S));return L.ok?L.state:L.why==="unconverged"?a(100,`the ${S} corner did not solve at ${A.toFixed(0)} mm of travel`):a(100+Math.abs(L.travelMiss),`the ${S} corner reaches only ${(A+L.travelMiss).toFixed(0)} of ${A.toFixed(0)} mm of travel`)}catch{return a(150,`the ${S} corner solve threw at ${A.toFixed(0)} mm of travel`)}}),readout:S=>C(R,`${S.heave}:${S.pitch}:${S.roll}:${S.steer}`,()=>{try{return S0(u(),S,x())}catch{return a(500,"the derived readout threw")}}),readoutAtTravel:(S,A)=>C(k,`${S}:${A}`,()=>{try{return yc(u(),{heave:p(S,A),pitch:0,roll:0,steer:0},S,x())}catch{return a(500,`the ${S} readout threw at ${A.toFixed(0)} mm of travel`)}}),travelAtRoll:(S,A)=>{let P=i(S).hardpoints.wheelCenter[1]*Math.sin(A*rp),L=u();if(!L.kc)return P;try{let D=gt(L,{heave:0,pitch:0,roll:A*rp,steer:0}),E=S==="front"?Math.max(D.FL.travel,D.FR.travel):Math.max(D.RL.travel,D.RR.travel);return Number.isFinite(E)?E:P}catch{return a(500,`the ${S} axle could not be rolled on its tyre`),P}},onTyre:()=>!!u().kc,contexts:u}}var fO=hg();function F0(e,t={}){let r=new Map;return{session(n){if(r.has(n))return r.get(n);let o=null,a=t.session?.();if(t.sessionParams&&a)try{let s=gm(n,a.rulesets),i=s?.events.some(c=>c.kind==="trackLap");if(s&&(a.track||!i)){let c=t.sessionParams(e),{standingStart:l,lapCounts:u}=a.settings,m=a.track?Zi([c],a.track,a.numerics,ji(s),a.settings,fO)[0]:Vi(c,s,{numerics:a.numerics,standingStart:l,lapCounts:u});o={};for(let f of s.metrics)Hc(f)&&(o[f.key]=f.value(m,void 0))}}catch{o=null}return r.set(n,o),o}}}var op=.01;function hO(e,t){return t.bump!==null&&e>t.bump-op?{at:"closed",past:Math.max(0,e-t.bump)}:t.droopStated&&e<t.droop+op?{at:"toppedOut",past:Math.max(0,t.droop-e)}:t.seat!==null&&e<t.seat+op?{at:"unseated",past:Math.max(0,t.seat-e)}:{at:"free",past:0}}var nF=e=>({droop:e.droop,droopStated:e.droopStated,bump:e.bump,seat:e.holdsLoad&&Number.isFinite(e.free)?e.free:null}),bO=[["front","FL","FR"],["rear","RL","RR"]];function C0(e,t){let r=[];for(let[n,o,a]of bO){let s=[t[o],t[a]];for(let m of[o,a]){let f=e.curve[m],p=f.spring?.law;if(!f.spring||!p)continue;let d=Gd(f,t[m]);d===null||!Number.isFinite(d)||r.push(w0(m,n,n,d,f.spring.length0-d,nF(p),!0))}let i=e.elements?.[n];if(!i)continue;let c=i.heave?.law;if(c){let m=gR(i,s),f=i.read.heave?.span0,p=n==="front"?"heaveFront":"heaveRear";r.push(w0(p,p,n,m,f!==void 0?f-m:null,nF(c),i.carriesLoad))}let l=i.rollStop,u=l?yR(i,s):null;if(l&&u!==null){let m=l.length0-u,f=n==="front"?"rollFront":"rollRear",p={droop:l.droop??-1/0,droopStated:l.droop!==null,bump:l.bump,seat:null};r.push(w0(f,f,n,m,u,p,i.carriesLoad))}}return r}function w0(e,t,r,n,o,a,s){return{damper:e,place:t,axle:r,length:o,compression:n,toToppedOut:a.droopStated?n-a.droop:null,toClosed:a.bump!==null?a.bump-n:null,...hO(n,a),bumpStated:a.bump!==null,bounds:s}}function oF(e,t){let r=t.vehicle.config;return e.map(n=>{let o=n.axle==="front"?r.frontAxleX:r.frontAxleX-r.wheelbase,a=o+Math.min(n.xMin,n.xMax),s=o+Math.max(n.xMin,n.xMax),i=(a+s)/2;return{...n,min:[a,Math.min(n.yMin,n.yMax),Ha(Math.min(n.zMin,n.zMax),i,t)],max:[s,Math.max(n.yMin,n.yMax),Ha(Math.max(n.zMin,n.zMax),i,t)]}})}var gO=(e,t)=>[e[0]+t[0],e[1]+t[1],e[2]+t[2]],yO=(e,t)=>[e[0]*t,e[1]*t,e[2]*t];var xO=(e,t,r)=>e.z0+e.dzdx*t+e.dzdy*r;function RO(e,t){let r=Math.sin(e.pitch);return{z0:-e.heave+t*r,dzdx:-r,dzdy:Math.sin(e.roll)}}function aF(e){return RO(Zm({heave:0,pitch:0,roll:0,steer:0},e),nn(e.vehicle.config))}function vO(e,t){let r=[];for(let c of[e.min[0],e.max[0]])for(let l of[e.min[1],e.max[1]])r.push([c,l,e.min[2]]);let n=r.map(t),o=Math.min(...n),a=r.filter((c,l)=>n[l]<=o+.5),s=new Set(a.map(c=>c[0])),i=new Set(a.map(c=>c[1]));return{height:o,lowest:{x:s.size>1||e.min[0]===e.max[0]?null:a[0][0]===e.max[0]?"front":"rear",y:i.size>1||e.min[1]===e.max[1]?null:a[0][1]===e.max[1]?"right":"left"},at:yO(a.reduce((c,l)=>gO(c,l),[0,0,0]),1/a.length)}}function sF(e,t){return{...vO(e,r=>r[2]-xO(t,r[0],r[1])),road:t}}function iF(e,t){let r=(a,s,i)=>a[0]*(s[1]*i[2]-s[2]*i[1])-a[1]*(s[0]*i[2]-s[2]*i[0])+a[2]*(s[0]*i[1]-s[1]*i[0]),n=r(e[0],e[1],e[2]);if(Math.abs(n)<1e-12)return null;let o=a=>e.map((s,i)=>s.map((c,l)=>l===a?t[i]:c));return[r(...o(0))/n,r(...o(1))/n,r(...o(2))/n]}var uF=Math.PI/180;function T0(e,t,r,n){let o=t.speedKmh/3.6,a=Md(e,o,t.axG,Jr(e,t.ayG,0));if(!a||!e.aero)return null;let s=e.wheelbase,i=$o(e.aero,s),c=(h,b)=>Math.atan((b-h)/s)/uF,l={},u={};for(let h of er)l[h]=r.corners[h].travel,u[h]=r.corners[h].ground;let m=n.kc?C0(n.kc,l):[],f=e.aero.model,p=a.downFront+a.downRear,d=f?{balance:Math.abs(p)>1e-9?100*a.downFront/p:NaN,clA:(a.clFront+a.clRear)*a.area,cdA:a.cd*a.area,loopMargin:1-a.gain,dataMargin:mF(f,s,a.hFront,a.hRear)}:null;return{front:{height:a.hFront,...cF(m,"front")},rear:{height:a.hRear,...cF(m,"rear")},rakeDeg:c(a.hFront,a.hRear),pitchDeg:c(a.hFront,a.hRear)-c(i.hFront,i.hRear),rollDeg:Math.abs(r.rollDeg),aero:d,clearance:kO(n,u)}}function cF(e,t){let r=e.filter(o=>o.axle===t&&o.bounds),n=o=>{let a=o.filter(s=>s!==null&&Number.isFinite(s));return a.length?Math.min(...a):null};return{toBump:n(r.map(o=>o.toClosed)),toDroop:n(r.map(o=>o.toToppedOut))}}function mF(e,t,r,n){let o=(a,[s,i])=>Math.min(a-s,i-a);if(ux(e)){let{x:a,y:s}=No(e),i=[a[0],a[a.length-1]],c=[s[0],s[s.length-1]];return Qr(e)?lF(e.frame,t,i,c,r,n):Math.min(o(r,i),o(n,c))}return Xc(e)?lF(e.frame,t,e.range.h,e.range.pitch,r,n):Math.min(o(r,e.range.hFront),o(n,e.range.hRear))}function lF(e,t,r,n,o,a){let s=Oo(e,t,o,a),i=l=>t*Math.tan(l*uF),c=a-o;return Math.min(s.h-r[0],r[1]-s.h,c-i(n[0]),i(n[1])-c)}function kO(e,t){let r=e.vehicle.chassis?.boxes;if(!r?.length)return null;let n={vehicle:e.vehicle,kc:e.kc},o=e.vehicle.config,a=o.frontAxleX,s=o.frontAxleX-o.wheelbase,i=Nt(e.vehicle,!0)/2,c=Nt(e.vehicle,!1)/2,l={FL:[a,-i],FR:[a,i],RL:[s,-c],RR:[s,c]},u=[[0,0,0],[0,0,0],[0,0,0]],m=[0,0,0];for(let b of er){let g=[1,l[b][0],l[b][1]];for(let y=0;y<3;y++){m[y]+=g[y]*t[b];for(let R=0;R<3;R++)u[y][R]+=g[y]*g[R]}}let f=iF(u,m);if(!f)return null;let p=aF(n),d={z0:p.z0+f[0],dzdx:p.dzdx+f[1],dzdy:p.dzdy+f[2]},h=null;for(let b of oF(r,n)){let g=sF(b,d);(!h||g.height<h.height)&&(h={height:g.height,volume:b.name})}return h}function P0(e){return e.aeroModel?null:"The car runs on aero constants, which do not move with the platform; attach an aero model in Aerodynamics"}var MO={front:"front",rear:"rear",heaveFront:"front",heaveRear:"rear",rollFront:"front",rollRear:"rear"};function ap(e,t,r,n){let o=Lu(e,t);return vu.some(s=>{if(MO[s]!==r)return!1;let i=o[s].coilover,c=i?.extended!==void 0&&i.extended>0;return n==="droop"?c:c&&i?.stroke!==void 0&&i.stroke>0})?null:n==="droop"?`No ${r} damper states its extended length; state it on its part in Dampers, or under Elements \u203A Stops`:`No ${r} damper states its stroke; state its extended length and stroke on its part in Dampers, or under Elements \u203A Stops`}function L0(e){return e.chassis?.boxes.length?null:"This suspension has no mockup volumes to measure the ground from; draw one under Kinematics \u203A Chassis"}var sp=Math.PI/180,ip=1e-6;function dF(e,t){let r=e.length;if(r===0)return 0;if(0<=e[0])return t[0];if(0>=e[r-1])return t[r-1];let n=0;for(;e[n+1]<0;)n++;let o=(0-e[n])/(e[n+1]-e[n]);return t[n]+o*(t[n+1]-t[n])}function Rc(e){let t=e.measured;if(t)return dF(t.travel,t.camber);let r=q(e.config.spinAxis);return-Math.asin(Math.max(-1,Math.min(1,r[2])))/sp}function vc(e){let t=e.measured;if(t)return dF(t.travel,t.toe);let[r,n]=e.config.spinAxis;return Math.atan2(r,n)/sp}function D0(e,t){let r=Math.abs(t.camber)>=ip,n=Math.abs(t.toe)>=ip;if(!r&&!n)return e;let o=e.measured;if(o)return{...e,measured:{...o,...r?{camber:o.camber.map(p=>p+t.camber)}:{},...n?{toe:o.toe.map(p=>p+t.toe)}:{}}};let[a,s]=e.config.spinAxis,i=Math.hypot(a,s);if(!(i>0))return e;let c=(Rc(e)+t.camber)*sp,l=(vc(e)+t.toe)*sp,[u,m]=n?[Math.sin(l),Math.cos(l)]:[a/i,s/i],f=[u*Math.cos(c),m*Math.cos(c),-Math.sin(c)];return{...e,config:{...e.config,spinAxis:f}}}function cp(e){let t=e&&typeof e=="object"?e.value:void 0;return typeof t=="number"&&Number.isFinite(t)?t:void 0}function SO(e,t){let r=t;return{front:cp(r.camber_front_deg)??Rc(e.front),rear:cp(r.camber_rear_deg)??Rc(e.rear)}}function AO(e,t){let r=t;return{front:cp(r.toe_front_deg)??vc(e.front),rear:cp(r.toe_rear_deg)??vc(e.rear)}}function FO(e){return{camber:{front:Rc(e.front),rear:Rc(e.rear)},toe:{front:vc(e.front),rear:vc(e.rear)}}}var pF=new WeakMap;function wO(e,t){let r=FO(e),n={front:{camber:t.camber.front-r.camber.front,toe:t.toe.front-r.toe.front},rear:{camber:t.camber.rear-r.camber.rear,toe:t.toe.rear-r.toe.rear}},o=u=>Math.abs(u.camber)<ip&&Math.abs(u.toe)<ip;if(o(n.front)&&o(n.rear))return e;let a=`${t.camber.front}|${t.camber.rear}|${t.toe.front}|${t.toe.rear}`,s=pF.get(e),i=s?.get(a);if(i)return i;let c=e.corners?Object.fromEntries(Object.entries(e.corners).map(([u,m])=>[u,m&&D0(m,n[Ko(u)])])):void 0,l={...e,front:D0(e.front,n.front),rear:D0(e.rear,n.rear),...c?{corners:c}:{}};return s||pF.set(e,s=new Map),s.size>=16&&s.clear(),s.set(a,l),l}function za(e,t){return t?wO(e,{camber:SO(e,t),toe:AO(e,t)}):e}var CO=9.81;function Ya(e){let t=Nn(e),r=Math.max(0,e.unsprungPerCorner)*CO,n=a=>{let s=a==="FL"||a==="FR",i=s?"front":"rear",c=Xe(e,i),l=c>0?c:1/0,u=nd(e,i);return{staticLoad:t[a],springLoad:Math.max(0,t[a]-r),tyreRate:l,arbRate:s?e.arbFront:e.arbRear,heaveRate:(s?e.heaveSpringFront:e.heaveSpringRear)??0,...u>0?{staticLoadedRadius:Gt(u,t[a],l,u)}:{}}},o={};for(let[a,s,i,c,l,u]of[["front",e.elementLinkagesFront,!!e.decoupledFront,e.heaveCoiloverFront,e.heaveSeatFront,e.rollCoiloverFront],["rear",e.elementLinkagesRear,!!e.decoupledRear,e.heaveCoiloverRear,e.heaveSeatRear,e.rollCoiloverRear]]){let m=!i&&!!l&&(l.gap>0||!l.bothWays);(s?.heave||s?.roll||i||m)&&(o[a]={...s,carriesLoad:i,...c?{coilover:c}:{},...l&&!i?{heaveSeat:l}:{},...u?{rollCoilover:u}:{}})}return{corners:{FL:n("FL"),FR:n("FR"),RL:n("RL"),RR:n("RR")},...o.front||o.rear?{elements:o}:{},...e.cornerCoiloverFront||e.cornerCoiloverRear?{cornerCoilover:{...e.cornerCoiloverFront?{front:e.cornerCoiloverFront}:{},...e.cornerCoiloverRear?{rear:e.cornerCoiloverRear}:{}}}:{}}}var fF=new WeakMap;function TO(e){let t=za(e.vehicle,e.params);if(t===e.vehicle)return e;let r=fF.get(e);return(!r||r.vehicle!==t)&&fF.set(e,r={...e,vehicle:t}),r}function Sn(e,t={}){let r=TO(e),n=m0(r,t),o=t.assemble?()=>{let m=n.dynInput();if(!m)throw new Error("the car did not assemble");return{kc:Ya(m),cgHeight:m.cgHeight}}:void 0,a=A0(r,t.density,t.envelope,o),s=g0(r,n,t),i=F0(r,t),c=t.states??[],l=new Map;return{...a,...n,...s,...i,get failure(){return a.failure},values:new Map,states:c,stateOf:m=>m===void 0?c[0]??null:c.find(f=>f.id===m)??null,platformAt:m=>{let f=`${m.speedKmh}|${m.ayG}|${m.axG}`,p=l.get(f);if(p!==void 0)return p;let d=n.poseAt(m),h=n.dynInput(),b=null;if(d&&h)try{b=T0(h,m,d,a.contexts())}catch{b=null}return l.set(f,b),b}}}var PO=["x","y","z"],LO=/^(line|plane)\((-?\d+),(-?\d+)\)([uv]?)$/,hF=Math.PI/18e3,bF=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],gF=(e,t)=>[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]],DO=e=>Math.hypot(e[0],e[1],e[2]),E0=(e,t)=>[e[0]*t,e[1]*t,e[2]*t];function I0(e){let t=DO(e);return t>1e-9?E0(e,1/t):null}function EO(e,t){let r=e*hF,n=t*hF;return[Math.cos(n)*Math.cos(r),Math.cos(n)*Math.sin(r),Math.sin(n)]}function gr(e){let t=e.lastIndexOf(".");if(t<0)return null;let r=LO.exec(e.slice(t+1));if(!r)return null;let n=r[1];return n==="line"!=(r[4]==="")?null:{point:e.slice(0,t),shape:{kind:n,dir:EO(Number(r[2]),Number(r[3]))},coord:n==="line"?"along":r[4]}}function yF(e){let t=I0(gF([0,0,1],e))??[1,0,0];(t[0]<-1e-9||Math.abs(t[0])<=1e-9&&t[1]<0)&&(t=E0(t,-1));let r=I0(gF(e,t))??[0,1,0];return(r[2]<-1e-9||Math.abs(r[2])<=1e-9&&r[1]<0)&&(r=E0(r,-1)),[t,r]}function _0(e){if(e.coord==="along")return e.shape.dir;let[t,r]=yF(e.shape.dir);return e.coord==="u"?t:r}function xF(e,t){let r=gr(t);if(!r)return;let n=PO.map(u=>e[`${r.point}.${u}`]);if(n.some(u=>!u))return;let o=_0(r),a=[0,1,2].filter(u=>Math.abs(o[u])>1e-12),s=u=>n.map(m=>m.read(u)),i=n[0],c=a.map(u=>n[u].supersededBy).find(Boolean),l=i.label.replace(/ x$/,"");return{id:t,group:i.group,label:r.coord==="along"?`${l} along its line`:`${l} in its plane, ${r.coord}`,...i.scope?{scope:i.scope}:{},unit:i.unit,defaultSpan:i.defaultSpan,read:u=>bF(s(u),o),write:(u,m)=>{let f=s(u),p=m-bF(f,o),d=u;for(let h of a)d=n[h].write(d,f[h]+p*o[h]);return d},...c?{supersededBy:c}:{}}}var lp=["x","y","z"];var IO=/^(?:hp\.(?:front|rear)\.\w+|(?:heave|roll)\.(?:front|rear)\.(?:outer|inner|anchor))$/;function kc(e){let t=e.lastIndexOf("."),r=e.slice(0,t);if(t<0||!IO.test(r))return null;let n=e.slice(t+1);if(n==="x"||n==="y"||n==="z")return{point:r,axis:n};let o=gr(e);return o?{point:r,axis:o.coord}:null}var Mc="*";function N0(e){let t={sum:"summed",min:"lowest",max:"highest",distance:"by length",harmonic:"overall"};return e?.across?`all courses, ${t[e.across]}`:"all courses"}var O0=e=>e?.reads==="speed"||e?.reads==="operating",V0=e=>e?.reads==="lateral"||e?.reads==="operating";function Ro(e){if(!e)return"";let t=[];return e.speed!==void 0&&Number.isFinite(e.speed)&&t.push(`v${e.speed}`),e.ayG!==void 0&&Number.isFinite(e.ayG)&&t.push(`a${e.ayG}`),e.courseId&&t.push(`c${e.courseId}`),e.stateId&&t.push(`s${e.stateId}`),t.join(",")}function up(e,t){return e?.appliesAt?t.find(r=>!e.appliesAt(r)):t[0]}function Wa(e,t,r){let n=r?.stateId?e.stateOf(r.stateId):up(t,e.states)??null;return n&&!t.appliesAt?.(n)?n:null}function Lt(e,t,r){let n=`${t.id}@${Ro(r)}`,o=e.values.get(n);if(o!==void 0)return o;let a;try{a=r?.courseId===Mc&&t.reads==="course"?_O(e,t,r):r?.stateId===Wr&&t.reads==="state"?NO(e,t,r):t.read(e,r)}catch{a=NaN}return e.values.set(n,a),a}function _O(e,t,r){if(!t.across)return NaN;let n=e.courses();if(!n.length)return NaN;let o=n.map(s=>{let i={...r,courseId:s.id};return{v:Lt(e,t,i),length:e.course(i)?.track.length??NaN}});if(o.some(s=>!Number.isFinite(s.v)))return NaN;if(t.across==="sum")return o.reduce((s,i)=>s+i.v,0);if(t.across==="min")return Math.min(...o.map(s=>s.v));if(t.across==="max")return Math.max(...o.map(s=>s.v));let a=o.reduce((s,i)=>s+i.length,0);return a>0?t.across==="harmonic"?a/o.reduce((s,i)=>s+i.length/i.v,0):o.reduce((s,i)=>s+i.v*i.length,0)/a:NaN}function NO(e,t,r){let n=t.appliesAt?e.states.filter(i=>!t.appliesAt(i)):e.states;if(!t.acrossStates||!n.length)return NaN;let o=n.map(i=>({v:Lt(e,t,{...r,stateId:i.id}),w:i.weight,s:i})),a=t.appliesAt?o.filter(i=>Number.isFinite(i.v)||!e.poseAt(i.s)):o;if(!a.length||a.some(i=>!Number.isFinite(i.v)))return NaN;if(t.acrossStates==="max")return Math.max(...a.map(i=>i.v));if(t.acrossStates==="min")return Math.min(...a.map(i=>i.v));if(t.acrossStates==="span")return Math.max(...a.map(i=>i.v))-Math.min(...a.map(i=>i.v));let s=a.reduce((i,c)=>i+c.w,0);return s>0?a.reduce((i,c)=>i+c.v*c.w,0)/s:NaN}function B0(e){let t={mean:"weighted mean",max:"highest",min:"lowest",span:"span"};return e?.acrossStates?`every state, ${t[e.acrossStates]}`:"every state"}function et(e){return`${e.quantity??e.groupShort??e.group} \xB7 ${e.label}`}var OO={front:"Front",rear:"Rear"},Sc={heave:0,pitch:0,roll:0,steer:0};function RF(e,t){let r=0,n=0;for(let o=1;o<e.length;o++){let a=e[o]-e[o-1];if(Math.abs(a)<1e-9)continue;let s=(t[o]-t[o-1])/a;r+=s*s,n++}return n?Math.sqrt(r/n):NaN}function VO(e,t){let r=0;for(let n=1;n<e.length;n++){let o=e[n]-e[n-1];Math.abs(o)<1e-9||(r=Math.max(r,Math.abs((t[n]-t[n-1])/o)))}return r}var Ac=e=>e.length?Math.max(...e)-Math.min(...e):NaN;function vF(e){let t=(e??[]).filter(Number.isFinite);if(!t.length)return NaN;let r=t.reduce((n,o)=>n+o,0)/t.length;return Math.abs(r)>0?(Math.max(...t)-Math.min(...t))/Math.abs(r):NaN}function kF(e,t){if(!e.length)return;let r=0;for(let n=1;n<e.length;n++)Math.abs(e[n])<Math.abs(e[r])&&(r=n);return t[r]}function ja(e,t,r){let n=e.stateOf(t?.stateId),o=n?e.poseAt(n):null;return o?r(o):NaN}var Fc=(e,t)=>`${e==="front"?"F":"R"}${t}`,MF=e=>e==="L"?"R":"L";function SF(e){let t=OO[e],r=x=>`kin.${e}.${x}`,n=(x,M)=>{let F=x.sweep(e);return F?{x:F.samples.map(w=>w.travel),y:F.samples.map(M)}:{x:[],y:[]}},o=x=>e==="front"?x.vehicle.front:x.vehicle.rear,a=x=>x.params[e==="front"?"heaveFrontDesign":"heaveRearDesign"],s=x=>x.params[e==="front"?"arbFrontDesign":"arbRearDesign"],i=e==="front"?"the front axle":"the rear axle";function c(x){return o(x).config.actuation==="decoupled"?`${i} is decoupled, with no corner damper \u2014 read its heave and roll elements`:null}function l(x){let M=a(x);return M&&M.design.kind!=="none"?null:`${i} has no heave element`}function u(x){let M=a(x);return M?.design.kind==="coil"&&M.linkage?null:`${i} has no heave element on a linkage`}function m(x){let M=s(x);return M&&M.design.kind!=="none"?null:`${i} has no roll element`}function f(x){let M=s(x);return M?.linkage&&M.design.kind!=="none"&&M.design.kind!=="direct"?null:`${i} has no roll element on a linkage`}let p=x=>{if(u(x.car))return null;let M=x.sweep(e);return M?Wd(o(x.car),a(x.car).linkage,M.samples):null},d=x=>{if(f(x.car))return null;let M=x.sweep(e);if(!M)return null;let F=s(x.car),w=Hd(o(x.car),F.linkage,F.design.kind,M.samples),C=w.atDesign<0?-1:1;return{travel:w.travel,ratio:w.ratio.map(T=>T*C),atDesign:w.atDesign*C}},h=x=>x.readout(Sc)?.[e],b=x=>x.readoutAtTravel(e,x.envelope.travelMax),g=x=>{let M=n(x,F=>F.metrics.camber);return M.x.length?{key:r("camberGain"),title:`${t} camber vs travel`,xLabel:"travel [mm]",yLabel:"camber [\xB0]",...M}:null},y=x=>{let M=n(x,F=>F.metrics.toe);return M.x.length?{key:r("bumpSteer"),title:`${t} toe vs travel`,xLabel:"travel [mm]",yLabel:"toe [\xB0]",...M}:null},R=[{id:r("rcStatic"),group:`${t} roll centre`,label:"static height",unit:"mm",scale:30,scope:e,cost:"cheap",read:x=>x.rcRoll(e)?.rc[0]?.heightAboveGround??NaN},{id:r("rcHeaveWorst"),group:`${t} roll centre`,label:"worst migration vs travel",unit:"mm/mm",scale:.5,scope:e,cost:"cheap",read:x=>{let M=x.rcHeave(e);return M?VO(M.at,M.rc.map(F=>F.height)):NaN},curve:x=>{let M=x.rcHeave(e);return M?{key:r("rcHeaveWorst"),title:`${t} roll-centre height vs wheel travel`,xLabel:"travel [mm]",yLabel:"RC height [mm]",x:M.at,y:M.rc.map(F=>F.height)}:null}},{id:r("rcRollSpan"),group:`${t} roll centre`,label:"height span over the roll envelope",unit:"mm",scale:15,scope:e,cost:"cheap",read:x=>{let M=x.rcRoll(e);return M?Ac(M.rc.map(F=>F.height)):NaN},curve:x=>{let M=x.rcRoll(e);return M?{key:r("rcRollSpan"),title:`${t} roll-centre height vs body roll`,xLabel:"roll [\xB0]",yLabel:"RC height [mm]",x:M.at,y:M.rc.map(F=>F.height)}:null}},{id:r("rcLateralSpan"),group:`${t} roll centre`,label:"lateral migration over roll",unit:"mm",scale:50,scope:e,cost:"cheap",read:x=>{let M=x.rcRoll(e);return M?Ac(M.rc.map(F=>F.lateral)):NaN},curve:x=>{let M=x.rcRoll(e);return M?{key:r("rcLateralSpan"),title:`${t} roll-centre lateral position vs body roll`,xLabel:"roll [\xB0]",yLabel:"RC lateral [mm]",x:M.at,y:M.rc.map(F=>F.lateral)}:null}},{id:r("minSinAngle"),group:`${t} roll centre`,label:"construction conditioning (min sinAngle)",unit:"-",scale:.04,scope:e,cost:"cheap",read:x=>{let M=x.rcHeave(e),F=x.rcRoll(e);return!M||!F?NaN:Math.min(...M.rc.map(w=>w.sinAngle),...F.rc.map(w=>w.sinAngle))},curve:x=>{let M=x.rcHeave(e);return M?{key:r("minSinAngle"),title:`${t} construction conditioning vs travel`,xLabel:"travel [mm]",yLabel:"sinAngle",x:M.at,y:M.rc.map(F=>F.sinAngle)}:null}},{id:r("fvsaLength"),group:`${t} roll centre`,label:"front-view swing-arm length",unit:"mm",scale:500,scope:e,cost:"readout",read:x=>h(x)?.fvsaLength??NaN},{id:r("complianceSteer"),group:`${t} compliance`,label:"compliance steer",unit:"\xB0/kN lateral",scale:.05,scope:e,cost:"readout",read:x=>(x.compliance(e)?.toePerFy??0)*1e3},{id:r("complianceCamber"),group:`${t} compliance`,label:"compliance camber",unit:"\xB0/kN lateral",scale:.05,scope:e,cost:"readout",read:x=>(x.compliance(e)?.camberPerFy??0)*1e3},{id:r("complianceSteerLong"),group:`${t} compliance`,label:"compliance steer under braking",unit:"\xB0/kN longitudinal",scale:.05,scope:e,cost:"readout",read:x=>(x.compliance(e)?.toePerFx??0)*1e3},{id:r("steeringCompliance"),group:`${t} compliance`,label:"steer given back under aligning torque",unit:"\xB0/100 N\xB7m",scale:.2,scope:e,cost:"readout",read:x=>(x.compliance(e)?.toePerMz??0)*1e5},{id:r("staticCamber"),group:`${t} camber & toe`,label:"static camber",unit:"\xB0",scale:1,scope:e,cost:"cheap",read:x=>{let M=x.solveAt(e,0);return M?M.metrics.camber:NaN}},{id:r("staticToe"),group:`${t} camber & toe`,label:"static toe",unit:"\xB0",scale:.5,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.toe??NaN},{id:r("camberGainDesign"),group:`${t} camber & toe`,label:"camber gain in bump",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.camberGain??NaN,curve:x=>g(x)},{id:r("rollCamber"),group:`${t} camber & toe`,label:"camber gain in roll",unit:"\xB0/\xB0",scale:.2,scope:e,cost:"readout",read:x=>h(x)?.rollCamber??NaN},{id:r("rollCamberRecovery"),group:`${t} camber & toe`,label:"camber recovery in roll",unit:"%",scale:20,scope:e,cost:"readout",read:x=>h(x)?.camberRecovery??NaN},{id:r("bumpSteerDesign"),group:`${t} camber & toe`,label:"bump steer at design",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.bumpSteer??NaN,curve:x=>y(x)},{id:r("rollSteer"),group:`${t} camber & toe`,label:"roll steer",unit:"\xB0/\xB0",scale:.1,scope:e,cost:"readout",read:x=>h(x)?.rollSteer??NaN},{id:r("bumpSteer"),group:`${t} camber & toe`,label:"bump steer, RMS over the travel",unit:"\xB0/mm",scale:.02,scope:e,cost:"cheap",read:x=>{let M=n(x,F=>F.metrics.toe);return M.x.length?RF(M.x,M.y):NaN},curve:x=>y(x)},{id:r("camberGain"),group:`${t} camber & toe`,label:"camber gain, RMS over the travel",unit:"\xB0/mm",scale:.02,scope:e,cost:"cheap",read:x=>{let M=n(x,F=>F.metrics.camber);return M.x.length?RF(M.x,M.y):NaN},curve:x=>g(x)},{id:r("camberSpan"),group:`${t} camber & toe`,label:"camber range over travel",unit:"\xB0",scale:1,scope:e,cost:"cheap",read:x=>Ac(n(x,M=>M.metrics.camber).y)},{id:r("toeSpan"),group:`${t} camber & toe`,label:"toe range over travel",unit:"\xB0",scale:.5,scope:e,cost:"cheap",read:x=>Ac(n(x,M=>M.metrics.toe).y)},{id:r("camberRecovery"),group:`${t} camber & toe`,label:"outer camber at limit roll",unit:"\xB0",scale:2,scope:e,cost:"cheap",read:x=>{let M=x.solveAt(e,x.travelAtRoll(e,x.envelope.rollAtLimitDeg)),F=x.solveAt(e,0);return!M||!F?NaN:Math.abs(M.metrics.camber-F.metrics.camber+x.envelope.rollAtLimitDeg)}},{id:r("stateCamberOuter"),group:`${t} camber & toe`,label:"outer camber to the road at a state",unit:"\xB0",scale:1,scope:e,cost:"cheap",reads:"state",acrossStates:"mean",read:(x,M)=>ja(x,M,F=>F.camber[Fc(e,F.outer)])},{id:r("stateCamberInner"),group:`${t} camber & toe`,label:"inner camber to the road at a state",unit:"\xB0",scale:1,scope:e,cost:"cheap",reads:"state",acrossStates:"mean",read:(x,M)=>ja(x,M,F=>F.camber[Fc(e,MF(F.outer))])},{id:r("stateToeOuter"),group:`${t} camber & toe`,label:"outer toe change at a state",unit:"\xB0",scale:.2,scope:e,cost:"cheap",reads:"state",acrossStates:"mean",read:(x,M)=>ja(x,M,F=>F.corners[Fc(e,F.outer)].bumpToe)},{id:r("caster"),group:`${t} upright`,label:"caster",unit:"\xB0",scale:5,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.caster??NaN},{id:r("kpi"),group:`${t} upright`,label:"kingpin inclination",unit:"\xB0",scale:5,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.kpi??NaN},{id:r("scrubRadius"),group:`${t} upright`,label:"scrub radius",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.scrubRadius??NaN},{id:r("mechanicalTrail"),group:`${t} upright`,label:"mechanical trail",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.mechanicalTrail??NaN},{id:r("kingpinOffset"),group:`${t} upright`,label:"kingpin offset at hub height",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.kingpinOffset??NaN},{id:r("casterOffset"),group:`${t} upright`,label:"caster offset at hub height",unit:"mm",scale:10,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.casterOffset??NaN},{id:r("steeringArm"),group:`${t} upright`,label:"steering arm",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.steeringArm??NaN},{id:r("casterGain"),group:`${t} upright`,label:"caster gain in bump",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.casterGain??NaN},{id:r("kpiGain"),group:`${t} upright`,label:"kingpin inclination gain in bump",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.kpiGain??NaN},{id:r("scrubGain"),group:`${t} upright`,label:"scrub radius gain in bump",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:x=>h(x)?.scrubGain??NaN},{id:r("trailGain"),group:`${t} upright`,label:"mechanical trail gain in bump",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:x=>h(x)?.trailGain??NaN},{id:r("motionRatio"),group:`${t} rates`,label:"motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let M=x.sweep(e);return M?kF(M.samples.map(F=>F.travel),M.samples.map(F=>F.metrics.motionRatio??NaN))??NaN:NaN},curve:x=>{if(c(x.car))return null;let M=n(x,F=>F.metrics.motionRatio??NaN);return M.x.length?{key:r("motionRatio"),title:`${t} motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",...M}:null}},{id:r("mrSpread"),group:`${t} rates`,label:"motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let M=x.sweep(e);if(!M)return NaN;let F=M.samples.map(C=>C.metrics.motionRatio??NaN).filter(Number.isFinite);if(!F.length)return NaN;let w=F.reduce((C,T)=>C+T,0)/F.length;return w>0?(Math.max(...F)-Math.min(...F))/w:NaN}},{id:r("wheelRate"),group:`${t} rates`,label:"wheel rate at design",unit:"N/mm",scale:10,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let M=x.sweep(e);return M?kF(M.samples.map(F=>F.travel),M.samples.map(F=>F.metrics.wheelRate??NaN))??NaN:NaN}},{id:r("heaveMotionRatio"),group:`${t} rates`,label:"heave element motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:u,read:x=>p(x)?.atDesign??NaN,curve:x=>{let M=p(x);return M?{key:r("heaveMotionRatio"),title:`${t} heave element motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",x:M.travel,y:M.ratio}:null}},{id:r("heaveMrSpread"),group:`${t} rates`,label:"heave element motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:u,read:x=>vF(p(x)?.ratio)},{id:r("heaveWheelRate"),group:`${t} rates`,label:"heave element wheel rate at design",unit:"N/mm",scale:10,scope:e,cost:"cheap",unavailable:l,read:x=>l(x.car)||!x.sweep(e)?NaN:va(x.car.vehicle,x.car.params)[e]??NaN},{id:r("rollMotionRatio"),group:`${t} rates`,label:"roll element motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:f,read:x=>d(x)?.atDesign??NaN,curve:x=>{let M=d(x);return M?{key:r("rollMotionRatio"),title:`${t} roll element motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",x:M.travel,y:M.ratio}:null}},{id:r("rollMrSpread"),group:`${t} rates`,label:"roll element motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:f,read:x=>vF(d(x)?.ratio)},{id:r("rollWheelRate"),group:`${t} rates`,label:"roll element wheel rate at design",unit:"N/mm",scale:10,scope:e,cost:"cheap",unavailable:m,read:x=>m(x.car)||!x.sweep(e)?NaN:Zn(x.car.vehicle,x.car.params)[e]??NaN},{id:r("ucaAxisLength"),group:`${t} package`,label:"upper arm pivot-axis length",unit:"mm",scale:80,scope:e,cost:"geometry",read:x=>x.axisLength(e,"uca")},{id:r("lcaAxisLength"),group:`${t} package`,label:"lower arm pivot-axis length",unit:"mm",scale:80,scope:e,cost:"geometry",read:x=>x.axisLength(e,"lca")},{id:r("linkLength"),group:`${t} package`,label:"tie/toe link length",unit:"mm",scale:100,scope:e,cost:"geometry",read:x=>x.linkLength(e)},{id:r("trackScrubRate"),group:`${t} package`,label:"track scrub rate",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:x=>x.readout(Sc)?.[e].trackScrubRate??NaN},{id:r("trackChange"),group:`${t} package`,label:"track change at full bump",unit:"mm",scale:2,scope:e,cost:"readout",read:x=>b(x)?.trackChange??NaN},{id:r("stateTravelOuter"),group:`${t} package`,label:"outer wheel travel at a state",unit:"mm",scale:10,scope:e,cost:"cheap",reads:"state",acrossStates:"max",read:(x,M)=>ja(x,M,F=>F.corners[Fc(e,F.outer)].travel)},{id:r("stateTravelInner"),group:`${t} package`,label:"inner wheel travel at a state",unit:"mm",scale:10,scope:e,cost:"cheap",reads:"state",acrossStates:"min",read:(x,M)=>ja(x,M,F=>F.corners[Fc(e,MF(F.outer))].travel)},{id:r("damperStroke"),group:`${t} package`,label:"damper stroke over the travel",unit:"mm",scale:20,scope:e,cost:"cheap",unavailable:c,read:x=>c(x.car)?NaN:Ac(n(x,M=>M.metrics.damperLength).y),curve:x=>{if(c(x.car))return null;let M=n(x,F=>F.metrics.damperLength);return M.x.length?{key:r("damperStroke"),title:`${t} damper length vs travel`,xLabel:"travel [mm]",yLabel:"length [mm]",...M}:null}}];e==="front"&&R.push({id:r("camberPerSteer"),group:`${t} camber & toe`,label:"camber change with steer",unit:"\xB0/\xB0",scale:.05,scope:"front",cost:"readout",read:x=>h(x)?.camberPerSteer??NaN},{id:r("steerJacking"),group:`${t} upright`,label:"corner rise per degree of steer",unit:"mm/\xB0",scale:.05,scope:"front",cost:"readout",read:x=>h(x)?.steerJacking??NaN}),e==="front"?R.push({id:r("antiDive"),group:`${t} anti geometry`,label:"anti-dive",unit:"%",scale:20,scope:"front",cost:"readout",read:x=>x.readout(Sc)?.front.antiDive??NaN}):R.push({id:r("antiSquat"),group:`${t} anti geometry`,label:"anti-squat (driving)",unit:"%",scale:20,scope:"rear",cost:"readout",read:x=>x.readout(Sc)?.rear.antiSquat??NaN},{id:r("antiLift"),group:`${t} anti geometry`,label:"anti-lift (braking)",unit:"%",scale:20,scope:"rear",cost:"readout",read:x=>x.readout(Sc)?.rear.antiLift??NaN});let k=x=>{let M=x.slice(t.length+1);return M.charAt(0).toUpperCase()+M.slice(1)};return[...new Set(R.map(x=>x.group))].flatMap(x=>R.filter(M=>M.group===x)).map(x=>({...x,quantity:`${t} \xB7 ${k(x.group)}`}))}function AF(e,t){let r=e.steer();if(!r)return NaN;let n=r.filter(a=>Number.isFinite(a.ackermannPct)&&a.inner>.3&&a.outer>.3);return n.length?n.reduce((a,s)=>t==="centre"?s.inner<a.inner?s:a:s.inner>a.inner?s:a).ackermannPct:NaN}var BO=[{id:"kin.front.ackermannCentre",group:"Steering",label:"Ackermann near centre",unit:"%",scale:25,scope:"front",cost:"cheap",read:e=>AF(e,"centre"),curve:e=>{let t=e.steer();if(!t)return null;let r=t.filter(n=>Number.isFinite(n.ackermannPct)&&n.inner>.3&&n.outer>.3);return r.length?{key:"kin.front.ackermann",title:"Ackermann vs steer",xLabel:"inner wheel steer [\xB0]",yLabel:"Ackermann [%]",x:r.map(n=>n.inner),y:r.map(n=>n.ackermannPct)}:null}},{id:"kin.front.ackermannLock",group:"Steering",label:"Ackermann at lock",unit:"%",scale:25,scope:"front",cost:"cheap",read:e=>AF(e,"lock")},{id:"kin.front.lockInner",group:"Steering",label:"inner wheel angle at full rack",unit:"\xB0",scale:5,scope:"front",cost:"cheap",read:e=>{let t=e.steer();return t?.length?Math.max(...t.map(r=>r.inner)):NaN}}],$O=[{id:"kin.car.trackFront",group:"Whole car",label:"front track",unit:"mm",scale:50,scope:"front",cost:"geometry",read:e=>2*e.car.vehicle.front.hardpoints.wheelCenter[1]},{id:"kin.car.trackRear",group:"Whole car",label:"rear track",unit:"mm",scale:50,scope:"rear",cost:"geometry",read:e=>2*e.car.vehicle.rear.hardpoints.wheelCenter[1]},{id:"kin.car.stateRoll",group:"Whole car",label:"body roll at a state",unit:"\xB0",scale:1,scope:"car",cost:"cheap",reads:"state",acrossStates:"max",read:(e,t)=>ja(e,t,r=>Math.abs(r.rollDeg))},{id:"kin.car.wheelbaseChange",group:"Whole car",label:"wheelbase change at full bump",unit:"mm",scale:2,scope:"car",cost:"readout",read:e=>{let t=e.readoutAtTravel("front",e.envelope.travelMax),r=e.readoutAtTravel("rear",e.envelope.travelMax);return t&&r?t.longitudinal-r.longitudinal:NaN}}],$0=[...SF("front"),...SF("rear"),...BO,...$O];var PF={front:"Front",rear:"Rear"},FF=e=>xo("side",e),GO=e=>xo("drive",e)&&xo("brake",e)?"neither brakes nor drives":null;function KO(e,t,r,n){let o=Wa(e,t,r),a=o?e.tyreAt(o):null;return a?n(a):NaN}function Ua(e,t){let r={...e,read:(n,o)=>KO(n,r,o,t)};return r}var wF=e=>e?100*e.lossCamber:NaN,CF=e=>e&&!e.lifted?e.camber-e.wants:NaN;function TF(e){let t=PF[e],r=s=>`tyre.${e}.${s}`,n={group:`${t} tyre`,quantity:`${t} \xB7 Tyre`,scope:e,cost:"cheap",reads:"state",acrossStates:"mean"},o={...n,appliesAt:FF,unavailable:s=>c0(s.params,e)},a=[Ua({...o,id:r("camberErrorOuter"),label:"camber error at the outer wheel",unit:"\xB0",scale:.5},s=>CF(s.side(e)?.wheels[0])),Ua({...o,id:r("camberErrorInner"),label:"camber error at the inner wheel",unit:"\xB0",scale:.5},s=>CF(s.side(e)?.wheels[1])),Ua({...o,id:r("sideLossCamber"),label:"side grip lost to camber",unit:"%",scale:1},s=>wF(s.side(e))),Ua({...n,appliesAt:FF,id:r("sideLossToe"),label:"side grip lost to the toe split",unit:"%",scale:1},s=>100*s.toeLoss(e)),Ua({...n,appliesAt:GO,unavailable:s=>l0(s.params,e),id:r("longLossCamber"),label:"drive and brake grip lost to camber",unit:"%",scale:1},s=>wF(s.long(e)))];return e==="front"&&a.push(Ua({...n,appliesAt:s=>xo("ackermann",s),id:r("ackermannError"),label:"Ackermann against the tyre",unit:"%",scale:25},s=>s.ackermann())),a}var G0=[...TF("front"),...TF("rear")],HO=/^tyre\.(front|rear)\.(camberErrorOuter|camberErrorInner|sideLossCamber|longLossCamber)$/;function K0(e,t){let r=new Map,n=a=>a.name.charAt(0).toLowerCase()+a.name.slice(1),o=a=>`${a>0?"+":a<0?"\u2212":""}${Math.abs(a).toFixed(1)}\xB0`;for(let{m:a,at:s}of t){let i=HO.exec(a.id);if(!i)continue;let c=i[1],l=i[2]==="longLossCamber",u=s?.stateId==="*"?e.states.filter(m=>!a.appliesAt?.(m)):[Wa(e,a,s)].filter(m=>!!m);for(let m of u){let f=`${c}|${m.id}|${l}`;if(r.has(f))continue;let p=e.tyreAt(m),d=p?l?p.long(c):p.side(c):null;if(!d)continue;let{lo:h,hi:b,stated:g}=d.range,y=g?`the ${o(h)} \u2026 ${o(b)} its data covers`:`the \xB1${b.toFixed(0)}\xB0 read without a stated range`,R=M=>l?M===0?"left":"right":M===0?"outer":"inner",k=d.wheels.findIndex(M=>M.atEdge),v=d.wheels.findIndex(M=>M.outside&&!M.lifted),x=[];k>=0&&x.push(`the ${PF[c].toLowerCase()} ${R(k)} tyre wants ${o(d.wheels[k].wants)}, the edge of ${y}, and may want more`),v>=0&&x.push(`the ${R(v)} wheel has ${o(d.wheels[v].camber)}, past it, and is read at ${o(d.wheels[v].read)}`),x.length&&r.set(f,`In the ${n(m)} ${x.join("; ")}.`)}}return[...r.values()]}function H0(e,t){let r=e.appliesAt?.(t);return r?`is read at ${t.name}, which ${r}`:null}var zO={front:"Front",rear:"Rear"};function YO(e,t,r,n){let o=Wa(e,t,r),a=o?e.platformAt(o):null;return(a?n(a):null)??NaN}function Kt(e,t){let r={...e,read:(n,o)=>YO(n,r,o,t)};return r}var z0={cost:"cheap",reads:"state"},WO={unavailable:e=>P0(e.params)};function LF(e){let t=zO[e],r=o=>`platform.${e}.${o}`,n={...z0,group:`${t} platform`,quantity:`${t} \xB7 Platform`,scope:e};return[Kt({...n,id:r("rideHeight"),label:"ride height at a state",unit:"mm",scale:5,acrossStates:"min"},o=>o[e].height),Kt({...n,id:r("toBumpStop"),label:"travel left to the bump stop",unit:"mm",scale:5,acrossStates:"min",unavailable:o=>ap(o.vehicle,o.params,e,"bump")},o=>o[e].toBump),Kt({...n,id:r("toDroopStop"),label:"travel left to the droop stop",unit:"mm",scale:5,acrossStates:"min",unavailable:o=>ap(o.vehicle,o.params,e,"droop")},o=>o[e].toDroop)]}var mp={...z0,group:"Platform",scope:"car"},wc={...z0,...WO,group:"Aero platform",groupShort:"Aero",scope:"car"},Y0=[...LF("front"),...LF("rear"),Kt({...mp,id:"platform.rake",label:"rake at a state",unit:"\xB0",scale:.2,acrossStates:"span"},e=>e.rakeDeg),Kt({...mp,id:"platform.pitch",label:"pitch at a state",unit:"\xB0",scale:.2,acrossStates:"max"},e=>e.pitchDeg),Kt({...mp,id:"platform.roll",label:"body roll at a state",unit:"\xB0",scale:.2,acrossStates:"max"},e=>e.rollDeg),Kt({...mp,id:"platform.groundClearance",label:"ground clearance at a state",unit:"mm",scale:5,acrossStates:"min",unavailable:e=>L0(e.vehicle)},e=>e.clearance?.height),Kt({...wc,id:"platform.balance",label:"balance at a state",unit:"%",scale:1,acrossStates:"span"},e=>e.aero?.balance),Kt({...wc,id:"platform.clA",label:"downforce Cl\xB7A at a state",unit:"m\xB2",scale:.1,acrossStates:"mean"},e=>e.aero?.clA),Kt({...wc,id:"platform.cdA",label:"drag Cd\xB7A at a state",unit:"m\xB2",scale:.05,acrossStates:"mean"},e=>e.aero?.cdA),Kt({...wc,id:"platform.dataMargin",label:"margin to the model\u2019s data",unit:"mm",scale:5,acrossStates:"min"},e=>e.aero?.dataMargin),Kt({...wc,id:"platform.loopMargin",label:"aero-elastic margin, 1 \u2212 loop gain",unit:"-",scale:.1,acrossStates:"min"},e=>e.aero?.loopMargin)];var DF={understeer:"operating",yawFreq:"speed",yawZeta:"speed",yawStiffness:"operating",steeringTorque:"operating",steeringTorqueGradient:"operating"};function nt(e,t,r,n="cheap"){let o=Ib[e];if(!o)throw new Error(`no DYN_METRIC "${e}"`);return{id:`dyn.${e}`,group:t,label:o.label,unit:o.unit,scale:r,scope:"car",cost:n,...DF[e]?{reads:DF[e]}:{},read:(a,s)=>{let i=a.dynInput(),c=a.dynCtx(s);return i&&c?o.compute(i,c):NaN}}}var jO=[nt("understeer","Handling \u2014 balance",.1),nt("tlltdFront","Handling \u2014 balance",5),nt("rollStiffFront","Handling \u2014 balance",5)],UO=[nt("yawFreq","Handling \u2014 response",.5),nt("yawZeta","Handling \u2014 response",.2),nt("stabilitySpeed","Handling \u2014 response",50),nt("yawStiffness","Handling \u2014 response",2e4,"trim")],XO=[nt("steeringTorque","Steering feel",1,"trim"),nt("steeringTorqueGradient","Steering feel",2,"trim")],qO=[nt("rollGradient","Ride & body",.5),nt("pitchGradient","Ride & body",.5),nt("rideFreqFront","Ride & body",.5),nt("rideFreqRear","Ride & body",.5),nt("rollFreq","Ride & body",.5),nt("pitchFreq","Ride & body",.5),nt("zetaFront","Ride & body",.2),nt("zetaRear","Ride & body",.2)],QO=[{id:"dyn.reserveStabil",group:"What the car has left",label:"Yaw stability reserve",unit:"N\xB7m",scale:200,scope:"car",cost:"trim",reads:"operating",read:(e,t)=>e.reserves("operating",t)?.stabil??NaN},{id:"dyn.reserveAgil",group:"What the car has left",label:"Yaw agility reserve",unit:"N\xB7m",scale:200,scope:"car",cost:"trim",reads:"operating",read:(e,t)=>e.reserves("operating",t)?.agil??NaN},{id:"dyn.limitBalance",group:"What the car has left",label:"Limit balance (+US / \u2212OS)",unit:"-",scale:.5,scope:"car",cost:"trim",reads:"speed",read:(e,t)=>e.reserves("limit",t)?.rel??NaN}],ZO=[{id:"dyn.ymdMaxAy",group:"Yaw-moment diagram",label:"Max lateral acceleration",unit:"g",scale:.2,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymd(t)?.maxAy??NaN},{id:"dyn.ymdStability",group:"Yaw-moment diagram",label:"Stability \u2202CN/\u2202\u03B2 at the origin",unit:"1/rad",scale:5,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymd(t)?.stability??NaN},{id:"dyn.ymdControl",group:"Yaw-moment diagram",label:"Control \u2202CN/\u2202\u03B4 at the origin",unit:"1/rad",scale:.5,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymd(t)?.control??NaN},{id:"dyn.trimAy",group:"Yaw-moment diagram",label:"Trim limit \u2014 the fastest corner it can hold",unit:"g",scale:.2,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.ay??NaN},{id:"dyn.trimBeta",group:"Yaw-moment diagram",label:"Body slip at the trim limit",unit:"\xB0",scale:2,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.betaDeg??NaN},{id:"dyn.trimDelta",group:"Yaw-moment diagram",label:"Steer at the trim limit",unit:"\xB0",scale:2,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.deltaDeg??NaN},{id:"dyn.trimControlFrac",group:"Yaw-moment diagram",label:"Control left at the trim limit",unit:"-",scale:.25,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.controlFrac??NaN},{id:"dyn.trimStiffnessFrac",group:"Yaw-moment diagram",label:"Yaw stiffness left at the trim limit",unit:"-",scale:.25,scope:"car",cost:"diagram",reads:"speed",read:(e,t)=>e.ymdLimit(t)?.stiffnessFrac??NaN}],W0=[...jO,...UO,...XO,...qO,...QO,...ZO];function JO(e,t){let r=e.lap(t),n=e.course(t);if(!r||!n)return NaN;let o=n.track.ds,a=0,s=0;for(let i=0;i<r.v.length-1;i++){let c=o[i]??0,l=.5*(r.v[i]+r.v[i+1]);c>0&&l>0&&(a+=c,s+=c/l)}return s>0?a/s:NaN}var j0=[{id:"lap.time",group:"Lap & manoeuvre",label:"Time",unit:"s",scale:.1,scope:"car",cost:"lap",reads:"course",across:"sum",read:(e,t)=>e.lap(t)?.laptime??NaN},{id:"lap.vMean",group:"Lap & manoeuvre",label:"Mean speed",unit:"km/h",scale:2,scope:"car",cost:"lap",reads:"course",across:"harmonic",read:(e,t)=>JO(e,t)*3.6},{id:"lap.vMin",group:"Lap & manoeuvre",label:"Minimum speed",unit:"km/h",scale:2,scope:"car",cost:"lap",reads:"course",across:"min",read:(e,t)=>{let r=e.lap(t);return r?Math.min(...r.v)*3.6:NaN}},{id:"lap.vMax",group:"Lap & manoeuvre",label:"Maximum speed",unit:"km/h",scale:5,scope:"car",cost:"lap",reads:"course",across:"max",read:(e,t)=>{let r=e.lap(t);return r?Math.max(...r.v)*3.6:NaN}},{id:"lap.ayPeak",group:"Lap & manoeuvre",label:"Peak lateral acceleration",unit:"g",scale:.1,scope:"car",cost:"lap",reads:"course",across:"max",read:(e,t)=>{let r=e.lap(t);return r?Math.max(...r.ay.map(Math.abs))/9.81:NaN}},{id:"lap.minStabil",group:"What the car had left",label:"Worst stability reserve",unit:"N\xB7m",scale:50,scope:"car",cost:"lap",reads:"course",across:"min",read:(e,t)=>e.lapReserve(t)?.minStabil??NaN},{id:"lap.understeerFrac",group:"What the car had left",label:"Lap fraction front-limited",unit:"-",scale:.1,scope:"car",cost:"lap",reads:"course",across:"distance",read:(e,t)=>e.lapReserve(t)?.understeerFrac??NaN},{id:"lap.beyondFrac",group:"What the car had left",label:"Beyond the tyre ellipse \u2014 a health warning, not a target",unit:"-",scale:.05,scope:"car",cost:"lap",reads:"course",across:"distance",read:(e,t)=>e.lapReserve(t)?.beyondFrac??NaN}];function eV(e,t){let r=/^(.*?)\s*\(([^)]+)\)\s*$/.exec(e);return r?{label:r[1],unit:r[2]}:{label:e,unit:t?"s":""}}function tV(e){return e==="s"||e==="kWh"?.1:e==="km/h"?2:1}var EF=new WeakMap;function pp(e){let t=EF.get(e);return t||(t=e.metrics.filter(Hc).map(r=>{let{label:n,unit:o}=eV(r.label,r.format==="time");return{id:`event.${e.id}.${r.key}`,group:`Events \xB7 ${e.label}`,groupShort:"Events",label:n,unit:o,scale:tV(o),scope:"car",cost:"session",read:a=>a.session(e.id)?.[r.key]??NaN}}),EF.set(e,t),t)}var U0=Na.flatMap(pp);var dp=[...$0,...G0,...Y0,...W0,...j0,...U0],Xa=Object.fromEntries(dp.map(e=>[e.id,e]));var IF={all:dp,byId:Xa},_F=new WeakMap;function Ur(e=[]){if(e.length===0)return IF;let t=_F.get(e);if(t)return t;let r=ag(e).filter(n=>!Oa(n.id)).flatMap(pp);return t=r.length?{all:[...dp,...r],byId:{...Xa,...Object.fromEntries(r.map(n=>[n.id,n]))}}:IF,_F.set(e,t),t}var Cc=180/Math.PI,qa=Math.PI/180,nV=.2;function fp(e,t){let r=H(t,e);return q(r[0]<0?Ad(r):r)}var hp=e=>({side:Math.atan2(e[2],e[0])*Cc,plan:Math.atan2(e[1],e[0])*Cc}),bp=(e,t)=>q([1,Math.tan(t*qa),Math.tan(e*qa)]),Tc=e=>Math.abs(e[0])>=nV,gp=(e,t)=>Math.atan(t/Math.max(e,1))*Cc,yp=(e,t)=>Math.tan(t*qa)*Math.max(e,1);var An=["side","plan","clock","len"],Xt={uca:{fore:"ucaFront",aft:"ucaRear",ball:"uprightUpper"},lca:{fore:"lcaFront",aft:"lcaRear",ball:"uprightLower"}},Pc={uca:"upper arm",lca:"lower arm"},oV=1,NF=(e,t)=>fp(e[Xt[t].fore],e[Xt[t].aft]);function OF(e){let t=q(H(Sd,U(e,X(Sd,e))));return{e1:t,e2:ae(e,t)}}function X0(e,t){let r=NF(e,t);if(!Tc(r))return`the ${Pc[t]}'s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it`;let n=Xt[t],o=tn(e[n.ball],e[n.fore],r);return Math.hypot(...H(o,e[n.ball]))>=oV?null:`the ${Pc[t]}'s ball joint sits on its own pivot axis, so the arm has no length to swing on`}function Xr(e,t){let r=Xt[t],n=e[r.ball],o=NF(e,t),a=tn(n,e[r.fore],o),s=H(a,n),i=Math.hypot(s[0],s[1],s[2]),{e1:c,e2:l}=OF(o),u=i>0?U(s,1/i):c;return{...hp(o),clock:Math.atan2(X(u,l),X(u,c))*Cc,len:i,sFront:X(H(e[r.fore],a),o),sRear:X(H(e[r.aft],a),o)}}function q0(e,t){let r=bp(e.side,e.plan),{e1:n,e2:o}=OF(r),a=ee(U(n,Math.cos(e.clock*qa)),U(o,Math.sin(e.clock*qa))),s=ee(t,U(a,e.len));return{fore:ee(s,U(r,e.sFront)),aft:ee(s,U(r,e.sRear))}}function VF(e,t,r,n){let o=Xt[t],a={...Xr(e,t),[r]:n},{fore:s,aft:i}=q0(a,e[o.ball]);return{...e,[o.fore]:s,[o.aft]:i}}function BF(e,t){return t==="clock"?e.len:Math.abs(e.sFront-e.sRear)/2}function xp(e,t,r){return t==="len"?r:gp(BF(e,t),r)}function Q0(e,t,r){return t==="len"?r:yp(BF(e,t),r)}var vo=["side","plan","atY","atZ"],ko={fore:"rockerPivotA",aft:"rockerPivotB"},aV=5,$F=e=>fp(e.rockerPivotA,e.rockerPivotB);function Qa(e){return Math.hypot(...H(e.rockerPivotB,e.rockerPivotA))<aV?"the rocker\u2019s two pivots are the same point, so there is no axis to describe":Tc($F(e))?null:"the rocker\u2019s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it"}function Fn(e){let t=$F(e),r=Tc(t)?t:[1,0,0],n=e.rockerPivotA,o=ee(n,U(r,-n[0]/r[0]));return{...hp(r),atY:o[1],atZ:o[2],sA:X(H(n,o),r),sB:X(H(e.rockerPivotB,o),r)}}function Z0(e){let t=bp(e.side,e.plan),r=[0,e.atY,e.atZ];return{a:ee(r,U(t,e.sA)),b:ee(r,U(t,e.sB))}}function GF(e,t,r){if(Qa(e))return e;let{a:n,b:o}=Z0({...Fn(e),[t]:r});return{...e,rockerPivotA:n,rockerPivotB:o}}var KF=e=>Math.abs(e.sA-e.sB)/2;function J0(e,t,r){return t==="side"||t==="plan"?gp(KF(e),r):r}function ey(e,t,r){return t==="side"||t==="plan"?yp(KF(e),r):r}var Qt={front:"Front",rear:"Rear"},qt=["x","y","z"],Ve=(e,t)=>t==="front"?e.front:e.rear,Lc=(e,t,r)=>t==="front"?{...e,front:r}:{...e,rear:r},HF=[{kind:"inboard",keys:[{key:"ucaFront",label:"UCA front pivot"},{key:"ucaRear",label:"UCA rear pivot"},{key:"lcaFront",label:"LCA front pivot"},{key:"lcaRear",label:"LCA rear pivot"},{key:"tieInner",label:"tie/toe link inner"}]},{kind:"outboard",keys:[{key:"uprightUpper",label:"upper ball joint"},{key:"uprightLower",label:"lower ball joint"},{key:"tieOuter",label:"tie/toe link outer"},{key:"wheelCenter",label:"wheel centre"}]},{kind:"actuation",keys:[{key:"pushrodOuter",label:"push/pull rod outer"},{key:"rockerPivotA",label:"rocker pivot A"},{key:"rockerPivotB",label:"rocker pivot B"},{key:"rockerToPushrod",label:"rocker \u2014 rod end"},{key:"rockerToDamper",label:"rocker \u2014 damper end"},{key:"damperChassis",label:"damper chassis mount"}]}],zF={damperChassis:"strut top mount",pushrodOuter:"strut lower mount"},Mo=30;function sV(e){let t=[];for(let r of["front","rear"]){let n=Ve(e.vehicle,r).config.layout==="mcpherson";for(let o of HF)for(let{key:a,label:s}of o.keys){let i=n&&zF[a]||s;for(let c=0;c<3;c++)t.push({id:`hp.${r}.${a}.${qt[c]}`,group:`${Qt[r]} hardpoints \u2014 ${o.kind}`,label:`${i} ${qt[c]}`,scope:Qt[r],unit:"mm",defaultSpan:Mo,read:l=>Ve(l.vehicle,r).hardpoints[a][c],write:(l,u)=>{let m=Ve(l.vehicle,r),f=[...m.hardpoints[a]];f[c]=u;let p={...m.hardpoints,[a]:f};return{...l,vehicle:Lc(l.vehicle,r,{...m,hardpoints:p})}}})}}return t}var iV={side:"axis side-view angle",plan:"axis plan-view angle",clock:"arm clock angle",len:"effective arm length"},cV={side:"\xB0",plan:"\xB0",clock:"\xB0",len:"mm"};function lV(e){let t=[];for(let r of["front","rear"]){let n=Ve(e.vehicle,r).config.layout==="mcpherson";for(let o of["uca","lca"]){let a=Ve(e.vehicle,r).hardpoints,s=X0(a,o)?null:Xr(a,o);for(let i of An)t.push({id:`arm.${r}.${o}.${i}`,group:`${Qt[r]} ${n?"arm axes":"wishbone axes"}`,label:`${Pc[o]} \u2014 ${iV[i]}`,scope:Qt[r],unit:cV[i],defaultSpan:s?xp(s,i,Mo):Mo,read:c=>Xr(Ve(c.vehicle,r).hardpoints,o)[i],write:(c,l)=>{let u=Ve(c.vehicle,r),m=VF(u.hardpoints,o,i,l);return{...c,vehicle:Lc(c.vehicle,r,{...u,hardpoints:m})}}})}}return t}var uV={side:"pivot axis side-view angle",plan:"pivot axis plan-view angle",atY:"pivot axis outboard, at the wheel-centre plane",atZ:"pivot axis height, at the wheel-centre plane"},mV={side:"\xB0",plan:"\xB0",atY:"mm",atZ:"mm"};function pV(e){let t=[];for(let r of["front","rear"]){let n=Ve(e.vehicle,r).hardpoints,o=Qa(n)?null:Fn(n);for(let a of vo)t.push({id:`rocker.${r}.${a}`,group:`${Qt[r]} rocker axis`,label:`rocker \u2014 ${uV[a]}`,scope:Qt[r],unit:mV[a],defaultSpan:o?J0(o,a,Mo):Mo,read:s=>Fn(Ve(s.vehicle,r).hardpoints)[a],write:(s,i)=>{let c=Ve(s.vehicle,r),l=GF(c.hardpoints,a,i);return{...s,vehicle:Lc(s.vehicle,r,{...c,hardpoints:l})}}})}return t}var Rp={front:"heaveFrontDesign",rear:"heaveRearDesign"},ty={front:"arbFrontDesign",rear:"arbRearDesign"};function dV(e,t){return{heave:e.config.actuation==="decoupled"?"heave element":"third spring",roll:t?.design.kind==="coil"?"roll shock":"anti-roll bar"}}var vp=e=>/^(heave|roll)\.(front|rear)\.(outer|inner|anchor)\.[xyz]$/.test(e);function fV(e){let t=[];for(let r of["front","rear"]){let n=Ve(e.vehicle,r),o=e.params[Rp[r]],a=e.params[ty[r]],s=dV(n,a),i=d=>d.params[Rp[r]],c=d=>d.params[ty[r]],l=(d,h)=>({...d,params:{...d.params,[Rp[r]]:h}}),u=(d,h)=>({...d,params:{...d.params,[ty[r]]:h}}),m={group:`${Qt[r]} heave & roll elements`,scope:Qt[r]},f=(d,h,b,g,y)=>{for(let R of b)t.push({...m,id:`${d}.${qt[R]}`,label:`${h} ${qt[R]}`,unit:"mm",defaultSpan:Mo,read:k=>g(k)[R],write:(k,v)=>{let x=[...g(k)];return x[R]=v,y(k,x)}})},p=(d,h,b,g,y)=>{t.push({...m,id:d,label:h,unit:"N/mm",defaultSpan:Math.max(5,b*.4),read:g,write:y})};if(o?.design.kind==="coil"){if(o.linkage){let d=b=>i(b).linkage;f(`heave.${r}.outer`,`${s.heave} eye`,[0,1,2],b=>d(b).outer,(b,g)=>l(b,{...i(b),linkage:{...d(b),outer:g}})),o.linkage.mount?.kind==="chassis"&&f(`heave.${r}.anchor`,`${s.heave} chassis anchor`,[0,2],b=>d(b).mount.anchor,(b,g)=>l(b,{...i(b),linkage:{...d(b),mount:{kind:"chassis",anchor:g}}}))}if(typeof o.design.rate=="number"){let d=h=>i(h).design;p(`heave.${r}.rate`,`${s.heave} spring rate (@element)`,o.design.rate,h=>d(h).rate,(h,b)=>l(h,{...i(h),design:{...d(h),rate:b}}))}}if(a&&a.design.kind!=="none"){if(a.linkage&&a.design.kind!=="direct"){let h=R=>c(R).linkage,b=an(n,a.linkage,a.design.kind),[g,y]=b?["left arm eye","right arm eye"]:["drop-link pickup","arm tip"];f(`roll.${r}.outer`,`${s.roll} ${g}`,[0,1,2],R=>h(R).outer,(R,k)=>u(R,{...c(R),linkage:{...h(R),outer:k}})),f(`roll.${r}.inner`,`${s.roll} ${y}`,[0,1,2],R=>h(R).inner,(R,k)=>u(R,{...c(R),linkage:{...h(R),inner:k}}))}let d=a.design;if(d.kind==="coil"&&typeof d.rate=="number"){let h=b=>c(b).design;p(`roll.${r}.rate`,`${s.roll} spring rate (@element)`,d.rate,b=>h(b).rate,(b,g)=>u(b,{...c(b),design:{kind:"coil",rate:g}}))}else d.kind==="direct"&&p(`roll.${r}.wheelRate`,`${s.roll} rate (@wheel)`,d.wheelRate,h=>c(h).design.wheelRate,(h,b)=>u(h,{...c(h),design:{kind:"direct",wheelRate:b}}))}}return t}var hV=[{axle:"front",field:"springRate",group:"Springs & bars",label:"spring rate (@spring)",unit:"N/mm",fallback:35,span:e=>Math.max(5,e*.4)},{axle:"rear",field:"springRate",group:"Springs & bars",label:"spring rate (@spring)",unit:"N/mm",fallback:40,span:e=>Math.max(5,e*.4)},{axle:"front",field:"rackTravel",group:"Steering",label:"rack travel from centre",unit:"mm",fallback:35,span:()=>15,frontOnly:!0},{axle:"front",field:"rackRatio",group:"Steering",label:"rack per steering-wheel turn",unit:"mm/rev",fallback:55,span:()=>15,frontOnly:!0},{axle:"front",field:"loadedRadius",group:"Wheel & tyre",label:"loaded radius",unit:"mm",fallback:228,span:()=>15},{axle:"rear",field:"loadedRadius",group:"Wheel & tyre",label:"loaded radius",unit:"mm",fallback:228,span:()=>15}];function bV(e){let t=[];for(let r of["front","rear"]){let n=Ve(e.vehicle,r).compliance;if(!n)continue;let o=(a,s,i,c)=>{let l=i(n);l===void 0||!(l>0)||!Number.isFinite(l)||t.push({id:`kc.${r}.${a}`,group:"Compliance",label:s,scope:Qt[r],unit:"N/mm",defaultSpan:Math.max(500,l*.4),read:u=>i(Ve(u.vehicle,r).compliance??{})??l,write:(u,m)=>{let f=Ve(u.vehicle,r),p={...f,compliance:c(f.compliance??{},Math.max(1,m))};return{...u,vehicle:Lc(u.vehicle,r,p)}}})};for(let a of["ucaFront","ucaRear","lcaFront","lcaRear","tieRod","pushRod"])o(`link.${a}`,`${gV[a]} (link)`,s=>s.links?.[a],(s,i)=>({...s,links:{...s.links,[a]:i}}));for(let a of["ucaFront","ucaRear","lcaFront","lcaRear","tieInner","topMount"])o(`bush.${a}`,`${yV[a]} (bushing)`,s=>s.bushings?.[a],(s,i)=>({...s,bushings:{...s.bushings,[a]:i}}));r==="front"&&o("rack","rack to housing",a=>a.rack,(a,s)=>({...a,rack:s}))}return t}var gV={ucaFront:"UCA front leg",ucaRear:"UCA rear leg",lcaFront:"LCA front leg",lcaRear:"LCA rear leg",tieRod:"tie rod",pushRod:"push/pull rod"},yV={ucaFront:"UCA front pickup",ucaRear:"UCA rear pickup",lcaFront:"LCA front pickup",lcaRear:"LCA rear pickup",tieInner:"tie-rod inner",topMount:"strut top mount"};function xV(){return hV.map(e=>({id:`cfg.${e.axle}.${e.field}`,group:e.group,label:e.label,scope:Qt[e.axle],unit:e.unit,defaultSpan:e.span(e.fallback),read:t=>Ve(t.vehicle,e.axle).config[e.field]??e.fallback,write:(t,r)=>{let n=Ve(t.vehicle,e.axle),o={...n,config:{...n.config,[e.field]:r}};return{...t,vehicle:Lc(t.vehicle,e.axle,o)}}}))}function RV(e){let t=Bn(e.params.steeringSystem);if(!t.enabled)return[];let r=(n,o,a,s,i)=>({id:`steeringSystem.${n}`,group:"Steering",label:o,unit:a,defaultSpan:s,read:c=>Bn(c.params.steeringSystem)[n],write:(c,l)=>({...c,params:{...c.params,steeringSystem:Bn({...c.params.steeringSystem,enabled:!0,[n]:i(l)})}})});return[r("roadFeedbackGain","road feedback gain","\xD7",Math.max(.1,.25*t.roadFeedbackGain),n=>Math.min(2,Math.max(0,n))),r("turnInFrictionNm","turn-in friction","N\xB7m",Math.max(.1,.5*t.turnInFrictionNm),n=>Math.max(0,n))]}function vV(e){let t=Mi(e.params),r=[];for(let n of["front","rear"]){if(t[n]!=="diff")continue;let o=eo(e.params.driveline?.[n]);if(o?.kind!=="clutch"&&o?.kind!=="torsen")continue;let a=(s,i)=>{let c=_u[`${n}.${s}`];return{id:`driveline.${n}.${s}`,group:"Differential",label:c.label.charAt(0).toLowerCase()+c.label.slice(1),scope:Qt[n],unit:c.unit===": 1"?"":c.unit??"",defaultSpan:i,read:l=>eo(l.params.driveline?.[n])?.[s],write:(l,u)=>({...l,params:{...l.params,driveline:Iu({...l.params.driveline,[n]:{...l.params.driveline?.[n],[s]:u}})}})}};o.kind==="clutch"?r.push(a("preloadNm",Math.max(5,.2*o.preloadNm)),a("rampDriveDeg",5),a("rampCoastDeg",5)):r.push(a("tbrDrive",Math.max(.25,.2*o.tbrDrive)),a("tbrCoast",Math.max(.25,.2*o.tbrCoast)))}return r}function kV(e){if(tu(e.params)!=="hydraulic")return[];let t=[{id:"brakeSetup.barFront",group:"Brakes",label:`${Ph("barFront").toLowerCase()}, front share`,unit:"-",defaultSpan:.05,read:a=>Pr(a.params.brakeSetup).barFront,write:(a,s)=>({...a,params:{...a.params,brakeSetup:Pr({...Pr(a.params.brakeSetup),barFront:s})}})}];if(!e.params.brakeModel)return t;let r=sr(e.params.brakeModel),n=(a,s)=>s.circuit?a[s.circuit][s.key]:a[s.key],o=(a,s,i)=>({id:`brakeModel.${a.circuit?`${a.circuit}.`:""}${String(a.key)}`,group:"Brakes",label:Th(a.circuit?`${a.circuit}.${String(a.key)}`:a.key),unit:s,defaultSpan:i,read:c=>n(sr(c.params.brakeModel),a),write:(c,l)=>{let u=sr(c.params.brakeModel),m=a.circuit?{...u,[a.circuit]:{...u[a.circuit],[a.key]:l}}:{...u,[a.key]:l};return{...c,params:{...c.params,brakeModel:sr(m)}}}});return t.push(o({key:"masterFrontMm"},"mm",1.5),o({key:"masterRearMm"},"mm",1.5),o({key:"pedalRatio"},"-",.5),o({key:"pistonDiaMm",circuit:"front"},"mm",2),o({key:"pistonDiaMm",circuit:"rear"},"mm",2),o({key:"effRadiusMm",circuit:"front"},"mm",10),o({key:"effRadiusMm",circuit:"rear"},"mm",10)),r.valve!=="none"&&t.push(o({key:"valveKneeBar"},"bar",5)),r.valve==="proportioning"&&t.push(o({key:"valveSlope"},"-",.1)),t}var YF=e=>!!e&&typeof e=="object"&&"value"in e&&"label"in e;function WF(e){let t={...e};for(let r of Object.keys(t)){let n=t[r];YF(n)&&(t[r]={...n})}return t}function MV(e){let t=[];for(let r of Xk(e))for(let n of r.rows){let o=Math.abs(n.value);t.push({id:`param.${n.key}`,group:r.title,label:n.label,unit:n.unit,defaultSpan:o>0?o*.2:1,read:a=>{let s=a.params[n.key];return YF(s)?s.value:NaN},write:(a,s)=>{let i=WF(a.params);return $u(i,n.label,s),{...a,params:i}}})}return t}function jF(e){let t={};for(let s of["front","rear"]){if(!Ve(e.vehicle,s).measured)continue;let c="this axle is described by measured curves, so its linkage is not solved";for(let l of HF)for(let{key:u}of l.keys)for(let m of qt)t[`hp.${s}.${u}.${m}`]={why:c};for(let l of["uca","lca"])for(let u of An)t[`arm.${s}.${l}.${u}`]={why:c};for(let l of vo)t[`rocker.${s}.${l}`]={why:c};for(let l of["heave.outer","heave.anchor","roll.outer","roll.inner"]){let[u,m]=l.split(".");for(let f of qt)t[`${u}.${s}.${m}.${f}`]={why:c}}t[`cfg.${s}.springRate`]={why:"the measured curve set carries its own spring rate"}}let r=["rockerPivotA","rockerPivotB","rockerToPushrod","rockerToDamper"];for(let s of["front","rear"]){if(Ve(e.vehicle,s).config.actuation!=="direct")continue;let i="this axle is direct-acting \u2014 there is no bell-crank";for(let c of r)for(let l of qt)t[`hp.${s}.${c}.${l}`]={why:i};for(let c of vo)t[`rocker.${s}.${c}`]={why:i}}for(let s of["front","rear"]){let i=Ve(e.vehicle,s);if(i.measured||i.config.actuation!=="decoupled")continue;let c="this axle is decoupled \u2014 the corner damper is out of circuit";for(let l of["rockerToDamper","damperChassis"])for(let u of qt)t[`hp.${s}.${l}.${u}`]={why:c,useInstead:`heave.${s}.outer.${u}`};t[`cfg.${s}.springRate`]={why:"a decoupled axle has no corner spring \u2014 its elements hold it up",useInstead:`heave.${s}.rate`}}for(let s of["front","rear"]){let i=Ve(e.vehicle,s),c=e.params[Rp[s]]?.linkage;if(i.measured||!c||c.attach!=="rocker"||c.mount?.kind==="chassis")continue;let l=i.hardpoints,u=[0,1,2].map(f=>l.rockerPivotB[f]-l.rockerPivotA[f]),m=Math.hypot(u[0],u[1],u[2]);if(m>0)for(let f=0;f<3;f++)Math.abs(u[f]/m)<1-1e-12||(t[`heave.${s}.outer.${qt[f]}`]={why:`the rocker shaft runs along ${qt[f]} \u2014 this only slides the eye along it`})}for(let s of["front","rear"]){let i=Ve(e.vehicle,s);if(i.measured||i.config.layout!=="mcpherson")continue;let c="this axle is a McPherson strut \u2014 there is no upper arm";for(let l of["ucaFront","ucaRear","uprightUpper"])for(let u of qt)t[`hp.${s}.${l}.${u}`]={why:c,useInstead:`hp.${s}.damperChassis.${u}`};for(let l of An)t[`arm.${s}.uca.${l}`]={why:c};for(let l of["link.ucaFront","link.ucaRear","bush.ucaFront","bush.ucaRear"])t[`kc.${s}.${l}`]={why:c}}for(let s of["front","rear"]){let i=Ve(e.vehicle,s);if(i.measured)continue;for(let l of["uca","lca"]){if(l==="uca"&&i.config.layout==="mcpherson")continue;let u=X0(i.hardpoints,l);if(u)for(let m of An)t[`arm.${s}.${l}.${m}`]={why:u,useInstead:`hp.${s}.${Xt[l].fore}.z`}}let c=Qa(i.hardpoints);if(c&&i.config.actuation!=="direct")for(let l of vo)t[`rocker.${s}.${l}`]={why:c,useInstead:`hp.${s}.${ko.fore}.z`}}let n=[["arbFrontDesign","param.arb_front","the front anti-roll bar design in Vehicle Dynamics","front","roll"],["arbRearDesign","param.arb_rear","the rear anti-roll bar design in Vehicle Dynamics","rear","roll"],["heaveFrontDesign","param.heave_spring_front","the front third-spring design","front","heave"],["heaveRearDesign","param.heave_spring_rear","the rear third-spring design","rear","heave"]];for(let[s,i,c,l,u]of n){let m=e.params[s];if(!m?.design||m.design.kind==="none")continue;let f=m.design.kind==="direct"?`${u}.${l}.wheelRate`:`${u}.${l}.rate`;t[i]={why:`computed from ${c}`,useInstead:f}}let o=e.params.aeroModelId||e.params.aeroModel?gb:yb;for(let[s,i]of Object.entries(o))t[`param.${s}`]={why:i};if(e.params.batteryModelId||e.params.batteryModel)for(let[s,i]of Object.entries(Ou))t[`param.${s}`]={why:i};for(let[s,i]of Object.entries(Vu(e.params)))t[`param.${s}`]={why:i};let a=tu(e.params);return a==="hydraulic"?t["param.brake_balance"]={why:"set by the balance bar and the brake hardware",useInstead:"brakeSetup.barFront"}:a==="tyre"&&(t["param.brake_balance"]={why:"tyre-limited brakes split as the grip does"}),t}function UF(e){let t={...AV,...jF(e)};for(let[n,o]of Object.entries(t))o.useInstead&&t[o.useInstead]&&(t[n]={why:o.why});let r=n=>{let o=t[n.id];return o?{...n,supersededBy:o}:n};return[...sV(e),...lV(e),...pV(e),...fV(e),...xV(),...RV(e),...kV(e),...vV(e),...bV(e),...MV(e.params)].map(r)}var SV={spring_front:"cfg.front.springRate",spring_rear:"cfg.rear.springRate"},AV=Object.fromEntries(Object.entries(bb).map(([e,t])=>[`param.${e}`,{why:t,useInstead:SV[e]}])),ct=e=>e.scope?`${e.scope} \xB7 ${e.label}`:e.label;function Ht(e){let t={};for(let n of UF(e))t[n.id]=n;let r=(n,o)=>{if(typeof o!="string")return;let a=xF(n,o);return a&&(n[o]=a),a};return new Proxy(t,{get:(n,o,a)=>typeof o=="string"&&!Object.hasOwn(n,o)?r(n,o)??Reflect.get(n,o,a):Reflect.get(n,o,a),has:(n,o)=>Reflect.has(n,o)||!!r(n,o)})}var ry=e=>e.step!==void 0&&Number.isFinite(e.step)&&e.step>0?e.step:0,ny=e=>ry(e)>0||(e.values?.length??0)>0,oy=e=>e.some(ny),XF=e=>1e-9*Math.max(1,Math.abs(e.lo),Math.abs(e.hi));function qF(e,t){if(!Number.isFinite(t))return t;if(e.values?.length){let s=e.values[0];for(let i of e.values)Math.abs(i-t)<Math.abs(s-t)&&(s=i);return s}let r=ry(e);if(!r||!Number.isFinite(e.start))return t;let n=XF(e),o=Math.round((t-e.start)/r),a=s=>e.start+s*r;return a(o)>e.hi+n&&a(o-1)>=e.lo-n?a(o-1):a(o)<e.lo-n&&a(o+1)<=e.hi+n?a(o+1):a(o)}var QF=(e,t)=>t.map((r,n)=>e[n]&&ny(e[n])?qF(e[n],r):r);function ay(e,t=1e3){if(e.values?.length)return e.values.length;let r=ry(e);if(!r||!Number.isFinite(e.start))return 1/0;let n=XF(e),o=Math.ceil((e.lo-n-e.start)/r),a=Math.floor((e.hi+n-e.start)/r);return Math.max(0,Math.min(t,a-o+1))}function sy(e,t,r){let n=QF(e.variables,t),o=n.every((a,s)=>a===t[s]);return{x:n,score:o?r:Fr(e,n)}}function ly(e,t){if(!e.variables.some(JF))return e;let r=e.variables.filter(o=>o.follows&&!o.fixed).map(o=>({id:o.id,follows:o.follows})),n=e.variables.filter(o=>!o.fixed&&!o.follows).map(o=>{if(ew(o))return{...o,lo:Math.min(...o.values),hi:Math.max(...o.values)};if(!o.around)return o;let{around:a,fixed:s,...i}=o,c=t(o.id);return Number.isFinite(c)?{...i,lo:c-a.minus,hi:c+a.plus}:i});return r.length?{...e,variables:n,followers:r}:{...e,variables:n}}var JF=e=>!!(e.fixed||e.around||e.follows)||ew(e),ew=e=>!!e.values?.length&&(e.lo!==Math.min(...e.values)||e.hi!==Math.max(...e.values));function Dt(e,t){if(!t.variables.some(JF))return t;let r=Ht(e);return ly(t,n=>{let o=r[n];if(!o)return NaN;try{return o.read(e)}catch{return NaN}})}function Zt(e){return[...e.objectives,...e.constraints,...e.watches??[]]}var Mp=e=>(e.metrics??Ur()).byId;function uy(e,t){t=Dt(e,t);let r=Ht(e),n=[];for(let o of t.variables){let a=r[o.id];a&&n.push({id:a.id,name:ct(a),unit:a.unit,lo:o.lo,hi:o.hi,start:a.read(e),...o.step!==void 0?{step:o.step}:{},...o.values?{values:o.values}:{}})}return n}function Sp(e,t,r){t=Dt(e,t);let n=Ht(e),o=e;return t.variables.forEach((a,s)=>{let i=n[a.id];i&&Number.isFinite(r[s])&&(o=i.write(o,r[s]))}),dy(e,o,t.followers,n)}function my(e,t,r={}){let n=t.states??[],o=n.some(c=>c.follows);if(!o&&!t.envelopeFollows)return t;let a=Sn(e,{density:t.density,envelope:t.envelope,states:n,operating:t.operating,lap:t.lap,assemble:r.assemble,simParams:r.simParams,projectTrack:r.projectTrack,libraryTrack:r.libraryTrack,numerics:r.numerics}),s=n;if(o&&r.simParams)try{let c=a.ggv();c&&(s=t0(n,c,CV(r)))}catch{s=n}let i=t.envelope;if(t.envelopeFollows&&s.length){let c=s.map(h=>a.poseAt(h)).filter(h=>h!==null),l=Mp(r),u=py(t,l),m=Zt(t).map(h=>({r:h,m:l[h.metricId]})).filter(({m:h})=>h&&h.id.startsWith("kin.")&&h.reads!=="state"&&(h.scope==="car"||u.includes(h.scope))),f=h=>{let b=Sn(e,{density:t.density,envelope:h,assemble:r.assemble,numerics:r.numerics});return m.every(({r:g,m:y})=>Number.isFinite(Lt(b,y,g.at)))},p=c.length===s.length?wV(e,n0(c,u),u):null,d=p&&m.length?FV(p,f):p;d&&!o0(d,t.envelope)&&(i=d)}return s===n&&i===t.envelope?t:{...t,states:s,envelope:i}}var kp=3;function FV(e,t){let r=(c,l)=>t({...e,travelMin:c,travelMax:l}),n=e.travelMin-kp,o=e.travelMax+kp;if(r(n,o))return e;let a=(c,l,u)=>{for(;Math.abs(l-c)>1;){let m=Math.round((c+l)/2);u(m)?c=m:l=m}return c};if(r(n,1))o=a(1,o,c=>r(n,c));else if(r(-1,1))n=a(-1,n,c=>r(c,1)),o=a(1,o,c=>r(n,c));else return e;let s=Math.min(-1,Math.max(e.travelMin,n+kp)),i=Math.max(1,Math.min(e.travelMax,o-kp));return s===e.travelMin&&i===e.travelMax?e:{...e,travelMin:s,travelMax:i}}function py(e,t){let r=new Set;for(let n of Zt(e)){let o=t[n.metricId];if(!(!o||!o.id.startsWith("kin.")||o.reads==="state")){if(o.scope==="car")return["front","rear"];r.add(o.scope)}}return r.size?["front","rear"].filter(n=>r.has(n)):["front","rear"]}function wV(e,t,r){if(!t)return null;let n=za(e.vehicle,e.params),{travelMin:o,travelMax:a}=t;for(let s of r.map(i=>n[i]))try{let i=Ke(s,{travelMin:o,travelMax:a,steps:xc.travelSteps});if(i.covered)continue;let c=i.samples.filter(l=>l.converged).map(l=>l.travel);if(!c.length)continue;o=Math.max(o,Math.min(-1,Math.ceil(Math.min(...c))+1)),a=Math.min(a,Math.max(1,Math.floor(Math.max(...c))-1))}catch{continue}return o===t.travelMin&&a===t.travelMax?t:{...t,travelMin:o,travelMax:a}}function CV(e){let t=e.projectTrack?.();if(!t)return null;try{return e0(it(t.asset,t.numerics))}catch{return null}}function dy(e,t,r,n){if(!r?.length)return t;let o=t;for(let a of r){let s=n[a.id],i=n[a.follows];if(!s||!i)continue;let c=i.read(t)-i.read(e);Number.isFinite(c)&&c!==0&&(o=s.write(o,s.read(e)+c))}return o}function Dc(e,t){if(!Number.isFinite(t))return NaN;if(e.op==="max")return t-e.limit;if(e.op==="min")return e.limit-t;let r=e.limit2??e.limit;return Math.max(e.limit-t,t-r)}var tw=(e,t="")=>t&&t!=="-"?`${e} ${t}`:`${e}`;function rw(e,t,r){let n=t??Xa[e.metricId],o=(n?et(n):e.metricId)+Ec(e.at,n,r),a=s=>tw(s,n?.unit);return e.op==="max"?`${o} \u2264 ${a(e.limit)}`:e.op==="min"?`${o} \u2265 ${a(e.limit)}`:`${o} between ${e.limit} and ${a(e.limit2??e.limit)}`}function Ec(e,t,r){if(!e&&t?.reads!=="state")return"";e??={};let n=[];if(t?.reads==="state")if(e.stateId===Wr)n.push(B0(t));else{let o=e.stateId===void 0?r?.states?.[0]:r?.states?.find(a=>a.id===e.stateId);o&&n.push(o.name)}if(e.speed!==void 0&&O0(t)&&n.push(`${(e.speed*3.6).toFixed(0)} km/h`),e.ayG!==void 0&&V0(t)&&n.push(`${e.ayG.toFixed(2)} g`),e.courseId===Mc&&t?.reads==="course")n.push(N0(t));else if(e.courseId&&t?.reads==="course"){let o=r?.lap.courses.find(a=>a.id===e.courseId);o&&n.push(b0(o))}return n.length?` @ ${n.join(", ")}`:""}function nw(e,t,r){let n=r/t.scale;return e.goal==="min"?e.weight*n:e.goal==="max"?-e.weight*n:e.weight*Math.max(0,Math.abs(r-(e.target??0))-Math.max(0,e.tolerance??0))/t.scale}var ow=5e-4;function aw(e,t){return e.cost!=="lap"&&e.cost!=="session"?0:Number.isFinite(t)?ow*Math.abs(t):0}function Ap(e,t,r={}){t=Dt(e,t);let n=uy(e,t),o=Ht(e),a=Mp(r),s=t.constraints.map(m=>({spec:m,metric:a[m.metricId]})).filter(m=>!!m.metric),i=s.filter(m=>m.metric.cost==="geometry"),c=s.filter(m=>m.metric.cost!=="geometry"),l=t.objectives.map(m=>({spec:m,metric:a[m.metricId]})).filter(m=>!!m.metric),u=(m,f)=>{let p=0,d=[];for(let{spec:h,metric:b}of m){let g=Lt(f,b,h.at);if(!Number.isFinite(g))return{ok:!1,violation:f.failure?.violation??400,reason:f.failure?.reason??`${et(b)} could not be computed`};let y=Dc(h,g);y>0&&(p+=y/b.scale,d.push(`${rw(h,b,t)} (${tw(g.toFixed(3),b.unit)})`))}return d.length===0?Ks:{ok:!1,violation:p,reason:d.join("; ")}};return{name:"study",variables:n,build:m=>{let f=e;return t.variables.forEach((p,d)=>{let h=o[p.id];h&&(f=h.write(f,m[d]))}),f=dy(e,f,t.followers,o),{car:f,ev:Sn(f,{density:t.density,envelope:t.envelope,states:t.states,operating:t.operating,lap:t.lap,assemble:r.assemble,simParams:r.simParams,projectTrack:r.projectTrack,libraryTrack:r.libraryTrack,sessionParams:r.sessionParams,session:r.session,numerics:r.numerics})}},feasible:({ev:m})=>{let f=u(i,m);if(!f.ok)return f;for(let{spec:p,metric:d}of c)Lt(m,d,p.at);for(let{spec:p,metric:d}of l)Lt(m,d,p.at);return m.failure?{ok:!1,violation:m.failure.violation,reason:m.failure.reason}:u(c,m)},terms:({ev:m})=>l.map(({spec:f,metric:p})=>{let d=Lt(m,p,f.at);return{name:et(p)+Ec(f.at,p,t),raw:d,unit:p.unit,weight:f.weight,contribution:nw(f,p,d),resolution:Math.abs(f.weight)*aw(p,d)/p.scale}})}}function iy(e){let t=/^arm\.(front|rear)\.(uca|lca)\./.exec(e);if(t)return`${t[1]}.${t[2]}`;let r=/^rocker\.(front|rear)\./.exec(e);if(r)return`${r[1]}.rocker`;let n=/^hp\.(front|rear)\.(ucaFront|ucaRear|lcaFront|lcaRear|rockerPivotA|rockerPivotB)\./.exec(e);return n?n[2].startsWith("rocker")?`${n[1]}.rocker`:`${n[1]}.${n[2].startsWith("uca")?"uca":"lca"}`:null}function sw(e,t){if(e.variables.some(o=>o.id===t))return!0;let r=kc(t);if(!r||!lp.includes(r.axis))return!1;if(e.variables.some(o=>gr(o.id)?.point===r.point))return!0;let n=iy(t);return!!n&&e.variables.some(o=>/^(arm|rocker)\./.test(o.id)&&iy(o.id)===n)}function TV(e,t){let r=e.followers??[],n=new Map(r.map(i=>[i.id,i.follows])),o=i=>{let c=t[i],l=kc(i);return c&&l&&lp.includes(l.axis)?{name:ct({...c,label:c.label.replace(/ [xyz]$/,"")}),axis:l.axis}:{name:c?ct(c):`\u201C${i}\u201D`}},a=new Map,s=(i,c,l)=>{let u=a.get(i);u||a.set(i,u={text:l,axes:[]}),c&&u.axes.push(c)};for(let i of r){let c=t[i.id],l=t[i.follows],u=o(i.id),m=o(i.follows),f=p=>p&&p!=="x, y, z"?` in ${p}`:"";if(!c){s(`missing:${i.id}`,void 0,()=>`\u201C${i.id}\u201D is not a variable this car has.`);continue}if(c.supersededBy&&s(`superseded:${u.name}`,u.axis,p=>`${u.name}${f(p)} cannot be moved: ${c.supersededBy.why}.`),!l)s(`no-lead:${u.name}:${i.follows}`,u.axis,p=>`${u.name}${f(p)} moves with \u201C${i.follows}\u201D, which is not a variable this car has.`);else if(i.follows===i.id)s(`self:${u.name}`,u.axis,p=>`${u.name}${f(p)} cannot move with itself.`);else if(l.unit!==c.unit)s(`unit:${u.name}:${m.name}`,u.axis,p=>`${u.name}${f(p)} moves with ${m.name}, which is in ${l.unit} where it is in ${c.unit}. Link it to one in the same unit.`);else if(n.has(i.follows)){let p=o(n.get(i.follows));s(`chain:${u.name}:${m.name}`,u.axis,d=>`${u.name}${f(d)} moves with ${m.name}, which itself moves with ${p.name}. Link it to ${p.name}.`)}else sw(e,i.follows)||s(`still:${u.name}:${m.name}`,u.axis,p=>`${u.name}${f(p)} moves with ${m.name}, which the study does not move${f(p)}. Free that one, or give this its own bound.`)}return[...a.values()].map(i=>i.text(i.axes.join(", ")))}function fy(e,t,r={}){let n=t.variables.length>0&&t.variables.every(y=>y.fixed||y.follows),o=t.variables.some(y=>y.follows&&!y.fixed);t=Dt(e,t);let a=Ht(e),s=[],i=Mp(r),c=Zt(t).map(y=>y.metricId),l=c.some(y=>y.startsWith("dyn.")),u=c.some(y=>y.startsWith("lap."));if(c.some(y=>y.startsWith("kin."))){let y=t.envelope;y.travelMin<0&&y.travelMax>0||s.push("The travel the linkage is read over must reach both ways from the design ride: droop below zero, bump above."),(!(y.rollMaxDeg>0)||!(y.rollAtLimitDeg>=0))&&s.push("The roll the linkage is read over must be above zero.")}let m=Zt(t).filter(y=>i[y.metricId]?.reads==="state");if(m.length){let y=t.states??[];if(!y.length)s.push("This study reads targets at a state and has none. Take the car\u2019s five under Conditions.");else{let R=new Set([...y.map(k=>k.id),Wr]);for(let k of m){let v=i[k.metricId];if(k.at?.stateId&&!R.has(k.at.stateId))s.push(`${et(v)} names a state this study no longer has. Point it at one of the states under Conditions.`);else if(k.at?.stateId===Wr&&!v.acrossStates)s.push(`${et(v)} is read at one state at a time, not over every state.`);else if(v.appliesAt){let x=k.at?.stateId&&k.at.stateId!==Wr?y.find(F=>F.id===k.at.stateId):void 0,M=x?H0(v,x):null;M?s.push(`${et(v)} ${M}. Point it at a state that does.`):!x&&!up(v,y)&&s.push(`${et(v)} has no state to be read at: ${v.appliesAt(y[0])} in every state of this study.`)}}}r.assemble||s.push("This study reads targets at a state, and nothing here can assemble the car to find its pose.")}for(let y of t.states??[])(!(y.speedKmh>=0)||!Number.isFinite(y.ayG)||!Number.isFinite(y.axG))&&s.push(`The state \u201C${y.name}\u201D needs a speed of zero or more and finite accelerations.`),y.weight>0||s.push(`The state \u201C${y.name}\u201D needs a weight above zero.`);if(l&&!r.assemble&&s.push("This study reads whole-car metrics, and nothing here can assemble the car to read them from."),u&&!r.simParams&&s.push("This study reads lap metrics, and nothing here can prepare the car for a lap."),u&&!t.lap.courses.length&&s.push("This study reads lap metrics and has no course to drive. Add one under \u201CWhat the car drives\u201D."),u&&t.lap.courses.some(y=>y.course.kind==="project")&&!r.projectTrack?.()&&s.push("This study laps the project\u2019s track, and the project has none. Pick a manoeuvre, or load a track."),u)for(let y of t.lap.courses)y.course.kind==="track"&&!r.libraryTrack?.(y.course.trackId)&&s.push(`This study drives ${y.course.name}, which is not in the project\u2019s tracks, or has not loaded yet.`);let f=new Set([...t.lap.courses.map(y=>y.id),Mc]);for(let y of Zt(t))if(y.at?.courseId&&!f.has(y.at.courseId)){let R=i[y.metricId];s.push(`${R?et(R):y.metricId} names a course this study no longer has. Point it at one of the courses below.`)}u&&t.lap.ggvMode==="fast"&&t.variables.some(R=>/arb_|spring|heave_|front_mass_diss|cg_height|^hp\./.test(R.id.replace("param.","")))&&s.push("The fast grip envelope is a point mass: no load transfer, no trim. It cannot see bars, springs, roll centres or where the mass sits, and this study moves at least one of those."),n?s.push(o?"Every variable is fixed or moves with another \u2014 there is nothing to search.":"Every variable is fixed \u2014 there is nothing to search."):t.variables.length===0&&s.push("No variables selected \u2014 there is nothing to search."),t.objectives.length===0&&s.push("No objective selected. Constraints alone say which designs are legal, not which is better.");for(let y of t.variables){let R=a[y.id];if(!R){s.push(`\u201C${y.id}\u201D is not a variable this car has.`);continue}if(y.values&&y.values.length<2?s.push(`${ct(R)}: list two values or more, or fix it where it is.`):y.hi>y.lo?y.step!==void 0&&ay({...y,start:R.read(e)})<2&&s.push(`${ct(R)}: a step of ${y.step} ${R.unit} leaves no other place to land in its box. Make the step finer or the box wider, or fix it.`):s.push(`${ct(R)}: the upper bound must be above the lower one (${y.lo} to ${y.hi}).`),R.supersededBy){let v=R.supersededBy.useInstead?a[R.supersededBy.useInstead]:void 0,x=v?ct(v):void 0;s.push(`${ct(R)} cannot be searched: ${R.supersededBy.why}.`+(x?` Use ${x} instead.`:""))}let k=R.read(e);Number.isFinite(k)&&(k<y.lo||k>y.hi)&&s.push(`${ct(R)} starts at ${k.toFixed(1)} ${R.unit}, outside its own bounds.`)}let p=t.followers??[],d=new Map;for(let y of[...t.variables.map(R=>R.id),...p.map(R=>R.id)]){let R=iy(y);if(!R)continue;let k=d.get(R);k||d.set(R,k={arms:[],coords:[]}),(/^(arm|rocker)\./.test(y)?k.arms:k.coords).push(y)}for(let[y,R]of d){if(R.arms.length===0||R.coords.length===0)continue;let k=x=>a[x]?ct(a[x]):x,v=y.endsWith("rocker")?"rocker":`${y.endsWith("uca")?"upper":"lower"} arm`;s.push(`${y.startsWith("front")?"The front":"The rear"} ${v} is being moved two ways at once \u2014 as an axis (${R.arms.map(k).join(", ")}) and as pivot coordinates (${R.coords.map(k).join(", ")}). They describe the same ${v}, so whichever is applied second overwrites the other. Keep one.`)}let h=new Map,b=new Set(p.map(y=>y.id));for(let y of[...t.variables.map(R=>R.id),...b]){let R=kc(y);if(!R)continue;let k=gr(y),v=b.has(y)?"with":k?`${k.shape.kind}:${y.slice(y.lastIndexOf(".")+1).replace(/[uv]$/,"")}`:"axes",x=h.get(R.point);x||h.set(R.point,x=new Set),x.add(v)}for(let[y,R]of h){if(R.size<2||R.size===2&&R.has("axes")&&R.has("with"))continue;let k=[...R].map(w=>w.split(":")[0]),v=w=>k.filter(C=>C===w).length,x=[v("axes")?"in its axes":"",v("line")===1?"along a line":v("line")>1?"along two lines":"",v("plane")===1?"in a plane":v("plane")>1?"in two planes":"",v("with")?"with another point":""].filter(Boolean),M=a[`${y}.x`],F=M?ct({...M,label:M.label.replace(/ x$/,"")}):y;s.push(`${F} is moved more than one way at once \u2014 ${x.join(" and ")}. Each write moves it off the other's, so keep one.`)}s.push(...TV(t,a));for(let y of t.constraints){let R=i[y.metricId];if(!R){s.push(`\u201C${y.metricId}\u201D is not a metric.`);continue}y.op==="band"&&!((y.limit2??y.limit)>y.limit)&&s.push(`${et(R)}: the band's upper limit must be above its lower one.`)}l&&!(t.operating.speed>0)&&s.push("Whole-car metrics need a speed to be read at; a yaw-moment diagram at rest is degenerate.");for(let y of Zt(t))if(y.at?.speed!==void 0&&!(y.at.speed>0)){let R=i[y.metricId];s.push(`${R?et(R):y.metricId} is asked for at rest, where a yaw-moment diagram is degenerate.`)}for(let y of t.watches??[])i[y.metricId]||s.push(`\u201C${y.metricId}\u201D is not a metric.`);let g=new Set;for(let y of Zt(t)){let R=i[y.metricId],k=R?.unavailable?.(e);!R||!k||g.has(R.id)||(g.add(R.id),s.push(`${et(R)} cannot be read on this car: ${k}.`))}for(let y of t.objectives)i[y.metricId]?y.weight>0?y.goal==="target"&&!Number.isFinite(y.target)?s.push(`${et(i[y.metricId])}: \u201Chit a value\u201D needs a value.`):y.goal==="target"&&y.tolerance!==void 0&&!(y.tolerance>=0)&&s.push(`${et(i[y.metricId])}: the tolerance must be zero or more.`):s.push(`${et(i[y.metricId])}: weight must be positive.`):s.push(`\u201C${y.metricId}\u201D is not a metric.`);return s}var iw=.1,cw=2e3,cy=3;function hy(e,t,r={},n=cw){t=Dt(e,t);let o=Ap(e,t,r),a=Mp(r),s=Ht(e),i=o.variables.map(S=>S.start),c=S=>{let A=o.build(S);return o.feasible(A).ok&&o.terms(A),A},l=c(i),u=o.feasible(l),m=[...t.objectives,...t.constraints],f=(S,A=m)=>{let P={};for(let L of A){let D=a[L.metricId];D&&(P[`${L.metricId}@${Ro(L.at)}`]=Lt(S.ev,D,L.at))}return P},p=S=>m.map(A=>S[`${A.metricId}@${Ro(A.at)}`]).map(A=>Number.isFinite(A)?A.toFixed(9):"x").join("|"),d=f(l,Zt(t)),h=p(d),b=[],g=[],y={},R=[],k=0;t.variables.forEach((S,A)=>{let P=s[S.id];if(!P)return;if(R.length>=cy&&k>n){g.push(P);return}let L=[...i];L[A]=i[A]+(S.hi-i[A])*.25||S.hi;let D=performance.now(),E=c(L),V=performance.now()-D;k+=V,R.push(V);let N=f(E);y[P.id]=N,p(N)===h&&b.push(P)});let v=t.variables[0],x=v?t.variables.indexOf(v):-1;for(let S=0;v&&R.length>0&&R.length<cy;S++){let A=[...i];A[x]=i[x]+(v.hi-i[x])*(.4+.15*S)||v.hi;let P=performance.now();c(A),R.push(performance.now()-P)}let M=[...R].sort((S,A)=>S-A),F=M.length?M[M.length>>1]:0,w=[],C=Zt(t).map(S=>S.metricId);if(C.some(S=>S.startsWith("dyn.trim")||S==="dyn.ymdMaxAy")){let S=l.ev.ymdLimit();S?.onGridEdge&&w.push("The yaw-moment diagram peaks on the edge of its swept grid, so the trim readings are where the sweep stopped rather than where the car does. Widen the \u03B2/\u03B4 envelope before trusting them."),!S&&l.ev.dynAvailable&&w.push("The yaw-moment diagram found no trim point, so anything read off the limit is unavailable.")}if(C.some(S=>S==="dyn.steeringTorque"||S==="dyn.steeringTorqueGradient")){let S=l.ev.tyre()?.model,A=S?sn(S):null;A==="assumed"?w.push("This tyre carries no explicit Mz coefficient block. Its steering-aligning contribution uses Magic Formula defaults, so optimise the curve only as a qualitative placeholder until Mz is imported or fitted."):A==="none"&&w.push("This tyre model has no aligning-moment curve. Steering metrics contain contact-patch force and jacking, but not the pneumatic-trail signal that normally warns the driver at the tyre limit.")}let T=["lap.minStabil","lap.understeerFrac"];if(C.some(S=>T.includes(S))){let A=l.ev.lapReserve()?.beyondFrac;if(A!==void 0&&Number.isFinite(A)){let P=(A*100).toFixed(0);A>=iw?w.push(`Over ${P} % of this course, some wheel is asked for more longitudinal force than its own tyre ellipse allows \u2014 the speed profile and the per-wheel reconstruction disagree that far. A reserve read there is the two models disagreeing rather than the car having nothing left, and a search pointed at one will optimise the disagreement. It concentrates in high-speed braking, so a shorter straight into the first corner is the usual cure.`):A>0&&w.push(`${P} % of this course is beyond the per-wheel tyre ellipse, which is the usual level of disagreement between the speed profile and the reconstruction. Reserves are readable; treat small differences between designs as smaller than they look.`)}}return w.push(...K0(l.ev,Zt(t).map(S=>({m:a[S.metricId],at:S.at})).filter(S=>!!S.m))),{msPerEval:F,values:d,samples:R.length,times:R,dead:b,moves:y,unprobed:g,warnings:w,beyondFrac:C.some(S=>T.includes(S))?l.ev.lapReserve()?.beyondFrac:void 0,startFeasible:u.ok,startReason:u.reason}}var LV=[{kind:"title",label:"Title",what:"The name, what it changes against the Reference, the version and the date",on:"both",make:()=>({kind:"title"})},{kind:"picture",label:"Picture",what:"The car in plan, to scale",on:"each",make:()=>({kind:"picture",half:!0})},{kind:"keyFigures",label:"Key figures",what:"Large numbers picked from the sheet, or formulas",on:"each",make:()=>({kind:"keyFigures",rows:DV.slice(0,4),half:!0})},{kind:"spec",label:"Setup",what:"The Setup by group, or rows picked one by one",on:"each",make:()=>({kind:"spec",rows:"essential"})},{kind:"parts",label:"Parts",what:"Each part by name",on:"each",make:()=>({kind:"parts"})},{kind:"characteristics",label:"Characteristics",what:"What follows from the Setup, at the layout\u2019s operating point",on:"each",make:()=>({kind:"characteristics",groups:[]})},{kind:"results",label:"Results",what:"The events, times, energy and points",on:"each",make:()=>({kind:"results"})},{kind:"chart",label:"Chart",what:"Speed round a lap, the cornering limit or the torque curve",on:"both",make:()=>({kind:"chart",chart:"grip",others:!0,half:!0})},{kind:"changes",label:"Changes since",what:"What was changed since the version compared against",on:"each",make:()=>({kind:"changes"})},{kind:"checks",label:"Checks",what:"The car\u2019s errors and warnings",on:"each",make:()=>({kind:"checks"})},{kind:"notes",label:"Notes",what:"Free text, on every page or one car\u2019s",on:"both",make:()=>({kind:"notes",text:"",cars:{}})},{kind:"comparison",label:"Comparison table",what:"The rows the cars differ in, side by side",on:"all",make:()=>({kind:"comparison"})}];var DV=["setup:m","characteristics:peak_power","characteristics:power_to_weight","characteristics:cla","characteristics:cda","characteristics:pack_energy","characteristics:maxAy","characteristics:top_speed"];var Iie=new Set(LV.map(e=>e.kind));var lw={travel:{name:"Wheel travel",unit:"mm",axis:"Wheel travel (mm, + bump)",from:-25,to:25,step:1,reach:150},roll:{name:"Body roll",unit:"\xB0",axis:"Body roll (\xB0, + right side down)",from:-3,to:3,step:.25,reach:12},steer:{name:"Rack",unit:"mm",axis:"Rack (mm, + right)",from:-30,to:30,step:1,reach:80},pitch:{name:"Body pitch",unit:"\xB0",axis:"Body pitch (\xB0, + nose down)",from:-2,to:2,step:.25,reach:8}};var by=["FL","FR","RL","RR"],kt=(e,t,r)=>({input:e,from:r?r[0]:lw[e].from,to:r?r[1]:lw[e].to,n:t}),Vie=[{id:"sides",name:"Inside and outside",cards:[{id:"camber-roll",form:"curves",title:"Camber to the road through roll",sweep:kt("roll",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"toe-rack",form:"curves",title:"Wheel angle against the rack",sweep:kt("steer",25),wheels:["FL","FR"],y:["toe"]},{id:"camber-rack",form:"curves",title:"Camber to the road through the steer",sweep:kt("steer",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"load-roll",form:"curves",title:"Wheel loads through roll",sweep:kt("roll",25),wheels:by,y:["wheelLoad"]},{id:"travel-roll",form:"curves",title:"Wheel travel through roll",sweep:kt("roll",25),wheels:by,y:["travel"]},{id:"toe-roll",form:"curves",title:"Roll steer, all four",sweep:kt("roll",25),wheels:by,y:["toe"]}]},{id:"maps",name:"Travel and steer together",cards:[{id:"camber-map",form:"surface",title:"Camber over travel and rack",sweep:kt("travel",17),second:kt("steer",13),wheels:["FL"],y:["camber"]},{id:"bump-steer-map",form:"map",title:"Bump steer over travel and rack",sweep:kt("travel",17),second:kt("steer",13),wheels:["FL"],y:["bumpSteer"]},{id:"bump-steer-family",form:"curves",title:"Bump steer through travel, at five rack positions",sweep:kt("travel",25),second:kt("steer",5,[-20,20]),wheels:["FL"],y:["bumpSteer"]},{id:"scrub-map",form:"surface",title:"Scrub radius over travel and rack",sweep:kt("travel",17),second:kt("steer",13),wheels:["FL"],y:["scrubRadius"]}]}];function gy(e){let t=Number(e);return Number.isFinite(t)?Math.min(Jf,Math.max(Zf,t)):At}var mw=6e4;var Dce=[{within:60*6e4,every:mw},{within:1440*6e4,every:60*6e4},{within:720*60*6e4,every:1440*6e4},{within:1/0,every:10080*6e4}];var zV=new Set(["color","visible","source","origin"]),Hce=["id",...zV];var fw=.18/1.18,hw={induction:{kind:"natural"}},bw=e=>e.breathing??hw;function Fp(e){switch(e?.kind){case"sae-j1349":return Ji(99e3,25);case"measured":return Ji(e.hPa*100,e.tempC);default:return Ji(101325,20)}}var WV=Fp(void 0);function gw(e,t){let r=Fp(e.rated),n=e.induction;if(n.kind==="boosted"){let o=n.boostKPa*1e3;return Math.min(n.maxPressureRatio*t.p,o)/Math.min(n.maxPressureRatio*r.p,o)*(t.pDry/t.p)/(r.pDry/r.p)}return t.pDry/r.pDry*Math.sqrt(r.T/t.T)}function yw(e,t){let r=e.induction;if(r.kind==="table"){let o=s=>$e(r.densityAltitudeM,r.powerPct,s),a=o(Fp(e.rated).densityAltitudeM);return a>0?Math.max(0,o(t.densityAltitudeM)/a):0}let n=e.frictionShare??fw;return Math.max(0,(gw(e,t)-n)/(1-n))}var dw=new WeakMap;function xy(e,t){let r=e.asRated??e,n=`${t.p}|${t.pDry}|${t.T}`,o=dw.get(r);o||dw.set(r,o=new Map);let a=o.get(n);if(a)return a;let s=yw(bw(r),t),i={...r,torque:r.torque.map(c=>c*s),asRated:r};return o.set(n,i),i}function qV(e){return JSON.parse(Ry(vy(e,"public/laptime/index.json"),"utf8")).tracks}var QV=async e=>{let t=await fetch(e.url);if(!t.ok)throw new Error(`The track could not be read from ${Vm(e)} (${t.status}).`);return new Uint8Array(await t.arrayBuffer())};function xw(e,t=new Map,r=QV){let n=qV(e);return async o=>{let a=o.kind==="catalogue"?`catalogue:${o.address}`:o.name,s=t.get(a);if(s)return structuredClone(s);let i;if(o.kind==="catalogue"&&o.link){if(!ic(o.address))throw new Error(`"${o.address}" is not a catalogue address`);if(!sc(o.link))throw new Error("This track is linked to a source this version does not read from.");i=await Bg(await r(o.link),o.link,o.address)}else if(o.kind==="catalogue"){if(!ic(o.address))throw new Error(`"${o.address}" is not a catalogue address`);let c=JSON.parse(Ry(vy(e,"public/catalogue",Gg(o.address)),"utf8"));i=await Hg(c,o.address)}else{let c=n.find(l=>l.name===o.name)?.file;if(!c)throw new Error(`"${o.name}" is not in the bundled catalogue`);i=JSON.parse(Ry(vy(e,"public/laptime",c),"utf8"))}return t.set(a,i),structuredClone(i)}}var ZV=9.81;function Rw(e,t=e.tireModel,r=e.tireModelRear){if(!t)return e;let n=e.m.value*ZV/4,o=Ma(e,t,r),a=Pe(o.front).rollingRadius(n),s=o.rear===o.front?a:Pe(o.rear).rollingRadius(n),i=JV(e,a,s);if(!(i>0))return e;let c={...e.r_dyn,value:i};return{...e,r_dyn:c,readouts:{...e.readouts,r_dyn:"the fitted tyre\u2019s rolling radius at the static load"}}}function JV(e,t,r){switch(e.motorPlacement??"rear"){case"front":return t;case"awd":return t>0&&r>0?.5*(t+r):0;default:return r}}var e5=1e-6;function vw(e,t,r){let n=e.cgReference;if(!n||!e.cg_height)return e;let o=Gk(e,t,r);if(o===void 0||Math.abs(o-n.standingRadius)<e5)return e;let a=n.typed??e.cg_height.value;return{...e,cg_height:{...e.cg_height,value:ka(e.cg_height.value,n.standingRadius,o)},cgReference:{...n,standingRadius:o,typed:a}}}function kw(e,t,r){let n=e.rcRoad,o=e.rc_front,a=e.rc_rear;if(!n||!o||!a)return e;let s=Eu(e,t,r),i=$r(o.value,n.gainFront,n.radiusFront,s.front),c=$r(a.value,n.gainRear,n.radiusRear,s.rear);return i===o.value&&c===a.value?e:{...e,rc_front:{...o,value:i},rc_rear:{...a,value:c},rcRoad:{...n,radiusFront:s.front??n.radiusFront,radiusRear:s.rear??n.radiusRear}}}var Mw=e=>({brakeFade:e.brakeFade,airTempC:e.airTempC,diffYaw:e.diffYaw,...ec(e.air)?{air:e.air}:{}});var So=(e,t)=>t?e.find(r=>r.id===t)?.model:void 0;function Ao(e){return{tire:t=>So(e.tires,t),motor:t=>So(e.motors,t),aero:t=>So(e.aeros,t),battery:t=>So(e.batteries,t),brake:t=>So(e.brakes??[],t),damper:t=>So(e.dampers??[],t),suspensionOf:t=>za(ky(e,t),t)}}function ky(e,t){let r=So(e.suspensions,t.suspensionId);if(r)return r;let n=e.suspensions.find(o=>o.id===e.activeSuspensionId)??e.suspensions[0];if(!n)throw new Error("this project holds no suspension, so no car can be resolved");return n.model}function Fo(e,t,r){let n={front:t.tire(e.tireModelId),rear:t.tire(e.tireModelIdRear)};return My(Ik(t.suspensionOf(e),e,n),t,r)}function t5(e){return ec(e.air)?ZS(e.air,e.airTempC??At):void 0}var r5="the air the session states, at its venue";function n5(e,t){return t?{...e,rho:{...e.rho,value:t.rho},readouts:{...e.readouts,rho:r5}}:e}function o5(e,t,r){if(!r)return{rho:e.rho,motorModel:t,readouts:e.readouts};let{rho:n,readouts:o}=n5(e,r);return{rho:n,motorModel:t&&ft(t)?xy(t,r):t,air:r,readouts:o}}function My(e,t,r){let n=t.tire(e.tireModelId),o=t.tire(e.tireModelIdRear),a=kw(vw(Rw(Yk(Kk(Jk(e,t.aero(e.aeroModelId)),t.battery(e.batteryModelId)),t.damper(e.damperModelId),t.damper(e.damperModelIdRear)??t.damper(e.damperModelId)),n,o),n,o),n,o),{readouts:s,...i}=o5(a,t.motor(e.motorModelId),t5(r));return{...a,...i,...s?{readouts:s}:{},tireModel:n,...o?{tireModelRear:o}:{},aeroModel:t.aero(e.aeroModelId),batteryModel:t.battery(e.batteryModelId),brakeModel:t.brake(e.brakeModelId),damperModel:t.damper(e.damperModelId),...fi(e,t.damper),ggvMode:r.ggvMode,quasiTransient:r.quasiTransient??!1,motorThermal:r.motorThermal??!1,brakeFade:r.brakeFade??!1,...r.airTempC!==void 0?{airTempC:r.airTempC}:{},...r.diffYaw?{diffYaw:!0}:{},airSettled:!0}}var c5=e=>e!==!1,l5=(e,t,r)=>r&&t>0?(e%t+t)%t:Math.min(Math.max(e,0),t);function u5(e,t,r){let n=e.points.filter(o=>Number.isFinite(o.at)&&Number.isFinite(o.z)).map(o=>({...o,at:l5(o.at,t,r)})).sort((o,a)=>o.at-a.at);return n.filter((o,a)=>a===0||o.at-n[a-1].at>1e-9)}function m5(e,t,r){let n=u5(e,t,r),o=n.length;if(o===0)return[];let a=p=>p<o-1?n[p+1].at-n[p].at:r?n[0].at+t-n[p].at:1/0,s=p=>p<o-1?(n[p+1].z-n[p].z)/a(p):r&&o>1?(n[0].z-n[p].z)/a(p):0,i=n.map(p=>Math.max(0,Number.isFinite(p.curve)?p.curve:0)/2),c=(p,d,h)=>i[p]+i[d]>h?h*i[p]/(i[p]+i[d]):i[p],l=p=>p<o-1||r?c(p,p<o-1?p+1:0,a(p)):Math.max(0,t-n[p].at),u=p=>p>0?c(p,p-1,a(p-1)):r?c(p,o-1,a(o-1)):n[p].at,m=p=>p>0?s(p-1):r&&o>1?s(o-1):n[p].at<=1e-9?s(p):0,f=p=>!r&&p===o-1&&o>1&&n[p].at>=t-1e-9?s(p-1):s(p);return n.map((p,d)=>{let h=l(d),b=u(d),g=Math.min(i[d],h,b),y=!r&&g<i[d]&&(d===o-1&&g===h||d===0&&g===b);return{at:p.at,z:p.z,gIn:m(d),gOut:f(d),half:g,asked:i[d],atEnd:y}})}function p5(e,t,r,n){let o=t-e.at;return n&&r>0?o-r*Math.round(o/r):o}function d5(e,t,r,n){for(let s of e){let i=p5(s,t,r,n);if(s.half>0&&Math.abs(i)<s.half){let c=i+s.half;return s.z-s.gIn*s.half+s.gIn*c+(s.gOut-s.gIn)/(4*s.half)*c*c}}let o=e[e.length-1],a=n?t-o.at+(t<o.at?r:0):t-o.at;for(let s of e)s.at<=t&&(o=s,a=t-s.at);return!n&&t<e[0].at?e[0].z:o.z+o.gOut*a}function Sw(e,t,r,n){let o=c5(n),a=m5(e,r,o);return a.length?t.map(s=>d5(a,s,r,o)):t.map(()=>0)}function Ic(e,t){if(!t?.points.length)return e;let r=dc(e),{zSmoothing:n,...o}=e;return{...o,z:Sw(t,r,p0(e),e.closed)}}var wp={widthLeft:1.5,widthRight:1.5,bank:0,mu:1};function Aw(e){return e.kind==="bundled"?{kind:"bundled",name:e.name}:e.kind==="catalogue"?{kind:"catalogue",id:e.id,address:e.address,...e.link?{link:e.link}:{}}:null}async function _c(e,t){let r=Aw(e.source);return Fw(e,r?await t(r):void 0)}function Fw(e,t){let{source:r}=e;if(r.kind==="segments"){let{segments:i,closed:c,spacing:l}=r,{asset:u}=hc(i,{name:e.name,closed:c,spacing:l,base:wp});return Ic(u,r.profile)}let n=r.sections??[];if(r.kind==="inline")return Ic(Wm(r.asset,n,wp),r.profile);if(!t)throw new Error(`Track "${e.name}" has to be loaded before it can be resolved.`);let{widthLeft:o,widthRight:a,closed:s}=r;return Ic(Wm({...t,...o!==void 0?{widthLeft:o}:{},...a!==void 0?{widthRight:a}:{},...s!==void 0?{closed:s}:{}},n,wp),r.profile)}var yme=1/500;var xme=5*Math.PI/180;var Cme=1/3;var g5=[4,2,1,.5,.25,.125];function ww(e,t,r={}){let n=[...r.steps??g5].sort((g,y)=>y-g),o=st(r.numerics),a=r.tolPct??.5,s=Ft(e),i=e.ggvMode??"twoTrack",c=pr(s,!1,i),l={...o,dsTarget:n[0]??o.dsTarget},u=n.length?ao(s,c,[it(t,l)],l,i):void 0,m=xn(s,c.rows),f=n.map((g,y)=>{let R={...o,dsTarget:g},k=Date.now(),v=it(t,R),x=Rt(c,v,R,{...u?{load:u}:{},...m?{shifts:m}:{}});return r.onStep?.(y+1,n.length),{dsTarget:g,npts:v.npts,lapTime:x.laptime,ms:Date.now()-k}}),p=f[f.length-1]?.lapTime??NaN,d=f.map(g=>{let y=g.lapTime-p;return{...g,delta:y,deltaPct:p?100*y/p:NaN}}),h=d.filter(g=>Math.abs(g.deltaPct)<=a),b=h.length?Math.max(...h.map(g=>g.dsTarget)):null;return{points:d,reference:p,recommended:b,tolPct:a}}function Za(e,t={}){let r=e.settings,n=t.ggvMode??r.ggvMode,o=(t.quasiTransient??r.quasiTransient)&&n!=="fast",a=e.tracks.find(s=>s.id===e.activeTrackId)??e.tracks[0];return{ggvMode:n,quasiTransient:o,motorThermal:t.motorThermal??r.motorThermal,brakeFade:t.brakeFade??r.brakeFade,airTempC:gy(t.airTempC??r.airTempC),...ec(Tm(t.air??r.air))?{air:Tm(t.air??r.air)}:{},diffYaw:t.diffYaw??r.diffYaw,racingLine:t.racingLine??r.useRacingLine,standingStart:t.standingStart??(a?a.standingStart===!0:r.standingStart),lapCounts:t.lapCounts??r.lapCounts,numerics:st(r.numerics)}}async function Cp(e,t){let r=e.tracks.find(n=>n.id===e.activeTrackId)??e.tracks[0];if(!r)throw new Error("this project holds no track \u2014 add one with track_select before running a lap event");return{entry:r,asset:await _c(r,t)}}function R5(e,t){let r=structuredClone(e);for(let[n,o]of Object.entries(t))if(!$u(r,n,o))throw new Error(`no parameter is labelled "${n}" on this car \u2014 read vehicle_get for the labels it has`);return r}var Sy=(e,t)=>{let r=e?.name;return typeof r=="string"&&r?r:t};function v5(e,t){let r={};for(let n of kn){let o=e[n.doc]??[];for(let i of n.slots.slice(1)){let c=t[i.ref],l=typeof c=="string"?o.find(u=>u.id===c):void 0;l&&(r[i.key]={id:l.id,name:Sy(l.model,l.id)})}let a=t[n.ref],s=typeof a=="string"?o.find(i=>i.id===a):void 0;if(s){r[n.doc]={id:s.id,name:Sy(s.model,s.id)};continue}if(n.doc==="suspensions"){let i=o.find(c=>c.id===e.activeSuspensionId)??o[0];r[n.doc]=i?{id:i.id,name:Sy(i.model,i.id),byFallback:!0}:null;continue}r[n.doc]=null}return r}function k5(e){return Object.values(e.events).map(t=>({id:t.id,label:t.label,kind:t.kind,time:t.time,lapTime:t.lapTime,distance:t.distance,laps:t.laps,...t.energy?{energyConsumedKwh:t.energy.consumed,energyRemaining:t.energy.remainingFraction}:{},...t.lapsOverridden?{lapsOverridden:t.lapsOverridden}:{},...t.incomplete?{incomplete:t.incomplete}:{},...t.energyTarget?{energyTarget:t.energyTarget}:{}}))}function Cw(e){let t=new Map;for(let{name:r,events:n}of e)for(let o of n){let a=t.get(o.label);a||t.set(o.label,a={event:o.label,finished:[],stopped:[]}),(o.incomplete?a.stopped:a.finished).push(r)}return[...t.values()].filter(r=>r.stopped.length>0)}var Tw=e=>e.length<2?e[0]??"":`${e.slice(0,-1).join(", ")} and ${e[e.length-1]}`;async function Tp(e,t,r={}){let n=Za(e,r.settings),{entry:o,asset:a}=await Cp(e,t),s=Ao(e),i=r.vehicleIds?.length?r.vehicleIds.map(d=>{let h=e.vehicles.find(b=>b.id===d);if(!h)throw new Error(`this project holds no vehicle "${d}"`);return h}):e.vehicles.filter(d=>d.visible);if(!i.length)throw new Error("no vehicle is visible in this project \u2014 name some in vehicleIds");let c=i.map(d=>{let h=r.overrides?.[d.id]?R5(d.params,r.overrides[d.id]):d.params;return Fo(structuredClone(h),s,n)}),l=ji(uo(e.meta.rulesetId,e.rulesets)),u=Zi(c,a,n.numerics,l,{racingLine:n.racingLine,standingStart:n.standingStart,lapCounts:n.lapCounts}),m={};i.forEach((d,h)=>{m[d.id]=u[h]});let{scores:f,field:p}=bg(l,m);return{rulesetId:e.meta.rulesetId,track:o.name,settings:{ggvMode:n.ggvMode,quasiTransient:n.quasiTransient,motorThermal:n.motorThermal,brakeFade:n.brakeFade,airTempC:n.airTempC,...n.air?{air:n.air}:{},diffYaw:n.diffYaw,racingLine:n.racingLine,standingStart:n.standingStart},fleetScored:f!==null,vehicles:i.map((d,h)=>({id:d.id,name:u[h].name||String(d.params.name??d.id),events:k5(u[h]),metrics:gg(l,u[h],p?.[d.id]),fitted:v5(e,d.params),...f?.[d.id]?{score:{total:f[d.id].total,parts:{...f[d.id].parts}}}:{}})),raw:{results:m,scores:f,field:p}}}async function Pw(e,t,r){let n=e.vehicles.find(i=>i.id===r.vehicleId);if(!n)throw new Error(`this project holds no vehicle "${r.vehicleId}"`);let o=Za(e),{asset:a}=await Cp(e,t),s=Fo(structuredClone(n.params),Ao(e),o);return ww(s,a,{...r.steps?{steps:r.steps}:{},numerics:o.numerics,...r.tolPct!==void 0?{tolPct:r.tolPct}:{},...r.onStep?{onStep:r.onStep}:{}})}var M5=(e,t)=>e[t]??[],S5=(e,t,r)=>r<=1?[e]:Array.from({length:r},(n,o)=>e+(t-e)*o/(r-1));function Pp(e){return e.kind==="param"?S5(e.start,e.end,Math.max(1,Math.round(e.steps))):e.kind==="part"?[...e.partIds]:[...e.values]}var Lw=e=>e.kind==="param"?e.label:e.kind==="part"?`${e.part} model`:e.setting;function A5(e,t){let r=e.vehicles.find(i=>i.id===t.vehicleId);if(!r)throw new Error(`this project holds no vehicle "${t.vehicleId}"`);if(!t.axes.length)throw new Error("a sweep needs at least one axis");let n=Fo(structuredClone(r.params),Ao(e),Za(e)),o=Qk(n,{geometry:!0}),a=Bu(n);for(let i of t.axes){if(i.kind==="param"){let c=a.find(u=>u.label===i.label);if(!c)throw new Error(`no parameter is labelled "${i.label}" on this car \u2014 read vehicle_get for the labels it has`);let l=o[c.key];if(l)throw new Error(`"${i.label}" is a readout on this car, not an input: ${l}. Sweeping it would report exactly zero. Sweep what produces it instead.`)}if(i.kind==="part"){let c=kn.find(l=>l.doc===i.part);if(!c)throw new Error(`"${i.part}" is not a library \u2014 it is one of ${kn.map(l=>l.doc).join(", ")}`);for(let l of i.partIds)if(!M5(e,c.doc).some(u=>u.id===l))throw new Error(`the ${c.label} library holds no "${l}"`)}}let s=t.axes.reduce((i,c)=>i*Pp(c).length,1);if(s>Am)throw new Error(`that grid is ${s} runs, over the ${Am} cap \u2014 a run is a whole session. Drop an axis or use fewer steps.`)}var F5=e=>e.map(t=>String(typeof t=="number"?Number(t.toPrecision(4)):t)).join(" \xD7 ");function w5(e,t){let r=[...new Set(e.flatMap(o=>(o.didNotFinish??[]).map(a=>a.label)))],n=e.map(o=>({name:F5(o.at),events:r.map(a=>({label:a,incomplete:o.didNotFinish?.find(s=>s.label===a)}))}));return Cw(n).map(({event:o,finished:a,stopped:s})=>{let i=`${s.length} of ${e.length} points did not finish ${o}`;if(!a.length)return`${i}: every time there is a part-distance${t?" and scores zero":""}, so compare laps before time.`;let c=s.length>6?`${s.slice(0,6).join(", ")}, \u2026`:Tw(s);return t?`${i}: ${c}. Their time there is a part-distance and scores zero, so read them as stopped, not slow \u2014 a points ranking favours the points that finished over faster ones that stopped.`:`${i}: ${c}. Their time there is a part-distance, so read them as stopped, not slow.`})}function C5(e){let t=[[]];for(let r of e){let n=Pp(r),o=[];for(let a of n)for(let s of t)o.push([...s,a]);t=o}return t}async function Dw(e,t,r,n){A5(e,r);let o=C5(r.axes),a=[],s=!1;for(let[u,m]of o.entries()){let f=structuredClone(e),p=f.vehicles.find(k=>k.id===r.vehicleId),d={...r.settings},h={};r.axes.forEach((k,v)=>{let x=m[v];if(k.kind==="param")h[k.label]=x;else if(k.kind==="part"){let M=kn.find(F=>F.doc===k.part);p.params[M.ref]=x}else d[k.setting]=x});let b=r.fleet?f.vehicles.filter(k=>k.visible||k.id===r.vehicleId).map(k=>k.id):[r.vehicleId],g=await Tp(f,t,{vehicleIds:b,settings:d,...Object.keys(h).length?{overrides:{[r.vehicleId]:h}}:{}});s=g.fleetScored;let y=g.vehicles.find(k=>k.id===r.vehicleId),R=y.events.flatMap(k=>k.incomplete?[{label:k.label,...k.incomplete}]:[]);a.push({at:m,metrics:y.metrics,...R.length?{didNotFinish:R}:{}}),n?.(u+1,o.length)}let i=Object.keys(a[0]?.metrics??{}),c=[];r.axes.forEach((u,m)=>{if(Pp(u).length<2)return;i.some(p=>{if(new Set(a.map(b=>`${b.at[m]}`)).size<2)return!1;let h=a.map(b=>b.metrics[p]).filter(Number.isFinite);return Math.max(...h)-Math.min(...h)>1e-9})||c.push(Lw(u))});let l=[];return s&&!r.fleet&&l.push("Points here were scored with this car alone, so it takes the maximum in every event and the points axis is flat by construction. Re-run with fleet: true to price a change in points."),l.push(...w5(a,s)),c.length&&l.push(`Nothing moved along ${c.join(", ")}. Exactly zero is a wiring question before it is a finding: check that a library part is not superseding the value, and that the switch it needs is on.`),{axes:r.axes.map(u=>({kind:u.kind,label:Lw(u),values:Pp(u)})),runs:a,metricKeys:i,fleetScored:s,flat:c,caveats:l}}var Ide=Math.PI/180;function Ay(e){if(!e.chassis)return e;let{chassis:t,...r}=e;return r}var Kge=180/Math.PI;var k3={id:"racecar",label:"Race car",description:"Suspension kinematics, tyres, powertrain and quasi-steady-state lap simulation for a four-wheeled race car.",tools:["laptime","garage","kinematics","track","studies","dynamics","tires","aero","powertrain","battery","brakes","dampers","forces","calibration"],defaultRulesetId:lo,templateIds:["fs-ev-comparison","fs-endurance-energy","fs-ev-single","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor","formula-1","touring-car","street-car","cup-car","stock-car","hill-climb","race-truck","suspension","direct-coilover","pushrod","pullrod","third-spring","mcpherson-strut","tyre-study"],collections:[{id:"start",label:"Start here",description:"What the model answers, then cars to build from.",templateIds:["fs-ev-comparison","fs-endurance-energy","suspension","tyre-study","fs-ev-single","formula-1","touring-car"]},{id:"formula-student",label:"Formula Student",description:"Electric and combustion cars on the five Formula Student events, by drive layout.",templateIds:["fs-ev-comparison","fs-endurance-energy","suspension","tyre-study","fs-ev-single","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor"]},{id:"circuits",label:"Circuit racing",description:"Single-seaters, GT, cup and road cars and a race truck on real circuits, with their heights.",templateIds:["formula-1","touring-car","street-car","cup-car","race-truck"]},{id:"ovals-hill-climbs",label:"Ovals and hill climbs",description:"A banked oval, and an open course climbed from rest in thin air.",templateIds:["stock-car","hill-climb"]},{id:"kinematics",label:"Suspension and kinematics",description:"Each suspension architecture: its hardpoints, its roll centres and what it does on track.",templateIds:["suspension","direct-coilover","pushrod","pullrod","third-spring","mcpherson-strut"]},{id:"tyres",label:"Tyres",description:"Grip curves, and what a tyre is worth on track.",templateIds:["tyre-study"]},{id:"powertrain",label:"Energy and powertrain",description:"What a pack lasts, and how each drive layout puts its power down.",templateIds:["fs-endurance-energy","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor"]}]};var hye=k3.id;var Nc=.02;function Yw(e){let t=Math.max(Nc,Math.abs(e.heaveMotionRatio)),r=Math.max(Nc,Math.abs(e.rollMotionRatio)),o=2*(e.cornerWheelRate+e.heaveWheelRate)/(t*t),a=2*(e.cornerDamper+(e.heaveWheelDamping??0))/(t*t),s=(e.cornerDamper+(e.rollWheelDamping??0))/(r*r);return{heaveRate:o,heaveDamper:a,rollWheelRate:e.cornerWheelRate+e.arbWheelRate,rollDamper:s}}var S3=(e,t)=>({od:t,id:Math.min(e.id,t-.5)}),A3=(e,t)=>e/(2*t*t);function zw(e,t){switch(e.kind){case"ubar":case"blade":case"torsionTube":return{...e,section:S3(e.section,t)};default:return e}}function Ww(e,t,r){let n=Math.max(Nc,Math.abs(r));if(e?.kind==="coil"){let l=A3(t,n),u=e.rate;if(typeof u=="number")return{...e,rate:l};let m=Vr(u,0);if(!(m>0))return{...e,rate:l};let f=l/m;return{...e,rate:{...u,y:u.y.map(p=>p*f)}}}let o=t/(n*n),a=e&&(e.kind==="ubar"||e.kind==="blade"||e.kind==="torsionTube")?e:{kind:"torsionTube",section:{od:20,id:16},length:400,leverArm:60,G:8e4},s=l=>yi(zw(a,l),0).rateAtLink,i=4,c=60;if(s(c)<o)return{kind:"direct",wheelRate:t};for(let l=0;l<80&&c-i>1e-9;l++){let u=.5*(i+c);s(u)<o?i=u:c=u}return zw(a,c)}function jw(e,t,r,n){let o=e?.design,a=Ww(t?.design,r.rollWheelRate,n);return{heave:{design:{kind:"coil",rate:r.heaveRate,motionRatio:o?.kind==="coil"?o.motionRatio:1,gap:0,bothWays:!0},linkage:e?.linkage,damper:r.heaveDamper},arb:{design:a,linkage:t?.linkage,damper:a.kind==="coil"?r.rollDamper/2:r.rollDamper}}}var F3=Math.PI/180,Lp=1e-6;function w3(e){return!(ve(e.rockerPivotA,e.rockerPivotB)<Lp||ve(e.rockerToPushrod,e.rockerPivotA)<Lp||ve(e.rockerToDamper,e.rockerPivotA)<Lp||ve(e.rockerToDamper,e.damperChassis)<Lp)}function Qw(e){if(!w3(e.hardpoints))return!1;let t={...e,config:{...e.config,actuation:"rocker"}};try{let r=tt(t);for(let n of[-20,-1,0,1,20]){let o=ye(r,n,0);if(!o.ok||!Number.isFinite(o.state.metrics.damperLength))return!1}return!0}catch{return!1}}function Zw(e){if(e.config.actuation!=="direct"||Qw(e))return;let{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}=T3(e);return{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}}var Uw=40;function Dp(e,t={}){let r=e.hardpoints,n=r.pushrodOuter,o=r.damperChassis,a=ve(n,o),s=ee(n,U(H(o,n),C3)),i=t.armRod??Math.max(25,.15*a),c=t.armDamper??i,l=[s[0]-Uw,s[1],s[2]],u=[s[0]+Uw,s[1],s[2]],m=q(H(u,l)),f=H(n,s),p=q(H(f,U(m,Xw(f,m)))),d=It(p,m,(t.armAngleDeg??60)*F3),h=ee(s,U(d,i)),b=H(o,s),g=q(H(b,U(m,Xw(b,m)))),y=U(q(ae(m,g)),t.damperSide??1),R=ee(s,U(y,c));return{...r,rockerPivotA:l,rockerPivotB:u,rockerToPushrod:h,rockerToDamper:R}}var C3=.72,Xw=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2];function qw(e){let t=Ke(e,{travelMin:-5,travelMax:5,steps:3}),[r,,n]=t.samples;if(!r||!n)return 0;let o=n.travel-r.travel;return o!==0?Math.abs((n.metrics.damperLength-r.metrics.damperLength)/o):0}function T3(e,t={}){let r=t.target??qw(e),n=t.armAngleDeg,o=Dp(e,{armAngleDeg:n});if(!(r>0))return o;let a=ve(e.hardpoints.pushrodOuter,e.hardpoints.damperChassis),s=Math.max(25,.15*a),i=(()=>{for(let p of[1,-1]){let d=Dp(e,{armRod:s,armAngleDeg:n,damperSide:p}),h={...e,config:{...e.config,actuation:"rocker"},hardpoints:d};try{let b=tt(h),g=ye(b,15,0),y=ye(b,-15,0);if(g.ok&&y.ok&&g.state.metrics.damperLength<y.state.metrics.damperLength)return p}catch{}}return 1})(),c=(p,d)=>{try{return qw({...e,config:{...e.config,actuation:"rocker"},hardpoints:Dp(e,{armRod:p,armAngleDeg:n,armDamper:d,damperSide:i})})}catch{return Number.NaN}},l=[1,.6,.35,.2,1.7,2.6].map(p=>Math.max(12,s*p)),u=s,m=s,f=1/0;for(let p of l){let d=.25*p,h=6*p,b=p;for(let y=0;y<24;y++){let R=(d+h)/2,k=c(p,R);if(!Number.isFinite(k))break;b=R,k<r?d=R:h=R}let g=Math.abs(c(p,b)-r);if(Number.isFinite(g)&&g<f&&(f=g,u=p,m=b),f<1e-4*Math.max(1,r))break}return Dp(e,{armRod:u,armAngleDeg:n,armDamper:m,damperSide:i})}var Tye=Array.from({length:19},(e,t)=>-45+5*t);var Pye=Math.PI/180;function P3(e){let t=e.hardpoints,r=q(H(t.rockerPivotB,t.rockerPivotA)),n=tn(t.rockerToDamper,t.rockerPivotA,r),o=.6*en(H(t.rockerToDamper,n)),a=ae(r,Tx),s=en(a)>1e-6?q(a):q(H(t.rockerToDamper,n));return{outer:ee(n,U(s,o)),inner:ee(n,U(s,-o)),attach:"rocker"}}var L3=(e,t)=>({...e,config:{...e.config,actuation:t}});function Cy(e,t,r,n){let o=r==="front"?e.front:e.rear,a=Cu(o),s=o.config.springRate*a*a,i=Q(t,r==="front"?"damper_front":"damper_rear")*a*a,c=r==="front"?t.arbFrontDesign:t.arbRearDesign,l=Zn(e,t)[r]??Q(t,r==="front"?"arb_front":"arb_rear"),u=va(e,t)[r]??Q(t,r==="front"?"heave_spring_front":"heave_spring_rear"),m=Zw(o),f=L3(m?{...o,hardpoints:{...o.hardpoints,...m}}:o,"decoupled"),p=r==="front"?t.heaveFrontDesign:t.heaveRearDesign,d=n?.heave??Jw(p?.linkage,w=>En(f,w).atDesign)??Ud(f,"rockerToRocker"),h=!c||c.design.kind==="none"||c.design.kind==="coil",b=h?"coil":"ubar",g=c?.linkage&&(c.design.kind==="none"||c.linkage.attach!=="rocker")?c.linkage:void 0,y=n?.roll??Jw(h?g:c?.linkage,w=>jo(f,w,{kind:b}).atDesign)??(h?P3(f):gk(f)),R=En(f,d).atDesign,k=jo(f,y,{kind:b}).atDesign,v=Pu(e,t),x=Yw({cornerWheelRate:s,cornerDamper:i,arbWheelRate:l,heaveWheelRate:u,heaveWheelDamping:r==="front"?v.heaveFront:v.heaveRear,rollWheelDamping:r==="front"?v.rollFront:v.rollRear,heaveMotionRatio:R,rollMotionRatio:k}),M=!c||c.design.kind==="none"?{design:{kind:"coil",rate:1},linkage:y}:{...c,linkage:y},F=jw({design:p?.design??{kind:"none"},linkage:d,damper:p?.damper},M,x,k);return m?{...F,crank:m}:F}function Jw(e,t){return e&&Math.abs(t(e))>=Nc?e:void 0}var Ep=[{id:"direct",name:"Direct-acting coilover",family:"GT / touring car",description:"Each lower wishbone drives a coilover straight into a chassis tower. No rod or rocker in the load path.",scope:"Both axles",tags:["Double wishbone","Coilover","Direct acting"]},{id:"pushrod",name:"Pushrod suspension",family:"Formula / prototype",description:"A rod from the lower wishbone pushes a rocker on the chassis shoulder. A 225 mm damper runs along the top at 1:1.",scope:"Both axles",tags:["Pushrod","Rocker","Inboard damper"]},{id:"pullrod",name:"Pullrod suspension",family:"Formula / low package",description:"A rod from the upper wishbone pulls a low rocker inside the side wall. A 225 mm damper runs along the floor at 1:1.",scope:"Both axles",tags:["Pullrod","Low rocker","Inboard damper"]},{id:"heave",name:"Third heave spring",family:"Formula / aero platform",description:"The pushrod car plus a front third spring worked by both rockers. It picks up after 5 mm of bump and stays out of roll.",scope:"Both axles, plus a front third spring",tags:["Pushrod","Third spring","Aero platform"]},{id:"decoupled",name:"Twin-rocker-bar decoupled modes",family:"Formula / prototype",description:"Each pushrod turns a long rocker bar. A shock between the bars takes heave, a diagonal one takes roll; no corner springs.",scope:"Both axles",tags:["Two rocker bars","Heave shock","Roll shock"]},{id:"mcpherson",name:"McPherson strut",family:"Road car",description:"A strut clamped to the upright runs up to a top mount on the tower: damper, spring seat and upper link in one. Coilover wishbones at the rear.",scope:"Front struts, rear double wishbones",tags:["McPherson","Strut","Road car"]}],Ty=()=>({arbFront:void 0,arbRear:void 0,heaveFront:void 0,heaveRear:void 0}),D3={front:{rockerPivotA:[-47,223,405],rockerPivotB:[-47,267,445],rockerToPushrod:[8,242,429],rockerToDamper:[-47,190,485],damperChassis:[-272,190,485]},rear:{rockerPivotA:[65,228,415],rockerPivotB:[65,272,455],rockerToPushrod:[10,247,439],rockerToDamper:[65,195,495],damperChassis:[290,195,495]}},E3={front:{pushrodOuter:[-3,510,359],rockerPivotA:[-20,174,181],rockerPivotB:[-20,200,139],rockerToPushrod:[18,199,167],rockerToDamper:[-20,102,108],damperChassis:[205,102,108]},rear:{pushrodOuter:[-1,516,365],rockerPivotA:[39,177,181],rockerPivotB:[39,203,139],rockerToPushrod:[1,202,167],rockerToDamper:[39,112,111],damperChassis:[-186,112,111]}},I3=()=>({outer:[0,189,486],attach:"rocker",mount:{kind:"chassis",anchor:[-225,0,486]}}),_3={rate:60,motionRatio:1},N3={front:{rockerPivotA:[-50,310,621],rockerPivotB:[-50,357,659],rockerToPushrod:[10,330,644],rockerToDamper:[-50,281,704],damperChassis:[-275,281,704]},rear:{rockerPivotA:[73,306,621],rockerPivotB:[73,352,659],rockerToPushrod:[13,326,644],rockerToDamper:[73,271,710],damperChassis:[298,271,710]}},O3=e=>e==="front"?{outer:[-2,280,705],attach:"rocker",mount:{kind:"chassis",anchor:[-227,0,705]}}:{outer:[25,270,711],attach:"rocker",mount:{kind:"chassis",anchor:[250,0,711]}},V3={kind:"coil",rate:1560,motionRatio:1,gap:0,bothWays:!0},B3=40,$3={rockerPivotA:[50,130,440],rockerPivotB:[-50,130,440],rockerToPushrod:[10,170,460],rockerToDamper:[-20,64,440],damperChassis:[-20,64,215]},eC=()=>({outer:[-50,130,480],attach:"rocker",shaftStation:-50}),tC=()=>({outer:[50,130,400],inner:[50,130,480],attach:"rocker",shaftStationOuter:50,shaftStationInner:50}),G3=e=>[e[0],e[1],e[2]];function K3(e){let t=r=>({...r,hardpoints:{...r.hardpoints,...nC($3)},config:{...r.config,actuation:"decoupled"}});return{...e,front:t(e.front),rear:t(e.rear)}}function nC(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,G3(r)]))}function oC(e,t=bo(),r=e==="pull"?E3:D3){let n=(o,a)=>({...o,hardpoints:{...o.hardpoints,...nC(r[a])},config:{...o.config,actuation:"rocker",rodType:e,...e==="pull"?{pushrodAttach:"upperArm"}:{}}});return{...t,front:n(t.front,"front"),rear:n(t.rear,"rear")}}function Ip(e,t){let r=Py(e),n=Ja(e);if(e==="heave")return{meta:r,vehicle:n,components:{...Ty(),heaveFront:{design:{...mb,..._3},linkage:I3()}}};if(e!=="decoupled")return{meta:r,vehicle:n,components:Ty()};let o=Cy(n,t,"front",{heave:eC(),roll:tC()}),a=Cy(n,t,"rear",{heave:eC(),roll:tC()});return{meta:r,vehicle:n,components:{arbFront:o.arb,arbRear:a.arb,heaveFront:o.heave,heaveRear:a.heave}}}function Ja(e){let{name:t}=Py(e);if(e==="direct")return{...rc(),name:t};if(e==="mcpherson"){let n=nc(),o=Lm();return{...n,front:{...o,config:{...o.config,loadedRadius:n.front.config.loadedRadius}},name:t}}let r=H3(oC(e==="pullrod"?"pull":"push"));return{...e==="decoupled"?K3(r):r,name:t}}var rC={front:221.7,rear:220.9};function H3(e){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:rC.front}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:rC.rear}}}}function Py(e){let t=Ep.find(r=>r.id===e);if(!t)throw new Error(`Unknown suspension template: ${e}`);return t}function _p(){let e=t=>({design:{...V3},linkage:O3(t),damper:B3});return{meta:Py("heave"),vehicle:oC("push",Sg(),N3),components:{...Ty(),heaveFront:e("front"),heaveRear:e("rear")}}}var aC=[10,25,50,100,200,300],z3=[{id:"c1",label:"Soft",scale:.7},{id:"c2",label:"Medium",scale:1},{id:"c3",label:"Firm",scale:1.4}],sC=e=>Math.round(e*100)/100;function Y3(e,t,r){let n=aC.map(o=>sC(r*o));return{id:e,label:t,speedMmS:[...aC],bumpN:n,reboundN:[...n]}}function W3(e){return{name:e.name,body:{...e.body},curves:z3.map(t=>Y3(t.id,t.label,sC(e.coefficient*t.scale)))}}function Oc(e,t){let r=(t.heave??t.car).coefficient,n=(t.roll??t.car).coefficient,o=(a,s)=>a?.damper?{...a,damper:s}:a;return{arbFront:o(e.arbFront,n),arbRear:o(e.arbRear,n),heaveFront:o(e.heaveFront,r),heaveRear:o(e.heaveRear,r)}}function yr(e,t){let r=i=>{if(!i)return;let c=e.dampers.length+1;for(;e.dampers.some(u=>u.id===`dmp${c}`);)c++;let l=`dmp${c}`;return e.dampers.push({id:l,color:lc[e.dampers.length%lc.length],model:W3(i)}),l},n=r(t.car),o=r(t.rear),a=r(t.heave),s=r(t.roll);for(let i of e.vehicles){let c=i.params;c.damperModelId=n,o&&(c.damperModelIdRear=o),a&&(c.heaveDamperModelId=a),s&&(c.rollDamperModelId=s)}}var lt=e=>`${e} (typical)`,Ly={car:{name:lt("Formula Student damper"),coefficient:2.5,body:{extended:249,stroke:55}}},Np={car:Ly.car,heave:{name:lt("Formula Student heave damper"),coefficient:3.4,body:{extended:270,stroke:47}},roll:{name:lt("Formula Student roll damper"),coefficient:3.7,body:{extended:322,stroke:100}}},Op={car:{name:lt("Formula 1 damper"),coefficient:6,body:{extended:240,stroke:40}},heave:{name:lt("Formula 1 heave damper"),coefficient:40,body:{extended:240,stroke:40}}},iC={car:{name:lt("GT damper"),coefficient:4.5,body:{extended:510,stroke:80}}},Dy={car:{name:lt("Sports car damper"),coefficient:2.4,body:{extended:515,stroke:110}}},cC={car:{name:lt("Sports car strut"),coefficient:2.4,body:{extended:310,stroke:120}},rear:Dy.car},lC={car:{name:lt("Cup car strut"),coefficient:4,body:{extended:285,stroke:75}},rear:{name:lt("Cup car rear damper"),coefficient:3.5,body:{extended:505,stroke:80}}},uC={car:{name:lt("Stock car front damper"),coefficient:7.5,body:{extended:555,stroke:110}},rear:{name:lt("Stock car rear damper"),coefficient:6.75,body:{extended:555,stroke:110}}},mC={car:{name:lt("Hill-climb front damper"),coefficient:3,body:{extended:285,stroke:65}},rear:{name:lt("Hill-climb rear damper"),coefficient:3.5,body:{extended:285,stroke:65}}},pC={car:{name:lt("Race truck front damper"),coefficient:12,body:{extended:780,stroke:160}},rear:{name:lt("Race truck rear damper"),coefficient:8.5,body:{extended:780,stroke:160}}};function ts(e){return e.vehicles=e.vehicles.slice(0,1),e.activeVehicleId=e.vehicles[0]?.id??null,e}function wn(e,t){let r=uc(e);return r.meta.rulesetId=t,r}function wo(e,t,r,n){let o=wn(e,t);return o.suspensions=[{...o.suspensions[0],model:n()}],o.vehicles=[qg(r,"v1",0)],o.activeVehicleId="v1",o}var[,j3,U3,X3,q3,Q3,Z3,J3]=Dg;function Ey(e,t){delete e.arbFrontDesign,delete e.arbRearDesign,delete e.heaveFrontDesign,delete e.heaveRearDesign,t.arbFront&&(e.arbFrontDesign=structuredClone(t.arbFront)),t.arbRear&&(e.arbRearDesign=structuredClone(t.arbRear)),t.heaveFront&&(e.heaveFrontDesign=structuredClone(t.heaveFront)),t.heaveRear&&(e.heaveRearDesign=structuredClone(t.heaveRear))}function dC(){return{...Ja("decoupled"),name:bo().name}}var eB=[{label:"Formula Student (decoupled)",vehicle:dC,components:e=>Oc(Ip("decoupled",e).components,Np)},{label:"Formula 1 (third springs)",vehicle:()=>_p().vehicle,components:()=>Oc(_p().components,Op)}],Iy={"direct-coilover":"direct",pushrod:"pushrod",pullrod:"pullrod","third-spring":"heave","mcpherson-strut":"mcpherson"},tB=[...eB.map(e=>e.vehicle),...Object.values(Iy).map(e=>()=>Ja(e))];function es(e){let t=Oc(Ip("decoupled",e.vehicles[0].params).components,Np);e.suspensions=[{...e.suspensions[0],model:dC()}];for(let r of e.vehicles)Ey(r.params,t);return yr(e,Np),e}var Co={title:"OpenStreetMap",url:"https://www.openstreetmap.org/copyright",licence:"ODbL-1.0",credit:"\xA9 OpenStreetMap contributors"},Vp={title:"USGS 3D Elevation Program, 1 m lidar terrain",url:"https://www.usgs.gov/3d-elevation-program",licence:"public-domain",credit:"U.S. Geological Survey, 3D Elevation Program"},fC={title:"Digitales Gel\xE4ndemodell DGM1 Rheinland-Pfalz",url:"https://www.geoportal.rlp.de/",licence:"dl-de-by-2.0",credit:"\xA9GeoBasis-DE / LVermGeoRP 2025, dl-de/by-2-0, www.lvermgeo.rlp.de [Daten bearbeitet]"},hC={title:"USDA National Agriculture Imagery Program (NAIP), 0.6 m aerial imagery",url:"https://imagery.nationalmap.gov/arcgis/rest/services/USGSNAIPImagery/ImageServer",licence:"public-domain",credit:"USDA Farm Service Agency, National Agriculture Imagery Program, via the USGS National Map"},rB={id:"cota",name:"Circuit of the Americas, Austin",address:"e0c6ea889d708cf15f9c",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,Vp,hC]}},nB={id:"laguna-seca",name:"Laguna Seca, Monterey",address:"185b5811b9c423ef44ef",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,Vp,hC]}},oB={id:"nordschleife",name:"Nordschleife, N\xFCrburg",address:"74c49603c7b2f15985c6",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,fC]}},aB={id:"brands-hatch",name:"Brands Hatch, Kent",address:"c4953e3c25eaba4a5b7e",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,{title:"Environment Agency LIDAR Composite DTM, 1 m",url:"https://environment.data.gov.uk/dataset/13787b9a-26a4-4775-8523-806d13af58fc",licence:"OGL-UK-3.0",credit:"\xA9 Environment Agency copyright and/or database right 2022. All rights reserved."}]}},sB={id:"bristol",name:"Bristol, Tennessee",address:"f0e23953669a414ad600",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,Vp]}},iB={id:"pikes-peak",name:"Pikes Peak, Colorado",address:"3de137fe33b5c2875036",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,Vp]},standingStart:!0},cB={source:"venue",altitudeM:3580,pressure:{kind:"standard"},humidityPct:0},lB=10,uB={id:"nurburg-sprint",name:"Sprintstrecke, N\xFCrburg",address:"1875636cdbb615aa2756",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,fC]}};function To(e,t){let{id:r,name:n,address:o,provenance:a,standingStart:s}=t,i={kind:"catalogue",id:r,address:o},c=oc(Kg({name:n,source:i}).model,structuredClone(a));return e.tracks=[{id:"tr1",name:n,source:i,provenance:c,...s?{standingStart:s}:{}}],e.activeTrackId="tr1",e.settings.standingStart=s===!0,e}function Cn(e,t,r){let n=e.vehicles[0].params,o=`m${e.motors.length+1}`;e.motors=[...e.motors,{id:o,color:Mn[e.motors.length%Mn.length],model:t}];let a=Vk({},{...n,motorModel:t});n.motorModelId=o,n.motorCount=1,a&&(n.driveline=a),n.gear_ratio&&(n.gear_ratio={...n.gear_ratio,value:r})}var mB=3.8,Bp={hubPlanetary:14.5,inboardChain:4,engineChain:3.4},pB="Hub motor, 35 kW (example)";function _y(e,t,r,n,o,a){let s=e.vehicles[0].params;s.motorModelId=t,s.motorCount=r,s.motorPlacement=n,a&&(s.motorMount=a),s.driven_wheels={...s.driven_wheels,value:n==="awd"?4:2},s.gear_ratio={...s.gear_ratio,value:o}}function bC(e){let t=e.motors.find(r=>r.id==="m1");return t.model={...t.model,name:pB},t.id}function $p(e,t,r){let n=ts(es(wn(e,r)));return n.vehicles[0].params.name=t,n}function dB(){let e=$p("Formula Student combustion car","Formula Student combustion","fs-cv");Cn(e,Og(),Bp.engineChain);let t=e.vehicles[0].params;return t.power_limit_kw&&(t.power_limit_kw={...t.power_limit_kw,value:0}),t.endurance_reserve&&(t.endurance_reserve={...t.endurance_reserve,value:0}),e}function fB(){let e=$p("Formula Student AWD car","Formula Student AWD","fs-ev");return _y(e,bC(e),4,"awd",Bp.hubPlanetary,"hub"),e}function hB(){let e=$p("Formula Student RWD hub-motor car","Formula Student RWD hub motors","fs-ev");return _y(e,bC(e),2,"rear",Bp.hubPlanetary,"hub"),e}function bB(){let e=$p("Formula Student one-motor car","Formula Student RWD one motor","fs-ev"),t=`m${e.motors.length+1}`;return e.motors=[...e.motors,{id:t,color:Mn[e.motors.length%Mn.length],model:Ng()}],_y(e,t,1,"rear",Bp.inboardChain),e.vehicles[0].params.driveline={rear:structuredClone(xt.clutch)},e}function gB(){let e=ts(es(wn("Formula Student endurance energy","fs-ev"))),t=e.vehicles[0],r=structuredClone(t);if(r.id="v2",r.color=cc[1],r.params.name=`${t.params.name} flat out`,!r.params.endurance_reserve)throw new Error("the Formula Student preset states no energy reserve");return r.params.endurance_reserve={...r.params.endurance_reserve,value:0},e.vehicles.push(r),e}function yB(){let e=_p(),t=wo("Formula 1 car","trackday",j3,()=>e.vehicle);return Ey(t.vehicles[0].params,Oc(e.components,Op)),yr(t,Op),Cn(t,Vg(),mB),To(t,rB)}function gC(e="GT car",t=rc){let r=wo(e,"trackday",U3,t);return yr(r,iC),Cn(r,pA(),r.vehicles[0].params.gear_ratio.value),To(r,nB)}function yC(e="Sports car",t=nc,r=Dy){let n=wo(e,"trackday",X3,t);return yr(n,r),Cn(n,dA(),n.vehicles[0].params.gear_ratio.value),To(n,oB)}function xB(){let e=wo("Cup car","trackday",q3,eA);return yr(e,lC),Cn(e,fA(),e.vehicles[0].params.gear_ratio.value),To(e,aB)}function RB(){let e=wo("Stock car","trackday",Q3,tA);return yr(e,uC),Cn(e,hA(),e.vehicles[0].params.gear_ratio.value),To(e,sB)}function vB(){let e=wo("Hill-climb prototype","trackday",Z3,rA);return yr(e,mC),Cn(e,bA(),e.vehicles[0].params.gear_ratio.value),e.settings.air=structuredClone(cB),e.settings.airTempC=lB,To(e,iB)}function kB(){let e=wo("Race truck","trackday",J3,nA);return yr(e,pC),Cn(e,gA(),e.vehicles[0].params.gear_ratio.value),To(e,uB)}function MB(e){let t=Ep.find(o=>o.id===e);if(e==="direct")return gC(t.name,()=>Ja(e));if(e==="mcpherson")return yC(t.name,()=>Ja(e),cC);let r=ts(wn(t.name,"trackday")),n=Ip(e,r.vehicles[0].params);return r.suspensions=[{...r.suspensions[0],model:n.vehicle}],Ey(r.vehicles[0].params,n.components),yr(r,Ly),r}function Vc(e,t,r){let n=Iy[e],o=Ep.find(a=>a.id===n);return{id:e,domain:"racecar",kind:"start",summary:t,title:o.name,blurb:`${o.description} ${r} Move a hardpoint in Kinematics and watch the motion ratio, camber and roll centre follow, then what it costs on track.`,tags:["kinematics","suspension",...o.tags.map(a=>a.toLowerCase())],openTool:"kinematics",load:()=>MB(n)}}var SB=[{id:"fs-ev-comparison",domain:"racecar",kind:"study",summary:"Four Formula Student cars scored on all five events: what mass, power and downforce buy.",title:"Formula Student \u2014 car comparison",blurb:"A generic Formula Student electric car and three what-ifs \u2014 15 % more downforce, 15 kg lighter, 15 % more power \u2014 scored side by side on the Formula Student electric events. All four run decoupled heave and roll suspension. A good first look at what each change buys.",tags:["formula student","comparison","lap sim"],openTool:"laptime",load:()=>es(wn("Formula Student comparison","fs-ev"))},{id:"fs-endurance-energy",domain:"racecar",kind:"study",summary:"The FS car flat out against its energy target: which finishes endurance, and the points.",title:"Formula Student \u2014 endurance energy",blurb:"The generic Formula Student electric car twice, scored together on the Formula Student electric events: once driven to its energy target, once flat out. The two differ in the endurance reserve and nothing else. Flat out the car laps faster and its pack runs out before the flag; on the target its speed is capped so the pack finishes with 5 % left. The endurance event shows the charge lap by lap, and the points what running dry costs.",tags:["formula student","endurance","energy","battery"],openTool:"laptime",load:gB},{id:"fs-ev-single",domain:"racecar",kind:"start",summary:"A generic Formula Student electric car on the five events, to set up as your own.",title:"Formula Student \u2014 single car",blurb:"One generic Formula Student electric car on the Formula Student electric events: 300 kg with driver, two motors, 80 kW, 10-inch tyres, decoupled heave and roll suspension. The uncluttered starting point for setting up your own car.",tags:["formula student","lap sim"],openTool:"laptime",load:()=>ts(es(wn("Formula Student car","fs-ev")))},{id:"fs-combustion",domain:"racecar",kind:"start",summary:"A restricted 600 cc four through six gears and a clutch-pack diff, on the CV events.",title:"Formula Student \u2014 combustion, LSD",blurb:"The generic Formula Student car with an engine: a restricted 600 cc four of about 64 kW through a six-speed box and a chain to a clutch-pack limited-slip diff, on the Formula Student combustion events. The same 300 kg chassis, tyres and decoupled suspension as the electric layouts, so the drive is the difference. Efficiency is scored on the work at the crankshaft until fuel is modelled. Representative of the class, not a measurement of any car.",tags:["formula student","combustion","engine","limited-slip diff","lsd","lap sim"],openTool:"laptime",load:dB},{id:"fs-ev-awd",domain:"racecar",kind:"start",summary:"All-wheel drive from a motor in each hub, held to 80 kW at the pack.",title:"Formula Student \u2014 AWD, four hub motors",blurb:"The generic Formula Student electric car with a motor in each of its four hubs: 35 kW hub motors on 14.5 : 1 planetaries, held to the rules\u2019 80 kW at the pack, each wheel\u2019s torque its own and every wheel braking back into the pack. The same 300 kg chassis, tyres, suspension and pack as the other layouts, so the drive is the difference; the hub motors\u2019 unsprung mass is not added. Representative of the class, not a measurement of any car.",tags:["formula student","awd","all-wheel drive","hub motors","outboard motors","lap sim"],openTool:"laptime",load:fB},{id:"fs-ev-rwd-hubs",domain:"racecar",kind:"start",summary:"Rear-wheel drive from a motor in each rear hub, with no diff between them.",title:"Formula Student \u2014 RWD, two hub motors",blurb:"The generic Formula Student electric car driven by a motor in each rear hub: two 35 kW hub motors on 14.5 : 1 planetaries with no differential between them, so each rear wheel\u2019s torque is set on its own. The pair cannot use all of the rules\u2019 80 kW. The same 300 kg chassis, tyres, suspension and pack as the other layouts, so the drive is the difference. Representative of the class, not a measurement of any car.",tags:["formula student","rwd","rear-wheel drive","hub motors","outboard motors","lap sim"],openTool:"laptime",load:hB},{id:"fs-ev-one-motor",domain:"racecar",kind:"start",summary:"One inboard motor chained to a clutch-pack diff on the rear axle.",title:"Formula Student \u2014 RWD, one motor, LSD",blurb:"The generic Formula Student electric car on one inboard motor: an axial-flux motor of 230 Nm on the chassis, chained at 4 : 1 to a clutch-pack limited-slip diff on the rear axle. The rules\u2019 80 kW at the pack holds it below its peak, and it brakes back into the pack through the diff. The same 300 kg chassis, tyres, suspension and pack as the other layouts, so the drive is the difference. Representative of the class, not a measurement of any car.",tags:["formula student","rwd","inboard motor","limited-slip diff","lsd","lap sim"],openTool:"laptime",load:bB},{id:"formula-1",domain:"racecar",kind:"start",summary:"A generic Formula 1 car on a flying lap of Austin.",title:"Formula 1 car",blurb:"A generic Formula 1 car of the 18-inch era at Austin: 798 kg with driver, a 735 kW power unit through eight gears and a clutch-pack diff, four and a half square metres of lift area on a 3.6 m wheelbase, pushrods with a third spring and heave damper on each axle, slicks with 1.8 of peak grip. One flying lap, no scoring. Every number is representative of the class, none is a measurement.",tags:["formula 1","lap sim","aero"],openTool:"laptime",load:yB},{id:"touring-car",domain:"racecar",kind:"start",summary:"A generic GT car on a flying lap of Laguna Seca.",title:"GT car",blurb:"A generic GT car at Laguna Seca: 1300 kg with driver, a 410 kW four-litre through six gears and a clutch-pack diff, 2.8 m\xB2 of lift area, coilovers on double wishbones, 18-inch slicks. One flying lap, no scoring. Representative of the class, not a measurement of any car.",tags:["gt","lap sim"],openTool:"laptime",load:gC},{id:"street-car",domain:"racecar",kind:"start",summary:"A generic sports car on road tyres, round the Nordschleife.",title:"Sports car",blurb:"A generic sports car on the Nordschleife: 1600 kg with driver, a 220 kW turbocharged six through a six-speed double-clutch box and an open diff, road tyres with about 1.0 of grip, soft springs and a little aerodynamic lift. One flying lap, no scoring. The car to start from when the question is a road car, and the one that shows what a race car's numbers actually buy.",tags:["sports car","road car","lap sim"],openTool:"laptime",load:yC},{id:"cup-car",domain:"racecar",kind:"start",summary:"A generic front-driven cup hatchback round Brands Hatch.",title:"Cup car",blurb:"A generic front-wheel-drive cup hatchback at Brands Hatch: 1265 kg with driver, a 250 kW two-litre turbo through six gears and a clutch-pack diff, a splitter and a wing, a McPherson strut front, 18-inch slicks. One flying lap, no scoring. Representative of the class, not a measurement of any car.",tags:["cup car","front-wheel drive","lap sim"],openTool:"laptime",load:xB},{id:"stock-car",domain:"racecar",kind:"start",summary:"A generic stock car on Bristol\u2019s half-mile, banked 25\xB0.",title:"Stock car",blurb:"A generic stock car of the American oval series at Bristol, the half-mile banked 25\xB0: 1620 kg with driver, a 500 kW 5.9-litre V8 through five gears and a clutch-pack diff, double wishbones on stiff springs, 18-inch slicks, set up the same on both sides. One flying lap, no scoring. Representative of the class, not a measurement of any car.",tags:["stock car","oval","lap sim"],openTool:"laptime",load:RB},{id:"hill-climb",domain:"racecar",kind:"start",summary:"A generic hill-climb prototype up Pikes Peak, from rest, in thin air.",title:"Hill-climb prototype",blurb:"A generic hill-climb sports prototype on Pikes Peak, 19.99 km and 1,440 m up to the summit: 650 kg with driver, a 330 kW turbocharged two-litre through six gears and a clutch-pack diff, 3 m\xB2 of lift area, pushrods, 13-inch slicks. It runs in the mountain\u2019s thin air, which costs its wings a third of their downforce. One run, no scoring. Representative of the class, not a measurement of any car.",tags:["hill climb","altitude","lap sim"],openTool:"laptime",load:vB},{id:"race-truck",domain:"racecar",kind:"start",summary:"A generic European race truck round the N\xFCrburg Sprintstrecke, held to 160 km/h.",title:"Race truck",blurb:"A generic European circuit race truck on the N\xFCrburg Grand Prix circuit\u2019s 3.6 km Sprintstrecke: a cab-over tractor at the class\u2019s 5300 kg minimum, 60 % of it on the front axle, an 880 kW 13-litre diesel through a twelve-speed box to a locked rear axle, geared to the 160 km/h the rules hold it to, 315/70 R22.5 tyres. One flying lap, no scoring. Representative of the class, not a measurement of any truck.",tags:["race truck","truck racing","lap sim"],openTool:"laptime",load:kB},{id:"suspension",domain:"racecar",kind:"study",summary:"The FS car\u2019s decoupled wishbones: move a hardpoint and watch the roll centre follow.",title:"Suspension kinematics study",blurb:"Opens on the double-wishbone editor with one Formula Student car. Move a hardpoint and watch camber, bump steer, motion ratio and roll-centre migration follow \u2014 then see what it costs on track.",tags:["kinematics","geometry"],openTool:"kinematics",load:()=>ts(es(wn("Suspension study","trackday")))},Vc("direct-coilover","The GT car\u2019s wishbones driving coilovers straight into the towers, at Laguna Seca.","On the GT car, at Laguna Seca."),Vc("pushrod","The FS car on pushrods: a rod from each lower wishbone works a rocker.","On the Formula Student car, at FSG."),Vc("pullrod","The FS car on pullrods: a rod from each upper wishbone pulls a low rocker.","On the Formula Student car, at FSG."),Vc("third-spring","The pushrod FS car plus a front third spring that picks up after 5 mm of bump.","On the Formula Student car, at FSG."),Vc("mcpherson-strut","The sports car on McPherson struts at the front and double wishbones at the rear.","On the sports car, at the Nordschleife."),{id:"tyre-study",domain:"racecar",kind:"study",summary:"The FS tyre\u2019s grip curves at three loads, beside the other classes\u2019 tyres.",title:"Tyre model study",blurb:"One Formula Student car on its Magic Formula tyre, opened on the tyre analysis, where the grip curves that drive the whole lap come from. The library beside it holds the other seven classes' tyres and the illustrative MF6.2 example to compare against.",tags:["tyres","magic formula"],openTool:"tires",load:()=>ts(es(wn("Tyre study","fs-ev")))}],xC=SB.map(e=>({...e,load:()=>Qg(e.load())}));var RC={width:320,height:200},fxe=[.6*RC.width-9,.6*RC.height-9];var vC=new WeakMap,kC=new WeakMap,Ny=e=>JSON.stringify(e,(t,r)=>r===1/0?"Infinity":r);function MC(e,t){if(!t){let a=vC.get(e);return a||(a=Ct(e),vC.set(e,a)),a}let r=kC.get(e);r||(r=new Map,kC.set(e,r));let n=Ny(t),o=r.get(n);return o||(r.size>=4&&r.clear(),o=Ct(e,t),r.set(n,o)),o}var wB=Math.PI/180,CB=e=>e>1?e/100:e;function Bc(e){let t=null;return()=>(t??={v:e()}).v}function SC(e){let t=Ke(e,{travelMin:-1,travelMax:1,steps:3}).samples[1],r=t.metrics.motionRatio??1;return{motionRatio:r,wheelRate:t.metrics.wheelRate??e.config.springRate*r*r}}var AC=new WeakMap,Oy={heave:0,pitch:0,roll:0,steer:0},FC=[0,1,2,3,4],wC=[-20,-10,0,10,20];function TC(e,t){let r=Br(e,Oy),n=["front","rear"],o=c=>{let l=Ri(c);return l?(l.left+l.right)/2:Number.NaN},a=n.map(c=>o(r[c])),s=n.map(()=>({rc:[],split:[]}));for(let c of FC){let l=c===0?null:Br(e,{...Oy,roll:c*wB});n.forEach((u,m)=>{let f=l?Ri(l[u]):null,p=f&&Number.isFinite(a[m]);s[m].rc.push(p?t[m]+(f.left+f.right)/2-a[m]:t[m]),s[m].split.push(p?(f.left-f.right)/2:0)})}let i=n.map(()=>[]);for(let c of wC){let l=c===0?null:Br(e,{...Oy,heave:-c});n.forEach((u,m)=>{let f=l&&l[u].valid&&r[u].valid;i[m].push(f?t[m]+l[u].height-r[u].height:t[m])})}return{roll:{rollDeg:FC,rcFront:s[0].rc,rcRear:s[1].rc,rcSplitFront:s[0].split,rcSplitRear:s[1].split},heave:{drop:wC,rcFront:i[0],rcRear:i[1]}}}var CC=new WeakMap;function TB(e,t,r,n){let o=CC.get(e);o||(o=new Map,CC.set(e,o));let a=`${Ny(r)}|${n[0]}|${n[1]}`,s=o.get(a);if(!s){o.size>=4&&o.clear();try{s=TC(MC(e,r),n)}catch{s=t.rigidMigration(n)}o.set(a,s)}return s}function PB(e){let t=AC.get(e);if(t)return t;let r=Ct(e),n=Br(r,{heave:0,pitch:0,roll:0,steer:0}),o=SC(e.front),a=SC(e.rear),s={wheelbase:e.config.wheelbase,trackFront:bt(e.front),trackRear:bt(e.rear),mrFront:o.motionRatio,mrRear:a.motionRatio,wheelRateFront:o.wheelRate,wheelRateRear:a.wheelRate,unsprungCgHeight:e.front.config.loadedRadius,rcHeightFront:n.front.valid?n.front.heightAboveGround:0,rcHeightRear:n.rear.valid?n.rear.heightAboveGround:0,rcGainFront:Ra(n.front),rcGainRear:Ra(n.rear),rigidMigration:i=>TC(r,i),kinFront:Bc(()=>oa(e.front)),kinRear:Bc(()=>oa(e.rear))};return AC.set(e,s),s}function PC(e,t,r,n){let o=PB(e),a=Zn(e,t),s=va(e,t),i=Lk(e,t),c=Pu(e,t),l=Dk(e,t),u=Ek(t),m=Lu(e,t),f=Qn(e.front),p=Qn(e.rear),d=qn(t.damperModel,t.damperSetup,o.mrFront,o.mrRear,t.damperModelRear??t.damperModel),h={rho:t.rho.value,area:t.A.value,cl:t.c_l.value,cw:t.c_w.value,copLongFront:1-Math.max(0,Math.min(1,Q(t,"cop_long"))),copHeight:Q(t,"cop_height"),...t.aeroModel?{model:t.aeroModel}:{},rideHeightFront:Q(t,"ride_height_front"),rideHeightRear:Q(t,"ride_height_rear")},b=9.81,g=CB(t.front_mass_diss.value),y=Ma(t,r,n),R=Pe(y.front),k=y.rear===y.front?R:Pe(y.rear),v=n??t.tireModelRear??r,x=t.m.value*b*g/2,M=t.m.value*b*(1-g)/2,F=R.corneringStiffness(x),w=k.corneringStiffness(M),C=(r?R.verticalStiffness():0)||Q(t,"tire_vertical_rate"),T=(v?k.verticalStiffness():0)||Q(t,"tire_vertical_rate"),S=ar(r)??0,A=ar(v)??0,P=Nu({freeRadius:S,staticLoad:x,tyreRate:C,surveyed:e.front.config.loadedRadius},{freeRadius:A,staticLoad:M,tyreRate:T,surveyed:e.rear.config.loadedRadius},g),L=Gt(S,x,C,e.front.config.loadedRadius),D=Gt(A,M,T,e.rear.config.loadedRadius),E=[$r(o.rcHeightFront,o.rcGainFront,e.front.config.loadedRadius,L),$r(o.rcHeightRear,o.rcGainRear,e.rear.config.loadedRadius,D)],V=Bc(()=>Ai(o.kinFront(),Q(t,"camber_front_deg"))),N=Bc(()=>Ai(o.kinRear(),Q(t,"camber_rear_deg"))),z=Bc(()=>TB(e,o,Ya(B),E)),I=ei({...t,wheelbase:{...t.wheelbase,value:o.wheelbase}}),_=Si(t),B={massTotal:t.m.value,frontMassFrac:g,steeringSystem:t.steeringSystem,tv:gu(t),cgHeight:ka(Q(t,"cg_height"),t.cgReference?.standingRadius,P),cgStandingRadius:P,wheelbase:o.wheelbase,trackFront:o.trackFront,trackRear:o.trackRear,wheelRateFront:f?0:o.wheelRateFront,wheelRateRear:p?0:o.wheelRateRear,decoupledFront:f,decoupledRear:p,...u.front?{elementLinkagesFront:u.front}:{},...u.rear?{elementLinkagesRear:u.rear}:{},...m.front.source==="part"?{cornerCoiloverFront:m.front.coilover}:{},...m.rear.source==="part"?{cornerCoiloverRear:m.rear.coilover}:{},...m.heaveFront.coilover?{heaveCoiloverFront:m.heaveFront.coilover}:{},...m.heaveRear.coilover?{heaveCoiloverRear:m.heaveRear.coilover}:{},...i.front&&!f?{heaveSeatFront:i.front}:{},...i.rear&&!p?{heaveSeatRear:i.rear}:{},...m.rollFront.coilover?{rollCoiloverFront:m.rollFront.coilover}:{},...m.rollRear.coilover?{rollCoiloverRear:m.rollRear.coilover}:{},tireRate:C,...T!==C?{tireRateRear:T}:{},tireDamping:Q(t,"tire_vertical_damping"),arbFront:a.front??Q(t,"arb_front"),arbRear:a.rear??Q(t,"arb_rear"),brakeBalanceFront:I.balanceFront,brakes:I,..._?{driveline:_}:{},heaveSpringFront:s.front??Q(t,"heave_spring_front"),heaveSpringRear:s.rear??Q(t,"heave_spring_rear"),unsprungPerCorner:Q(t,"unsprung_mass"),unsprungCgHeight:Gt(S,x,C,o.unsprungCgHeight),tyreFreeRadius:S,...A!==S?{tyreFreeRadiusRear:A}:{},rcHeightFront:E[0],rcHeightRear:E[1],corneringStiffnessFront:F,corneringStiffnessRear:w,get kinFront(){return V()},get kinRear(){return N()},damperFront:f?0:d?.front?.rate??Q(t,"damper_front")*o.mrFront*o.mrFront,damperRear:p?0:d?.rear?.rate??Q(t,"damper_rear")*o.mrRear*o.mrRear,...d?.front&&!f?{damperCurveFront:d.front.curve}:{},...d?.rear&&!p?{damperCurveRear:d.rear.curve}:{},heaveDamperFront:l.heaveFront?.rate??c.heaveFront,heaveDamperRear:l.heaveRear?.rate??c.heaveRear,rollDamperFront:l.rollFront?.rate??c.rollFront,rollDamperRear:l.rollRear?.rate??c.rollRear,...l.heaveFront?{heaveDamperCurveFront:l.heaveFront.curve}:{},...l.heaveRear?{heaveDamperCurveRear:l.heaveRear.curve}:{},...l.rollFront?{rollDamperCurveFront:l.rollFront.curve}:{},...l.rollRear?{rollDamperCurveRear:l.rollRear.curve}:{},unsprungCornerMass:Q(t,"unsprung_mass"),get rollCentreCurve(){return z().roll},get rcHeaveCurve(){return z().heave},aero:h,yawInertia:Q(t,"I_yaw"),rollInertia:Q(t,"I_roll"),pitchInertia:Q(t,"I_pitch"),get steerFront(){return Du(e.front,L)},ackermannPct:Q(t,"ackermann_pct"),toeFrontDeg:Q(t,"toe_front_deg"),toeRearDeg:Q(t,"toe_rear_deg")};return B}var DC=e=>({tire:t=>t==null?void 0:t===e.tireModelIdRear&&e.tireModelRear?e.tireModelRear:e.tireModel,motor:()=>e.motorModel,aero:()=>e.aeroModel,battery:()=>e.batteryModel,brake:()=>e.brakeModel,damper:t=>t!=null&&t===e.damperModelIdRear&&e.damperModelRear?e.damperModelRear:t!=null&&t===e.heaveDamperModelId?e.heaveDamperModel:t!=null&&t===e.rollDamperModelId?e.rollDamperModel:e.damperModel}),By={ggvMode:"twoTrack"},LC=new WeakMap;function $y(e,t=By){let r=LC.get(e.vehicle);r||LC.set(e.vehicle,r=new WeakMap);let n=r.get(e.params);n||r.set(e.params,n=new Map);let o=JSON.stringify(t),a=n.get(o);if(!a){n.size>=8&&n.clear();let s={...DC(e.params),suspensionOf:()=>e.vehicle};n.set(o,a=Fo(e.params,s,t))}return a}var EC=(e=By)=>t=>$y(t,e),IC=(e=By)=>t=>PC(t.vehicle,My(t.params,DC(t.params),e),t.params.tireModel,t.params.tireModelRear);function LB(e,t){return $y(e,t.switches)}var Gy=e=>Ur(e?.rulesets);function _C(e,t,r,n,o={},a=()=>r.standingStart){let s=$y(n,r.switches),i=(l,u)=>{let m=Sm(l,t,{racingLine:r.racingLine,params:s});return{asset:m.asset,numerics:m.numerics,standingStart:u,racingLine:r.racingLine}},c=Object.fromEntries(Object.entries(o).map(([l,u])=>[l,i(u,a(l))]));return{course:e?i(e,r.standingStart):null,numerics:t,tracks:c,switches:r.switches}}var NC=e=>[...new Set(e.lap.courses.flatMap(t=>t.course.kind==="track"?[t.course.trackId]:[]))],OC=e=>{let t=e?.session;return t?{sessionParams:r=>LB(r,t),session:()=>t}:{}},Gp=e=>({metrics:Gy(e),assemble:IC(e?.switches),simParams:EC(e?.switches),projectTrack:()=>e?.course??null,libraryTrack:t=>e?.tracks?.[t]??null,numerics:e?.numerics,...OC(e)}),DB=(e,t)=>({density:e.density,envelope:e.envelope,states:e.states,operating:e.operating,lap:e.lap,assemble:IC(t?.switches),simParams:EC(t?.switches),projectTrack:()=>t?.course??null,libraryTrack:r=>t?.tracks?.[r]??null,numerics:t?.numerics,...OC(t)}),VC="nelder-mead",BC=600,$c=[0,.15,.15];function $C(e,t,r,n=$c.length){let o=zy(t);return $c.slice(0,Math.max(1,n)).map((a,s)=>({...e,seed:s+1,startJitter:a,car:o,...r?{lap:r}:{}}))}function GC(e,t,r=.5){let n=[];return e.forEach((o,a)=>{let s=o.hi-o.lo;if(s<=0)return;let i=Math.min(r,s*.01);t[a]<=o.lo+i?n.push({id:o.id,name:o.name,unit:o.unit,at:"lo",value:t[a],moved:t[a]-o.start}):t[a]>=o.hi-i&&n.push({id:o.id,name:o.name,unit:o.unit,at:"hi",value:t[a],moved:t[a]-o.start})}),n}function KC(e,t,r,n,o=.01){let a=Gy(n).byId;return EB(e,t,r,n).filter(s=>s.excess>-o*(a[s.metricId]?.scale??1))}function EB(e,t,r,n){let o;try{o=Sn(Sp(e,t,r),DB(t,n))}catch{return[]}return IB(o,t,Gy(n))}function IB(e,t,r){let n=[];for(let o of t.constraints){let a=r.byId[o.metricId];if(!a)continue;let s=Lt(e,a,o.at);if(!Number.isFinite(s))continue;let i=`${et(a)}${Ec(o.at,a)}`;n.push({key:o.key,metricId:o.metricId,label:i,unit:a.unit==="-"?"":a.unit,value:s,excess:Dc(o,s)})}return n}var _B=.05;function NB(e,t){if(t.id.startsWith("hp.")||vp(t.id))return 1;let r=/^rocker\.(front|rear)\.(\w+)$/.exec(t.id);if(r){let a=r[1]==="front"?e.vehicle.front:e.vehicle.rear;return ey(Fn(a.hardpoints),r[2],1)}let n=/^arm\.(front|rear)\.(uca|lca)\.(\w+)$/.exec(t.id);if(!n)return null;let o=n[1]==="front"?e.vehicle.front:e.vehicle.rear;return Q0(Xr(o.hardpoints,n[2]),n[3],1)}function HC(e,t,r){let n=r.filter(f=>f.score.feasible);if(n.length<2)return null;let o=t.map(f=>NB(e,f)),a=o.every(f=>f!==null)?"mm":null,s=0,i="",c=0,l=n.reduce((f,p)=>p.score.total<f.score.total?p:f);for(let f of n)if(f!==l)for(let p=0;p<t.length;p++){let d=Math.abs(f.x[p]-l.x[p])*(o[p]??1);c+=d*d,d>s&&(s=d,i=t[p].name)}let u=n.map(f=>f.score.total),m=l.score.terms.reduce((f,p)=>f+(p.resolution??0),0);return{distance:Math.sqrt(c),worst:s,worstName:i,scoreSpread:Math.max(...u)-Math.min(...u),tolerance:Math.max(_B,m),unit:a}}var OB={steeringSystem:!0,brakeSetup:!0,driveline:!0,heaveFrontDesign:!0,heaveRearDesign:!0,arbFrontDesign:!0,arbRearDesign:!0},zC=e=>Object.hasOwn(OB,e);function Vy(e){let[t,r]=e.split("."),n=r==="front"?"Front":r==="rear"?"Rear":null;return n?t==="heave"?`heave${n}Design`:t==="roll"?`arb${n}Design`:null:null}function VB(e){let t=e.split(".")[0];return t==="hp"||t==="arm"||t==="rocker"?"hardpoint":t==="cfg"?"config":t==="kc"?"compliance":t==="param"?"param":t==="brakeModel"?"part":zC(t)||Vy(e)?"block":null}function Ky(e,t){t=Dt(e,t);let r=Ht(e);return[...t.variables,...t.followers??[]].filter(n=>r[n.id]&&!r[n.id].supersededBy&&!VB(n.id)).map(n=>ct(r[n.id]))}function YC(e,t,r){t=Dt(e,t);let n=Ht(e),o=Sp(e,t,r),a=[],s=new Set,i=new Set;for(let c of[...t.variables,...t.followers??[]]){let l=n[c.id];if(!l||l.supersededBy)continue;let u=l.read(o),[m,f,p,d]=c.id.split(".");if(m==="rocker"){let h=`${f}.rocker`;if(i.has(h))continue;i.add(h);let b=f==="front"?o.vehicle.front:o.vehicle.rear;for(let g of[ko.fore,ko.aft]){let y=b.hardpoints[g];for(let R=0;R<3;R++)a.push({kind:"hardpoint",axle:f,key:g,axis:R,value:y[R]})}}else if(m==="arm"){let h=`${f}.${p}`;if(i.has(h))continue;i.add(h);let b=f==="front"?o.vehicle.front:o.vehicle.rear,g=Xt[p];for(let y of[g.fore,g.aft]){let R=b.hardpoints[y];for(let k=0;k<3;k++)a.push({kind:"hardpoint",axle:f,key:y,axis:k,value:R[k]})}}else if(m==="hp"&&gr(c.id)){let h=`${f}.${p}`;if(i.has(h))continue;i.add(h);let b=(f==="front"?o.vehicle.front:o.vehicle.rear).hardpoints[p];for(let g=0;g<3;g++)a.push({kind:"hardpoint",axle:f,key:p,axis:g,value:b[g]})}else if(m==="hp")a.push({kind:"hardpoint",axle:f,key:p,axis:"xyz".indexOf(d),value:u});else if(m==="cfg")a.push({kind:"config",axle:f,field:p,value:u});else if(m==="kc"){if(s.has(`kc.${f}`))continue;s.add(`kc.${f}`);let h=f==="front"?o.vehicle.front:o.vehicle.rear;a.push({kind:"compliance",axle:f,value:h.compliance})}else if(m==="param")a.push({kind:"param",label:ct(l),value:u});else if(m==="brakeModel"){if(s.has(m))continue;if(s.add(m),!o.params.brakeModel)throw new Error(`optimiser: "${c.id}" left the car with no brake part to adopt`);a.push({kind:"part",key:"brakeModel",fromId:e.params.brakeModelId,value:o.params.brakeModel})}else if(zC(m)||Vy(c.id)){let h=Vy(c.id)??m;if(s.has(h))continue;s.add(h);let b=o.params[h];if(!b)throw new Error(`optimiser: "${c.id}" left the car with no ${h} to adopt`);a.push({kind:"block",key:h,value:b})}else throw new Error(`optimiser: Adopt has no way to write "${c.id}" back into the project`)}return a}function Hy(e){let t=performance.now(),r=Gp(e.lap),n=e.follow?my(e.car,e.spec,r):e.spec,{dead:o,unprobed:a,...s}=hy(e.car,n,r);return{...s,deadIds:o.map(i=>i.id),unprobedIds:a.map(i=>i.id),elapsedMs:performance.now()-t,...e.follow?{followed:!0,fromCar:n===e.spec?null:{states:n.states,envelope:n.envelope}}:{}}}var zy=e=>e.vehicle.chassis?{...e,vehicle:Ay(e.vehicle)}:e;function WC(e,t){try{let r=Yy(e.car,e.spec,e.lap),n=ia.find(u=>u.name===e.method);if(!n)throw new Error(`unknown method "${e.method}"`);t({kind:"progress",seed:e.seed,progress:{evaluations:0,budget:e.budget,x:wr(r.variables),score:Fr(r,wr(r.variables)),infeasible:0}});let o=e.from,a=o?{...r,variables:r.variables.map((u,m)=>({...u,start:Number.isFinite(o[m])?o[m]:u.start}))}:r,s=performance.now(),i=n.run(a,{budget:e.budget,seed:e.seed,startJitter:e.startJitter,progressEvery:20,onProgress:u=>t({kind:"progress",seed:e.seed,progress:u})}),c=performance.now()-s,l=i.score.feasible&&oy(r.variables)?sy(r,i.x,i.score):void 0;t({kind:"done",seed:e.seed,result:l?{...i,snapped:l}:i,elapsedMs:c})}catch(r){t({kind:"error",seed:e.seed,message:r instanceof Error?r.message:String(r)})}}var Yy=(e,t,r)=>Ap(e,t,Gp(r));function jC(e,t){let r=e.tireModelIdRear?t.tire(e.tireModelIdRear):void 0;return{tireModel:t.tire(e.tireModelId),...r?{tireModelRear:r}:{},motorModel:t.motor(e.motorModelId),aeroModel:t.aero(e.aeroModelId),batteryModel:t.battery(e.batteryModelId),brakeModel:t.brake(e.brakeModelId),damperModel:t.damper(e.damperModelId),...fi(e,t.damper)}}function UC(e,t,r){let{tireModelRear:n,damperModelRear:o,heaveDamperModel:a,rollDamperModel:s,...i}=r;return{vehicle:e,params:{...t,...i,...n?{tireModelRear:n}:{},...o?{damperModelRear:o}:{},...a?{heaveDamperModel:a}:{},...s?{rollDamperModel:s}:{}}}}var XC=e=>({ggvMode:e.ggvMode,quasiTransient:e.quasiTransient===!0&&e.ggvMode!=="fast",motorThermal:e.motorThermal===!0,...Mw({brakeFade:e.brakeFade===!0,airTempC:e.airTempC,diffYaw:e.diffYaw===!0,...e.air?{air:e.air}:{}})});function BB(e){if(!(e.plannedPath!==void 0||!e.track))return{track:e.track,numerics:e.numerics,settings:{racingLine:e.racingLine,standingStart:e.standingStart,...Object.keys(e.lapCounts).length?{lapCounts:e.lapCounts}:{}},switches:e.switches,rulesets:e.rulesets}}function qC(e,t){let r=t.plannedPath!==void 0,n=BB(t);return{..._C(r?t.plannedPath:t.track,t.numerics,{racingLine:r?!1:t.racingLine,standingStart:t.standingStart,switches:t.switches},e,t.library,t.standingOf),...n?{session:n}:{},rulesets:t.rulesets}}function Wy(e,t){let r=e.vehicles.find(o=>o.id===t);if(!r)throw new Error(`this project holds no vehicle "${t}"`);let n=Ao(e);return UC(structuredClone(ky(e,r.params)),structuredClone(r.params),jC(r.params,n))}var $B="this project's laps follow a fixed trajectory from the planner, which the server cannot read \u2014 set Laptime back to the track to run this study here, or run it in the Studies tool";async function jy(e,t,r,n){if(e.settings.pathPlanId)throw new Error($B);let o=Za(e),a=e.tracks.length?(await Cp(e,t)).asset:null,s={};for(let i of n?NC(n):[]){let c=e.tracks.find(l=>l.id===i);c&&(s[i]=await _c(c,t))}return qC(r,{track:a,numerics:o.numerics,racingLine:o.racingLine,standingStart:o.standingStart,lapCounts:o.lapCounts??{},switches:XC(o),rulesets:e.rulesets??[],library:s,standingOf:i=>e.tracks.find(c=>c.id===i)?.standingStart===!0})}async function QC(e,t,r,n){let o=Wy(e,r),a=Dt(o,n),s=await jy(e,t,o,a);return Hy({id:0,car:o,spec:a,lap:s})}async function ZC(e,t,r,n){let o=Wy(e,r),a=Dt(o,n),s=Ky(o,a);if(s.length)return{problems:[`Adopt has no way to write ${s.join(", ")} back into the project. Take them out of the study.`]};let i;try{i=await jy(e,t,o,a)}catch(l){return{problems:[l instanceof Error?l.message:String(l)]}}let c=fy(o,a,{...Gp(i),metrics:Ur(e.rulesets)});return c.length?{problems:c}:{problems:[],msPerEval:Hy({id:0,car:o,spec:a,lap:i}).msPerEval,carFingerprint:co(zy(o))}}async function GB(e,t,r,n,o,a=[]){let s=$C(t,e,r,n),i=s.length*t.budget,c=null,l=[];for(let[u,m]of s.entries()){if(a.includes(m.seed))continue;await o?.tick();let f=[],p=null,d=null;if(WC(m,y=>{y.kind==="progress"?(f.push([y.progress.evaluations,y.progress.score.total]),y.progress.evaluations===0&&(c??=y.progress.score),o?.progress(u*t.budget+y.progress.evaluations,i)):y.kind==="done"?p={result:y.result,elapsedMs:y.elapsedMs}:d=y.message}),d)throw new Error(d);if(!p)throw new Error("the search stopped without a result");let{result:h,elapsedMs:b}=p,g={seed:m.seed,startJitter:m.startJitter,x:h.x,score:h.score,evaluations:h.evaluations,infeasible:h.infeasible,history:h.history,trace:f,elapsedMs:b,...h.snapped?{snapped:h.snapped}:{}};l.push(g),o?.progress((u+1)*t.budget,i),await o?.finished?.(g)}if(!c)throw new Error("the search never scored the starting design");return{method:t.method,budget:t.budget,designScore:c,runs:l}}async function JC(e,t,r,n){let o=Wy(e,r.vehicleId),a=Dt(o,r.spec),s=Ky(o,a);if(s.length)throw new Error(`study_adopt has no way to write ${s.join(", ")} back into the project \u2014 take them out of the study`);let i=await jy(e,t,o,a),c=r.method??VC;if(!ia.some(b=>b.name===c))throw new Error(`unknown method "${c}" \u2014 it is one of ${ia.map(b=>b.name).join(", ")}`);let l=r.budget??BC,u=Math.max(1,Math.min(r.seeds??$c.length,$c.length)),m=await GB(o,{spec:a,method:c,budget:l},i,u,n),f=Yy(o,a,i),p=m.runs.map(b=>({seed:b.seed,startScore:m.designScore.total,score:b.score.total,feasible:b.score.feasible,...b.score.reason?{reason:b.score.reason}:{},terms:b.score.terms,x:b.x,evaluations:b.evaluations,infeasible:b.infeasible,bounds:GC(f.variables,b.x),constraints:KC(o,a,b.x,i),...b.snapped?{onSteps:{x:b.snapped.x,score:b.snapped.score.total,feasible:b.snapped.score.feasible,...b.snapped.score.reason?{reason:b.snapped.score.reason}:{},terms:b.snapped.score.terms}}:{}})),d=m.runs.reduce((b,g)=>Hs(g.score,b.score)?g:b),h=d.snapped?.score.feasible?d.snapped:null;return{method:c,budget:l,seeds:p,spread:m.runs.length>1?HC(o,f.variables,m.runs.map(b=>({x:b.x,score:b.score}))):null,writes:YC(o,a,h?h.x:d.x),...d.snapped?{adopts:h?"on its steps":`as found: on its steps it breaks a hold (${d.snapped.score.reason??"not legal"})`}:{}}}function tT(){if(typeof process.threadCpuUsage!="function")return performance.now();let e=process.threadCpuUsage();return(e.user+e.system)/1e3}async function HB(e,t){let r=xw(e.root);switch(e.kind){case"sweep":return Dw(e.doc,r,e.req,t);case"convergence":return Pw(e.doc,r,{vehicleId:e.vehicleId,...e.steps?{steps:e.steps}:{},...e.tolPct!==void 0?{tolPct:e.tolPct}:{},onStep:t});case"study":return JC(e.doc,r,{vehicleId:e.vehicleId,spec:e.spec,...e.method?{method:e.method}:{},...e.budget?{budget:e.budget}:{},...e.seeds?{seeds:e.seeds}:{}},{progress:t,cancelled:()=>!1,tick:async()=>{}});case"fleet":return Tp(e.doc,r,{...e.vehicleIds?{vehicleIds:e.vehicleIds}:{},...e.settings?{settings:e.settings}:{},...e.overrides?{overrides:e.overrides}:{}});case"probe":return QC(e.doc,r,e.vehicleId,e.spec);case"quote":return ZC(e.doc,r,e.vehicleId,e.spec)}}if(eT){let e=eT,t=r=>e.postMessage(r);(async()=>{try{let r=await HB(KB,(n,o)=>t({type:"progress",done:n,total:o}));t({type:"done",result:r,cpuMs:tT()})}catch(r){t({type:"failed",message:r instanceof Error?r.message:String(r),cpuMs:tT()})}})()}export{HB as runJob,tT as threadCpuMs};
226
+ `)),this.name="RulesetDefError",this.problems=r}},zi=e=>typeof e=="number"&&Number.isFinite(e),Hi=e=>zi(e)&&e>0,Lt=(e,t)=>e===void 0||t(e);function l_(e){let t=[],r=(o,a=null)=>t.push({key:a,message:o});if(typeof e.id!="string"||e.id===""?r("A ruleset needs an id"):/^[A-Za-z0-9_-]+$/.test(e.id)||r(`The id "${e.id}" is letters, digits, "-" and "_" only`),typeof e.label!="string"&&r("A ruleset needs a label"),typeof e.description!="string"&&r("A ruleset needs a description, even an empty one"),Array.isArray(e.events)||r("A ruleset\u2019s events are a list"),Array.isArray(e.kpis)||r("A ruleset\u2019s KPIs are a list"),t.length)return t;for(let o of e.events){let a=o,s=typeof a?.id=="string"?`Event "${a.id}"`:"An event";if(typeof a!="object"||a===null||typeof a.id!="string"||typeof a.label!="string"){r(`${s} needs an id and a label`);continue}switch(a.kind){case"straightLineAccel":Hi(a.distance)||r(`${s} needs a distance above zero, in metres`),Lt(a.vStart,i=>zi(i)&&i>=0)||r(`${s}'s entry speed must be zero or more`);break;case"constantRadius":Hi(a.radius)||r(`${s} needs a radius above zero, in metres`),Lt(a.laps,i=>zi(i)&&i>=1)||r(`${s} runs at least one lap`);break;case"trackLap":Lt(a.laps,i=>zi(i)&&i>=1)||r(`${s} runs at least one lap`),Lt(a.distance,Hi)||r(`${s}'s distance must be above zero, in metres`),Lt(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),Lt(a.unit,i=>typeof i=="string")||r("Its unit is text",s),Lt(a.over,i=>typeof i=="string")||r("Names its event by id",s),Lt(a.format,i=>i==="time"||i==="points")||r("Is shown as a time, as points, or as a number",s),Lt(a.max,zi)||r("Its maximum is a number",s),Lt(a.lowerBetter,i=>typeof i=="boolean")||r("Lower is better, or it is not",s),Lt(a.hidden,i=>typeof i=="boolean")||r("Is hidden, or it is not",s)}Lt(e.track?.minTurnRadius,Hi)||r("The tightest turn the rules allow is a radius above zero");let n=e.battery;for(let o of["packVoltageMax","segmentVoltageMax","powerLimitKw"])Lt(n?.[o],Hi)||r(`The pack's ${o} must be above zero`);if(e.score!==void 0){let o=e.score?.parts;typeof e.score?.total!="string"||typeof o!="object"||o===null||Array.isArray(o)?r("The score names its total and its parts"):Object.values(o).every(a=>typeof a=="string")||r("Each part of the score names a KPI")}return t}function DS(e){let t=l_(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}=fm(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 bm(e){return DS(e).problems}var ng=e=>Number.isFinite(e)?e:NaN;function u_(e){return e.unit&&e.format!=="time"?`${e.label} (${e.unit})`:e.label}function Rn(e){let t=structuredClone(e),{plan:r,problems:n}=DS(t);if(!r)throw new hm(t.id,n);let o=new WeakMap,a=p=>{let d=o.get(p);return d||(d=rg(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 ng(b);let g=h,y=i.get(p);return y!==void 0?ng(g.parts?.[y]):p===t.score?.total?ng(g.total):NaN},l=t.kpis.filter(p=>!p.hidden).map(p=>{let d=r.field.has(p.key);return{key:p.key,label:u_(p),lowerBetter:p.lowerBetter??!1,...p.format?{format:p.format}:{},...d?{field:!0}:{},value:d?c(p.key):h=>a(h)[p.key]}}),u=t.score,m=u?p=>{let d=Ki(r,p),h={};for(let[b,g]of Object.entries(d)){let y={},R={};for(let[k,v]of Object.entries(u.parts)){y[k]=g[v];let x=s.get(v)?.max;x!=null&&(R[k]=x)}h[b]={total:g[u.total],parts:y,...Object.keys(R).length?{maxima:R}:{},kpis:Object.fromEntries(t.kpis.map(k=>[k.key,g[k.key]]))}}return h}:void 0,f=m||(r.field.size>0?p=>{let d=Ki(r,p),h={};for(let[b,g]of Object.entries(d))h[b]={kpis:Object.fromEntries(t.kpis.map(y=>[y.key,g[y.key]]))};return h}:void 0);return{id:t.id,label:t.label,description:t.description,events:t.events,metrics:l,...t.track?{track:t.track}:{},...t.battery?{battery:t.battery}:{},...t.traceEventId?{traceEventId:t.traceEventId}:{},...m?{score:m}:{},...f?{field:f}:{},definition:t}}var Ut={accel:"accel",skidpad:"skidpad",autocross:"autocross",endurance:"endurance"},ES=[{kind:"straightLineAccel",id:Ut.accel,label:"Acceleration (75 m)",distance:75},{kind:"constantRadius",id:Ut.skidpad,label:"Skidpad",radius:8.375},{kind:"trackLap",id:Ut.autocross,label:"Autocross (1 lap)",laps:1},{kind:"trackLap",id:Ut.endurance,label:"Endurance (22 km)",distance:22e3}],IS=[{key:"autocross",label:"Autocross lap",format:"time",lowerBetter:!0,expr:"autocross.time"},{key:"accel",label:"Acceleration",format:"time",lowerBetter:!0,expr:"accel.time"},{key:"skidpad",label:"Skidpad lap",format:"time",lowerBetter:!0,expr:"skidpad.lapTime"},{key:"endurance",label:"Endurance",format:"time",lowerBetter:!0,expr:"endurance.time"},{key:"energy",label:"Energy",unit:"kWh",lowerBetter:!0,expr:"endurance.energy"},{key:"overall",label:"Overall",unit:"pts",format:"points",expr:"accelPts + skidpadPts + autocrossPts + endurancePts + efficiencyPts"},{key:"endurancePts",label:"Endurance",unit:"pts",format:"points",max:250,expr:"if(finite(finishedEndurance), 0.9 * 250 * ((1.333 * fleetmin(finishedEndurance) / min(finishedEndurance, 1.333 * fleetmin(finishedEndurance)) - 1) / 0.333) + 0.1 * 250, 0)"},{key:"efficiencyPts",label:"Efficiency",unit:"pts",format:"points",max:100,expr:"if(and(finite(finishedEndurance), finishedEndurance <= 1.333 * fleetmin(finishedEndurance)), 100 * ((1.5 * fleetmin(efficiencyFactor) - min(1.5 * fleetmin(efficiencyFactor), efficiencyFactor)) / (1.5 * fleetmin(efficiencyFactor) - fleetmin(efficiencyFactor))), 0)"},{key:"finishedEndurance",label:"Endurance, if finished",unit:"s",hidden:!0,expr:"if(endurance.finished, endurance.time, nan)"},{key:"efficiencyFactor",label:"Efficiency factor",unit:"s\xB2\xB7kWh",hidden:!0,expr:"finishedEndurance ^ 2 * endurance.energy"},{key:"accelPts",label:"Acceleration",unit:"pts",format:"points",max:75,hidden:!0,expr:"0.95 * 75 * ((1.5 * fleetmin(accel) / min(accel, 1.5 * fleetmin(accel)) - 1) / 0.5) + 0.05 * 75"},{key:"skidpadPts",label:"Skidpad",unit:"pts",format:"points",max:75,hidden:!0,expr:"0.95 * 75 * (((1.25 * fleetmin(skidpad) / min(skidpad, 1.25 * fleetmin(skidpad))) ^ 2 - 1) / 0.5625) + 0.05 * 75"},{key:"autocrossPts",label:"Autocross",unit:"pts",format:"points",max:100,hidden:!0,expr:"0.95 * 100 * ((1.25 * fleetmin(autocross) / min(autocross, 1.25 * fleetmin(autocross)) - 1) / 0.25) + 0.05 * 100"}],_S={total:"overall",parts:{[Ut.accel]:"accelPts",[Ut.skidpad]:"skidpadPts",[Ut.autocross]:"autocrossPts",[Ut.endurance]:"endurancePts",efficiency:"efficiencyPts"}},NS={id:"fs-ev",label:"Formula Student \u2014 Electric",description:"The four dynamic events (acceleration, skidpad, autocross, endurance) scored on the Formula Student point table, with efficiency from battery energy.",events:ES,kpis:IS,score:_S,track:{minTurnRadius:4.5},battery:Qy,traceEventId:Ut.autocross},OS={id:"fs-cv",label:"Formula Student \u2014 Combustion",description:"Same events and point table as the electric class. An engine car\u2019s efficiency is scored on the work at its crankshaft until its fuel is modelled; an electric car\u2019s on its pack.",events:ES,kpis:IS,score:_S,track:{minTurnRadius:4.5},traceEventId:Ut.autocross},Yi=Rn(NS),og=Rn(OS);var ag="lap",m_=[{kind:"trackLap",id:ag,label:pm,laps:1}],VS={id:"trackday",label:"Track day",description:"One flying lap of the selected track. Times and traces only \u2014 no scoring.",events:m_,kpis:[{key:"lap",label:"Lap time",format:"time",lowerBetter:!0,expr:"lap.time"},{key:"topSpeed",label:"Top speed",unit:"km/h",over:ag,expr:"peak(speed)"},{key:"energy",label:"Energy / lap",unit:"kWh",lowerBetter:!0,expr:"lap.energy"}],traceEventId:ag},sg=Rn(VS);function vn(e){if(e===null||typeof e!="object")return JSON.stringify(e)??"null";if(Array.isArray(e))return`[${e.map(vn).join(",")}]`;let t=e,r=Object.keys(t).sort(),n=[];for(let o of r)t[o]!==void 0&&n.push(`${JSON.stringify(o)}:${vn(t[o])}`);return`{${n.join(",")}}`}function co(e){let t=vn(e),r=2166136261;for(let n=0;n<t.length;n++)r^=t.charCodeAt(n),r=r+((r<<1)+(r<<4)+(r<<7)+(r<<8)+(r<<24))>>>0;return r.toString(16).padStart(8,"0").slice(-6)}var Na=[Yi,og,sg],lo=Yi.id,Oa=e=>Na.some(t=>t.id===e),BS=new WeakMap,Wi=new Map,p_=64;function gm(e){let t=BS.get(e);if(t!==void 0)return t;let r=vn(e),n=Wi.get(r);return n===void 0&&(n=bm(e).length?null:Rn(e),Wi.size>=p_&&Wi.delete(Wi.keys().next().value),Wi.set(r,n)),BS.set(e,n),n}function ym(e,t=[]){if(e==null)return;if(typeof e!="string")return gm(e)??void 0;let r=Na.find(o=>o.id===e);if(r)return r;let n=t.find(o=>o.id===e);return n?gm(n)??void 0:void 0}function uo(e,t=[]){return ym(e,t)??Yi}function ig(e=[]){let t=e.filter(r=>!Oa(r.id)).map(r=>gm(r)).filter(r=>r!==null);return[...Na,...t]}var ji=e=>e.definition??e.id;function xm(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=d_(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 lg(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=cg(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 d_(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=cg(e,c,r,n),u=new Array(o).fill(0);u[0]=i,u[o-1]=s;let m=cg(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 cg(e,t,r,n){let o=t.length,a=new Array(o),s=new Array(o);a[0]=r[0]/t[0],s[0]=n[0]/t[0];for(let c=1;c<o;c++){let l=t[c]-e[c]*a[c-1];a[c]=r[c]/l,s[c]=(n[c]-e[c]*s[c-1])/l}let i=new Array(o);i[o-1]=s[o-1];for(let c=o-2;c>=0;c--)i[c]=s[c]-a[c]*i[c+1];return i}function Ui(e){let t=e.z;if(!Array.isArray(t)||t.length<2)return null;let r=e.closed!==!1,n=e.x.length,o=r?n:n-1,a=[0];for(let l=0;l<o;l++){let u=(l+1)%n;a.push(a[l]+Math.hypot(e.x[u]-e.x[l],e.y[u]-e.y[l]))}let s=a[o],i=t.length,c=i===n?a.slice(0,n):Array.from({length:i},(l,u)=>r?u/i*s:u/(i-1)*s);return{z:t,pos:c,length:s,closed:r}}function $S(e,t,r){let n=e.pos[r]-e.pos[t];return e.closed?n>e.length/2?n-e.length:n<-e.length/2?n+e.length:n:n}function GS(e,t){let[r,n,o,a,s,i]=e,c=a*i-s*s,l=o*s-n*i,u=n*s-o*a,m=r*c+n*l+o*u;if(!(Math.abs(m)>1e-12*Math.max(1,Math.abs(r*a*i))))return null;let f=r*i-o*o,p=n*o-r*s,d=r*a-n*n;return[(c*t[0]+l*t[1]+u*t[2])/m,(l*t[0]+f*t[1]+p*t[2])/m,(u*t[0]+p*t[1]+d*t[2])/m]}function KS(e){let t=e.z.length;if(t<5)return 0;let r=[];for(let a=0;a<t;a++){let s=[a-2,a-1,a+1,a+2].map(h=>e.closed?(h+t)%t:h);if(s.some(h=>h<0||h>=t))continue;let i=s.map(h=>$S(e,a,h)),c=Math.max(...i.map(Math.abs));if(!(c>0))continue;let l=i.map(h=>h/c),u=[0,0,0,0,0];for(let h of l)for(let b=0;b<5;b++)u[b]+=h**b;let m=GS([u[0],u[1],u[2],u[2],u[3],u[4]],[1,0,0]);if(!m)continue;let f=l.map(h=>m[0]+m[1]*h+m[2]*h*h),p=0,d=1;f.forEach((h,b)=>{p+=h*e.z[s[b]],d+=h*h}),r.push(Math.abs(e.z[a]-p)/Math.sqrt(d))}if(!r.length)return 0;r.sort((a,s)=>a-s);let n=r.length>>1;return 1.4826*(r.length%2?r[n]:(r[n-1]+r[n])/2)}function f_(e,t,r){let n=e.z.length,o=[t],a=[0];for(let s of[-1,1])for(let i=1;i<n;i++){let c=e.closed?((t+s*i)%n+n)%n:t+s*i;if(c<0||c>=n)break;let l=$S(e,t,c);if(Math.abs(l)>=r||Math.sign(l)!==s)break;o.push(c),a.push(l)}return{j:o,t:a}}function h_(e,t,r){let{j:n,t:o}=f_(e,t,r);if(n.length<4)return null;let a=o.map(l=>(1-Math.abs(l/r)**3)**3),s=o.map(l=>l/r),i=[0,0,0,0,0];s.forEach((l,u)=>{let m=a[u];for(let f=0;f<5;f++)i[f]+=m,m*=l});let c=GS([i[0],i[1],i[2],i[2],i[3],i[4]],[1,0,0]);return c?{j:n,value:s.map((l,u)=>a[u]*(c[0]+c[1]*l+c[2]*l*l))}:null}function ug(e,t){return t>0?e.z.map((r,n)=>{let o=h_(e,n,t/2);return o?o.value.reduce((a,s,i)=>a+s*e.z[o.j[i]],0):r}):[...e.z]}function b_(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 Rm(e){let t=Ui(e);if(!t)return 0;let r=KS(t);return r>1e-6?Math.max(10,b_(r,g_(t))):0}function g_(e){let t=[];for(let r=1;r<e.pos.length;r++)t.push(e.pos[r]-e.pos[r-1]);return e.closed&&e.pos.length&&t.push(e.length-e.pos[e.pos.length-1]+e.pos[0]),t.sort((r,n)=>r-n),t.length?t[t.length>>1]:0}function hr(e,t,r){let n=e.n;if(e.closed===!1){let a=r-t;return a===0?e.diag[t]:a===1?e.off1[t]:a===2?e.off2[t]:a===-1?e.off1[r]:a===-2?e.off2[r]:0}let o=((r-t)%n+n)%n;return o===0?e.diag[t]:o===1?e.off1[t]:o===2?e.off2[t]:o===n-1?e.off1[r]:o===n-2?e.off2[r]:0}function km(e,t){let r=e.n,n=new Array(r).fill(0);for(let o=0;o<r;o++){let a=e.diag[o]*t[o];for(let[s,i]of[[1,e.off1],[2,e.off2]]){(o+s<r||e.closed!==!1)&&(a+=i[o]*t[(o+s)%r]);let c=(o-s+r)%r;(o-s>=0||e.closed!==!1)&&(a+=i[c]*t[c])}n[o]=a}return n}function HS(e,t){let r=new Array(e).fill(0),n=new Array(e).fill(0),o=new Array(e).fill(0);for(let a=0;a<e;a++){a>=2&&(o[a]=r[a-2]!==0?t(a,a-2)/r[a-2]:0),a>=1&&(n[a]=r[a-1]!==0?(t(a,a-1)-o[a]*n[a-1])/r[a-1]:0);let s=t(a,a)-n[a]*n[a]-o[a]*o[a];if(!(s>0)||!Number.isFinite(s))return null;r[a]=Math.sqrt(s)}return{d:r,l1:n,l2:o}}function vm(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 y_(e,t){let r=e[0][0]*e[1][1]-e[0][1]*e[1][0],n=Math.max(Math.abs(e[0][0]*e[1][1]),Math.abs(e[0][1]*e[1][0]),Number.MIN_VALUE);return!Number.isFinite(r)||Math.abs(r)<1e-12*n?null:[(t[0]*e[1][1]-e[0][1]*t[1])/r,(e[0][0]*t[1]-t[0]*e[1][0])/r]}function mg(e,t){let r=e.n;if(r<7)throw new Error(`periodic band solver needs n >= 7, got ${r}`);if(e.closed===!1){let b=HS(r,(y,R)=>hr(e,y,R));if(!b)return null;let g=vm(b,t);return g.every(Number.isFinite)?g:null}let n=r-2,a=HS(n,(b,g)=>hr(e,b,g));if(!a)return null;let s=new Array(n).fill(0),i=new Array(n).fill(0);for(let b=0;b<n;b++)s[b]=hr(e,b,r-2),i[b]=hr(e,b,r-1);let c=vm(a,t.slice(0,n)),l=vm(a,s),u=vm(a,i),m=(b,g)=>{let y=0;for(let R=0;R<b.length;R++)y+=b[R]*g[R];return y},f=[[hr(e,r-2,r-2)-m(s,l),hr(e,r-2,r-1)-m(s,u)],[hr(e,r-1,r-2)-m(i,l),hr(e,r-1,r-1)-m(i,u)]],p=[t[r-2]-m(s,c),t[r-1]-m(i,c)],d=y_(f,p);if(!d)return null;let h=new Array(r).fill(0);for(let b=0;b<n;b++)h[b]=c[b]-l[b]*d[0]-u[b]*d[1];return h[r-2]=d[0],h[r-1]=d[1],h.every(Number.isFinite)?h:null}function zS(e,t,r=0){let n=Math.max(...e.diag.map(Math.abs),1e-30),o=r>0?r:n*1e-12,a=Math.sqrt(t.reduce((s,i)=>s+i*i,0));for(let s=0;s<40;s++){let i={...e,diag:e.diag.map(l=>l+o)},c=mg(i,t);if(c){let l=km(i,c).map((m,f)=>m-t[f]);if(Math.sqrt(l.reduce((m,f)=>m+f*f,0))<=1e-6*Math.max(a,1e-12))return c}o=o===0?n*1e-12:o*10}return null}var YS=4,x_=8,pg=.001;function R_(e,t,r){let n=[];for(let c=1;c<e.length;c++){let l=e[c]-e[c-1];l>=pg&&n.push(l)}let o=Float64Array.from(n).sort(),a=o.length>>1,s=o.length?o.length%2?o[a]:.5*(o[a-1]+o[a]):0,i=t?n.length:n.length+1;return Math.max(3,Math.round(i/eM(r,s,i)))}function v_(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])<pg||(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:R_(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])<pg;)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?xm(b.slice(0,d),n,b[d]):lg(b,n),y=r?xm(b.slice(0,d),o,b[d]):lg(b,o),R=new Array(h);for(let F=0;F<h;F++)R[F]=b[F+1]-b[F];let k=[0],v=[0],x=[0],M=0;for(let F=0;F<h;F++){let w=R[F]/YS;for(let C=0;C<YS;C++){let T=C*w;M+=gh(S=>Math.hypot(g.d1(F,S),y.d1(F,S)),T,T+w),k.push(M),v.push(F),x.push(T+w)}}return{closed:r,sx:g,sy:y,h:R,sTable:k,segTable:v,uTable:x,length:M,rawCum:c,rawLength:l}}function Xi(e,t,r,n){if(e===void 0)return r.map(()=>t);if(typeof e=="number")return r.map(()=>e);let o=e.length;if(o===0)return r.map(()=>t);if(o===1)return r.map(()=>e[0]);let a=n.rawCum.length-1,s=o===(n.closed?a:a+1);return r.map(i=>{let c;if(s){let f=i*n.rawLength,p=0,d=a;for(;p<d;){let b=p+d+1>>1;n.rawCum[b]<=f?p=b:d=b-1}let h=p<a?n.rawCum[p+1]-n.rawCum[p]:0;c=p+(h>0?(f-n.rawCum[p])/h:0)}else c=n.closed?i*o:i*(o-1);let l=Math.min(Math.floor(c),o-1)%o,u=c-Math.floor(c),m=n.closed?(l+1)%o:Math.min(l+1,o-1);return e[l]+u*(e[m]-e[l])})}var k_=.01,M_=3,WS=10;function S_(e,t,r,n=WS){let o={step:0,uncertainty:1/0},a=e.length;if(a<8||!(r>0))return o;let s=Math.max(WS,n,6*r/a),i=(r-t[a-1])/2,c=0;for(;c<a/2&&t[c]+i<=s;)c++;let l=0;for(;l<a/2&&r-t[a-1-l]-i<=s;)l++;let u=Math.min(c,l);if(u<3)return o;let m=[],f=[],p=(R,k,v)=>{let x=R/s;m.push([1,x,x*x,x*x*x,k]),f.push(v)};for(let R=0;R<u;R++)p(t[R]+i,1,e[R]);for(let R=0;R<u;R++)p(t[a-1-R]-r+i,0,e[a-1-R]);let d=Array.from({length:5},()=>new Array(5).fill(0)),h=new Array(5).fill(0);m.forEach((R,k)=>{for(let v=0;v<5;v++){h[v]+=R[v]*f[k];for(let x=0;x<5;x++)d[v][x]+=R[v]*R[x]}});let b=Jt(d,h),g=Jt(d,[0,0,0,0,1]);if(b.singular||g.singular)return o;let y=0;return m.forEach((R,k)=>{let v=0;for(let x=0;x<5;x++)v+=R[x]*b.x[x];y+=(f[k]-v)**2}),{step:b.x[4],uncertainty:Math.sqrt(y/(m.length-5)*g.x[4])}}function A_(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 F_(e,t,r){let{pos:n,loop:o}=A_(e.length,t),{step:a,uncertainty:s}=S_(e,n,o,r);return Math.abs(a)>Math.max(k_,M_*s)?{z:e.map((i,c)=>i+a*n[c]/o),drift:-a}:{z:e,drift:0}}function w_(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+gh(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 C_=3,dg=5;function T_(e,t,r,n=dg){return Sm(e,t,r,n)}function Sm(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 mg({n:a,diag:i,off1:c,off2:l,closed:r},u)??[...e]}function it(e,t){let r=st(t),n=v_(e,r.fitSpacing),o=n.length,a=Math.max(x_,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}=w_(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?F_(e.z,n.rawCum,g):null,R=y?y.z:e.z,k=g>0?Ui(e):null,v=k?ug({...k,z:R},g):R,x=Xi(v,0,h,n),M=new Array(s).fill(0);if(b){for(let T=0;T<s;T++){let S=n.closed?(T+1)%s:Math.min(T+1,s-1),A=n.closed?(T-1+s)%s:Math.max(T-1,0),P=n.closed?2:S-A,L=x[S]-x[A];M[T]=P>0?Math.atan2(L,P*i)*180/Math.PI:0}for(let T=0;T<s;T++){if(m[T]===0)continue;let S=n.closed?(T+1)%s:T+1,A=x[S]-x[T];m[T]=Math.hypot(i,A)}let C=0;for(let T=0;T<s;T++)u[T]=C,C+=m[T]}let F=b?m.reduce((C,T)=>C+T,0):o,w;if(b){w=new Array(s).fill(0);let C=Math.max(C_,e.zReach??Rm(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?T_(f,i,n.closed,e.turnReach):f,npts:s,length:F,nx:p,ny:d,z:x,gradient:M,...w?{verticalCurvature:w}:{},widthLeft:Xi(e.widthLeft,1.5,h,n),widthRight:Xi(e.widthRight,1.5,h,n),bank:Xi(e.bank,0,h,n),mu:Xi(e.mu,1,h,n),...y?.drift?{elevationDrift:y.drift}:{}}}function jS(e,t,r){let n=km(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 P_(e,t,r,n){let o=e.n,a=e.closed!==!1,s=(l,u)=>{let m=l+u;return a?(m%o+o)%o:m>=0&&m<o?m:null},i=[...t];for(let l=0;l<o;l++){if(r[l]==="free")continue;let u=n(l);if(u!==0)for(let m of[-2,-1,1,2]){let f=s(l,m);f!=null&&(i[f]-=hr(e,f,l)*u)}}let c={n:o,closed:e.closed,diag:[...e.diag],off1:[...e.off1],off2:[...e.off2]};for(let l=0;l<o;l++){if(r[l]==="free")continue;c.diag[l]=1,c.off1[l]=0,c.off2[l]=0;let u=s(l,-1),m=s(l,-2);u!=null&&(c.off1[u]=0),m!=null&&(c.off2[m]=0),i[l]=n(l)}return zS(c,i)}var L_=1e-4;function US(e,t,r,n,o={}){let a=e.n,s=o.maxIter??60,i=o.tol??1e-9,c=o.bounds,l=(d,h)=>Math.min(n[h],Math.max(r[h],d)),u=r.map((d,h)=>c?.[h]==="hi"?n[h]:c?.[h]==="lo"?r[h]:l(0,h)),m=jS(e,t,u),f=new Array(a).fill("free"),p=!1;for(let d=0;d<s;d++){let h=km(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=P_(e,t,f,R=>u[R]);if(!g)return{x:u,iterations:d+1,converged:!1,bounds:f};let y=!1;for(let R=1;R>1e-12;R*=.5){let k=!1,v=u.map((F,w)=>{if(f[w]!=="free")return F;let C=F+R*(g[w]-F),T=l(C,w);return T!==C&&(k=!0),T}),x=jS(e,t,v),M=0;for(let F=0;F<a;F++)M+=h[F]*(v[F]-u[F]);if(R===1&&!k||x<m&&x<=m+L_*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 fg={lineStep:2,carHalfWidth:.75,margin:.1,foldMargin:.25,referenceReach:5,passes:40,iterations:400},D_=[1,.5,.25,.125,.0625,.03125,.015625,.0078125,.00390625,.001953125,.0009765625],E_=e=>Math.sqrt(e.reduce((t,r)=>t+r*r,0)/(e.length||1));function Qi(e,t,r=!0){let n=e.length,o=new Array(n).fill(0);for(let a=0;a<n;a++){if(!r&&(a===0||a===n-1))continue;let s=(a-1+n)%n,i=(a+1)%n,c=e[a]-e[s],l=t[a]-t[s],u=e[i]-e[a],m=t[i]-t[a],f=e[i]-e[s],p=t[i]-t[s],d=Math.hypot(c,l),h=Math.hypot(u,m),b=Math.hypot(f,p),g=d*h*b;o[a]=g>1e-12?2*(c*m-l*u)/g:0}return o}var I_=Math.PI/180,XS=20;function __(e,t){let r=e.npts,n=e.closed,o=e.x.map((p,d)=>p+t[d]*e.nx[d]),a=e.y.map((p,d)=>p+t[d]*e.ny[d]),s=[0];for(let p=1;p<r;p++)s.push(s[p-1]+Math.hypot(o[p]-o[p-1],a[p]-a[p-1]));let i=n?s[r-1]+Math.hypot(o[0]-o[r-1],a[0]-a[r-1]):s[r-1],c=n?[-1,0,1]:[0],l=[],u=[];for(let p of c)for(let d=0;d<r;d++)l.push(s[d]+p*i),u.push(d+p*r);n&&(l.push(2*i),u.push(2*r));let m=[0];for(let p=1;p<l.length;p++)m.push(m[p-1]+.5*(u[p]+u[p-1])*(l[p]-l[p-1]));let f=p=>{let d=0,h=l.length-1;for(;h-d>1;){let g=d+h>>1;l[g]<=p?d=g:h=g}let b=l[h]>l[d]?(p-l[d])/(l[h]-l[d]):0;return m[d]+(l[h]-l[d])*b*(u[d]+.5*b*(u[h]-u[d]))};return s.map((p,d)=>{let h=n?XS:Math.min(XS,p,i-p);if(!(h>0))return e.z[d];let b=(f(p+h)-f(p-h))/(2*h),g=n?(b%r+r)%r:Math.min(Math.max(b,0),r-1),y=Math.min(Math.floor(g),r-1),R=n?(y+1)%r:Math.min(y+1,r-1);return e.z[y]+(g-y)*(e.z[R]-e.z[y])})}function N_(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?__(t,r):t.z;return{...n||o?{z:s.map((i,c)=>i+r[c]*Math.tan(t.bank[c]*I_))}:{},...n?{zReach:e.zReach??Rm(e)}:{},...o?{bank:[...t.bank]}:{},...a?{mu:[...t.mu]}:{}}}function QS(e,t,r=!0){let n=e.length,o=new Array(n).fill(0);for(let a=0;a<n;a++){if(!r&&(a===0||a===n-1))continue;let s=(a-1+n)%n,i=(a+1)%n;o[a]=.5*(Math.hypot(e[a]-e[s],t[a]-t[s])+Math.hypot(e[i]-e[a],t[i]-t[a]))}return o}function O_(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 V_(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 B_(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=Sm(e.x,s,n,t,!0),c=Sm(e.y,s,n,t,!0),l=new Array(r),u=new Array(r);for(let f=0;f<r;f++){let p=n?(f-1+r)%r:Math.max(f-1,0),d=n?(f+1)%r:Math.min(f+1,r-1),h=i[d]-i[p],b=c[d]-c[p],g=Math.hypot(h,b)||1;l[f]=-b/g,u[f]=h/g}let m=Qi(i,c,n);return n||(m[0]=m[1],m[r-1]=m[r-2]),{...e,x:i,y:c,nx:l,ny:u,curvature:m}}var $_=6;function G_(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($_/(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 hg(e,t={}){let r={...fg,...t},n=it(e,{dsTarget:r.lineStep}),o=B_(n,r.referenceReach),a=o.npts,s=T=>({x:o.x.map((S,A)=>S+o.nx[A]*T[A]),y:o.y.map((S,A)=>S+o.ny[A]*T[A])}),i=T=>{let S=Qi(T.x,T.y,o.closed),A=QS(T.x,T.y,o.closed),P=0;for(let L=0;L<S.length;L++)P+=S[L]*S[L]*A[L];return P},c=E_(n.curvature),l=QS(n.x,n.y,n.closed).reduce((T,S)=>T+S,0),u=new Array(a).fill(0),m=r.carHalfWidth+r.margin,f=new Array(a),p=new Array(a),d=0;for(let T=0;T<a;T++){let S=o.widthLeft[T]-m,A=-(o.widthRight[T]-m);if(S<A){d++;let P=(o.widthLeft[T]-o.widthRight[T])/2;f[T]=P,p[T]=P}else f[T]=S,p[T]=A}let h=[...f],b=[...p];G_(o,f,p,r.foldMargin);let g=T=>{let S=s(T),A=N_(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:dg},L=1e-6,D=T.filter((I,_)=>I>=f[_]-L||I<=p[_]+L).length,E=Qi(S.x,S.y,o.closed),V=I=>1/Math.max(...I.map(Math.abs),1e-9),N=0,z=o.closed?S.x.length:S.x.length-1;for(let I=0;I<z;I++){let _=(I+1)%S.x.length,B=S.x[_]-S.x[I],O=S.y[_]-S.y[I];N+=A.z?Math.hypot(B,O,A.z[_]-A.z[I]):Math.hypot(B,O)}return{offset:T,s:[...o.s],asset:P,curvatureRms:{centreLine:c,racingLine:Math.sqrt(i(S)/(l||1))},infeasibleSamples:d,atBoundary:a?D/a:0,length:{centreLine:n.length,racingLine:N},worstRadius:{centreLine:V(n.curvature),racingLine:V(E)}}},y=o.closed?0:1,R=o.closed?a-1:a-2,k=R-y+1,v=new Array(k),x=new Array(k);for(let T=0;T<k;T++)v[T]=p[y+T],x[T]=f[y+T];if(!o.closed&&k>0){let T=(S,A)=>{if(v[S]=Math.max(v[S],p[A]),x[S]=Math.min(x[S],f[A]),v[S]>x[S]){let P=.5*(v[S]+x[S]);v[S]=P,x[S]=P}};T(0,0),T(k-1,a-1),v[0]=x[0]=Math.min(x[0],Math.max(v[0],0))}if(k<7)return g(u);let M=T=>{let S=s(T),P=[...Qi(S.x,S.y,o.closed).map(Math.abs)].sort((L,D)=>L-D);return{integral:i(S),tail:P[Math.floor(.99*(P.length-1))]}},F=[...u],w=M(u),C;for(let T=0;T<r.passes;T++){let S=s(F),{res:A,jac:P}=O_(S.x,S.y,o.nx,o.ny,o.closed),{M:L,b:D}=V_(P,A,y,R,o.closed),E=US(L,D,v.map((z,I)=>z-F[y+I]),x.map((z,I)=>z-F[y+I]),{maxIter:r.iterations,bounds:C});C=E.bounds;let V=new Array(a).fill(0);for(let z=0;z<k;z++)V[y+z]=E.x[z];o.closed||(V[0]=V[1],V[a-1]=V[a-2]);let N=!1;for(let z of D_){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 bg(e){let t=Math.max(q(e,"track_front"),q(e,"track_rear"));return(t>0?t/2e3:.6)+.1}function Am(e,t,r={}){if(!r.racingLine)return{asset:e,numerics:t,line:null};let n=r.params?bg(r.params):void 0,o=hg(e,{...r.line,...n?{carHalfWidth:n}:{}});return{asset:o.asset,numerics:{...t,fitSpacing:0},line:o}}function qi(e,t,r={}){let n=Am(e,t,r);return{track:it(n.asset,n.numerics),line:n.line}}function gg(e=4,t=qi){let r=new WeakMap;return(n,o,a={})=>{let s=a.racingLine===!0,i=s?[a.params?bg(a.params):null,a.line??null]:null,c=JSON.stringify([o,s,i]),l=r.get(n);l||(l=new Map,r.set(n,l));let u=l.get(c);if(u)return l.delete(c),l.set(c,u),u;let m=t(n,o,a);return l.set(c,m),l.size>e&&l.delete(l.keys().next().value),m}}var qS={racingLine:!1,standingStart:!1},Fm=256;function Zi(e,t,r,n,o=qS,a=qi){let s=uo(n),{racingLine:i,standingStart:c,lapCounts:l}=o;return e.map(u=>{let{track:m}=a(t,r,{racingLine:i,params:u});return qb(Vi(u,s,{track:m,numerics:r,standingStart:c,lapCounts:l}))})}function yg(e,t){let r=uo(e),n=r.score?r.score(t):null,o=r.field===r.score?n:r.field?r.field(t):null;return{scores:n,field:o}}function xg(e,t,r){let n={};for(let o of uo(e).metrics)n[o.key]=o.value(t,r);return n}var wm=36;var kg=287.05287,H_=461.495,Cm=9.80665/(kg*.0065),z_=101325/(kg*288.15),Y_=273.15,W_=-500,j_=6e3,U_=400,X_=1100,Tm={source:"car",altitudeM:0,pressure:{kind:"standard"},humidityPct:0};function Q_(e){return 101325*Math.pow(1-.0065*e/288.15,Cm)}function q_(e){return 288.15/.0065*(1-Math.pow(e/z_,1/(Cm-1)))}function Z_(e){return 288.15/.0065*(1-Math.pow(e/101325,1/Cm))}function J_(e,t){return e*Math.pow(1-.0065*t/288.15,Cm)}function eN(e){return 611.21*Math.exp((18.678-e/234.5)*(e/(257.14+e)))}function tN(e,t){switch(e.kind){case"standard":return Q_(t);case"qnh":return J_(e.hPa*100,t);case"station":return e.hPa*100}}function Ji(e,t,r=0,n=Z_(e)){let o=t+Y_,a=Math.min(.5*e,Math.max(0,Math.min(100,r))/100*eN(t)),s=e-a,i=s/(kg*o)+a/(H_*o);return{altitudeM:n,p:e,pDry:s,T:o,rho:i,densityAltitudeM:q_(i)}}function ZS(e,t){return Ji(tN(e.pressure,e.altitudeM),t,e.humidityPct,e.altitudeM)}var Rg=(e,t,r)=>Math.min(r,Math.max(t,e)),vg=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function Pm(e){if(!e||typeof e!="object")return structuredClone(Tm);let t=e,r=t.pressure??{},n=Rg(vg(r.hPa,1013.25),U_,X_),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:Rg(vg(t.altitudeM,0),W_,j_),pressure:o,humidityPct:Rg(vg(t.humidityPct,0),0,100)}}var ec=e=>e?.source==="venue";var rN=Math.PI/180;function nN(){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 oN(){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 Mg(e){let t=-e*rN;return Q([0,Math.cos(t),Math.sin(t)])}function Lm(){let e={rodType:"push",pushrodAttach:"lowerArm",steerMode:"rack",spinAxis:Mg(-1),loadedRadius:230,springRate:35,rackAxis:[0,1,0]};return{hardpoints:nN(),config:e}}function tc(){let e={rodType:"pull",pushrodAttach:"lowerArm",steerMode:"fixed",spinAxis:Mg(-1.5),loadedRadius:232,springRate:40,rackAxis:[0,1,0]};return{hardpoints:oN(),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:Mg(-.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 Sg(){return{front:Lm(),rear:tc(),config:{wheelbase:1600,trackFront:1200,trackRear:1220,frontAxleX:800}}}var aN=Math.PI/180;function JS(e){let t=-e*aN;return Q([0,Math.cos(t),Math.sin(t)])}function Ag(e,t){let r=([l,u,m])=>[l*t.kx,u*t.ky,m*t.kz],n=e.hardpoints,o=Object.fromEntries(Object.entries(n).map(([l,u])=>[l,r(u)])),a=(l,u)=>{o[l]=[o[l][0],o[l][1],o[l][2]+u]},s=t.lowerInnerDz??0,i=t.upperInnerDz??0;a("lcaFront",s),a("lcaRear",s),a("tieInner",s),a("ucaFront",i),a("ucaRear",i);let c={...e.config,spinAxis:JS(t.camberDeg),loadedRadius:t.loadedRadius,springRate:t.springRate};if(t.actuation==="direct"){let l=o.pushrodOuter,u=[l[0],l[1]*.7,l[2]+1.3*t.loadedRadius];o.damperChassis=u,o.rockerPivotA=u,o.rockerPivotB=u,o.rockerToPushrod=l,o.rockerToDamper=u,c={...c,actuation:"direct",rodType:"push",pushrodAttach:"lowerArm"}}else c={...c,actuation:"rocker"};for(let l of Object.keys(o))o[l]=sN(o[l]);return{hardpoints:o,config:c}}function sN(e){return e.map(t=>Math.round(t*10)/10+0)}function po(e){return{name:e.name,front:Ag(Lm(),e.front),rear:Ag(tc(),e.rear),config:{wheelbase:e.wheelbase,trackFront:e.trackFront,trackRear:e.trackRear,frontAxleX:e.wheelbase/2}}}function Va(e,t,r){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:t}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:r}}}}var Ba=600,fo=610,$a=230,ho=232;function bo(){let e=Sg();return{...e,name:"Formula Student",front:{...e.front,config:{...e.front.config,actuation:"rocker"}},rear:{...e.rear,config:{...e.rear.config,actuation:"rocker"}}}}function Fg(){return po({name:"Formula 1",wheelbase:3600,trackFront:1600,trackRear:1600,front:{kx:1.3,ky:800/Ba,kz:355/$a,lowerInnerDz:-5,upperInnerDz:0,camberDeg:-3,loadedRadius:355,springRate:200},rear:{kx:1.3,ky:800/fo,kz:355/ho,lowerInnerDz:35,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:220}})}function rc(){return Va(po({name:"GT car",wheelbase:2700,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/Ba,kz:325/$a,lowerInnerDz:18,upperInnerDz:5,camberDeg:-3.5,loadedRadius:325,springRate:110,actuation:"direct"},rear:{kx:1.2,ky:825/fo,kz:325/ho,lowerInnerDz:36,upperInnerDz:15,camberDeg:-2,loadedRadius:325,springRate:120,actuation:"direct"}}),318.6,318.6)}function nc(){return Va(po({name:"Sports car",wheelbase:2750,trackFront:1550,trackRear:1550,front:{kx:1.15,ky:775/Ba,kz:320/$a,lowerInnerDz:36,upperInnerDz:15,camberDeg:-.5,loadedRadius:320,springRate:55,actuation:"direct"},rear:{kx:1.15,ky:775/fo,kz:320/ho,lowerInnerDz:57,upperInnerDz:25,camberDeg:-1,loadedRadius:320,springRate:60,actuation:"direct"}}),305.4,309)}function iN(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:JS(n),springRate:o,rackTravel:a}}}function eA(){return Va({name:"Cup car",front:iN(55,-25,-23,-3.5,150,55),rear:Ag(tc(),{kx:1.15,ky:820/fo,kz:320/ho,lowerInnerDz:37,upperInnerDz:12,camberDeg:-2,loadedRadius:320,springRate:130,actuation:"direct"}),config:{wheelbase:2650,trackFront:1660,trackRear:1640,frontAxleX:2650/2},chassis:{boxes:[],body:"cup"}},306.3,311.6)}function tA(){return{...Va(po({name:"Stock car",wheelbase:2794,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/Ba,kz:355/$a,lowerInnerDz:20,upperInnerDz:5,camberDeg:-2.5,loadedRadius:355,springRate:175,actuation:"direct"},rear:{kx:1.2,ky:825/fo,kz:355/ho,lowerInnerDz:40,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:150,actuation:"direct"}}),343.8,345.3),chassis:{boxes:[],body:"nascar"}}}function rA(){let e=Va(po({name:"Hill-climb prototype",wheelbase:2550,trackFront:1580,trackRear:1540,front:{kx:1.1,ky:790/Ba,kz:300/$a,lowerInnerDz:10,upperInnerDz:5,camberDeg:-2.5,loadedRadius:300,springRate:90},rear:{kx:1.1,ky:770/fo,kz:300/ho,lowerInnerDz:30,upperInnerDz:15,camberDeg:-1.5,loadedRadius:300,springRate:120}}),293.3,290.8);return{...e,front:{...e.front,config:{...e.front.config,rackTravel:45}},chassis:{boxes:[],body:"hillclimb"}}}function nA(){let e=Va(po({name:"Race truck",wheelbase:3700,trackFront:2050,trackRear:1950,front:{kx:1.5,ky:1025/Ba,kz:506/$a,lowerInnerDz:40,upperInnerDz:10,camberDeg:-.5,loadedRadius:506,springRate:200,actuation:"direct"},rear:{kx:1.5,ky:975/fo,kz:506/ho,lowerInnerDz:60,upperInnerDz:20,camberDeg:-.25,loadedRadius:506,springRate:160,actuation:"direct"}}),490.4,495.6);return{...e,front:{...e.front,config:{...e.front.config,rackTravel:60}},chassis:{boxes:[],body:"truck"}}}var rt=(e,t,r)=>({value:e,label:t,unit:r}),oA=(e,t)=>({...cr[e],value:t});function aA(e,t,r){let n=[],o=[];for(let a=0;a<=r;a+=500)n.push(a),o.push(a<=t?e:e*t/a);return{rpm:n,torque:o}}function go(e,t,r,n,o){let a=[],s=[];for(let i=0;i<=r;i+=500){a.push(i);let c=i<=t?n:Math.min(n,9549*e/i);s.push(c/o)}return{rpm:a,torque:s}}function Wr(e){let t={name:e.name,m:rt(e.m,"vehicle mass (with driver)","kg"),A:rt(e.A,"frontal area","m^2"),c_l:rt(e.cl,"downforce coefficient","-"),c_w:rt(e.cw,"drag coefficient","-"),l_to_d_ratio:rt(e.cw>0?e.cl/e.cw:0,"lift-to-drag ratio","-"),driven_wheels:rt(e.drivenWheels,"driven wheels","-"),fr_0:rt(-.012,"rolling-resistance coefficient","-"),front_aero_diss:rt(e.frontAero,"front aero distribution","-"),front_mass_diss:rt(e.frontMass,"front mass distribution","-"),r_dyn:rt(e.rDyn,"dynamic tyre radius","m"),rho:rt(1.2,"air density","kg/m^3"),gear_ratio:rt(e.gearRatio,"gear ratio","-"),effi_pgb:rt(e.drivetrainEfficiency,"drivetrain efficiency","-"),capacity:rt(e.capacityAh,"pack capacity","Ah"),soc:rt(1,"state of charge","-"),ocv:rt(e.ocv,"pack open-circuit voltage","V"),power_scale:rt(1,"power scaling factor","-"),power_limit_kw:oA("power_limit_kw",e.powerLimitKw),motor:e.motor,tireModelId:e.tireModelId};e.motorCount!==void 0&&(t.motorCount=e.motorCount),e.driveline&&(t.driveline=structuredClone(e.driveline)),e.motorPlacement&&(t.motorPlacement=e.motorPlacement);for(let[r,n]of Object.entries(e.dynamics))t[r]=oA(r,n);return t}var Ga={name:"Formula Student",m:300,A:1,cl:3,cw:1.3,frontMass:.47,frontAero:.45,rDyn:.222,drivenWheels:2,gearRatio:11.5,motor:aA(25,15e3,2e4),capacityAh:12,ocv:550,drivetrainEfficiency:.95,powerLimitKw:80,tireModelId:"t3",dynamics:{grip_scale:1,stiffness_scale:1,endurance_reserve:5,cg_height:300,tire_vertical_rate:110,unsprung_mass:8,brake_balance:.62,arb_front:20,arb_rear:15,damper_front:2.5,damper_rear:2.5,spring_front:35,spring_rear:40,mr_front:.94,mr_rear:.92,cop_long:.55,cop_height:300,ride_height_front:30,ride_height_rear:35,I_yaw:140,I_roll:45,I_pitch:130,camber_front_deg:-1,camber_rear_deg:-1.5,track_front:1200,track_rear:1220,wheelbase:1600,rc_front:5,rc_rear:4}},Cg={name:"Formula 1",m:798,A:1.5,cl:3,cw:.9,frontMass:.46,frontAero:.44,rDyn:.35,drivenWheels:2,gearRatio:4.9,motor:go(735,2e3,12500,2500,2),motorCount:1,driveline:{rear:xt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t4",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:290,tire_vertical_rate:300,unsprung_mass:30,brake_balance:.58,arb_front:250,arb_rear:150,damper_front:6,damper_rear:6,spring_front:200,spring_rear:220,mr_front:.95,mr_rear:.91,heave_spring_front:800,heave_spring_rear:800,tire_vertical_damping:.5,cop_long:.56,cop_height:400,ride_height_front:35,ride_height_rear:70,I_yaw:800,I_roll:150,I_pitch:800,camber_front_deg:-3,camber_rear_deg:-1.5,track_front:1600,track_rear:1600,wheelbase:3600,rc_front:-4,rc_rear:78}},Em={name:"GT car",m:1300,A:2,cl:1.4,cw:.42,frontMass:.5,frontAero:.42,rDyn:.33,drivenWheels:2,gearRatio:3.43,motor:go(410,2e3,8e3,2e3,2),motorCount:1,driveline:{rear:xt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t5",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:450,tire_vertical_rate:280,unsprung_mass:45,brake_balance:.6,arb_front:40,arb_rear:25,damper_front:4.5,damper_rear:4.5,spring_front:110,spring_rear:120,mr_front:.79,mr_rear:.77,cop_long:.58,cop_height:500,ride_height_front:55,ride_height_rear:75,I_yaw:1800,I_roll:450,I_pitch:1800,camber_front_deg:-3.5,camber_rear_deg:-2,track_front:1650,track_rear:1650,wheelbase:2700,rc_front:48,rc_rear:80}},Im={name:"Sports car",m:1600,A:2.2,cl:-.1,cw:.3,frontMass:.55,frontAero:.5,rDyn:.32,drivenWheels:2,gearRatio:3.14,motor:go(220,1500,6500,1400,2),motorCount:1,driveline:{rear:xt.open},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t6",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:520,tire_vertical_rate:220,unsprung_mass:50,brake_balance:.65,arb_front:25,arb_rear:12,damper_front:2.4,damper_rear:2.4,spring_front:55,spring_rear:60,mr_front:.78,mr_rear:.75,cop_long:.5,cop_height:500,ride_height_front:130,ride_height_rear:140,I_yaw:2600,I_roll:550,I_pitch:2500,camber_front_deg:-.5,camber_rear_deg:-1,track_front:1550,track_rear:1550,wheelbase:2750,rc_front:80,rc_rear:122}},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:go(250,2e3,7e3,1190,2),motorCount:1,motorPlacement:"front",driveline:{front:xt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t7",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:480,tire_vertical_rate:280,unsprung_mass:40,brake_balance:.68,arb_front:20,arb_rear:90,damper_front:4,damper_rear:3.5,spring_front:150,spring_rear:130,mr_front:.95,mr_rear:.76,cop_long:.55,cop_height:450,ride_height_front:64,ride_height_rear:78,I_yaw:1700,I_roll:400,I_pitch:1700,camber_front_deg:-3.5,camber_rear_deg:-2,track_front:1660,track_rear:1640,wheelbase:2650,rc_front:60,rc_rear:84}},Pg={name:"Stock car",m:1620,A:2.2,cl:.6,cw:.45,frontMass:.53,frontAero:.45,rDyn:.35,drivenWheels:2,gearRatio:4.1,motor:go(500,2500,9e3,1680,2),motorCount:1,driveline:{rear:xt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t8",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:430,tire_vertical_rate:320,unsprung_mass:55,brake_balance:.6,arb_front:60,arb_rear:15,damper_front:7.5,damper_rear:6.75,spring_front:175,spring_rear:150,mr_front:.8,mr_rear:.78,cop_long:.55,cop_height:500,ride_height_front:75,ride_height_rear:90,I_yaw:2500,I_roll:550,I_pitch:2500,camber_front_deg:-2.5,camber_rear_deg:-1.5,track_front:1650,track_rear:1650,wheelbase:2794,rc_front:53,rc_rear:91}},Lg={name:"Hill-climb prototype",m:650,A:1.2,cl:2.5,cw:.9,frontMass:.42,frontAero:.42,rDyn:.29,drivenWheels:2,gearRatio:4,motor:go(330,3e3,8500,1240,2),motorCount:1,driveline:{rear:xt.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t9",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:280,tire_vertical_rate:200,unsprung_mass:25,brake_balance:.58,arb_front:40,arb_rear:30,damper_front:3,damper_rear:3.5,spring_front:90,spring_rear:120,mr_front:.94,mr_rear:.91,cop_long:.58,cop_height:350,ride_height_front:45,ride_height_rear:55,I_yaw:550,I_roll:120,I_pitch:550,camber_front_deg:-2.5,camber_rear_deg:-1.5,track_front:1580,track_rear:1540,wheelbase:2550,rc_front:27,rc_rear:65}},Dg={name:"Race truck",m:5300,A:6.2,cl:-.1,cw:.65,frontMass:.6,frontAero:.6,rDyn:.502,drivenWheels:2,gearRatio:3.55,motor:go(880,100,3e3,88e3,2),motorCount:1,driveline:{rear:xt.spool},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t10",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:950,tire_vertical_rate:1e3,unsprung_mass:350,brake_balance:.75,arb_front:350,arb_rear:150,damper_front:12,damper_rear:8.5,spring_front:200,spring_rear:160,mr_front:.81,mr_rear:.8,cop_long:.4,cop_height:1500,ride_height_front:110,ride_height_rear:240,I_yaw:16e3,I_roll:3500,I_pitch:16e3,camber_front_deg:-.5,camber_rear_deg:-.25,track_front:2050,track_rear:1950,wheelbase:3700,rc_front:95,rc_rear:134}};function wg(e,t,r){return Wr(r({...structuredClone(e),name:t}))}var _m={[Ga.name]:Wr(Ga),"Formula Student +15% downforce":wg(Ga,"Formula Student +15% downforce",e=>({...e,cl:e.cl*1.15,cw:e.cw*1.08})),"Formula Student -15 kg":wg(Ga,"Formula Student -15 kg",e=>({...e,m:e.m-15})),"Formula Student +15% power":wg(Ga,"Formula Student +15% power",e=>({...e,motor:aA(25*1.15,15e3,2e4),powerLimitKw:80*1.15})),[Cg.name]:Wr(Cg),[Em.name]:Wr(Em),[Im.name]:Wr(Im),[Tg.name]:Wr(Tg),[Pg.name]:Wr(Pg),[Lg.name]:Wr(Lg),[Dg.name]:Wr(Dg)},sA=Object.keys(_m),Eg=sA.slice(0,4),Ig=[Ga.name,Cg.name,Em.name,Im.name,Tg.name,Pg.name,Lg.name,Dg.name];var Wre={"Touring car":Em.name,"Street car":Im.name};var cN={bg:"#0e1116",panel:"#161b22",panel2:"#1c232d",border:"#2a323d",borderBright:"#39424e",sunken:"#11161c",ink:"#06090d"},lN={normal:"#d6dde6",dim:"#8b96a3",bright:"#e7ecf3",white:"#ffffff"},uN={label:"#c8d2dc",grid:"#39424e",gridFaint:"#232b35",empty:"#1a2028"},mN={accent:"#4aa3ff",accentInk:"#04121f",warn:"#ffb454",good:"#4ec9a0",bad:"#ff6b6b",badSoft:"#ff8f8f"},pN=["#f0e442","#7b68ee","#f7a8b8","#d55e00","#d8b4fe","#b5e48c"],Nm={front:"#a6e22e",rear:"#00b4d8"},iA=["#5b4bd6","#4aa3ff","#4ec9a0","#f0e442"],_g={power:"#ffb454",traction:"#f0845c",front:Nm.front,rear:Nm.rear,grip:"#73c9b3",braking:"#b48aff",crest:"#e88fd0",below:"rgba(214, 221, 230, 0.32)"},dN={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"},fN={x:"#ff6b6b",y:"#57c75a",z:"#4aa3ff"},hN={line:"#b4bfcb"},bN={compression:"#b48aff",tension:"#ff6b6b"},gN={fz:"#e7ecf3",fx:"#7ad7f0",fy:"#ff54c8"},yN={drivenLine:"#4d7cff",axis:"#eef3fa",slip:"#ffe81a",drive:_g.power,brake:_g.braking},xN={ground:"#101920",grid:"#1a2630",gridMajor:"#26343f",horizon:"#1d2833",bridge:"#6f7a86",coneLeft:"#2f63c9",coneRight:"#d9b51f",coneStart:"#ee7a2c"},RN={chassis:"#435160",volume:"#303b47",tyre:"#435160",tyreLine:"#39424e",tyreFace:"#1c232d"},vN={centreLine:"#4aa3ff",corridorFill:"rgba(74,163,255,0.10)",boundary:"#3d4956",racingLine:"#ffb454",start:"#e7ecf3",finish:"#ff6b6b",direction:"#8b96a3"},kN={SURFACE:cN,TEXT:lN,CHART:uN,ROLE:mN,SERIES:pN,AXLE:Nm,LAP_SPEED:iA,LIMITER:_g,RIG:dN,AXIS:fN,CONSTRUCTION:hN,FORCE:bN,TYRE_FORCE:gN,REPLAY:yN,SCENERY:xN,BODY:RN,TRACK:vN},cA=e=>Object.fromEntries(Object.entries(e).map(([t,r])=>[t,Array.isArray(r)?Object.freeze([...r]):Object.freeze({...r})])),Om=cA(kN),vt=Om.SERIES,lA=(()=>{let e="#b06400",t="#d1343a",r={front:"#70bf03",rear:"#3392d0"},n={power:e,traction:"#d05a2a",front:r.front,rear:r.rear,grip:"#2a9a83",braking:"#7b55d0",crest:"#c2479f",below:"rgba(34, 39, 45, 0.28)"};return cA({SURFACE:{bg:"#f4f5f3",panel:"#fbfbfa",panel2:"#ffffff",border:"#d6dadd",borderBright:"#b7bec4",sunken:"#eceeeb",ink:"#ffffff"},TEXT:{normal:"#22272d",dim:"#5c6570",bright:"#0f1215",white:"#000000"},CHART:{label:"#3a424b",grid:"#c2c8cd",gridFaint:"#e2e5e7",empty:"#e8eae7"},ROLE:{accent:"#1a64c2",accentInk:"#ffffff",warn:e,good:"#0f8a66",bad:t,badSoft:"#e2696d"},SERIES:["#b5a11a","#2844e3","#f47ec1","#9b3a1b","#764299","#58b977"],AXLE:r,LAP_SPEED:["#4b3bc4","#1a64c2","#0f8a66","#a87e00"],LIMITER:n,RIG:{chassis:"#1a64c2",ballJoint:"#c27200",arm:"#56616d",tie:"#24907b",pushrod:"#a3820f",rocker:"#6656b8",kingpin:"#8f7f10",arbBar:"#b04d77",arbArm:"#9a4767",arbLink:"#c27200",heaveSpring:"#1688ad",wheelCentre:"#15181c",contactPatch:t,ground:"#e2e6e8",groundFaint:"#edf0f1"},AXIS:{x:"#d93a3a",y:"#2f9d34",z:"#1a64c2"},CONSTRUCTION:{line:"#5a6570"},FORCE:{compression:"#7b55d0",tension:t},TYRE_FORCE:{fz:"#15181c",fx:"#0f8fb0",fy:"#c8198f"},REPLAY:{drivenLine:"#2f5be0",axis:"#15181c",slip:"#c79a00",drive:n.power,brake:n.braking},SCENERY:{ground:"#dde3e1",grid:"#ccd3d1",gridMajor:"#b5bfbc",horizon:"#e8edf0",bridge:"#9aa3ab",coneLeft:"#2f63c9",coneRight:"#d9b51f",coneStart:"#ee7a2c"},BODY:{chassis:"#a9b3bd",volume:"#c7ced5",tyre:"#24282c",tyreLine:"#2c333a",tyreFace:"#c3cad0"},TRACK:{centreLine:"#1a64c2",corridorFill:"rgba(26,100,194,0.10)",boundary:"#a3acb4",racingLine:e,start:"#15181c",finish:t,direction:"#5c6570"}})})();var uA=e=>{let t=/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(e.trim());return t?`#${(t[1].length===3?t[1].replace(/./g,n=>n+n):t[1]).toLowerCase()}`:null},Ure=(()=>{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=Om[r],o=lA[r];for(let a of Object.keys(n)){let s=uA(n[a]);s&&!e.has(s)&&e.set(s,o[a])}}return e})();var mA=(e,t)=>new Set(t.flatMap(r=>{let n=e[r];return Array.isArray(n)?[...n]:Object.values(n)}).map(uA).filter(r=>r!==null)),Xre=mA(lA,["SERIES","AXLE","LAP_SPEED","LIMITER","ROLE","RIG","FORCE","TYRE_FORCE","REPLAY","AXIS","TRACK","CONSTRUCTION"]),Qre=mA(Om,Object.keys(Om).filter(e=>e!=="SURFACE"));function Ng(){return{kind:"simple",name:"Simple motor",rpm:[0,16e3,2e4],torque:[21,21,14],efficiency:.95}}function Og(){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 Vg(){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 Bg(){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 $g(){return{kind:"ice",name:"Formula 1 power unit (example)",rpm:[4e3,5e3,6e3,7e3,8e3,9e3,1e4,10500,11e3,11500,12e3,12500],torque:[896,822,773,738,712,692,675,668,638,610,585,545],idleRpm:4e3,limitRpm:12500,inertia:.02,gearbox:{primary:1,ratios:[4,3.15,2.575,2.175,1.85,1.6,1.375,1.18],efficiency:.94,upshiftTime:0,downshiftTime:0,driveKept:1},breathing:{induction:{kind:"boosted",boostKPa:350,maxPressureRatio:5}}}}function pA(){return{kind:"ice",name:"GT race engine, 4.0 l (example)",rpm:[2500,3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3,7500,8e3],torque:[380,410,440,465,485,500,515,525,530,540,522,480],idleRpm:2500,limitRpm:8e3,inertia:.15,gearbox:{primary:1,ratios:[3,2.15,1.7,1.4,1.17,.98],efficiency:.93,upshiftTime:.05,downshiftTime:.08},breathing:{induction:{kind:"natural"}}}}function dA(){return{kind:"ice",name:"Turbocharged 3.0 l six (example)",rpm:[1e3,1500,1800,2500,3500,4500,5e3,5500,6e3,6500,7e3],torque:[230,340,400,400,400,400,400,382,350,315,280],idleRpm:1e3,limitRpm:7e3,inertia:.2,gearbox:{primary:1,ratios:[3.6,2.19,1.54,1.21,1,.83],efficiency:.92,upshiftTime:.2,downshiftTime:.2,driveKept:.8},breathing:{induction:{kind:"boosted",boostKPa:220,maxPressureRatio:3}}}}function fA(){return{kind:"ice",name:"Turbocharged 2.0 l four (example)",rpm:[2e3,2500,3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3],torque:[330,400,420,420,420,420,415,410,398,365,330],idleRpm:2e3,limitRpm:7e3,inertia:.15,gearbox:{primary:1,ratios:[2.92,2.05,1.61,1.32,1.12,.97],efficiency:.93,upshiftTime:.07,downshiftTime:.08},breathing:{induction:{kind:"boosted",boostKPa:250,maxPressureRatio:3.2}}}}function hA(){return{kind:"ice",name:"Stock car V8, 5.9 l (example)",rpm:[2500,3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3,7500,8e3,8500,9e3],torque:[450,480,510,535,555,570,585,595,600,598,590,578,562,525],idleRpm:2500,limitRpm:9e3,inertia:.18,gearbox:{primary:1,ratios:[2.8,2,1.55,1.24,1],efficiency:.93,upshiftTime:.1,downshiftTime:.1},breathing:{induction:{kind:"natural"}}}}function bA(){return{kind:"ice",name:"Turbocharged 2.0 l four, hill climb (example)",rpm:[3e3,3500,4e3,4500,5e3,5500,6e3,6500,7e3,7500,8e3,8500],torque:[314,380,446,462,462,462,458,450,437,420,388,347],idleRpm:3e3,limitRpm:8500,inertia:.1,gearbox:{primary:1,ratios:[2.69,2,1.6,1.33,1.14,1],efficiency:.93,upshiftTime:.05,downshiftTime:.08},breathing:{induction:{kind:"boosted",boostKPa:250,maxPressureRatio:4.5}}}}function gA(){return{kind:"ice",name:"Race truck diesel six, 13 l (example)",rpm:[800,1e3,1200,1400,1600,1800,2e3,2200,2400,2600,2800,3e3],torque:[3e3,4e3,4900,5500,5250,4670,4200,3820,3500,3230,3e3,2700],idleRpm:800,limitRpm:3e3,inertia:1.5,gearbox:{primary:1,ratios:[16,12.44,9.67,7.51,5.84,4.54,3.53,2.74,2.13,1.66,1.29,1],efficiency:.92,upshiftTime:.35,downshiftTime:.35},breathing:{induction:{kind:"boosted",boostKPa:350,maxPressureRatio:4.3}}}}function yA(e){return co(MN(e))}function MN(e){if(e===null||typeof e!="object"||Array.isArray(e))return e;let t={...e};return delete t.name,Array.isArray(t.vehicles)&&(t.vehicles=t.vehicles.map(r=>{if(r===null||typeof r!="object"||Array.isArray(r))return r;let n={...r};return delete n.name,n})),t}function oc(e,t){return{...t,fingerprint:yA(e)}}var xA="CC-BY-4.0",SN={title:"PaceDynamics built-in library",url:"https://pacedyn.dev/",licence:xA},RA={fidelity:"generic",licence:xA,sources:[SN]};var Vm=e=>oc(e,RA);var vA=["raw.githubusercontent.com"],kA=["tum-csv"],FN=/^[0-9a-f]{64}$/;function sc(e){if(typeof e!="object"||e===null||Array.isArray(e))return!1;let{url:t,sha256:r,format:n}=e;if(typeof t!="string"||t.length>500||typeof r!="string"||!FN.test(r)||!kA.includes(n))return!1;try{let o=new URL(t);return o.protocol==="https:"&&vA.includes(o.hostname)&&!o.username&&!o.password&&!o.port}catch{return!1}}var Bm=e=>new URL(e.url).hostname;async function MA(e){let t=await globalThis.crypto.subtle.digest("SHA-256",e);return[...new Uint8Array(t)].map(r=>r.toString(16).padStart(2,"0")).join("")}function wN(e){let t=new URL(e).pathname.split("/").pop()??"";return decodeURIComponent(t).replace(/\.[^.]*$/,"")||"Linked track"}function CN(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 TN={"tum-csv":CN};function SA(e,t){return TN[t.format](e,wN(t.url))}async function Gg(e,t,r){let n=await MA(e);if(n!==t.sha256)throw new Error(`${Bm(t)} did not return the file that was reviewed (its SHA-256 is ${n.slice(0,12)}\u2026, not ${t.sha256.slice(0,12)}\u2026).`);let o=SA(new TextDecoder().decode(e),t),a=await $m(o);if(a!==r)throw new Error(`Linked track ${r} does not convert to its name (it is ${a}).`);return o}var Kg=20,LN=new RegExp(`^[0-9a-f]{${Kg}}$`),ic=e=>typeof e=="string"&&LN.test(e);async function $m(e){let t=new TextEncoder().encode(vn(e)),r=await globalThis.crypto.subtle.digest("SHA-256",t);return[...new Uint8Array(r)].map(n=>n.toString(16).padStart(2,"0")).join("").slice(0,Kg)}var Hg=e=>`tracks/${e}.json`;var DN=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function zg(e){return{model:{name:e.name,source:e.source},...e.provenance?{provenance:e.provenance}:{}}}async function Yg(e,t){if(!DN(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 $m(e);if(r!==t)throw new Error(`Catalogue track ${t} does not match its name (it is ${r}).`);return e}var yo=(e,t,r,n=[])=>({doc:e,ref:t,refs:[t,...n.map(o=>o.ref)],slots:[{key:e,ref:t,label:r},...n],label:r}),kn=[yo("suspensions","suspensionId","suspension"),yo("tires","tireModelId","tyre",[{key:"tiresRear",ref:"tireModelIdRear",label:"rear tyre"}]),yo("motors","motorModelId","motor"),yo("aeros","aeroModelId","aero map"),yo("batteries","batteryModelId","battery"),yo("brakes","brakeModelId","brakes"),yo("dampers","damperModelId","dampers",[{key:"dampersRear",ref:"damperModelIdRear",label:"rear dampers"},{key:"dampersHeave",ref:"heaveDamperModelId",label:"heave dampers"},{key:"dampersRoll",ref:"rollDamperModelId",label:"roll dampers"}])];function Gm(e){let t={...e};for(let r of kn)for(let n of r.refs)delete t[n];return t}var Km=vt,cc=Km,Wg=Km,Mn=[...vt.slice(3),...vt.slice(0,3)],Xg=[...vt.slice(1),vt[0]],jg=[...vt.slice(2),...vt.slice(0,2)],Ug=[...vt.slice(4),...vt.slice(0,4)],Qg=[...vt.slice(5),...vt.slice(0,5)],lc=[...vt.slice(2),...vt.slice(0,2)];function qg(){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 Zg(e,t,r){let n=_m[e];if(!n)throw new Error(`no preset vehicle named "${e}"`);return{id:t,params:{...ui(structuredClone(n)),energy:{...Dr},suspensionId:"sus1"},visible:!0,color:cc[r%cc.length]}}function _N(){return Eg.map((e,t)=>Zg(e,`v${t+1}`,t))}function NN(){return[Gs(),_f(),Nf(),Of(),Vf(),Bf(),$f(),Gf(),Kf(),Hf()].map((t,r)=>({id:`t${r+1}`,color:Wg[r%Wg.length],model:t}))}function ON(){return[hd(),bd(),gd(),yd(),xd(),Rd(),vd(),kd()].map((t,r)=>({id:`a${r+1}`,color:jg[r%jg.length],model:t}))}function VN(){return[ed(),td(),rd()].map((t,r)=>({id:`b${r+1}`,color:Ug[r%Ug.length],model:t}))}function BN(){return[{id:"brk1",color:Qg[0],model:structuredClone(ch)}]}function $N(){return[{id:"dmp1",color:lc[0],model:structuredClone(xu)}]}function GN(){return[Ng(),Og()].map((t,r)=>({id:`m${r+1}`,color:Mn[r%Mn.length],model:t}))}function Jg(e){let t=r=>({...r,provenance:Vm(r.model)});return{...e,suspensions:e.suspensions.map(t),vehicles:e.vehicles.map(r=>({...r,provenance:Vm(Gm(r.params))})),tires:e.tires.map(t),motors:e.motors.map(t),aeros:e.aeros.map(t),batteries:e.batteries.map(t),brakes:e.brakes.map(t),dampers:e.dampers.map(t)}}function uc(e="Untitled project"){let t=new Date().toISOString(),r=_N();return Jg({schemaVersion:wm,meta:{id:qg(),name:e,domain:"racecar",rulesetId:lo,createdAt:t,updatedAt:t},suspensions:[{id:"sus1",color:Xg[0],model:bo()}],activeSuspensionId:"sus1",vehicles:r,activeVehicleId:r[0]?.id??null,tires:NN(),motors:GN(),aeros:ON(),batteries:VN(),brakes:BN(),dampers:$N(),tracks:[],activeTrackId:null,mathChannels:[],rulesets:[],studies:[],activeStudyId:null,loadCases:[],reportLayouts:[],tyreSheets:[],kinSheets:[],plans:[],results:[],settings:{numerics:{...Fi},ggvMode:"twoTrack",quasiTransient:!1,motorThermal:!1,brakeFade:!1,airTempC:Ft,air:structuredClone(Tm),diffYaw:!1,lapCounts:{},pathPlanId:null,useRacingLine:!0,standingStart:!1}})}var KN=["front","rear"],e0=9.81,HN=Math.PI/180;var br="*",t0=40,AA=.8;function r0(e){let{s:t,curvature:r}=e;if(!t?.length||t.length!==r?.length)return null;let n=0,o=0,a=0,s=0;for(let i=0;i<t.length;i++){for(;a<t.length&&t[a]<=t[i]+2.5;)s+=Math.abs(r[a++]);for(;t[o]<t[i]-2.5;)s-=Math.abs(r[o++]);let c=s/Math.max(1,a-o);c>n&&(n=c)}return n>1e-6?1/n:null}function FA(e,t,r){let n=t.rows.map(c=>c.v),o=c=>mt(n,t.rows.map(l=>l.ayMax),Math.min(n[n.length-1],Math.max(n[0],c))),a=(c,l,u)=>({speedKmh:Math.round(c*36)/10,ayG:Math.round(l/e0*100)/100+0,axG:Math.round(u/e0*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(t0/3.6,o(t0/3.6),0);let c=10;for(let l=0;l<30;l++)c=Math.min(s,Math.sqrt(r*o(c)));return a(c,o(c),0)}case"fastCorner":return a(AA*s,o(AA*s),0);case"braking":{let c=i.reduce((l,u)=>t.axDecel(u,0)<t.axDecel(l,0)?u:l);return a(c,0,t.axDecel(c,0))}case"traction":{let c=i.reduce((l,u)=>t.axAccel(u,0)>t.axAccel(l,0)?u:l);return a(c,0,t.axAccel(c,0))}case"topSpeed":return a(s,0,0)}}function n0(e,t,r){let n=!1,o=e.map(a=>{if(!a.follows)return a;let s=FA(a.follows,t,r);return![s.speedKmh,s.ayG,s.axG].every(Number.isFinite)||!t.rows.some(i=>i.ayMax>0)||s.speedKmh===a.speedKmh&&s.ayG===a.ayG&&s.axG===a.axG?a:(n=!0,{...a,...s})});return n?o:e}function o0(e,t){let r=e.speedKmh/3.6,n=e.ayG*e0;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)/HN}var wA=e=>e.ayG<0?"L":"R";function a0(e,t=KN){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 s0=(e,t)=>e.travelMin===t.travelMin&&e.travelMax===t.travelMax&&e.rollMaxDeg===t.rollMaxDeg&&e.rollAtLimitDeg===t.rollAtLimitDeg;var jr=Math.PI/180,zN=9.81,mc=.1,i0=20,CA=6,DA=50;function TA(e,t,r){let n=e(0),o=0;for(let f=t;f<=r+1e-9;f+=t){let p=e(f);if(p>n)n=p,o=f;else if(f>o+3*t)break}let a=Math.max(0,o-t),s=Math.min(r,o+t),i=.6180339887498949,c=s-i*(s-a),l=a+i*(s-a),u=e(c),m=e(l);for(let f=0;f<14;f++)u>m?(s=l,l=c,m=u,c=s-i*(s-a),u=e(c)):(a=c,c=l,u=m,l=a+i*(s-a),m=e(l));return u>n?u>=m?{force:u,at:c}:{force:m,at:l}:m>n?{force:m,at:l}:{force:n,at:o}}function c0(e,t,r,n,o){let a=o*jr;if(t==="side")return TA(i=>r*e.Fy(r*i*jr,n,a),1,45);let s=t==="drive"?1:-1;return TA(i=>s*e.Fx(s*i,n,a),.02,.6)}function zm(e){let t=e?Bl(e)?.gamma:void 0,r=[t?.min,t?.max].filter(o=>o!==void 0&&Number.isFinite(o));if(!r.length)return{lo:-CA,hi:CA,stated:!1};let n=Math.max(...r.map(Math.abs))/jr;return{lo:-n,hi:n,stated:!0}}function YN(e,t,r){if(!(r>t))return t;let n=Math.max(2,Math.ceil(r-t)+1),o=(r-t)/(n-1),a=t,s=-1/0;for(let h=0;h<n;h++){let b=t+h*o,g=e(b);g>s&&(s=g,a=b)}let i=Math.max(t,a-o),c=Math.min(r,a+o),l=.6180339887498949,u=c-l*(c-i),m=i+l*(c-i),f=e(u),p=e(m);for(let h=0;h<12;h++)f>p?(c=m,m=u,p=f,u=c-l*(c-i),f=e(u)):(i=u,u=m,f=p,m=i+l*(c-i),p=e(m));let d=f>=p?{g:u,v:f}:{g:m,v:p};return d.v>s?d.g:a}var PA=250,LA=new WeakMap;function WN(e,t,r,n,o,a,s){let i=LA.get(e);i||LA.set(e,i=new Map);let c=`${t}|${n}|${o}|${s.lo}|${s.hi}`,l=i.get(c);l||i.set(c,l=new Map);let u=d=>{let h=l.get(d);if(h===void 0){let b=Math.max(50,d*PA);h=YN(g=>c0(r,n,o,b,g).force,s.lo,s.hi),l.set(d,h)}return h},m=Math.max(0,a)/PA,f=Math.floor(m),p=m-f;return p<1e-9?u(f):u(f)*(1-p)+u(f+1)*p}function Ka(e,t){return t==="front"?e.tireModel:e.tireModelRear??e.tireModel}var jN=new WeakMap,UN=new WeakMap,XN=new WeakMap,l0=(e,t,r)=>{let n=e.get(t);return n===void 0&&e.set(t,n=r()),n};function Ym(e,t){let r=Ka(e,t);return r?l0(jN,r,()=>Is(r))?null:"This tyre\u2019s side force does not change with camber, so it wants no camber.":"The car runs the built-in simple tyre, which has no camber term."}function u0(e,t){let r=Ka(e,t);return r?l0(XN,r,()=>$l(r).none)?"This tyre file has no drive or brake grip.":l0(UN,r,()=>{let n=Pe(r),o=r.kind==="magic"?r.fnomin:r.nominalLoad,a=n.Fx(.1,o,0),s=n.Fx(.1,o,3*jr);return Number.isFinite(a)&&Number.isFinite(s)&&Math.abs(s-a)>1})?null:"This tyre\u2019s drive and brake grip does not change with camber.":"The car runs the built-in simple tyre, which has no camber term."}function xo(e,t){return e==="side"||e==="ackermann"?Math.abs(t.ayG)>=mc?e==="ackermann"&&!(EA(t)<=i0)?`is a corner wider than ${i0} m`:null:"does not corner":(e==="drive"?t.axG:-t.axG)>=mc?null:e==="drive"?"does not drive":"does not brake"}var QN=e=>e.axG>=mc?"drive":e.axG<=-mc?"brake":null;function EA(e){let t=e.speedKmh/3.6,r=Math.abs(e.ayG)*zN;return r>1e-9?t*t/r:1/0}var Hm=(e,t)=>`${e==="front"?"F":"R"}${t}`,qN=e=>e==="L"?"R":"L",ZN=(e,t,r)=>Math.min(r,Math.max(t,e));function m0({ev:e,params:t,input:r,state:n,pose:o}){let a=`${q(t,"grip_scale")}|${q(t,"stiffness_scale")}`,s=EA(n),i=r.wheelbase*(1-r.frontMassFrac)/1e3,c=r.wheelbase*r.frontMassFrac/1e3,l=r.wheelbase/1e3,u=k=>(k==="front"?r.trackFront:r.trackRear)/2e3,m=(k,v,x,M,F)=>{let w=ge(e,k),C=Ka(t,k),T=Math.max(0,o.loads[v]),S=o.camber[v],A=ZN(S,F.lo,F.hi),P=c0(w,x,M,T,A),L=T<DA,D=C&&!L?WN(C,a,w,x,M,T,F):A,E=L?P.force:c0(w,x,M,T,D).force,V=.05;return{corner:v,Fz:T,lifted:L,camber:S,read:A,outside:A!==S,wants:D,atEdge:!L&&(D-F.lo<V||F.hi-D<V),peak:P.force,slip:P.at,best:E}},f=(k,v,x)=>{let M=v[0].best+v[1].best,F=v[0].peak+v[1].peak;return{kind:k,wheels:v,lossCamber:M>0?Math.max(0,1-F/M):NaN,range:x}},p=new Map,d=k=>{if(p.has(k))return p.get(k)??null;let v=null;if(!xo("side",n)){let x=zm(Ka(t,k));v=[m(k,Hm(k,o.outer),"side",1,x),m(k,Hm(k,qN(o.outer)),"side",-1,x)]}return p.set(k,v),v},h=new Map,b=new Map,g=new Map,y=(k,v,x)=>{let M=k==="front"?i:-c,F=(v?1:-1)*u(k),w=x*jr;return Math.atan2(M+s*Math.sin(w),s*Math.cos(w)-F)/jr},R=k=>(n.ayG<0?-1:1)*o.steer[k];return{side(k){if(h.has(k))return h.get(k)??null;let v=Ym(t,k)?null:d(k),x=v?f("side",v,zm(Ka(t,k))):null;return h.set(k,x),x},long(k){if(b.has(k))return b.get(k)??null;let v=QN(n),x=null;if(v&&!u0(t,k)){let M=zm(Ka(t,k));x=f(v,[m(k,Hm(k,"L"),v,1,M),m(k,Hm(k,"R"),v,1,M)],M)}return b.set(k,x),x},toeLoss(k){let v=g.get(k);if(v!==void 0)return v;let x=d(k),M=NaN;if(x&&x[0].peak+x[1].peak>0){let F=ge(e,k),[w,C]=x,T=[{g:w,dt:1,inner:!1,steer:R(w.corner)},{g:C,dt:-1,inner:!0,steer:R(C.corner)}],S=E=>T.reduce((V,N)=>{let z=N.steer-y(k,N.inner,E);return V+N.dt*F.Fy(N.dt*z*jr,N.g.Fz,N.g.read*jr)},0),A=T.map(E=>E.steer-E.g.slip-y(k,E.inner,0)),P=Math.min(...A)-2,L=Math.max(...A)+2,D=JN(S,P,L,.25);M=Math.max(0,1-D/(w.peak+C.peak))}return g.set(k,M),M},ackermann(){if(xo("ackermann",n))return NaN;let k=d("front");if(!k||k[0].lifted||k[1].lifted)return NaN;let[v,x]=k,M=Math.sqrt(Math.max(s*s-c*c,1e-6)),F=u("front"),w=(Math.atan(l/(M-F))-Math.atan(l/(M+F)))/jr;if(!(w>.001))return NaN;let C=R(x.corner)-R(v.corner),T=w+(x.slip-v.slip);return 100*(C-T)/w}}}function JN(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 eO=9.81,IA=Math.PI/180,pc={speed:20,ayG:1.2};function p0(e,t={}){let r=t.operating??pc,n=t.assemble,o,a,s,i=new Map,c=new Map,l=new Map,u=new Map,m=new Map,f=v=>({speed:v?.speed!==void 0&&Number.isFinite(v.speed)&&v.speed>0?v.speed:r.speed,ayG:v?.ayG!==void 0&&Number.isFinite(v.ayG)?v.ayG:r.ayG}),p=()=>{if(o!==void 0)return o;if(!n)return o=null;try{o=n(e)}catch{o=null}return o},d=()=>{if(a!==void 0)return a;try{a=mr(e.params)}catch{a=null}return a},h=v=>{let x=f(v),M=`${x.speed}|${x.ayG}`,F=i.get(M);if(F!==void 0)return F;let w=d();if(!w)return i.set(M,null),null;let C={cornerStiffness:T=>w.corneringStiffness(T),ayG:x.ayG,speed:x.speed,fyAxle:(T,S)=>2*w.Fy(T,S/2),tire:w};return i.set(M,C),C},b=()=>{if(s!==void 0)return s;let v=p(),x=d();if(!v||!x)return s=null;try{s=jn(x,v.massTotal*eO*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=ob(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=o0(v,w.wheelbase),A=v.speedKmh/3.6,P=ln(w,C,T,A)(v.ayG,v.axG,0,S),L={FL:P.FL.travel,FR:P.FR.travel},D=Xn(w,S*IA,L),E=S?D.camber:null,V={},N={};for(let I of["FL","FR","RL","RR"]){let _=I[1]==="R"?P[I].camberRoad:0-P[I].camberRoad;V[I]=_+(E?.[I]??0),N[I]=D.steer[I]/IA+(I[1]==="R"?1:-1)*P[I].bumpToe}let z=Ce(w,v.ayG,v.axG,A,0,S,L,P.steeringJacking);F={corners:P,rollDeg:P.FL.camberRoad-P.FL.camber,steerDeg:S,camber:V,outer:wA(v),loads:z,steer:N}}}catch{F=null}return m.set(x,F),F},R=new Map;return{operating:r,dynAvailable:!!n,poseAt:y,tyreAt:v=>{let x=`${v.speedKmh}|${v.ayG}|${v.axG}`,M=R.get(x);if(M!==void 0)return M;let F=y(v),w=p(),C=d(),T=F&&w&&C?m0({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?_b(F):null;return l.set(x,w),w},reserves:(v,x)=>{let M=f(x),F=`${v}|${M.speed}|${M.ayG}`,w=u.get(F);if(w!==void 0)return w;let C=p(),T=h(x),S=null;if(C&&T)try{S=Di(C,T,v,b()??void 0)}catch{S=null}return u.set(F,S),S}}}var _A=["widthLeft","widthRight","bank","mu"];function dc(e){let t=e.x.length,r=new Array(t).fill(0);for(let n=1;n<t;n++)r[n]=r[n-1]+Math.hypot(e.x[n]-e.x[n-1],e.y[n]-e.y[n-1]);return r}function d0(e){let t=dc(e),r=e.x.length;return r===0?0:e.closed===!1||r<2?t[r-1]:t[r-1]+Math.hypot(e.x[0]-e.x[r-1],e.y[0]-e.y[r-1])}function jm(e,t,r,n={}){let o=t.length,a=l=>{let u=n[l];return u&&u.length===o?u.slice():new Array(o).fill(r[l])},s={widthLeft:a("widthLeft"),widthRight:a("widthRight"),bank:a("bank"),mu:a("mu")};if(!e.length)return s;let i=[...e].sort((l,u)=>l.from-u.from),c=o?t[o-1]:0;for(let l of i){if(!(l.to>l.from))continue;let u=Math.max(0,l.ramp??0),m=l.to>=c-1e-9;for(let f of _A){let p=l[f];if(p===void 0)continue;let d=s[f],h=r[f];for(let b=0;b<o&&t[b]<l.from;b++)h=d[b];for(let b=0;b<o;b++){let g=t[b];if(g<l.from||g>=l.to&&!(m&&g>=c-1e-9))continue;let y=g-l.from;d[b]=u>0&&y<u?h+(p-h)*(y/u):p}}}return s}function Um(e,t,r){if(!t.length)return e;let n=dc(e),o=n.length,a={widthLeft:Wm(e.widthLeft,r.widthLeft),widthRight:Wm(e.widthRight,r.widthRight),bank:Wm(e.bank,r.bank),mu:Wm(e.mu,r.mu)},s={};for(let c of _A){let l=e[c];Array.isArray(l)&&l.length===o&&(s[c]=l)}let i=jm(t,n,a,s);return{...e,...i}}function Wm(e,t){return typeof e=="number"?e:t}var VA=1,NA=4,Qm=Math.PI/180,f0=e=>e===null||!Number.isFinite(e)||e===0?0:1/e;function h0(e){return e.kind==="arc"?Math.abs(e.radius)*Math.abs(e.angle)*Qm:e.length}function Xm(e,t){return e.kind==="straight"?0:e.kind==="arc"?f0(e.radius):t}function OA(e){return e.kind==="straight"?0:e.kind==="arc"?f0(e.radius):f0(e.endRadius)}var fc=(e,t,r,n,o)=>e+t*o+(n>0?(r-t)*o*o/(2*n):0);function hc(e,t={}){let r=Math.max(.05,t.spacing??VA),n=t.closed!==!1,o=t.start??{x:0,y:0,heading:0},a=t.base??{widthLeft:1.5,widthRight:1.5,bank:0,mu:1},s=[],i=[],c=[],l=[],u=e.reduce((S,A)=>S+h0(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*Qm,b=e.length?Xm(e[0],0):0,g=0,y=f,R=(S,A,P)=>{s.push(S),i.push(A),c.push(P)};R(p,d,0);let k=(S,A,P,L,D)=>{let E=D-L;if(E<=0)return;if(Math.abs(A-S)<1e-12){let N=fc(h,S,S,P,L);if(Math.abs(S)<1e-12)p+=E*Math.cos(N),d+=E*Math.sin(N);else{let z=N+S*E;p+=(Math.sin(z)-Math.sin(N))/S,d+=-(Math.cos(z)-Math.cos(N))/S}return}let V=E/NA;for(let N=0;N<NA;N++){let z=L+N*V,I=fc(h,S,A,P,z),_=fc(h,S,A,P,z+V/2),B=fc(h,S,A,P,z+V);p+=V/6*(Math.cos(I)+4*Math.cos(_)+Math.cos(B)),d+=V/6*(Math.sin(I)+4*Math.sin(_)+Math.sin(B))}};for(let S of e){let A=h0(S),P=Xm(S,b),L=OA(S);if(l.push({from:g,to:g+A,...S.widthLeft!==void 0?{widthLeft:S.widthLeft}:{},...S.widthRight!==void 0?{widthRight:S.widthRight}:{},...S.bank!==void 0?{bank:S.bank}:{},...S.mu!==void 0?{mu:S.mu}:{},...S.ramp!==void 0?{ramp:S.ramp}:{}}),A<=0){b=L;continue}let D=0;for(;y<=g+A+1e-9;){let E=Math.min(A,y-g);k(P,L,A,D,E),D=E,R(p,d,g+E),y+=f}k(P,L,A,D,A),h=fc(h,P,L,A,A),b=L,g+=A}let v=s.length>1?Math.hypot(s[0]-s[s.length-1],i[0]-i[i.length-1]):0,x=g;n&&s.length>1&&(s.pop(),i.pop(),c.pop());let M=e.length?Xm(e[0],b):0,F={gap:v,headingError:tO((h-o.heading*Qm)/Qm),curvatureError:b-M},w=[];for(let S=0;S<e.length;S++){let A=OA(e[S]),P=S+1<e.length?e[S+1]:n?e[0]:null;if(!P)continue;let L=Xm(P,A);w.push({index:S,before:A,after:L,jump:Math.abs(L-A)})}let C=jm(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 tO(e){let t=e%360;return t>180&&(t-=360),t<-180&&(t+=360),t}var rO={halfWidthM:1.5,spacingM:.5};function bc(e){switch(e.kind){case"skidpad":return`${e.radiusM.toFixed(2)} m constant-radius circle`;case"acceleration":return`${e.distanceM.toFixed(0)} m straight from rest`;case"slalom":return`${e.gates} gates at ${e.pitchM.toFixed(1)} m, \xB1${e.offsetM.toFixed(2)} m`;case"curves":{let t=e.segments.filter(r=>r.kind==="arc").length;return`${t} ${t===1?"curve":"curves"} over ${$A(e).toFixed(0)} m`}}}function $A(e){switch(e.kind){case"skidpad":return 2*Math.PI*e.radiusM;case"acceleration":return e.distanceM;case"slalom":return e.leadInM+Math.max(1,e.gates)*e.pitchM;case"curves":return e.segments.reduce((t,r)=>t+(r.kind==="arc"?Math.abs(r.angle)*Math.PI*Math.abs(r.radius)/180:r.length),0)}}var GA=e=>e.kind==="skidpad"||e.kind==="curves"&&e.closed===!0,KA=e=>e.kind==="acceleration",HA=1.5,zA=3;function nO(e,t){let r=e.offsetM,n=e.pitchM,o=Math.max(1,e.gates)*n,a=Math.max(0,e.leadInM),s=HA*n,i=h=>{let b=Math.min(1,Math.max(0,h));return b*b*b*(b*(b*6-15)+10)},c=h=>Math.min(i(h/s),i((o-h)/s)),l=r*(Math.PI/n)**2,u=l>0?Math.max(.05,Math.min(t.spacingM,1/l*(zA*Math.PI/180))):t.spacingM,m=[],f=[],p=Math.max(1,Math.round(a/u));for(let h=0;h<p;h++)m.push(-a+a*h/p),f.push(0);let d=Math.max(8,Math.round(o/u));for(let h=0;h<=d;h++){let b=o*h/d;m.push(b),f.push(r*c(b)*Math.sin(Math.PI*b/n))}return{name:bc(e),x:m,y:f,closed:!1,widthLeft:t.halfWidthM,widthRight:t.halfWidthM,fit:"interpolate"}}function oO(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 b0(e,t={}){let r={...rO,...t},n=KA(e),o=oO(e);if(!o){let u=nO(e,r);return{asset:u,peakCurvature:BA(u),worstJoint:0,standingStart:n}}let a=GA(e),s=o.reduce((u,m)=>m.kind==="arc"?Math.min(u,Math.abs(m.radius)):u,1/0),i=Number.isFinite(s)?Math.max(.05,Math.min(r.spacingM,s*(zA*Math.PI/180))):r.spacingM,c=hc(o,{name:bc(e),spacing:i,closed:a,base:{widthLeft:r.halfWidthM,widthRight:r.halfWidthM,bank:0,mu:1}}),l=a?c.joints:c.joints.filter(u=>u.index<o.length-1);return{asset:c.asset,peakCurvature:BA(c.asset),worstJoint:l.reduce((u,m)=>Math.max(u,m.jump),0),standingStart:n}}function BA(e){try{return Math.max(...it(e).curvature.map(Math.abs))}catch{return NaN}}var Zm={courses:[{id:"c1",course:{kind:"manoeuvre",spec:{kind:"skidpad",radiusM:8.375}}}],ggvMode:"twoTrack"};function g0(e){return e.course.kind==="project"?"the project\u2019s track":e.course.kind==="track"?e.course.name:bc(e.course.spec)}var YA=new WeakMap,qm=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=qm.get(n);if(o)return{...o,numerics:r};let a=b0(e.spec),s={asset:a.asset,standingStart:a.standingStart};return qm.size>64&&qm.clear(),qm.set(n,s),{...s,numerics:r}}function y0(e,t,r={}){let n=r.lap??Zm,o=r.simParams,a=r.numerics??{},s=n.courses.length?n.courses:Zm.courses,i,c,l,u=new Map,m=new Map,f=new Map,p=new Map,d=k=>(k?.courseId?s.find(v=>v.id===k.courseId):void 0)??s[0],h=()=>{if(i!==void 0)return i;if(!o)return i=null;try{i={...o(e),ggvMode:n.ggvMode}}catch{i=null}return i},b=k=>{let v=d(k);if(!v)return null;let x=m.get(v.id);if(x!==void 0)return x;let M=WA(v.course,r,a),F=null;if(M)try{let w=JSON.stringify(M.numerics),C=YA.get(M.asset);C||(C=new Map,YA.set(M.asset,C));let T=C.get(w);T||(T=it(M.asset,M.numerics),C.set(w,T)),F={id:v.id,track:T,standingStart:M.standingStart,numerics:M.numerics,name:M.asset.name}}catch{F=null}return m.set(v.id,F),F},g=()=>{if(c!==void 0)return c;let k=h();if(!k)return c=null;try{l=wt(k),c=pr(l,!1,n.ggvMode)}catch{c=null}return c},y=k=>{let v=b(k);if(!v)return null;let x=f.get(v.id);if(x!==void 0)return x;let M=g(),F=null;if(M)try{let w=l?ao(l,M,[v.track],v.numerics,n.ggvMode,u):void 0,C=l?xn(l,M.rows):void 0;F=Rt(M,v.track,v.numerics,{standingStart:v.standingStart,...w?{load:w}:{},...C?{shifts:C}:{}})}catch{F=null}return f.set(v.id,F),F};return{lapSettings:n,get lapAvailable(){return!!o&&s.some(k=>!!WA(k.course,r,a))},lapParams:h,courses:()=>s,course:b,ggv:g,lap:y,lapReserve:k=>{let v=b(k);if(!v)return null;let x=p.get(v.id);if(x!==void 0)return x;let M=y(k),F=t.dynInput(),w=t.tyre(),C=null;if(M&&F&&w)try{let T=h();C=nm(F,w,{v:M.v,ax:M.ax,ay:M.ay,ds:v.track.ds,axDrag:Ea(g()?.rows,M.v),...M.axScrub?{axScrub:M.axScrub}:{},axGrade:yn(v.track.gradient,M.v.length),bank:v.track.bank,...M.loadFactor?{loadFactor:M.loadFactor}:{}},T?{driven:Mh(T)}:{})}catch{C=null}return p.set(v.id,C),C}}}var jA=180/Math.PI,x0={rise:0,sinPitch:0,sinRoll:0};function UA(e){let t=e.kc;return t?XA(e.vehicle,r=>t.ground0[r]):x0}function XA(e,t){let r=e.config,n=nn(r),o=0,a=0,s=0,i=0,c=0,l=0,u=0,m=0,f=0;for(let g of er){let y=Ze(g,r),R=y.axleX-n,k=y.sideSign*Nt(e,y.isFront)/2,v=t(g);if(!Number.isFinite(v))return x0;o++,a+=R,s+=k,i+=v,c+=R*R,l+=k*k,u+=R*k,m+=R*v,f+=k*v}let p=o*(c*l-u*u)-a*(a*l-u*s)+s*(a*u-c*s);if(!(Math.abs(p)>1e-9))return{rise:i/o,sinPitch:0,sinRoll:0};let d=(i*(c*l-u*u)-a*(m*l-u*f)+s*(m*u-c*f))/p,h=(o*(m*l-u*f)-i*(a*l-u*s)+s*(a*f-m*s))/p,b=(o*(c*f-m*u)-a*(a*f-m*s)+i*(a*u-c*s))/p;return{rise:d,sinPitch:h,sinRoll:-b}}function gc(e,t){let r=e.kc,n=XA(e.vehicle,o=>(r?r.ground0[o]:0)+t[o]);return Q([-n.sinPitch,n.sinRoll,1])}function R0(e,t,r,n){let o=Q(rn(e,Ze(t,r)));return-Math.asin(Math.max(-1,Math.min(1,X(o,n))))*jA}function Jm(e,t,r,n,o){let a=Q(rn(n,Ze(t,r))),s=Q([1-a[0]*a[0],-a[0]*a[1],-a[0]*a[2]]),i=ae(a,s),c=p=>[X(p,s),X(p,i),X(p,a)],l=p=>ee(ee(U(s,p[0]),U(i,p[1])),U(a,p[2])),u=e.points,m=c(u.spinAxis),f=ms({uprightUpper:c(u.uprightUpper),uprightLower:c(u.uprightLower),wheelCenter:c(u.wheelCenter),spinAxis:m,tieOuter:c(u.tieOuter),loadedRadius:o.loadedRadius,patchShift:o.patchShift&&aO(o.patchShift,e.metrics.toe/jA,Math.atan2(m[0],m[1]))});return{caster:f.caster,kpi:f.kpi,scrubRadius:f.scrubRadius,mechanicalTrail:f.mechanicalTrail,scrubAtWheel:f.scrubAtWheel,trailAtWheel:f.trailAtWheel,kingpinOffset:f.kingpinOffset,casterOffset:f.casterOffset,kingpinGround:l(f.kingpinGround),contactPatch:l(f.contactPatch),elbow:l([f.contactPatch[0],f.kingpinGround[1],f.kingpinGround[2]]),kingpinAtHub:l(f.kingpinAtHub)}}function aO(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 ep(e,t){let r=UA(t);if(r===x0)return e;let n=o=>Math.max(-1,Math.min(1,o));return{...e,heave:e.heave-r.rise,pitch:Math.asin(n(Math.sin(e.pitch)-r.sinPitch)),roll:Math.asin(n(Math.sin(e.roll)-r.sinRoll))}}function Ha(e,t,r){let n=ep({heave:0,pitch:0,roll:0,steer:0},r);return e-Nd(n,[t,0,0],nn(r.vehicle.config))}var sO=180/Math.PI;function v0(e,t){return!e.valid||!e.ic?!1:Math.hypot(e.ic[0]-e.cp[0],e.ic[1]-e.cp[1])<=t}function tp(e,t,r){let n=Ze(t,e.vehicle.config),o=gt(e,r),a=Au(e,t,o[t]),s=a.at("uprightUpper"),i=a.at("uprightLower"),c=a.at("contactPatch"),l=a.at("wheelCenter"),u=A=>{let P=a.velocity(A);return[P[0],P[2]]},m=u(c),f=u(l),p=[c[0],c[2]],d=[l[0],l[2]];if(!a.solved)return{ic:null,line:null,cp:p,wc:d,road:[1,0],swingArmAngleDeg:NaN,tanTheta:NaN,tanThetaHub:NaN,valid:!1,unsolved:!0,sinAngle:0};let h=gc(e,{FL:o.FL.ground,FR:o.FR.ground,RL:o.RL.ground,RR:o.RR.ground}),b=Math.hypot(h[0],h[2]),g=[h[0]/b,h[2]/b],y=[g[1],-g[0]],R=A=>{let P=A[0]*g[0]+A[1]*g[1];return Math.abs(P)>1e-9?-(A[0]*y[0]+A[1]*y[1])/P:0},k=a.omega[1],v=Math.hypot(m[0],m[1]),x=Math.abs(k)*1e9>v?[p[0]+m[1]/k,p[1]-m[0]/k]:null,F=x?(A=>{let P=[s[0]-A[0],s[2]-A[1]],L=[i[0]-A[0],i[2]-A[1]];return Math.abs(P[0]*L[1]-P[1]*L[0])/(Math.hypot(...P)*Math.hypot(...L))})(x):0;if(!(Math.abs(m[0]*g[0]+m[1]*g[1])>1e-9))return{ic:x,line:null,cp:p,wc:d,road:y,swingArmAngleDeg:0,tanTheta:0,tanThetaHub:0,valid:!1,sinAngle:F};let w=[m[1]/v,-m[0]/v],C=x?[x[0]-p[0],x[1]-p[1]]:[n.isFront?-1:1,0],T=w[0]*C[0]+w[1]*C[1]<0?[-w[0],-w[1]]:w,S=R(m);return{ic:x,line:T,cp:p,wc:d,road:y,swingArmAngleDeg:Math.atan(S)*sO,tanTheta:S,tanThetaHub:R(f),valid:!0,sinAngle:F}}function QA(e,t,r,n){let o=r/Math.max(1e-6,n.cgHeight),a=t==="front",s=a?n.drive.front:1-n.drive.front,i=a?n.brakeBalanceFront:1-n.brakeBalanceFront,c=(a?n.drive.inboard.front:n.drive.inboard.rear)?e.tanThetaHub:e.tanTheta,l=(a?n.brakeInboard?.front:n.brakeInboard?.rear)?e.tanThetaHub:e.tanTheta,u=a?-1:1;return{brake:u*100*l*o*i,drive:u*100*c*o*s}}var cO=180/Math.PI,lO=Math.PI/180,k0=.5,rp=2,M0=.25,uO={heave:0,pitch:0,roll:0,steer:0},mO={FL:"FR",FR:"FL",RL:"RR",RR:"RL"},np=e=>e.ok?e.state:{...e.nearest,converged:!1};function S0(e,t,r){return t.state?t.solved===!1?{...t.state,converged:!1}:t.state:np(ye(e,t.travel,t.steer,void 0,r))}var qA=new WeakMap;function ZA(e,t){let r=e.ctx[t],n=Ge(e.vehicle,t).config.loadedRadius,o=rr(n,e.kc,t),a=qA.get(r);a||(a=new Map,qA.set(r,a));let s=a.get(o);if(!s){let i=on(t,e.vehicle.config,uO,e.vehicle);s=np(ye(r,i.travel,i.steer,void 0,o===n?void 0:{loadedRadius:o})),a.set(o,s)}return s}var gr=(e,t)=>!e||!e.lo.converged||!e.hi.converged?NaN:(t(e.hi)-t(e.lo))/(2*e.step),JA=(e,t,r)=>{if(!e||!e.lo.converged||!e.hi.converged)return NaN;let n=r(e.hi)-r(e.lo);return Math.abs(n)<1e-9?NaN:(t(e.hi)-t(e.lo))/n};function tF(e,t,r,n,o){let a=e.vehicle.config,s=Ko(r),i=Ge(e.vehicle,r),c=Ze(r,a),l=e.ctx[r],u=gt(e,t),m=u[r],f={travel:m.travel,steer:m.steer},p=m.rigid?void 0:{loadedRadius:m.loadedRadius},d=S0(l,m,p),h=ZA(e,r),b={lo:np(ye(l,f.travel-k0,f.steer,void 0,p)),hi:np(ye(l,f.travel+k0,f.steer,void 0,p)),step:k0},g=c.isFront?{lo:Ie(l,d.beta,f.steer-rp,void 0,p),hi:Ie(l,d.beta,f.steer+rp,void 0,p),step:rp}:null,y=Y=>{let j=gt(e,{...t,roll:t.roll+Y*lO})[r];return S0(l,j,j.rigid?void 0:{loadedRadius:j.loadedRadius})},R={lo:y(-M0),hi:y(M0),step:M0},k=dO(e,t,r,c.isFront,u,g),v=Ot(d.points.contactPatch,c),x=Ot(h.points.contactPatch,c),M=Math.abs(v[1])-Math.abs(x[1]),F=mO[r],w=u[F],C=S0(e.ctx[F],w,w.rigid?void 0:{loadedRadius:w.loadedRadius}),T=C.converged?M+Math.abs(C.points.contactPatch[1])-Math.abs(ZA(e,F).points.contactPatch[1]):NaN,S=o??lr(e,t,s),A=Fu(S,bt(i)),P=A?null:Mk(S),L=c.sideSign>0?S.icRight:S.icLeft,D=L?Math.hypot(L[0]-v[1],L[1]-v[2]):1/0,E=tp(e,r,t),V=E.ic?Math.hypot(E.ic[0]-E.cp[0],E.ic[1]-E.cp[1]):1/0,N=QA(E,s,a.wheelbase,n),z=-gr(b,Y=>Y.points.damperLength),I=i.config.springRate,_=gr(R,Y=>Y.metrics.camber),B=gc(e,{FL:u.FL.ground,FR:u.FR.ground,RL:u.RL.ground,RR:u.RR.ground}),O=e.kc?.loadCase,G=Y=>O?Jm(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:R0(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:gr(b,Y=>Y.metrics.camber),bumpSteer:gr(b,Y=>Y.metrics.toe),trackScrubRate:gr(b,Y=>Math.abs(Ot(Y.points.contactPatch,c)[1])),casterGain:gr(b,Y=>G(Y).caster),kpiGain:gr(b,Y=>G(Y).kpi),scrubGain:gr(b,Y=>G(Y).scrubRadius),trailGain:gr(b,Y=>G(Y).mechanicalTrail),...c.isFront?{camberPerSteer:JA(g,Y=>Y.metrics.camber,Y=>Y.metrics.toe),steerJacking:-JA(g,Y=>Y.points.contactPatch[2],Y=>Y.metrics.toe),...k!==void 0?{steerLoad:k}:{}}:{},rollCamber:_,camberRecovery:-100*c.sideSign*_,rollSteer:c.sideSign*gr(R,Y=>Y.metrics.toe),halfTrackChange:M,trackChange:T,longitudinal:v[0]-x[0],rollCentreHeight:P?P.heightAboveGround:S.heightAboveGround,rollCentreHeightChassis:(P?P.height:S.height)-Ha(0,c.axleX,e),rollCentreLateral:S.lateralAlongGround,rollCentreValid:S.valid,rollCentreUsable:A,rollCentreHeightUsable:A||P!==null,rollCentreSinAngle:S.sinAngle,fvsaLength:D,svsaLength:V,swingArmAngle:E.swingArmAngleDeg,svsaUsable:v0(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,...pO(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)*cO,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 pO(e,t,r,n){if(e.config.actuation==="decoupled")return{};let o=n?{droop:n.droopStated?n.droop:null,bump:n.bump}:zo(t,e.config.coilover),a=t-r;return{...o.droop!==null?{damperToExtended:a-o.droop}:{},...o.bump!==null?{damperToClosed:o.bump-a}:{}}}function dO(e,t,r,n,o,a){if(!a||!n)return;let s=bl(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)*rp,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]=Mr(i.curve[b],g.travel,w.points.damperLength)-Mr(i.curve[b],g.travel,F.points.damperLength),m.lo.push(F),m.hi.push(w),b===r&&(f=w.metrics.toe-F.metrics.toe)}let p=i.elements?.front;if(p){let h=[o.FL.travel,o.FR.travel],b=ks(p,h,[m.hi[0],m.hi[1]]),g=ks(p,h,[m.lo[0],m.lo[1]]);u[0]+=b[0]-g[0],u[1]+=b[1]-g[1]}return Math.abs(f)>1e-9?s([0,0],l,u)[r==="FL"?0:1]/f:NaN}function yc(e,t,r,n,o){return tF(e,t,r==="front"?"FL":"RL",n,o)}function A0(e,t,r,n){let o=yc(e,t,"front",r,n?.front),a=yc(e,t,"rear",r,n?.rear);return{front:o,rear:a,wheelbaseChange:o.longitudinal-a.longitudinal}}var op=Math.PI/180,xc={travelSteps:9,heaveSteps:5,rollSteps:4,rackSteps:6},ap={travelMin:-25,travelMax:25,rollMaxDeg:3,rollAtLimitDeg:2.5};function fO(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,...wh(t),drive:Sh(t)}}function rF(e,t){for(let r=1;r<e.length;r++){let n=3*t(r)+10;for(let o of["cpLeft","cpRight"]){let a=e[r-1][o],s=e[r][o];if(a&&s&&Math.hypot(s[0]-a[0],s[1]-a[1])>n)return r}}return-1}function F0(e,t=xc,r=ap,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=Tt(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=Tt(s)},m=S=>S==="front"?"FL":"RL",f=S=>{let A=u();if(!A.kc)return;let P=i(S).config.loadedRadius,L=rr(P,A.kc,m(S));return L===P?void 0:{loadedRadius:L}},p=(S,A)=>-Ms(u(),m(S),A),d=new Map,h=new Map,b=new Map,g=new Map,y=new Map,R=new Map,k=new Map,v=null,x=()=>{if(v)return v;u();let S=fO(e);return v=l!==null&&Number.isFinite(l)?{...S,cgHeight:l}:S},M,F,w=()=>{if(F!==void 0)return F;let S=kl(u().ctx.FL,Vt(s.front.config));return F=S?Ml(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,()=>Tf(i(S))??null),sweep:S=>C(d,S,()=>{let A;try{A=Ke(i(S),{travelMin:r.travelMin,travelMax:r.travelMax,steps:t.travelSteps})}catch{return a(500,`the ${S} travel sweep threw`)}if(!A.covered){let L=A.samples.map(V=>V.travel),D=Math.max(...L)-Math.min(...L),E=r.travelMax-r.travelMin;return a(Math.max(0,E-D),`the ${S} linkage reaches only ${D.toFixed(0)} mm of the ${E.toFixed(0)} mm travel range`)}if(A.fold)return a(200,`the ${S} travel(beta) folds \u2014 the suspension goes over centre in range`);let P=A.samples.filter(L=>!L.converged).length;if(P>0)return a(100+10*P,`${P} of ${A.samples.length} ${S} travel solves did not converge`);if(S==="front"&&i("front").config.steerMode==="rack"){let L=w();if(L)return a(L.violation,L.reason)}return A}),rcHeave:S=>C(b,S,()=>{let A=[],P=[],L=Math.max(2,t.heaveSteps);try{for(let E=0;E<L;E++){let V=r.travelMin+(r.travelMax-r.travelMin)*E/(L-1);A.push(V),P.push(lr(u(),{heave:p(S,V),pitch:0,roll:0,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in heave`)}let D=rF(P,E=>Math.abs(A[E]-A[E-1]));return D>0?a(300,`the ${S} roll-centre construction lands on another branch at ${A[D].toFixed(0)} mm of travel`):{at:A,rc:P}}),rcRoll:S=>C(g,S,()=>{let A=[],P=[],L=Math.max(2,t.rollSteps);try{for(let E=0;E<L;E++){let V=r.rollMaxDeg*E/(L-1);A.push(V),P.push(lr(u(),{heave:0,pitch:0,roll:V*op,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in roll`)}let D=rF(P,E=>Math.abs(P[E].cpLeft?.[0]??0)*Math.abs(A[E]-A[E-1])*op);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=uf(u(),{steerMax:Vt(s.front.config),steps:t.rackSteps})}catch{M=a(500,"the steering sweep threw")}let S=M?.filter(A=>!A.converged).length??0;if(M&&S>0){let A=w();M=A?a(A.violation,A.reason):a(100+10*S,`${S} of ${M.length} steering solves did not converge`)}return M??null},solveAt:(S,A,P=0)=>C(y,`${S}:${A}:${P}`,()=>{try{let L=ye(u().ctx[m(S)],A,P,void 0,f(S));return L.ok?L.state:L.why==="unconverged"?a(100,`the ${S} corner did not solve at ${A.toFixed(0)} mm of travel`):a(100+Math.abs(L.travelMiss),`the ${S} corner reaches only ${(A+L.travelMiss).toFixed(0)} of ${A.toFixed(0)} mm of travel`)}catch{return a(150,`the ${S} corner solve threw at ${A.toFixed(0)} mm of travel`)}}),readout:S=>C(R,`${S.heave}:${S.pitch}:${S.roll}:${S.steer}`,()=>{try{return A0(u(),S,x())}catch{return a(500,"the derived readout threw")}}),readoutAtTravel:(S,A)=>C(k,`${S}:${A}`,()=>{try{return yc(u(),{heave:p(S,A),pitch:0,roll:0,steer:0},S,x())}catch{return a(500,`the ${S} readout threw at ${A.toFixed(0)} mm of travel`)}}),travelAtRoll:(S,A)=>{let P=i(S).hardpoints.wheelCenter[1]*Math.sin(A*op),L=u();if(!L.kc)return P;try{let D=gt(L,{heave:0,pitch:0,roll:A*op,steer:0}),E=S==="front"?Math.max(D.FL.travel,D.FR.travel):Math.max(D.RL.travel,D.RR.travel);return Number.isFinite(E)?E:P}catch{return a(500,`the ${S} axle could not be rolled on its tyre`),P}},onTyre:()=>!!u().kc,contexts:u}}var hO=gg();function w0(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=ym(n,a.rulesets),i=s?.events.some(c=>c.kind==="trackLap");if(s&&(a.track||!i)){let c=t.sessionParams(e),{standingStart:l,lapCounts:u}=a.settings,m=a.track?Zi([c],a.track,a.numerics,ji(s),a.settings,hO)[0]:Vi(c,s,{numerics:a.numerics,standingStart:l,lapCounts:u});o={};for(let f of s.metrics)zc(f)&&(o[f.key]=f.value(m,void 0))}}catch{o=null}return r.set(n,o),o}}}var sp=.01;function bO(e,t){return t.bump!==null&&e>t.bump-sp?{at:"closed",past:Math.max(0,e-t.bump)}:t.droopStated&&e<t.droop+sp?{at:"toppedOut",past:Math.max(0,t.droop-e)}:t.seat!==null&&e<t.seat+sp?{at:"unseated",past:Math.max(0,t.seat-e)}:{at:"free",past:0}}var nF=e=>({droop:e.droop,droopStated:e.droopStated,bump:e.bump,seat:e.holdsLoad&&Number.isFinite(e.free)?e.free:null}),gO=[["front","FL","FR"],["rear","RL","RR"]];function T0(e,t){let r=[];for(let[n,o,a]of gO){let s=[t[o],t[a]];for(let m of[o,a]){let f=e.curve[m],p=f.spring?.law;if(!f.spring||!p)continue;let d=Hd(f,t[m]);d===null||!Number.isFinite(d)||r.push(C0(m,n,n,d,f.spring.length0-d,nF(p),!0))}let i=e.elements?.[n];if(!i)continue;let c=i.heave?.law;if(c){let m=gR(i,s),f=i.read.heave?.span0,p=n==="front"?"heaveFront":"heaveRear";r.push(C0(p,p,n,m,f!==void 0?f-m:null,nF(c),i.carriesLoad))}let l=i.rollStop,u=l?yR(i,s):null;if(l&&u!==null){let m=l.length0-u,f=n==="front"?"rollFront":"rollRear",p={droop:l.droop??-1/0,droopStated:l.droop!==null,bump:l.bump,seat:null};r.push(C0(f,f,n,m,u,p,i.carriesLoad))}}return r}function C0(e,t,r,n,o,a,s){return{damper:e,place:t,axle:r,length:o,compression:n,toToppedOut:a.droopStated?n-a.droop:null,toClosed:a.bump!==null?a.bump-n:null,...bO(n,a),bumpStated:a.bump!==null,bounds:s}}function oF(e,t){let r=t.vehicle.config;return e.map(n=>{let o=n.axle==="front"?r.frontAxleX:r.frontAxleX-r.wheelbase,a=o+Math.min(n.xMin,n.xMax),s=o+Math.max(n.xMin,n.xMax),i=(a+s)/2;return{...n,min:[a,Math.min(n.yMin,n.yMax),Ha(Math.min(n.zMin,n.zMax),i,t)],max:[s,Math.max(n.yMin,n.yMax),Ha(Math.max(n.zMin,n.zMax),i,t)]}})}var yO=(e,t)=>[e[0]+t[0],e[1]+t[1],e[2]+t[2]],xO=(e,t)=>[e[0]*t,e[1]*t,e[2]*t];var RO=(e,t,r)=>e.z0+e.dzdx*t+e.dzdy*r;function vO(e,t){let r=Math.sin(e.pitch);return{z0:-e.heave+t*r,dzdx:-r,dzdy:Math.sin(e.roll)}}function aF(e){return vO(ep({heave:0,pitch:0,roll:0,steer:0},e),nn(e.vehicle.config))}function kO(e,t){let r=[];for(let c of[e.min[0],e.max[0]])for(let l of[e.min[1],e.max[1]])r.push([c,l,e.min[2]]);let n=r.map(t),o=Math.min(...n),a=r.filter((c,l)=>n[l]<=o+.5),s=new Set(a.map(c=>c[0])),i=new Set(a.map(c=>c[1]));return{height:o,lowest:{x:s.size>1||e.min[0]===e.max[0]?null:a[0][0]===e.max[0]?"front":"rear",y:i.size>1||e.min[1]===e.max[1]?null:a[0][1]===e.max[1]?"right":"left"},at:xO(a.reduce((c,l)=>yO(c,l),[0,0,0]),1/a.length)}}function sF(e,t){return{...kO(e,r=>r[2]-RO(t,r[0],r[1])),road:t}}function iF(e,t){let r=(a,s,i)=>a[0]*(s[1]*i[2]-s[2]*i[1])-a[1]*(s[0]*i[2]-s[2]*i[0])+a[2]*(s[0]*i[1]-s[1]*i[0]),n=r(e[0],e[1],e[2]);if(Math.abs(n)<1e-12)return null;let o=a=>e.map((s,i)=>s.map((c,l)=>l===a?t[i]:c));return[r(...o(0))/n,r(...o(1))/n,r(...o(2))/n]}var uF=Math.PI/180;function P0(e,t,r,n){let o=t.speedKmh/3.6,a=Ad(e,o,t.axG,Jr(e,t.ayG,0));if(!a||!e.aero)return null;let s=e.wheelbase,i=$o(e.aero,s),c=(h,b)=>Math.atan((b-h)/s)/uF,l={},u={};for(let h of er)l[h]=r.corners[h].travel,u[h]=r.corners[h].ground;let m=n.kc?T0(n.kc,l):[],f=e.aero.model,p=a.downFront+a.downRear,d=f?{balance:Math.abs(p)>1e-9?100*a.downFront/p:NaN,clA:(a.clFront+a.clRear)*a.area,cdA:a.cd*a.area,loopMargin:1-a.gain,dataMargin:mF(f,s,a.hFront,a.hRear)}:null;return{front:{height:a.hFront,...cF(m,"front")},rear:{height:a.hRear,...cF(m,"rear")},rakeDeg:c(a.hFront,a.hRear),pitchDeg:c(a.hFront,a.hRear)-c(i.hFront,i.hRear),rollDeg:Math.abs(r.rollDeg),aero:d,clearance:MO(n,u)}}function cF(e,t){let r=e.filter(o=>o.axle===t&&o.bounds),n=o=>{let a=o.filter(s=>s!==null&&Number.isFinite(s));return a.length?Math.min(...a):null};return{toBump:n(r.map(o=>o.toClosed)),toDroop:n(r.map(o=>o.toToppedOut))}}function mF(e,t,r,n){let o=(a,[s,i])=>Math.min(a-s,i-a);if(ux(e)){let{x:a,y:s}=No(e),i=[a[0],a[a.length-1]],c=[s[0],s[s.length-1]];return qr(e)?lF(e.frame,t,i,c,r,n):Math.min(o(r,i),o(n,c))}return Qc(e)?lF(e.frame,t,e.range.h,e.range.pitch,r,n):Math.min(o(r,e.range.hFront),o(n,e.range.hRear))}function lF(e,t,r,n,o,a){let s=Oo(e,t,o,a),i=l=>t*Math.tan(l*uF),c=a-o;return Math.min(s.h-r[0],r[1]-s.h,c-i(n[0]),i(n[1])-c)}function MO(e,t){let r=e.vehicle.chassis?.boxes;if(!r?.length)return null;let n={vehicle:e.vehicle,kc:e.kc},o=e.vehicle.config,a=o.frontAxleX,s=o.frontAxleX-o.wheelbase,i=Nt(e.vehicle,!0)/2,c=Nt(e.vehicle,!1)/2,l={FL:[a,-i],FR:[a,i],RL:[s,-c],RR:[s,c]},u=[[0,0,0],[0,0,0],[0,0,0]],m=[0,0,0];for(let b of er){let g=[1,l[b][0],l[b][1]];for(let y=0;y<3;y++){m[y]+=g[y]*t[b];for(let R=0;R<3;R++)u[y][R]+=g[y]*g[R]}}let f=iF(u,m);if(!f)return null;let p=aF(n),d={z0:p.z0+f[0],dzdx:p.dzdx+f[1],dzdy:p.dzdy+f[2]},h=null;for(let b of oF(r,n)){let g=sF(b,d);(!h||g.height<h.height)&&(h={height:g.height,volume:b.name})}return h}function ip(e){return e.aeroModel?null:"The car runs on aero constants, which do not move with the platform; attach an aero model in Aerodynamics"}var SO={front:"front",rear:"rear",heaveFront:"front",heaveRear:"rear",rollFront:"front",rollRear:"rear"};function Rc(e,t,r,n){let o=Du(e,t);return ku.some(s=>{if(SO[s]!==r)return!1;let i=o[s].coilover,c=i?.extended!==void 0&&i.extended>0;return n==="droop"?c:c&&i?.stroke!==void 0&&i.stroke>0})?null:n==="droop"?`No ${r} damper states its extended length; state it on its part in Dampers, or under Elements \u203A Stops`:`No ${r} damper states its stroke; state its extended length and stroke on its part in Dampers, or under Elements \u203A Stops`}function L0(e){return e.chassis?.boxes.length?null:"This suspension has no mockup volumes to measure the ground from; draw one under Kinematics \u203A Chassis"}var cp=Math.PI/180,lp=1e-6;function dF(e,t){let r=e.length;if(r===0)return 0;if(0<=e[0])return t[0];if(0>=e[r-1])return t[r-1];let n=0;for(;e[n+1]<0;)n++;let o=(0-e[n])/(e[n+1]-e[n]);return t[n]+o*(t[n+1]-t[n])}function vc(e){let t=e.measured;if(t)return dF(t.travel,t.camber);let r=Q(e.config.spinAxis);return-Math.asin(Math.max(-1,Math.min(1,r[2])))/cp}function kc(e){let t=e.measured;if(t)return dF(t.travel,t.toe);let[r,n]=e.config.spinAxis;return Math.atan2(r,n)/cp}function D0(e,t){let r=Math.abs(t.camber)>=lp,n=Math.abs(t.toe)>=lp;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=(vc(e)+t.camber)*cp,l=(kc(e)+t.toe)*cp,[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 up(e){let t=e&&typeof e=="object"?e.value:void 0;return typeof t=="number"&&Number.isFinite(t)?t:void 0}function AO(e,t){let r=t;return{front:up(r.camber_front_deg)??vc(e.front),rear:up(r.camber_rear_deg)??vc(e.rear)}}function FO(e,t){let r=t;return{front:up(r.toe_front_deg)??kc(e.front),rear:up(r.toe_rear_deg)??kc(e.rear)}}function wO(e){return{camber:{front:vc(e.front),rear:vc(e.rear)},toe:{front:kc(e.front),rear:kc(e.rear)}}}var pF=new WeakMap;function CO(e,t){let r=wO(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)<lp&&Math.abs(u.toe)<lp;if(o(n.front)&&o(n.rear))return e;let a=`${t.camber.front}|${t.camber.rear}|${t.toe.front}|${t.toe.rear}`,s=pF.get(e),i=s?.get(a);if(i)return i;let c=e.corners?Object.fromEntries(Object.entries(e.corners).map(([u,m])=>[u,m&&D0(m,n[Ko(u)])])):void 0,l={...e,front:D0(e.front,n.front),rear:D0(e.rear,n.rear),...c?{corners:c}:{}};return s||pF.set(e,s=new Map),s.size>=16&&s.clear(),s.set(a,l),l}function za(e,t){return t?CO(e,{camber:AO(e,t),toe:FO(e,t)}):e}var TO=9.81;function Ya(e){let t=Nn(e),r=Math.max(0,e.unsprungPerCorner)*TO,n=a=>{let s=a==="FL"||a==="FR",i=s?"front":"rear",c=Xe(e,i),l=c>0?c:1/0,u=ad(e,i);return{staticLoad:t[a],springLoad:Math.max(0,t[a]-r),tyreRate:l,arbRate:s?e.arbFront:e.arbRear,heaveRate:(s?e.heaveSpringFront:e.heaveSpringRear)??0,...u>0?{staticLoadedRadius:Gt(u,t[a],l,u)}:{}}},o={};for(let[a,s,i,c,l,u]of[["front",e.elementLinkagesFront,!!e.decoupledFront,e.heaveCoiloverFront,e.heaveSeatFront,e.rollCoiloverFront],["rear",e.elementLinkagesRear,!!e.decoupledRear,e.heaveCoiloverRear,e.heaveSeatRear,e.rollCoiloverRear]]){let m=!i&&!!l&&(l.gap>0||!l.bothWays);(s?.heave||s?.roll||i||m)&&(o[a]={...s,carriesLoad:i,...c?{coilover:c}:{},...l&&!i?{heaveSeat:l}:{},...u?{rollCoilover:u}:{}})}return{corners:{FL:n("FL"),FR:n("FR"),RL:n("RL"),RR:n("RR")},...o.front||o.rear?{elements:o}:{},...e.cornerCoiloverFront||e.cornerCoiloverRear?{cornerCoilover:{...e.cornerCoiloverFront?{front:e.cornerCoiloverFront}:{},...e.cornerCoiloverRear?{rear:e.cornerCoiloverRear}:{}}}:{}}}var fF=new WeakMap;function PO(e){let t=za(e.vehicle,e.params);if(t===e.vehicle)return e;let r=fF.get(e);return(!r||r.vehicle!==t)&&fF.set(e,r={...e,vehicle:t}),r}function Sn(e,t={}){let r=PO(e),n=p0(r,t),o=t.assemble?()=>{let m=n.dynInput();if(!m)throw new Error("the car did not assemble");return{kc:Ya(m),cgHeight:m.cgHeight}}:void 0,a=F0(r,t.density,t.envelope,o),s=y0(r,n,t),i=w0(r,t),c=t.states??[],l=new Map;return{...a,...n,...s,...i,get failure(){return a.failure},values:new Map,states:c,stateOf:m=>m===void 0?c[0]??null:c.find(f=>f.id===m)??null,platformAt:m=>{let f=`${m.speedKmh}|${m.ayG}|${m.axG}`,p=l.get(f);if(p!==void 0)return p;let d=n.poseAt(m),h=n.dynInput(),b=null;if(d&&h)try{b=P0(h,m,d,a.contexts())}catch{b=null}return l.set(f,b),b}}}var LO=["x","y","z"],DO=/^(line|plane)\((-?\d+),(-?\d+)\)([uv]?)$/,hF=Math.PI/18e3,bF=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],gF=(e,t)=>[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]],EO=e=>Math.hypot(e[0],e[1],e[2]),E0=(e,t)=>[e[0]*t,e[1]*t,e[2]*t];function I0(e){let t=EO(e);return t>1e-9?E0(e,1/t):null}function IO(e,t){let r=e*hF,n=t*hF;return[Math.cos(n)*Math.cos(r),Math.cos(n)*Math.sin(r),Math.sin(n)]}function yr(e){let t=e.lastIndexOf(".");if(t<0)return null;let r=DO.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:IO(Number(r[2]),Number(r[3]))},coord:n==="line"?"along":r[4]}}function yF(e){let t=I0(gF([0,0,1],e))??[1,0,0];(t[0]<-1e-9||Math.abs(t[0])<=1e-9&&t[1]<0)&&(t=E0(t,-1));let r=I0(gF(e,t))??[0,1,0];return(r[2]<-1e-9||Math.abs(r[2])<=1e-9&&r[1]<0)&&(r=E0(r,-1)),[t,r]}function _0(e){if(e.coord==="along")return e.shape.dir;let[t,r]=yF(e.shape.dir);return e.coord==="u"?t:r}function xF(e,t){let r=yr(t);if(!r)return;let n=LO.map(u=>e[`${r.point}.${u}`]);if(n.some(u=>!u))return;let o=_0(r),a=[0,1,2].filter(u=>Math.abs(o[u])>1e-12),s=u=>n.map(m=>m.read(u)),i=n[0],c=a.map(u=>n[u].supersededBy).find(Boolean),l=i.label.replace(/ x$/,"");return{id:t,group:i.group,label:r.coord==="along"?`${l} along its line`:`${l} in its plane, ${r.coord}`,...i.scope?{scope:i.scope}:{},unit:i.unit,defaultSpan:i.defaultSpan,read:u=>bF(s(u),o),write:(u,m)=>{let f=s(u),p=m-bF(f,o),d=u;for(let h of a)d=n[h].write(d,f[h]+p*o[h]);return d},...c?{supersededBy:c}:{}}}var mp=["x","y","z"];var _O=/^(?:hp\.(?:front|rear)\.\w+|(?:heave|roll)\.(?:front|rear)\.(?:outer|inner|anchor))$/;function Mc(e){let t=e.lastIndexOf("."),r=e.slice(0,t);if(t<0||!_O.test(r))return null;let n=e.slice(t+1);if(n==="x"||n==="y"||n==="z")return{point:r,axis:n};let o=yr(e);return o?{point:r,axis:o.coord}:null}var Sc="*";function N0(e){let t={sum:"summed",min:"lowest",max:"highest",distance:"by length",harmonic:"overall"};return e?.across?`all courses, ${t[e.across]}`:"all courses"}var O0=e=>e?.reads==="speed"||e?.reads==="operating",V0=e=>e?.reads==="lateral"||e?.reads==="operating";function Ro(e){if(!e)return"";let t=[];return e.speed!==void 0&&Number.isFinite(e.speed)&&t.push(`v${e.speed}`),e.ayG!==void 0&&Number.isFinite(e.ayG)&&t.push(`a${e.ayG}`),e.courseId&&t.push(`c${e.courseId}`),e.stateId&&t.push(`s${e.stateId}`),t.join(",")}function pp(e,t){return e?.appliesAt?t.find(r=>!e.appliesAt(r)):t[0]}function Wa(e,t,r){let n=r?.stateId?e.stateOf(r.stateId):pp(t,e.states)??null;return n&&!t.appliesAt?.(n)?n:null}function kt(e,t,r){let n=`${t.id}@${Ro(r)}`,o=e.values.get(n);if(o!==void 0)return o;let a;try{a=r?.courseId===Sc&&t.reads==="course"?NO(e,t,r):r?.stateId===br&&t.reads==="state"?OO(e,t,r):t.read(e,r)}catch{a=NaN}return e.values.set(n,a),a}function NO(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:kt(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 OO(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:kt(e,t,{...r,stateId:i.id}),w:i.weight,s:i})),a=t.appliesAt?o.filter(i=>Number.isFinite(i.v)||!e.poseAt(i.s)):o;if(!a.length||a.some(i=>!Number.isFinite(i.v)))return NaN;if(t.acrossStates==="max")return Math.max(...a.map(i=>i.v));if(t.acrossStates==="min")return Math.min(...a.map(i=>i.v));if(t.acrossStates==="span")return Math.max(...a.map(i=>i.v))-Math.min(...a.map(i=>i.v));let s=a.reduce((i,c)=>i+c.w,0);return s>0?a.reduce((i,c)=>i+c.v*c.w,0)/s:NaN}function B0(e){let t={mean:"weighted mean",max:"highest",min:"lowest",span:"span"};return e?.acrossStates?`every state, ${t[e.acrossStates]}`:"every state"}function et(e){return`${e.quantity??e.groupShort??e.group} \xB7 ${e.label}`}var VO={front:"Front",rear:"Rear"},Ac={heave:0,pitch:0,roll:0,steer:0};function RF(e,t){let r=0,n=0;for(let o=1;o<e.length;o++){let a=e[o]-e[o-1];if(Math.abs(a)<1e-9)continue;let s=(t[o]-t[o-1])/a;r+=s*s,n++}return n?Math.sqrt(r/n):NaN}function BO(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 Fc=e=>e.length?Math.max(...e)-Math.min(...e):NaN;function vF(e){let t=(e??[]).filter(Number.isFinite);if(!t.length)return NaN;let r=t.reduce((n,o)=>n+o,0)/t.length;return Math.abs(r)>0?(Math.max(...t)-Math.min(...t))/Math.abs(r):NaN}function kF(e,t){if(!e.length)return;let r=0;for(let n=1;n<e.length;n++)Math.abs(e[n])<Math.abs(e[r])&&(r=n);return t[r]}function ja(e,t,r){let n=e.stateOf(t?.stateId),o=n?e.poseAt(n):null;return o?r(o):NaN}var wc=(e,t)=>`${e==="front"?"F":"R"}${t}`,MF=e=>e==="L"?"R":"L";function SF(e){let t=VO[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?Ud(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=Yd(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(Ac)?.[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?BO(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?Fc(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?Fc(M.rc.map(F=>F.lateral)):NaN},curve:x=>{let M=x.rcRoll(e);return M?{key:r("rcLateralSpan"),title:`${t} roll-centre lateral position vs body roll`,xLabel:"roll [\xB0]",yLabel:"RC lateral [mm]",x:M.at,y:M.rc.map(F=>F.lateral)}:null}},{id:r("minSinAngle"),group:`${t} roll centre`,label:"construction conditioning (min sinAngle)",unit:"-",scale:.04,scope:e,cost:"cheap",read:x=>{let M=x.rcHeave(e),F=x.rcRoll(e);return!M||!F?NaN:Math.min(...M.rc.map(w=>w.sinAngle),...F.rc.map(w=>w.sinAngle))},curve:x=>{let M=x.rcHeave(e);return M?{key:r("minSinAngle"),title:`${t} construction conditioning vs travel`,xLabel:"travel [mm]",yLabel:"sinAngle",x:M.at,y:M.rc.map(F=>F.sinAngle)}:null}},{id:r("fvsaLength"),group:`${t} roll centre`,label:"front-view swing-arm length",unit:"mm",scale:500,scope:e,cost:"readout",read:x=>h(x)?.fvsaLength??NaN},{id:r("complianceSteer"),group:`${t} compliance`,label:"compliance steer",unit:"\xB0/kN lateral",scale:.05,scope:e,cost:"readout",read:x=>(x.compliance(e)?.toePerFy??0)*1e3},{id:r("complianceCamber"),group:`${t} compliance`,label:"compliance camber",unit:"\xB0/kN lateral",scale:.05,scope:e,cost:"readout",read:x=>(x.compliance(e)?.camberPerFy??0)*1e3},{id:r("complianceSteerLong"),group:`${t} compliance`,label:"compliance steer under braking",unit:"\xB0/kN longitudinal",scale:.05,scope:e,cost:"readout",read:x=>(x.compliance(e)?.toePerFx??0)*1e3},{id:r("steeringCompliance"),group:`${t} compliance`,label:"steer given back under aligning torque",unit:"\xB0/100 N\xB7m",scale:.2,scope:e,cost:"readout",read:x=>(x.compliance(e)?.toePerMz??0)*1e5},{id:r("staticCamber"),group:`${t} camber & toe`,label:"static camber",unit:"\xB0",scale:1,scope:e,cost:"cheap",read:x=>{let M=x.solveAt(e,0);return M?M.metrics.camber:NaN}},{id:r("staticToe"),group:`${t} camber & toe`,label:"static toe",unit:"\xB0",scale:.5,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.toe??NaN},{id:r("camberGainDesign"),group:`${t} camber & toe`,label:"camber gain in bump",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.camberGain??NaN,curve:x=>g(x)},{id:r("rollCamber"),group:`${t} camber & toe`,label:"camber gain in roll",unit:"\xB0/\xB0",scale:.2,scope:e,cost:"readout",read:x=>h(x)?.rollCamber??NaN},{id:r("rollCamberRecovery"),group:`${t} camber & toe`,label:"camber recovery in roll",unit:"%",scale:20,scope:e,cost:"readout",read:x=>h(x)?.camberRecovery??NaN},{id:r("bumpSteerDesign"),group:`${t} camber & toe`,label:"bump steer at design",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.bumpSteer??NaN,curve:x=>y(x)},{id:r("rollSteer"),group:`${t} camber & toe`,label:"roll steer",unit:"\xB0/\xB0",scale:.1,scope:e,cost:"readout",read:x=>h(x)?.rollSteer??NaN},{id:r("bumpSteer"),group:`${t} camber & toe`,label:"bump steer, RMS over the travel",unit:"\xB0/mm",scale:.02,scope:e,cost:"cheap",read:x=>{let M=n(x,F=>F.metrics.toe);return M.x.length?RF(M.x,M.y):NaN},curve:x=>y(x)},{id:r("camberGain"),group:`${t} camber & toe`,label:"camber gain, RMS over the travel",unit:"\xB0/mm",scale:.02,scope:e,cost:"cheap",read:x=>{let M=n(x,F=>F.metrics.camber);return M.x.length?RF(M.x,M.y):NaN},curve:x=>g(x)},{id:r("camberSpan"),group:`${t} camber & toe`,label:"camber range over travel",unit:"\xB0",scale:1,scope:e,cost:"cheap",read:x=>Fc(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=>Fc(n(x,M=>M.metrics.toe).y)},{id:r("camberRecovery"),group:`${t} camber & toe`,label:"outer camber at limit roll",unit:"\xB0",scale:2,scope:e,cost:"cheap",read:x=>{let M=x.solveAt(e,x.travelAtRoll(e,x.envelope.rollAtLimitDeg)),F=x.solveAt(e,0);return!M||!F?NaN:Math.abs(M.metrics.camber-F.metrics.camber+x.envelope.rollAtLimitDeg)}},{id:r("stateCamberOuter"),group:`${t} camber & toe`,label:"outer camber to the road at a state",unit:"\xB0",scale:1,scope:e,cost:"cheap",reads:"state",acrossStates:"mean",read:(x,M)=>ja(x,M,F=>F.camber[wc(e,F.outer)])},{id:r("stateCamberInner"),group:`${t} camber & toe`,label:"inner camber to the road at a state",unit:"\xB0",scale:1,scope:e,cost:"cheap",reads:"state",acrossStates:"mean",read:(x,M)=>ja(x,M,F=>F.camber[wc(e,MF(F.outer))])},{id:r("stateToeOuter"),group:`${t} camber & toe`,label:"outer toe change at a state",unit:"\xB0",scale:.2,scope:e,cost:"cheap",reads:"state",acrossStates:"mean",read:(x,M)=>ja(x,M,F=>F.corners[wc(e,F.outer)].bumpToe)},{id:r("caster"),group:`${t} upright`,label:"caster",unit:"\xB0",scale:5,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.caster??NaN},{id:r("kpi"),group:`${t} upright`,label:"kingpin inclination",unit:"\xB0",scale:5,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.kpi??NaN},{id:r("scrubRadius"),group:`${t} upright`,label:"scrub radius",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.scrubRadius??NaN},{id:r("mechanicalTrail"),group:`${t} upright`,label:"mechanical trail",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.mechanicalTrail??NaN},{id:r("kingpinOffset"),group:`${t} upright`,label:"kingpin offset at hub height",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.kingpinOffset??NaN},{id:r("casterOffset"),group:`${t} upright`,label:"caster offset at hub height",unit:"mm",scale:10,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.casterOffset??NaN},{id:r("steeringArm"),group:`${t} upright`,label:"steering arm",unit:"mm",scale:20,scope:e,cost:"cheap",read:x=>x.solveAt(e,0)?.metrics.steeringArm??NaN},{id:r("casterGain"),group:`${t} upright`,label:"caster gain in bump",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.casterGain??NaN},{id:r("kpiGain"),group:`${t} upright`,label:"kingpin inclination gain in bump",unit:"\xB0/mm",scale:.02,scope:e,cost:"readout",read:x=>h(x)?.kpiGain??NaN},{id:r("scrubGain"),group:`${t} upright`,label:"scrub radius gain in bump",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:x=>h(x)?.scrubGain??NaN},{id:r("trailGain"),group:`${t} upright`,label:"mechanical trail gain in bump",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:x=>h(x)?.trailGain??NaN},{id:r("motionRatio"),group:`${t} rates`,label:"motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let M=x.sweep(e);return M?kF(M.samples.map(F=>F.travel),M.samples.map(F=>F.metrics.motionRatio??NaN))??NaN:NaN},curve:x=>{if(c(x.car))return null;let M=n(x,F=>F.metrics.motionRatio??NaN);return M.x.length?{key:r("motionRatio"),title:`${t} motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",...M}:null}},{id:r("mrSpread"),group:`${t} rates`,label:"motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let M=x.sweep(e);if(!M)return NaN;let F=M.samples.map(C=>C.metrics.motionRatio??NaN).filter(Number.isFinite);if(!F.length)return NaN;let w=F.reduce((C,T)=>C+T,0)/F.length;return w>0?(Math.max(...F)-Math.min(...F))/w:NaN}},{id:r("wheelRate"),group:`${t} rates`,label:"wheel rate at design",unit:"N/mm",scale:10,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let M=x.sweep(e);return M?kF(M.samples.map(F=>F.travel),M.samples.map(F=>F.metrics.wheelRate??NaN))??NaN:NaN}},{id:r("heaveMotionRatio"),group:`${t} rates`,label:"heave element motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:u,read:x=>p(x)?.atDesign??NaN,curve:x=>{let M=p(x);return M?{key:r("heaveMotionRatio"),title:`${t} heave element motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",x:M.travel,y:M.ratio}:null}},{id:r("heaveMrSpread"),group:`${t} rates`,label:"heave element motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:u,read:x=>vF(p(x)?.ratio)},{id:r("heaveWheelRate"),group:`${t} rates`,label:"heave element wheel rate at design",unit:"N/mm",scale:10,scope:e,cost:"cheap",unavailable:l,read:x=>l(x.car)||!x.sweep(e)?NaN:va(x.car.vehicle,x.car.params)[e]??NaN},{id:r("rollMotionRatio"),group:`${t} rates`,label:"roll element motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:f,read:x=>d(x)?.atDesign??NaN,curve:x=>{let M=d(x);return M?{key:r("rollMotionRatio"),title:`${t} roll element motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",x:M.travel,y:M.ratio}:null}},{id:r("rollMrSpread"),group:`${t} rates`,label:"roll element motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:f,read:x=>vF(d(x)?.ratio)},{id:r("rollWheelRate"),group:`${t} rates`,label:"roll element wheel rate at design",unit:"N/mm",scale:10,scope:e,cost:"cheap",unavailable:m,read:x=>m(x.car)||!x.sweep(e)?NaN:Zn(x.car.vehicle,x.car.params)[e]??NaN},{id:r("ucaAxisLength"),group:`${t} package`,label:"upper arm pivot-axis length",unit:"mm",scale:80,scope:e,cost:"geometry",read:x=>x.axisLength(e,"uca")},{id:r("lcaAxisLength"),group:`${t} package`,label:"lower arm pivot-axis length",unit:"mm",scale:80,scope:e,cost:"geometry",read:x=>x.axisLength(e,"lca")},{id:r("linkLength"),group:`${t} package`,label:"tie/toe link length",unit:"mm",scale:100,scope:e,cost:"geometry",read:x=>x.linkLength(e)},{id:r("trackScrubRate"),group:`${t} package`,label:"track scrub rate",unit:"mm/mm",scale:.05,scope:e,cost:"readout",read:x=>x.readout(Ac)?.[e].trackScrubRate??NaN},{id:r("trackChange"),group:`${t} package`,label:"track change at full bump",unit:"mm",scale:2,scope:e,cost:"readout",read:x=>b(x)?.trackChange??NaN},{id:r("stateTravelOuter"),group:`${t} package`,label:"outer wheel travel at a state",unit:"mm",scale:10,scope:e,cost:"cheap",reads:"state",acrossStates:"max",read:(x,M)=>ja(x,M,F=>F.corners[wc(e,F.outer)].travel)},{id:r("stateTravelInner"),group:`${t} package`,label:"inner wheel travel at a state",unit:"mm",scale:10,scope:e,cost:"cheap",reads:"state",acrossStates:"min",read:(x,M)=>ja(x,M,F=>F.corners[wc(e,MF(F.outer))].travel)},{id:r("damperStroke"),group:`${t} package`,label:"damper stroke over the travel",unit:"mm",scale:20,scope:e,cost:"cheap",unavailable:c,read:x=>c(x.car)?NaN:Fc(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(Ac)?.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(Ac)?.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(Ac)?.rear.antiLift??NaN});let k=x=>{let M=x.slice(t.length+1);return M.charAt(0).toUpperCase()+M.slice(1)};return[...new Set(R.map(x=>x.group))].flatMap(x=>R.filter(M=>M.group===x)).map(x=>({...x,quantity:`${t} \xB7 ${k(x.group)}`}))}function AF(e,t){let r=e.steer();if(!r)return NaN;let n=r.filter(a=>Number.isFinite(a.ackermannPct)&&a.inner>.3&&a.outer>.3);return n.length?n.reduce((a,s)=>t==="centre"?s.inner<a.inner?s:a:s.inner>a.inner?s:a).ackermannPct:NaN}var $O=[{id:"kin.front.ackermannCentre",group:"Steering",label:"Ackermann near centre",unit:"%",scale:25,scope:"front",cost:"cheap",read:e=>AF(e,"centre"),curve:e=>{let t=e.steer();if(!t)return null;let r=t.filter(n=>Number.isFinite(n.ackermannPct)&&n.inner>.3&&n.outer>.3);return r.length?{key:"kin.front.ackermann",title:"Ackermann vs steer",xLabel:"inner wheel steer [\xB0]",yLabel:"Ackermann [%]",x:r.map(n=>n.inner),y:r.map(n=>n.ackermannPct)}:null}},{id:"kin.front.ackermannLock",group:"Steering",label:"Ackermann at lock",unit:"%",scale:25,scope:"front",cost:"cheap",read:e=>AF(e,"lock")},{id:"kin.front.lockInner",group:"Steering",label:"inner wheel angle at full rack",unit:"\xB0",scale:5,scope:"front",cost:"cheap",read:e=>{let t=e.steer();return t?.length?Math.max(...t.map(r=>r.inner)):NaN}}],GO=[{id:"kin.car.trackFront",group:"Whole car",label:"front track",unit:"mm",scale:50,scope:"front",cost:"geometry",read:e=>2*e.car.vehicle.front.hardpoints.wheelCenter[1]},{id:"kin.car.trackRear",group:"Whole car",label:"rear track",unit:"mm",scale:50,scope:"rear",cost:"geometry",read:e=>2*e.car.vehicle.rear.hardpoints.wheelCenter[1]},{id:"kin.car.stateRoll",group:"Whole car",label:"body roll at a state",unit:"\xB0",scale:1,scope:"car",cost:"cheap",reads:"state",acrossStates:"max",read:(e,t)=>ja(e,t,r=>Math.abs(r.rollDeg))},{id:"kin.car.wheelbaseChange",group:"Whole car",label:"wheelbase change at full bump",unit:"mm",scale:2,scope:"car",cost:"readout",read:e=>{let t=e.readoutAtTravel("front",e.envelope.travelMax),r=e.readoutAtTravel("rear",e.envelope.travelMax);return t&&r?t.longitudinal-r.longitudinal:NaN}}],$0=[...SF("front"),...SF("rear"),...$O,...GO];var PF={front:"Front",rear:"Rear"},FF=e=>xo("side",e),KO=e=>xo("drive",e)&&xo("brake",e)?"neither brakes nor drives":null;function HO(e,t,r,n){let o=Wa(e,t,r),a=o?e.tyreAt(o):null;return a?n(a):NaN}function Ua(e,t){let r={...e,read:(n,o)=>HO(n,r,o,t)};return r}var wF=e=>e?100*e.lossCamber:NaN,CF=e=>e&&!e.lifted?e.camber-e.wants:NaN;function TF(e){let t=PF[e],r=s=>`tyre.${e}.${s}`,n={group:`${t} tyre`,quantity:`${t} \xB7 Tyre`,scope:e,cost:"cheap",reads:"state",acrossStates:"mean"},o={...n,appliesAt:FF,unavailable:s=>Ym(s.params,e)},a=[Ua({...o,id:r("camberErrorOuter"),label:"camber error at the outer wheel",unit:"\xB0",scale:.5},s=>CF(s.side(e)?.wheels[0])),Ua({...o,id:r("camberErrorInner"),label:"camber error at the inner wheel",unit:"\xB0",scale:.5},s=>CF(s.side(e)?.wheels[1])),Ua({...o,id:r("sideLossCamber"),label:"side grip lost to camber",unit:"%",scale:1},s=>wF(s.side(e))),Ua({...n,appliesAt:FF,id:r("sideLossToe"),label:"side grip lost to the toe split",unit:"%",scale:1},s=>100*s.toeLoss(e)),Ua({...n,appliesAt:KO,unavailable:s=>u0(s.params,e),id:r("longLossCamber"),label:"drive and brake grip lost to camber",unit:"%",scale:1},s=>wF(s.long(e)))];return e==="front"&&a.push(Ua({...n,appliesAt:s=>xo("ackermann",s),id:r("ackermannError"),label:"Ackermann against the tyre",unit:"%",scale:25},s=>s.ackermann())),a}var G0=[...TF("front"),...TF("rear")],zO=/^tyre\.(front|rear)\.(camberErrorOuter|camberErrorInner|sideLossCamber|longLossCamber)$/;function K0(e,t){let r=new Map,n=a=>a.name.charAt(0).toLowerCase()+a.name.slice(1),o=a=>`${a>0?"+":a<0?"\u2212":""}${Math.abs(a).toFixed(1)}\xB0`;for(let{m:a,at:s}of t){let i=zO.exec(a.id);if(!i)continue;let c=i[1],l=i[2]==="longLossCamber",u=s?.stateId==="*"?e.states.filter(m=>!a.appliesAt?.(m)):[Wa(e,a,s)].filter(m=>!!m);for(let m of u){let f=`${c}|${m.id}|${l}`;if(r.has(f))continue;let p=e.tyreAt(m),d=p?l?p.long(c):p.side(c):null;if(!d)continue;let{lo:h,hi:b,stated:g}=d.range,y=g?`the ${o(h)} \u2026 ${o(b)} its data covers`:`the \xB1${b.toFixed(0)}\xB0 read without a stated range`,R=M=>l?M===0?"left":"right":M===0?"outer":"inner",k=d.wheels.findIndex(M=>M.atEdge),v=d.wheels.findIndex(M=>M.outside&&!M.lifted),x=[];k>=0&&x.push(`the ${PF[c].toLowerCase()} ${R(k)} tyre wants ${o(d.wheels[k].wants)}, the edge of ${y}, and may want more`),v>=0&&x.push(`the ${R(v)} wheel has ${o(d.wheels[v].camber)}, past it, and is read at ${o(d.wheels[v].read)}`),x.length&&r.set(f,`In the ${n(m)} ${x.join("; ")}.`)}}return[...r.values()]}function H0(e,t){let r=e.appliesAt?.(t);return r?`is read at ${t.name}, which ${r}`:null}var YO={front:"Front",rear:"Rear"};function WO(e,t,r,n){let o=Wa(e,t,r),a=o?e.platformAt(o):null;return(a?n(a):null)??NaN}function Kt(e,t){let r={...e,read:(n,o)=>WO(n,r,o,t)};return r}var z0={cost:"cheap",reads:"state"},jO={unavailable:e=>ip(e.params)};function LF(e){let t=YO[e],r=o=>`platform.${e}.${o}`,n={...z0,group:`${t} platform`,quantity:`${t} \xB7 Platform`,scope:e};return[Kt({...n,id:r("rideHeight"),label:"ride height at a state",unit:"mm",scale:5,acrossStates:"min"},o=>o[e].height),Kt({...n,id:r("toBumpStop"),label:"travel left to the bump stop",unit:"mm",scale:5,acrossStates:"min",unavailable:o=>Rc(o.vehicle,o.params,e,"bump")},o=>o[e].toBump),Kt({...n,id:r("toDroopStop"),label:"travel left to the droop stop",unit:"mm",scale:5,acrossStates:"min",unavailable:o=>Rc(o.vehicle,o.params,e,"droop")},o=>o[e].toDroop)]}var dp={...z0,group:"Platform",scope:"car"},Cc={...z0,...jO,group:"Aero platform",groupShort:"Aero",scope:"car"},Y0=[...LF("front"),...LF("rear"),Kt({...dp,id:"platform.rake",label:"rake at a state",unit:"\xB0",scale:.2,acrossStates:"span"},e=>e.rakeDeg),Kt({...dp,id:"platform.pitch",label:"pitch at a state",unit:"\xB0",scale:.2,acrossStates:"max"},e=>e.pitchDeg),Kt({...dp,id:"platform.roll",label:"body roll at a state",unit:"\xB0",scale:.2,acrossStates:"max"},e=>e.rollDeg),Kt({...dp,id:"platform.groundClearance",label:"ground clearance at a state",unit:"mm",scale:5,acrossStates:"min",unavailable:e=>L0(e.vehicle)},e=>e.clearance?.height),Kt({...Cc,id:"platform.balance",label:"balance at a state",unit:"%",scale:1,acrossStates:"span"},e=>e.aero?.balance),Kt({...Cc,id:"platform.clA",label:"downforce Cl\xB7A at a state",unit:"m\xB2",scale:.1,acrossStates:"mean"},e=>e.aero?.clA),Kt({...Cc,id:"platform.cdA",label:"drag Cd\xB7A at a state",unit:"m\xB2",scale:.05,acrossStates:"mean"},e=>e.aero?.cdA),Kt({...Cc,id:"platform.dataMargin",label:"margin to the model\u2019s data",unit:"mm",scale:5,acrossStates:"min"},e=>e.aero?.dataMargin),Kt({...Cc,id:"platform.loopMargin",label:"aero-elastic margin, 1 \u2212 loop gain",unit:"-",scale:.1,acrossStates:"min"},e=>e.aero?.loopMargin)];var DF={understeer:"operating",yawFreq:"speed",yawZeta:"speed",yawStiffness:"operating",steeringTorque:"operating",steeringTorqueGradient:"operating"};function nt(e,t,r,n="cheap"){let o=Nb[e];if(!o)throw new Error(`no DYN_METRIC "${e}"`);return{id:`dyn.${e}`,group:t,label:o.label,unit:o.unit,scale:r,scope:"car",cost:n,...DF[e]?{reads:DF[e]}:{},read:(a,s)=>{let i=a.dynInput(),c=a.dynCtx(s);return i&&c?o.compute(i,c):NaN}}}var UO=[nt("understeer","Handling \u2014 balance",.1),nt("tlltdFront","Handling \u2014 balance",5),nt("rollStiffFront","Handling \u2014 balance",5)],XO=[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")],QO=[nt("steeringTorque","Steering feel",1,"trim"),nt("steeringTorqueGradient","Steering feel",2,"trim")],qO=[nt("rollGradient","Ride & body",.5),nt("pitchGradient","Ride & body",.5),nt("rideFreqFront","Ride & body",.5),nt("rideFreqRear","Ride & body",.5),nt("rollFreq","Ride & body",.5),nt("pitchFreq","Ride & body",.5),nt("zetaFront","Ride & body",.2),nt("zetaRear","Ride & body",.2)],ZO=[{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}],JO=[{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=[...UO,...XO,...QO,...qO,...ZO,...JO];function eV(e,t){let r=e.lap(t),n=e.course(t);if(!r||!n)return NaN;let o=n.track.ds,a=0,s=0;for(let i=0;i<r.v.length-1;i++){let c=o[i]??0,l=.5*(r.v[i]+r.v[i+1]);c>0&&l>0&&(a+=c,s+=c/l)}return s>0?a/s:NaN}var j0=[{id:"lap.time",group:"Lap & manoeuvre",label:"Time",unit:"s",scale:.1,scope:"car",cost:"lap",reads:"course",across:"sum",read:(e,t)=>e.lap(t)?.laptime??NaN},{id:"lap.vMean",group:"Lap & manoeuvre",label:"Mean speed",unit:"km/h",scale:2,scope:"car",cost:"lap",reads:"course",across:"harmonic",read:(e,t)=>eV(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 tV(e,t){let r=/^(.*?)\s*\(([^)]+)\)\s*$/.exec(e);return r?{label:r[1],unit:r[2]}:{label:e,unit:t?"s":""}}function rV(e){return e==="s"||e==="kWh"?.1:e==="km/h"?2:1}var EF=new WeakMap;function fp(e){let t=EF.get(e);return t||(t=e.metrics.filter(zc).map(r=>{let{label:n,unit:o}=tV(r.label,r.format==="time");return{id:`event.${e.id}.${r.key}`,group:`Events \xB7 ${e.label}`,groupShort:"Events",label:n,unit:o,scale:rV(o),scope:"car",cost:"session",read:a=>a.session(e.id)?.[r.key]??NaN}}),EF.set(e,t),t)}var U0=Na.flatMap(fp);var hp=[...$0,...G0,...Y0,...W0,...j0,...U0],Xa=Object.fromEntries(hp.map(e=>[e.id,e]));var IF={all:hp,byId:Xa},_F=new WeakMap;function Ur(e=[]){if(e.length===0)return IF;let t=_F.get(e);if(t)return t;let r=ig(e).filter(n=>!Oa(n.id)).flatMap(fp);return t=r.length?{all:[...hp,...r],byId:{...Xa,...Object.fromEntries(r.map(n=>[n.id,n]))}}:IF,_F.set(e,t),t}var Tc=180/Math.PI,Qa=Math.PI/180,oV=.2;function bp(e,t){let r=H(t,e);return Q(r[0]<0?wd(r):r)}var gp=e=>({side:Math.atan2(e[2],e[0])*Tc,plan:Math.atan2(e[1],e[0])*Tc}),yp=(e,t)=>Q([1,Math.tan(t*Qa),Math.tan(e*Qa)]),Pc=e=>Math.abs(e[0])>=oV,xp=(e,t)=>Math.atan(t/Math.max(e,1))*Tc,Rp=(e,t)=>Math.tan(t*Qa)*Math.max(e,1);var An=["side","plan","clock","len"],Xt={uca:{fore:"ucaFront",aft:"ucaRear",ball:"uprightUpper"},lca:{fore:"lcaFront",aft:"lcaRear",ball:"uprightLower"}},Lc={uca:"upper arm",lca:"lower arm"},aV=1,NF=(e,t)=>bp(e[Xt[t].fore],e[Xt[t].aft]);function OF(e){let t=Q(H(Fd,U(e,X(Fd,e))));return{e1:t,e2:ae(e,t)}}function X0(e,t){let r=NF(e,t);if(!Pc(r))return`the ${Lc[t]}'s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it`;let n=Xt[t],o=tn(e[n.ball],e[n.fore],r);return Math.hypot(...H(o,e[n.ball]))>=aV?null:`the ${Lc[t]}'s ball joint sits on its own pivot axis, so the arm has no length to swing on`}function Xr(e,t){let r=Xt[t],n=e[r.ball],o=NF(e,t),a=tn(n,e[r.fore],o),s=H(a,n),i=Math.hypot(s[0],s[1],s[2]),{e1:c,e2:l}=OF(o),u=i>0?U(s,1/i):c;return{...gp(o),clock:Math.atan2(X(u,l),X(u,c))*Tc,len:i,sFront:X(H(e[r.fore],a),o),sRear:X(H(e[r.aft],a),o)}}function Q0(e,t){let r=yp(e.side,e.plan),{e1:n,e2:o}=OF(r),a=ee(U(n,Math.cos(e.clock*Qa)),U(o,Math.sin(e.clock*Qa))),s=ee(t,U(a,e.len));return{fore:ee(s,U(r,e.sFront)),aft:ee(s,U(r,e.sRear))}}function VF(e,t,r,n){let o=Xt[t],a={...Xr(e,t),[r]:n},{fore:s,aft:i}=Q0(a,e[o.ball]);return{...e,[o.fore]:s,[o.aft]:i}}function BF(e,t){return t==="clock"?e.len:Math.abs(e.sFront-e.sRear)/2}function vp(e,t,r){return t==="len"?r:xp(BF(e,t),r)}function q0(e,t,r){return t==="len"?r:Rp(BF(e,t),r)}var vo=["side","plan","atY","atZ"],ko={fore:"rockerPivotA",aft:"rockerPivotB"},sV=5,$F=e=>bp(e.rockerPivotA,e.rockerPivotB);function qa(e){return Math.hypot(...H(e.rockerPivotB,e.rockerPivotA))<sV?"the rocker\u2019s two pivots are the same point, so there is no axis to describe":Pc($F(e))?null:"the rocker\u2019s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it"}function Fn(e){let t=$F(e),r=Pc(t)?t:[1,0,0],n=e.rockerPivotA,o=ee(n,U(r,-n[0]/r[0]));return{...gp(r),atY:o[1],atZ:o[2],sA:X(H(n,o),r),sB:X(H(e.rockerPivotB,o),r)}}function Z0(e){let t=yp(e.side,e.plan),r=[0,e.atY,e.atZ];return{a:ee(r,U(t,e.sA)),b:ee(r,U(t,e.sB))}}function GF(e,t,r){if(qa(e))return e;let{a:n,b:o}=Z0({...Fn(e),[t]:r});return{...e,rockerPivotA:n,rockerPivotB:o}}var KF=e=>Math.abs(e.sA-e.sB)/2;function J0(e,t,r){return t==="side"||t==="plan"?xp(KF(e),r):r}function ey(e,t,r){return t==="side"||t==="plan"?Rp(KF(e),r):r}var qt={front:"Front",rear:"Rear"},Qt=["x","y","z"],Ve=(e,t)=>t==="front"?e.front:e.rear,Dc=(e,t,r)=>t==="front"?{...e,front:r}:{...e,rear:r},HF=[{kind:"inboard",keys:[{key:"ucaFront",label:"UCA front pivot"},{key:"ucaRear",label:"UCA rear pivot"},{key:"lcaFront",label:"LCA front pivot"},{key:"lcaRear",label:"LCA rear pivot"},{key:"tieInner",label:"tie/toe link inner"}]},{kind:"outboard",keys:[{key:"uprightUpper",label:"upper ball joint"},{key:"uprightLower",label:"lower ball joint"},{key:"tieOuter",label:"tie/toe link outer"},{key:"wheelCenter",label:"wheel centre"}]},{kind:"actuation",keys:[{key:"pushrodOuter",label:"push/pull rod outer"},{key:"rockerPivotA",label:"rocker pivot A"},{key:"rockerPivotB",label:"rocker pivot B"},{key:"rockerToPushrod",label:"rocker \u2014 rod end"},{key:"rockerToDamper",label:"rocker \u2014 damper end"},{key:"damperChassis",label:"damper chassis mount"}]}],zF={damperChassis:"strut top mount",pushrodOuter:"strut lower mount"},Mo=30;function iV(e){let t=[];for(let r of["front","rear"]){let n=Ve(e.vehicle,r).config.layout==="mcpherson";for(let o of HF)for(let{key:a,label:s}of o.keys){let i=n&&zF[a]||s;for(let c=0;c<3;c++)t.push({id:`hp.${r}.${a}.${Qt[c]}`,group:`${qt[r]} hardpoints \u2014 ${o.kind}`,label:`${i} ${Qt[c]}`,scope:qt[r],unit:"mm",defaultSpan:Mo,read:l=>Ve(l.vehicle,r).hardpoints[a][c],write:(l,u)=>{let m=Ve(l.vehicle,r),f=[...m.hardpoints[a]];f[c]=u;let p={...m.hardpoints,[a]:f};return{...l,vehicle:Dc(l.vehicle,r,{...m,hardpoints:p})}}})}}return t}var cV={side:"axis side-view angle",plan:"axis plan-view angle",clock:"arm clock angle",len:"effective arm length"},lV={side:"\xB0",plan:"\xB0",clock:"\xB0",len:"mm"};function uV(e){let t=[];for(let r of["front","rear"]){let n=Ve(e.vehicle,r).config.layout==="mcpherson";for(let o of["uca","lca"]){let a=Ve(e.vehicle,r).hardpoints,s=X0(a,o)?null:Xr(a,o);for(let i of An)t.push({id:`arm.${r}.${o}.${i}`,group:`${qt[r]} ${n?"arm axes":"wishbone axes"}`,label:`${Lc[o]} \u2014 ${cV[i]}`,scope:qt[r],unit:lV[i],defaultSpan:s?vp(s,i,Mo):Mo,read:c=>Xr(Ve(c.vehicle,r).hardpoints,o)[i],write:(c,l)=>{let u=Ve(c.vehicle,r),m=VF(u.hardpoints,o,i,l);return{...c,vehicle:Dc(c.vehicle,r,{...u,hardpoints:m})}}})}}return t}var mV={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"},pV={side:"\xB0",plan:"\xB0",atY:"mm",atZ:"mm"};function dV(e){let t=[];for(let r of["front","rear"]){let n=Ve(e.vehicle,r).hardpoints,o=qa(n)?null:Fn(n);for(let a of vo)t.push({id:`rocker.${r}.${a}`,group:`${qt[r]} rocker axis`,label:`rocker \u2014 ${mV[a]}`,scope:qt[r],unit:pV[a],defaultSpan:o?J0(o,a,Mo):Mo,read:s=>Fn(Ve(s.vehicle,r).hardpoints)[a],write:(s,i)=>{let c=Ve(s.vehicle,r),l=GF(c.hardpoints,a,i);return{...s,vehicle:Dc(s.vehicle,r,{...c,hardpoints:l})}}})}return t}var kp={front:"heaveFrontDesign",rear:"heaveRearDesign"},ty={front:"arbFrontDesign",rear:"arbRearDesign"};function fV(e,t){return{heave:e.config.actuation==="decoupled"?"heave element":"third spring",roll:t?.design.kind==="coil"?"roll shock":"anti-roll bar"}}var Mp=e=>/^(heave|roll)\.(front|rear)\.(outer|inner|anchor)\.[xyz]$/.test(e);function hV(e){let t=[];for(let r of["front","rear"]){let n=Ve(e.vehicle,r),o=e.params[kp[r]],a=e.params[ty[r]],s=fV(n,a),i=d=>d.params[kp[r]],c=d=>d.params[ty[r]],l=(d,h)=>({...d,params:{...d.params,[kp[r]]:h}}),u=(d,h)=>({...d,params:{...d.params,[ty[r]]:h}}),m={group:`${qt[r]} heave & roll elements`,scope:qt[r]},f=(d,h,b,g,y)=>{for(let R of b)t.push({...m,id:`${d}.${Qt[R]}`,label:`${h} ${Qt[R]}`,unit:"mm",defaultSpan:Mo,read:k=>g(k)[R],write:(k,v)=>{let x=[...g(k)];return x[R]=v,y(k,x)}})},p=(d,h,b,g,y)=>{t.push({...m,id:d,label:h,unit:"N/mm",defaultSpan:Math.max(5,b*.4),read:g,write:y})};if(o?.design.kind==="coil"){if(o.linkage){let d=b=>i(b).linkage;f(`heave.${r}.outer`,`${s.heave} eye`,[0,1,2],b=>d(b).outer,(b,g)=>l(b,{...i(b),linkage:{...d(b),outer:g}})),o.linkage.mount?.kind==="chassis"&&f(`heave.${r}.anchor`,`${s.heave} chassis anchor`,[0,2],b=>d(b).mount.anchor,(b,g)=>l(b,{...i(b),linkage:{...d(b),mount:{kind:"chassis",anchor:g}}}))}if(typeof o.design.rate=="number"){let d=h=>i(h).design;p(`heave.${r}.rate`,`${s.heave} spring rate (@element)`,o.design.rate,h=>d(h).rate,(h,b)=>l(h,{...i(h),design:{...d(h),rate:b}}))}}if(a&&a.design.kind!=="none"){if(a.linkage&&a.design.kind!=="direct"){let h=R=>c(R).linkage,b=an(n,a.linkage,a.design.kind),[g,y]=b?["left arm eye","right arm eye"]:["drop-link pickup","arm tip"];f(`roll.${r}.outer`,`${s.roll} ${g}`,[0,1,2],R=>h(R).outer,(R,k)=>u(R,{...c(R),linkage:{...h(R),outer:k}})),f(`roll.${r}.inner`,`${s.roll} ${y}`,[0,1,2],R=>h(R).inner,(R,k)=>u(R,{...c(R),linkage:{...h(R),inner:k}}))}let d=a.design;if(d.kind==="coil"&&typeof d.rate=="number"){let h=b=>c(b).design;p(`roll.${r}.rate`,`${s.roll} spring rate (@element)`,d.rate,b=>h(b).rate,(b,g)=>u(b,{...c(b),design:{kind:"coil",rate:g}}))}else d.kind==="direct"&&p(`roll.${r}.wheelRate`,`${s.roll} rate (@wheel)`,d.wheelRate,h=>c(h).design.wheelRate,(h,b)=>u(h,{...c(h),design:{kind:"direct",wheelRate:b}}))}}return t}var bV=[{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 gV(e){let t=[];for(let r of["front","rear"]){let n=Ve(e.vehicle,r).compliance;if(!n)continue;let o=(a,s,i,c)=>{let l=i(n);l===void 0||!(l>0)||!Number.isFinite(l)||t.push({id:`kc.${r}.${a}`,group:"Compliance",label:s,scope:qt[r],unit:"N/mm",defaultSpan:Math.max(500,l*.4),read:u=>i(Ve(u.vehicle,r).compliance??{})??l,write:(u,m)=>{let f=Ve(u.vehicle,r),p={...f,compliance:c(f.compliance??{},Math.max(1,m))};return{...u,vehicle:Dc(u.vehicle,r,p)}}})};for(let a of["ucaFront","ucaRear","lcaFront","lcaRear","tieRod","pushRod"])o(`link.${a}`,`${yV[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}`,`${xV[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 yV={ucaFront:"UCA front leg",ucaRear:"UCA rear leg",lcaFront:"LCA front leg",lcaRear:"LCA rear leg",tieRod:"tie rod",pushRod:"push/pull rod"},xV={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 RV(){return bV.map(e=>({id:`cfg.${e.axle}.${e.field}`,group:e.group,label:e.label,scope:qt[e.axle],unit:e.unit,defaultSpan:e.span(e.fallback),read:t=>Ve(t.vehicle,e.axle).config[e.field]??e.fallback,write:(t,r)=>{let n=Ve(t.vehicle,e.axle),o={...n,config:{...n.config,[e.field]:r}};return{...t,vehicle:Dc(t.vehicle,e.axle,o)}}}))}function vV(e){let t=Bn(e.params.steeringSystem);if(!t.enabled)return[];let r=(n,o,a,s,i)=>({id:`steeringSystem.${n}`,group:"Steering",label:o,unit:a,defaultSpan:s,read:c=>Bn(c.params.steeringSystem)[n],write:(c,l)=>({...c,params:{...c.params,steeringSystem:Bn({...c.params.steeringSystem,enabled:!0,[n]:i(l)})}})});return[r("roadFeedbackGain","road feedback gain","\xD7",Math.max(.1,.25*t.roadFeedbackGain),n=>Math.min(2,Math.max(0,n))),r("turnInFrictionNm","turn-in friction","N\xB7m",Math.max(.1,.5*t.turnInFrictionNm),n=>Math.max(0,n))]}function kV(e){let t=Mi(e.params),r=[];for(let n of["front","rear"]){if(t[n]!=="diff")continue;let o=eo(e.params.driveline?.[n]);if(o?.kind!=="clutch"&&o?.kind!=="torsen")continue;let a=(s,i)=>{let c=Nu[`${n}.${s}`];return{id:`driveline.${n}.${s}`,group:"Differential",label:c.label.charAt(0).toLowerCase()+c.label.slice(1),scope:qt[n],unit:c.unit===": 1"?"":c.unit??"",defaultSpan:i,read:l=>eo(l.params.driveline?.[n])?.[s],write:(l,u)=>({...l,params:{...l.params,driveline:_u({...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 MV(e){if(ru(e.params)!=="hydraulic")return[];let t=[{id:"brakeSetup.barFront",group:"Brakes",label:`${Dh("barFront").toLowerCase()}, front share`,unit:"-",defaultSpan:.05,read:a=>Lr(a.params.brakeSetup).barFront,write:(a,s)=>({...a,params:{...a.params,brakeSetup:Lr({...Lr(a.params.brakeSetup),barFront:s})}})}];if(!e.params.brakeModel)return t;let r=sr(e.params.brakeModel),n=(a,s)=>s.circuit?a[s.circuit][s.key]:a[s.key],o=(a,s,i)=>({id:`brakeModel.${a.circuit?`${a.circuit}.`:""}${String(a.key)}`,group:"Brakes",label:Lh(a.circuit?`${a.circuit}.${String(a.key)}`:a.key),unit:s,defaultSpan:i,read:c=>n(sr(c.params.brakeModel),a),write:(c,l)=>{let u=sr(c.params.brakeModel),m=a.circuit?{...u,[a.circuit]:{...u[a.circuit],[a.key]:l}}:{...u,[a.key]:l};return{...c,params:{...c.params,brakeModel:sr(m)}}}});return t.push(o({key:"masterFrontMm"},"mm",1.5),o({key:"masterRearMm"},"mm",1.5),o({key:"pedalRatio"},"-",.5),o({key:"pistonDiaMm",circuit:"front"},"mm",2),o({key:"pistonDiaMm",circuit:"rear"},"mm",2),o({key:"effRadiusMm",circuit:"front"},"mm",10),o({key:"effRadiusMm",circuit:"rear"},"mm",10)),r.valve!=="none"&&t.push(o({key:"valveKneeBar"},"bar",5)),r.valve==="proportioning"&&t.push(o({key:"valveSlope"},"-",.1)),t}var YF=e=>!!e&&typeof e=="object"&&"value"in e&&"label"in e;function WF(e){let t={...e};for(let r of Object.keys(t)){let n=t[r];YF(n)&&(t[r]={...n})}return t}function SV(e){let t=[];for(let r of Xk(e))for(let n of r.rows){let o=Math.abs(n.value);t.push({id:`param.${n.key}`,group:r.title,label:n.label,unit:n.unit,defaultSpan:o>0?o*.2:1,read:a=>{let s=a.params[n.key];return YF(s)?s.value:NaN},write:(a,s)=>{let i=WF(a.params);return Gu(i,n.label,s),{...a,params:i}}})}return t}function jF(e){let t={};for(let s of["front","rear"]){if(!Ve(e.vehicle,s).measured)continue;let c="this axle is described by measured curves, so its linkage is not solved";for(let l of HF)for(let{key:u}of l.keys)for(let m of Qt)t[`hp.${s}.${u}.${m}`]={why:c};for(let l of["uca","lca"])for(let u of An)t[`arm.${s}.${l}.${u}`]={why:c};for(let l of vo)t[`rocker.${s}.${l}`]={why:c};for(let l of["heave.outer","heave.anchor","roll.outer","roll.inner"]){let[u,m]=l.split(".");for(let f of Qt)t[`${u}.${s}.${m}.${f}`]={why:c}}t[`cfg.${s}.springRate`]={why:"the measured curve set carries its own spring rate"}}let r=["rockerPivotA","rockerPivotB","rockerToPushrod","rockerToDamper"];for(let s of["front","rear"]){if(Ve(e.vehicle,s).config.actuation!=="direct")continue;let i="this axle is direct-acting \u2014 there is no bell-crank";for(let c of r)for(let l of Qt)t[`hp.${s}.${c}.${l}`]={why:i};for(let c of vo)t[`rocker.${s}.${c}`]={why:i}}for(let s of["front","rear"]){let i=Ve(e.vehicle,s);if(i.measured||i.config.actuation!=="decoupled")continue;let c="this axle is decoupled \u2014 the corner damper is out of circuit";for(let l of["rockerToDamper","damperChassis"])for(let u of Qt)t[`hp.${s}.${l}.${u}`]={why:c,useInstead:`heave.${s}.outer.${u}`};t[`cfg.${s}.springRate`]={why:"a decoupled axle has no corner spring \u2014 its elements hold it up",useInstead:`heave.${s}.rate`}}for(let s of["front","rear"]){let i=Ve(e.vehicle,s),c=e.params[kp[s]]?.linkage;if(i.measured||!c||c.attach!=="rocker"||c.mount?.kind==="chassis")continue;let l=i.hardpoints,u=[0,1,2].map(f=>l.rockerPivotB[f]-l.rockerPivotA[f]),m=Math.hypot(u[0],u[1],u[2]);if(m>0)for(let f=0;f<3;f++)Math.abs(u[f]/m)<1-1e-12||(t[`heave.${s}.outer.${Qt[f]}`]={why:`the rocker shaft runs along ${Qt[f]} \u2014 this only slides the eye along it`})}for(let s of["front","rear"]){let i=Ve(e.vehicle,s);if(i.measured||i.config.layout!=="mcpherson")continue;let c="this axle is a McPherson strut \u2014 there is no upper arm";for(let l of["ucaFront","ucaRear","uprightUpper"])for(let u of Qt)t[`hp.${s}.${l}.${u}`]={why:c,useInstead:`hp.${s}.damperChassis.${u}`};for(let l of An)t[`arm.${s}.uca.${l}`]={why:c};for(let l of["link.ucaFront","link.ucaRear","bush.ucaFront","bush.ucaRear"])t[`kc.${s}.${l}`]={why:c}}for(let s of["front","rear"]){let i=Ve(e.vehicle,s);if(i.measured)continue;for(let l of["uca","lca"]){if(l==="uca"&&i.config.layout==="mcpherson")continue;let u=X0(i.hardpoints,l);if(u)for(let m of An)t[`arm.${s}.${l}.${m}`]={why:u,useInstead:`hp.${s}.${Xt[l].fore}.z`}}let c=qa(i.hardpoints);if(c&&i.config.actuation!=="direct")for(let l of vo)t[`rocker.${s}.${l}`]={why:c,useInstead:`hp.${s}.${ko.fore}.z`}}let n=[["arbFrontDesign","param.arb_front","the front anti-roll bar design in Vehicle Dynamics","front","roll"],["arbRearDesign","param.arb_rear","the rear anti-roll bar design in Vehicle Dynamics","rear","roll"],["heaveFrontDesign","param.heave_spring_front","the front third-spring design","front","heave"],["heaveRearDesign","param.heave_spring_rear","the rear third-spring design","rear","heave"]];for(let[s,i,c,l,u]of n){let m=e.params[s];if(!m?.design||m.design.kind==="none")continue;let f=m.design.kind==="direct"?`${u}.${l}.wheelRate`:`${u}.${l}.rate`;t[i]={why:`computed from ${c}`,useInstead:f}}let o=e.params.aeroModelId||e.params.aeroModel?xb:Rb;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(Vu))t[`param.${s}`]={why:i};for(let[s,i]of Object.entries(Bu(e.params)))t[`param.${s}`]={why:i};let a=ru(e.params);return a==="hydraulic"?t["param.brake_balance"]={why:"set by the balance bar and the brake hardware",useInstead:"brakeSetup.barFront"}:a==="tyre"&&(t["param.brake_balance"]={why:"tyre-limited brakes split as the grip does"}),t}function UF(e){let t={...FV,...jF(e)};for(let[n,o]of Object.entries(t))o.useInstead&&t[o.useInstead]&&(t[n]={why:o.why});let r=n=>{let o=t[n.id];return o?{...n,supersededBy:o}:n};return[...iV(e),...uV(e),...dV(e),...hV(e),...RV(),...vV(e),...MV(e),...kV(e),...gV(e),...SV(e.params)].map(r)}var AV={spring_front:"cfg.front.springRate",spring_rear:"cfg.rear.springRate"},FV=Object.fromEntries(Object.entries(yb).map(([e,t])=>[`param.${e}`,{why:t,useInstead:AV[e]}])),ct=e=>e.scope?`${e.scope} \xB7 ${e.label}`:e.label;function Ht(e){let t={};for(let n of UF(e))t[n.id]=n;let r=(n,o)=>{if(typeof o!="string")return;let a=xF(n,o);return a&&(n[o]=a),a};return new Proxy(t,{get:(n,o,a)=>typeof o=="string"&&!Object.hasOwn(n,o)?r(n,o)??Reflect.get(n,o,a):Reflect.get(n,o,a),has:(n,o)=>Reflect.has(n,o)||!!r(n,o)})}var ry=e=>e.step!==void 0&&Number.isFinite(e.step)&&e.step>0?e.step:0,ny=e=>ry(e)>0||(e.values?.length??0)>0,oy=e=>e.some(ny),XF=e=>1e-9*Math.max(1,Math.abs(e.lo),Math.abs(e.hi));function QF(e,t){if(!Number.isFinite(t))return t;if(e.values?.length){let s=e.values[0];for(let i of e.values)Math.abs(i-t)<Math.abs(s-t)&&(s=i);return s}let r=ry(e);if(!r||!Number.isFinite(e.start))return t;let n=XF(e),o=Math.round((t-e.start)/r),a=s=>e.start+s*r;return a(o)>e.hi+n&&a(o-1)>=e.lo-n?a(o-1):a(o)<e.lo-n&&a(o+1)<=e.hi+n?a(o+1):a(o)}var qF=(e,t)=>t.map((r,n)=>e[n]&&ny(e[n])?QF(e[n],r):r);function ay(e,t=1e3){if(e.values?.length)return e.values.length;let r=ry(e);if(!r||!Number.isFinite(e.start))return 1/0;let n=XF(e),o=Math.ceil((e.lo-n-e.start)/r),a=Math.floor((e.hi+n-e.start)/r);return Math.max(0,Math.min(t,a-o+1))}function sy(e,t,r){let n=qF(e.variables,t),o=n.every((a,s)=>a===t[s]);return{x:n,score:o?r:wr(e,n)}}function ly(e,t){if(!e.variables.some(JF))return e;let r=e.variables.filter(o=>o.follows&&!o.fixed).map(o=>({id:o.id,follows:o.follows})),n=e.variables.filter(o=>!o.fixed&&!o.follows).map(o=>{if(ew(o))return{...o,lo:Math.min(...o.values),hi:Math.max(...o.values)};if(!o.around)return o;let{around:a,fixed:s,...i}=o,c=t(o.id);return Number.isFinite(c)?{...i,lo:c-a.minus,hi:c+a.plus}:i});return r.length?{...e,variables:n,followers:r}:{...e,variables:n}}var JF=e=>!!(e.fixed||e.around||e.follows)||ew(e),ew=e=>!!e.values?.length&&(e.lo!==Math.min(...e.values)||e.hi!==Math.max(...e.values));function Dt(e,t){if(!t.variables.some(JF))return t;let r=Ht(e);return ly(t,n=>{let o=r[n];if(!o)return NaN;try{return o.read(e)}catch{return NaN}})}function Zt(e){return[...e.objectives,...e.constraints,...e.watches??[]]}var Ap=e=>(e.metrics??Ur()).byId;function uy(e,t){t=Dt(e,t);let r=Ht(e),n=[];for(let o of t.variables){let a=r[o.id];a&&n.push({id:a.id,name:ct(a),unit:a.unit,lo:o.lo,hi:o.hi,start:a.read(e),...o.step!==void 0?{step:o.step}:{},...o.values?{values:o.values}:{}})}return n}function Fp(e,t,r){t=Dt(e,t);let n=Ht(e),o=e;return t.variables.forEach((a,s)=>{let i=n[a.id];i&&Number.isFinite(r[s])&&(o=i.write(o,r[s]))}),dy(e,o,t.followers,n)}function my(e,t,r={}){let n=t.states??[],o=n.some(c=>c.follows);if(!o&&!t.envelopeFollows)return t;let a=Sn(e,{density:t.density,envelope:t.envelope,states:n,operating:t.operating,lap:t.lap,assemble:r.assemble,simParams:r.simParams,projectTrack:r.projectTrack,libraryTrack:r.libraryTrack,numerics:r.numerics}),s=n;if(o&&r.simParams)try{let c=a.ggv();c&&(s=n0(n,c,TV(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=Ap(r),u=py(t,l),m=Zt(t).map(h=>({r:h,m:l[h.metricId]})).filter(({m:h})=>h&&h.id.startsWith("kin.")&&h.reads!=="state"&&(h.scope==="car"||u.includes(h.scope))),f=h=>{let b=Sn(e,{density:t.density,envelope:h,assemble:r.assemble,numerics:r.numerics});return m.every(({r:g,m:y})=>Number.isFinite(kt(b,y,g.at)))},p=c.length===s.length?CV(e,a0(c,u),u):null,d=p&&m.length?wV(p,f):p;d&&!s0(d,t.envelope)&&(i=d)}return s===n&&i===t.envelope?t:{...t,states:s,envelope:i}}var Sp=3;function wV(e,t){let r=(c,l)=>t({...e,travelMin:c,travelMax:l}),n=e.travelMin-Sp,o=e.travelMax+Sp;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+Sp)),i=Math.max(1,Math.min(e.travelMax,o-Sp));return s===e.travelMin&&i===e.travelMax?e:{...e,travelMin:s,travelMax:i}}function py(e,t){let r=new Set;for(let n of Zt(e)){let o=t[n.metricId];if(!(!o||!o.id.startsWith("kin.")||o.reads==="state")){if(o.scope==="car")return["front","rear"];r.add(o.scope)}}return r.size?["front","rear"].filter(n=>r.has(n)):["front","rear"]}function CV(e,t,r){if(!t)return null;let n=za(e.vehicle,e.params),{travelMin:o,travelMax:a}=t;for(let s of r.map(i=>n[i]))try{let i=Ke(s,{travelMin:o,travelMax:a,steps:xc.travelSteps});if(i.covered)continue;let c=i.samples.filter(l=>l.converged).map(l=>l.travel);if(!c.length)continue;o=Math.max(o,Math.min(-1,Math.ceil(Math.min(...c))+1)),a=Math.min(a,Math.max(1,Math.floor(Math.max(...c))-1))}catch{continue}return o===t.travelMin&&a===t.travelMax?t:{...t,travelMin:o,travelMax:a}}function TV(e){let t=e.projectTrack?.();if(!t)return null;try{return r0(it(t.asset,t.numerics))}catch{return null}}function dy(e,t,r,n){if(!r?.length)return t;let o=t;for(let a of r){let s=n[a.id],i=n[a.follows];if(!s||!i)continue;let c=i.read(t)-i.read(e);Number.isFinite(c)&&c!==0&&(o=s.write(o,s.read(e)+c))}return o}function Ec(e,t){if(!Number.isFinite(t))return NaN;if(e.op==="max")return t-e.limit;if(e.op==="min")return e.limit-t;let r=e.limit2??e.limit;return Math.max(e.limit-t,t-r)}var tw=(e,t="")=>t&&t!=="-"?`${e} ${t}`:`${e}`;function rw(e,t,r){let n=t??Xa[e.metricId],o=(n?et(n):e.metricId)+Ic(e.at,n,r),a=s=>tw(s,n?.unit);return e.op==="max"?`${o} \u2264 ${a(e.limit)}`:e.op==="min"?`${o} \u2265 ${a(e.limit)}`:`${o} between ${e.limit} and ${a(e.limit2??e.limit)}`}function Ic(e,t,r){if(!e&&t?.reads!=="state")return"";e??={};let n=[];if(t?.reads==="state")if(e.stateId===br)n.push(B0(t));else{let o=e.stateId===void 0?r?.states?.[0]:r?.states?.find(a=>a.id===e.stateId);o&&n.push(o.name)}if(e.speed!==void 0&&O0(t)&&n.push(`${(e.speed*3.6).toFixed(0)} km/h`),e.ayG!==void 0&&V0(t)&&n.push(`${e.ayG.toFixed(2)} g`),e.courseId===Sc&&t?.reads==="course")n.push(N0(t));else if(e.courseId&&t?.reads==="course"){let o=r?.lap.courses.find(a=>a.id===e.courseId);o&&n.push(g0(o))}return n.length?` @ ${n.join(", ")}`:""}function nw(e,t,r){let n=r/t.scale;return e.goal==="min"?e.weight*n:e.goal==="max"?-e.weight*n:e.weight*Math.max(0,Math.abs(r-(e.target??0))-Math.max(0,e.tolerance??0))/t.scale}var ow=5e-4;function aw(e,t){return e.cost!=="lap"&&e.cost!=="session"?0:Number.isFinite(t)?ow*Math.abs(t):0}function wp(e,t,r={}){t=Dt(e,t);let n=uy(e,t),o=Ht(e),a=Ap(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=kt(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=Ec(h,g);y>0&&(p+=y/b.scale,d.push(`${rw(h,b,t)} (${tw(g.toFixed(3),b.unit)})`))}return d.length===0?Ks:{ok:!1,violation:p,reason:d.join("; ")}};return{name:"study",variables:n,build:m=>{let f=e;return t.variables.forEach((p,d)=>{let h=o[p.id];h&&(f=h.write(f,m[d]))}),f=dy(e,f,t.followers,o),{car:f,ev:Sn(f,{density:t.density,envelope:t.envelope,states:t.states,operating:t.operating,lap:t.lap,assemble:r.assemble,simParams:r.simParams,projectTrack:r.projectTrack,libraryTrack:r.libraryTrack,sessionParams:r.sessionParams,session:r.session,numerics:r.numerics})}},feasible:({ev:m})=>{let f=u(i,m);if(!f.ok)return f;for(let{spec:p,metric:d}of c)kt(m,d,p.at);for(let{spec:p,metric:d}of l)kt(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=kt(m,p,f.at);return{name:et(p)+Ic(f.at,p,t),raw:d,unit:p.unit,weight:f.weight,contribution:nw(f,p,d),resolution:Math.abs(f.weight)*aw(p,d)/p.scale}})}}function iy(e){let t=/^arm\.(front|rear)\.(uca|lca)\./.exec(e);if(t)return`${t[1]}.${t[2]}`;let r=/^rocker\.(front|rear)\./.exec(e);if(r)return`${r[1]}.rocker`;let n=/^hp\.(front|rear)\.(ucaFront|ucaRear|lcaFront|lcaRear|rockerPivotA|rockerPivotB)\./.exec(e);return n?n[2].startsWith("rocker")?`${n[1]}.rocker`:`${n[1]}.${n[2].startsWith("uca")?"uca":"lca"}`:null}function sw(e,t){if(e.variables.some(o=>o.id===t))return!0;let r=Mc(t);if(!r||!mp.includes(r.axis))return!1;if(e.variables.some(o=>yr(o.id)?.point===r.point))return!0;let n=iy(t);return!!n&&e.variables.some(o=>/^(arm|rocker)\./.test(o.id)&&iy(o.id)===n)}function PV(e,t){let r=e.followers??[],n=new Map(r.map(i=>[i.id,i.follows])),o=i=>{let c=t[i],l=Mc(i);return c&&l&&mp.includes(l.axis)?{name:ct({...c,label:c.label.replace(/ [xyz]$/,"")}),axis:l.axis}:{name:c?ct(c):`\u201C${i}\u201D`}},a=new Map,s=(i,c,l)=>{let u=a.get(i);u||a.set(i,u={text:l,axes:[]}),c&&u.axes.push(c)};for(let i of r){let c=t[i.id],l=t[i.follows],u=o(i.id),m=o(i.follows),f=p=>p&&p!=="x, y, z"?` in ${p}`:"";if(!c){s(`missing:${i.id}`,void 0,()=>`\u201C${i.id}\u201D is not a variable this car has.`);continue}if(c.supersededBy&&s(`superseded:${u.name}`,u.axis,p=>`${u.name}${f(p)} cannot be moved: ${c.supersededBy.why}.`),!l)s(`no-lead:${u.name}:${i.follows}`,u.axis,p=>`${u.name}${f(p)} moves with \u201C${i.follows}\u201D, which is not a variable this car has.`);else if(i.follows===i.id)s(`self:${u.name}`,u.axis,p=>`${u.name}${f(p)} cannot move with itself.`);else if(l.unit!==c.unit)s(`unit:${u.name}:${m.name}`,u.axis,p=>`${u.name}${f(p)} moves with ${m.name}, which is in ${l.unit} where it is in ${c.unit}. Link it to one in the same unit.`);else if(n.has(i.follows)){let p=o(n.get(i.follows));s(`chain:${u.name}:${m.name}`,u.axis,d=>`${u.name}${f(d)} moves with ${m.name}, which itself moves with ${p.name}. Link it to ${p.name}.`)}else sw(e,i.follows)||s(`still:${u.name}:${m.name}`,u.axis,p=>`${u.name}${f(p)} moves with ${m.name}, which the study does not move${f(p)}. Free that one, or give this its own bound.`)}return[...a.values()].map(i=>i.text(i.axes.join(", ")))}function fy(e,t,r={}){let n=t.variables.length>0&&t.variables.every(y=>y.fixed||y.follows),o=t.variables.some(y=>y.follows&&!y.fixed);t=Dt(e,t);let a=Ht(e),s=[],i=Ap(r),c=Zt(t).map(y=>y.metricId),l=c.some(y=>y.startsWith("dyn.")),u=c.some(y=>y.startsWith("lap."));if(c.some(y=>y.startsWith("kin."))){let y=t.envelope;y.travelMin<0&&y.travelMax>0||s.push("The travel the linkage is read over must reach both ways from the design ride: droop below zero, bump above."),(!(y.rollMaxDeg>0)||!(y.rollAtLimitDeg>=0))&&s.push("The roll the linkage is read over must be above zero.")}let m=Zt(t).filter(y=>i[y.metricId]?.reads==="state");if(m.length){let y=t.states??[];if(!y.length)s.push("This study reads targets at a state and has none. Take the car\u2019s five under Conditions.");else{let R=new Set([...y.map(k=>k.id),br]);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===br&&!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!==br?y.find(F=>F.id===k.at.stateId):void 0,M=x?H0(v,x):null;M?s.push(`${et(v)} ${M}. Point it at a state that does.`):!x&&!pp(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),Sc]);for(let y of Zt(t))if(y.at?.courseId&&!f.has(y.at.courseId)){let R=i[y.metricId];s.push(`${R?et(R):y.metricId} names a course this study no longer has. Point it at one of the courses below.`)}u&&t.lap.ggvMode==="fast"&&t.variables.some(R=>/arb_|spring|heave_|front_mass_diss|cg_height|^hp\./.test(R.id.replace("param.","")))&&s.push("The fast grip envelope is a point mass: no load transfer, no trim. It cannot see bars, springs, roll centres or where the mass sits, and this study moves at least one of those."),n?s.push(o?"Every variable is fixed or moves with another \u2014 there is nothing to search.":"Every variable is fixed \u2014 there is nothing to search."):t.variables.length===0&&s.push("No variables selected \u2014 there is nothing to search."),t.objectives.length===0&&s.push("No objective selected. Constraints alone say which designs are legal, not which is better.");for(let y of t.variables){let R=a[y.id];if(!R){s.push(`\u201C${y.id}\u201D is not a variable this car has.`);continue}if(y.values&&y.values.length<2?s.push(`${ct(R)}: list two values or more, or fix it where it is.`):y.hi>y.lo?y.step!==void 0&&ay({...y,start:R.read(e)})<2&&s.push(`${ct(R)}: a step of ${y.step} ${R.unit} leaves no other place to land in its box. Make the step finer or the box wider, or fix it.`):s.push(`${ct(R)}: the upper bound must be above the lower one (${y.lo} to ${y.hi}).`),R.supersededBy){let v=R.supersededBy.useInstead?a[R.supersededBy.useInstead]:void 0,x=v?ct(v):void 0;s.push(`${ct(R)} cannot be searched: ${R.supersededBy.why}.`+(x?` Use ${x} instead.`:""))}let k=R.read(e);Number.isFinite(k)&&(k<y.lo||k>y.hi)&&s.push(`${ct(R)} starts at ${k.toFixed(1)} ${R.unit}, outside its own bounds.`)}let p=t.followers??[],d=new Map;for(let y of[...t.variables.map(R=>R.id),...p.map(R=>R.id)]){let R=iy(y);if(!R)continue;let k=d.get(R);k||d.set(R,k={arms:[],coords:[]}),(/^(arm|rocker)\./.test(y)?k.arms:k.coords).push(y)}for(let[y,R]of d){if(R.arms.length===0||R.coords.length===0)continue;let k=x=>a[x]?ct(a[x]):x,v=y.endsWith("rocker")?"rocker":`${y.endsWith("uca")?"upper":"lower"} arm`;s.push(`${y.startsWith("front")?"The front":"The rear"} ${v} is being moved two ways at once \u2014 as an axis (${R.arms.map(k).join(", ")}) and as pivot coordinates (${R.coords.map(k).join(", ")}). They describe the same ${v}, so whichever is applied second overwrites the other. Keep one.`)}let h=new Map,b=new Set(p.map(y=>y.id));for(let y of[...t.variables.map(R=>R.id),...b]){let R=Mc(y);if(!R)continue;let k=yr(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(...PV(t,a));for(let y of t.constraints){let R=i[y.metricId];if(!R){s.push(`\u201C${y.metricId}\u201D is not a metric.`);continue}y.op==="band"&&!((y.limit2??y.limit)>y.limit)&&s.push(`${et(R)}: the band's upper limit must be above its lower one.`)}l&&!(t.operating.speed>0)&&s.push("Whole-car metrics need a speed to be read at; a yaw-moment diagram at rest is degenerate.");for(let y of Zt(t))if(y.at?.speed!==void 0&&!(y.at.speed>0)){let R=i[y.metricId];s.push(`${R?et(R):y.metricId} is asked for at rest, where a yaw-moment diagram is degenerate.`)}for(let y of t.watches??[])i[y.metricId]||s.push(`\u201C${y.metricId}\u201D is not a metric.`);let g=new Set;for(let y of Zt(t)){let R=i[y.metricId],k=R?.unavailable?.(e);!R||!k||g.has(R.id)||(g.add(R.id),s.push(`${et(R)} cannot be read on this car: ${k}.`))}for(let y of t.objectives)i[y.metricId]?y.weight>0?y.goal==="target"&&!Number.isFinite(y.target)?s.push(`${et(i[y.metricId])}: \u201Chit a value\u201D needs a value.`):y.goal==="target"&&y.tolerance!==void 0&&!(y.tolerance>=0)&&s.push(`${et(i[y.metricId])}: the tolerance must be zero or more.`):s.push(`${et(i[y.metricId])}: weight must be positive.`):s.push(`\u201C${y.metricId}\u201D is not a metric.`);return s}var iw=.1,cw=2e3,cy=3;function hy(e,t,r={},n=cw){t=Dt(e,t);let o=wp(e,t,r),a=Ap(r),s=Ht(e),i=o.variables.map(S=>S.start),c=S=>{let A=o.build(S);return o.feasible(A).ok&&o.terms(A),A},l=c(i),u=o.feasible(l),m=[...t.objectives,...t.constraints],f=(S,A=m)=>{let P={};for(let L of A){let D=a[L.metricId];D&&(P[`${L.metricId}@${Ro(L.at)}`]=kt(S.ev,D,L.at))}return P},p=S=>m.map(A=>S[`${A.metricId}@${Ro(A.at)}`]).map(A=>Number.isFinite(A)?A.toFixed(9):"x").join("|"),d=f(l,Zt(t)),h=p(d),b=[],g=[],y={},R=[],k=0;t.variables.forEach((S,A)=>{let P=s[S.id];if(!P)return;if(R.length>=cy&&k>n){g.push(P);return}let L=[...i];L[A]=i[A]+(S.hi-i[A])*.25||S.hi;let D=performance.now(),E=c(L),V=performance.now()-D;k+=V,R.push(V);let N=f(E);y[P.id]=N,p(N)===h&&b.push(P)});let v=t.variables[0],x=v?t.variables.indexOf(v):-1;for(let S=0;v&&R.length>0&&R.length<cy;S++){let A=[...i];A[x]=i[x]+(v.hi-i[x])*(.4+.15*S)||v.hi;let P=performance.now();c(A),R.push(performance.now()-P)}let M=[...R].sort((S,A)=>S-A),F=M.length?M[M.length>>1]:0,w=[],C=Zt(t).map(S=>S.metricId);if(C.some(S=>S.startsWith("dyn.trim")||S==="dyn.ymdMaxAy")){let S=l.ev.ymdLimit();S?.onGridEdge&&w.push("The yaw-moment diagram peaks on the edge of its swept grid, so the trim readings are where the sweep stopped rather than where the car does. Widen the \u03B2/\u03B4 envelope before trusting them."),!S&&l.ev.dynAvailable&&w.push("The yaw-moment diagram found no trim point, so anything read off the limit is unavailable.")}if(C.some(S=>S==="dyn.steeringTorque"||S==="dyn.steeringTorqueGradient")){let S=l.ev.tyre()?.model,A=S?sn(S):null;A==="assumed"?w.push("This tyre carries no explicit Mz coefficient block. Its steering-aligning contribution uses Magic Formula defaults, so optimise the curve only as a qualitative placeholder until Mz is imported or fitted."):A==="none"&&w.push("This tyre model has no aligning-moment curve. Steering metrics contain contact-patch force and jacking, but not the pneumatic-trail signal that normally warns the driver at the tyre limit.")}let T=["lap.minStabil","lap.understeerFrac"];if(C.some(S=>T.includes(S))){let A=l.ev.lapReserve()?.beyondFrac;if(A!==void 0&&Number.isFinite(A)){let P=(A*100).toFixed(0);A>=iw?w.push(`Over ${P} % of this course, some wheel is asked for more longitudinal force than its own tyre ellipse allows \u2014 the speed profile and the per-wheel reconstruction disagree that far. A reserve read there is the two models disagreeing rather than the car having nothing left, and a search pointed at one will optimise the disagreement. It concentrates in high-speed braking, so a shorter straight into the first corner is the usual cure.`):A>0&&w.push(`${P} % of this course is beyond the per-wheel tyre ellipse, which is the usual level of disagreement between the speed profile and the reconstruction. Reserves are readable; treat small differences between designs as smaller than they look.`)}}return w.push(...K0(l.ev,Zt(t).map(S=>({m:a[S.metricId],at:S.at})).filter(S=>!!S.m))),{msPerEval:F,values:d,samples:R.length,times:R,dead:b,moves:y,unprobed:g,warnings:w,beyondFrac:C.some(S=>T.includes(S))?l.ev.lapReserve()?.beyondFrac:void 0,startFeasible:u.ok,startReason:u.reason}}var DV=[{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:EV.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 EV=["setup:m","characteristics:peak_power","characteristics:power_to_weight","characteristics:cla","characteristics:cda","characteristics:pack_energy","characteristics:maxAy","characteristics:top_speed"];var _ie=new Set(DV.map(e=>e.kind));var lw={travel:{name:"Wheel travel",unit:"mm",axis:"Wheel travel (mm, + bump)",from:-25,to:25,step:1,reach:150},roll:{name:"Body roll",unit:"\xB0",axis:"Body roll (\xB0, + right side down)",from:-3,to:3,step:.25,reach:12},steer:{name:"Rack",unit:"mm",axis:"Rack (mm, + right)",from:-30,to:30,step:1,reach:80},pitch:{name:"Body pitch",unit:"\xB0",axis:"Body pitch (\xB0, + nose down)",from:-2,to:2,step:.25,reach:8}};var by=["FL","FR","RL","RR"],Mt=(e,t,r)=>({input:e,from:r?r[0]:lw[e].from,to:r?r[1]:lw[e].to,n:t}),Bie=[{id:"sides",name:"Inside and outside",cards:[{id:"camber-roll",form:"curves",title:"Camber to the road through roll",sweep:Mt("roll",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"toe-rack",form:"curves",title:"Wheel angle against the rack",sweep:Mt("steer",25),wheels:["FL","FR"],y:["toe"]},{id:"camber-rack",form:"curves",title:"Camber to the road through the steer",sweep:Mt("steer",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"load-roll",form:"curves",title:"Wheel loads through roll",sweep:Mt("roll",25),wheels:by,y:["wheelLoad"]},{id:"travel-roll",form:"curves",title:"Wheel travel through roll",sweep:Mt("roll",25),wheels:by,y:["travel"]},{id:"toe-roll",form:"curves",title:"Roll steer, all four",sweep:Mt("roll",25),wheels:by,y:["toe"]}]},{id:"maps",name:"Travel and steer together",cards:[{id:"camber-map",form:"surface",title:"Camber over travel and rack",sweep:Mt("travel",17),second:Mt("steer",13),wheels:["FL"],y:["camber"]},{id:"bump-steer-map",form:"map",title:"Bump steer over travel and rack",sweep:Mt("travel",17),second:Mt("steer",13),wheels:["FL"],y:["bumpSteer"]},{id:"bump-steer-family",form:"curves",title:"Bump steer through travel, at five rack positions",sweep:Mt("travel",25),second:Mt("steer",5,[-20,20]),wheels:["FL"],y:["bumpSteer"]},{id:"scrub-map",form:"surface",title:"Scrub radius over travel and rack",sweep:Mt("travel",17),second:Mt("steer",13),wheels:["FL"],y:["scrubRadius"]}]}];function gy(e){let t=Number(e);return Number.isFinite(t)?Math.min(th,Math.max(eh,t)):Ft}var mw=6e4;var Ece=[{within:60*6e4,every:mw},{within:1440*6e4,every:60*6e4},{within:720*60*6e4,every:1440*6e4},{within:1/0,every:10080*6e4}];var YV=new Set(["color","visible","source","origin"]),zce=["id",...YV];var fw=.18/1.18,hw={induction:{kind:"natural"}},bw=e=>e.breathing??hw;function Cp(e){switch(e?.kind){case"sae-j1349":return Ji(99e3,25);case"measured":return Ji(e.hPa*100,e.tempC);default:return Ji(101325,20)}}var jV=Cp(void 0);function gw(e,t){let r=Cp(e.rated),n=e.induction;if(n.kind==="boosted"){let o=n.boostKPa*1e3;return Math.min(n.maxPressureRatio*t.p,o)/Math.min(n.maxPressureRatio*r.p,o)*(t.pDry/t.p)/(r.pDry/r.p)}return t.pDry/r.pDry*Math.sqrt(r.T/t.T)}function yw(e,t){let r=e.induction;if(r.kind==="table"){let o=s=>$e(r.densityAltitudeM,r.powerPct,s),a=o(Cp(e.rated).densityAltitudeM);return a>0?Math.max(0,o(t.densityAltitudeM)/a):0}let n=e.frictionShare??fw;return Math.max(0,(gw(e,t)-n)/(1-n))}var dw=new WeakMap;function xy(e,t){let r=e.asRated??e,n=`${t.p}|${t.pDry}|${t.T}`,o=dw.get(r);o||dw.set(r,o=new Map);let a=o.get(n);if(a)return a;let s=yw(bw(r),t),i={...r,torque:r.torque.map(c=>c*s),asRated:r};return o.set(n,i),i}function qV(e){return JSON.parse(Ry(vy(e,"public/laptime/index.json"),"utf8")).tracks}var ZV=async e=>{let t=await fetch(e.url);if(!t.ok)throw new Error(`The track could not be read from ${Bm(e)} (${t.status}).`);return new Uint8Array(await t.arrayBuffer())};function xw(e,t=new Map,r=ZV){let n=qV(e);return async o=>{let a=o.kind==="catalogue"?`catalogue:${o.address}`:o.name,s=t.get(a);if(s)return structuredClone(s);let i;if(o.kind==="catalogue"&&o.link){if(!ic(o.address))throw new Error(`"${o.address}" is not a catalogue address`);if(!sc(o.link))throw new Error("This track is linked to a source this version does not read from.");i=await Gg(await r(o.link),o.link,o.address)}else if(o.kind==="catalogue"){if(!ic(o.address))throw new Error(`"${o.address}" is not a catalogue address`);let c=JSON.parse(Ry(vy(e,"public/catalogue",Hg(o.address)),"utf8"));i=await Yg(c,o.address)}else{let c=n.find(l=>l.name===o.name)?.file;if(!c)throw new Error(`"${o.name}" is not in the bundled catalogue`);i=JSON.parse(Ry(vy(e,"public/laptime",c),"utf8"))}return t.set(a,i),structuredClone(i)}}var JV=9.81;function Rw(e,t=e.tireModel,r=e.tireModelRear){if(!t)return e;let n=e.m.value*JV/4,o=Ma(e,t,r),a=Pe(o.front).rollingRadius(n),s=o.rear===o.front?a:Pe(o.rear).rollingRadius(n),i=e5(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 e5(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 t5=1e-6;function vw(e,t,r){let n=e.cgReference;if(!n||!e.cg_height)return e;let o=Gk(e,t,r);if(o===void 0||Math.abs(o-n.standingRadius)<t5)return e;let a=n.typed??e.cg_height.value;return{...e,cg_height:{...e.cg_height,value:ka(e.cg_height.value,n.standingRadius,o)},cgReference:{...n,standingRadius:o,typed:a}}}function kw(e,t,r){let n=e.rcRoad,o=e.rc_front,a=e.rc_rear;if(!n||!o||!a)return e;let s=Iu(e,t,r),i=Gr(o.value,n.gainFront,n.radiusFront,s.front),c=Gr(a.value,n.gainRear,n.radiusRear,s.rear);return i===o.value&&c===a.value?e:{...e,rc_front:{...o,value:i},rc_rear:{...a,value:c},rcRoad:{...n,radiusFront:s.front??n.radiusFront,radiusRear:s.rear??n.radiusRear}}}var Mw=e=>({brakeFade:e.brakeFade,airTempC:e.airTempC,diffYaw:e.diffYaw,...ec(e.air)?{air:e.air}:{}});var So=(e,t)=>t?e.find(r=>r.id===t)?.model:void 0;function Ao(e){return{tire:t=>So(e.tires,t),motor:t=>So(e.motors,t),aero:t=>So(e.aeros,t),battery:t=>So(e.batteries,t),brake:t=>So(e.brakes??[],t),damper:t=>So(e.dampers??[],t),suspensionOf:t=>za(ky(e,t),t)}}function ky(e,t){let r=So(e.suspensions,t.suspensionId);if(r)return r;let n=e.suspensions.find(o=>o.id===e.activeSuspensionId)??e.suspensions[0];if(!n)throw new Error("this project holds no suspension, so no car can be resolved");return n.model}function Fo(e,t,r){let n={front:t.tire(e.tireModelId),rear:t.tire(e.tireModelIdRear)};return My(Ik(t.suspensionOf(e),e,n),t,r)}function r5(e){return ec(e.air)?ZS(e.air,e.airTempC??Ft):void 0}var n5="the air the session states, at its venue";function o5(e,t){return t?{...e,rho:{...e.rho,value:t.rho},readouts:{...e.readouts,rho:n5}}:e}function a5(e,t,r){if(!r)return{rho:e.rho,motorModel:t,readouts:e.readouts};let{rho:n,readouts:o}=o5(e,r);return{rho:n,motorModel:t&&ft(t)?xy(t,r):t,air:r,readouts:o}}function My(e,t,r){let n=t.tire(e.tireModelId),o=t.tire(e.tireModelIdRear),a=kw(vw(Rw(Yk(Kk(Jk(e,t.aero(e.aeroModelId)),t.battery(e.batteryModelId)),t.damper(e.damperModelId),t.damper(e.damperModelIdRear)??t.damper(e.damperModelId)),n,o),n,o),n,o),{readouts:s,...i}=a5(a,t.motor(e.motorModelId),r5(r));return{...a,...i,...s?{readouts:s}:{},tireModel:n,...o?{tireModelRear:o}:{},aeroModel:t.aero(e.aeroModelId),batteryModel:t.battery(e.batteryModelId),brakeModel:t.brake(e.brakeModelId),damperModel:t.damper(e.damperModelId),...fi(e,t.damper),ggvMode:r.ggvMode,quasiTransient:r.quasiTransient??!1,motorThermal:r.motorThermal??!1,brakeFade:r.brakeFade??!1,...r.airTempC!==void 0?{airTempC:r.airTempC}:{},...r.diffYaw?{diffYaw:!0}:{},airSettled:!0}}var l5=e=>e!==!1,u5=(e,t,r)=>r&&t>0?(e%t+t)%t:Math.min(Math.max(e,0),t);function m5(e,t,r){let n=e.points.filter(o=>Number.isFinite(o.at)&&Number.isFinite(o.z)).map(o=>({...o,at:u5(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 p5(e,t,r){let n=m5(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 d5(e,t,r,n){let o=t-e.at;return n&&r>0?o-r*Math.round(o/r):o}function f5(e,t,r,n){for(let s of e){let i=d5(s,t,r,n);if(s.half>0&&Math.abs(i)<s.half){let c=i+s.half;return s.z-s.gIn*s.half+s.gIn*c+(s.gOut-s.gIn)/(4*s.half)*c*c}}let o=e[e.length-1],a=n?t-o.at+(t<o.at?r:0):t-o.at;for(let s of e)s.at<=t&&(o=s,a=t-s.at);return!n&&t<e[0].at?e[0].z:o.z+o.gOut*a}function Sw(e,t,r,n){let o=l5(n),a=p5(e,r,o);return a.length?t.map(s=>f5(a,s,r,o)):t.map(()=>0)}function _c(e,t){if(!t?.points.length)return e;let r=dc(e),{zSmoothing:n,...o}=e;return{...o,z:Sw(t,r,d0(e),e.closed)}}var Tp={widthLeft:1.5,widthRight:1.5,bank:0,mu:1};function Aw(e){return e.kind==="bundled"?{kind:"bundled",name:e.name}:e.kind==="catalogue"?{kind:"catalogue",id:e.id,address:e.address,...e.link?{link:e.link}:{}}:null}async function Nc(e,t){let r=Aw(e.source);return Fw(e,r?await t(r):void 0)}function Fw(e,t){let{source:r}=e;if(r.kind==="segments"){let{segments:i,closed:c,spacing:l}=r,{asset:u}=hc(i,{name:e.name,closed:c,spacing:l,base:Tp});return _c(u,r.profile)}let n=r.sections??[];if(r.kind==="inline")return _c(Um(r.asset,n,Tp),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 _c(Um({...t,...o!==void 0?{widthLeft:o}:{},...a!==void 0?{widthRight:a}:{},...s!==void 0?{closed:s}:{}},n,Tp),r.profile)}var xme=1/500;var Rme=5*Math.PI/180;var Tme=1/3;var y5=[4,2,1,.5,.25,.125];function ww(e,t,r={}){let n=[...r.steps??y5].sort((g,y)=>y-g),o=st(r.numerics),a=r.tolPct??.5,s=wt(e),i=e.ggvMode??"twoTrack",c=pr(s,!1,i),l={...o,dsTarget:n[0]??o.dsTarget},u=n.length?ao(s,c,[it(t,l)],l,i):void 0,m=xn(s,c.rows),f=n.map((g,y)=>{let R={...o,dsTarget:g},k=Date.now(),v=it(t,R),x=Rt(c,v,R,{...u?{load:u}:{},...m?{shifts:m}:{}});return r.onStep?.(y+1,n.length),{dsTarget:g,npts:v.npts,lapTime:x.laptime,ms:Date.now()-k}}),p=f[f.length-1]?.lapTime??NaN,d=f.map(g=>{let y=g.lapTime-p;return{...g,delta:y,deltaPct:p?100*y/p:NaN}}),h=d.filter(g=>Math.abs(g.deltaPct)<=a),b=h.length?Math.max(...h.map(g=>g.dsTarget)):null;return{points:d,reference:p,recommended:b,tolPct:a}}function Za(e,t={}){let r=e.settings,n=t.ggvMode??r.ggvMode,o=(t.quasiTransient??r.quasiTransient)&&n!=="fast",a=e.tracks.find(s=>s.id===e.activeTrackId)??e.tracks[0];return{ggvMode:n,quasiTransient:o,motorThermal:t.motorThermal??r.motorThermal,brakeFade:t.brakeFade??r.brakeFade,airTempC:gy(t.airTempC??r.airTempC),...ec(Pm(t.air??r.air))?{air:Pm(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 Pp(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 Nc(r,t)}}function v5(e,t){let r=structuredClone(e);for(let[n,o]of Object.entries(t))if(!Gu(r,n,o))throw new Error(`no parameter is labelled "${n}" on this car \u2014 read vehicle_get for the labels it has`);return r}var Sy=(e,t)=>{let r=e?.name;return typeof r=="string"&&r?r:t};function k5(e,t){let r={};for(let n of kn){let o=e[n.doc]??[];for(let i of n.slots.slice(1)){let c=t[i.ref],l=typeof c=="string"?o.find(u=>u.id===c):void 0;l&&(r[i.key]={id:l.id,name:Sy(l.model,l.id)})}let a=t[n.ref],s=typeof a=="string"?o.find(i=>i.id===a):void 0;if(s){r[n.doc]={id:s.id,name:Sy(s.model,s.id)};continue}if(n.doc==="suspensions"){let i=o.find(c=>c.id===e.activeSuspensionId)??o[0];r[n.doc]=i?{id:i.id,name:Sy(i.model,i.id),byFallback:!0}:null;continue}r[n.doc]=null}return r}function M5(e){return Object.values(e.events).map(t=>({id:t.id,label:t.label,kind:t.kind,time:t.time,lapTime:t.lapTime,distance:t.distance,laps:t.laps,...t.energy?{energyConsumedKwh:t.energy.consumed,energyRemaining:t.energy.remainingFraction}:{},...t.lapsOverridden?{lapsOverridden:t.lapsOverridden}:{},...t.incomplete?{incomplete:t.incomplete}:{},...t.energyTarget?{energyTarget:t.energyTarget}:{}}))}function Cw(e){let t=new Map;for(let{name:r,events:n}of e)for(let o of n){let a=t.get(o.label);a||t.set(o.label,a={event:o.label,finished:[],stopped:[]}),(o.incomplete?a.stopped:a.finished).push(r)}return[...t.values()].filter(r=>r.stopped.length>0)}var Tw=e=>e.length<2?e[0]??"":`${e.slice(0,-1).join(", ")} and ${e[e.length-1]}`;async function Lp(e,t,r={}){let n=Za(e,r.settings),{entry:o,asset:a}=await Pp(e,t),s=Ao(e),i=r.vehicleIds?.length?r.vehicleIds.map(d=>{let h=e.vehicles.find(b=>b.id===d);if(!h)throw new Error(`this project holds no vehicle "${d}"`);return h}):e.vehicles.filter(d=>d.visible);if(!i.length)throw new Error("no vehicle is visible in this project \u2014 name some in vehicleIds");let c=i.map(d=>{let h=r.overrides?.[d.id]?v5(d.params,r.overrides[d.id]):d.params;return Fo(structuredClone(h),s,n)}),l=ji(uo(e.meta.rulesetId,e.rulesets)),u=Zi(c,a,n.numerics,l,{racingLine:n.racingLine,standingStart:n.standingStart,lapCounts:n.lapCounts}),m={};i.forEach((d,h)=>{m[d.id]=u[h]});let{scores:f,field:p}=yg(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:M5(u[h]),metrics:xg(l,u[h],p?.[d.id]),fitted:k5(e,d.params),...f?.[d.id]?{score:{total:f[d.id].total,parts:{...f[d.id].parts}}}:{}})),raw:{results:m,scores:f,field:p}}}async function Pw(e,t,r){let n=e.vehicles.find(i=>i.id===r.vehicleId);if(!n)throw new Error(`this project holds no vehicle "${r.vehicleId}"`);let o=Za(e),{asset:a}=await Pp(e,t),s=Fo(structuredClone(n.params),Ao(e),o);return ww(s,a,{...r.steps?{steps:r.steps}:{},numerics:o.numerics,...r.tolPct!==void 0?{tolPct:r.tolPct}:{},...r.onStep?{onStep:r.onStep}:{}})}var S5=(e,t)=>e[t]??[],A5=(e,t,r)=>r<=1?[e]:Array.from({length:r},(n,o)=>e+(t-e)*o/(r-1));function Dp(e){return e.kind==="param"?A5(e.start,e.end,Math.max(1,Math.round(e.steps))):e.kind==="part"?[...e.partIds]:[...e.values]}var Lw=e=>e.kind==="param"?e.label:e.kind==="part"?`${e.part} model`:e.setting;function F5(e,t){let r=e.vehicles.find(i=>i.id===t.vehicleId);if(!r)throw new Error(`this project holds no vehicle "${t.vehicleId}"`);if(!t.axes.length)throw new Error("a sweep needs at least one axis");let n=Fo(structuredClone(r.params),Ao(e),Za(e)),o=qk(n,{geometry:!0}),a=$u(n);for(let i of t.axes){if(i.kind==="param"){let c=a.find(u=>u.label===i.label);if(!c)throw new Error(`no parameter is labelled "${i.label}" on this car \u2014 read vehicle_get for the labels it has`);let l=o[c.key];if(l)throw new Error(`"${i.label}" is a readout on this car, not an input: ${l}. Sweeping it would report exactly zero. Sweep what produces it instead.`)}if(i.kind==="part"){let c=kn.find(l=>l.doc===i.part);if(!c)throw new Error(`"${i.part}" is not a library \u2014 it is one of ${kn.map(l=>l.doc).join(", ")}`);for(let l of i.partIds)if(!S5(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*Dp(c).length,1);if(s>Fm)throw new Error(`that grid is ${s} runs, over the ${Fm} cap \u2014 a run is a whole session. Drop an axis or use fewer steps.`)}var w5=e=>e.map(t=>String(typeof t=="number"?Number(t.toPrecision(4)):t)).join(" \xD7 ");function C5(e,t){let r=[...new Set(e.flatMap(o=>(o.didNotFinish??[]).map(a=>a.label)))],n=e.map(o=>({name:w5(o.at),events:r.map(a=>({label:a,incomplete:o.didNotFinish?.find(s=>s.label===a)}))}));return Cw(n).map(({event:o,finished:a,stopped:s})=>{let i=`${s.length} of ${e.length} points did not finish ${o}`;if(!a.length)return`${i}: every time there is a part-distance${t?" and scores zero":""}, so compare laps before time.`;let c=s.length>6?`${s.slice(0,6).join(", ")}, \u2026`:Tw(s);return t?`${i}: ${c}. Their time there is a part-distance and scores zero, so read them as stopped, not slow \u2014 a points ranking favours the points that finished over faster ones that stopped.`:`${i}: ${c}. Their time there is a part-distance, so read them as stopped, not slow.`})}function T5(e){let t=[[]];for(let r of e){let n=Dp(r),o=[];for(let a of n)for(let s of t)o.push([...s,a]);t=o}return t}async function Dw(e,t,r,n){F5(e,r);let o=T5(r.axes),a=[],s=!1;for(let[u,m]of o.entries()){let f=structuredClone(e),p=f.vehicles.find(k=>k.id===r.vehicleId),d={...r.settings},h={};r.axes.forEach((k,v)=>{let x=m[v];if(k.kind==="param")h[k.label]=x;else if(k.kind==="part"){let M=kn.find(F=>F.doc===k.part);p.params[M.ref]=x}else d[k.setting]=x});let b=r.fleet?f.vehicles.filter(k=>k.visible||k.id===r.vehicleId).map(k=>k.id):[r.vehicleId],g=await Lp(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(Dp(u).length<2)return;i.some(p=>{if(new Set(a.map(b=>`${b.at[m]}`)).size<2)return!1;let h=a.map(b=>b.metrics[p]).filter(Number.isFinite);return Math.max(...h)-Math.min(...h)>1e-9})||c.push(Lw(u))});let l=[];return s&&!r.fleet&&l.push("Points here were scored with this car alone, so it takes the maximum in every event and the points axis is flat by construction. Re-run with fleet: true to price a change in points."),l.push(...C5(a,s)),c.length&&l.push(`Nothing moved along ${c.join(", ")}. Exactly zero is a wiring question before it is a finding: check that a library part is not superseding the value, and that the switch it needs is on.`),{axes:r.axes.map(u=>({kind:u.kind,label:Lw(u),values:Dp(u)})),runs:a,metricKeys:i,fleetScored:s,flat:c,caveats:l}}var _de=Math.PI/180;function Ay(e){if(!e.chassis)return e;let{chassis:t,...r}=e;return r}var Zge=180/Math.PI;var M3={id:"racecar",label:"Race car",description:"Suspension kinematics, tyres, powertrain and quasi-steady-state lap simulation for a four-wheeled race car.",tools:["laptime","garage","kinematics","track","studies","dynamics","tires","aero","powertrain","battery","brakes","dampers","forces","calibration"],defaultRulesetId:lo,templateIds:["fs-ev-comparison","fs-endurance-energy","fs-ev-single","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor","formula-1","touring-car","street-car","cup-car","stock-car","hill-climb","race-truck","suspension","direct-coilover","pushrod","pullrod","third-spring","mcpherson-strut","tyre-study"],collections:[{id:"start",label:"Start here",description:"What the model answers, then cars to build from.",templateIds:["fs-ev-comparison","fs-endurance-energy","suspension","tyre-study","fs-ev-single","formula-1","touring-car"]},{id:"formula-student",label:"Formula Student",description:"Electric and combustion cars on the five Formula Student events, by drive layout.",templateIds:["fs-ev-comparison","fs-endurance-energy","suspension","tyre-study","fs-ev-single","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor"]},{id:"circuits",label:"Circuit racing",description:"Single-seaters, GT, cup and road cars and a race truck on real circuits, with their heights.",templateIds:["formula-1","touring-car","street-car","cup-car","race-truck"]},{id:"ovals-hill-climbs",label:"Ovals and hill climbs",description:"A banked oval, and an open course climbed from rest in thin air.",templateIds:["stock-car","hill-climb"]},{id:"kinematics",label:"Suspension and kinematics",description:"Each suspension architecture: its hardpoints, its roll centres and what it does on track.",templateIds:["suspension","direct-coilover","pushrod","pullrod","third-spring","mcpherson-strut"]},{id:"tyres",label:"Tyres",description:"Grip curves, and what a tyre is worth on track.",templateIds:["tyre-study"]},{id:"powertrain",label:"Energy and powertrain",description:"What a pack lasts, and how each drive layout puts its power down.",templateIds:["fs-endurance-energy","fs-combustion","fs-ev-awd","fs-ev-rwd-hubs","fs-ev-one-motor"]}]};var Aye=M3.id;var Oc=.02;function Ww(e){let t=Math.max(Oc,Math.abs(e.heaveMotionRatio)),r=Math.max(Oc,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 A3=(e,t)=>({od:t,id:Math.min(e.id,t-.5)}),F3=(e,t)=>e/(2*t*t);function Yw(e,t){switch(e.kind){case"ubar":case"blade":case"torsionTube":return{...e,section:A3(e.section,t)};default:return e}}function jw(e,t,r){let n=Math.max(Oc,Math.abs(r));if(e?.kind==="coil"){let l=F3(t,n),u=e.rate;if(typeof u=="number")return{...e,rate:l};let m=Br(u,0);if(!(m>0))return{...e,rate:l};let f=l/m;return{...e,rate:{...u,y:u.y.map(p=>p*f)}}}let o=t/(n*n),a=e&&(e.kind==="ubar"||e.kind==="blade"||e.kind==="torsionTube")?e:{kind:"torsionTube",section:{od:20,id:16},length:400,leverArm:60,G:8e4},s=l=>yi(Yw(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 Yw(a,c)}function Uw(e,t,r,n){let o=e?.design,a=jw(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 w3=Math.PI/180,Ep=1e-6;function C3(e){return!(ve(e.rockerPivotA,e.rockerPivotB)<Ep||ve(e.rockerToPushrod,e.rockerPivotA)<Ep||ve(e.rockerToDamper,e.rockerPivotA)<Ep||ve(e.rockerToDamper,e.damperChassis)<Ep)}function Zw(e){if(!C3(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 Jw(e){if(e.config.actuation!=="direct"||Zw(e))return;let{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}=P3(e);return{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}}var Xw=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),T3)),i=t.armRod??Math.max(25,.15*a),c=t.armDamper??i,l=[s[0]-Xw,s[1],s[2]],u=[s[0]+Xw,s[1],s[2]],m=Q(H(u,l)),f=H(n,s),p=Q(H(f,U(m,Qw(f,m)))),d=It(p,m,(t.armAngleDeg??60)*w3),h=ee(s,U(d,i)),b=H(o,s),g=Q(H(b,U(m,Qw(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 T3=.72,Qw=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2];function qw(e){let t=Ke(e,{travelMin:-5,travelMax:5,steps:3}),[r,,n]=t.samples;if(!r||!n)return 0;let o=n.travel-r.travel;return o!==0?Math.abs((n.metrics.damperLength-r.metrics.damperLength)/o):0}function P3(e,t={}){let r=t.target??qw(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=tt(h),g=ye(b,15,0),y=ye(b,-15,0);if(g.ok&&y.ok&&g.state.metrics.damperLength<y.state.metrics.damperLength)return p}catch{}}return 1})(),c=(p,d)=>{try{return qw({...e,config:{...e.config,actuation:"rocker"},hardpoints: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 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 Ip(e,{armRod:u,armAngleDeg:n,armDamper:m,damperSide:i})}var Bye=Array.from({length:19},(e,t)=>-45+5*t);var $ye=Math.PI/180;function L3(e){let t=e.hardpoints,r=Q(H(t.rockerPivotB,t.rockerPivotA)),n=tn(t.rockerToDamper,t.rockerPivotA,r),o=.6*en(H(t.rockerToDamper,n)),a=ae(r,Tx),s=en(a)>1e-6?Q(a):Q(H(t.rockerToDamper,n));return{outer:ee(n,U(s,o)),inner:ee(n,U(s,-o)),attach:"rocker"}}var D3=(e,t)=>({...e,config:{...e.config,actuation:t}});function Cy(e,t,r,n){let o=r==="front"?e.front:e.rear,a=Tu(o),s=o.config.springRate*a*a,i=q(t,r==="front"?"damper_front":"damper_rear")*a*a,c=r==="front"?t.arbFrontDesign:t.arbRearDesign,l=Zn(e,t)[r]??q(t,r==="front"?"arb_front":"arb_rear"),u=va(e,t)[r]??q(t,r==="front"?"heave_spring_front":"heave_spring_rear"),m=Jw(o),f=D3(m?{...o,hardpoints:{...o.hardpoints,...m}}:o,"decoupled"),p=r==="front"?t.heaveFrontDesign:t.heaveRearDesign,d=n?.heave??eC(p?.linkage,w=>En(f,w).atDesign)??Qd(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??eC(h?g:c?.linkage,w=>jo(f,w,{kind:b}).atDesign)??(h?L3(f):gk(f)),R=En(f,d).atDesign,k=jo(f,y,{kind:b}).atDesign,v=Lu(e,t),x=Ww({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=Uw({design:p?.design??{kind:"none"},linkage:d,damper:p?.damper},M,x,k);return m?{...F,crank:m}:F}function eC(e,t){return e&&Math.abs(t(e))>=Oc?e:void 0}var _p=[{id:"direct",name:"Direct-acting coilover",family:"GT / touring car",description:"Each lower wishbone drives a coilover straight into a chassis tower. No rod or rocker in the load path.",scope:"Both axles",tags:["Double wishbone","Coilover","Direct acting"]},{id:"pushrod",name:"Pushrod suspension",family:"Formula / prototype",description:"A rod from the lower wishbone pushes a rocker on the chassis shoulder. A 225 mm damper runs along the top at 1:1.",scope:"Both axles",tags:["Pushrod","Rocker","Inboard damper"]},{id:"pullrod",name:"Pullrod suspension",family:"Formula / low package",description:"A rod from the upper wishbone pulls a low rocker inside the side wall. A 225 mm damper runs along the floor at 1:1.",scope:"Both axles",tags:["Pullrod","Low rocker","Inboard damper"]},{id:"heave",name:"Third heave spring",family:"Formula / aero platform",description:"The pushrod car plus a front third spring worked by both rockers. It picks up after 5 mm of bump and stays out of roll.",scope:"Both axles, plus a front third spring",tags:["Pushrod","Third spring","Aero platform"]},{id:"decoupled",name:"Twin-rocker-bar decoupled modes",family:"Formula / prototype",description:"Each pushrod turns a long rocker bar. A shock between the bars takes heave, a diagonal one takes roll; no corner springs.",scope:"Both axles",tags:["Two rocker bars","Heave shock","Roll shock"]},{id:"mcpherson",name:"McPherson strut",family:"Road car",description:"A strut clamped to the upright runs up to a top mount on the tower: damper, spring seat and upper link in one. Coilover wishbones at the rear.",scope:"Front struts, rear double wishbones",tags:["McPherson","Strut","Road car"]}],Ty=()=>({arbFront:void 0,arbRear:void 0,heaveFront:void 0,heaveRear:void 0}),E3={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]}},I3={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]}},_3=()=>({outer:[0,189,486],attach:"rocker",mount:{kind:"chassis",anchor:[-225,0,486]}}),N3={rate:60,motionRatio:1},O3={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]}},V3=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]}},B3={kind:"coil",rate:1560,motionRatio:1,gap:0,bothWays:!0},$3=40,G3={rockerPivotA:[50,130,440],rockerPivotB:[-50,130,440],rockerToPushrod:[10,170,460],rockerToDamper:[-20,64,440],damperChassis:[-20,64,215]},tC=()=>({outer:[-50,130,480],attach:"rocker",shaftStation:-50}),rC=()=>({outer:[50,130,400],inner:[50,130,480],attach:"rocker",shaftStationOuter:50,shaftStationInner:50}),K3=e=>[e[0],e[1],e[2]];function H3(e){let t=r=>({...r,hardpoints:{...r.hardpoints,...oC(G3)},config:{...r.config,actuation:"decoupled"}});return{...e,front:t(e.front),rear:t(e.rear)}}function oC(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,K3(r)]))}function aC(e,t=bo(),r=e==="pull"?I3:E3){let n=(o,a)=>({...o,hardpoints:{...o.hardpoints,...oC(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 Np(e,t){let r=Py(e),n=Ja(e);if(e==="heave")return{meta:r,vehicle:n,components:{...Ty(),heaveFront:{design:{...db,...N3},linkage:_3()}}};if(e!=="decoupled")return{meta:r,vehicle:n,components:Ty()};let o=Cy(n,t,"front",{heave:tC(),roll:rC()}),a=Cy(n,t,"rear",{heave:tC(),roll:rC()});return{meta:r,vehicle:n,components:{arbFront:o.arb,arbRear:a.arb,heaveFront:o.heave,heaveRear:a.heave}}}function Ja(e){let{name:t}=Py(e);if(e==="direct")return{...rc(),name:t};if(e==="mcpherson"){let n=nc(),o=Dm();return{...n,front:{...o,config:{...o.config,loadedRadius:n.front.config.loadedRadius}},name:t}}let r=z3(aC(e==="pullrod"?"pull":"push"));return{...e==="decoupled"?H3(r):r,name:t}}var nC={front:221.7,rear:220.9};function z3(e){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:nC.front}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:nC.rear}}}}function Py(e){let t=_p.find(r=>r.id===e);if(!t)throw new Error(`Unknown suspension template: ${e}`);return t}function Op(){let e=t=>({design:{...B3},linkage:V3(t),damper:$3});return{meta:Py("heave"),vehicle:aC("push",Fg(),O3),components:{...Ty(),heaveFront:e("front"),heaveRear:e("rear")}}}var sC=[10,25,50,100,200,300],Y3=[{id:"c1",label:"Soft",scale:.7},{id:"c2",label:"Medium",scale:1},{id:"c3",label:"Firm",scale:1.4}],iC=e=>Math.round(e*100)/100;function W3(e,t,r){let n=sC.map(o=>iC(r*o));return{id:e,label:t,speedMmS:[...sC],bumpN:n,reboundN:[...n]}}function j3(e){return{name:e.name,body:{...e.body},curves:Y3.map(t=>W3(t.id,t.label,iC(e.coefficient*t.scale)))}}function Vc(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 xr(e,t){let r=i=>{if(!i)return;let c=e.dampers.length+1;for(;e.dampers.some(u=>u.id===`dmp${c}`);)c++;let l=`dmp${c}`;return e.dampers.push({id:l,color:lc[e.dampers.length%lc.length],model:j3(i)}),l},n=r(t.car),o=r(t.rear),a=r(t.heave),s=r(t.roll);for(let i of e.vehicles){let c=i.params;c.damperModelId=n,o&&(c.damperModelIdRear=o),a&&(c.heaveDamperModelId=a),s&&(c.rollDamperModelId=s)}}var lt=e=>`${e} (typical)`,Ly={car:{name:lt("Formula Student damper"),coefficient:2.5,body:{extended:249,stroke:55}}},Vp={car:Ly.car,heave:{name:lt("Formula Student heave damper"),coefficient:3.4,body:{extended:270,stroke:47}},roll:{name:lt("Formula Student roll damper"),coefficient:3.7,body:{extended:322,stroke:100}}},Bp={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}}},cC={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}}},lC={car:{name:lt("Sports car strut"),coefficient:2.4,body:{extended:310,stroke:120}},rear:Dy.car},uC={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}}},mC={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}}},pC={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}}},dC={car:{name:lt("Race truck front damper"),coefficient:12,body:{extended:780,stroke:160}},rear:{name:lt("Race truck rear damper"),coefficient:8.5,body:{extended:780,stroke:160}}};function ts(e){return e.vehicles=e.vehicles.slice(0,1),e.activeVehicleId=e.vehicles[0]?.id??null,e}function wn(e,t){let r=uc(e);return r.meta.rulesetId=t,r}function wo(e,t,r,n){let o=wn(e,t);return o.suspensions=[{...o.suspensions[0],model:n()}],o.vehicles=[Zg(r,"v1",0)],o.activeVehicleId="v1",o}var[,U3,X3,Q3,q3,Z3,J3,eB]=Ig;function Ey(e,t){delete e.arbFrontDesign,delete e.arbRearDesign,delete e.heaveFrontDesign,delete e.heaveRearDesign,t.arbFront&&(e.arbFrontDesign=structuredClone(t.arbFront)),t.arbRear&&(e.arbRearDesign=structuredClone(t.arbRear)),t.heaveFront&&(e.heaveFrontDesign=structuredClone(t.heaveFront)),t.heaveRear&&(e.heaveRearDesign=structuredClone(t.heaveRear))}function fC(){return{...Ja("decoupled"),name:bo().name}}var tB=[{label:"Formula Student (decoupled)",vehicle:fC,components:e=>Vc(Np("decoupled",e).components,Vp)},{label:"Formula 1 (third springs)",vehicle:()=>Op().vehicle,components:()=>Vc(Op().components,Bp)}],Iy={"direct-coilover":"direct",pushrod:"pushrod",pullrod:"pullrod","third-spring":"heave","mcpherson-strut":"mcpherson"},rB=[...tB.map(e=>e.vehicle),...Object.values(Iy).map(e=>()=>Ja(e))];function es(e){let t=Vc(Np("decoupled",e.vehicles[0].params).components,Vp);e.suspensions=[{...e.suspensions[0],model:fC()}];for(let r of e.vehicles)Ey(r.params,t);return xr(e,Vp),e}var Co={title:"OpenStreetMap",url:"https://www.openstreetmap.org/copyright",licence:"ODbL-1.0",credit:"\xA9 OpenStreetMap contributors"},$p={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"},hC={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]"},bC={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"},nB={id:"cota",name:"Circuit of the Americas, Austin",address:"e0c6ea889d708cf15f9c",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,$p,bC]}},oB={id:"laguna-seca",name:"Laguna Seca, Monterey",address:"185b5811b9c423ef44ef",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,$p,bC]}},aB={id:"nordschleife",name:"Nordschleife, N\xFCrburg",address:"74c49603c7b2f15985c6",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,hC]}},sB={id:"brands-hatch",name:"Brands Hatch, Kent",address:"c4953e3c25eaba4a5b7e",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,{title:"Environment Agency LIDAR Composite DTM, 1 m",url:"https://environment.data.gov.uk/dataset/13787b9a-26a4-4775-8523-806d13af58fc",licence:"OGL-UK-3.0",credit:"\xA9 Environment Agency copyright and/or database right 2022. All rights reserved."}]}},iB={id:"bristol",name:"Bristol, Tennessee",address:"f0e23953669a414ad600",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,$p]}},cB={id:"pikes-peak",name:"Pikes Peak, Colorado",address:"3de137fe33b5c2875036",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,$p]},standingStart:!0},lB={source:"venue",altitudeM:3580,pressure:{kind:"standard"},humidityPct:0},uB=10,mB={id:"nurburg-sprint",name:"Sprintstrecke, N\xFCrburg",address:"1875636cdbb615aa2756",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[Co,hC]}};function To(e,t){let{id:r,name:n,address:o,provenance:a,standingStart:s}=t,i={kind:"catalogue",id:r,address:o},c=oc(zg({name:n,source:i}).model,structuredClone(a));return e.tracks=[{id:"tr1",name:n,source:i,provenance:c,...s?{standingStart:s}:{}}],e.activeTrackId="tr1",e.settings.standingStart=s===!0,e}function Cn(e,t,r){let n=e.vehicles[0].params,o=`m${e.motors.length+1}`;e.motors=[...e.motors,{id:o,color:Mn[e.motors.length%Mn.length],model:t}];let a=Vk({},{...n,motorModel:t});n.motorModelId=o,n.motorCount=1,a&&(n.driveline=a),n.gear_ratio&&(n.gear_ratio={...n.gear_ratio,value:r})}var pB=3.8,Gp={hubPlanetary:14.5,inboardChain:4,engineChain:3.4},dB="Hub motor, 35 kW (example)";function _y(e,t,r,n,o,a){let s=e.vehicles[0].params;s.motorModelId=t,s.motorCount=r,s.motorPlacement=n,a&&(s.motorMount=a),s.driven_wheels={...s.driven_wheels,value:n==="awd"?4:2},s.gear_ratio={...s.gear_ratio,value:o}}function gC(e){let t=e.motors.find(r=>r.id==="m1");return t.model={...t.model,name:dB},t.id}function Kp(e,t,r){let n=ts(es(wn(e,r)));return n.vehicles[0].params.name=t,n}function fB(){let e=Kp("Formula Student combustion car","Formula Student combustion","fs-cv");Cn(e,Bg(),Gp.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 hB(){let e=Kp("Formula Student AWD car","Formula Student AWD","fs-ev");return _y(e,gC(e),4,"awd",Gp.hubPlanetary,"hub"),e}function bB(){let e=Kp("Formula Student RWD hub-motor car","Formula Student RWD hub motors","fs-ev");return _y(e,gC(e),2,"rear",Gp.hubPlanetary,"hub"),e}function gB(){let e=Kp("Formula Student one-motor car","Formula Student RWD one motor","fs-ev"),t=`m${e.motors.length+1}`;return e.motors=[...e.motors,{id:t,color:Mn[e.motors.length%Mn.length],model:Vg()}],_y(e,t,1,"rear",Gp.inboardChain),e.vehicles[0].params.driveline={rear:structuredClone(xt.clutch)},e}function yB(){let e=ts(es(wn("Formula Student endurance energy","fs-ev"))),t=e.vehicles[0],r=structuredClone(t);if(r.id="v2",r.color=cc[1],r.params.name=`${t.params.name} flat out`,!r.params.endurance_reserve)throw new Error("the Formula Student preset states no energy reserve");return r.params.endurance_reserve={...r.params.endurance_reserve,value:0},e.vehicles.push(r),e}function xB(){let e=Op(),t=wo("Formula 1 car","trackday",U3,()=>e.vehicle);return Ey(t.vehicles[0].params,Vc(e.components,Bp)),xr(t,Bp),Cn(t,$g(),pB),To(t,nB)}function yC(e="GT car",t=rc){let r=wo(e,"trackday",X3,t);return xr(r,cC),Cn(r,pA(),r.vehicles[0].params.gear_ratio.value),To(r,oB)}function xC(e="Sports car",t=nc,r=Dy){let n=wo(e,"trackday",Q3,t);return xr(n,r),Cn(n,dA(),n.vehicles[0].params.gear_ratio.value),To(n,aB)}function RB(){let e=wo("Cup car","trackday",q3,eA);return xr(e,uC),Cn(e,fA(),e.vehicles[0].params.gear_ratio.value),To(e,sB)}function vB(){let e=wo("Stock car","trackday",Z3,tA);return xr(e,mC),Cn(e,hA(),e.vehicles[0].params.gear_ratio.value),To(e,iB)}function kB(){let e=wo("Hill-climb prototype","trackday",J3,rA);return xr(e,pC),Cn(e,bA(),e.vehicles[0].params.gear_ratio.value),e.settings.air=structuredClone(lB),e.settings.airTempC=uB,To(e,cB)}function MB(){let e=wo("Race truck","trackday",eB,nA);return xr(e,dC),Cn(e,gA(),e.vehicles[0].params.gear_ratio.value),To(e,mB)}function SB(e){let t=_p.find(o=>o.id===e);if(e==="direct")return yC(t.name,()=>Ja(e));if(e==="mcpherson")return xC(t.name,()=>Ja(e),lC);let r=ts(wn(t.name,"trackday")),n=Np(e,r.vehicles[0].params);return r.suspensions=[{...r.suspensions[0],model:n.vehicle}],Ey(r.vehicles[0].params,n.components),xr(r,Ly),r}function Bc(e,t,r){let n=Iy[e],o=_p.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:()=>SB(n)}}var AB=[{id:"fs-ev-comparison",domain:"racecar",kind:"study",summary:"Four Formula Student cars scored on all five events: what mass, power and downforce buy.",title:"Formula Student \u2014 car comparison",blurb:"A generic Formula Student electric car and three what-ifs \u2014 15 % more downforce, 15 kg lighter, 15 % more power \u2014 scored side by side on the Formula Student electric events. All four run decoupled heave and roll suspension. A good first look at what each change buys.",tags:["formula student","comparison","lap sim"],openTool:"laptime",load:()=>es(wn("Formula Student comparison","fs-ev"))},{id:"fs-endurance-energy",domain:"racecar",kind:"study",summary:"The FS car flat out against its energy target: which finishes endurance, and the points.",title:"Formula Student \u2014 endurance energy",blurb:"The generic Formula Student electric car twice, scored together on the Formula Student electric events: once driven to its energy target, once flat out. The two differ in the endurance reserve and nothing else. Flat out the car laps faster and its pack runs out before the flag; on the target its speed is capped so the pack finishes with 5 % left. The endurance event shows the charge lap by lap, and the points what running dry costs.",tags:["formula student","endurance","energy","battery"],openTool:"laptime",load:yB},{id:"fs-ev-single",domain:"racecar",kind:"start",summary:"A generic Formula Student electric car on the five events, to set up as your own.",title:"Formula Student \u2014 single car",blurb:"One generic Formula Student electric car on the Formula Student electric events: 300 kg with driver, two motors, 80 kW, 10-inch tyres, decoupled heave and roll suspension. The uncluttered starting point for setting up your own car.",tags:["formula student","lap sim"],openTool:"laptime",load:()=>ts(es(wn("Formula Student car","fs-ev")))},{id:"fs-combustion",domain:"racecar",kind:"start",summary:"A restricted 600 cc four through six gears and a clutch-pack diff, on the CV events.",title:"Formula Student \u2014 combustion, LSD",blurb:"The generic Formula Student car with an engine: a restricted 600 cc four of about 64 kW through a six-speed box and a chain to a clutch-pack limited-slip diff, on the Formula Student combustion events. The same 300 kg chassis, tyres and decoupled suspension as the electric layouts, so the drive is the difference. Efficiency is scored on the work at the crankshaft until fuel is modelled. Representative of the class, not a measurement of any car.",tags:["formula student","combustion","engine","limited-slip diff","lsd","lap sim"],openTool:"laptime",load:fB},{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:hB},{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:bB},{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:gB},{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:xB},{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:yC},{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:xC},{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:RB},{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:vB},{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:kB},{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:MB},{id:"suspension",domain:"racecar",kind:"study",summary:"The FS car\u2019s decoupled wishbones: move a hardpoint and watch the roll centre follow.",title:"Suspension kinematics study",blurb:"Opens on the double-wishbone editor with one Formula Student car. Move a hardpoint and watch camber, bump steer, motion ratio and roll-centre migration follow \u2014 then see what it costs on track.",tags:["kinematics","geometry"],openTool:"kinematics",load:()=>ts(es(wn("Suspension study","trackday")))},Bc("direct-coilover","The GT car\u2019s wishbones driving coilovers straight into the towers, at Laguna Seca.","On the GT car, at Laguna Seca."),Bc("pushrod","The FS car on pushrods: a rod from each lower wishbone works a rocker.","On the Formula Student car, at FSG."),Bc("pullrod","The FS car on pullrods: a rod from each upper wishbone pulls a low rocker.","On the Formula Student car, at FSG."),Bc("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."),Bc("mcpherson-strut","The sports car on McPherson struts at the front and double wishbones at the rear.","On the sports car, at the Nordschleife."),{id:"tyre-study",domain:"racecar",kind:"study",summary:"The FS tyre\u2019s grip curves at three loads, beside the other classes\u2019 tyres.",title:"Tyre model study",blurb:"One Formula Student car on its Magic Formula tyre, opened on the tyre analysis, where the grip curves that drive the whole lap come from. The library beside it holds the other seven classes' tyres and the illustrative MF6.2 example to compare against.",tags:["tyres","magic formula"],openTool:"tires",load:()=>ts(es(wn("Tyre study","fs-ev")))}],RC=AB.map(e=>({...e,load:()=>Jg(e.load())}));var vC={width:320,height:200},Sxe=[.6*vC.width-9,.6*vC.height-9];var kC=new WeakMap,MC=new WeakMap,Ny=e=>JSON.stringify(e,(t,r)=>r===1/0?"Infinity":r);function SC(e,t){if(!t){let a=kC.get(e);return a||(a=Tt(e),kC.set(e,a)),a}let r=MC.get(e);r||(r=new Map,MC.set(e,r));let n=Ny(t),o=r.get(n);return o||(r.size>=4&&r.clear(),o=Tt(e,t),r.set(n,o)),o}var CB=Math.PI/180,TB=e=>e>1?e/100:e;function $c(e){let t=null;return()=>(t??={v:e()}).v}function AC(e){let t=Ke(e,{travelMin:-1,travelMax:1,steps:3}).samples[1],r=t.metrics.motionRatio??1;return{motionRatio:r,wheelRate:t.metrics.wheelRate??e.config.springRate*r*r}}var FC=new WeakMap,Oy={heave:0,pitch:0,roll:0,steer:0},wC=[0,1,2,3,4],CC=[-20,-10,0,10,20];function PC(e,t){let r=$r(e,Oy),n=["front","rear"],o=c=>{let l=Ri(c);return l?(l.left+l.right)/2:Number.NaN},a=n.map(c=>o(r[c])),s=n.map(()=>({rc:[],split:[]}));for(let c of wC){let l=c===0?null:$r(e,{...Oy,roll:c*CB});n.forEach((u,m)=>{let f=l?Ri(l[u]):null,p=f&&Number.isFinite(a[m]);s[m].rc.push(p?t[m]+(f.left+f.right)/2-a[m]:t[m]),s[m].split.push(p?(f.left-f.right)/2:0)})}let i=n.map(()=>[]);for(let c of CC){let l=c===0?null:$r(e,{...Oy,heave:-c});n.forEach((u,m)=>{let f=l&&l[u].valid&&r[u].valid;i[m].push(f?t[m]+l[u].height-r[u].height:t[m])})}return{roll:{rollDeg:wC,rcFront:s[0].rc,rcRear:s[1].rc,rcSplitFront:s[0].split,rcSplitRear:s[1].split},heave:{drop:CC,rcFront:i[0],rcRear:i[1]}}}var TC=new WeakMap;function PB(e,t,r,n){let o=TC.get(e);o||(o=new Map,TC.set(e,o));let a=`${Ny(r)}|${n[0]}|${n[1]}`,s=o.get(a);if(!s){o.size>=4&&o.clear();try{s=PC(SC(e,r),n)}catch{s=t.rigidMigration(n)}o.set(a,s)}return s}function LB(e){let t=FC.get(e);if(t)return t;let r=Tt(e),n=$r(r,{heave:0,pitch:0,roll:0,steer:0}),o=AC(e.front),a=AC(e.rear),s={wheelbase:e.config.wheelbase,trackFront:bt(e.front),trackRear:bt(e.rear),mrFront:o.motionRatio,mrRear:a.motionRatio,wheelRateFront:o.wheelRate,wheelRateRear:a.wheelRate,unsprungCgHeight:e.front.config.loadedRadius,rcHeightFront:n.front.valid?n.front.heightAboveGround:0,rcHeightRear:n.rear.valid?n.rear.heightAboveGround:0,rcGainFront:Ra(n.front),rcGainRear:Ra(n.rear),rigidMigration:i=>PC(r,i),kinFront:$c(()=>oa(e.front)),kinRear:$c(()=>oa(e.rear))};return FC.set(e,s),s}function LC(e,t,r,n){let o=LB(e),a=Zn(e,t),s=va(e,t),i=Lk(e,t),c=Lu(e,t),l=Dk(e,t),u=Ek(t),m=Du(e,t),f=qn(e.front),p=qn(e.rear),d=Qn(t.damperModel,t.damperSetup,o.mrFront,o.mrRear,t.damperModelRear??t.damperModel),h={rho:t.rho.value,area:t.A.value,cl:t.c_l.value,cw:t.c_w.value,copLongFront:1-Math.max(0,Math.min(1,q(t,"cop_long"))),copHeight:q(t,"cop_height"),...t.aeroModel?{model:t.aeroModel}:{},rideHeightFront:q(t,"ride_height_front"),rideHeightRear:q(t,"ride_height_rear")},b=9.81,g=TB(t.front_mass_diss.value),y=Ma(t,r,n),R=Pe(y.front),k=y.rear===y.front?R:Pe(y.rear),v=n??t.tireModelRear??r,x=t.m.value*b*g/2,M=t.m.value*b*(1-g)/2,F=R.corneringStiffness(x),w=k.corneringStiffness(M),C=(r?R.verticalStiffness():0)||q(t,"tire_vertical_rate"),T=(v?k.verticalStiffness():0)||q(t,"tire_vertical_rate"),S=ar(r)??0,A=ar(v)??0,P=Ou({freeRadius:S,staticLoad:x,tyreRate:C,surveyed:e.front.config.loadedRadius},{freeRadius:A,staticLoad:M,tyreRate:T,surveyed:e.rear.config.loadedRadius},g),L=Gt(S,x,C,e.front.config.loadedRadius),D=Gt(A,M,T,e.rear.config.loadedRadius),E=[Gr(o.rcHeightFront,o.rcGainFront,e.front.config.loadedRadius,L),Gr(o.rcHeightRear,o.rcGainRear,e.rear.config.loadedRadius,D)],V=$c(()=>Ai(o.kinFront(),q(t,"camber_front_deg"))),N=$c(()=>Ai(o.kinRear(),q(t,"camber_rear_deg"))),z=$c(()=>PB(e,o,Ya(B),E)),I=ei({...t,wheelbase:{...t.wheelbase,value:o.wheelbase}}),_=Si(t),B={massTotal:t.m.value,frontMassFrac:g,steeringSystem:t.steeringSystem,tv:yu(t),cgHeight:ka(q(t,"cg_height"),t.cgReference?.standingRadius,P),cgStandingRadius:P,wheelbase:o.wheelbase,trackFront:o.trackFront,trackRear:o.trackRear,wheelRateFront:f?0:o.wheelRateFront,wheelRateRear:p?0:o.wheelRateRear,decoupledFront:f,decoupledRear:p,...u.front?{elementLinkagesFront:u.front}:{},...u.rear?{elementLinkagesRear:u.rear}:{},...m.front.source==="part"?{cornerCoiloverFront:m.front.coilover}:{},...m.rear.source==="part"?{cornerCoiloverRear:m.rear.coilover}:{},...m.heaveFront.coilover?{heaveCoiloverFront:m.heaveFront.coilover}:{},...m.heaveRear.coilover?{heaveCoiloverRear:m.heaveRear.coilover}:{},...i.front&&!f?{heaveSeatFront:i.front}:{},...i.rear&&!p?{heaveSeatRear:i.rear}:{},...m.rollFront.coilover?{rollCoiloverFront:m.rollFront.coilover}:{},...m.rollRear.coilover?{rollCoiloverRear:m.rollRear.coilover}:{},tireRate:C,...T!==C?{tireRateRear:T}:{},tireDamping:q(t,"tire_vertical_damping"),arbFront:a.front??q(t,"arb_front"),arbRear:a.rear??q(t,"arb_rear"),brakeBalanceFront:I.balanceFront,brakes:I,..._?{driveline:_}:{},heaveSpringFront:s.front??q(t,"heave_spring_front"),heaveSpringRear:s.rear??q(t,"heave_spring_rear"),unsprungPerCorner:q(t,"unsprung_mass"),unsprungCgHeight:Gt(S,x,C,o.unsprungCgHeight),tyreFreeRadius:S,...A!==S?{tyreFreeRadiusRear:A}:{},rcHeightFront:E[0],rcHeightRear:E[1],corneringStiffnessFront:F,corneringStiffnessRear:w,get kinFront(){return V()},get kinRear(){return N()},damperFront:f?0:d?.front?.rate??q(t,"damper_front")*o.mrFront*o.mrFront,damperRear:p?0:d?.rear?.rate??q(t,"damper_rear")*o.mrRear*o.mrRear,...d?.front&&!f?{damperCurveFront:d.front.curve}:{},...d?.rear&&!p?{damperCurveRear:d.rear.curve}:{},heaveDamperFront:l.heaveFront?.rate??c.heaveFront,heaveDamperRear:l.heaveRear?.rate??c.heaveRear,rollDamperFront:l.rollFront?.rate??c.rollFront,rollDamperRear:l.rollRear?.rate??c.rollRear,...l.heaveFront?{heaveDamperCurveFront:l.heaveFront.curve}:{},...l.heaveRear?{heaveDamperCurveRear:l.heaveRear.curve}:{},...l.rollFront?{rollDamperCurveFront:l.rollFront.curve}:{},...l.rollRear?{rollDamperCurveRear:l.rollRear.curve}:{},unsprungCornerMass:q(t,"unsprung_mass"),get rollCentreCurve(){return z().roll},get rcHeaveCurve(){return z().heave},aero:h,yawInertia:q(t,"I_yaw"),rollInertia:q(t,"I_roll"),pitchInertia:q(t,"I_pitch"),get steerFront(){return Eu(e.front,L)},ackermannPct:q(t,"ackermann_pct"),toeFrontDeg:q(t,"toe_front_deg"),toeRearDeg:q(t,"toe_rear_deg")};return B}var EC=e=>({tire:t=>t==null?void 0:t===e.tireModelIdRear&&e.tireModelRear?e.tireModelRear:e.tireModel,motor:()=>e.motorModel,aero:()=>e.aeroModel,battery:()=>e.batteryModel,brake:()=>e.brakeModel,damper:t=>t!=null&&t===e.damperModelIdRear&&e.damperModelRear?e.damperModelRear:t!=null&&t===e.heaveDamperModelId?e.heaveDamperModel:t!=null&&t===e.rollDamperModelId?e.rollDamperModel:e.damperModel}),By={ggvMode:"twoTrack"},DC=new WeakMap;function $y(e,t=By){let r=DC.get(e.vehicle);r||DC.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={...EC(e.params),suspensionOf:()=>e.vehicle};n.set(o,a=Fo(e.params,s,t))}return a}var IC=(e=By)=>t=>$y(t,e),_C=(e=By)=>t=>LC(t.vehicle,My(t.params,EC(t.params),e),t.params.tireModel,t.params.tireModelRear);function DB(e,t){return $y(e,t.switches)}var Gy=e=>Ur(e?.rulesets);function NC(e,t,r,n,o={},a=()=>r.standingStart){let s=$y(n,r.switches),i=(l,u)=>{let m=Am(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 OC=e=>[...new Set(e.lap.courses.flatMap(t=>t.course.kind==="track"?[t.course.trackId]:[]))],VC=e=>{let t=e?.session;return t?{sessionParams:r=>DB(r,t),session:()=>t}:{}},Hp=e=>({metrics:Gy(e),assemble:_C(e?.switches),simParams:IC(e?.switches),projectTrack:()=>e?.course??null,libraryTrack:t=>e?.tracks?.[t]??null,numerics:e?.numerics,...VC(e)}),EB=(e,t)=>({density:e.density,envelope:e.envelope,states:e.states,operating:e.operating,lap:e.lap,assemble:_C(t?.switches),simParams:IC(t?.switches),projectTrack:()=>t?.course??null,libraryTrack:r=>t?.tracks?.[r]??null,numerics:t?.numerics,...VC(t)}),BC="nelder-mead",$C=600,Gc=[0,.15,.15];function GC(e,t,r,n=Gc.length){let o=zy(t);return Gc.slice(0,Math.max(1,n)).map((a,s)=>({...e,seed:s+1,startJitter:a,car:o,...r?{lap:r}:{}}))}function KC(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 HC(e,t,r,n,o=.01){let a=Gy(n).byId;return IB(e,t,r,n).filter(s=>s.excess>-o*(a[s.metricId]?.scale??1))}function IB(e,t,r,n){let o;try{o=Sn(Fp(e,t,r),EB(t,n))}catch{return[]}return _B(o,t,Gy(n))}function _B(e,t,r){let n=[];for(let o of t.constraints){let a=r.byId[o.metricId];if(!a)continue;let s=kt(e,a,o.at);if(!Number.isFinite(s))continue;let i=`${et(a)}${Ic(o.at,a)}`;n.push({key:o.key,metricId:o.metricId,label:i,unit:a.unit==="-"?"":a.unit,value:s,excess:Ec(o,s)})}return n}var NB=.05;function OB(e,t){if(t.id.startsWith("hp.")||Mp(t.id))return 1;let r=/^rocker\.(front|rear)\.(\w+)$/.exec(t.id);if(r){let a=r[1]==="front"?e.vehicle.front:e.vehicle.rear;return ey(Fn(a.hardpoints),r[2],1)}let n=/^arm\.(front|rear)\.(uca|lca)\.(\w+)$/.exec(t.id);if(!n)return null;let o=n[1]==="front"?e.vehicle.front:e.vehicle.rear;return q0(Xr(o.hardpoints,n[2]),n[3],1)}function zC(e,t,r){let n=r.filter(f=>f.score.feasible);if(n.length<2)return null;let o=t.map(f=>OB(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(NB,m),unit:a}}var VB={steeringSystem:!0,brakeSetup:!0,driveline:!0,heaveFrontDesign:!0,heaveRearDesign:!0,arbFrontDesign:!0,arbRearDesign:!0},YC=e=>Object.hasOwn(VB,e);function Vy(e){let[t,r]=e.split("."),n=r==="front"?"Front":r==="rear"?"Rear":null;return n?t==="heave"?`heave${n}Design`:t==="roll"?`arb${n}Design`:null:null}function BB(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":YC(t)||Vy(e)?"block":null}function Ky(e,t){t=Dt(e,t);let r=Ht(e);return[...t.variables,...t.followers??[]].filter(n=>r[n.id]&&!r[n.id].supersededBy&&!BB(n.id)).map(n=>ct(r[n.id]))}function WC(e,t,r){t=Dt(e,t);let n=Ht(e),o=Fp(e,t,r),a=[],s=new Set,i=new Set;for(let c of[...t.variables,...t.followers??[]]){let l=n[c.id];if(!l||l.supersededBy)continue;let u=l.read(o),[m,f,p,d]=c.id.split(".");if(m==="rocker"){let h=`${f}.rocker`;if(i.has(h))continue;i.add(h);let b=f==="front"?o.vehicle.front:o.vehicle.rear;for(let g of[ko.fore,ko.aft]){let y=b.hardpoints[g];for(let R=0;R<3;R++)a.push({kind:"hardpoint",axle:f,key:g,axis:R,value:y[R]})}}else if(m==="arm"){let h=`${f}.${p}`;if(i.has(h))continue;i.add(h);let b=f==="front"?o.vehicle.front:o.vehicle.rear,g=Xt[p];for(let y of[g.fore,g.aft]){let R=b.hardpoints[y];for(let k=0;k<3;k++)a.push({kind:"hardpoint",axle:f,key:y,axis:k,value:R[k]})}}else if(m==="hp"&&yr(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(YC(m)||Vy(c.id)){let h=Vy(c.id)??m;if(s.has(h))continue;s.add(h);let b=o.params[h];if(!b)throw new Error(`optimiser: "${c.id}" left the car with no ${h} to adopt`);a.push({kind:"block",key:h,value:b})}else throw new Error(`optimiser: Adopt has no way to write "${c.id}" back into the project`)}return a}function Hy(e){let t=performance.now(),r=Hp(e.lap),n=e.follow?my(e.car,e.spec,r):e.spec,{dead:o,unprobed:a,...s}=hy(e.car,n,r);return{...s,deadIds:o.map(i=>i.id),unprobedIds:a.map(i=>i.id),elapsedMs:performance.now()-t,...e.follow?{followed:!0,fromCar:n===e.spec?null:{states:n.states,envelope:n.envelope}}:{}}}var zy=e=>e.vehicle.chassis?{...e,vehicle:Ay(e.vehicle)}:e;function jC(e,t){try{let r=Yy(e.car,e.spec,e.lap),n=ia.find(u=>u.name===e.method);if(!n)throw new Error(`unknown method "${e.method}"`);t({kind:"progress",seed:e.seed,progress:{evaluations:0,budget:e.budget,x:Cr(r.variables),score:wr(r,Cr(r.variables)),infeasible:0}});let o=e.from,a=o?{...r,variables:r.variables.map((u,m)=>({...u,start:Number.isFinite(o[m])?o[m]:u.start}))}:r,s=performance.now(),i=n.run(a,{budget:e.budget,seed:e.seed,startJitter:e.startJitter,progressEvery:20,onProgress:u=>t({kind:"progress",seed:e.seed,progress:u})}),c=performance.now()-s,l=i.score.feasible&&oy(r.variables)?sy(r,i.x,i.score):void 0;t({kind:"done",seed:e.seed,result:l?{...i,snapped:l}:i,elapsedMs:c})}catch(r){t({kind:"error",seed:e.seed,message:r instanceof Error?r.message:String(r)})}}var Yy=(e,t,r)=>wp(e,t,Hp(r));function UC(e,t){let r=e.tireModelIdRear?t.tire(e.tireModelIdRear):void 0;return{tireModel:t.tire(e.tireModelId),...r?{tireModelRear:r}:{},motorModel:t.motor(e.motorModelId),aeroModel:t.aero(e.aeroModelId),batteryModel:t.battery(e.batteryModelId),brakeModel:t.brake(e.brakeModelId),damperModel:t.damper(e.damperModelId),...fi(e,t.damper)}}function XC(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 QC=e=>({ggvMode:e.ggvMode,quasiTransient:e.quasiTransient===!0&&e.ggvMode!=="fast",motorThermal:e.motorThermal===!0,...Mw({brakeFade:e.brakeFade===!0,airTempC:e.airTempC,diffYaw:e.diffYaw===!0,...e.air?{air:e.air}:{}})});function $B(e){if(!(e.plannedPath!==void 0||!e.track))return{track:e.track,numerics:e.numerics,settings:{racingLine:e.racingLine,standingStart:e.standingStart,...Object.keys(e.lapCounts).length?{lapCounts:e.lapCounts}:{}},switches:e.switches,rulesets:e.rulesets}}function qC(e,t){let r=t.plannedPath!==void 0,n=$B(t);return{...NC(r?t.plannedPath:t.track,t.numerics,{racingLine:r?!1:t.racingLine,standingStart:t.standingStart,switches:t.switches},e,t.library,t.standingOf),...n?{session:n}:{},rulesets:t.rulesets}}function Wy(e,t){let r=e.vehicles.find(o=>o.id===t);if(!r)throw new Error(`this project holds no vehicle "${t}"`);let n=Ao(e);return XC(structuredClone(ky(e,r.params)),structuredClone(r.params),UC(r.params,n))}var GB="this project's laps follow a fixed trajectory from the planner, which the server cannot read \u2014 set Laptime back to the track to run this study here, or run it in the Studies tool";async function jy(e,t,r,n){if(e.settings.pathPlanId)throw new Error(GB);let o=Za(e),a=e.tracks.length?(await Pp(e,t)).asset:null,s={};for(let i of n?OC(n):[]){let c=e.tracks.find(l=>l.id===i);c&&(s[i]=await Nc(c,t))}return qC(r,{track:a,numerics:o.numerics,racingLine:o.racingLine,standingStart:o.standingStart,lapCounts:o.lapCounts??{},switches:QC(o),rulesets:e.rulesets??[],library:s,standingOf:i=>e.tracks.find(c=>c.id===i)?.standingStart===!0})}async function ZC(e,t,r,n){let o=Wy(e,r),a=Dt(o,n),s=await jy(e,t,o,a);return Hy({id:0,car:o,spec:a,lap:s})}async function JC(e,t,r,n){let o=Wy(e,r),a=Dt(o,n),s=Ky(o,a);if(s.length)return{problems:[`Adopt has no way to write ${s.join(", ")} back into the project. Take them out of the study.`]};let i;try{i=await jy(e,t,o,a)}catch(l){return{problems:[l instanceof Error?l.message:String(l)]}}let c=fy(o,a,{...Hp(i),metrics:Ur(e.rulesets)});return c.length?{problems:c}:{problems:[],msPerEval:Hy({id:0,car:o,spec:a,lap:i}).msPerEval,carFingerprint:co(zy(o))}}async function KB(e,t,r,n,o,a=[]){let s=GC(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(jC(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 eT(e,t,r,n){let o=Wy(e,r.vehicleId),a=Dt(o,r.spec),s=Ky(o,a);if(s.length)throw new Error(`study_adopt has no way to write ${s.join(", ")} back into the project \u2014 take them out of the study`);let i=await jy(e,t,o,a),c=r.method??BC;if(!ia.some(b=>b.name===c))throw new Error(`unknown method "${c}" \u2014 it is one of ${ia.map(b=>b.name).join(", ")}`);let l=r.budget??$C,u=Math.max(1,Math.min(r.seeds??Gc.length,Gc.length)),m=await KB(o,{spec:a,method:c,budget:l},i,u,n),f=Yy(o,a,i),p=m.runs.map(b=>({seed:b.seed,startScore:m.designScore.total,score:b.score.total,feasible:b.score.feasible,...b.score.reason?{reason:b.score.reason}:{},terms:b.score.terms,x:b.x,evaluations:b.evaluations,infeasible:b.infeasible,bounds:KC(f.variables,b.x),constraints:HC(o,a,b.x,i),...b.snapped?{onSteps:{x:b.snapped.x,score:b.snapped.score.total,feasible:b.snapped.score.feasible,...b.snapped.score.reason?{reason:b.snapped.score.reason}:{},terms:b.snapped.score.terms}}:{}})),d=m.runs.reduce((b,g)=>Hs(g.score,b.score)?g:b),h=d.snapped?.score.feasible?d.snapped:null;return{method:c,budget:l,seeds:p,spread:m.runs.length>1?zC(o,f.variables,m.runs.map(b=>({x:b.x,score:b.score}))):null,writes:WC(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 rT(){if(typeof process.threadCpuUsage!="function")return performance.now();let e=process.threadCpuUsage();return(e.user+e.system)/1e3}async function zB(e,t){let r=xw(e.root);switch(e.kind){case"sweep":return Dw(e.doc,r,e.req,t);case"convergence":return Pw(e.doc,r,{vehicleId:e.vehicleId,...e.steps?{steps:e.steps}:{},...e.tolPct!==void 0?{tolPct:e.tolPct}:{},onStep:t});case"study":return eT(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 Lp(e.doc,r,{...e.vehicleIds?{vehicleIds:e.vehicleIds}:{},...e.settings?{settings:e.settings}:{},...e.overrides?{overrides:e.overrides}:{}});case"probe":return ZC(e.doc,r,e.vehicleId,e.spec);case"quote":return JC(e.doc,r,e.vehicleId,e.spec)}}if(tT){let e=tT,t=r=>e.postMessage(r);(async()=>{try{let r=await zB(HB,(n,o)=>t({type:"progress",done:n,total:o}));t({type:"done",result:r,cpuMs:rT()})}catch(r){t({type:"failed",message:r instanceof Error?r.message:String(r),cpuMs:rT()})}})()}export{zB as runJob,rT as threadCpuMs};