@pacedyn/mcp 0.386.0 → 0.388.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +38 -38
- package/dist/worker.js +3 -3
- package/package.json +1 -1
package/dist/worker.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{parentPort as Cw,workerData as I5}from"node:worker_threads";import{readFileSync as x0}from"node:fs";import{join as R0}from"node:path";var yc=e=>e.format!=="points"&&!e.field;var mt=e=>e?.kind==="ice";var X0={packVoltageMax:600,segmentVoltageMax:120,powerLimitKw:80};var De=e=>typeof e=="number"&&Number.isFinite(e);function Pw(e){let{soc:t,ocv:r,r0:n}=e;if(!Array.isArray(t)||t.length<2)return"The curve needs at least two state-of-charge points.";if(!t.every(De))return"The state-of-charge axis contains a value that is not a number.";if(t[0]<0||t[t.length-1]>1)return`The state-of-charge axis must lie within 0 to 1 (it runs ${t[0]} to ${t[t.length-1]}).`;for(let o=1;o<t.length;o++)if(!(t[o]>t[o-1]))return`The state-of-charge axis must increase (${t[o-1]} then ${t[o]}).`;if(!Array.isArray(r)||r.length!==t.length)return`The curve has ${Array.isArray(r)?r.length:0} voltages against ${t.length} state-of-charge points.`;if(!r.every(De))return"The open-circuit voltage contains a value that is not a number.";if(r.some(o=>o<=0))return"The open-circuit voltage must be positive everywhere.";for(let o=1;o<r.length;o++)if(r[o]<r[o-1])return`The open-circuit voltage must rise with state of charge (${r[o-1]} V at ${t[o-1]} then ${r[o]} V at ${t[o]}).`;if(!Array.isArray(n)||n.length!==t.length)return`The curve has ${Array.isArray(n)?n.length:0} resistances against ${t.length} state-of-charge points.`;if(!n.every(De))return"The resistance contains a value that is not a number.";if(n.some(o=>o<0))return"The resistance cannot be negative.";if(e.rTempC!==void 0||e.rGrid!==void 0){let o=e.rTempC,a=e.rGrid;if(!Array.isArray(o)||o.length<1)return"The resistance temperature axis needs at least one temperature.";if(!o.every(De))return"The resistance temperature axis contains a value that is not a number.";for(let s=1;s<o.length;s++)if(!(o[s]>o[s-1]))return`The temperature axis must increase (${o[s-1]} then ${o[s]} \xB0C).`;if(!Array.isArray(a)||a.length!==o.length)return`The resistance grid has ${Array.isArray(a)?a.length:0} rows against ${o.length} temperatures.`;for(let s=0;s<a.length;s++){let i=a[s];if(!Array.isArray(i)||i.length!==t.length)return`Resistance row ${s+1} has ${Array.isArray(i)?i.length:0} values against ${t.length} state-of-charge points.`;if(!i.every(De))return"The resistance grid contains a value that is not a number.";if(i.some(c=>c<0))return"The resistance grid contains a negative resistance."}}return null}function Lw(e){return!e||typeof e!="object"?"The cell has no curve.":e.kind==="table"?Pw(e):e.kind==="analytic"?!De(e.vCut)||!De(e.vNom)||!De(e.vFull)?"The cut-off, nominal and full voltages must be numbers.":e.vCut<=0?"The cut-off voltage must be positive.":e.vCut<e.vNom&&e.vNom<e.vFull?!De(e.r0)||e.r0<0?"The cell resistance must be a number and cannot be negative.":e.socAtNom!==void 0&&(!De(e.socAtNom)||e.socAtNom<=0||e.socAtNom>=1)?"The state of charge the nominal voltage is met at must lie strictly between 0 and 1.":null:`The voltages must order cut-off < nominal < full (given ${e.vCut}, ${e.vNom}, ${e.vFull} V).`:`Unknown cell curve kind "${e.kind}".`}function xc(e){if(!e||typeof e!="object")return"Not a battery model.";let t=e.cell;if(!t||typeof t!="object")return"The model has no cell.";if(!De(t.capacityAh)||t.capacityAh<=0)return"The cell capacity must be a positive number of amp-hours.";if(!De(t.vMin)||t.vMin<0)return"The cut-off voltage must be a number and cannot be negative.";if(!De(t.vMax)||t.vMax<=0)return"The maximum cell voltage must be a positive number.";if(!(t.vMin<t.vMax))return`The cut-off voltage (${t.vMin} V) must be below the maximum (${t.vMax} V).`;if(!De(t.iMaxA)||t.iMaxA<0)return"The discharge current limit must be a number of amps, 0 for no limit.";if(t.iMaxChargeA!==void 0&&(!De(t.iMaxChargeA)||t.iMaxChargeA<0))return"The charge current limit must be a number of amps, 0 for no limit.";if(t.massKg!==void 0&&(!De(t.massKg)||t.massKg<0))return"The cell mass must be a number and cannot be negative.";let r=Lw(t.curve);if(r)return r;let n=t.curve.kind==="table"?t.curve.ocv[t.curve.ocv.length-1]:t.curve.vFull;if(t.vMin>=n)return`The cut-off voltage (${t.vMin} V) is at or above the cell's voltage at full charge (${n} V), so no power could ever be drawn.`;let o=e.thermal;if(o!==void 0){if(!o||typeof o!="object")return"The thermal model must be an object, or absent.";if(!De(o.heatCapacityJPerK)||o.heatCapacityJPerK<=0)return"The cell heat capacity must be a positive number of joules per kelvin.";if(!De(o.coolingWPerK)||o.coolingWPerK<0)return"The cooling must be a number of watts per kelvin and cannot be negative.";if(o.startC!==void 0&&!De(o.startC))return"The starting temperature must be a number.";if(o.entropicVPerK!==void 0&&!De(o.entropicVPerK))return"The entropic coefficient must be a number.";if(o.derateFromC!==void 0){if(!De(o.derateFromC))return"The temperature the derate starts at must be a number.";if(o.derateToC!==void 0){if(!De(o.derateToC))return"The temperature the derate ends at must be a number.";if(!(o.derateToC>o.derateFromC))return`The derate must end above where it starts (given ${o.derateFromC} then ${o.derateToC} \xB0C).`}}else if(o.derateToC!==void 0)return"The derate has an end temperature but no start; give both or neither."}let a=e.pack;if(!a||typeof a!="object")return"The model has no pack.";if(!Number.isInteger(a.series)||a.series<1)return"The pack needs a whole number of cells in series, at least one.";if(!Number.isInteger(a.parallel)||a.parallel<1)return"The pack needs a whole number of strings in parallel, at least one.";if(!De(a.busResistance)||a.busResistance<0)return"The busbar resistance must be a number and cannot be negative.";if(a.seriesPerSegment!==void 0&&a.seriesPerSegment!==0){if(!Number.isInteger(a.seriesPerSegment)||a.seriesPerSegment<1)return"The cells per segment must be a whole number, at least one.";if(a.seriesPerSegment>a.series)return`A segment cannot hold more cells (${a.seriesPerSegment}) than the pack has in series (${a.series}).`}return null}function vn(e,t){let r=e.length;if(r<=1)return{i:0,t:0,clamped:!1};if(t<=e[0])return{i:0,t:0,clamped:t<e[0]};if(t>=e[r-1])return{i:r-2,t:1,clamped:t>e[r-1]};let n=0,o=r-1;for(;o-n>1;){let a=n+o>>1;e[a]<=t?n=a:o=a}return{i:n,t:(t-e[n])/(e[o]-e[n]),clamped:!1}}function Be(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function Rc(e,t,r,n,o){let a=e.length,s=t.length;if(a===0||s===0)return 0;let i=vn(e,n),c=vn(t,o),l=Math.min(i.i+1,a-1),u=Math.min(c.i+1,s-1),m=r[c.i][i.i],f=r[c.i][l],p=r[u][i.i],d=r[u][l],h=m+i.t*(f-m),b=p+i.t*(d-p);return h+c.t*(b-h)}var ko=[0,.05,.1,.2,.3,.4,.5,.6,.7,.8,.9,1],hp={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]},q0=[0,.05,.1,.2,.5,.8,1],Q0=[2.2,1.55,1.3,1.12,1,.97,.98];function Z0(e){return Be(q0,Q0,e)}var J0=[-20,-10,0,10,25,40,60],ey=[4,2.8,2,1.4,1,.82,.75];function bp(e){return Be(J0,ey,e)}var ty=.5;function gp(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=hp[t]??hp.other,l=e.socAtNom??ty,u=ko.includes(l)?[...ko]:[...ko,l].sort((h,b)=>h-b),m=Be(ko,c,l),f=m>0&&m<1?Math.log(i)/Math.log(m):1,p=[],d=[];for(let h of u){let b=Be(ko,c,h);p.push(o+s*Math.pow(b,f)),d.push(e.constantResistance?a:a*Z0(h))}return{kind:"table",soc:u,ocv:p,r0:d}}function yp(e){let t=e.soc,r=e.ocv,n=[0,...t.filter(a=>a>0&&a<1),1],o=0;for(let a=1;a<n.length;a++){let s=n[a-1],i=n[a];o+=(Be(t,r,s)+Be(t,r,i))/2*(i-s)}return o}var Mo=25,ry=new WeakMap;function fr(e){let t=ry.get(e);if(t)return t;let r=xc(e);if(r)throw new Error(r);let{cell:n,pack:o}=e,a=n.curve.kind==="table"?n.curve:gp(n.curve,n.chemistry),s=o.series,i=o.parallel,c=s/i,l=a.rTempC,u=a.rGrid,m=i*n.capacityAh,f=s*n.vMin,p=n.iMaxA>0?i*n.iMaxA:1/0,d=n.iMaxChargeA!==void 0&&n.iMaxChargeA>0?n.iMaxChargeA:n.iMaxA/4,h=d>0?i*d:1/0,b=F=>s*Be(a.soc,a.ocv,F),g=(F,w=Mo)=>{let C=l&&u?Rc(a.soc,l,u,F,w):Be(a.soc,a.r0,F)*bp(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))},M=(F,w,C)=>{if(!(F>0))return 0;let T=b(w),S=g(w,C);return S>0?2*F/(T+Math.sqrt(T*T+4*S*F)):F/T},v=F=>{let w=e.thermal;if(!w||w.derateFromC===void 0)return 1;let C=w.derateToC??w.derateFromC;return F<=w.derateFromC?1:!(C>w.derateFromC)||F>=C?0:1-(F-w.derateFromC)/(C-w.derateFromC)},x=(F,w,C=0)=>{let T=b(F),S=g(F,w),A=S>0?T/(2*S):1/0,P=$=>{if(!(S>0))return $*T;let K=Math.min($,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,I=S>0?P(L):1/0,G=Number.isFinite(p)?P(p):1/0,O=S>0?T*T/(4*S):1/0,W=[["rules",D],["voltage-floor",I],["current",G],["matched-load",O]],E=W[0][0],_=W[0][1];for(let[$,K]of W)K<_&&(_=K,E=$);let V=v(w??Mo);V<1&&(_=Number.isFinite(_)?_*V:_,E="temperature");let N=Number.isFinite(_)?R(_,F,w):1/0;return{watts:_,binding:E,rules:D,voltageFloor:I,current:G,matchedLoad:O,derate:V,amps:N,volts:Number.isFinite(N)?T-N*S:T}},k={model:e,table:a,capacityAh:m,chargeC:m*3600,energyKwh:m*(s*yp(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:M,maxPower:x};return ry.set(e,k),k}function xp(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 ny={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},oy={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},ay={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 Rp(){return{name:"Formula Student accumulator",cell:xp(ny),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 vp(){return{name:"LFP pack",cell:xp(oy),pack:{series:160,parallel:1,busResistance:.02,seriesPerSegment:32},provenance:{source:"assumed",note:"Assumed LFP prismatic pack; the flat plateau is the chemistry, the numbers are class-level guesses."}}}function kp(){return{name:"Road car pack",cell:xp(ay),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 Mp(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 vc(e){if(e.kind==="ice"){let n=e.gearbox.efficiency;return{model:e,maxTorque:o=>o>e.limitRpm?0:Be(e.rpm,e.torque,o),efficiency:()=>n}}let t=n=>Be(e.rpm,e.torque,n),r=e.kind==="simple"?()=>e.efficiency:(n,o)=>Rc(e.effRpm,e.effTorque,e.effGrid,n,o);return{model:e,maxTorque:t,efficiency:r}}function Sp(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 M=0;M<g;M++)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 Ue(e,t){return t==="rear"&&e.tireRateRear!==void 0?e.tireRateRear:e.tireRate}function Ap(e,t){let r=e.tyreFreeRadiusRear;return(t==="rear"&&r!==void 0?r:e.tyreFreeRadius)??0}var kc=9.81,sy=(e,t)=>e*(t*t)/2*(Math.PI/180)/1e3,Ka=(e,t)=>e+t>0?e*t/(e+t):0,iy=.5;function Mc(e,t,r){if(!(r>0))return 1;let n=e*kc*t*(Math.PI/180)/r;return 1/(1-Math.min(iy,n))}function Fp(e,t,r){return r>0?e*kc*t/(r*r):0}function cy(e,t,r,n,o){if(!(n>0)||!(o>0))return 1;let a=Fp(e,t,r)*(1/n+1/o);return 1/(1-Math.min(iy,a))}function Ce(e){let t=4*e.unsprungPerCorner,r=Math.max(0,e.massTotal-t),n=r*e.frontMassFrac,o=r*(1-e.frontMassFrac),a=Ue(e,"front"),s=Ue(e,"rear"),i=e.wheelRateFront+(e.heaveSpringFront??0),c=e.wheelRateRear+(e.heaveSpringRear??0),l=Ka(i,a),u=Ka(c,s),m=(G,O)=>{let W=O/2;return W>0?1/(2*Math.PI)*Math.sqrt(G*1e3/W):0},f=m(l,n),p=m(u,o),d=Ka(e.wheelRateFront+e.arbFront,a),h=Ka(e.wheelRateRear+e.arbRear,s),b=sy(d,e.trackFront),g=sy(h,e.trackRear),y=b+g,R=y>0?b/y:.5,M=e.rcHeightFront+(e.rcHeightRear-e.rcHeightFront)*(1-e.frontMassFrac),v=(e.cgHeight-M)/1e3,x=r*kc*v,k=Mc(r,v,y),F=y>0?x/y*k:0,w=e.massTotal*kc*e.cgHeight/e.wheelbase,C=2*l,T=2*u,S=cy(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*Ka(C,T)*(Math.PI/180)/1e3,D=e.damperFront??2.5,I=e.damperRear??2.5;return{sprungMass:r,sprungFront:n,sprungRear:o,rideRateFront:l,rideRateRear:u,rideFreqFront:f,rideFreqRear:p,rollRateFront:b,rollRateRear:g,rollRateTotal:y,rollWheelRateFront:d,rollWheelRateRear:h,frontRollStiffFrac:R,rollGradient:F,pitchGradient:P,pitchRate:L,cgRollGain:k,cgPitchGain:S,rideDampingFront:D+(e.heaveDamperFront??0),rideDampingRear:I+(e.heaveDamperRear??0),rollDampingFront:D+(e.rollDamperFront??0),rollDampingRear:I+(e.rollDamperRear??0)}}var Hr=["clFront","clRear","cd"],So=e=>e.frame?.kind==="pitch";function Sc(e){return So(e)?{x:e.axes.h,y:e.axes.pitch}:{x:e.axes.hFront,y:e.axes.hRear}}var ly=e=>e.frame?.kind==="pitch";var Ac=45,Qe=e=>typeof e=="number"&&Number.isFinite(e);function Fc(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 uy(e,t){if(t===void 0)return null;for(let r of Hr){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 my(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 Ha(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=Fc("front ride-height",e.axes?.hFront);if(i)return i;let c=Fc("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=Fc("ride-height",e.axes?.h);if(i)return i;let c=Fc("pitch",e.axes?.pitch,"\xB0","pitch");if(c)return c;let l=e.axes.pitch.find(u=>Math.abs(u)>=Ac);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 Hr){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 uy("yaw",e.attitude?.yaw)??uy("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 Hr){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])>=Ac||Math.abs(i[1])>=Ac))return`A pitch range reaching ${Math.abs(i[0])>=Ac?i[0]:i[1]}\xB0 is not a car's attitude. Pitch is in degrees.`}return my("yaw",e.attitude?.yaw)??my("roll",e.attitude?.roll)}return`Unknown aero model kind "${e.kind}".`}var py=180/Math.PI;function wc(e,t,r,n){let o=(n-r)/t;return{h:r+e.refX*o,pitch:Math.atan(o)*py}}function Ao(e,t,r,n){let o=Math.tan(n/py);return{hFront:r-e.refX*o,hRear:r+(t-e.refX)*o}}var R3=180/Math.PI,Dw=["hFront","hRear"],Ew=["h","pitch"],Tp=e=>e?.kind==="pitch"?Ew:Dw,kt=(e,t)=>e[t],Cc=(e,t)=>e[t],wp=(e,t)=>({[e[0]]:t(e[0]),[e[1]]:t(e[1])});function Iw(e){if(!(!e.yaw&&!e.roll))return{...e.yaw?{yaw:{...e.yaw}}:{},...e.roll?{roll:{...e.roll}}:{}}}function Pp(e){let t=Tp(e.frame),r=e.balanceFront,n=e.cl*r,o=e.cl*(1-r),a=wp(t,c=>kt(e.dCl,c)*r+e.cl*kt(e.dBalance,c)),s=wp(t,c=>kt(e.dCl,c)*(1-r)-e.cl*kt(e.dBalance,c)),i=Iw(e);return{kind:"sensitivity",name:e.name,area:e.area,...e.frame?{frame:{...e.frame}}:{},ref:{...e.ref},at:{clFront:n,clRear:o,cd:e.cd},slope:{clFront:a,clRear:s,cd:wp(t,c=>kt(e.dCd,c))},range:{[t[0]]:[...Cc(e.range,t[0])],[t[1]]:[...Cc(e.range,t[1])]},provenance:{...e.provenance},...i?{attitude:i}:{}}}function Tc(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 Cp(e,t,r=11){let n=Array.from({length:r},(a,s)=>t.maxDeg*s/(r-1)),o=n.map(a=>Tc(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 dy(e){if(!(!e.attitude?.yaw&&!e.attitude?.roll))return{...e.attitude.yaw?{yaw:Cp(e.at,e.attitude.yaw)}:{},...e.attitude.roll?{roll:Cp(e.at,e.attitude.roll)}:{}}}function fy(e,t,r,n=0,o=0){let[a,s]=Tp(e.frame),i=t-kt(e.ref,a),c=r-kt(e.ref,s),l={clFront:e.at.clFront+kt(e.slope.clFront,a)*i+kt(e.slope.clFront,s)*c,clRear:e.at.clRear+kt(e.slope.clRear,a)*i+kt(e.slope.clRear,s)*c,cd:e.at.cd+kt(e.slope.cd,a)*i+kt(e.slope.cd,s)*c},u=e.attitude?.yaw?Tc(e.at,e.attitude.yaw,n):{clFront:1,clRear:1,cd:1},m=e.attitude?.roll?Tc(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 Lp(e){let[t,r]=Tp(e.frame),n=[...Cc(e.range,t)],o=[...Cc(e.range,r)],a=i=>o.map(c=>n.map(l=>i(fy(e,l,c)))),s=dy(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 Dp=180/Math.PI,hy=new WeakMap,by=new WeakMap,Ep=new WeakMap;function zr(e,t){let r=by.get(e);if(r)return r;let n=t?.wheelbase,o=n!==void 0?Ep.get(e)?.get(n):void 0;if(o)return o;let a=_w(e),s=a.map;if(!So(s)){let l=Nw(e,a);return by.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=Ow(e,a,s.frame,n),c=Ep.get(e);return c||(c=new Map,Ep.set(e,c)),c.set(n,i),i}function _w(e){let t=hy.get(e);if(t)return t;let r=Ha(e);if(r)throw new Error(r);let n=e.kind==="map"?e:Lp(e),{x:o,y:a}=Sc(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 M=Math.abs(R),v=y.clFront.deg[y.clFront.deg.length-1];return{clFront:Be(y.clFront.deg,y.clFront.factor,M),clRear:Be(y.clRear.deg,y.clRear.factor,M),cd:Be(y.cd.deg,y.cd.factor,M),clamped:M>v}},p=(y,R)=>{if(!u)return m;let M=c?f(c,y):m,v=l?f(l,R):m;return{clFront:M.clFront*v.clFront,clRear:M.clRear*v.clRear,cd:M.cd*v.cd,clamped:M.clamped||v.clamped}},d=(y,R,M=0,v=0)=>{let x=vn(o,y),k=vn(a,R),F=Math.min(x.i+1,s-1),w=Math.min(k.i+1,i-1),C=S=>{let A=S[k.i][x.i],P=S[k.i][F],L=S[w][x.i],D=S[w][F],I=A+x.t*(P-A),G=L+x.t*(D-L);return I+k.t*(G-I)},T=p(M,v);return{clFront:u?C(n.clFront)*T.clFront:C(n.clFront),clRear:u?C(n.clRear)*T.clRear:C(n.clRear),cd:u?C(n.cd)*T.cd:C(n.cd),clampedRide:x.clamped||k.clamped,clampedAttitude:T.clamped}},h={x:[o[0],o[s-1]],y:[a[0],a[i-1]]},b=(y,R,M=!1,v=0,x=0)=>{let k=p(v,x),F=vn(o,M?Math.min(Math.max(y,h.x[0]),h.x[1]):y),w=vn(a,M?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 Hr){let D=n[L],I=D[w.i][F.i],G=D[w.i][C],O=D[T][F.i],W=D[T][C],E=F.clamped||S===0?0:((G-I)*(1-w.t)+(W-O)*w.t)/S,_=w.clamped||A===0?0:((O-I)*(1-F.t)+(W-G)*F.t)/A;P[L]=u?{x:E*k[L],y:_*k[L]}:{x:E,y:_}}return P},g={map:n,x:h.x,y:h.y,hasAttitude:u,factors:p,at:d,slopes:b};return hy.set(e,g),g}function Nw(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 Hr)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 Ow(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)*Dp,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)*Dp,m,f,p),b=Dp/(n*(1+d*d)),g={};for(let y of Hr)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)=>Ao(r,n,l,u),fromAxles:(l,u)=>{let m=wc(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 Ip(e){let t=e.clFront+e.clRear;return{cl:t,balanceFront:t!==0?e.clFront/t:.5}}var he=(e,t)=>e*t/100,Xe=e=>e/100,gy={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:Xe(-.3),hRear:Xe(.15)},dCd:{hFront:he(1.3,-.1),hRear:he(1.3,.05)},yaw:{dCl:he(3,-1),dBalance:Xe(-.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."},yy={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:Xe(-.15),hRear:Xe(.15)},dCd:{hFront:he(.9,-.15),hRear:he(.9,-.05)},yaw:{dCl:he(3,-1.5),dBalance:Xe(.2),dCd:he(.9,.8),maxDeg:8},roll:{dCl:he(3,-1),dBalance:Xe(-.3),dCd:0,maxDeg:2},note:"Assumed class-level sensitivities for a ground-effect floor, ride height, yaw and roll; not measured."},xy={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:Xe(-.25),hRear:Xe(.15)},dCd:{hFront:he(.42,-.1),hRear:0},yaw:{dCl:he(1.4,-.8),dBalance:Xe(-.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."},Ry={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."},vy={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:Xe(-.25),hRear:Xe(.15)},dCd:{hFront:he(.4,-.1),hRear:0},yaw:{dCl:he(.45,-1.2),dBalance:Xe(-.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."},ky={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:Xe(-.25),hRear:Xe(.15)},dCd:{hFront:he(.45,-.1),hRear:0},yaw:{dCl:he(.6,-1),dBalance:Xe(-.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."},My={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:Xe(-.25),hRear:Xe(.15)},dCd:{hFront:he(.9,-.1),hRear:he(.9,.05)},yaw:{dCl:he(2.5,-1),dBalance:Xe(-.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."},Sy={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 hr(e){return Pp({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 _p=()=>hr(gy),Np=()=>hr(yy),Op=()=>hr(xy),Vp=()=>hr(Ry),Bp=()=>hr(vy),$p=()=>hr(ky),Gp=()=>hr(My),Kp=()=>hr(Sy);function Fo(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 Pc(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,Ue(e,"front")))/r,rear:(t.sprungMass*(1-n)+o*a(t.rideRateRear,Ue(e,"rear")))/r}}function Lc(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 Hp(e,t){return e.wheelbase>0?e.massTotal*t*9.81/e.wheelbase:0}function wo(e,t,r){let n=2*t.rideRateFront,o=2*t.rideRateRear;return!(n>0)||!(o>0)?0:Math.min(Fp(t.sprungMass,r,e.wheelbase),.5*n*o/(n+o))}function Dc(e,t,r,n,o){let a=e.cgHeight,s=Hp(e,r);if(n===0&&o===0&&s===0)return{height:a,forward:0,noseLoad:0,dropFront:0,dropRear:0};let i=Pc(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=wo(e,t,u);let b=n-s*u,g=o+s*u;if(p>0){let M=c*l-p*(c+l);m=(b*(l-p)-p*g)/M,f=(g*(c-p)-p*b)/M}else m=c>0?b/c:0,f=l>0?g/l:0;let y=Lc(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 zp={yawDeg:0,rollDeg:0},Ay=1e-4,Vw=40,Fy=50;function Co(e,t,r=0){let n=e.aero?.model;if(!(!n||!zr(n,e).hasAttitude))return{yawDeg:r,rollDeg:Ce(e).rollGradient*t}}function Yp(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 Ao(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=ly(r)?n(r.frame,r.ref.h,r.ref.pitch):r.ref;else if(r){let{x:a,y:s}=Sc(r),i=(a[0]+a[a.length-1])/2,c=(s[0]+s[s.length-1])/2;o=So(r)?n(r.frame,i,c):{hFront:i,hRear:c}}return{hFront:e.rideHeightFront??o.hFront,hRear:e.rideHeightRear??o.hRear}}var wy=new WeakMap;function Yr(e,t,r=0,n){let o=e.aero;if(!o?.model)return null;let a=wy.get(e);a||(a=new Map,wy.set(e,a));let s=n&&zr(o.model,e).hasAttitude?n:zp,i=s===zp?`${t}|${r}`:`${t}|${r}|${s.yawDeg.toFixed(3)}|${s.rollDeg.toFixed(3)}`,c=a.get(i);if(c)return c;let l=Bw(e,o,t,r,s);return a.size>4096&&a.clear(),a.set(i,l),l}function Bw(e,t,r,n,o){let a=zr(t.model,e),s=Ce(e),i=2*s.rideRateFront,c=2*s.rideRateRear,l=Yp(t,e.wheelbase),u=.5*t.rho*r*r,m=a.area,f=e.wheelbase>0?t.copHeight/e.wheelbase:0,p=Pc(e,s),d=Hp(e,n),h=(C,T)=>Lc(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,I=h(C,T),G=d*I,O=wo(e,s,I)*b(C,T),W=A-G-D+O,E=P+G+D-O,_=C-l.hFront+(i>0?W/i:0),V=T-l.hRear+(c>0?E/c:0);return{c:S,downFront:A,downRear:P,drag:L,rF:_,rR:V,norm:Math.hypot(_,V)}},y=(C,T,S=!1)=>{let A=a.slopes(C,T,S,o.yawDeg,o.rollDeg),P=i>0?u*m/i:0,L=c>0?u*m/c:0;return[[P*(A.clFront.hFront-f*A.cd.hFront),P*(A.clFront.hRear-f*A.cd.hRear)],[L*(A.clRear.hFront+f*A.cd.hFront),L*(A.clRear.hRear+f*A.cd.hRear)]]},R=l.hFront,M=l.hRear,v=g(R,M),x=0;for(;v.norm>=Ay&&x<Vw;){x++;let C=y(R,M),T=i>0?d/i:0,S=c>0?d/c:0,A=wo(e,s,h(R,M)),P=i>0?A/i:0,L=c>0?A/c:0,D=1+C[0][0]-T*p.front-P,I=C[0][1]-T*p.rear+P,G=C[1][0]+S*p.front+L,O=1+C[1][1]+S*p.rear-L,W=D*O-I*G,E,_;Math.abs(W)>1e-9?(E=-(O*v.rF-I*v.rR)/W,_=-(-G*v.rF+D*v.rR)/W):(E=-.5*v.rF,_=-.5*v.rR);let V=Math.max(1,Math.abs(E)/Fy,Math.abs(_)/Fy);E/=V,_/=V;let N=1;for(let $=0;$<6;$++){let K=g(R+N*E,M+N*_);if(K.norm<=v.norm||$===5){R+=N*E,M+=N*_,v=K;break}N*=.5}}let k=y(R,M,!0),F=2+k[0][0]+k[1][1],w=(1+k[0][0])*(1+k[1][1])-k[0][1]*k[1][0];return{v:r,axG:n,hFront:R,hRear:M,cgHeight:h(R,M),cgForward:e.wheelbase>0?h(R,M)*b(R,M)/e.wheelbase:0,cgNoseLoad:wo(e,s,h(R,M))*b(R,M),clFront:v.c.clFront,clRear:v.c.clRear,cd:v.c.cd,area:m,downforce:v.downFront+v.downRear,drag:v.drag,downFront:v.downFront,downRear:v.downRear,gain:$w(k),stable:w>0&&F>0,converged:v.norm<Ay,iterations:x,clampedRide:v.c.clampedRide,yawDeg:o.yawDeg,rollDeg:o.rollDeg,clampedAttitude:v.c.clampedAttitude}}function $w(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 za(e,t,r=0,n){let o=Yr(e,t,r,n);return o?{downforce:o.downforce,drag:o.drag,downFront:o.downFront,downRear:o.downRear}:e.aero?Fo(e.aero,t):{downforce:0,drag:0,downFront:0,downRear:0}}function Ec(e,t=0,r=0,n,o){if(e.aero&&t>0){if(e.aero.model){let i=Yr(e,t,r,n);return{height:i.cgHeight,forward:i.cgForward,noseLoad:i.cgNoseLoad}}let a=Fo(e.aero,t),s=e.wheelbase>0?a.drag*e.aero.copHeight/e.wheelbase:0;return Dc(e,o??Ce(e),r,a.downFront-s,a.downRear+s)}return r===0?{height:e.cgHeight,forward:0,noseLoad:0}:Dc(e,o??Ce(e),r,0,0)}var Cy=[0,1,0],Wp=[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],jp=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]],Gw=e=>X(e,e),Wr=e=>Math.sqrt(X(e,e)),Ya=(e,t)=>Gw(H(e,t)),ve=(e,t)=>Wr(H(e,t)),q=e=>{let t=Wr(e);return t<1e-12?[0,0,0]:[e[0]/t,e[1]/t,e[2]/t]};var jr=(e,t,r)=>{let n=q(r),o=H(e,t);return ee(t,U(n,X(o,n)))},Ty=(e,t,r)=>ve(e,jr(e,t,r));var Hw=1e-6;function zw(e){if(e<Hw){let n=e*e;return[1-n/6,.5-n/24]}let t=Math.sin(e),r=Math.cos(e);return[t/e,(1-r)/(e*e)]}function nt(e,t){let r=Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]);if(r<1e-14)return t;let[n,o]=zw(r),a=ae(e,t),s=ae(e,a);return ee(t,ee(U(a,n),U(s,o)))}function Et(e,t,r){let n=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);if(n<1e-14)return e;let o=[t[0]/n,t[1]/n,t[2]/n];return nt(U(o,r),e)}function qt(e,t){let r=t.length,n=e.map(a=>a.slice()),o=t.slice();return Ly(n,o,r,new Array(r).fill(0))}function Py(e,t,r){return Ly(e,t,t.length,r)}function Ly(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 Dy=e=>{let t=0;for(let r of e)t=Math.max(t,Math.abs(r));return t},Ey=e=>{let t=0;for(let r of e)t+=r*r;return t},Yw=Math.sqrt(Number.EPSILON);function Iy(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=Dy(c),u=Ey(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),M=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=Yw*Math.max(Math.abs(i[C]),s[C]);for(let A=0;A<a;A++)M[A]=i[A];M[C]+=T;let S=e(M);for(let A=0;A<p;A++)d[A][C]=(S[A]-c[A])/T}let k=0;for(let C=0;C<a;C++){for(let S=0;S<a;S++){let A=0;for(let P=0;P<p;P++)A+=d[P][C]*d[P][S];h[C][S]=A}let T=0;for(let S=0;S<p;S++)T+=d[S][C]*c[S];g[C]=T,k=Math.max(k,h[C][C])}let F=Math.max(k,1e-9),w=!1;for(let C=0;C<18;C++){let T=m*F;for(let A=0;A<a;A++){let P=h[A],L=b[A];for(let D=0;D<a;D++)L[D]=A===D?P[D]+T:P[D];y[A]=-g[A]}let S=Py(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=Ey(A);if(P<u){for(let L=0;L<a;L++)i[L]=v[L];c=A,u=P,l=Dy(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 Wa(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 Up(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 _y=e=>[e[0],-e[1],-e[2],-e[3]];function Ny(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 Oy(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 Vy(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 Xp(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 By(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 $y(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 Ww(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 jw(e){let t=e.hardpoints,r=q(H(t.damperChassis,t.pushrodOuter)),[n,o]=Ww(r);return{top:t.damperChassis,lower0:t.pushrodOuter,axis0:r,e1:n,e2:o}}function qp(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=Ya(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:jw(e)}:{}}}function It(e,t,r){let n=[t[3],t[4],t[5]],o=[t[0],t[1],t[2]],a=H(r,e.c0);return ee(ee(nt(n,a),e.c0),o)}function Qp(e,t){return ee(e.lcaFront,Et(e.lbjRel0,e.lcaDir,t))}function To(e,t){return e.steerMovesRack?ee(e.tieInner0,U(e.rackAxis,t)):e.tieInner0}function Zp(e,t,r,n){let o=It(e,t,e.lbj0),a=Qp(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,It(e,t,d.lower0));l=X(b,nt(h,d.e1)),u=X(b,nt(h,d.e2))}else{let d=It(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=It(e,t,e.tro0),f=To(e,n),p=(Ya(m,f)-e.tieLen2)/e.tieLenRef;return[s,i,c,l,u,p]}var ja=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]),Ic=e=>{let t=ja(e);return[e[0]/t,e[1]/t,e[2]/t]},Uw=(e,t)=>H(e,U(t,X(e,t))),Jp=e=>Ic(ae(e,Math.abs(e[0])<.6?[1,0,0]:[0,1,0]));function Xw(e,t){let r=e.ucaDir,n=ee(e.ucaFront,U(r,e.ubjAxial0)),o=Math.sqrt(e.ubjRadius2),a=Uw(H(e.ubj0,e.ucaFront),r),s=ja(a)>1e-9?Ic(a):Jp(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=Wa(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=Ic(c),d=(h,b)=>{let g=ee(n,ee(U(s,o*h),U(i,o*b))),y=Ic(H(g,t));return{q1:Oy(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 qw(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=ja(a),i=s>1e-9?U(a,1/s):Jp(n),c=H(t.top,r),l=ja(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=Jp(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:Up(Xp(R,y,ae(R,y)),_y(Xp(i,n,ae(i,n)))),k:u,margin:f,ok:f>=0}};return f>0?[h(1),h(-1)]:[h(1)]}function Qw(e,t,r,n){let{k:o}=n,a=Ny(n.q1,H(e.tro0,e.lbj0)),s=X(a,o),i=H(a,U(o,s)),c=ja(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=Wa(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:Up(Vy(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 Gy(e,t,r,n=[0,0,0,0,0,0]){let o=Qp(e,t),a=To(e,r),s=By([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?qw(e,e.strut,o):Xw(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=Qw(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 M=i(R);y&&(!l||M>l.near)&&(l={q:R,margin:g,near:M}),!y&&(!u||M>u.near)&&(u={q:R,margin:g,near:M})}}let{q:m,margin:f}=l??u,p=$y(m),d=H(H(o,e.c0),nt(p,H(e.lbj0,e.c0)));return{x:[d[0],d[1],d[2],p[0],p[1],p[2]],converged:l!==null,margin:f,free:!1}}function Hy(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:Ya(e.pushrodOuter,e.rockerToPushrod),damperLen0:ve(e.rockerToDamper,e.damperChassis)}}var Zw=(e,t)=>ee(e.pivotA,Et(e.rprRel0,e.axis,t)),ed=(e,t)=>ee(e.pivotA,Et(e.rdmRel0,e.axis,t));function Ua(e,t){return{pushrod:Zw(e,t),damper:ed(e,t)}}function zy(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=Wa(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(ed(e,r),e.damperChassis),converged:p,margin:0}}let u=Ky(Math.atan2(l.s1,l.c1),r),m=Ky(Math.atan2(l.s2,l.c2),r),f=Math.abs(m-r)<Math.abs(u-r)?m:u;return{phi:f,damperLength:ve(ed(e,f),e.damperChassis),converged:l.ok,margin:l.margin}}function Ky(e,t){let r=2*Math.PI;return e+r*Math.round((t-e)/r)}function Yy(e,t,r,n){return ee(t,nt(U(q(r),n),H(e,t)))}function Wy(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 jy(e,t,r,n){return ee(t,nt(U(q(r),n),H(e,t)))}var _c=180/Math.PI,Jw=(e,t,r)=>Math.max(t,Math.min(r,e)),Uy=[NaN,NaN,NaN];function Xa(e){let t=q(e.spinAxis),r=q(H(e.uprightUpper,e.uprightLower)),n=-Math.asin(Jw(t[2],-1,1))*_c,o=Math.atan2(t[0],t[1])*_c,a=Math.atan2(-r[0],r[2])*_c,s=Math.atan2(-r[1],r[2])*_c,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]):Uy,d=m?f(e.wheelCenter[2]):Uy,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),M=X(R,y),v=-X(R,g),x=e.wheelCenter[1]-d[1],k=d[0]-e.wheelCenter[0],F=Ty(e.tieOuter,u,r);return{camber:n,toe:o,caster:a,kpi:s,scrubRadius:h,mechanicalTrail:b,scrubAtWheel:M,trailAtWheel:v,kingpinOffset:x,casterOffset:k,steeringArm:F,contactPatch:l,kingpinGround:p,kingpinAtHub:d}}function et(e){return{corner:e,inv:qp(e),rocker:Hy(e.hardpoints)}}var eC=[20,20,20,.2,.2,.2];function qy(e,t,r,n=[0,0,0,0,0,0]){let o=Gy(e,t,r,n);if(!o.free)return o;let a=tC(e,t,r,n);return{x:a.x,converged:a.converged,margin:0}}function tC(e,t,r,n=[0,0,0,0,0,0]){return Iy(o=>Zp(e,o,t,r),n,{scales:eC,tol:1e-10,maxIter:40})}var rC=.01,Nc=1.2,pt=e=>e.ok?e.state:null,ot=e=>e.ok?e.state:e.nearest;function ge(e,t,r,n,o){let a=0,s=Ee(e,a,r,n,o);if(Math.abs(s.travel-t)<1e-4)return Xy(s,t,!1);let c=(Ee(e,.02,r,td(s),o).travel-s.travel)/.02;(!Number.isFinite(c)||Math.abs(c)<1e-6)&&(c=1);let l=f=>Math.max(-Nc,Math.min(Nc,f)),u=l((t-s.travel)/c),m=Ee(e,u,r,td(s),o);for(let f=0;f<12&&!(Math.abs(m.travel-t)<1e-4);f++){let p=m.travel-s.travel,d=Math.abs(p)<1e-9?u:u-(m.travel-t)*((u-a)/p);a=u,s=m,u=l(d),m=Ee(e,u,r,td(s),o)}return Xy(m,t,Math.abs(u)===Nc)}function Xy(e,t,r){let n=e.travel-t,o=Math.abs(n)<=rC,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 td(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 nC(e,t,r,n,o){switch(e){case"upright":return It(t,r,o.pushrodOuter);case"upperArm":{let a=It(t,r,t.ubj0),s=Wy(t.ubj0,a,t.ucaFront,t.ucaDir);return jy(o.pushrodOuter,t.ucaFront,t.ucaDir,s)}default:return Yy(o.pushrodOuter,t.lcaFront,t.lcaDir,n)}}function Ee(e,t,r,n,o){let{inv:a,corner:s}=e,i=n?.q??[0,0,0,0,0,0],c=qy(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:It(a,l,f.uprightUpper),b=It(a,l,f.uprightLower),g=It(a,l,f.tieOuter),y=It(a,l,f.wheelCenter),R=q(nt(u,p.spinAxis)),M=nC(d?"upright":p.pushrodAttach,a,l,t,f),v=d?d.top:f.damperChassis,x=d||p.actuation==="direct"?{phi:0,damperLength:ve(M,v),converged:!0,margin:1}:zy(e.rocker,M,n?.phi??0),k=Xa({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:M,spinAxis:R,contactPatch:k.contactPatch,kingpinGround:k.kingpinGround,kingpinAtHub:k.kingpinAtHub,rockerAngle:x.phi,damperLength:x.damperLength},metrics:{camber:k.camber,toe:k.toe,caster:k.caster,kpi:k.kpi,scrubRadius:k.scrubRadius,mechanicalTrail:k.mechanicalTrail,scrubAtWheel:k.scrubAtWheel,trailAtWheel:k.trailAtWheel,kingpinOffset:k.kingpinOffset,casterOffset:k.casterOffset,steeringArm:k.steeringArm,damperLength:x.damperLength},converged:c.converged&&x.converged,margin:Math.min(c.margin,x.margin)}}var Po=e=>e==="FL"||e==="FR"?"front":"rear",Zy=e=>e==="FL"||e==="RL"?"left":"right";function $e(e,t){return e.corners?.[t]??oC(e[Po(t)],Zy(t))}function Jy(e){let t=e.config.springSplit;return e.config.actuation==="decoupled"||t===void 0||!Number.isFinite(t)||Math.abs(t)>=1?0:t}var Qy=new WeakMap;function oC(e,t){let r=Jy(e);if(r===0)return e;let n=Qy.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)},Qy.set(e,n)}return n[t]}var Lo=["FL","FR","RL","RR"],dt=e=>2*e.hardpoints.wheelCenter[1],Ur=(e,t)=>t?dt($e(e,"FL"))/2+dt($e(e,"FR"))/2:dt($e(e,"RL"))/2+dt($e(e,"RR"))/2;function Ze(e,t){let r=e==="FL"||e==="FR";return{axleX:r?t.frontAxleX:t.frontAxleX-t.wheelbase,sideSign:e==="FR"||e==="RR"?1:-1,isFront:r}}function _t(e,t){return[t.axleX+e[0],t.sideSign*e[1],e[2]]}function Xr(e,t){return[e[0],t.sideSign*e[1],e[2]]}function Do(e){return e.frontAxleX-e.wheelbase/2}function rd(e,t,r){return t[2]+e.heave+(t[0]-r)*Math.sin(e.pitch)-t[1]*Math.sin(e.roll)}function qr(e,t,r,n){let o=Ze(e,t),a=(n?Ur(n,o.isFront):o.isFront?t.trackFront:t.trackRear)/2,s=o.sideSign*a,i=o.axleX-Do(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 aC={travelMin:-40,travelMax:40,steps:41,steer:0};function qa(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 qe(e,t={}){let r={...aC,...t},n=et(e);return Eo(n,r)}function Eo(e,t){let r=t.steer,n=.01,o=Ee(e,n,r),a=Ee(e,-n,r),s=(o.travel-a.travel)/(2*n);(!Number.isFinite(s)||Math.abs(s)<1e-6)&&(s=1);let i=Math.max(Math.abs(t.travelMax),Math.abs(t.travelMin)),c=Math.min(1.2,1.5*i/Math.abs(s)),l=Math.max(20,t.steps*2),u=[],m=Ee(e,0,r);u.push({beta:0,travel:m.travel,warm:qa(m),converged:m.converged});let f=qa(m);for(let R=1;R<=l;R++){let M=c*R/l,v=Ee(e,M,r,f);f=qa(v),u.push({beta:M,travel:v.travel,warm:f,converged:v.converged})}f=qa(m);for(let R=1;R<=l;R++){let M=-c*R/l,v=Ee(e,M,r,f);f=qa(v),u.push({beta:M,travel:v.travel,warm:f,converged:v.converged})}u.sort((R,M)=>R.beta-M.beta);let p=u[u.length-1].travel>=u[0].travel,d=!1;for(let R=1;R<u.length;R++){let M=u[R].travel-u[R-1].travel;(p&&M<-1e-6||!p&&M>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 M=t.steps===1?t.travelMin:t.travelMin+(t.travelMax-t.travelMin)*R/(t.steps-1),v=sC(u,M,p),x=iC(u,v);y.push(Ee(e,v,r,x))}return cC(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 sC(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 iC(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 nd(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 cC(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=nd(n,r,s),c=nd(o,r,s),l=-nd(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 Oc=e=>e!==void 0&&Number.isFinite(e)&&e>0;function lC(e){return e&&Oc(e.helperRate)&&Oc(e.helperTravel)?{rate:e.helperRate,travel:e.helperTravel}:null}function od(e,t,r){let n=t/e;return r?n+Math.min(t/r.rate,r.travel):n}function Qa(e,t,r,n){if(!(e>0)||!Number.isFinite(e)||!(t>0)||!Number.isFinite(t))return null;let o=lC(n),a=-od(e,t,o),s=Io(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 Io(e,t){if(!Number.isFinite(e))return{droop:null,bump:null};let r=Oc(t?.extended)&&t.extended>e?t.extended:null,n=r!==null&&Oc(t?.stroke)?r-t.stroke:null;return{droop:r!==null?e-r:null,bump:n!==null&&n<e?e-n:null}}function ad(e,t){if(!(e>0)||!Number.isFinite(e))return null;let r=Io(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 uC(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=od(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 mC(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=od(r,n,o)+t;return a<=0?0:a>=o.rate*o.travel/r+o.travel?r:r*o.rate/(r+o.rate)}function _o(e,t){let r=uC(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 sd(e,t){let r=mC(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 id(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 Vc={min:-60,max:60,steps:61},cd=e=>({travel:[e.min,e.max],force:[0,0],motionRatio:[0,0],spring:null}),ex=new WeakMap;function pC(e,t){let r=ex.get(e.corner);r||ex.set(e.corner,r=new Map);let n=`${t.min}|${t.max}|${t.steps}`,o=r.get(n);return o||r.set(n,o=Eo(e,{travelMin:t.min,travelMax:t.max,steps:t.steps,steer:0})),o}function Za(e,t,r=Vc,n=e.corner.config.coilover){let o=e.corner.config;if(o.actuation==="decoupled")return cd(r);let a=pC(e,r),s=fC(e,o.springRate,a.samples),i=[];for(let h of a.samples){let b=h.metrics.motionRatio;!h.converged||b===void 0||!Number.isFinite(b)||!Number.isFinite(h.metrics.damperLength)||i.length>0&&h.travel<=i[i.length-1].t+1e-6||i.push({t:h.travel,L:h.metrics.damperLength,mr:b})}if(i.length<2)return cd(r);let c=bC(i,0);if(!(Math.abs(c.mr)>1e-6))return cd(r);let l=t/c.mr,u=Qa(s,l,c.L,n),m=u?dC(i,id(u).map(h=>c.L-h)):i,f=m.map(h=>(u?_o(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?id(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}:{}}}function dC(e,t){let r=[...e];for(let n of t)for(let o=0;o+1<e.length;o++){let a=e[o],s=e[o+1];if(a.L===n)break;if((a.L-n)*(s.L-n)>=0)continue;let i=(n-a.L)/(s.L-a.L);r.push({t:a.t+i*(s.t-a.t),L:n,mr:a.mr+i*(s.mr-a.mr)});break}return r.sort((n,o)=>n.t-o.t),r.filter((n,o)=>o===0||n.t>r[o-1].t+1e-6)}function fC(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:hC(e,n,r);return!(o>0)||!Number.isFinite(o)?t:t*o/(t+o)}function hC(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=Ua(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 ld(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.motionRatio[0];let n=gr(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 br(e,t,r){if(!e.spring)return Kt(e,t);let{rate:n,preload:o,length0:a,law:s}=e.spring,i=ld(e,0),c=a-r;return(s?_o(s,c):o+n*c)*ld(e,t)-o*i}function bC(e,t){let r=gr(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 gr(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 Kt(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.force[0];let n=gr(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 No(e,t){let r=e.travel.length;if(r<3)return Ja(e,t);let n=gr(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 Ja(e,t){if(e.travel.length<2)return 0;let n=gr(e.travel,t);return(e.force[n+1]-e.force[n])/(e.travel[n+1]-e.travel[n])}function Pe(e,t,r){let n=e.hardpoints;switch(t.attach){case"upright":{let o=H(t.outer,n.wheelCenter);return ee(ee(nt(r.pose.omega,o),n.wheelCenter),r.pose.t)}case"lowerArm":{let o=q(H(n.lcaRear,n.lcaFront));return ee(n.lcaFront,nt(U(o,r.beta),H(t.outer,n.lcaFront)))}case"rocker":{let o=q(H(n.rockerPivotB,n.rockerPivotA));return ee(n.rockerPivotA,Et(H(t.outer,n.rockerPivotA),o,r.points.rockerAngle))}}}function Qr(e,t,r){return e.config.actuation==="decoupled"&&t.attach==="rocker"&&r==="coil"}function ud(e,t,r){return Qr(e,t,r)?[t.inner[0],-t.inner[1],t.inner[2]]:t.inner}function Oo(e,t,r){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return md(e,t,r.kind,qe(e,{travelMin:n,travelMax:o,steps:a}).samples)}function md(e,t,r,n){let o=q(H(t.outer,ud(e,t,r))),a=[],s=[],i=t.outer;for(let p of n)a.push(p.travel),s.push(X(H(Pe(e,t,p),i),o));let c=a.length,l=new Array(c).fill(0);for(let p=0;p<c;p++){let d=Math.max(0,p-1),h=Math.min(c-1,p+1),b=a[h]-a[d];l[p]=b!==0?(s[h]-s[d])/b:0}let u=l[0];for(let p=1;p<c;p++)if(a[p]>=0){let d=a[p]-a[p-1],h=d!==0?(0-a[p-1])/d:0;u=l[p-1]+h*(l[p]-l[p-1]);break}let m=l.filter(p=>Math.abs(p)>1e-9).map(Math.sign),f=m.length>0&&m.some(p=>p!==m[0]);return{travel:a,ratio:l,linkTravel:s,atDesign:u,reverses:f}}function pd(e,t){let{travel:r,ratio:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}function dd(e,t){let{travel:r,linkTravel:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}var es=e=>e.mount??{kind:"rockerToRocker"},ox=e=>[e[0],0,e[2]],gC=e=>2*Math.abs(e[1]),yC=(e,t)=>Math.hypot(e[0]-t[0],e[2]-t[2]);function $c(e,t){return t.kind==="chassis"?yC(e,t.anchor):gC(e)}function ts(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 kn(e,t,r={}){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return fd(e,t,qe(e,{travelMin:n,travelMax:o,steps:a}).samples)}function fd(e,t,r){let n=es(t),o=d=>Pe(e,{...t,inner:t.outer},r[d]),a=[],s=[],i=[];for(let d=0;d<r.length;d++)a.push(r[d].travel),i.push($c(o(d),n));let c=rx(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=tx(a,20),f=tx(a,-20),p=ts(o(m),o(f),n);return{travel:a,ratio:u,springTravel:s,atDesign:rx(a,u,0),installedLength:c,rollSensitivity:c-p}}function tx(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 rx(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 hd(e,t,r){let n={outer:t.outer,attach:t.attach},o=qe(e,{travelMin:-5,travelMax:5,steps:3}),a=d=>ox(Pe(e,{...n,inner:n.outer},o.samples[d])),s=a(1),i=a(2),c=a(0),l=i[0]-c[0],u=i[2]-c[2],m=Math.hypot(l,u),f=m>1e-9?[l/m,u/m]:[0,1],p=r??Math.max(80,2*Math.abs(t.outer[1])*.5);return[s[0]+f[0]*p,0,s[2]+f[1]*p]}function bd(e,t){let r=e.hardpoints,n=r.rockerPivotA,o=nx(Bc(r.rockerPivotB,r.rockerPivotA)),a=Math.max(30,.6*ax(Bc(r.rockerToDamper,n))),s=Bc(r.rockerToDamper,n),i=nx(Bc(s,xC(o,RC(s,o)))),c=vC(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:hd(e,d)}}:d,b;try{b=kn(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 Bc=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],xC=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],RC=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],ax=e=>Math.hypot(e[0],e[1],e[2]),nx=e=>{let t=ax(e)||1;return[e[0]/t,e[1]/t,e[2]/t]},vC=(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 gd=.001,kC=e=>({outer:e.outer,inner:e.outer,attach:e.attach}),dx=(e,t,r)=>($c(e.at0,t)-$c(r,t))/2,MC=(e,t)=>X(H(t,e.pickup.at0),e.axis);function yd(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 sx(e,t){let r=[0,1,2].map(n=>yd(e,t.map(o=>o[n])));return t.map((n,o)=>[r[0][o],r[1][o],r[2][o]])}function xd(e){return{travel:e,heave:e.map(t=>t/2),heaveRatio:e.map(()=>.5),roll:[...e],rollRatio:e.map(()=>1)}}function ix(e,t,r,n){let o=e.corner;if(!t.heave&&!t.roll)return{side:xd([n.min,n.max]),pickups:{}};let a=ot(ge(e,0,0)),s={};if(t.heave&&r){let h=kC(t.heave);s.heave={corner:o,link:h,at0:Pe(o,h,a)}}if(t.roll){let h=t.roll;s.roll={pickup:{corner:o,link:h,at0:Pe(o,h,a)},axis:q(H(h.outer,ud(o,h,t.rollKind??"coil")))}}let i=t.roll&&Qr(o,t.roll,t.rollKind??"coil")?{near:t.roll,far:{...t.roll,outer:t.roll.inner}}:null,c=Eo(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?dx(s.heave,r,Pe(o,s.heave.link,h)):h.travel/2),m.push(s.roll?MC(s.roll,Pe(o,s.roll.pickup.link,h)):h.travel),i&&(f.push(Pe(o,i.near,h)),p.push(Pe(o,i.far,h))));if(l.length<2)return{side:xd([n.min,n.max]),pickups:{}};let d={travel:l,heave:u,heaveRatio:yd(l,u),roll:m,rollRatio:yd(l,m)};return i&&(d.eyes={near:f,nearRatio:sx(l,f),far:p,farRatio:sx(l,p)}),{side:d,pickups:s}}function Gc(e,t,r){let n=gr(e,r);return t[n]+(r-e[n])/(e[n+1]-e[n])*(t[n+1]-t[n])}function cx(e,t,r){let n=gr(e,r);return(t[n+1]-t[n])/(e[n+1]-e[n])}function He(e,t){return{h:Gc(e.travel,e.heave,t),dh:Gc(e.travel,e.heaveRatio,t),ddh:cx(e.travel,e.heaveRatio,t),r:Gc(e.travel,e.roll,t),dr:Gc(e.travel,e.rollRatio,t),ddr:cx(e.travel,e.rollRatio,t)}}function lx(e,t,r,n){let o=gr(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 Rd=(e,t)=>Math.hypot(e[0]-t[0],e[1]+t[1],e[2]-t[2]);function fx(e,t){let r=e.side[0].eyes,n=e.side[1].eyes;if(!r||!n)return null;let o=lx(e.side[0].travel,r.near,r.nearRatio,t[0]),a=lx(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 hx=(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,SC=(e,t)=>e.bump!==null&&t>e.bump||e.droop!==null&&t<e.droop?e.rate:0;function rs(e,t,r,n,o=0){let a=e.rollStop;if(!a)return r;let s=fx(e,t);if(!s)return r;let i=hx(a,a.length0-(n??s.L+o));return i===0?r:[r[0]-i*s.dL[0],r[1]-i*s.dL[1]]}function Kc(e,t){let r=xd(e.travel);return t==="heave"?{...e,heave:r.heave,heaveRatio:r.heaveRatio}:{...e,roll:r.roll,rollRatio:r.rollRatio}}var Hc=(e,t)=>e?e.law?_o(e.law,t):e.preload+e.rate*t:0,ux=(e,t)=>e?e.law?sd(e.law,t):e.rate:0;function ns(e,t,r,n,o){let a=Hc(e.heave,n),s=Hc(e.roll,o);return[a*t.dh+s*t.dr,a*r.dh-s*r.dr]}var mx=(e,t)=>He(e[0],t).h+He(e[1],t).h;function AC(e,t){let r=e.gap>0?mx(t,e.gap):0;return e.bothWays?{free:r,pull:e.gap>0?mx(t,-e.gap):0}:{free:r,pull:null}}function FC(e,t,r){let n={...t,outer:t.inner},o=(u,m)=>{let f=pt(ge(e[0],u,0)),p=pt(ge(e[1],m,0));if(!f||!p)return NaN;let d=Pe(e[0].corner,t,f),h=Pe(e[1].corner,n,p);return Math.hypot(d[0]-h[0],d[1]+h[1],d[2]-h[2])},a=1,s=o(0,0),i=o(-a,a)-o(a,-a),c=He(r[0],a).r-He(r[1],-a).r-(He(r[0],-a).r-He(r[1],a).r),l=i/c;return Number.isFinite(s)&&s>0&&Number.isFinite(l)&&Math.abs(l)>gd?{length0:s,scale:l}:null}function bx(e,t,r,n=Vc){let o=r.heave?es(r.heave):void 0,a=ix(e[0],r,o,n),s=e[1].corner===e[0].corner?a:ix(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=>He(A,0));c&&!(Math.abs(p[0].dh+p[1].dh)>gd)&&(i=[Kc(i[0],"heave"),Kc(i[1],"heave")],c=!1),l&&!(Math.abs(p[0].dr+p[1].dr)>gd)&&(i=[Kc(i[0],"roll"),Kc(i[1],"roll")],l=!1),p=i.map(A=>He(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 M={};if(c&&o){let A=[a.pickups.heave,s.pickups.heave];M.heave={pickups:A,mount:o,span0:ts(A[0].at0,A[1].at0,o)}}let v=M.heave?M.heave.span0:NaN,x=M.heave?r.coilover:void 0,k=r.carriesLoad?Qa(b,y,v,x):u?ad(b,{...AC(u,i),length0:v,coilover:x}):null,F=b>0?{rate:b,preload:y,...k?{law:k}:{}}:null;if(l&&(M.roll={pickups:[a.pickups.roll.pickup,s.pickups.roll.pickup],axes:[a.pickups.roll.axis,s.pickups.roll.axis]},r.roll&&Qr(e[0].corner,r.roll,r.rollKind??"coil"))){let A=FC(e,r.roll,i);A&&(M.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:M},T=M.roll?.unit,S=T&&g>0&&i[0].eyes&&i[1].eyes?Io(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=rs(C,[0,0],ns(C,p[0],p[1],p[0].h+p[1].h,p[0].r-p[1].r)),C}function os(e,t,r){let n=He(e.side[0],t[0]),o=He(e.side[1],t[1]),a=r?rs(e,t,ns(e,n,o,n.h+o.h+r.heave,n.r-o.r+r.roll),void 0,r.unit):rs(e,t,ns(e,n,o,n.h+o.h,n.r-o.r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function vd(e,t,r){let n=He(e.side[0],t[0]),o=He(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=ux(e.heave,a),c=ux(e.roll,s),l=Hc(e.heave,a),u=Hc(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?fx(e,t):null;if(!p||!d)return f;let h=p.length0-(r?d.L+r.unit:d.L),b=SC(p,h);if(b===0)return f;let g=hx(p,h),y=(M,v)=>b*d.dL[M]*d.dL[v]-g*d.ddL[M][v],R=m+y(0,1);return[[f[0][0]+y(0,0),R],[R,f[1][1]+y(1,1)]]}function kd(e,t,r){let n=vd(e,t);return n[r][0]+n[r][1]}function wC(e,t,r){let n=e.read.heave;if(!n)return He(e.side[0],t[0]).h+He(e.side[1],t[1]).h;let[o,a]=n.pickups;return n.span0-ts(Pe(o.corner,o.link,r[0]),Pe(a.corner,a.link,r[1]),n.mount)}function CC(e,t,r){let n=e.read.roll;if(!n)return He(e.side[0],t[0]).r-He(e.side[1],t[1]).r;let o=a=>X(H(Pe(n.pickups[a].corner,n.pickups[a].link,r[a]),n.pickups[a].at0),n.axes[a]);return o(0)-o(1)}function TC(e,t){let r=e.read.roll;if(!e.rollStop||!r)return;let[n,o]=r.pickups;return Rd(Pe(n.corner,n.link,t[0]),Pe(o.corner,{...o.link,outer:o.link.inner},t[1]))}function as(e,t,r){let n=He(e.side[0],t[0]),o=He(e.side[1],t[1]),a=rs(e,t,ns(e,n,o,wC(e,t,r),CC(e,t,r)),TC(e,r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function Md(e,t,r,n){let o=He(e.side[0],r),a=He(e.side[1],r),s=e.read.heave,i=s?.pickups[t],c=s&&i&&n?2*dx(i,s.mount,Pe(i.corner,i.link,n)):o.h+a.h,l=e.rollStop&&n?e.read.roll?.pickups[t]:void 0,u=l&&n?Rd(Pe(l.corner,l.link,n),Pe(l.corner,{...l.link,outer:l.link.inner},n)):void 0;return rs(e,[r,r],ns(e,o,a,c,n?0:o.r-a.r),u)[t]-e.force0[t]}function Sd(e,t,r,n){let o=No(e,r[n]);return t?.carriesLoad?o+kd(t,r,n):o}var Ad=e=>e==="FR"||e==="RR"?1:0,zc=(e,t)=>e.elements?.[t==="FL"||t==="FR"?"front":"rear"]??null;var gx=e=>Number.isFinite(e)&&e>0?1/e:0;var yx=(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},PC=(e,t)=>[e[0][0]*t[0]+e[0][1]*t[1],e[1][0]*t[0]+e[1][1]*t[1]],xx=1e-8,LC=40;function DC(e,t,r,n){return{force:(s,i)=>{if(r){let u=os(r,s,n);return[Kt(t[0],s[0])+i[0]+u[0],Kt(t[1],s[1])+i[1]+u[1]]}let c=(s[0]+s[1])/2,l=(s[0]-s[1])/2;return[Kt(t[0],s[0])+i[0]+e[0].heaveRate*c+e[0].arbRate*l,Kt(t[1],s[1])+i[1]+e[1].heaveRate*c-e[1].arbRate*l]},stiffness:(s,i=Ja)=>{if(r){let c=vd(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 Vo(e,t,r,n,o,a=[0,0],s=[0,0],i=null,c){let l=[gx(r[0].tyreRate),gx(r[1].tyreRate)],u=[r[0].staticLoad,r[1].staticLoad],m=DC(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]),I=[D[0]+s[0]*L,D[1]+s[1]*L],G=[P[0]+t[0]*L+I[0]*l[0]-e[0]*L,P[1]+t[1]*L+I[1]*l[1]-e[1]*L],O=[d[0]*(u[0]+I[0]),d[1]*(u[1]+I[1])],W=[O[0]<G[0],O[1]<G[1]];return{f:I,on:G,off:O,lifted:W,r:[Math.min(G[0],O[0]),Math.min(G[1],O[1])]}},b=(P,L)=>[L[0]?[d[0]*P[0][0],d[0]*P[0][1]]:[1+P[0][0]*l[0],P[0][1]*l[0]],L[1]?[d[1]*P[1][0],d[1]*P[1][1]]:[P[1][0]*l[1],1+P[1][1]*l[1]]],g=P=>Math.max(Math.abs(P[0]),Math.abs(P[1])),y=(P,L)=>{let D=[P[0],P[1]],I=h(D,L),G=!1,O=0;for(;O<LC;O++){if(g(I.r)<xx){G=!0;break}let W=yx(b(m.stiffness(D),I.lifted),[-I.r[0],-I.r[1]]);if(!W)break;let E=1,_=[D[0]+W[0],D[1]+W[1]],V=h(_,L);for(let N=0;N<8&&g(V.r)>g(I.r);N++)E/=2,_=[D[0]+E*W[0],D[1]+E*W[1]],V=h(_,L);D=_,I=V}return!G&&g(I.r)<xx&&(G=!0),{t:D,b:I,converged:G,it:O}},R=y(o?[o[0],o[1]]:[e[0]-t[0],e[1]-t[1]],1),M=R.it;if(!R.converged){let P=0,L=[0,0],D=.25;for(;P<1&&D>=1/256;){let I=Math.min(1,P+D),G=y(L,I);M+=G.it,G.converged?(P=I,L=G.t,I===1&&(R=G)):D/=2}}let{t:v,b:x,converged:k}=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,No),S=b(T,F);return{t:v,dF:w,lifted:F,clearance:C,converged:k,iterations:M,respond:(P,L,D=[0,0])=>{let I=[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]],G=yx(S,I);if(!G)return[NaN,NaN];let O=PC(T,G);return[F[0]?0:O[0]+D[0],F[1]?0:O[1]+D[1]]}}}var Mn=e=>!(Number.isFinite(e.tyreRate)&&e.tyreRate>0);function Qt(e,t,r){return t?.input.corners[r].staticLoadedRadius??e}var Fd=["FL","FR","RL","RR"],kx={front:["FL","FR"],rear:["RL","RR"]},EC=512,IC=5e-4,_C=8;function Yc(e,t){let r={},n={},o=new Map;for(let s of Fd){let i=e.ctx[s],c=t.corners[s],l=c.staticLoadedRadius;n[s]=ot(ge(i,0,0,void 0,l===void 0?void 0:{loadedRadius:l})).points.contactPatch[2];let u=t.cornerCoilover?.[s==="FL"||s==="FR"?"front":"rear"],m=`${Fd.findIndex(p=>$e(e.vehicle,p)===$e(e.vehicle,s))}|${c.springLoad}|${u?`${u.extended}/${u.stroke}`:""}`,f=o.get(m);f?r[s]=f:(r[s]=u?Za(i,c.springLoad,void 0,u):Za(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=kx[s];a[s]=bx([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 Mx(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 NC=e=>`${e.heave}|${e.pitch}|${e.roll}|${e.steer}`;function wd(e,t,r){return{travel:r.travel,steer:r.steer,ground:r.travel,tyreDeflection:0,load:NaN,loadedRadius:Qt($e(e.vehicle,t).config.loadedRadius,e.kc,t),lifted:!1,contactLength:0,converged:!0,rigid:!0,rideRate:NaN,wheelRateAtLoad:NaN}}var OC=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 Rx(e,t,r,n){let o=kx[n],a=e.vehicle.config,s=o.map(w=>qr(w,a,r,e.vehicle)),i=[t.input.corners[o[0]],t.input.corners[o[1]]],c=t.loadCase;if(!c&&i.every(Mn))return{corners:[wd(e,o[0],s[0]),wd(e,o[1],s[1])],respond:null};let l=o.map(w=>t.curve[w]),u=t.elements?.[n]??null,m=o.map(w=>Qt($e(e.vehicle,w).config.loadedRadius,t,w)),f=[s[0].travel+(c?.ground[o[0]]??0),s[1].travel+(c?.ground[o[1]]??0)],p=[c?.linkLoad[o[0]]??0,c?.linkLoad[o[1]]??0],d=[c?.patchShift[o[0]],c?.patchShift[o[1]]],h=[0,0],b=[0,0],g,y=Vo(f,h,i,l,void 0,void 0,p,u),R=[void 0,void 0],M=[!0,!0],v=[0,0],x=!1;for(let w=0;w<_C;w++){w>0&&(y=Vo(f,h,i,l,g,b,p,u)),v=[Number.isFinite(i[0].tyreRate)&&i[0].tyreRate>0?y.dF[0]/i[0].tyreRate:0,Number.isFinite(i[1].tyreRate)&&i[1].tyreRate>0?y.dF[1]/i[1].tyreRate:0];let C=[0,0],T=[0,0];for(let A=0;A<2;A++){let P=ge(e.ctx[o[A]],y.t[A],s[A].steer,OC(R[A]),{loadedRadius:m[A]-v[A],patchShift:d[A]}),L=ot(P);R[A]=L,M[A]=P.ok,C[A]=L.points.contactPatch[2]-t.ground0[o[A]]-y.t[A]-v[A],T[A]=br(l[A],y.t[A],L.points.damperLength)-Kt(l[A],y.t[A])}if(u){let A=as(u,y.t,[R[0],R[1]]),P=os(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<IC){x=!0;break}}let k=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:Mx(m[w]-v[w],i[w].staticLoad+y.dF[w],i[w].tyreRate),converged:y.converged&&x&&M[w],rigid:!1,state:C,solved:M[w],rideRate:k[w],wheelRateAtLoad:Sd(l[w],u,y.t,w)}}),respond:y.respond}}function Sx(e,t){let r=e.kc,n=NC(t),o=r.memo.get(n);if(o)return o;let a=Rx(e,r,t,"front"),s=Rx(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>=EC&&r.memo.clear(),r.memo.set(n,i),i}function ft(e,t){if(!e.kc){let r={};for(let n of Fd)r[n]=wd(e,n,qr(n,e.vehicle.config,t,e.vehicle));return r}return Sx(e,t).corners}function Wc(e,t,r){return e.kc?Sx(e,t).respond[r]:null}function ss(e,t,r,n=0){let o=e.kc;if(!o)return r;let a=o.input.corners[t];if(Mn(a))return r;let s=qr(t,e.vehicle.config,{heave:0,pitch:0,roll:0,steer:n},e.vehicle).steer,i=Qt($e(e.vehicle,t).config.loadedRadius,o,t),c=o.loadCase,l=c?.linkLoad[t]??0,u=c?.patchShift[t],m=ot(ge(e.ctx[t],r,s,void 0,{loadedRadius:i,patchShift:u})),f=zc(o,t),p=br(o.curve[t],r,m.points.damperLength)+(f?Md(f,Ad(t),r,m):a.heaveRate*r),h=Math.max(p+l,-a.staticLoad)/a.tyreRate;return(h===0?m:ot(ge(e.ctx[t],r,s,void 0,{loadedRadius:i-h,patchShift:u}))).points.contactPatch[2]-o.ground0[t]-(c?.ground[t]??0)}var VC=180/Math.PI,BC=[0,0,1];function $C(e,t){let r=Xr(e,t),n=U(ae(BC,r),-t.sideSign);return-Math.atan2(n[1],n[0])*VC}var Ax=e=>1/Math.tan(e*Math.PI/180),Fx=.05,wx=.001;function Cx(e,t,r){if(!Number.isFinite(e)||!Number.isFinite(t))return NaN;if(!(Math.abs(e)<wx&&Math.abs(t)<wx))return e>0&&t>0?100*(Ax(t)-Ax(e))/r:NaN}function GC(e,t){let r=Ur(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=[Fx,-Fx].map(l=>{let{inner:u,outer:m}=a(t("FL",l).deg-n,t("FR",l).deg-o);return Cx(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=Cx(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 Cd(e,t){let r=e.vehicle.config,n={FL:Ze("FL",r),FR:Ze("FR",r)},o=t.travel??0,a=GC(e,(i,c)=>{let l=pt(ge(e.ctx[i],o,n[i].sideSign*c));return{deg:l?$C(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 Tx=35,Px=55,Nt=e=>e.rackTravel&&e.rackTravel>0?e.rackTravel:Tx,Td=e=>e.rackRatio&&e.rackRatio>0?e.rackRatio:Px;var Pd=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 Lx(e,t,r,n,o){let a=ge(e,n,0,void 0,o),s=ot(a),i=a.ok?0:1,c=s.points.contactPatch[2],l={steer:s.metrics.toe,camber:s.metrics.camber,lift:0,contactPatch:s.points.contactPatch,spinAxis:s.points.spinAxis,yaw:-s.metrics.toe*Math.PI/180},u=p=>{let d=[l],h=Pd(s);for(let b=1;b<=r;b++){let g=p*(t*b)/r,y=Ee(e,s.beta,g,h,o),R=pt(ge(e,n,g,Pd(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=Pd(y)}return d},m=u(1),f=u(-1);return{travelMm:n,unsolved:i,centre:l,positive:m,negative:f}}function KC(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 Dx(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:KC(o,t)});return{travelMm:e.travelMm,inner:n(r?e.positive:e.negative),outer:n(r?e.negative:e.positive)}}function HC(e){return e.positive[1].steer-e.centre.steer<0}function zC(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:Td(e.config),innerJacobian:r.inner.jacobian,outerJacobian:r.outer.jacobian}}function Ld(e,t,r=13,n=-40,o=40,a=5,s){let i=et(e),c=Array.from({length:r+1},(b,g)=>t*g/r),l=Lx(i,t,r,0,s),u=HC(l),m=Dx(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=Lx(i,t,r,b,s);return d+=g.unsolved,Dx(g,c,u)});return{...zC(e,c,m),...Ex(l.unsolved),travelSurface:{rackMm:c,rows:h,...Ex(d)}}}var Ex=e=>e>0?{unsolved:e}:{};function Zt(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function jc(e,t,r){let n=e.length;if(n===0)return{longitudinal:0,lateral:0,vertical:0,yaw:0};let o,a;if(r<=e[0])o=a=0;else if(r>=e[n-1])o=a=n-1;else for(o=0,a=n-1;a-o>1;){let l=o+a>>1;e[l]<=r?o=l:a=l}let s=t[o];if(o===a)return{longitudinal:s.longitudinal,lateral:s.lateral,vertical:s.vertical,yaw:s.yaw};let i=t[a],c=(r-e[o])/(e[a]-e[o]);return{longitudinal:s.longitudinal+c*(i.longitudinal-s.longitudinal),lateral:s.lateral+c*(i.lateral-s.lateral),vertical:s.vertical+c*(i.vertical-s.vertical),yaw:s.yaw+c*(i.yaw-s.yaw)}}function Ix(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 Sn=(e,t,r)=>e+r*(t-e);function Bo(e,t,r,n,o){let a=Zt(e.rackMm,e.rows[n.lo][t][r],o);if(n.lo===n.hi)return a;let s=Zt(e.rackMm,e.rows[n.hi][t][r],o);return Sn(a,s,n.t)}function _x(e,t,r,n){let o=jc(e.rackMm,e.rows[r.lo][t].jacobian,n);if(r.lo===r.hi)return o;let a=jc(e.rackMm,e.rows[r.hi][t].jacobian,n);return{longitudinal:Sn(o.longitudinal,a.longitudinal,r.t),lateral:Sn(o.lateral,a.lateral,r.t),vertical:Sn(o.vertical,a.vertical,r.t),yaw:Sn(o.yaw,a.yaw,r.t)}}function $o(e,t,r,n){let o=e.travelSurface;if(!o||o.rackMm.length<2||o.rows.length===0)return Go(e,t);let a=Ix(o,r),s=Ix(o,n),i=(p,d,h)=>{let b=o.rows[d.lo][p].steerDeg[h];return d.lo===d.hi?b:Sn(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=Sn(o.rackMm[d],o.rackMm[p],b)}return{innerDeg:Bo(o,"inner","steerDeg",a,m),outerDeg:Bo(o,"outer","steerDeg",s,m),innerCamber:Bo(o,"inner","camberDeg",a,m),outerCamber:Bo(o,"outer","camberDeg",s,m),innerLift:Bo(o,"inner","liftMm",a,m),outerLift:Bo(o,"outer","liftMm",s,m),innerJacobian:_x(o,"inner",a,m),outerJacobian:_x(o,"outer",s,m),atLock:f}}function Go(e,t){let r=e.meanDeg.length-1;return{innerDeg:Zt(e.meanDeg,e.innerDeg,t),outerDeg:Zt(e.meanDeg,e.outerDeg,t),innerCamber:Zt(e.meanDeg,e.innerCamber,t),outerCamber:Zt(e.meanDeg,e.outerCamber,t),innerLift:e.innerLift?Zt(e.meanDeg,e.innerLift,t):0,outerLift:e.outerLift?Zt(e.meanDeg,e.outerLift,t):0,...e.innerJacobian&&e.outerJacobian?{innerJacobian:jc(e.meanDeg,e.innerJacobian,t),outerJacobian:jc(e.meanDeg,e.outerJacobian,t)}:{},atLock:r>=0&&t>e.meanDeg[r]}}var YC=()=>({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 Ko(e,t,r=Ce(e),n){let o=e.steerFront;if(!o?.innerLift||!o.outerLift||o.meanDeg.length<2||Math.abs(t)<1e-12)return YC();let a=Math.abs(t),s=t>0,i=n&&o.travelSurface?$o(o,a,s?n.FL:n.FR,s?n.FR:n.FL):null,c=i?.innerLift??Zt(o.meanDeg,o.innerLift,a),l=i?.outerLift??Zt(o.meanDeg,o.outerLift,a),u=s?c:l,m=s?l:c,f=.5*(u+m),p=r.rollWheelRateFront,d=r.rollWheelRateRear,h=e.trackFront,b=e.trackRear,g=p*h*h+d*b*b,y=g>0?p*h*(m-u)/g:0,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 Dd(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 is=9.81;function Ho(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?Yr(e,t,r,Co(e,n,o)):Fo(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 Ed(e,t,r=0,n=0,o=0){if(!e.aero?.model||t<=0)return!1;let a=Yr(e,t,r,Co(e,n,o));return a!=null&&(a.clampedRide||a.clampedAttitude)}function An(e){let t=e.loadFactor===void 0?e.massTotal*is:e.massTotal*is*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 Nx(e,t=Ce(e),r=e.cgHeight){let n=e.trackFront/1e3,o=e.trackRear/1e3,a=e.rcHeightFront/1e3,s=e.rcHeightRear/1e3,i=(e.rcHeightFront+(e.rcHeightRear-e.rcHeightFront)*(1-e.frontMassFrac))/1e3,c=r/1e3-i,l=2*e.unsprungPerCorner,u=e.unsprungCgHeight/1e3,m=t.sprungMass*c*Mc(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 Id(e){let{cf:t,cr:r}=Nx(e);return t+r>0?t/(t+r):.5}function Ox(e,t,r){if(e.FL>=0&&e.FR>=0&&e.RL>=0&&e.RR>=0)return{loads:{FL:Math.max(0,e.FL),FR:Math.max(0,e.FR),RL:Math.max(0,e.RL),RR:Math.max(0,e.RR)},lifted:{FL:!1,FR:!1,RL:!1,RR:!1},overturned:!1};let n=e.FL+e.FR+e.RL+e.RR;if(!(n>0))return{loads:{FL:0,FR:0,RL:0,RR:0},lifted:{FL:!0,FR:!0,RL:!0,RR:!0},overturned:!0};let o=!1,a=e.FL+e.FR,s=e.RL+e.RR;a<0?(a=0,s=n,o=!0):s<0&&(s=0,a=n,o=!0);let i=(e.FR-e.FL)*t+(e.RR-e.RL)*r,c=Math.min(a,Math.max(-a,e.FR-e.FL)),l=Math.min(s,Math.max(-s,e.RR-e.RL)),u=i-(c*t+l*r);if(u!==0){let f=u>0?1:-1,p=(f*a-c)*t;f*u>=f*p?(c=f*a,u-=p):(c+=u/t,u=0);let d=(f*s-l)*r;u!==0&&(f*u>=f*d?(l=f*s,u-=d):(l+=u/r,u=0)),Math.abs(u)>1e-9*(Math.abs(i)+n*(t+r))&&(o=!0)}let m={FL:Math.max(0,(a-c)/2),FR:Math.max(0,(a+c)/2),RL:Math.max(0,(s-l)/2),RR:Math.max(0,(s+l)/2)};return{loads:m,lifted:{FL:m.FL===0,FR:m.FR===0,RL:m.RL===0,RR:m.RR===0},overturned:o}}function Le(e,t,r,n=0,o=0,a=0,s,i){return Uc(e,t,r,n,o,a,s,i).loads}function Uc(e,t,r,n=0,o=0,a=0,s,i){let c=An(e),l=Ce(e),u=Ec(e,n,r,Co(e,t,o),l),{cf:m,cr:f}=Nx(e,l,u.height),p=m*t*is,d=f*t*is,h=e.massTotal*(r*is)*u.height/e.wheelbase-u.noseLoad,b=Ho(e,n,r,t,o),g=(i??Ko(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 Ox(y,e.trackFront,e.trackRear)}var _d=Math.PI/180;function qc(e,t){let r=8*_d,n=0,o=0;for(let a=1;a<=90;a++){let s=a*.5,i=Math.abs(e.Fy(s*_d,t,0));if(i>n&&(n=i,r=s*_d,o=a),a>o+12&&i<.995*n)break}return{aPeak:r,fyPeak:n}}function Vx(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 ls=.999;function Mt(e,t,r,n,o){if(t<=0)return 0;let{aPeak:a,fyPeak:s}=o??qc(e,t),i=Math.min(Math.abs(r),ls*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,k=NaN,F=f;for(let w=0;w<9;w++){let C=.5*(v+x),T=l(C,a);T>=i?(v=C,k=T):(x=C,F=T)}Number.isNaN(k)&&(k=l(0,a)),m=k<i?0:Vx(v,k,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,k=a,F=NaN,w=NaN;for(let C=0;C<5;C++){let T=.5*(x+k),S=l(v,T);S<i?(x=T,F=S):(k=T,w=S)}return Number.isNaN(F)&&(F=l(v,0)),Number.isNaN(w)&&(w=l(v,a)),c*e.forces({Fz:t,kappa:c*v,alpha:Vx(x,F,k,w,i)}).Fx},d=4,h=v=>m*v/d,b=[0],g=1;for(let v=1;v<=d;v++)b.push(p(h(v))),b[v]>b[g]&&(g=v);let[y,R]=g===d?[d-1,d-2]:b[g-1]>=b[g+1]?[g-1,g+1]:[g+1,g-1],M=XC(p,h(g-1),h(Math.min(d,g+1)),h(g),b[g],h(y),b[y],h(R),b[R],WC);return c*Math.max(0,M)}var WC=.01,jC=20,UC=(3-Math.sqrt(5))/2;function XC(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<jC;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),M=(n-i)*R-(n-a)*y;R=2*(R-y),R>0&&(M=-M),R=Math.abs(R);let v=u;if(u=m,Math.abs(M)<Math.abs(.5*R*v)&&M>R*(t-n)&&M<R*(r-n)){m=M/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=UC*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 Vd(e,t){return e.model?.kind==="simple"?null:Gx(e,t)}var Bx=new WeakMap,Nd=100,$x=1.35,Od=18,Jt=41,Xc=41,cs=65;function Gx(e,t){let r=Bx.get(e);if(r)return r;let n=Math.log($x),o=(p,d)=>{let h=k=>Math.abs(Mt(e,p,k,d)),b=h(0),g=t.muY(p)*p,y=new Float64Array(Jt),R=b>0&&g>0?Math.max(1,t.muX(p)*p/b):1;if(!(b>0)||!(g>0))y.fill(1);else{let k=[],F=[];for(let C=0;C<Xc;C++){let T=Math.sin(.5*Math.PI*C/(Xc-1));k.push(T),F.push(C===0?1:C===Xc-1?0:Math.min(F[C-1],h(T*g)/b))}let w=Xc-1;for(let C=0;C<Jt;C++){let T=C/(Jt-1);for(;w>0&&F[w-1]<T;)w--;let S=w>0?F[w-1]-F[w]:0;y[C]=w===0?k[0]:k[w]+(S>0?(T-F[w])/S:0)*(k[w-1]-k[w])}y[0]=1,y[Jt-1]=0}let M=new Float64Array(cs),v=k=>Math.atan2(y[k],k/(Jt-1)/R),x=Jt-2;for(let k=0;k<cs;k++){let F=.5*Math.PI*k/(cs-1),w=Math.cos(F),C=Math.sin(F);for(;x>0&&v(x)<F;)x--;let T=x/(Jt-1)/R,S=y[x],A=(x+1)/(Jt-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);M[k]=D>0?D:Math.hypot(T,S)}return{room:y,scale:R,edge:M}},a=Array.from({length:Od},(p,d)=>Nd*$x**d),s=a.map(p=>o(p,!1)),i=a.map(p=>o(p,!0)),c=(p,d)=>{let h=Math.min(1,Math.abs(d)*p.scale)*(Jt-1),b=Math.min(Jt-2,Math.floor(h));return p.room[b]+(h-b)*(p.room[b+1]-p.room[b])},l=p=>{let d=p>Nd?Math.log(p/Nd)/n:0;if(d>=Od-1)return[Od-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)*(cs-1),M=Math.min(cs-2,Math.floor(R)),v=k=>k.edge[M]+(R-M)*(k.edge[M+1]-k.edge[M]),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 Bx.set(e,f),f}var qC=[["front","FL","FR"],["rear","RL","RR"]];function zo(e,t,r,n){let o={...e},a=0,s=ls;for(let[i,c,l]of qC){let u=(M,v)=>n(i,Math.max(0,v[M])).fyPeak,m=Math.min(s,e[c]),f=Math.min(s,e[l]),p=m*u(c,r)+f*u(l,r);if(!(p>0))continue;let d=u(c,t),h=u(l,t),b=m*d+f*h,g=b>0?p/b:1/0,y=m*g,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 Kx=.001,QC=1e-5,Hx=100;function ZC(e,t,r,n){if(!(n>Kx))return r;let o=t,a=Math.abs(r-t)<Hx?t+Math.sign(r-t)*Hx:r;for(let s=0;s<60&&Math.abs(a-o)>QC;s++){let i=.5*(o+a);e(i)>Kx?a=i:o=i}return o}function Qc(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=ZC(e,t,o,e(o));return a!==o&&(n=a),a},edge:()=>n}}function Zc(e,t){let r=n=>{try{return ge(e,0,n).ok}catch{return!1}};for(let n of[1,-1]){if(r(n*t))continue;let o=0;for(let a=1;a<=6;a++){let s=n*t*a/6;if(!r(s))break;o=Math.abs(s)}return{lock:t,reached:o,side:n}}return null}var Bd=40;function Jc(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 zx=[0,0,0];function JC(e,t){let r=q(H(e.rockerPivotB,e.rockerPivotA)),n=q(H(e.rockerToPushrod,e.pushrodOuter)),o=q(H(e.damperChassis,e.rockerToDamper)),a=Math.abs(X(r,ae(H(e.rockerToPushrod,e.rockerPivotA),n))),s=Math.abs(X(r,ae(H(e.rockerToDamper,e.rockerPivotA),o)));return s<1e-9?0:t*a/s}function el(e,t,r){if(e.mcpherson)return eT(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??zx,c=[-t[0],-t[1],-t[2],-(s[0]+i[0]),-(s[1]+i[1]),-(s[2]+i[2])],l=qt(a,c),u=l.x;return{ucaFront:u[0],ucaRear:u[1],lcaFront:u[2],lcaRear:u[3],tieRod:u[4],pushRod:u[5],damper:l.singular||e.decoupled?NaN:e.direct?u[5]:JC(e,u[5]),condProxy:l.condProxy,singular:l.singular}}function eT(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??zx,l=[-t[0],-t[1],-t[2],-(i[0]+c[0]),-(i[1]+c[1]),-(i[2]+c[2])],u=qt(s,l),m=u.x,f=[m[3],m[4],m[5]],p=q(H(o,e.pushrodOuter)),d=X(f,p),h=Math.hypot(f[0]-d*p[0],f[1]-d*p[1],f[2]-d*p[2]);return{ucaFront:NaN,ucaRear:NaN,lcaFront:m[0],lcaRear:m[1],tieRod:m[2],pushRod:u.singular?NaN:d,damper:u.singular?NaN:d,condProxy:u.condProxy,singular:u.singular,strutSide:u.singular?NaN:h,topMount:f}}function $d(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 tT=[0,0,0];function us(e,t,r,n){let o=e.direct?e.damperChassis:e.rockerToPushrod;if(e.mcpherson)return{...el(e,r,n),armResidual:0};if(t==="upright")return{...el(e,r,n),armResidual:0};let a=t==="lowerArm",s=a?{bj:e.uprightUpper,front:e.ucaFront,rear:e.ucaRear}:{bj:e.uprightLower,front:e.lcaFront,rear:e.lcaRear},i=a?{bj:e.uprightLower,front:e.lcaFront,rear:e.lcaRear}:{bj:e.uprightUpper,front:e.ucaFront,rear:e.ucaRear},c=e.wheelCenter,l=q(H(s.front,s.bj)),u=q(H(s.rear,s.bj)),m=q(H(e.tieInner,e.tieOuter)),f=[{at:s.bj,dir:l},{at:s.bj,dir:u},{at:e.tieOuter,dir:m},{at:i.bj,dir:[1,0,0]},{at:i.bj,dir:[0,1,0]},{at:i.bj,dir:[0,0,1]}],p=[[],[],[],[],[],[]];for(let Q=0;Q<6;Q++){let ne=f[Q].dir,te=ae(H(f[Q].at,c),ne);p[0][Q]=ne[0],p[1][Q]=ne[1],p[2][Q]=ne[2],p[3][Q]=te[0],p[4][Q]=te[1],p[5][Q]=te[2]}let d=ae(H(e.contactPatch,c),r),h=n??tT,b=[-r[0],-r[1],-r[2],-(d[0]+h[0]),-(d[1]+h[1]),-(d[2]+h[2])],g=qt(p,b),y=g.singular,R=g.x,M=R[0],v=R[1],x=R[2],k=[R[3],R[4],R[5]],F=q(H(i.rear,i.front)),w=q(H(o,e.pushrodOuter)),C=U(k,-1),T=(Q,ne)=>X(F,ae(H(Q,i.front),ne)),S=T(e.pushrodOuter,w),A=Math.abs(S)>1e-9?-T(i.bj,C)/S:NaN,P=ee(C,U(w,A)),L=U(P,-1),D=q(H(i.front,i.bj)),I=q(H(i.rear,i.bj)),G=X(D,D),O=X(D,I),W=X(I,I),E=X(D,L),_=X(I,L),V=G*W-O*O,N=NaN,$=NaN,K=NaN;if(Math.abs(V)>1e-12){N=(E*W-_*O)/V,$=(G*_-O*E)/V;let Q=ee(U(D,N),U(I,$)),ne=H(L,Q);K=Math.hypot(ne[0],ne[1],ne[2])}let z=a?{f:M,r:v}:{f:N,r:$},j=a?{f:N,r:$}:{f:M,r:v};return{ucaFront:z.f,ucaRear:z.r,lcaFront:j.f,lcaRear:j.r,tieRod:x,pushRod:A,damper:y||!Number.isFinite(A)||e.decoupled?NaN:e.direct?A:rT(e,A),condProxy:g.condProxy,singular:y,armResidual:K}}function rT(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 j$=Math.PI/180;function ms(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 Wx=["QSX3","QSX8","QSX13","QSX14"],nT=["QSX1"],tl=["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",...Wx];function oT(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 aT(e){let t=new Set(oT(e)),r=tl.filter(n=>!Wx.includes(n));return[...r.filter(n=>!t.has(n)),...[...t].filter(n=>!r.includes(n)),...nT]}function sT(e,t){let r={...e};for(let n of t)r[n]!==void 0&&r[n]!==0&&(r[n]=-r[n]);return r}var yr=(e,t,r)=>Number.isFinite(e[t])?e[t]:r;function jx(e,t){return t!=="5.2"?yr(e,"PKY6",0)*yr(e,"LKYC",1):yr(e,"PKY1",-15)*Math.sin(yr(e,"PKY4",2)*Math.atan(1/yr(e,"PKY2",2)))*yr(e,"LKY",1)*yr(e,"PHY3",0)+yr(e,"PVY3",0)*yr(e,"LMUY",1)}var Yx=.1;function Ux(e){if(e.fitData)return"sae";let t=jx(e.coeffs,e.version);return t>Yx?"sae":t<-Yx?"iso":null}function ps(e){return e.axisSystem??Ux(e)??"sae"}function rl(e){let t=new Set,r=n=>{for(let o of n)t.has(o)?t.delete(o):t.add(o)};return ps(e)==="iso"&&r(tl),e.axisSystem&&e.side==="left"&&r(aT(e.version)),t.size?sT(e.coeffs,t):e.coeffs}var X$=Math.PI/180;var B=(e,t)=>Number.isFinite(e)?e:t;function qx(e){let t=rl(e);return{PCX1:B(t.PCX1,1.65),PDX1:B(t.PDX1,1),PDX2:B(t.PDX2,0),PDX3:B(t.PDX3,0),PEX1:B(t.PEX1,0),PEX2:B(t.PEX2,0),PEX3:B(t.PEX3,0),PEX4:B(t.PEX4,0),PHX1:B(t.PHX1,0),PHX2:B(t.PHX2,0),PKX1:B(t.PKX1,20),PKX2:B(t.PKX2,0),PKX3:B(t.PKX3,0),PPX1:B(t.PPX1,0),PPX2:B(t.PPX2,0),PPX3:B(t.PPX3,0),PPX4:B(t.PPX4,0),PVX1:B(t.PVX1,0),PVX2:B(t.PVX2,0),PCY1:B(t.PCY1,1.3),PDY1:B(t.PDY1,1),PDY2:B(t.PDY2,0),PDY3:B(t.PDY3,0),PEY1:B(t.PEY1,0),PEY2:B(t.PEY2,0),PEY3:B(t.PEY3,0),PEY4:B(t.PEY4,0),PEY5:B(t.PEY5,0),PHY1:B(t.PHY1,0),PHY2:B(t.PHY2,0),PHY3:B(t.PHY3,0),PKY1:B(t.PKY1,-15),PKY2:B(t.PKY2,2),PKY3:B(t.PKY3,0),PKY4:B(t.PKY4,2),PKY5:B(t.PKY5,0),PKY6:B(t.PKY6,0),PKY7:B(t.PKY7,0),PPY1:B(t.PPY1,0),PPY2:B(t.PPY2,0),PPY3:B(t.PPY3,0),PPY4:B(t.PPY4,0),PPY5:B(t.PPY5,0),PVY1:B(t.PVY1,0),PVY2:B(t.PVY2,0),PVY3:B(t.PVY3,0),PVY4:B(t.PVY4,0),RBX1:B(t.RBX1,0),RBX2:B(t.RBX2,0),RBX3:B(t.RBX3,0),RBY1:B(t.RBY1,0),RBY2:B(t.RBY2,0),RBY3:B(t.RBY3,0),RBY4:B(t.RBY4,0),RCX1:B(t.RCX1,1),RCY1:B(t.RCY1,1),REX1:B(t.REX1,0),REX2:B(t.REX2,0),REY1:B(t.REY1,0),REY2:B(t.REY2,0),RHX1:B(t.RHX1,0),RHY1:B(t.RHY1,0),RHY2:B(t.RHY2,0),RVY1:B(t.RVY1,0),RVY2:B(t.RVY2,0),RVY3:B(t.RVY3,0),RVY4:B(t.RVY4,0),RVY5:B(t.RVY5,1),RVY6:B(t.RVY6,0),PPZ1:B(t.PPZ1,0),PPZ2:B(t.PPZ2,0),QBZ1:B(t.QBZ1,8),QBZ2:B(t.QBZ2,0),QBZ3:B(t.QBZ3,0),QBZ4:B(t.QBZ4,0),QBZ5:B(t.QBZ5,0),QBZ6:B(t.QBZ6,0),QBZ9:B(t.QBZ9,0),QBZ10:B(t.QBZ10,0),QCZ1:B(t.QCZ1,1.1),QDZ1:B(t.QDZ1,.1),QDZ2:B(t.QDZ2,0),QDZ3:B(t.QDZ3,0),QDZ4:B(t.QDZ4,0),QDZ6:B(t.QDZ6,0),QDZ7:B(t.QDZ7,0),QDZ8:B(t.QDZ8,0),QDZ9:B(t.QDZ9,0),QDZ10:B(t.QDZ10,0),QDZ11:B(t.QDZ11,0),QEZ1:B(t.QEZ1,0),QEZ2:B(t.QEZ2,0),QEZ3:B(t.QEZ3,0),QEZ4:B(t.QEZ4,0),QEZ5:B(t.QEZ5,0),QHZ1:B(t.QHZ1,0),QHZ2:B(t.QHZ2,0),QHZ3:B(t.QHZ3,0),QHZ4:B(t.QHZ4,0),SSZ1:B(t.SSZ1,0),SSZ2:B(t.SSZ2,0),SSZ3:B(t.SSZ3,0),SSZ4:B(t.SSZ4,0),QSX1:B(t.QSX1,0),QSX2:B(t.QSX2,0),QSX3:B(t.QSX3,0),QSX4:B(t.QSX4,0),QSX5:B(t.QSX5,0),QSX6:B(t.QSX6,0),QSX7:B(t.QSX7,0),QSX8:B(t.QSX8,0),QSX9:B(t.QSX9,0),QSX10:B(t.QSX10,0),QSX11:B(t.QSX11,0),QSX12:B(t.QSX12,0),QSX13:B(t.QSX13,0),QSX14:B(t.QSX14,0),PPMX1:B(t.PPMX1,0),QSY1:B(t.QSY1,0),QSY2:B(t.QSY2,0),QSY3:B(t.QSY3,0),QSY4:B(t.QSY4,0),QSY5:B(t.QSY5,0),QSY6:B(t.QSY6,0),QSY7:B(t.QSY7,0),QSY8:B(t.QSY8,0),LONGVL:t.LONGVL!==void 0&&t.LONGVL>0?t.LONGVL:16.7,LCX:B(t.LCX,1),LCY:B(t.LCY,1),LEX:B(t.LEX,1),LEY:B(t.LEY,1),LFZO:B(t.LFZO,1),LHX:B(t.LHX,1),LHY:B(t.LHY,1),LKX:B(t.LKX,1),LKY:B(t.LKY,1),LKYC:B(t.LKYC,1),LKZC:B(t.LKZC,1),LMUX:B(t.LMUX,1),LMUY:B(t.LMUY,1),LMX:B(t.LMX,1),LMY:B(t.LMY,1),LVMX:B(t.LVMX,1),LRES:B(t.LRES,1),LS:B(t.LS,1),LTR:B(t.LTR,1),LVX:B(t.LVX,1),LVY:B(t.LVY,1),LVYKA:B(t.LVYKA,1),LXAL:B(t.LXAL,1),LYKA:B(t.LYKA,1)}}var Xx=new WeakMap;function ds(e){let t=Xx.get(e);return t===void 0&&(t=qx(e),Xx.set(e,t)),t}var Qx=e=>e>=0?1:-1;function nl(e,t,r=0,n){let o=ds(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,M=h?a*(o.PVY1+o.PVY2*c)*o.LVY*o.LMUY+g:a*((o.PVY1+o.PVY2*c)*o.LVY+(o.PVY3+o.PVY4*c)*s)*o.LMUY,v=f*p!==0?d/(f*p):0;return{Fz:a,g:s,dfz:c,dpi:l,Fz0p:i,R0:u,Cy:f,Dy:p,By:v,SHy:R,SVy:M,Kya:d,muy:m,EyA:o.PEY1+o.PEY2*c,EyG:1+o.PEY5*s*s,EyS:o.PEY3+o.PEY4*s,LEY:o.LEY}}function ol(e,t,r=0,n){let o=nl(e,t,r,n),a=ds(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,M=(a.PDX1+a.PDX2*c)*(1+a.PPX3*l+a.PPX4*l*l)*(1-a.PDX3*i*i)*a.LMUX,v=a.PCX1*a.LCX,x=M*s,k=s*(a.PKX1+a.PKX2*c)*Math.exp(a.PKX3*c)*(1+a.PPX1*l+a.PPX2*l*l)*a.LKX,F=v*x!==0?k/(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:k/w*(k/w),sS0:m*(a.SSZ1+(a.SSZ3+a.SSZ4*c)*i)*a.LS,sS2:m*a.SSZ2*a.LS/u}}function fs(e,t){let r=t+e.SHy,n=e.EyA*(e.EyG-e.EyS*Qx(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 al(e,t){let r=t+e.SHx,n=e.ExA*(1-e.PEX4*Qx(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 Zx(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 iT(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=Zx(e,o,r),i=e.Bt*s;return e.Dt*Math.cos(e.Ct*Math.atan(i-a*(i-Math.atan(i))))*n}function cT(e,t,r,n){return e.Dr*Math.cos(Math.atan(e.Br*Zx(e,t+e.SHy+e.arOff,r)))*n}function Jx(e,t,r,n,o,a){let s=Math.cos(t),i=iT(e,t,r,s),c=cT(e,t,r,s);return-i*(o-a)+c+(e.sS0+e.sS2*o)*n}function eR(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*al(e,t)}function Gd(e,t){let r=e.sS0===0&&e.sS2===0?0:eR(e,0,t);return Jx(e,t,0,r,fs(e,t),0)}function sl(e,t,r){let n=fs(e,r),o=eR(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:Jx(e,r,t,o,m,u)}}var hs=(e,t)=>Math.max(.1,e.muY0+e.loadSensY*(t-e.nominalLoad)),bs=(e,t)=>Math.max(.1,e.muX0+e.loadSensX*(t-e.nominalLoad)),tR=(e,t,r)=>hs(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cy*Math.atan(e.By*r)),rR=(e,t,r)=>bs(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cx*Math.atan(e.Bx*r));function Kd(e,t){let r=Math.max(1,t.Fz),n=hs(e,r)*r,o=bs(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 il=Math.PI/180;function Zr(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 nR(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?ms(r,t):1,s=n?ms(n,t):1,i=o?ms(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 Yo(e,t,r){let n=0,o=0;for(let s=r;s<=t;s+=r){let i=Math.abs(e(s));i>o&&(o=i,n=s)}let a=r/10;for(let s=Math.max(a,n-r);s<=n+r;s+=a)o=Math.max(o,Math.abs(e(s)));return o}function Ie(e){let t=nR(e),r=t,n=t,o=null,a=NaN,s=NaN,i=NaN,c=(v,x,k)=>(o!==null&&v===a&&x===s&&k===i||(o=ol(r,v,x,k),a=v,s=x,i=k),o),l=null,u=NaN,m=NaN,f=NaN,p=(v,x,k)=>(l!==null&&v===u&&x===m&&k===f||(l=nl(r,v,x,k),u=v,m=x,f=k),l),d=v=>e.kind==="magic"?sl(c(v.Fz,v.gamma??0,v.p),v.kappa,v.alpha):Kd(n,v),h=(v,x,k=0,F)=>e.kind==="magic"?fs(p(x,k,F),v):tR(n,x,v),b=(v,x,k=0,F)=>e.kind==="magic"?al(c(x,k,F),v):rR(n,x,v),g=(v,x,k=0,F)=>e.kind==="magic"?Gd(c(x,k,F),v):d({Fz:x,kappa:0,alpha:v,gamma:k,p:F}).Mz,y=v=>e.kind==="simple"?hs(n,v):Yo(x=>h(x*il,v),45,1)/Math.max(1,v),R=v=>e.kind==="simple"?bs(n,v):Yo(x=>b(x,v),.6,.02)/Math.max(1,v),M=v=>{let x=.1*il;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:M,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 k=e.verticalStiffness*1e3;if(!(k>0))return x;let F=e.rollingFraction??.306;return x-F*Math.max(0,v)/k},relaxationLength:v=>{let x=e.relaxation;if(!x)return 0;let k=x.carcassStiffness??0;if(!(k>0))return x.sigma;let F=M(Math.max(0,v));return F>0?F/(k*1e3):x.sigma}}}function Wo(e){let t=Math.max(1,e.model.kind==="magic"?e.model.fnomin:e.model.nominalLoad);return e.Fy(2*il,t,0)-e.Fy(-2*il,t,0)>=0?1:-1}var lT=Math.PI/180;function xe(e,t){return e.axle?e.axle(t):e}function ll(e,t){if(e===t)return e;let r=Wo(e)*Wo(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=>Yo(u=>s(u,l),.6,.02)/Math.max(1,l),muY:l=>Yo(u=>i(u*lT,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 ct(e){if(oR.has(e))return e;let t=aR.get(e);if(t)return t;let r;if(e.axle){let n=e.axle("front"),o=e.axle("rear"),a=ct(n),s=ct(o);r=a===n&&s===o?e:ll(a,s)}else Wo(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 oR.add(r),r!==e&&aR.set(e,r),r}var oR=new WeakSet,aR=new WeakMap;var ul=25*(Math.PI/180);function uT(e){let t=.6180339887,r=0,n=ul,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 gs(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=ul;if(s(ul)<=a){let u=uT(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(ul,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 Hd={shaft:!1,trail:0,hub:[0,0,0]};function iR(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 zd(e,t,r){let n=r.shaft?$d(e,t):[0,0,0];if(r.trail!==0){let a=iR(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 mT=(e,t)=>{let r=e!==void 0&&e>0?1/e:0,n=t!==void 0&&t>0?1/t:0;return r+n},ml={ucaFront:0,ucaRear:0,lcaFront:0,lcaRear:0,tieRod:0,pushRod:0,rack:0};function Fn(e){return!e.measured}function wn(e){if(!e)return!1;let t=r=>!!r&&Object.values(r).some(n=>n!==void 0&&n>0&&Number.isFinite(n));return t(e.links)||t(e.bushings)||e.rack!==void 0&&e.rack>0}function ys(e,t){let r=e.corner.hardpoints,n=Ua(e.rocker,t.points.rockerAngle);return{ucaFront:r.ucaFront,ucaRear:r.ucaRear,lcaFront:r.lcaFront,lcaRear:r.lcaRear,tieInner:To(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 Yd(e,t,r=0){let n=t.links??{},o=t.bushings??{},a=(l,u,m)=>{let f=mT(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 cR(e,t,r,n){let o=ve(e,t);if(!(o>1e-9))return{axial:r,radius2:0};let a=(r*r-n*n+o*o)/(2*o);return{axial:a,radius2:Math.max(0,r*r-a*a)}}function xs(e,t){let r=e.corner.hardpoints,n=e.inv,o={...n};if(n.strut&&t.topMount&&t.topMount.some(i=>i!==0)&&(o.strut={...n.strut,top:ee(n.strut.top,t.topMount)}),t.ucaFront!==0||t.ucaRear!==0){let i=cR(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=cR(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 pT=8,dT=1e-5,fT=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 Wd(e,t,r){let n=zd(e,r.force,r.extras??Hd),o=r.alignMoment?ee(n.moment,[0,0,r.alignMoment]):n.moment;return us(e,t,n.force,o)}function dl(e,t,r,n,o,a,s=0){let i=Ee(e,t,r,o,a),c=e.corner.compliance;if(!(wn(c)&&Fn(e.corner)))return{state:i,forces:Wd(ys(e,i),e.corner.config.pushrodAttach,n),deflection:ml,rigid:i,iterations:0,converged:!0,bypassed:!0};let u=i,m=e,f=e.corner.config.pushrodAttach,p=Wd(ys(e,i),f,n),d=ml,h=!1,b=0;for(;b<pT;b++){let g=ys(m,u);if(p=Wd(g,f,n),p.singular)break;d=Yd(p,c,s),m=xs(e,d);let y=Ee(m,t,r,fT(u),a),R=ve(y.points.wheelCenter,u.points.wheelCenter);if(u=y,R<dT){h=!0;break}}return{state:u,forces:p,deflection:d,rigid:i,iterations:b+1,converged:h&&u.converged,bypassed:!1}}var pl=1e3,lR=1e5;function uR(e,t,r,n,o){let a=dl(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 fl(e,t,r,n,o){let a={force:[0,0,n]},s=(b,g=0)=>uR(e,t,r,{force:b,alignMoment:g},o),i=uR(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,pl,n]),l=s([0,-pl,n]),u=s([pl,0,n]),m=s([-pl,0,n]),f=s([0,0,n],lR),p=s([0,0,n],-lR),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 hT=1e3;function jd(e,t=hT){if(!wn(e.compliance)||!Fn(e))return;let r=et(e),n=Ee(r,0,0),o=fl(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 jo(e,t=-Bd,r=Bd,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=qe(e,{travelMin:t,travelMax:r,steps:n}),s=jd(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 hl(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 Jr(e,t){return{motionRatio:hl(e.travel,e.motionRatio,t),camber:hl(e.travel,e.camber,t),toe:hl(e.travel,e.toe,t),damperLen:hl(e.travel,e.damperLen,t)}}var mR=Math.PI/180,bT=9.81;function Uo(e,t,r,n=0){let o=Ce(e),a=e.wheelbase*(1-e.frontMassFrac),s=e.wheelbase*e.frontMassFrac,i=Ho(e,n),c=e.aero?.model?(M,v,x)=>Ho(e,n,v,M,x):()=>i,l=Jr(t,0),u=Jr(r,0),m=e.loadFactor,f=m!==void 0&&m!==1?(m-1)*e.massTotal*bT:0,p=f*e.frontMassFrac/2,d=f*(1-e.frontMassFrac)/2,h=(M,v)=>v>0&&Number.isFinite(v)&&M+v>0?v/(M+v):1,b=Ue(e,"front"),g=Ue(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(M,v,x=0,k=0)=>{let F=c(M,v,x),w=o.rollGradient*M,C=w*mR,T=o.pitchGradient*v*mR,S=(G,O)=>{let W=O==="F"?e.trackFront:e.trackRear,E=O==="F"?o.rideRateFront:o.rideRateRear,_=(G==="R"?1:-1)*(W/2)*Math.tan(C),V=(O==="R"?s:-a)*Math.tan(T),N=`${O}${G}`,$=f?F[N]+(O==="F"?p:d):F[N],K=E>0?$/E:0;return{anti:_,sym:V+K}},A={FL:S("L","F"),FR:S("R","F"),RL:S("L","R"),RR:S("R","R")},P=G=>{let O=G[0];return A[G].sym*y[O]+A[G].anti*R[O]},L=Ko(e,k,o,{FL:P("FL"),FR:P("FR")}),D=w+L.rollDeg,I=(G,O)=>{let W=O==="F"?t:r,E=O==="F"?l:u,_=`${O==="F"?"F":"R"}${G}`,V=A[_].sym+A[_].anti+L.travel[_],N=P(_)+L.travel[_]*R[O],$=V-N,K=Jr(W,N),z=(G==="R"?1:-1)*K.camber;return{travel:N,tyre:$,ground:V,camber:z,camberRoad:z+D,toe:K.toe,bumpToe:K.toe-E.toe,damperTravel:E.damperLen-K.damperLen}};return{FL:I("L","F"),FR:I("R","F"),RL:I("L","R"),RR:I("R","R"),steeringJacking:L}}}var Ud=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function Cn(e){return{enabled:e?.enabled===!0,roadFeedbackGain:Math.min(2,Math.max(0,Ud(e?.roadFeedbackGain,1))),turnInFrictionNm:Math.max(0,Ud(e?.turnInFrictionNm,0)),columnStiffnessNmPerRad:Math.max(0,Ud(e?.columnStiffnessNmPerRad,0))}}function Xd(e,t,r){let n=Cn(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 pR=()=>({totalNm:0,aligningNm:0,lateralNm:0,longitudinalNm:0,jackingNm:0});function Tn(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 Rs(e,t,r,n="model",o){let a=e.steerFront;if(!Tn(e)||!a)return null;let s=t<0?-1:1,c=a.rackRatioMmPerRev/(2*Math.PI)/1e3,l=t>=0,u=o&&a.travelSurface?$o(a,Math.abs(t),l?o.FL:o.FR,l?o.FR:o.FL):Go(a,Math.abs(t));if(!u.innerJacobian||!u.outerJacobian)return null;let m=(b,g)=>{let y=r[b],R=b==="FL"?-1:1,M=-R*y.Fy,x={aligning:1e3*(-R*y.Mz)*g.yaw,lateral:M*g.lateral,longitudinal:y.Fx*g.longitudinal,jacking:y.Fz*g.vertical},k=pR();k.aligningNm=-s*x.aligning*c,k.lateralNm=-s*x.lateral*c,k.longitudinalNm=-s*x.longitudinal*c,k.jackingNm=-s*x.jacking*c,k.totalNm=k.aligningNm+k.lateralNm+k.longitudinalNm+k.jackingNm;let F=-s*(x.aligning+x.lateral+x.longitudinal+x.jacking);return{moment:k,rackN:F}},f=m("FL",l?u.innerJacobian:u.outerJacobian),p=m("FR",l?u.outerJacobian:u.innerJacobian),d=pR();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=Xd(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 gT=e=>"front"in e&&"rear"in e;function Xo(e,t){return gT(e)?e[t]:e}function Qd(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 qd(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 dR(e,t,r){let n=qd(e,t),o=qd(e,r);return{left:n,right:o,fyRes:n.fyRes+o.fyRes}}function xr(e,t,r){let n=dR(Xo(e,"front"),t.FL,t.FR),o=dR(Xo(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 bl=[{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"}],xT=bl.flatMap(e=>[e.min,e.max]);function bR(e){return Math.max(1,e.kind==="magic"?e.fnomin:e.nominalLoad)}function fR(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 Ht(e){let t=hR.get(e);if(t!==void 0)return t;let r=10*bR(e.model),{turnover:n,collapse:o}=vT(e,r),a=n??o??r;return hR.set(e,a),a}var hR=new WeakMap;function vT(e,t){let r=bR(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=fR(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=fR(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 gR=["FL","FR","RL","RR"],kT=e=>e==="FL"||e==="RL",MT=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 gR)a[l]={...t[l]};let s=l=>{let u=0;for(let f of gR)MT(f)===e.axle&&(a[f].Fx=e.sense*(f===e.strong?l-e.open/2:e.open/2),u-=(kT(f)?o:-o)*a[f].Fx);let m=xr(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 ST=[["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]],AT=[["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]],FT=[["QBZ1","Trail slope factor for trail Bpt at Fznom",8],["QBZ2","Variation of slope Bpt with load",0],["QBZ3","Variation of slope Bpt with load squared",0],["QBZ4","Variation of slope Bpt with camber",0],["QBZ5","Variation of slope Bpt with absolute camber",0],["QBZ6","Camber influence Bt",0],["QBZ9","Factor for scaling factors of slope factor Br of Mzr",0],["QBZ10","Factor for dimensionless cornering stiffness of Br of Mzr",0],["QCZ1","Shape factor Cpt for pneumatic trail",1.1],["QDZ1","Peak trail Dpt = Dpt*(Fz/Fznom*R0)",.1],["QDZ2","Variation of peak Dpt with load",0],["QDZ3","Variation of peak Dpt with camber",0],["QDZ4","Variation of peak Dpt with camber squared",0],["QDZ6","Peak residual torque Dmr = Dmr/(Fz*R0)",0],["QDZ7","Variation of peak factor Dmr with load",0],["QDZ8","Variation of peak factor Dmr with camber",0],["QDZ9","Variation of peak factor Dmr with camber and load",0],["QDZ10","Variation of peak factor Dmr with camber squared",0],["QDZ11","Variation of Dmr with camber squared and load",0],["QEZ1","Trail curvature Ept at Fznom",0],["QEZ2","Variation of curvature Ept with load",0],["QEZ3","Variation of curvature Ept with load squared",0],["QEZ4","Variation of curvature Ept with sign of Alpha-t",0],["QEZ5","Variation of Ept with camber and sign Alpha-t",0],["QHZ1","Trail horizontal shift Sht at Fznom",0],["QHZ2","Variation of shift Sht with load",0],["QHZ3","Variation of shift Sht with camber",0],["QHZ4","Variation of shift Sht with camber and load",0],["PPZ1","Effect of inflation pressure on length of pneumatic trail",0],["PPZ2","Influence of inflation pressure on residual aligning torque",0],["SSZ1","Nominal value of s/R0: effect of Fx on Mz",0],["SSZ2","Variation of distance s/R0 with Fy/Fznom",0],["SSZ3","Variation of distance s/R0 with camber",0],["SSZ4","Variation of distance s/R0 with load and camber",0]],wT=[["RBX1","Slope factor for combined slip Fx reduction",0],["RBX2","Variation of slope Fx reduction with kappa",0],["RBX3","Influence of camber on stiffness for Fx combined",0],["RCX1","Shape factor for combined slip Fx reduction",1],["REX1","Curvature factor of combined Fx",0],["REX2","Curvature factor of combined Fx with load",0],["RHX1","Shift factor for combined slip Fx reduction",0],["RBY1","Slope factor for combined Fy reduction",0],["RBY2","Variation of slope Fy reduction with alpha",0],["RBY3","Shift term for alpha in slope Fy reduction",0],["RBY4","Influence of camber on stiffness of Fy combined",0],["RCY1","Shape factor for combined Fy reduction",1],["REY1","Curvature factor of combined Fy",0],["REY2","Curvature factor of combined Fy with load",0],["RHY1","Shift factor for combined Fy reduction",0],["RHY2","Shift factor for combined Fy reduction with load",0],["RVY1","Kappa induced side force Svyk/Muy*Fz at Fznom",0],["RVY2","Variation of Svyk/Muy*Fz with load",0],["RVY3","Variation of Svyk/Muy*Fz with camber",0],["RVY4","Variation of Svyk/Muy*Fz with alpha",0],["RVY5","Variation of Svyk/Muy*Fz with kappa",1],["RVY6","Variation of Svyk/Muy*Fz with atan(kappa)",0]],CT=[["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]],xR=[["lateral",ST],["longitudinal",AT],["aligning",FT],["combined",wT],["scaling",CT]].flatMap(([e,t])=>t.map(([r,n,o])=>({key:r,section:e,text:n,fallback:o}))),ZG=new Map(xR.map(e=>[e.key,e]));var TT=/^\$\s*EDITED\s+([A-Z][A-Z0-9_]*)\s+was\s+(absent|[-+0-9.eE]+)\s*$/;function RR(e){let t={};for(let r of e.split(/\r?\n/)){let n=r.trim().match(TT);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 LT=/^\s*\$\s*UNLOADED_RADIUS_STAND_IN\s*=\s*([0-9.eE+-]+)/,DT=/^\$-+ written by (?:PaceDynamics|PaceLab)\b/m,ET=/^\$\s*AXIS_SYSTEM\s*=\s*(ISO-W|SAE)\b/m;function IT(e){let t=e.match(ET);return t?{axisSystem:t[1]==="SAE"?"sae":"iso",trustSide:!0}:DT.test(e)?{axisSystem:"sae",trustSide:!1}:{axisSystem:"iso",trustSide:!0}}function _T(e){return e>=62?"6.2":e>=61?"6.1":"5.2"}var vR=new Map([["pa",1],["pascal",1],["kpa",1e3],["kilopascal",1e3],["mpa",1e6],["megapascal",1e6],["bar",1e5],["psi",6894.757293168]]);function NT(e,t,r){let n=r.PRESSURE?.trim().toLowerCase(),o=n===void 0?1:vR.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 OT=new Map([["radians",1],["radian",1],["rad",1],["degrees",Math.PI/180],["degree",Math.PI/180],["deg",Math.PI/180]]);function VT(e,t){let r=(s,i)=>s===void 0?1:i.get(s.trim().toLowerCase()),n=r(t.ANGLE,OT),o={fz:1,kappa:1,alpha:n,gamma:n,p:r(t.PRESSURE,vR)},a={};for(let s of bl){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 vs(e,t="imported",r={}){let n=IT(e),o=r.axisSystem??n.axisSystem,a={},s={},i={},c="",l;for(let g of e.split(/\r?\n/)){let y=g.match(LT);y&&(l=parseFloat(y[1]));let R=g.replace(/[$!].*$/,"").trim();if(!R)continue;if(R.startsWith("[")){c=(R.match(/^\[([^\]]*)/)?.[1]??"").trim().toUpperCase();continue}let M=R.indexOf("=");if(M<0)continue;let v=R.slice(0,M).trim().toUpperCase(),x=R.slice(M+1).trim(),k=x.match(/^'([^']*)'|^"([^"]*)"/);if(k){s[v]=k[1]??k[2]??"",c==="UNITS"&&(i[v]=s[v]);continue}let F=parseFloat(x);Number.isFinite(F)&&(a[v]=F)}let u=_T(a.FITTYP??62),m=RR(e),f=m?Object.fromEntries(Object.entries(m).filter(([g])=>a[g]!==void 0)):void 0,p=a.VERTICAL_STIFFNESS??a.KZ??0,d=NT(a,s,i),h=VT(a,i),b=[];return a.UNLOADED_RADIUS===void 0&&a.R0===void 0&&b.push("UNLOADED_RADIUS"),p<=0&&b.push("VERTICAL_STIFFNESS"),a.FNOMIN===void 0&&b.push("FNOMIN"),d===void 0&&b.push("NOMPRES"),{kind:"magic",name:t,version:u,coeffs:a,axisSystem:o,side:n.trustSide?s.TYRESIDE==="RIGHT"?"right":s.TYRESIDE==="LEFT"?"left":void 0:void 0,fnomin:a.FNOMIN??5e3,unloadedR0:a.UNLOADED_RADIUS??a.R0??(l!==void 0&&l>0?l:.3),...a.WIDTH!==void 0&&a.WIDTH>0?{sectionWidth:a.WIDTH}:{},verticalStiffness:p>0?p/1e3:0,...a.FREFF!==void 0&&!a.DREFF?{rollingFraction:a.FREFF}:{},...a.LATERAL_STIFFNESS!==void 0&&a.LATERAL_STIFFNESS>0?{relaxation:{sigma:0,carcassStiffness:a.LATERAL_STIFFNESS/1e3,source:"fitted"}}:{},nomPressure:d??0,missing:b,...f&&Object.keys(f).length?{edited:f}:{},...h?{range:h}:{}}}function er(e){if(!e)return null;let t=e.unloadedR0;return t===void 0||!(t>0)||e.kind==="magic"&&e.missing?.includes("UNLOADED_RADIUS")?null:t*1e3}var s4=Math.PI/180;var m4=Math.PI/180,p4=180/Math.PI;function ks(){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 AR=`$ AXIS_SYSTEM = SAE (authored in the evaluation frame: y right)
|
|
2
|
+
import{parentPort as Cw,workerData as _5}from"node:worker_threads";import{readFileSync as x0}from"node:fs";import{join as R0}from"node:path";var yc=e=>e.format!=="points"&&!e.field;var mt=e=>e?.kind==="ice";var X0={packVoltageMax:600,segmentVoltageMax:120,powerLimitKw:80};var De=e=>typeof e=="number"&&Number.isFinite(e);function Pw(e){let{soc:t,ocv:r,r0:n}=e;if(!Array.isArray(t)||t.length<2)return"The curve needs at least two state-of-charge points.";if(!t.every(De))return"The state-of-charge axis contains a value that is not a number.";if(t[0]<0||t[t.length-1]>1)return`The state-of-charge axis must lie within 0 to 1 (it runs ${t[0]} to ${t[t.length-1]}).`;for(let o=1;o<t.length;o++)if(!(t[o]>t[o-1]))return`The state-of-charge axis must increase (${t[o-1]} then ${t[o]}).`;if(!Array.isArray(r)||r.length!==t.length)return`The curve has ${Array.isArray(r)?r.length:0} voltages against ${t.length} state-of-charge points.`;if(!r.every(De))return"The open-circuit voltage contains a value that is not a number.";if(r.some(o=>o<=0))return"The open-circuit voltage must be positive everywhere.";for(let o=1;o<r.length;o++)if(r[o]<r[o-1])return`The open-circuit voltage must rise with state of charge (${r[o-1]} V at ${t[o-1]} then ${r[o]} V at ${t[o]}).`;if(!Array.isArray(n)||n.length!==t.length)return`The curve has ${Array.isArray(n)?n.length:0} resistances against ${t.length} state-of-charge points.`;if(!n.every(De))return"The resistance contains a value that is not a number.";if(n.some(o=>o<0))return"The resistance cannot be negative.";if(e.rTempC!==void 0||e.rGrid!==void 0){let o=e.rTempC,a=e.rGrid;if(!Array.isArray(o)||o.length<1)return"The resistance temperature axis needs at least one temperature.";if(!o.every(De))return"The resistance temperature axis contains a value that is not a number.";for(let s=1;s<o.length;s++)if(!(o[s]>o[s-1]))return`The temperature axis must increase (${o[s-1]} then ${o[s]} \xB0C).`;if(!Array.isArray(a)||a.length!==o.length)return`The resistance grid has ${Array.isArray(a)?a.length:0} rows against ${o.length} temperatures.`;for(let s=0;s<a.length;s++){let i=a[s];if(!Array.isArray(i)||i.length!==t.length)return`Resistance row ${s+1} has ${Array.isArray(i)?i.length:0} values against ${t.length} state-of-charge points.`;if(!i.every(De))return"The resistance grid contains a value that is not a number.";if(i.some(c=>c<0))return"The resistance grid contains a negative resistance."}}return null}function Lw(e){return!e||typeof e!="object"?"The cell has no curve.":e.kind==="table"?Pw(e):e.kind==="analytic"?!De(e.vCut)||!De(e.vNom)||!De(e.vFull)?"The cut-off, nominal and full voltages must be numbers.":e.vCut<=0?"The cut-off voltage must be positive.":e.vCut<e.vNom&&e.vNom<e.vFull?!De(e.r0)||e.r0<0?"The cell resistance must be a number and cannot be negative.":e.socAtNom!==void 0&&(!De(e.socAtNom)||e.socAtNom<=0||e.socAtNom>=1)?"The state of charge the nominal voltage is met at must lie strictly between 0 and 1.":null:`The voltages must order cut-off < nominal < full (given ${e.vCut}, ${e.vNom}, ${e.vFull} V).`:`Unknown cell curve kind "${e.kind}".`}function xc(e){if(!e||typeof e!="object")return"Not a battery model.";let t=e.cell;if(!t||typeof t!="object")return"The model has no cell.";if(!De(t.capacityAh)||t.capacityAh<=0)return"The cell capacity must be a positive number of amp-hours.";if(!De(t.vMin)||t.vMin<0)return"The cut-off voltage must be a number and cannot be negative.";if(!De(t.vMax)||t.vMax<=0)return"The maximum cell voltage must be a positive number.";if(!(t.vMin<t.vMax))return`The cut-off voltage (${t.vMin} V) must be below the maximum (${t.vMax} V).`;if(!De(t.iMaxA)||t.iMaxA<0)return"The discharge current limit must be a number of amps, 0 for no limit.";if(t.iMaxChargeA!==void 0&&(!De(t.iMaxChargeA)||t.iMaxChargeA<0))return"The charge current limit must be a number of amps, 0 for no limit.";if(t.massKg!==void 0&&(!De(t.massKg)||t.massKg<0))return"The cell mass must be a number and cannot be negative.";let r=Lw(t.curve);if(r)return r;let n=t.curve.kind==="table"?t.curve.ocv[t.curve.ocv.length-1]:t.curve.vFull;if(t.vMin>=n)return`The cut-off voltage (${t.vMin} V) is at or above the cell's voltage at full charge (${n} V), so no power could ever be drawn.`;let o=e.thermal;if(o!==void 0){if(!o||typeof o!="object")return"The thermal model must be an object, or absent.";if(!De(o.heatCapacityJPerK)||o.heatCapacityJPerK<=0)return"The cell heat capacity must be a positive number of joules per kelvin.";if(!De(o.coolingWPerK)||o.coolingWPerK<0)return"The cooling must be a number of watts per kelvin and cannot be negative.";if(o.startC!==void 0&&!De(o.startC))return"The starting temperature must be a number.";if(o.entropicVPerK!==void 0&&!De(o.entropicVPerK))return"The entropic coefficient must be a number.";if(o.derateFromC!==void 0){if(!De(o.derateFromC))return"The temperature the derate starts at must be a number.";if(o.derateToC!==void 0){if(!De(o.derateToC))return"The temperature the derate ends at must be a number.";if(!(o.derateToC>o.derateFromC))return`The derate must end above where it starts (given ${o.derateFromC} then ${o.derateToC} \xB0C).`}}else if(o.derateToC!==void 0)return"The derate has an end temperature but no start; give both or neither."}let a=e.pack;if(!a||typeof a!="object")return"The model has no pack.";if(!Number.isInteger(a.series)||a.series<1)return"The pack needs a whole number of cells in series, at least one.";if(!Number.isInteger(a.parallel)||a.parallel<1)return"The pack needs a whole number of strings in parallel, at least one.";if(!De(a.busResistance)||a.busResistance<0)return"The busbar resistance must be a number and cannot be negative.";if(a.seriesPerSegment!==void 0&&a.seriesPerSegment!==0){if(!Number.isInteger(a.seriesPerSegment)||a.seriesPerSegment<1)return"The cells per segment must be a whole number, at least one.";if(a.seriesPerSegment>a.series)return`A segment cannot hold more cells (${a.seriesPerSegment}) than the pack has in series (${a.series}).`}return null}function vn(e,t){let r=e.length;if(r<=1)return{i:0,t:0,clamped:!1};if(t<=e[0])return{i:0,t:0,clamped:t<e[0]};if(t>=e[r-1])return{i:r-2,t:1,clamped:t>e[r-1]};let n=0,o=r-1;for(;o-n>1;){let a=n+o>>1;e[a]<=t?n=a:o=a}return{i:n,t:(t-e[n])/(e[o]-e[n]),clamped:!1}}function Be(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function Rc(e,t,r,n,o){let a=e.length,s=t.length;if(a===0||s===0)return 0;let i=vn(e,n),c=vn(t,o),l=Math.min(i.i+1,a-1),u=Math.min(c.i+1,s-1),m=r[c.i][i.i],f=r[c.i][l],p=r[u][i.i],d=r[u][l],h=m+i.t*(f-m),b=p+i.t*(d-p);return h+c.t*(b-h)}var ko=[0,.05,.1,.2,.3,.4,.5,.6,.7,.8,.9,1],hp={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]},q0=[0,.05,.1,.2,.5,.8,1],Q0=[2.2,1.55,1.3,1.12,1,.97,.98];function Z0(e){return Be(q0,Q0,e)}var J0=[-20,-10,0,10,25,40,60],ey=[4,2.8,2,1.4,1,.82,.75];function bp(e){return Be(J0,ey,e)}var ty=.5;function gp(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=hp[t]??hp.other,l=e.socAtNom??ty,u=ko.includes(l)?[...ko]:[...ko,l].sort((h,b)=>h-b),m=Be(ko,c,l),f=m>0&&m<1?Math.log(i)/Math.log(m):1,p=[],d=[];for(let h of u){let b=Be(ko,c,h);p.push(o+s*Math.pow(b,f)),d.push(e.constantResistance?a:a*Z0(h))}return{kind:"table",soc:u,ocv:p,r0:d}}function yp(e){let t=e.soc,r=e.ocv,n=[0,...t.filter(a=>a>0&&a<1),1],o=0;for(let a=1;a<n.length;a++){let s=n[a-1],i=n[a];o+=(Be(t,r,s)+Be(t,r,i))/2*(i-s)}return o}var Mo=25,ry=new WeakMap;function fr(e){let t=ry.get(e);if(t)return t;let r=xc(e);if(r)throw new Error(r);let{cell:n,pack:o}=e,a=n.curve.kind==="table"?n.curve:gp(n.curve,n.chemistry),s=o.series,i=o.parallel,c=s/i,l=a.rTempC,u=a.rGrid,m=i*n.capacityAh,f=s*n.vMin,p=n.iMaxA>0?i*n.iMaxA:1/0,d=n.iMaxChargeA!==void 0&&n.iMaxChargeA>0?n.iMaxChargeA:n.iMaxA/4,h=d>0?i*d:1/0,b=F=>s*Be(a.soc,a.ocv,F),g=(F,w=Mo)=>{let C=l&&u?Rc(a.soc,l,u,F,w):Be(a.soc,a.r0,F)*bp(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))},M=(F,w,C)=>{if(!(F>0))return 0;let T=b(w),S=g(w,C);return S>0?2*F/(T+Math.sqrt(T*T+4*S*F)):F/T},v=F=>{let w=e.thermal;if(!w||w.derateFromC===void 0)return 1;let C=w.derateToC??w.derateFromC;return F<=w.derateFromC?1:!(C>w.derateFromC)||F>=C?0:1-(F-w.derateFromC)/(C-w.derateFromC)},x=(F,w,C=0)=>{let T=b(F),S=g(F,w),A=S>0?T/(2*S):1/0,P=$=>{if(!(S>0))return $*T;let K=Math.min($,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,I=S>0?P(L):1/0,G=Number.isFinite(p)?P(p):1/0,O=S>0?T*T/(4*S):1/0,W=[["rules",D],["voltage-floor",I],["current",G],["matched-load",O]],E=W[0][0],_=W[0][1];for(let[$,K]of W)K<_&&(_=K,E=$);let V=v(w??Mo);V<1&&(_=Number.isFinite(_)?_*V:_,E="temperature");let N=Number.isFinite(_)?R(_,F,w):1/0;return{watts:_,binding:E,rules:D,voltageFloor:I,current:G,matchedLoad:O,derate:V,amps:N,volts:Number.isFinite(N)?T-N*S:T}},k={model:e,table:a,capacityAh:m,chargeC:m*3600,energyKwh:m*(s*yp(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:M,maxPower:x};return ry.set(e,k),k}function xp(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 ny={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},oy={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},ay={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 Rp(){return{name:"Formula Student accumulator",cell:xp(ny),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 vp(){return{name:"LFP pack",cell:xp(oy),pack:{series:160,parallel:1,busResistance:.02,seriesPerSegment:32},provenance:{source:"assumed",note:"Assumed LFP prismatic pack; the flat plateau is the chemistry, the numbers are class-level guesses."}}}function kp(){return{name:"Road car pack",cell:xp(ay),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 Mp(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 vc(e){if(e.kind==="ice"){let n=e.gearbox.efficiency;return{model:e,maxTorque:o=>o>e.limitRpm?0:Be(e.rpm,e.torque,o),efficiency:()=>n}}let t=n=>Be(e.rpm,e.torque,n),r=e.kind==="simple"?()=>e.efficiency:(n,o)=>Rc(e.effRpm,e.effTorque,e.effGrid,n,o);return{model:e,maxTorque:t,efficiency:r}}function Sp(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 M=0;M<g;M++)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 Ue(e,t){return t==="rear"&&e.tireRateRear!==void 0?e.tireRateRear:e.tireRate}function Ap(e,t){let r=e.tyreFreeRadiusRear;return(t==="rear"&&r!==void 0?r:e.tyreFreeRadius)??0}var kc=9.81,sy=(e,t)=>e*(t*t)/2*(Math.PI/180)/1e3,Ka=(e,t)=>e+t>0?e*t/(e+t):0,iy=.5;function Mc(e,t,r){if(!(r>0))return 1;let n=e*kc*t*(Math.PI/180)/r;return 1/(1-Math.min(iy,n))}function Fp(e,t,r){return r>0?e*kc*t/(r*r):0}function cy(e,t,r,n,o){if(!(n>0)||!(o>0))return 1;let a=Fp(e,t,r)*(1/n+1/o);return 1/(1-Math.min(iy,a))}function Ce(e){let t=4*e.unsprungPerCorner,r=Math.max(0,e.massTotal-t),n=r*e.frontMassFrac,o=r*(1-e.frontMassFrac),a=Ue(e,"front"),s=Ue(e,"rear"),i=e.wheelRateFront+(e.heaveSpringFront??0),c=e.wheelRateRear+(e.heaveSpringRear??0),l=Ka(i,a),u=Ka(c,s),m=(G,O)=>{let W=O/2;return W>0?1/(2*Math.PI)*Math.sqrt(G*1e3/W):0},f=m(l,n),p=m(u,o),d=Ka(e.wheelRateFront+e.arbFront,a),h=Ka(e.wheelRateRear+e.arbRear,s),b=sy(d,e.trackFront),g=sy(h,e.trackRear),y=b+g,R=y>0?b/y:.5,M=e.rcHeightFront+(e.rcHeightRear-e.rcHeightFront)*(1-e.frontMassFrac),v=(e.cgHeight-M)/1e3,x=r*kc*v,k=Mc(r,v,y),F=y>0?x/y*k:0,w=e.massTotal*kc*e.cgHeight/e.wheelbase,C=2*l,T=2*u,S=cy(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*Ka(C,T)*(Math.PI/180)/1e3,D=e.damperFront??2.5,I=e.damperRear??2.5;return{sprungMass:r,sprungFront:n,sprungRear:o,rideRateFront:l,rideRateRear:u,rideFreqFront:f,rideFreqRear:p,rollRateFront:b,rollRateRear:g,rollRateTotal:y,rollWheelRateFront:d,rollWheelRateRear:h,frontRollStiffFrac:R,rollGradient:F,pitchGradient:P,pitchRate:L,cgRollGain:k,cgPitchGain:S,rideDampingFront:D+(e.heaveDamperFront??0),rideDampingRear:I+(e.heaveDamperRear??0),rollDampingFront:D+(e.rollDamperFront??0),rollDampingRear:I+(e.rollDamperRear??0)}}var Hr=["clFront","clRear","cd"],So=e=>e.frame?.kind==="pitch";function Sc(e){return So(e)?{x:e.axes.h,y:e.axes.pitch}:{x:e.axes.hFront,y:e.axes.hRear}}var ly=e=>e.frame?.kind==="pitch";var Ac=45,Qe=e=>typeof e=="number"&&Number.isFinite(e);function Fc(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 uy(e,t){if(t===void 0)return null;for(let r of Hr){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 my(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 Ha(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=Fc("front ride-height",e.axes?.hFront);if(i)return i;let c=Fc("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=Fc("ride-height",e.axes?.h);if(i)return i;let c=Fc("pitch",e.axes?.pitch,"\xB0","pitch");if(c)return c;let l=e.axes.pitch.find(u=>Math.abs(u)>=Ac);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 Hr){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 uy("yaw",e.attitude?.yaw)??uy("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 Hr){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])>=Ac||Math.abs(i[1])>=Ac))return`A pitch range reaching ${Math.abs(i[0])>=Ac?i[0]:i[1]}\xB0 is not a car's attitude. Pitch is in degrees.`}return my("yaw",e.attitude?.yaw)??my("roll",e.attitude?.roll)}return`Unknown aero model kind "${e.kind}".`}var py=180/Math.PI;function wc(e,t,r,n){let o=(n-r)/t;return{h:r+e.refX*o,pitch:Math.atan(o)*py}}function Ao(e,t,r,n){let o=Math.tan(n/py);return{hFront:r-e.refX*o,hRear:r+(t-e.refX)*o}}var v3=180/Math.PI,Dw=["hFront","hRear"],Ew=["h","pitch"],Tp=e=>e?.kind==="pitch"?Ew:Dw,kt=(e,t)=>e[t],Cc=(e,t)=>e[t],wp=(e,t)=>({[e[0]]:t(e[0]),[e[1]]:t(e[1])});function Iw(e){if(!(!e.yaw&&!e.roll))return{...e.yaw?{yaw:{...e.yaw}}:{},...e.roll?{roll:{...e.roll}}:{}}}function Pp(e){let t=Tp(e.frame),r=e.balanceFront,n=e.cl*r,o=e.cl*(1-r),a=wp(t,c=>kt(e.dCl,c)*r+e.cl*kt(e.dBalance,c)),s=wp(t,c=>kt(e.dCl,c)*(1-r)-e.cl*kt(e.dBalance,c)),i=Iw(e);return{kind:"sensitivity",name:e.name,area:e.area,...e.frame?{frame:{...e.frame}}:{},ref:{...e.ref},at:{clFront:n,clRear:o,cd:e.cd},slope:{clFront:a,clRear:s,cd:wp(t,c=>kt(e.dCd,c))},range:{[t[0]]:[...Cc(e.range,t[0])],[t[1]]:[...Cc(e.range,t[1])]},provenance:{...e.provenance},...i?{attitude:i}:{}}}function Tc(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 Cp(e,t,r=11){let n=Array.from({length:r},(a,s)=>t.maxDeg*s/(r-1)),o=n.map(a=>Tc(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 dy(e){if(!(!e.attitude?.yaw&&!e.attitude?.roll))return{...e.attitude.yaw?{yaw:Cp(e.at,e.attitude.yaw)}:{},...e.attitude.roll?{roll:Cp(e.at,e.attitude.roll)}:{}}}function fy(e,t,r,n=0,o=0){let[a,s]=Tp(e.frame),i=t-kt(e.ref,a),c=r-kt(e.ref,s),l={clFront:e.at.clFront+kt(e.slope.clFront,a)*i+kt(e.slope.clFront,s)*c,clRear:e.at.clRear+kt(e.slope.clRear,a)*i+kt(e.slope.clRear,s)*c,cd:e.at.cd+kt(e.slope.cd,a)*i+kt(e.slope.cd,s)*c},u=e.attitude?.yaw?Tc(e.at,e.attitude.yaw,n):{clFront:1,clRear:1,cd:1},m=e.attitude?.roll?Tc(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 Lp(e){let[t,r]=Tp(e.frame),n=[...Cc(e.range,t)],o=[...Cc(e.range,r)],a=i=>o.map(c=>n.map(l=>i(fy(e,l,c)))),s=dy(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 Dp=180/Math.PI,hy=new WeakMap,by=new WeakMap,Ep=new WeakMap;function zr(e,t){let r=by.get(e);if(r)return r;let n=t?.wheelbase,o=n!==void 0?Ep.get(e)?.get(n):void 0;if(o)return o;let a=_w(e),s=a.map;if(!So(s)){let l=Nw(e,a);return by.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=Ow(e,a,s.frame,n),c=Ep.get(e);return c||(c=new Map,Ep.set(e,c)),c.set(n,i),i}function _w(e){let t=hy.get(e);if(t)return t;let r=Ha(e);if(r)throw new Error(r);let n=e.kind==="map"?e:Lp(e),{x:o,y:a}=Sc(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 M=Math.abs(R),v=y.clFront.deg[y.clFront.deg.length-1];return{clFront:Be(y.clFront.deg,y.clFront.factor,M),clRear:Be(y.clRear.deg,y.clRear.factor,M),cd:Be(y.cd.deg,y.cd.factor,M),clamped:M>v}},p=(y,R)=>{if(!u)return m;let M=c?f(c,y):m,v=l?f(l,R):m;return{clFront:M.clFront*v.clFront,clRear:M.clRear*v.clRear,cd:M.cd*v.cd,clamped:M.clamped||v.clamped}},d=(y,R,M=0,v=0)=>{let x=vn(o,y),k=vn(a,R),F=Math.min(x.i+1,s-1),w=Math.min(k.i+1,i-1),C=S=>{let A=S[k.i][x.i],P=S[k.i][F],L=S[w][x.i],D=S[w][F],I=A+x.t*(P-A),G=L+x.t*(D-L);return I+k.t*(G-I)},T=p(M,v);return{clFront:u?C(n.clFront)*T.clFront:C(n.clFront),clRear:u?C(n.clRear)*T.clRear:C(n.clRear),cd:u?C(n.cd)*T.cd:C(n.cd),clampedRide:x.clamped||k.clamped,clampedAttitude:T.clamped}},h={x:[o[0],o[s-1]],y:[a[0],a[i-1]]},b=(y,R,M=!1,v=0,x=0)=>{let k=p(v,x),F=vn(o,M?Math.min(Math.max(y,h.x[0]),h.x[1]):y),w=vn(a,M?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 Hr){let D=n[L],I=D[w.i][F.i],G=D[w.i][C],O=D[T][F.i],W=D[T][C],E=F.clamped||S===0?0:((G-I)*(1-w.t)+(W-O)*w.t)/S,_=w.clamped||A===0?0:((O-I)*(1-F.t)+(W-G)*F.t)/A;P[L]=u?{x:E*k[L],y:_*k[L]}:{x:E,y:_}}return P},g={map:n,x:h.x,y:h.y,hasAttitude:u,factors:p,at:d,slopes:b};return hy.set(e,g),g}function Nw(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 Hr)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 Ow(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)*Dp,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)*Dp,m,f,p),b=Dp/(n*(1+d*d)),g={};for(let y of Hr)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)=>Ao(r,n,l,u),fromAxles:(l,u)=>{let m=wc(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 Ip(e){let t=e.clFront+e.clRear;return{cl:t,balanceFront:t!==0?e.clFront/t:.5}}var he=(e,t)=>e*t/100,Xe=e=>e/100,gy={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:Xe(-.3),hRear:Xe(.15)},dCd:{hFront:he(1.3,-.1),hRear:he(1.3,.05)},yaw:{dCl:he(3,-1),dBalance:Xe(-.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."},yy={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:Xe(-.15),hRear:Xe(.15)},dCd:{hFront:he(.9,-.15),hRear:he(.9,-.05)},yaw:{dCl:he(3,-1.5),dBalance:Xe(.2),dCd:he(.9,.8),maxDeg:8},roll:{dCl:he(3,-1),dBalance:Xe(-.3),dCd:0,maxDeg:2},note:"Assumed class-level sensitivities for a ground-effect floor, ride height, yaw and roll; not measured."},xy={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:Xe(-.25),hRear:Xe(.15)},dCd:{hFront:he(.42,-.1),hRear:0},yaw:{dCl:he(1.4,-.8),dBalance:Xe(-.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."},Ry={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."},vy={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:Xe(-.25),hRear:Xe(.15)},dCd:{hFront:he(.4,-.1),hRear:0},yaw:{dCl:he(.45,-1.2),dBalance:Xe(-.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."},ky={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:Xe(-.25),hRear:Xe(.15)},dCd:{hFront:he(.45,-.1),hRear:0},yaw:{dCl:he(.6,-1),dBalance:Xe(-.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."},My={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:Xe(-.25),hRear:Xe(.15)},dCd:{hFront:he(.9,-.1),hRear:he(.9,.05)},yaw:{dCl:he(2.5,-1),dBalance:Xe(-.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."},Sy={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 hr(e){return Pp({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 _p=()=>hr(gy),Np=()=>hr(yy),Op=()=>hr(xy),Vp=()=>hr(Ry),Bp=()=>hr(vy),$p=()=>hr(ky),Gp=()=>hr(My),Kp=()=>hr(Sy);function Fo(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 Pc(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,Ue(e,"front")))/r,rear:(t.sprungMass*(1-n)+o*a(t.rideRateRear,Ue(e,"rear")))/r}}function Lc(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 Hp(e,t){return e.wheelbase>0?e.massTotal*t*9.81/e.wheelbase:0}function wo(e,t,r){let n=2*t.rideRateFront,o=2*t.rideRateRear;return!(n>0)||!(o>0)?0:Math.min(Fp(t.sprungMass,r,e.wheelbase),.5*n*o/(n+o))}function Dc(e,t,r,n,o){let a=e.cgHeight,s=Hp(e,r);if(n===0&&o===0&&s===0)return{height:a,forward:0,noseLoad:0,dropFront:0,dropRear:0};let i=Pc(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=wo(e,t,u);let b=n-s*u,g=o+s*u;if(p>0){let M=c*l-p*(c+l);m=(b*(l-p)-p*g)/M,f=(g*(c-p)-p*b)/M}else m=c>0?b/c:0,f=l>0?g/l:0;let y=Lc(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 zp={yawDeg:0,rollDeg:0},Ay=1e-4,Vw=40,Fy=50;function Co(e,t,r=0){let n=e.aero?.model;if(!(!n||!zr(n,e).hasAttitude))return{yawDeg:r,rollDeg:Ce(e).rollGradient*t}}function Yp(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 Ao(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=ly(r)?n(r.frame,r.ref.h,r.ref.pitch):r.ref;else if(r){let{x:a,y:s}=Sc(r),i=(a[0]+a[a.length-1])/2,c=(s[0]+s[s.length-1])/2;o=So(r)?n(r.frame,i,c):{hFront:i,hRear:c}}return{hFront:e.rideHeightFront??o.hFront,hRear:e.rideHeightRear??o.hRear}}var wy=new WeakMap;function Yr(e,t,r=0,n){let o=e.aero;if(!o?.model)return null;let a=wy.get(e);a||(a=new Map,wy.set(e,a));let s=n&&zr(o.model,e).hasAttitude?n:zp,i=s===zp?`${t}|${r}`:`${t}|${r}|${s.yawDeg.toFixed(3)}|${s.rollDeg.toFixed(3)}`,c=a.get(i);if(c)return c;let l=Bw(e,o,t,r,s);return a.size>4096&&a.clear(),a.set(i,l),l}function Bw(e,t,r,n,o){let a=zr(t.model,e),s=Ce(e),i=2*s.rideRateFront,c=2*s.rideRateRear,l=Yp(t,e.wheelbase),u=.5*t.rho*r*r,m=a.area,f=e.wheelbase>0?t.copHeight/e.wheelbase:0,p=Pc(e,s),d=Hp(e,n),h=(C,T)=>Lc(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,I=h(C,T),G=d*I,O=wo(e,s,I)*b(C,T),W=A-G-D+O,E=P+G+D-O,_=C-l.hFront+(i>0?W/i:0),V=T-l.hRear+(c>0?E/c:0);return{c:S,downFront:A,downRear:P,drag:L,rF:_,rR:V,norm:Math.hypot(_,V)}},y=(C,T,S=!1)=>{let A=a.slopes(C,T,S,o.yawDeg,o.rollDeg),P=i>0?u*m/i:0,L=c>0?u*m/c:0;return[[P*(A.clFront.hFront-f*A.cd.hFront),P*(A.clFront.hRear-f*A.cd.hRear)],[L*(A.clRear.hFront+f*A.cd.hFront),L*(A.clRear.hRear+f*A.cd.hRear)]]},R=l.hFront,M=l.hRear,v=g(R,M),x=0;for(;v.norm>=Ay&&x<Vw;){x++;let C=y(R,M),T=i>0?d/i:0,S=c>0?d/c:0,A=wo(e,s,h(R,M)),P=i>0?A/i:0,L=c>0?A/c:0,D=1+C[0][0]-T*p.front-P,I=C[0][1]-T*p.rear+P,G=C[1][0]+S*p.front+L,O=1+C[1][1]+S*p.rear-L,W=D*O-I*G,E,_;Math.abs(W)>1e-9?(E=-(O*v.rF-I*v.rR)/W,_=-(-G*v.rF+D*v.rR)/W):(E=-.5*v.rF,_=-.5*v.rR);let V=Math.max(1,Math.abs(E)/Fy,Math.abs(_)/Fy);E/=V,_/=V;let N=1;for(let $=0;$<6;$++){let K=g(R+N*E,M+N*_);if(K.norm<=v.norm||$===5){R+=N*E,M+=N*_,v=K;break}N*=.5}}let k=y(R,M,!0),F=2+k[0][0]+k[1][1],w=(1+k[0][0])*(1+k[1][1])-k[0][1]*k[1][0];return{v:r,axG:n,hFront:R,hRear:M,cgHeight:h(R,M),cgForward:e.wheelbase>0?h(R,M)*b(R,M)/e.wheelbase:0,cgNoseLoad:wo(e,s,h(R,M))*b(R,M),clFront:v.c.clFront,clRear:v.c.clRear,cd:v.c.cd,area:m,downforce:v.downFront+v.downRear,drag:v.drag,downFront:v.downFront,downRear:v.downRear,gain:$w(k),stable:w>0&&F>0,converged:v.norm<Ay,iterations:x,clampedRide:v.c.clampedRide,yawDeg:o.yawDeg,rollDeg:o.rollDeg,clampedAttitude:v.c.clampedAttitude}}function $w(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 za(e,t,r=0,n){let o=Yr(e,t,r,n);return o?{downforce:o.downforce,drag:o.drag,downFront:o.downFront,downRear:o.downRear}:e.aero?Fo(e.aero,t):{downforce:0,drag:0,downFront:0,downRear:0}}function Ec(e,t=0,r=0,n,o){if(e.aero&&t>0){if(e.aero.model){let i=Yr(e,t,r,n);return{height:i.cgHeight,forward:i.cgForward,noseLoad:i.cgNoseLoad}}let a=Fo(e.aero,t),s=e.wheelbase>0?a.drag*e.aero.copHeight/e.wheelbase:0;return Dc(e,o??Ce(e),r,a.downFront-s,a.downRear+s)}return r===0?{height:e.cgHeight,forward:0,noseLoad:0}:Dc(e,o??Ce(e),r,0,0)}var Cy=[0,1,0],Wp=[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],jp=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]],Gw=e=>X(e,e),Wr=e=>Math.sqrt(X(e,e)),Ya=(e,t)=>Gw(H(e,t)),ve=(e,t)=>Wr(H(e,t)),q=e=>{let t=Wr(e);return t<1e-12?[0,0,0]:[e[0]/t,e[1]/t,e[2]/t]};var jr=(e,t,r)=>{let n=q(r),o=H(e,t);return ee(t,U(n,X(o,n)))},Ty=(e,t,r)=>ve(e,jr(e,t,r));var Hw=1e-6;function zw(e){if(e<Hw){let n=e*e;return[1-n/6,.5-n/24]}let t=Math.sin(e),r=Math.cos(e);return[t/e,(1-r)/(e*e)]}function nt(e,t){let r=Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]);if(r<1e-14)return t;let[n,o]=zw(r),a=ae(e,t),s=ae(e,a);return ee(t,ee(U(a,n),U(s,o)))}function Et(e,t,r){let n=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);if(n<1e-14)return e;let o=[t[0]/n,t[1]/n,t[2]/n];return nt(U(o,r),e)}function qt(e,t){let r=t.length,n=e.map(a=>a.slice()),o=t.slice();return Ly(n,o,r,new Array(r).fill(0))}function Py(e,t,r){return Ly(e,t,t.length,r)}function Ly(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 Dy=e=>{let t=0;for(let r of e)t=Math.max(t,Math.abs(r));return t},Ey=e=>{let t=0;for(let r of e)t+=r*r;return t},Yw=Math.sqrt(Number.EPSILON);function Iy(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=Dy(c),u=Ey(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),M=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=Yw*Math.max(Math.abs(i[C]),s[C]);for(let A=0;A<a;A++)M[A]=i[A];M[C]+=T;let S=e(M);for(let A=0;A<p;A++)d[A][C]=(S[A]-c[A])/T}let k=0;for(let C=0;C<a;C++){for(let S=0;S<a;S++){let A=0;for(let P=0;P<p;P++)A+=d[P][C]*d[P][S];h[C][S]=A}let T=0;for(let S=0;S<p;S++)T+=d[S][C]*c[S];g[C]=T,k=Math.max(k,h[C][C])}let F=Math.max(k,1e-9),w=!1;for(let C=0;C<18;C++){let T=m*F;for(let A=0;A<a;A++){let P=h[A],L=b[A];for(let D=0;D<a;D++)L[D]=A===D?P[D]+T:P[D];y[A]=-g[A]}let S=Py(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=Ey(A);if(P<u){for(let L=0;L<a;L++)i[L]=v[L];c=A,u=P,l=Dy(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 Wa(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 Up(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 _y=e=>[e[0],-e[1],-e[2],-e[3]];function Ny(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 Oy(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 Vy(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 Xp(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 By(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 $y(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 Ww(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 jw(e){let t=e.hardpoints,r=q(H(t.damperChassis,t.pushrodOuter)),[n,o]=Ww(r);return{top:t.damperChassis,lower0:t.pushrodOuter,axis0:r,e1:n,e2:o}}function qp(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=Ya(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:jw(e)}:{}}}function It(e,t,r){let n=[t[3],t[4],t[5]],o=[t[0],t[1],t[2]],a=H(r,e.c0);return ee(ee(nt(n,a),e.c0),o)}function Qp(e,t){return ee(e.lcaFront,Et(e.lbjRel0,e.lcaDir,t))}function To(e,t){return e.steerMovesRack?ee(e.tieInner0,U(e.rackAxis,t)):e.tieInner0}function Zp(e,t,r,n){let o=It(e,t,e.lbj0),a=Qp(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,It(e,t,d.lower0));l=X(b,nt(h,d.e1)),u=X(b,nt(h,d.e2))}else{let d=It(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=It(e,t,e.tro0),f=To(e,n),p=(Ya(m,f)-e.tieLen2)/e.tieLenRef;return[s,i,c,l,u,p]}var ja=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]),Ic=e=>{let t=ja(e);return[e[0]/t,e[1]/t,e[2]/t]},Uw=(e,t)=>H(e,U(t,X(e,t))),Jp=e=>Ic(ae(e,Math.abs(e[0])<.6?[1,0,0]:[0,1,0]));function Xw(e,t){let r=e.ucaDir,n=ee(e.ucaFront,U(r,e.ubjAxial0)),o=Math.sqrt(e.ubjRadius2),a=Uw(H(e.ubj0,e.ucaFront),r),s=ja(a)>1e-9?Ic(a):Jp(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=Wa(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=Ic(c),d=(h,b)=>{let g=ee(n,ee(U(s,o*h),U(i,o*b))),y=Ic(H(g,t));return{q1:Oy(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 qw(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=ja(a),i=s>1e-9?U(a,1/s):Jp(n),c=H(t.top,r),l=ja(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=Jp(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:Up(Xp(R,y,ae(R,y)),_y(Xp(i,n,ae(i,n)))),k:u,margin:f,ok:f>=0}};return f>0?[h(1),h(-1)]:[h(1)]}function Qw(e,t,r,n){let{k:o}=n,a=Ny(n.q1,H(e.tro0,e.lbj0)),s=X(a,o),i=H(a,U(o,s)),c=ja(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=Wa(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:Up(Vy(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 Gy(e,t,r,n=[0,0,0,0,0,0]){let o=Qp(e,t),a=To(e,r),s=By([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?qw(e,e.strut,o):Xw(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=Qw(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 M=i(R);y&&(!l||M>l.near)&&(l={q:R,margin:g,near:M}),!y&&(!u||M>u.near)&&(u={q:R,margin:g,near:M})}}let{q:m,margin:f}=l??u,p=$y(m),d=H(H(o,e.c0),nt(p,H(e.lbj0,e.c0)));return{x:[d[0],d[1],d[2],p[0],p[1],p[2]],converged:l!==null,margin:f,free:!1}}function Hy(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:Ya(e.pushrodOuter,e.rockerToPushrod),damperLen0:ve(e.rockerToDamper,e.damperChassis)}}var Zw=(e,t)=>ee(e.pivotA,Et(e.rprRel0,e.axis,t)),ed=(e,t)=>ee(e.pivotA,Et(e.rdmRel0,e.axis,t));function Ua(e,t){return{pushrod:Zw(e,t),damper:ed(e,t)}}function zy(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=Wa(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(ed(e,r),e.damperChassis),converged:p,margin:0}}let u=Ky(Math.atan2(l.s1,l.c1),r),m=Ky(Math.atan2(l.s2,l.c2),r),f=Math.abs(m-r)<Math.abs(u-r)?m:u;return{phi:f,damperLength:ve(ed(e,f),e.damperChassis),converged:l.ok,margin:l.margin}}function Ky(e,t){let r=2*Math.PI;return e+r*Math.round((t-e)/r)}function Yy(e,t,r,n){return ee(t,nt(U(q(r),n),H(e,t)))}function Wy(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 jy(e,t,r,n){return ee(t,nt(U(q(r),n),H(e,t)))}var _c=180/Math.PI,Jw=(e,t,r)=>Math.max(t,Math.min(r,e)),Uy=[NaN,NaN,NaN];function Xa(e){let t=q(e.spinAxis),r=q(H(e.uprightUpper,e.uprightLower)),n=-Math.asin(Jw(t[2],-1,1))*_c,o=Math.atan2(t[0],t[1])*_c,a=Math.atan2(-r[0],r[2])*_c,s=Math.atan2(-r[1],r[2])*_c,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]):Uy,d=m?f(e.wheelCenter[2]):Uy,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),M=X(R,y),v=-X(R,g),x=e.wheelCenter[1]-d[1],k=d[0]-e.wheelCenter[0],F=Ty(e.tieOuter,u,r);return{camber:n,toe:o,caster:a,kpi:s,scrubRadius:h,mechanicalTrail:b,scrubAtWheel:M,trailAtWheel:v,kingpinOffset:x,casterOffset:k,steeringArm:F,contactPatch:l,kingpinGround:p,kingpinAtHub:d}}function et(e){return{corner:e,inv:qp(e),rocker:Hy(e.hardpoints)}}var eC=[20,20,20,.2,.2,.2];function qy(e,t,r,n=[0,0,0,0,0,0]){let o=Gy(e,t,r,n);if(!o.free)return o;let a=tC(e,t,r,n);return{x:a.x,converged:a.converged,margin:0}}function tC(e,t,r,n=[0,0,0,0,0,0]){return Iy(o=>Zp(e,o,t,r),n,{scales:eC,tol:1e-10,maxIter:40})}var rC=.01,Nc=1.2,pt=e=>e.ok?e.state:null,ot=e=>e.ok?e.state:e.nearest;function ge(e,t,r,n,o){let a=0,s=Ee(e,a,r,n,o);if(Math.abs(s.travel-t)<1e-4)return Xy(s,t,!1);let c=(Ee(e,.02,r,td(s),o).travel-s.travel)/.02;(!Number.isFinite(c)||Math.abs(c)<1e-6)&&(c=1);let l=f=>Math.max(-Nc,Math.min(Nc,f)),u=l((t-s.travel)/c),m=Ee(e,u,r,td(s),o);for(let f=0;f<12&&!(Math.abs(m.travel-t)<1e-4);f++){let p=m.travel-s.travel,d=Math.abs(p)<1e-9?u:u-(m.travel-t)*((u-a)/p);a=u,s=m,u=l(d),m=Ee(e,u,r,td(s),o)}return Xy(m,t,Math.abs(u)===Nc)}function Xy(e,t,r){let n=e.travel-t,o=Math.abs(n)<=rC,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 td(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 nC(e,t,r,n,o){switch(e){case"upright":return It(t,r,o.pushrodOuter);case"upperArm":{let a=It(t,r,t.ubj0),s=Wy(t.ubj0,a,t.ucaFront,t.ucaDir);return jy(o.pushrodOuter,t.ucaFront,t.ucaDir,s)}default:return Yy(o.pushrodOuter,t.lcaFront,t.lcaDir,n)}}function Ee(e,t,r,n,o){let{inv:a,corner:s}=e,i=n?.q??[0,0,0,0,0,0],c=qy(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:It(a,l,f.uprightUpper),b=It(a,l,f.uprightLower),g=It(a,l,f.tieOuter),y=It(a,l,f.wheelCenter),R=q(nt(u,p.spinAxis)),M=nC(d?"upright":p.pushrodAttach,a,l,t,f),v=d?d.top:f.damperChassis,x=d||p.actuation==="direct"?{phi:0,damperLength:ve(M,v),converged:!0,margin:1}:zy(e.rocker,M,n?.phi??0),k=Xa({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:M,spinAxis:R,contactPatch:k.contactPatch,kingpinGround:k.kingpinGround,kingpinAtHub:k.kingpinAtHub,rockerAngle:x.phi,damperLength:x.damperLength},metrics:{camber:k.camber,toe:k.toe,caster:k.caster,kpi:k.kpi,scrubRadius:k.scrubRadius,mechanicalTrail:k.mechanicalTrail,scrubAtWheel:k.scrubAtWheel,trailAtWheel:k.trailAtWheel,kingpinOffset:k.kingpinOffset,casterOffset:k.casterOffset,steeringArm:k.steeringArm,damperLength:x.damperLength},converged:c.converged&&x.converged,margin:Math.min(c.margin,x.margin)}}var Po=e=>e==="FL"||e==="FR"?"front":"rear",Zy=e=>e==="FL"||e==="RL"?"left":"right";function $e(e,t){return e.corners?.[t]??oC(e[Po(t)],Zy(t))}function Jy(e){let t=e.config.springSplit;return e.config.actuation==="decoupled"||t===void 0||!Number.isFinite(t)||Math.abs(t)>=1?0:t}var Qy=new WeakMap;function oC(e,t){let r=Jy(e);if(r===0)return e;let n=Qy.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)},Qy.set(e,n)}return n[t]}var Lo=["FL","FR","RL","RR"],dt=e=>2*e.hardpoints.wheelCenter[1],Ur=(e,t)=>t?dt($e(e,"FL"))/2+dt($e(e,"FR"))/2:dt($e(e,"RL"))/2+dt($e(e,"RR"))/2;function Ze(e,t){let r=e==="FL"||e==="FR";return{axleX:r?t.frontAxleX:t.frontAxleX-t.wheelbase,sideSign:e==="FR"||e==="RR"?1:-1,isFront:r}}function _t(e,t){return[t.axleX+e[0],t.sideSign*e[1],e[2]]}function Xr(e,t){return[e[0],t.sideSign*e[1],e[2]]}function Do(e){return e.frontAxleX-e.wheelbase/2}function rd(e,t,r){return t[2]+e.heave+(t[0]-r)*Math.sin(e.pitch)-t[1]*Math.sin(e.roll)}function qr(e,t,r,n){let o=Ze(e,t),a=(n?Ur(n,o.isFront):o.isFront?t.trackFront:t.trackRear)/2,s=o.sideSign*a,i=o.axleX-Do(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 aC={travelMin:-40,travelMax:40,steps:41,steer:0};function qa(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 qe(e,t={}){let r={...aC,...t},n=et(e);return Eo(n,r)}function Eo(e,t){let r=t.steer,n=.01,o=Ee(e,n,r),a=Ee(e,-n,r),s=(o.travel-a.travel)/(2*n);(!Number.isFinite(s)||Math.abs(s)<1e-6)&&(s=1);let i=Math.max(Math.abs(t.travelMax),Math.abs(t.travelMin)),c=Math.min(1.2,1.5*i/Math.abs(s)),l=Math.max(20,t.steps*2),u=[],m=Ee(e,0,r);u.push({beta:0,travel:m.travel,warm:qa(m),converged:m.converged});let f=qa(m);for(let R=1;R<=l;R++){let M=c*R/l,v=Ee(e,M,r,f);f=qa(v),u.push({beta:M,travel:v.travel,warm:f,converged:v.converged})}f=qa(m);for(let R=1;R<=l;R++){let M=-c*R/l,v=Ee(e,M,r,f);f=qa(v),u.push({beta:M,travel:v.travel,warm:f,converged:v.converged})}u.sort((R,M)=>R.beta-M.beta);let p=u[u.length-1].travel>=u[0].travel,d=!1;for(let R=1;R<u.length;R++){let M=u[R].travel-u[R-1].travel;(p&&M<-1e-6||!p&&M>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 M=t.steps===1?t.travelMin:t.travelMin+(t.travelMax-t.travelMin)*R/(t.steps-1),v=sC(u,M,p),x=iC(u,v);y.push(Ee(e,v,r,x))}return cC(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 sC(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 iC(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 nd(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 cC(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=nd(n,r,s),c=nd(o,r,s),l=-nd(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 Oc=e=>e!==void 0&&Number.isFinite(e)&&e>0;function lC(e){return e&&Oc(e.helperRate)&&Oc(e.helperTravel)?{rate:e.helperRate,travel:e.helperTravel}:null}function od(e,t,r){let n=t/e;return r?n+Math.min(t/r.rate,r.travel):n}function Qa(e,t,r,n){if(!(e>0)||!Number.isFinite(e)||!(t>0)||!Number.isFinite(t))return null;let o=lC(n),a=-od(e,t,o),s=Io(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 Io(e,t){if(!Number.isFinite(e))return{droop:null,bump:null};let r=Oc(t?.extended)&&t.extended>e?t.extended:null,n=r!==null&&Oc(t?.stroke)?r-t.stroke:null;return{droop:r!==null?e-r:null,bump:n!==null&&n<e?e-n:null}}function ad(e,t){if(!(e>0)||!Number.isFinite(e))return null;let r=Io(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 uC(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=od(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 mC(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=od(r,n,o)+t;return a<=0?0:a>=o.rate*o.travel/r+o.travel?r:r*o.rate/(r+o.rate)}function _o(e,t){let r=uC(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 sd(e,t){let r=mC(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 id(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 Vc={min:-60,max:60,steps:61},cd=e=>({travel:[e.min,e.max],force:[0,0],motionRatio:[0,0],spring:null}),ex=new WeakMap;function pC(e,t){let r=ex.get(e.corner);r||ex.set(e.corner,r=new Map);let n=`${t.min}|${t.max}|${t.steps}`,o=r.get(n);return o||r.set(n,o=Eo(e,{travelMin:t.min,travelMax:t.max,steps:t.steps,steer:0})),o}function Za(e,t,r=Vc,n=e.corner.config.coilover){let o=e.corner.config;if(o.actuation==="decoupled")return cd(r);let a=pC(e,r),s=fC(e,o.springRate,a.samples),i=[];for(let h of a.samples){let b=h.metrics.motionRatio;!h.converged||b===void 0||!Number.isFinite(b)||!Number.isFinite(h.metrics.damperLength)||i.length>0&&h.travel<=i[i.length-1].t+1e-6||i.push({t:h.travel,L:h.metrics.damperLength,mr:b})}if(i.length<2)return cd(r);let c=bC(i,0);if(!(Math.abs(c.mr)>1e-6))return cd(r);let l=t/c.mr,u=Qa(s,l,c.L,n),m=u?dC(i,id(u).map(h=>c.L-h)):i,f=m.map(h=>(u?_o(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?id(u).map(p).filter(h=>h!==null):[];return{travel:m.map(h=>h.t),force:f,motionRatio:m.map(h=>h.mr),spring:{rate:s,preload:l,length0:c.L,law:u},...u?{stops:{droop:p(u.droop),bump:p(u.bump)}}:{},...d.length?{kinks:d}:{},length:m.map(h=>h.L)}}function dC(e,t){let r=[...e];for(let n of t)for(let o=0;o+1<e.length;o++){let a=e[o],s=e[o+1];if(a.L===n)break;if((a.L-n)*(s.L-n)>=0)continue;let i=(n-a.L)/(s.L-a.L);r.push({t:a.t+i*(s.t-a.t),L:n,mr:a.mr+i*(s.mr-a.mr)});break}return r.sort((n,o)=>n.t-o.t),r.filter((n,o)=>o===0||n.t>r[o-1].t+1e-6)}function fC(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:hC(e,n,r);return!(o>0)||!Number.isFinite(o)?t:t*o/(t+o)}function hC(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=Ua(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 ld(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.motionRatio[0];let n=gr(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 br(e,t,r){if(!e.spring)return Kt(e,t);let{rate:n,preload:o,length0:a,law:s}=e.spring,i=ld(e,0),c=a-r;return(s?_o(s,c):o+n*c)*ld(e,t)-o*i}function bC(e,t){let r=gr(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 gr(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 Kt(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.force[0];let n=gr(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 No(e,t){let r=e.travel.length;if(r<3)return Ja(e,t);let n=gr(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 Ja(e,t){if(e.travel.length<2)return 0;let n=gr(e.travel,t);return(e.force[n+1]-e.force[n])/(e.travel[n+1]-e.travel[n])}function Pe(e,t,r){let n=e.hardpoints;switch(t.attach){case"upright":{let o=H(t.outer,n.wheelCenter);return ee(ee(nt(r.pose.omega,o),n.wheelCenter),r.pose.t)}case"lowerArm":{let o=q(H(n.lcaRear,n.lcaFront));return ee(n.lcaFront,nt(U(o,r.beta),H(t.outer,n.lcaFront)))}case"rocker":{let o=q(H(n.rockerPivotB,n.rockerPivotA));return ee(n.rockerPivotA,Et(H(t.outer,n.rockerPivotA),o,r.points.rockerAngle))}}}function Qr(e,t,r){return e.config.actuation==="decoupled"&&t.attach==="rocker"&&r==="coil"}function ud(e,t,r){return Qr(e,t,r)?[t.inner[0],-t.inner[1],t.inner[2]]:t.inner}function Oo(e,t,r){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return md(e,t,r.kind,qe(e,{travelMin:n,travelMax:o,steps:a}).samples)}function md(e,t,r,n){let o=q(H(t.outer,ud(e,t,r))),a=[],s=[],i=t.outer;for(let p of n)a.push(p.travel),s.push(X(H(Pe(e,t,p),i),o));let c=a.length,l=new Array(c).fill(0);for(let p=0;p<c;p++){let d=Math.max(0,p-1),h=Math.min(c-1,p+1),b=a[h]-a[d];l[p]=b!==0?(s[h]-s[d])/b:0}let u=l[0];for(let p=1;p<c;p++)if(a[p]>=0){let d=a[p]-a[p-1],h=d!==0?(0-a[p-1])/d:0;u=l[p-1]+h*(l[p]-l[p-1]);break}let m=l.filter(p=>Math.abs(p)>1e-9).map(Math.sign),f=m.length>0&&m.some(p=>p!==m[0]);return{travel:a,ratio:l,linkTravel:s,atDesign:u,reverses:f}}function pd(e,t){let{travel:r,ratio:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}function dd(e,t){let{travel:r,linkTravel:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}var es=e=>e.mount??{kind:"rockerToRocker"},ox=e=>[e[0],0,e[2]],gC=e=>2*Math.abs(e[1]),yC=(e,t)=>Math.hypot(e[0]-t[0],e[2]-t[2]);function $c(e,t){return t.kind==="chassis"?yC(e,t.anchor):gC(e)}function ts(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 kn(e,t,r={}){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return fd(e,t,qe(e,{travelMin:n,travelMax:o,steps:a}).samples)}function fd(e,t,r){let n=es(t),o=d=>Pe(e,{...t,inner:t.outer},r[d]),a=[],s=[],i=[];for(let d=0;d<r.length;d++)a.push(r[d].travel),i.push($c(o(d),n));let c=rx(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=tx(a,20),f=tx(a,-20),p=ts(o(m),o(f),n);return{travel:a,ratio:u,springTravel:s,atDesign:rx(a,u,0),installedLength:c,rollSensitivity:c-p}}function tx(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 rx(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 hd(e,t,r){let n={outer:t.outer,attach:t.attach},o=qe(e,{travelMin:-5,travelMax:5,steps:3}),a=d=>ox(Pe(e,{...n,inner:n.outer},o.samples[d])),s=a(1),i=a(2),c=a(0),l=i[0]-c[0],u=i[2]-c[2],m=Math.hypot(l,u),f=m>1e-9?[l/m,u/m]:[0,1],p=r??Math.max(80,2*Math.abs(t.outer[1])*.5);return[s[0]+f[0]*p,0,s[2]+f[1]*p]}function bd(e,t){let r=e.hardpoints,n=r.rockerPivotA,o=nx(Bc(r.rockerPivotB,r.rockerPivotA)),a=Math.max(30,.6*ax(Bc(r.rockerToDamper,n))),s=Bc(r.rockerToDamper,n),i=nx(Bc(s,xC(o,RC(s,o)))),c=vC(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:hd(e,d)}}:d,b;try{b=kn(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 Bc=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],xC=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],RC=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],ax=e=>Math.hypot(e[0],e[1],e[2]),nx=e=>{let t=ax(e)||1;return[e[0]/t,e[1]/t,e[2]/t]},vC=(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 gd=.001,kC=e=>({outer:e.outer,inner:e.outer,attach:e.attach}),dx=(e,t,r)=>($c(e.at0,t)-$c(r,t))/2,MC=(e,t)=>X(H(t,e.pickup.at0),e.axis);function yd(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 sx(e,t){let r=[0,1,2].map(n=>yd(e,t.map(o=>o[n])));return t.map((n,o)=>[r[0][o],r[1][o],r[2][o]])}function xd(e){return{travel:e,heave:e.map(t=>t/2),heaveRatio:e.map(()=>.5),roll:[...e],rollRatio:e.map(()=>1)}}function ix(e,t,r,n){let o=e.corner;if(!t.heave&&!t.roll)return{side:xd([n.min,n.max]),pickups:{}};let a=ot(ge(e,0,0)),s={};if(t.heave&&r){let h=kC(t.heave);s.heave={corner:o,link:h,at0:Pe(o,h,a)}}if(t.roll){let h=t.roll;s.roll={pickup:{corner:o,link:h,at0:Pe(o,h,a)},axis:q(H(h.outer,ud(o,h,t.rollKind??"coil")))}}let i=t.roll&&Qr(o,t.roll,t.rollKind??"coil")?{near:t.roll,far:{...t.roll,outer:t.roll.inner}}:null,c=Eo(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?dx(s.heave,r,Pe(o,s.heave.link,h)):h.travel/2),m.push(s.roll?MC(s.roll,Pe(o,s.roll.pickup.link,h)):h.travel),i&&(f.push(Pe(o,i.near,h)),p.push(Pe(o,i.far,h))));if(l.length<2)return{side:xd([n.min,n.max]),pickups:{}};let d={travel:l,heave:u,heaveRatio:yd(l,u),roll:m,rollRatio:yd(l,m)};return i&&(d.eyes={near:f,nearRatio:sx(l,f),far:p,farRatio:sx(l,p)}),{side:d,pickups:s}}function Gc(e,t,r){let n=gr(e,r);return t[n]+(r-e[n])/(e[n+1]-e[n])*(t[n+1]-t[n])}function cx(e,t,r){let n=gr(e,r);return(t[n+1]-t[n])/(e[n+1]-e[n])}function He(e,t){return{h:Gc(e.travel,e.heave,t),dh:Gc(e.travel,e.heaveRatio,t),ddh:cx(e.travel,e.heaveRatio,t),r:Gc(e.travel,e.roll,t),dr:Gc(e.travel,e.rollRatio,t),ddr:cx(e.travel,e.rollRatio,t)}}function lx(e,t,r,n){let o=gr(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 Rd=(e,t)=>Math.hypot(e[0]-t[0],e[1]+t[1],e[2]-t[2]);function fx(e,t){let r=e.side[0].eyes,n=e.side[1].eyes;if(!r||!n)return null;let o=lx(e.side[0].travel,r.near,r.nearRatio,t[0]),a=lx(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 hx=(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,SC=(e,t)=>e.bump!==null&&t>e.bump||e.droop!==null&&t<e.droop?e.rate:0;function rs(e,t,r,n,o=0){let a=e.rollStop;if(!a)return r;let s=fx(e,t);if(!s)return r;let i=hx(a,a.length0-(n??s.L+o));return i===0?r:[r[0]-i*s.dL[0],r[1]-i*s.dL[1]]}function Kc(e,t){let r=xd(e.travel);return t==="heave"?{...e,heave:r.heave,heaveRatio:r.heaveRatio}:{...e,roll:r.roll,rollRatio:r.rollRatio}}var Hc=(e,t)=>e?e.law?_o(e.law,t):e.preload+e.rate*t:0,ux=(e,t)=>e?e.law?sd(e.law,t):e.rate:0;function ns(e,t,r,n,o){let a=Hc(e.heave,n),s=Hc(e.roll,o);return[a*t.dh+s*t.dr,a*r.dh-s*r.dr]}var mx=(e,t)=>He(e[0],t).h+He(e[1],t).h;function AC(e,t){let r=e.gap>0?mx(t,e.gap):0;return e.bothWays?{free:r,pull:e.gap>0?mx(t,-e.gap):0}:{free:r,pull:null}}function FC(e,t,r){let n={...t,outer:t.inner},o=(u,m)=>{let f=pt(ge(e[0],u,0)),p=pt(ge(e[1],m,0));if(!f||!p)return NaN;let d=Pe(e[0].corner,t,f),h=Pe(e[1].corner,n,p);return Math.hypot(d[0]-h[0],d[1]+h[1],d[2]-h[2])},a=1,s=o(0,0),i=o(-a,a)-o(a,-a),c=He(r[0],a).r-He(r[1],-a).r-(He(r[0],-a).r-He(r[1],a).r),l=i/c;return Number.isFinite(s)&&s>0&&Number.isFinite(l)&&Math.abs(l)>gd?{length0:s,scale:l}:null}function bx(e,t,r,n=Vc){let o=r.heave?es(r.heave):void 0,a=ix(e[0],r,o,n),s=e[1].corner===e[0].corner?a:ix(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=>He(A,0));c&&!(Math.abs(p[0].dh+p[1].dh)>gd)&&(i=[Kc(i[0],"heave"),Kc(i[1],"heave")],c=!1),l&&!(Math.abs(p[0].dr+p[1].dr)>gd)&&(i=[Kc(i[0],"roll"),Kc(i[1],"roll")],l=!1),p=i.map(A=>He(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 M={};if(c&&o){let A=[a.pickups.heave,s.pickups.heave];M.heave={pickups:A,mount:o,span0:ts(A[0].at0,A[1].at0,o)}}let v=M.heave?M.heave.span0:NaN,x=M.heave?r.coilover:void 0,k=r.carriesLoad?Qa(b,y,v,x):u?ad(b,{...AC(u,i),length0:v,coilover:x}):null,F=b>0?{rate:b,preload:y,...k?{law:k}:{}}:null;if(l&&(M.roll={pickups:[a.pickups.roll.pickup,s.pickups.roll.pickup],axes:[a.pickups.roll.axis,s.pickups.roll.axis]},r.roll&&Qr(e[0].corner,r.roll,r.rollKind??"coil"))){let A=FC(e,r.roll,i);A&&(M.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:M},T=M.roll?.unit,S=T&&g>0&&i[0].eyes&&i[1].eyes?Io(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=rs(C,[0,0],ns(C,p[0],p[1],p[0].h+p[1].h,p[0].r-p[1].r)),C}function os(e,t,r){let n=He(e.side[0],t[0]),o=He(e.side[1],t[1]),a=r?rs(e,t,ns(e,n,o,n.h+o.h+r.heave,n.r-o.r+r.roll),void 0,r.unit):rs(e,t,ns(e,n,o,n.h+o.h,n.r-o.r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function vd(e,t,r){let n=He(e.side[0],t[0]),o=He(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=ux(e.heave,a),c=ux(e.roll,s),l=Hc(e.heave,a),u=Hc(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?fx(e,t):null;if(!p||!d)return f;let h=p.length0-(r?d.L+r.unit:d.L),b=SC(p,h);if(b===0)return f;let g=hx(p,h),y=(M,v)=>b*d.dL[M]*d.dL[v]-g*d.ddL[M][v],R=m+y(0,1);return[[f[0][0]+y(0,0),R],[R,f[1][1]+y(1,1)]]}function kd(e,t,r){let n=vd(e,t);return n[r][0]+n[r][1]}function wC(e,t,r){let n=e.read.heave;if(!n)return He(e.side[0],t[0]).h+He(e.side[1],t[1]).h;let[o,a]=n.pickups;return n.span0-ts(Pe(o.corner,o.link,r[0]),Pe(a.corner,a.link,r[1]),n.mount)}function CC(e,t,r){let n=e.read.roll;if(!n)return He(e.side[0],t[0]).r-He(e.side[1],t[1]).r;let o=a=>X(H(Pe(n.pickups[a].corner,n.pickups[a].link,r[a]),n.pickups[a].at0),n.axes[a]);return o(0)-o(1)}function TC(e,t){let r=e.read.roll;if(!e.rollStop||!r)return;let[n,o]=r.pickups;return Rd(Pe(n.corner,n.link,t[0]),Pe(o.corner,{...o.link,outer:o.link.inner},t[1]))}function as(e,t,r){let n=He(e.side[0],t[0]),o=He(e.side[1],t[1]),a=rs(e,t,ns(e,n,o,wC(e,t,r),CC(e,t,r)),TC(e,r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function Md(e,t,r,n){let o=He(e.side[0],r),a=He(e.side[1],r),s=e.read.heave,i=s?.pickups[t],c=s&&i&&n?2*dx(i,s.mount,Pe(i.corner,i.link,n)):o.h+a.h,l=e.rollStop&&n?e.read.roll?.pickups[t]:void 0,u=l&&n?Rd(Pe(l.corner,l.link,n),Pe(l.corner,{...l.link,outer:l.link.inner},n)):void 0;return rs(e,[r,r],ns(e,o,a,c,n?0:o.r-a.r),u)[t]-e.force0[t]}function Sd(e,t,r,n){let o=No(e,r[n]);return t?.carriesLoad?o+kd(t,r,n):o}var Ad=e=>e==="FR"||e==="RR"?1:0,zc=(e,t)=>e.elements?.[t==="FL"||t==="FR"?"front":"rear"]??null;var gx=e=>Number.isFinite(e)&&e>0?1/e:0;var yx=(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},PC=(e,t)=>[e[0][0]*t[0]+e[0][1]*t[1],e[1][0]*t[0]+e[1][1]*t[1]],xx=1e-8,LC=40;function DC(e,t,r,n){return{force:(s,i)=>{if(r){let u=os(r,s,n);return[Kt(t[0],s[0])+i[0]+u[0],Kt(t[1],s[1])+i[1]+u[1]]}let c=(s[0]+s[1])/2,l=(s[0]-s[1])/2;return[Kt(t[0],s[0])+i[0]+e[0].heaveRate*c+e[0].arbRate*l,Kt(t[1],s[1])+i[1]+e[1].heaveRate*c-e[1].arbRate*l]},stiffness:(s,i=Ja)=>{if(r){let c=vd(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 Vo(e,t,r,n,o,a=[0,0],s=[0,0],i=null,c){let l=[gx(r[0].tyreRate),gx(r[1].tyreRate)],u=[r[0].staticLoad,r[1].staticLoad],m=DC(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]),I=[D[0]+s[0]*L,D[1]+s[1]*L],G=[P[0]+t[0]*L+I[0]*l[0]-e[0]*L,P[1]+t[1]*L+I[1]*l[1]-e[1]*L],O=[d[0]*(u[0]+I[0]),d[1]*(u[1]+I[1])],W=[O[0]<G[0],O[1]<G[1]];return{f:I,on:G,off:O,lifted:W,r:[Math.min(G[0],O[0]),Math.min(G[1],O[1])]}},b=(P,L)=>[L[0]?[d[0]*P[0][0],d[0]*P[0][1]]:[1+P[0][0]*l[0],P[0][1]*l[0]],L[1]?[d[1]*P[1][0],d[1]*P[1][1]]:[P[1][0]*l[1],1+P[1][1]*l[1]]],g=P=>Math.max(Math.abs(P[0]),Math.abs(P[1])),y=(P,L)=>{let D=[P[0],P[1]],I=h(D,L),G=!1,O=0;for(;O<LC;O++){if(g(I.r)<xx){G=!0;break}let W=yx(b(m.stiffness(D),I.lifted),[-I.r[0],-I.r[1]]);if(!W)break;let E=1,_=[D[0]+W[0],D[1]+W[1]],V=h(_,L);for(let N=0;N<8&&g(V.r)>g(I.r);N++)E/=2,_=[D[0]+E*W[0],D[1]+E*W[1]],V=h(_,L);D=_,I=V}return!G&&g(I.r)<xx&&(G=!0),{t:D,b:I,converged:G,it:O}},R=y(o?[o[0],o[1]]:[e[0]-t[0],e[1]-t[1]],1),M=R.it;if(!R.converged){let P=0,L=[0,0],D=.25;for(;P<1&&D>=1/256;){let I=Math.min(1,P+D),G=y(L,I);M+=G.it,G.converged?(P=I,L=G.t,I===1&&(R=G)):D/=2}}let{t:v,b:x,converged:k}=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,No),S=b(T,F);return{t:v,dF:w,lifted:F,clearance:C,converged:k,iterations:M,respond:(P,L,D=[0,0])=>{let I=[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]],G=yx(S,I);if(!G)return[NaN,NaN];let O=PC(T,G);return[F[0]?0:O[0]+D[0],F[1]?0:O[1]+D[1]]}}}var Mn=e=>!(Number.isFinite(e.tyreRate)&&e.tyreRate>0);function Qt(e,t,r){return t?.input.corners[r].staticLoadedRadius??e}var Fd=["FL","FR","RL","RR"],kx={front:["FL","FR"],rear:["RL","RR"]},EC=512,IC=5e-4,_C=8;function Yc(e,t){let r={},n={},o=new Map;for(let s of Fd){let i=e.ctx[s],c=t.corners[s],l=c.staticLoadedRadius;n[s]=ot(ge(i,0,0,void 0,l===void 0?void 0:{loadedRadius:l})).points.contactPatch[2];let u=t.cornerCoilover?.[s==="FL"||s==="FR"?"front":"rear"],m=`${Fd.findIndex(p=>$e(e.vehicle,p)===$e(e.vehicle,s))}|${c.springLoad}|${u?`${u.extended}/${u.stroke}`:""}`,f=o.get(m);f?r[s]=f:(r[s]=u?Za(i,c.springLoad,void 0,u):Za(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=kx[s];a[s]=bx([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 Mx(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 NC=e=>`${e.heave}|${e.pitch}|${e.roll}|${e.steer}`;function wd(e,t,r){return{travel:r.travel,steer:r.steer,ground:r.travel,tyreDeflection:0,load:NaN,loadedRadius:Qt($e(e.vehicle,t).config.loadedRadius,e.kc,t),lifted:!1,contactLength:0,converged:!0,rigid:!0,rideRate:NaN,wheelRateAtLoad:NaN}}var OC=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 Rx(e,t,r,n){let o=kx[n],a=e.vehicle.config,s=o.map(w=>qr(w,a,r,e.vehicle)),i=[t.input.corners[o[0]],t.input.corners[o[1]]],c=t.loadCase;if(!c&&i.every(Mn))return{corners:[wd(e,o[0],s[0]),wd(e,o[1],s[1])],respond:null};let l=o.map(w=>t.curve[w]),u=t.elements?.[n]??null,m=o.map(w=>Qt($e(e.vehicle,w).config.loadedRadius,t,w)),f=[s[0].travel+(c?.ground[o[0]]??0),s[1].travel+(c?.ground[o[1]]??0)],p=[c?.linkLoad[o[0]]??0,c?.linkLoad[o[1]]??0],d=[c?.patchShift[o[0]],c?.patchShift[o[1]]],h=[0,0],b=[0,0],g,y=Vo(f,h,i,l,void 0,void 0,p,u),R=[void 0,void 0],M=[!0,!0],v=[0,0],x=!1;for(let w=0;w<_C;w++){w>0&&(y=Vo(f,h,i,l,g,b,p,u)),v=[Number.isFinite(i[0].tyreRate)&&i[0].tyreRate>0?y.dF[0]/i[0].tyreRate:0,Number.isFinite(i[1].tyreRate)&&i[1].tyreRate>0?y.dF[1]/i[1].tyreRate:0];let C=[0,0],T=[0,0];for(let A=0;A<2;A++){let P=ge(e.ctx[o[A]],y.t[A],s[A].steer,OC(R[A]),{loadedRadius:m[A]-v[A],patchShift:d[A]}),L=ot(P);R[A]=L,M[A]=P.ok,C[A]=L.points.contactPatch[2]-t.ground0[o[A]]-y.t[A]-v[A],T[A]=br(l[A],y.t[A],L.points.damperLength)-Kt(l[A],y.t[A])}if(u){let A=as(u,y.t,[R[0],R[1]]),P=os(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<IC){x=!0;break}}let k=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:Mx(m[w]-v[w],i[w].staticLoad+y.dF[w],i[w].tyreRate),converged:y.converged&&x&&M[w],rigid:!1,state:C,solved:M[w],rideRate:k[w],wheelRateAtLoad:Sd(l[w],u,y.t,w)}}),respond:y.respond}}function Sx(e,t){let r=e.kc,n=NC(t),o=r.memo.get(n);if(o)return o;let a=Rx(e,r,t,"front"),s=Rx(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>=EC&&r.memo.clear(),r.memo.set(n,i),i}function ft(e,t){if(!e.kc){let r={};for(let n of Fd)r[n]=wd(e,n,qr(n,e.vehicle.config,t,e.vehicle));return r}return Sx(e,t).corners}function Wc(e,t,r){return e.kc?Sx(e,t).respond[r]:null}function ss(e,t,r,n=0){let o=e.kc;if(!o)return r;let a=o.input.corners[t];if(Mn(a))return r;let s=qr(t,e.vehicle.config,{heave:0,pitch:0,roll:0,steer:n},e.vehicle).steer,i=Qt($e(e.vehicle,t).config.loadedRadius,o,t),c=o.loadCase,l=c?.linkLoad[t]??0,u=c?.patchShift[t],m=ot(ge(e.ctx[t],r,s,void 0,{loadedRadius:i,patchShift:u})),f=zc(o,t),p=br(o.curve[t],r,m.points.damperLength)+(f?Md(f,Ad(t),r,m):a.heaveRate*r),h=Math.max(p+l,-a.staticLoad)/a.tyreRate;return(h===0?m:ot(ge(e.ctx[t],r,s,void 0,{loadedRadius:i-h,patchShift:u}))).points.contactPatch[2]-o.ground0[t]-(c?.ground[t]??0)}var VC=180/Math.PI,BC=[0,0,1];function $C(e,t){let r=Xr(e,t),n=U(ae(BC,r),-t.sideSign);return-Math.atan2(n[1],n[0])*VC}var Ax=e=>1/Math.tan(e*Math.PI/180),Fx=.05,wx=.001;function Cx(e,t,r){if(!Number.isFinite(e)||!Number.isFinite(t))return NaN;if(!(Math.abs(e)<wx&&Math.abs(t)<wx))return e>0&&t>0?100*(Ax(t)-Ax(e))/r:NaN}function GC(e,t){let r=Ur(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=[Fx,-Fx].map(l=>{let{inner:u,outer:m}=a(t("FL",l).deg-n,t("FR",l).deg-o);return Cx(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=Cx(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 Cd(e,t){let r=e.vehicle.config,n={FL:Ze("FL",r),FR:Ze("FR",r)},o=t.travel??0,a=GC(e,(i,c)=>{let l=pt(ge(e.ctx[i],o,n[i].sideSign*c));return{deg:l?$C(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 Tx=35,Px=55,Nt=e=>e.rackTravel&&e.rackTravel>0?e.rackTravel:Tx,Td=e=>e.rackRatio&&e.rackRatio>0?e.rackRatio:Px;var Pd=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 Lx(e,t,r,n,o){let a=ge(e,n,0,void 0,o),s=ot(a),i=a.ok?0:1,c=s.points.contactPatch[2],l={steer:s.metrics.toe,camber:s.metrics.camber,lift:0,contactPatch:s.points.contactPatch,spinAxis:s.points.spinAxis,yaw:-s.metrics.toe*Math.PI/180},u=p=>{let d=[l],h=Pd(s);for(let b=1;b<=r;b++){let g=p*(t*b)/r,y=Ee(e,s.beta,g,h,o),R=pt(ge(e,n,g,Pd(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=Pd(y)}return d},m=u(1),f=u(-1);return{travelMm:n,unsolved:i,centre:l,positive:m,negative:f}}function KC(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 Dx(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:KC(o,t)});return{travelMm:e.travelMm,inner:n(r?e.positive:e.negative),outer:n(r?e.negative:e.positive)}}function HC(e){return e.positive[1].steer-e.centre.steer<0}function zC(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:Td(e.config),innerJacobian:r.inner.jacobian,outerJacobian:r.outer.jacobian}}function Ld(e,t,r=13,n=-40,o=40,a=5,s){let i=et(e),c=Array.from({length:r+1},(b,g)=>t*g/r),l=Lx(i,t,r,0,s),u=HC(l),m=Dx(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=Lx(i,t,r,b,s);return d+=g.unsolved,Dx(g,c,u)});return{...zC(e,c,m),...Ex(l.unsolved),travelSurface:{rackMm:c,rows:h,...Ex(d)}}}var Ex=e=>e>0?{unsolved:e}:{};function Zt(e,t,r){let n=e.length;if(n===0)return 0;if(r<=e[0])return t[0];if(r>=e[n-1])return t[n-1];let o=0,a=n-1;for(;a-o>1;){let i=o+a>>1;e[i]<=r?o=i:a=i}let s=(r-e[o])/(e[a]-e[o]);return t[o]+s*(t[a]-t[o])}function jc(e,t,r){let n=e.length;if(n===0)return{longitudinal:0,lateral:0,vertical:0,yaw:0};let o,a;if(r<=e[0])o=a=0;else if(r>=e[n-1])o=a=n-1;else for(o=0,a=n-1;a-o>1;){let l=o+a>>1;e[l]<=r?o=l:a=l}let s=t[o];if(o===a)return{longitudinal:s.longitudinal,lateral:s.lateral,vertical:s.vertical,yaw:s.yaw};let i=t[a],c=(r-e[o])/(e[a]-e[o]);return{longitudinal:s.longitudinal+c*(i.longitudinal-s.longitudinal),lateral:s.lateral+c*(i.lateral-s.lateral),vertical:s.vertical+c*(i.vertical-s.vertical),yaw:s.yaw+c*(i.yaw-s.yaw)}}function Ix(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 Sn=(e,t,r)=>e+r*(t-e);function Bo(e,t,r,n,o){let a=Zt(e.rackMm,e.rows[n.lo][t][r],o);if(n.lo===n.hi)return a;let s=Zt(e.rackMm,e.rows[n.hi][t][r],o);return Sn(a,s,n.t)}function _x(e,t,r,n){let o=jc(e.rackMm,e.rows[r.lo][t].jacobian,n);if(r.lo===r.hi)return o;let a=jc(e.rackMm,e.rows[r.hi][t].jacobian,n);return{longitudinal:Sn(o.longitudinal,a.longitudinal,r.t),lateral:Sn(o.lateral,a.lateral,r.t),vertical:Sn(o.vertical,a.vertical,r.t),yaw:Sn(o.yaw,a.yaw,r.t)}}function $o(e,t,r,n){let o=e.travelSurface;if(!o||o.rackMm.length<2||o.rows.length===0)return Go(e,t);let a=Ix(o,r),s=Ix(o,n),i=(p,d,h)=>{let b=o.rows[d.lo][p].steerDeg[h];return d.lo===d.hi?b:Sn(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=Sn(o.rackMm[d],o.rackMm[p],b)}return{innerDeg:Bo(o,"inner","steerDeg",a,m),outerDeg:Bo(o,"outer","steerDeg",s,m),innerCamber:Bo(o,"inner","camberDeg",a,m),outerCamber:Bo(o,"outer","camberDeg",s,m),innerLift:Bo(o,"inner","liftMm",a,m),outerLift:Bo(o,"outer","liftMm",s,m),innerJacobian:_x(o,"inner",a,m),outerJacobian:_x(o,"outer",s,m),atLock:f}}function Go(e,t){let r=e.meanDeg.length-1;return{innerDeg:Zt(e.meanDeg,e.innerDeg,t),outerDeg:Zt(e.meanDeg,e.outerDeg,t),innerCamber:Zt(e.meanDeg,e.innerCamber,t),outerCamber:Zt(e.meanDeg,e.outerCamber,t),innerLift:e.innerLift?Zt(e.meanDeg,e.innerLift,t):0,outerLift:e.outerLift?Zt(e.meanDeg,e.outerLift,t):0,...e.innerJacobian&&e.outerJacobian?{innerJacobian:jc(e.meanDeg,e.innerJacobian,t),outerJacobian:jc(e.meanDeg,e.outerJacobian,t)}:{},atLock:r>=0&&t>e.meanDeg[r]}}var YC=()=>({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 Ko(e,t,r=Ce(e),n){let o=e.steerFront;if(!o?.innerLift||!o.outerLift||o.meanDeg.length<2||Math.abs(t)<1e-12)return YC();let a=Math.abs(t),s=t>0,i=n&&o.travelSurface?$o(o,a,s?n.FL:n.FR,s?n.FR:n.FL):null,c=i?.innerLift??Zt(o.meanDeg,o.innerLift,a),l=i?.outerLift??Zt(o.meanDeg,o.outerLift,a),u=s?c:l,m=s?l:c,f=.5*(u+m),p=r.rollWheelRateFront,d=r.rollWheelRateRear,h=e.trackFront,b=e.trackRear,g=p*h*h+d*b*b,y=g>0?p*h*(m-u)/g:0,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 Dd(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 is=9.81;function Ho(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?Yr(e,t,r,Co(e,n,o)):Fo(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 Ed(e,t,r=0,n=0,o=0){if(!e.aero?.model||t<=0)return!1;let a=Yr(e,t,r,Co(e,n,o));return a!=null&&(a.clampedRide||a.clampedAttitude)}function An(e){let t=e.loadFactor===void 0?e.massTotal*is:e.massTotal*is*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 Nx(e,t=Ce(e),r=e.cgHeight){let n=e.trackFront/1e3,o=e.trackRear/1e3,a=e.rcHeightFront/1e3,s=e.rcHeightRear/1e3,i=(e.rcHeightFront+(e.rcHeightRear-e.rcHeightFront)*(1-e.frontMassFrac))/1e3,c=r/1e3-i,l=2*e.unsprungPerCorner,u=e.unsprungCgHeight/1e3,m=t.sprungMass*c*Mc(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 Id(e){let{cf:t,cr:r}=Nx(e);return t+r>0?t/(t+r):.5}function Ox(e,t,r){if(e.FL>=0&&e.FR>=0&&e.RL>=0&&e.RR>=0)return{loads:{FL:Math.max(0,e.FL),FR:Math.max(0,e.FR),RL:Math.max(0,e.RL),RR:Math.max(0,e.RR)},lifted:{FL:!1,FR:!1,RL:!1,RR:!1},overturned:!1};let n=e.FL+e.FR+e.RL+e.RR;if(!(n>0))return{loads:{FL:0,FR:0,RL:0,RR:0},lifted:{FL:!0,FR:!0,RL:!0,RR:!0},overturned:!0};let o=!1,a=e.FL+e.FR,s=e.RL+e.RR;a<0?(a=0,s=n,o=!0):s<0&&(s=0,a=n,o=!0);let i=(e.FR-e.FL)*t+(e.RR-e.RL)*r,c=Math.min(a,Math.max(-a,e.FR-e.FL)),l=Math.min(s,Math.max(-s,e.RR-e.RL)),u=i-(c*t+l*r);if(u!==0){let f=u>0?1:-1,p=(f*a-c)*t;f*u>=f*p?(c=f*a,u-=p):(c+=u/t,u=0);let d=(f*s-l)*r;u!==0&&(f*u>=f*d?(l=f*s,u-=d):(l+=u/r,u=0)),Math.abs(u)>1e-9*(Math.abs(i)+n*(t+r))&&(o=!0)}let m={FL:Math.max(0,(a-c)/2),FR:Math.max(0,(a+c)/2),RL:Math.max(0,(s-l)/2),RR:Math.max(0,(s+l)/2)};return{loads:m,lifted:{FL:m.FL===0,FR:m.FR===0,RL:m.RL===0,RR:m.RR===0},overturned:o}}function Le(e,t,r,n=0,o=0,a=0,s,i){return Uc(e,t,r,n,o,a,s,i).loads}function Uc(e,t,r,n=0,o=0,a=0,s,i){let c=An(e),l=Ce(e),u=Ec(e,n,r,Co(e,t,o),l),{cf:m,cr:f}=Nx(e,l,u.height),p=m*t*is,d=f*t*is,h=e.massTotal*(r*is)*u.height/e.wheelbase-u.noseLoad,b=Ho(e,n,r,t,o),g=(i??Ko(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 Ox(y,e.trackFront,e.trackRear)}var _d=Math.PI/180;function qc(e,t){let r=8*_d,n=0,o=0;for(let a=1;a<=90;a++){let s=a*.5,i=Math.abs(e.Fy(s*_d,t,0));if(i>n&&(n=i,r=s*_d,o=a),a>o+12&&i<.995*n)break}return{aPeak:r,fyPeak:n}}function Vx(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 ls=.999;function Mt(e,t,r,n,o){if(t<=0)return 0;let{aPeak:a,fyPeak:s}=o??qc(e,t),i=Math.min(Math.abs(r),ls*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,k=NaN,F=f;for(let w=0;w<9;w++){let C=.5*(v+x),T=l(C,a);T>=i?(v=C,k=T):(x=C,F=T)}Number.isNaN(k)&&(k=l(0,a)),m=k<i?0:Vx(v,k,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,k=a,F=NaN,w=NaN;for(let C=0;C<5;C++){let T=.5*(x+k),S=l(v,T);S<i?(x=T,F=S):(k=T,w=S)}return Number.isNaN(F)&&(F=l(v,0)),Number.isNaN(w)&&(w=l(v,a)),c*e.forces({Fz:t,kappa:c*v,alpha:Vx(x,F,k,w,i)}).Fx},d=4,h=v=>m*v/d,b=[0],g=1;for(let v=1;v<=d;v++)b.push(p(h(v))),b[v]>b[g]&&(g=v);let[y,R]=g===d?[d-1,d-2]:b[g-1]>=b[g+1]?[g-1,g+1]:[g+1,g-1],M=XC(p,h(g-1),h(Math.min(d,g+1)),h(g),b[g],h(y),b[y],h(R),b[R],WC);return c*Math.max(0,M)}var WC=.01,jC=20,UC=(3-Math.sqrt(5))/2;function XC(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<jC;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),M=(n-i)*R-(n-a)*y;R=2*(R-y),R>0&&(M=-M),R=Math.abs(R);let v=u;if(u=m,Math.abs(M)<Math.abs(.5*R*v)&&M>R*(t-n)&&M<R*(r-n)){m=M/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=UC*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 Vd(e,t){return e.model?.kind==="simple"?null:Gx(e,t)}var Bx=new WeakMap,Nd=100,$x=1.35,Od=18,Jt=41,Xc=41,cs=65;function Gx(e,t){let r=Bx.get(e);if(r)return r;let n=Math.log($x),o=(p,d)=>{let h=k=>Math.abs(Mt(e,p,k,d)),b=h(0),g=t.muY(p)*p,y=new Float64Array(Jt),R=b>0&&g>0?Math.max(1,t.muX(p)*p/b):1;if(!(b>0)||!(g>0))y.fill(1);else{let k=[],F=[];for(let C=0;C<Xc;C++){let T=Math.sin(.5*Math.PI*C/(Xc-1));k.push(T),F.push(C===0?1:C===Xc-1?0:Math.min(F[C-1],h(T*g)/b))}let w=Xc-1;for(let C=0;C<Jt;C++){let T=C/(Jt-1);for(;w>0&&F[w-1]<T;)w--;let S=w>0?F[w-1]-F[w]:0;y[C]=w===0?k[0]:k[w]+(S>0?(T-F[w])/S:0)*(k[w-1]-k[w])}y[0]=1,y[Jt-1]=0}let M=new Float64Array(cs),v=k=>Math.atan2(y[k],k/(Jt-1)/R),x=Jt-2;for(let k=0;k<cs;k++){let F=.5*Math.PI*k/(cs-1),w=Math.cos(F),C=Math.sin(F);for(;x>0&&v(x)<F;)x--;let T=x/(Jt-1)/R,S=y[x],A=(x+1)/(Jt-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);M[k]=D>0?D:Math.hypot(T,S)}return{room:y,scale:R,edge:M}},a=Array.from({length:Od},(p,d)=>Nd*$x**d),s=a.map(p=>o(p,!1)),i=a.map(p=>o(p,!0)),c=(p,d)=>{let h=Math.min(1,Math.abs(d)*p.scale)*(Jt-1),b=Math.min(Jt-2,Math.floor(h));return p.room[b]+(h-b)*(p.room[b+1]-p.room[b])},l=p=>{let d=p>Nd?Math.log(p/Nd)/n:0;if(d>=Od-1)return[Od-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)*(cs-1),M=Math.min(cs-2,Math.floor(R)),v=k=>k.edge[M]+(R-M)*(k.edge[M+1]-k.edge[M]),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 Bx.set(e,f),f}var qC=[["front","FL","FR"],["rear","RL","RR"]];function zo(e,t,r,n){let o={...e},a=0,s=ls;for(let[i,c,l]of qC){let u=(M,v)=>n(i,Math.max(0,v[M])).fyPeak,m=Math.min(s,e[c]),f=Math.min(s,e[l]),p=m*u(c,r)+f*u(l,r);if(!(p>0))continue;let d=u(c,t),h=u(l,t),b=m*d+f*h,g=b>0?p/b:1/0,y=m*g,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 Kx=.001,QC=1e-5,Hx=100;function ZC(e,t,r,n){if(!(n>Kx))return r;let o=t,a=Math.abs(r-t)<Hx?t+Math.sign(r-t)*Hx:r;for(let s=0;s<60&&Math.abs(a-o)>QC;s++){let i=.5*(o+a);e(i)>Kx?a=i:o=i}return o}function Qc(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=ZC(e,t,o,e(o));return a!==o&&(n=a),a},edge:()=>n}}function Zc(e,t){let r=n=>{try{return ge(e,0,n).ok}catch{return!1}};for(let n of[1,-1]){if(r(n*t))continue;let o=0;for(let a=1;a<=6;a++){let s=n*t*a/6;if(!r(s))break;o=Math.abs(s)}return{lock:t,reached:o,side:n}}return null}var Bd=40;function Jc(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 zx=[0,0,0];function JC(e,t){let r=q(H(e.rockerPivotB,e.rockerPivotA)),n=q(H(e.rockerToPushrod,e.pushrodOuter)),o=q(H(e.damperChassis,e.rockerToDamper)),a=Math.abs(X(r,ae(H(e.rockerToPushrod,e.rockerPivotA),n))),s=Math.abs(X(r,ae(H(e.rockerToDamper,e.rockerPivotA),o)));return s<1e-9?0:t*a/s}function el(e,t,r){if(e.mcpherson)return eT(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??zx,c=[-t[0],-t[1],-t[2],-(s[0]+i[0]),-(s[1]+i[1]),-(s[2]+i[2])],l=qt(a,c),u=l.x;return{ucaFront:u[0],ucaRear:u[1],lcaFront:u[2],lcaRear:u[3],tieRod:u[4],pushRod:u[5],damper:l.singular||e.decoupled?NaN:e.direct?u[5]:JC(e,u[5]),condProxy:l.condProxy,singular:l.singular}}function eT(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??zx,l=[-t[0],-t[1],-t[2],-(i[0]+c[0]),-(i[1]+c[1]),-(i[2]+c[2])],u=qt(s,l),m=u.x,f=[m[3],m[4],m[5]],p=q(H(o,e.pushrodOuter)),d=X(f,p),h=Math.hypot(f[0]-d*p[0],f[1]-d*p[1],f[2]-d*p[2]);return{ucaFront:NaN,ucaRear:NaN,lcaFront:m[0],lcaRear:m[1],tieRod:m[2],pushRod:u.singular?NaN:d,damper:u.singular?NaN:d,condProxy:u.condProxy,singular:u.singular,strutSide:u.singular?NaN:h,topMount:f}}function $d(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 tT=[0,0,0];function us(e,t,r,n){let o=e.direct?e.damperChassis:e.rockerToPushrod;if(e.mcpherson)return{...el(e,r,n),armResidual:0};if(t==="upright")return{...el(e,r,n),armResidual:0};let a=t==="lowerArm",s=a?{bj:e.uprightUpper,front:e.ucaFront,rear:e.ucaRear}:{bj:e.uprightLower,front:e.lcaFront,rear:e.lcaRear},i=a?{bj:e.uprightLower,front:e.lcaFront,rear:e.lcaRear}:{bj:e.uprightUpper,front:e.ucaFront,rear:e.ucaRear},c=e.wheelCenter,l=q(H(s.front,s.bj)),u=q(H(s.rear,s.bj)),m=q(H(e.tieInner,e.tieOuter)),f=[{at:s.bj,dir:l},{at:s.bj,dir:u},{at:e.tieOuter,dir:m},{at:i.bj,dir:[1,0,0]},{at:i.bj,dir:[0,1,0]},{at:i.bj,dir:[0,0,1]}],p=[[],[],[],[],[],[]];for(let Q=0;Q<6;Q++){let ne=f[Q].dir,te=ae(H(f[Q].at,c),ne);p[0][Q]=ne[0],p[1][Q]=ne[1],p[2][Q]=ne[2],p[3][Q]=te[0],p[4][Q]=te[1],p[5][Q]=te[2]}let d=ae(H(e.contactPatch,c),r),h=n??tT,b=[-r[0],-r[1],-r[2],-(d[0]+h[0]),-(d[1]+h[1]),-(d[2]+h[2])],g=qt(p,b),y=g.singular,R=g.x,M=R[0],v=R[1],x=R[2],k=[R[3],R[4],R[5]],F=q(H(i.rear,i.front)),w=q(H(o,e.pushrodOuter)),C=U(k,-1),T=(Q,ne)=>X(F,ae(H(Q,i.front),ne)),S=T(e.pushrodOuter,w),A=Math.abs(S)>1e-9?-T(i.bj,C)/S:NaN,P=ee(C,U(w,A)),L=U(P,-1),D=q(H(i.front,i.bj)),I=q(H(i.rear,i.bj)),G=X(D,D),O=X(D,I),W=X(I,I),E=X(D,L),_=X(I,L),V=G*W-O*O,N=NaN,$=NaN,K=NaN;if(Math.abs(V)>1e-12){N=(E*W-_*O)/V,$=(G*_-O*E)/V;let Q=ee(U(D,N),U(I,$)),ne=H(L,Q);K=Math.hypot(ne[0],ne[1],ne[2])}let z=a?{f:M,r:v}:{f:N,r:$},j=a?{f:N,r:$}:{f:M,r:v};return{ucaFront:z.f,ucaRear:z.r,lcaFront:j.f,lcaRear:j.r,tieRod:x,pushRod:A,damper:y||!Number.isFinite(A)||e.decoupled?NaN:e.direct?A:rT(e,A),condProxy:g.condProxy,singular:y,armResidual:K}}function rT(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 U$=Math.PI/180;function ms(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 Wx=["QSX3","QSX8","QSX13","QSX14"],nT=["QSX1"],tl=["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",...Wx];function oT(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 aT(e){let t=new Set(oT(e)),r=tl.filter(n=>!Wx.includes(n));return[...r.filter(n=>!t.has(n)),...[...t].filter(n=>!r.includes(n)),...nT]}function sT(e,t){let r={...e};for(let n of t)r[n]!==void 0&&r[n]!==0&&(r[n]=-r[n]);return r}var yr=(e,t,r)=>Number.isFinite(e[t])?e[t]:r;function jx(e,t){return t!=="5.2"?yr(e,"PKY6",0)*yr(e,"LKYC",1):yr(e,"PKY1",-15)*Math.sin(yr(e,"PKY4",2)*Math.atan(1/yr(e,"PKY2",2)))*yr(e,"LKY",1)*yr(e,"PHY3",0)+yr(e,"PVY3",0)*yr(e,"LMUY",1)}var Yx=.1;function Ux(e){if(e.fitData)return"sae";let t=jx(e.coeffs,e.version);return t>Yx?"sae":t<-Yx?"iso":null}function ps(e){return e.axisSystem??Ux(e)??"sae"}function rl(e){let t=new Set,r=n=>{for(let o of n)t.has(o)?t.delete(o):t.add(o)};return ps(e)==="iso"&&r(tl),e.axisSystem&&e.side==="left"&&r(aT(e.version)),t.size?sT(e.coeffs,t):e.coeffs}var q$=Math.PI/180;var B=(e,t)=>Number.isFinite(e)?e:t;function qx(e){let t=rl(e);return{PCX1:B(t.PCX1,1.65),PDX1:B(t.PDX1,1),PDX2:B(t.PDX2,0),PDX3:B(t.PDX3,0),PEX1:B(t.PEX1,0),PEX2:B(t.PEX2,0),PEX3:B(t.PEX3,0),PEX4:B(t.PEX4,0),PHX1:B(t.PHX1,0),PHX2:B(t.PHX2,0),PKX1:B(t.PKX1,20),PKX2:B(t.PKX2,0),PKX3:B(t.PKX3,0),PPX1:B(t.PPX1,0),PPX2:B(t.PPX2,0),PPX3:B(t.PPX3,0),PPX4:B(t.PPX4,0),PVX1:B(t.PVX1,0),PVX2:B(t.PVX2,0),PCY1:B(t.PCY1,1.3),PDY1:B(t.PDY1,1),PDY2:B(t.PDY2,0),PDY3:B(t.PDY3,0),PEY1:B(t.PEY1,0),PEY2:B(t.PEY2,0),PEY3:B(t.PEY3,0),PEY4:B(t.PEY4,0),PEY5:B(t.PEY5,0),PHY1:B(t.PHY1,0),PHY2:B(t.PHY2,0),PHY3:B(t.PHY3,0),PKY1:B(t.PKY1,-15),PKY2:B(t.PKY2,2),PKY3:B(t.PKY3,0),PKY4:B(t.PKY4,2),PKY5:B(t.PKY5,0),PKY6:B(t.PKY6,0),PKY7:B(t.PKY7,0),PPY1:B(t.PPY1,0),PPY2:B(t.PPY2,0),PPY3:B(t.PPY3,0),PPY4:B(t.PPY4,0),PPY5:B(t.PPY5,0),PVY1:B(t.PVY1,0),PVY2:B(t.PVY2,0),PVY3:B(t.PVY3,0),PVY4:B(t.PVY4,0),RBX1:B(t.RBX1,0),RBX2:B(t.RBX2,0),RBX3:B(t.RBX3,0),RBY1:B(t.RBY1,0),RBY2:B(t.RBY2,0),RBY3:B(t.RBY3,0),RBY4:B(t.RBY4,0),RCX1:B(t.RCX1,1),RCY1:B(t.RCY1,1),REX1:B(t.REX1,0),REX2:B(t.REX2,0),REY1:B(t.REY1,0),REY2:B(t.REY2,0),RHX1:B(t.RHX1,0),RHY1:B(t.RHY1,0),RHY2:B(t.RHY2,0),RVY1:B(t.RVY1,0),RVY2:B(t.RVY2,0),RVY3:B(t.RVY3,0),RVY4:B(t.RVY4,0),RVY5:B(t.RVY5,1),RVY6:B(t.RVY6,0),PPZ1:B(t.PPZ1,0),PPZ2:B(t.PPZ2,0),QBZ1:B(t.QBZ1,8),QBZ2:B(t.QBZ2,0),QBZ3:B(t.QBZ3,0),QBZ4:B(t.QBZ4,0),QBZ5:B(t.QBZ5,0),QBZ6:B(t.QBZ6,0),QBZ9:B(t.QBZ9,0),QBZ10:B(t.QBZ10,0),QCZ1:B(t.QCZ1,1.1),QDZ1:B(t.QDZ1,.1),QDZ2:B(t.QDZ2,0),QDZ3:B(t.QDZ3,0),QDZ4:B(t.QDZ4,0),QDZ6:B(t.QDZ6,0),QDZ7:B(t.QDZ7,0),QDZ8:B(t.QDZ8,0),QDZ9:B(t.QDZ9,0),QDZ10:B(t.QDZ10,0),QDZ11:B(t.QDZ11,0),QEZ1:B(t.QEZ1,0),QEZ2:B(t.QEZ2,0),QEZ3:B(t.QEZ3,0),QEZ4:B(t.QEZ4,0),QEZ5:B(t.QEZ5,0),QHZ1:B(t.QHZ1,0),QHZ2:B(t.QHZ2,0),QHZ3:B(t.QHZ3,0),QHZ4:B(t.QHZ4,0),SSZ1:B(t.SSZ1,0),SSZ2:B(t.SSZ2,0),SSZ3:B(t.SSZ3,0),SSZ4:B(t.SSZ4,0),QSX1:B(t.QSX1,0),QSX2:B(t.QSX2,0),QSX3:B(t.QSX3,0),QSX4:B(t.QSX4,0),QSX5:B(t.QSX5,0),QSX6:B(t.QSX6,0),QSX7:B(t.QSX7,0),QSX8:B(t.QSX8,0),QSX9:B(t.QSX9,0),QSX10:B(t.QSX10,0),QSX11:B(t.QSX11,0),QSX12:B(t.QSX12,0),QSX13:B(t.QSX13,0),QSX14:B(t.QSX14,0),PPMX1:B(t.PPMX1,0),QSY1:B(t.QSY1,0),QSY2:B(t.QSY2,0),QSY3:B(t.QSY3,0),QSY4:B(t.QSY4,0),QSY5:B(t.QSY5,0),QSY6:B(t.QSY6,0),QSY7:B(t.QSY7,0),QSY8:B(t.QSY8,0),LONGVL:t.LONGVL!==void 0&&t.LONGVL>0?t.LONGVL:16.7,LCX:B(t.LCX,1),LCY:B(t.LCY,1),LEX:B(t.LEX,1),LEY:B(t.LEY,1),LFZO:B(t.LFZO,1),LHX:B(t.LHX,1),LHY:B(t.LHY,1),LKX:B(t.LKX,1),LKY:B(t.LKY,1),LKYC:B(t.LKYC,1),LKZC:B(t.LKZC,1),LMUX:B(t.LMUX,1),LMUY:B(t.LMUY,1),LMX:B(t.LMX,1),LMY:B(t.LMY,1),LVMX:B(t.LVMX,1),LRES:B(t.LRES,1),LS:B(t.LS,1),LTR:B(t.LTR,1),LVX:B(t.LVX,1),LVY:B(t.LVY,1),LVYKA:B(t.LVYKA,1),LXAL:B(t.LXAL,1),LYKA:B(t.LYKA,1)}}var Xx=new WeakMap;function ds(e){let t=Xx.get(e);return t===void 0&&(t=qx(e),Xx.set(e,t)),t}var Qx=e=>e>=0?1:-1;function nl(e,t,r=0,n){let o=ds(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,M=h?a*(o.PVY1+o.PVY2*c)*o.LVY*o.LMUY+g:a*((o.PVY1+o.PVY2*c)*o.LVY+(o.PVY3+o.PVY4*c)*s)*o.LMUY,v=f*p!==0?d/(f*p):0;return{Fz:a,g:s,dfz:c,dpi:l,Fz0p:i,R0:u,Cy:f,Dy:p,By:v,SHy:R,SVy:M,Kya:d,muy:m,EyA:o.PEY1+o.PEY2*c,EyG:1+o.PEY5*s*s,EyS:o.PEY3+o.PEY4*s,LEY:o.LEY}}function ol(e,t,r=0,n){let o=nl(e,t,r,n),a=ds(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,M=(a.PDX1+a.PDX2*c)*(1+a.PPX3*l+a.PPX4*l*l)*(1-a.PDX3*i*i)*a.LMUX,v=a.PCX1*a.LCX,x=M*s,k=s*(a.PKX1+a.PKX2*c)*Math.exp(a.PKX3*c)*(1+a.PPX1*l+a.PPX2*l*l)*a.LKX,F=v*x!==0?k/(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:k/w*(k/w),sS0:m*(a.SSZ1+(a.SSZ3+a.SSZ4*c)*i)*a.LS,sS2:m*a.SSZ2*a.LS/u}}function fs(e,t){let r=t+e.SHy,n=e.EyA*(e.EyG-e.EyS*Qx(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 al(e,t){let r=t+e.SHx,n=e.ExA*(1-e.PEX4*Qx(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 Zx(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 iT(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=Zx(e,o,r),i=e.Bt*s;return e.Dt*Math.cos(e.Ct*Math.atan(i-a*(i-Math.atan(i))))*n}function cT(e,t,r,n){return e.Dr*Math.cos(Math.atan(e.Br*Zx(e,t+e.SHy+e.arOff,r)))*n}function Jx(e,t,r,n,o,a){let s=Math.cos(t),i=iT(e,t,r,s),c=cT(e,t,r,s);return-i*(o-a)+c+(e.sS0+e.sS2*o)*n}function eR(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*al(e,t)}function Gd(e,t){let r=e.sS0===0&&e.sS2===0?0:eR(e,0,t);return Jx(e,t,0,r,fs(e,t),0)}function sl(e,t,r){let n=fs(e,r),o=eR(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:Jx(e,r,t,o,m,u)}}var hs=(e,t)=>Math.max(.1,e.muY0+e.loadSensY*(t-e.nominalLoad)),bs=(e,t)=>Math.max(.1,e.muX0+e.loadSensX*(t-e.nominalLoad)),tR=(e,t,r)=>hs(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cy*Math.atan(e.By*r)),rR=(e,t,r)=>bs(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cx*Math.atan(e.Bx*r));function Kd(e,t){let r=Math.max(1,t.Fz),n=hs(e,r)*r,o=bs(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 il=Math.PI/180;function Zr(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 nR(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?ms(r,t):1,s=n?ms(n,t):1,i=o?ms(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 Yo(e,t,r){let n=0,o=0;for(let s=r;s<=t;s+=r){let i=Math.abs(e(s));i>o&&(o=i,n=s)}let a=r/10;for(let s=Math.max(a,n-r);s<=n+r;s+=a)o=Math.max(o,Math.abs(e(s)));return o}function Ie(e){let t=nR(e),r=t,n=t,o=null,a=NaN,s=NaN,i=NaN,c=(v,x,k)=>(o!==null&&v===a&&x===s&&k===i||(o=ol(r,v,x,k),a=v,s=x,i=k),o),l=null,u=NaN,m=NaN,f=NaN,p=(v,x,k)=>(l!==null&&v===u&&x===m&&k===f||(l=nl(r,v,x,k),u=v,m=x,f=k),l),d=v=>e.kind==="magic"?sl(c(v.Fz,v.gamma??0,v.p),v.kappa,v.alpha):Kd(n,v),h=(v,x,k=0,F)=>e.kind==="magic"?fs(p(x,k,F),v):tR(n,x,v),b=(v,x,k=0,F)=>e.kind==="magic"?al(c(x,k,F),v):rR(n,x,v),g=(v,x,k=0,F)=>e.kind==="magic"?Gd(c(x,k,F),v):d({Fz:x,kappa:0,alpha:v,gamma:k,p:F}).Mz,y=v=>e.kind==="simple"?hs(n,v):Yo(x=>h(x*il,v),45,1)/Math.max(1,v),R=v=>e.kind==="simple"?bs(n,v):Yo(x=>b(x,v),.6,.02)/Math.max(1,v),M=v=>{let x=.1*il;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:M,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 k=e.verticalStiffness*1e3;if(!(k>0))return x;let F=e.rollingFraction??.306;return x-F*Math.max(0,v)/k},relaxationLength:v=>{let x=e.relaxation;if(!x)return 0;let k=x.carcassStiffness??0;if(!(k>0))return x.sigma;let F=M(Math.max(0,v));return F>0?F/(k*1e3):x.sigma}}}function Wo(e){let t=Math.max(1,e.model.kind==="magic"?e.model.fnomin:e.model.nominalLoad);return e.Fy(2*il,t,0)-e.Fy(-2*il,t,0)>=0?1:-1}var lT=Math.PI/180;function xe(e,t){return e.axle?e.axle(t):e}function ll(e,t){if(e===t)return e;let r=Wo(e)*Wo(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=>Yo(u=>s(u,l),.6,.02)/Math.max(1,l),muY:l=>Yo(u=>i(u*lT,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 ct(e){if(oR.has(e))return e;let t=aR.get(e);if(t)return t;let r;if(e.axle){let n=e.axle("front"),o=e.axle("rear"),a=ct(n),s=ct(o);r=a===n&&s===o?e:ll(a,s)}else Wo(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 oR.add(r),r!==e&&aR.set(e,r),r}var oR=new WeakSet,aR=new WeakMap;var ul=25*(Math.PI/180);function uT(e){let t=.6180339887,r=0,n=ul,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 gs(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=ul;if(s(ul)<=a){let u=uT(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(ul,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 Hd={shaft:!1,trail:0,hub:[0,0,0]};function iR(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 zd(e,t,r){let n=r.shaft?$d(e,t):[0,0,0];if(r.trail!==0){let a=iR(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 mT=(e,t)=>{let r=e!==void 0&&e>0?1/e:0,n=t!==void 0&&t>0?1/t:0;return r+n},ml={ucaFront:0,ucaRear:0,lcaFront:0,lcaRear:0,tieRod:0,pushRod:0,rack:0};function Fn(e){return!e.measured}function wn(e){if(!e)return!1;let t=r=>!!r&&Object.values(r).some(n=>n!==void 0&&n>0&&Number.isFinite(n));return t(e.links)||t(e.bushings)||e.rack!==void 0&&e.rack>0}function ys(e,t){let r=e.corner.hardpoints,n=Ua(e.rocker,t.points.rockerAngle);return{ucaFront:r.ucaFront,ucaRear:r.ucaRear,lcaFront:r.lcaFront,lcaRear:r.lcaRear,tieInner:To(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 Yd(e,t,r=0){let n=t.links??{},o=t.bushings??{},a=(l,u,m)=>{let f=mT(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 cR(e,t,r,n){let o=ve(e,t);if(!(o>1e-9))return{axial:r,radius2:0};let a=(r*r-n*n+o*o)/(2*o);return{axial:a,radius2:Math.max(0,r*r-a*a)}}function xs(e,t){let r=e.corner.hardpoints,n=e.inv,o={...n};if(n.strut&&t.topMount&&t.topMount.some(i=>i!==0)&&(o.strut={...n.strut,top:ee(n.strut.top,t.topMount)}),t.ucaFront!==0||t.ucaRear!==0){let i=cR(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=cR(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 pT=8,dT=1e-5,fT=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 Wd(e,t,r){let n=zd(e,r.force,r.extras??Hd),o=r.alignMoment?ee(n.moment,[0,0,r.alignMoment]):n.moment;return us(e,t,n.force,o)}function dl(e,t,r,n,o,a,s=0){let i=Ee(e,t,r,o,a),c=e.corner.compliance;if(!(wn(c)&&Fn(e.corner)))return{state:i,forces:Wd(ys(e,i),e.corner.config.pushrodAttach,n),deflection:ml,rigid:i,iterations:0,converged:!0,bypassed:!0};let u=i,m=e,f=e.corner.config.pushrodAttach,p=Wd(ys(e,i),f,n),d=ml,h=!1,b=0;for(;b<pT;b++){let g=ys(m,u);if(p=Wd(g,f,n),p.singular)break;d=Yd(p,c,s),m=xs(e,d);let y=Ee(m,t,r,fT(u),a),R=ve(y.points.wheelCenter,u.points.wheelCenter);if(u=y,R<dT){h=!0;break}}return{state:u,forces:p,deflection:d,rigid:i,iterations:b+1,converged:h&&u.converged,bypassed:!1}}var pl=1e3,lR=1e5;function uR(e,t,r,n,o){let a=dl(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 fl(e,t,r,n,o){let a={force:[0,0,n]},s=(b,g=0)=>uR(e,t,r,{force:b,alignMoment:g},o),i=uR(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,pl,n]),l=s([0,-pl,n]),u=s([pl,0,n]),m=s([-pl,0,n]),f=s([0,0,n],lR),p=s([0,0,n],-lR),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 hT=1e3;function jd(e,t=hT){if(!wn(e.compliance)||!Fn(e))return;let r=et(e),n=Ee(r,0,0),o=fl(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 jo(e,t=-Bd,r=Bd,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=qe(e,{travelMin:t,travelMax:r,steps:n}),s=jd(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 hl(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 Jr(e,t){return{motionRatio:hl(e.travel,e.motionRatio,t),camber:hl(e.travel,e.camber,t),toe:hl(e.travel,e.toe,t),damperLen:hl(e.travel,e.damperLen,t)}}var mR=Math.PI/180,bT=9.81;function Uo(e,t,r,n=0){let o=Ce(e),a=e.wheelbase*(1-e.frontMassFrac),s=e.wheelbase*e.frontMassFrac,i=Ho(e,n),c=e.aero?.model?(M,v,x)=>Ho(e,n,v,M,x):()=>i,l=Jr(t,0),u=Jr(r,0),m=e.loadFactor,f=m!==void 0&&m!==1?(m-1)*e.massTotal*bT:0,p=f*e.frontMassFrac/2,d=f*(1-e.frontMassFrac)/2,h=(M,v)=>v>0&&Number.isFinite(v)&&M+v>0?v/(M+v):1,b=Ue(e,"front"),g=Ue(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(M,v,x=0,k=0)=>{let F=c(M,v,x),w=o.rollGradient*M,C=w*mR,T=o.pitchGradient*v*mR,S=(G,O)=>{let W=O==="F"?e.trackFront:e.trackRear,E=O==="F"?o.rideRateFront:o.rideRateRear,_=(G==="R"?1:-1)*(W/2)*Math.tan(C),V=(O==="R"?s:-a)*Math.tan(T),N=`${O}${G}`,$=f?F[N]+(O==="F"?p:d):F[N],K=E>0?$/E:0;return{anti:_,sym:V+K}},A={FL:S("L","F"),FR:S("R","F"),RL:S("L","R"),RR:S("R","R")},P=G=>{let O=G[0];return A[G].sym*y[O]+A[G].anti*R[O]},L=Ko(e,k,o,{FL:P("FL"),FR:P("FR")}),D=w+L.rollDeg,I=(G,O)=>{let W=O==="F"?t:r,E=O==="F"?l:u,_=`${O==="F"?"F":"R"}${G}`,V=A[_].sym+A[_].anti+L.travel[_],N=P(_)+L.travel[_]*R[O],$=V-N,K=Jr(W,N),z=(G==="R"?1:-1)*K.camber;return{travel:N,tyre:$,ground:V,camber:z,camberRoad:z+D,toe:K.toe,bumpToe:K.toe-E.toe,damperTravel:E.damperLen-K.damperLen}};return{FL:I("L","F"),FR:I("R","F"),RL:I("L","R"),RR:I("R","R"),steeringJacking:L}}}var Ud=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function Cn(e){return{enabled:e?.enabled===!0,roadFeedbackGain:Math.min(2,Math.max(0,Ud(e?.roadFeedbackGain,1))),turnInFrictionNm:Math.max(0,Ud(e?.turnInFrictionNm,0)),columnStiffnessNmPerRad:Math.max(0,Ud(e?.columnStiffnessNmPerRad,0))}}function Xd(e,t,r){let n=Cn(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 pR=()=>({totalNm:0,aligningNm:0,lateralNm:0,longitudinalNm:0,jackingNm:0});function Tn(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 Rs(e,t,r,n="model",o){let a=e.steerFront;if(!Tn(e)||!a)return null;let s=t<0?-1:1,c=a.rackRatioMmPerRev/(2*Math.PI)/1e3,l=t>=0,u=o&&a.travelSurface?$o(a,Math.abs(t),l?o.FL:o.FR,l?o.FR:o.FL):Go(a,Math.abs(t));if(!u.innerJacobian||!u.outerJacobian)return null;let m=(b,g)=>{let y=r[b],R=b==="FL"?-1:1,M=-R*y.Fy,x={aligning:1e3*(-R*y.Mz)*g.yaw,lateral:M*g.lateral,longitudinal:y.Fx*g.longitudinal,jacking:y.Fz*g.vertical},k=pR();k.aligningNm=-s*x.aligning*c,k.lateralNm=-s*x.lateral*c,k.longitudinalNm=-s*x.longitudinal*c,k.jackingNm=-s*x.jacking*c,k.totalNm=k.aligningNm+k.lateralNm+k.longitudinalNm+k.jackingNm;let F=-s*(x.aligning+x.lateral+x.longitudinal+x.jacking);return{moment:k,rackN:F}},f=m("FL",l?u.innerJacobian:u.outerJacobian),p=m("FR",l?u.outerJacobian:u.innerJacobian),d=pR();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=Xd(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 gT=e=>"front"in e&&"rear"in e;function Xo(e,t){return gT(e)?e[t]:e}function Qd(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 qd(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 dR(e,t,r){let n=qd(e,t),o=qd(e,r);return{left:n,right:o,fyRes:n.fyRes+o.fyRes}}function xr(e,t,r){let n=dR(Xo(e,"front"),t.FL,t.FR),o=dR(Xo(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 bl=[{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"}],xT=bl.flatMap(e=>[e.min,e.max]);function bR(e){return Math.max(1,e.kind==="magic"?e.fnomin:e.nominalLoad)}function fR(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 Ht(e){let t=hR.get(e);if(t!==void 0)return t;let r=10*bR(e.model),{turnover:n,collapse:o}=vT(e,r),a=n??o??r;return hR.set(e,a),a}var hR=new WeakMap;function vT(e,t){let r=bR(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=fR(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=fR(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 gR=["FL","FR","RL","RR"],kT=e=>e==="FL"||e==="RL",MT=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 gR)a[l]={...t[l]};let s=l=>{let u=0;for(let f of gR)MT(f)===e.axle&&(a[f].Fx=e.sense*(f===e.strong?l-e.open/2:e.open/2),u-=(kT(f)?o:-o)*a[f].Fx);let m=xr(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 ST=[["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]],AT=[["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]],FT=[["QBZ1","Trail slope factor for trail Bpt at Fznom",8],["QBZ2","Variation of slope Bpt with load",0],["QBZ3","Variation of slope Bpt with load squared",0],["QBZ4","Variation of slope Bpt with camber",0],["QBZ5","Variation of slope Bpt with absolute camber",0],["QBZ6","Camber influence Bt",0],["QBZ9","Factor for scaling factors of slope factor Br of Mzr",0],["QBZ10","Factor for dimensionless cornering stiffness of Br of Mzr",0],["QCZ1","Shape factor Cpt for pneumatic trail",1.1],["QDZ1","Peak trail Dpt = Dpt*(Fz/Fznom*R0)",.1],["QDZ2","Variation of peak Dpt with load",0],["QDZ3","Variation of peak Dpt with camber",0],["QDZ4","Variation of peak Dpt with camber squared",0],["QDZ6","Peak residual torque Dmr = Dmr/(Fz*R0)",0],["QDZ7","Variation of peak factor Dmr with load",0],["QDZ8","Variation of peak factor Dmr with camber",0],["QDZ9","Variation of peak factor Dmr with camber and load",0],["QDZ10","Variation of peak factor Dmr with camber squared",0],["QDZ11","Variation of Dmr with camber squared and load",0],["QEZ1","Trail curvature Ept at Fznom",0],["QEZ2","Variation of curvature Ept with load",0],["QEZ3","Variation of curvature Ept with load squared",0],["QEZ4","Variation of curvature Ept with sign of Alpha-t",0],["QEZ5","Variation of Ept with camber and sign Alpha-t",0],["QHZ1","Trail horizontal shift Sht at Fznom",0],["QHZ2","Variation of shift Sht with load",0],["QHZ3","Variation of shift Sht with camber",0],["QHZ4","Variation of shift Sht with camber and load",0],["PPZ1","Effect of inflation pressure on length of pneumatic trail",0],["PPZ2","Influence of inflation pressure on residual aligning torque",0],["SSZ1","Nominal value of s/R0: effect of Fx on Mz",0],["SSZ2","Variation of distance s/R0 with Fy/Fznom",0],["SSZ3","Variation of distance s/R0 with camber",0],["SSZ4","Variation of distance s/R0 with load and camber",0]],wT=[["RBX1","Slope factor for combined slip Fx reduction",0],["RBX2","Variation of slope Fx reduction with kappa",0],["RBX3","Influence of camber on stiffness for Fx combined",0],["RCX1","Shape factor for combined slip Fx reduction",1],["REX1","Curvature factor of combined Fx",0],["REX2","Curvature factor of combined Fx with load",0],["RHX1","Shift factor for combined slip Fx reduction",0],["RBY1","Slope factor for combined Fy reduction",0],["RBY2","Variation of slope Fy reduction with alpha",0],["RBY3","Shift term for alpha in slope Fy reduction",0],["RBY4","Influence of camber on stiffness of Fy combined",0],["RCY1","Shape factor for combined Fy reduction",1],["REY1","Curvature factor of combined Fy",0],["REY2","Curvature factor of combined Fy with load",0],["RHY1","Shift factor for combined Fy reduction",0],["RHY2","Shift factor for combined Fy reduction with load",0],["RVY1","Kappa induced side force Svyk/Muy*Fz at Fznom",0],["RVY2","Variation of Svyk/Muy*Fz with load",0],["RVY3","Variation of Svyk/Muy*Fz with camber",0],["RVY4","Variation of Svyk/Muy*Fz with alpha",0],["RVY5","Variation of Svyk/Muy*Fz with kappa",1],["RVY6","Variation of Svyk/Muy*Fz with atan(kappa)",0]],CT=[["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]],xR=[["lateral",ST],["longitudinal",AT],["aligning",FT],["combined",wT],["scaling",CT]].flatMap(([e,t])=>t.map(([r,n,o])=>({key:r,section:e,text:n,fallback:o}))),JG=new Map(xR.map(e=>[e.key,e]));var TT=/^\$\s*EDITED\s+([A-Z][A-Z0-9_]*)\s+was\s+(absent|[-+0-9.eE]+)\s*$/;function RR(e){let t={};for(let r of e.split(/\r?\n/)){let n=r.trim().match(TT);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 LT=/^\s*\$\s*UNLOADED_RADIUS_STAND_IN\s*=\s*([0-9.eE+-]+)/,DT=/^\$-+ written by (?:PaceDynamics|PaceLab)\b/m,ET=/^\$\s*AXIS_SYSTEM\s*=\s*(ISO-W|SAE)\b/m;function IT(e){let t=e.match(ET);return t?{axisSystem:t[1]==="SAE"?"sae":"iso",trustSide:!0}:DT.test(e)?{axisSystem:"sae",trustSide:!1}:{axisSystem:"iso",trustSide:!0}}function _T(e){return e>=62?"6.2":e>=61?"6.1":"5.2"}var vR=new Map([["pa",1],["pascal",1],["kpa",1e3],["kilopascal",1e3],["mpa",1e6],["megapascal",1e6],["bar",1e5],["psi",6894.757293168]]);function NT(e,t,r){let n=r.PRESSURE?.trim().toLowerCase(),o=n===void 0?1:vR.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 OT=new Map([["radians",1],["radian",1],["rad",1],["degrees",Math.PI/180],["degree",Math.PI/180],["deg",Math.PI/180]]);function VT(e,t){let r=(s,i)=>s===void 0?1:i.get(s.trim().toLowerCase()),n=r(t.ANGLE,OT),o={fz:1,kappa:1,alpha:n,gamma:n,p:r(t.PRESSURE,vR)},a={};for(let s of bl){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 vs(e,t="imported",r={}){let n=IT(e),o=r.axisSystem??n.axisSystem,a={},s={},i={},c="",l;for(let g of e.split(/\r?\n/)){let y=g.match(LT);y&&(l=parseFloat(y[1]));let R=g.replace(/[$!].*$/,"").trim();if(!R)continue;if(R.startsWith("[")){c=(R.match(/^\[([^\]]*)/)?.[1]??"").trim().toUpperCase();continue}let M=R.indexOf("=");if(M<0)continue;let v=R.slice(0,M).trim().toUpperCase(),x=R.slice(M+1).trim(),k=x.match(/^'([^']*)'|^"([^"]*)"/);if(k){s[v]=k[1]??k[2]??"",c==="UNITS"&&(i[v]=s[v]);continue}let F=parseFloat(x);Number.isFinite(F)&&(a[v]=F)}let u=_T(a.FITTYP??62),m=RR(e),f=m?Object.fromEntries(Object.entries(m).filter(([g])=>a[g]!==void 0)):void 0,p=a.VERTICAL_STIFFNESS??a.KZ??0,d=NT(a,s,i),h=VT(a,i),b=[];return a.UNLOADED_RADIUS===void 0&&a.R0===void 0&&b.push("UNLOADED_RADIUS"),p<=0&&b.push("VERTICAL_STIFFNESS"),a.FNOMIN===void 0&&b.push("FNOMIN"),d===void 0&&b.push("NOMPRES"),{kind:"magic",name:t,version:u,coeffs:a,axisSystem:o,side:n.trustSide?s.TYRESIDE==="RIGHT"?"right":s.TYRESIDE==="LEFT"?"left":void 0:void 0,fnomin:a.FNOMIN??5e3,unloadedR0:a.UNLOADED_RADIUS??a.R0??(l!==void 0&&l>0?l:.3),...a.WIDTH!==void 0&&a.WIDTH>0?{sectionWidth:a.WIDTH}:{},verticalStiffness:p>0?p/1e3:0,...a.FREFF!==void 0&&!a.DREFF?{rollingFraction:a.FREFF}:{},...a.LATERAL_STIFFNESS!==void 0&&a.LATERAL_STIFFNESS>0?{relaxation:{sigma:0,carcassStiffness:a.LATERAL_STIFFNESS/1e3,source:"fitted"}}:{},nomPressure:d??0,missing:b,...f&&Object.keys(f).length?{edited:f}:{},...h?{range:h}:{}}}function er(e){if(!e)return null;let t=e.unloadedR0;return t===void 0||!(t>0)||e.kind==="magic"&&e.missing?.includes("UNLOADED_RADIUS")?null:t*1e3}var i4=Math.PI/180;var p4=Math.PI/180,d4=180/Math.PI;function ks(){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 AR=`$ AXIS_SYSTEM = SAE (authored in the evaluation frame: y right)
|
|
3
3
|
[MODEL]
|
|
4
4
|
FITTYP = 62
|
|
5
5
|
[DIMENSION]
|
|
@@ -220,7 +220,7 @@ QHZ1 = 0
|
|
|
220
220
|
QHZ2 = 0
|
|
221
221
|
QHZ3 = 0
|
|
222
222
|
QHZ4 = 0
|
|
223
|
-
`}function Rr(e){let t=vs(CR(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 TR={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},PR={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},LR={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},DR={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},ER={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},IR={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},_R={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},NR={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},Jd=()=>Rr(TR),ef=()=>Rr(PR),tf=()=>Rr(LR),rf=()=>Rr(DR),nf=()=>Rr(ER),of=()=>Rr(IR),af=()=>Rr(_R),sf=()=>Rr(NR);var OR=e=>Number.isFinite(e)&&e>0;function yl(e,t){let r=OR(t.grip)?t.grip:1,n=OR(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 Ms={ok:!0,violation:0},Pn=1e7;function vr(e,t){let r;try{r=e.build(t)}catch(s){return{total:Pn*2,feasible:!1,terms:[],reason:`build failed: ${String(s)}`}}let n=e.feasible(r);if(!n.ok)return{total:Pn+Math.max(0,n.violation),feasible:!1,terms:[],reason:n.reason};let o;try{o=e.terms(r)}catch(s){return{total:Pn*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:Pn*2,feasible:!1,terms:o,reason:"objective was not finite"}}var Ss=(e,t)=>!t||(e.feasible!==t.feasible?e.feasible:e.total<t.total);function cf(e,t){return t.map((r,n)=>Math.min(e[n].hi,Math.max(e[n].lo,r)))}var kr=e=>e.map(t=>t.start);function xl(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 KT(e){let t=0;for(;t===0;)t=e();return Math.sqrt(-2*Math.log(t))*Math.cos(2*Math.PI*e())}function lf(e,t){let{budget:r}=t,n=Math.max(1,Math.floor(t.progressEvery??1)),o=e.variables,a=p=>cf(o,p.map((d,h)=>o[h].lo+d*(o[h].hi-o[h].lo))),s=p=>p.map((d,h)=>(d-o[h].lo)/(o[h].hi-o[h].lo)),i=0,c=0,l=null,u=null,m=[];return{vars:o,denorm:a,norm:s,evaluate:p=>{if(i>=r)return l?.total??Number.POSITIVE_INFINITY;i++;let d=p.map(g=>Math.min(1,Math.max(0,g))),h=vr(e,a(d));h.feasible||c++;let b=Ss(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):kr(o),score:l??vr(e,kr(o)),evaluations:i,history:m,infeasible:c})}}var uf=(e,t,r,n=0,o)=>{let a=t?r.norm(kr(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 VR(e,t){let r=lf(e,t),n=xl(t.seed??1),o=e.variables.length;for(r.evaluate(uf(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 qo(e,t){let r=lf(e,t),n=e.variables.length,o=xl(t.seed??1),a=1,s=2,i=.5,c=.5,l=uf(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],M=0;for(let v=1;v<=n;v++)for(let x=0;x<n;x++)M=Math.max(M,Math.abs(m[v].u[x]-R.u[x]));if(M<1e-4)break;for(let v=1;v<=n&&r.left()>0;v++){let x=m[v].u.map((k,F)=>R.u[F]+c*(k-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 BR(e,t){let r=lf(e,t),n=e.variables.length,o=xl(t.seed??1),a=4+Math.floor(3*Math.log(n)),s=Math.floor(a/2),i=[];for(let k=1;k<=s;k++)i.push(Math.log(s+.5)-Math.log(k));let c=i.reduce((k,F)=>k+F,0);for(let k=0;k<s;k++)i[k]/=c;let l=1/i.reduce((k,F)=>k+F*F,0),u=(l+2)/(n+l+5),m=1+2*Math.max(0,Math.sqrt((l-1)/(n+1))-1)+u,f=(4+l/n)/(n+4+2*l/n),p=(n+2)/3,d=Math.min(1,p*2/((n+1.3)**2+l)),h=Math.min(1-d,p*2*(l-2+1/l)/((n+2)**2+l)),b=Math.sqrt(n)*(1-1/(4*n)+1/(21*n*n)),g=uf(e,t.warmStart!==!1,r,t.startJitter,o),y=.25,R=new Array(n).fill(1),M=new Array(n).fill(0),v=new Array(n).fill(0),x=0;for(;r.left()>0;){x++;let k=[];for(let S=0;S<a&&r.left()>0;S++){let A=[];for(let L=0;L<n;L++)A.push(KT(o));let P=g.map((L,D)=>L+y*R[D]*A[D]);k.push({z:A,u:P,f:r.evaluate(P)})}if(k.length<s)break;k.sort((S,A)=>S.f-A.f);let F=g.slice(),w=new Array(n).fill(0);g=new Array(n).fill(0);for(let S=0;S<s;S++)for(let A=0;A<n;A++)g[A]+=i[S]*k[S].u[A],w[A]+=i[S]*k[S].z[A];g=g.map(S=>Math.min(1,Math.max(0,S)));for(let S=0;S<n;S++)M[S]=(1-u)*M[S]+Math.sqrt(u*(2-u)*l)*w[S];let C=Math.sqrt(M.reduce((S,A)=>S+A*A,0)),T=C/Math.sqrt(1-(1-u)**(2*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]*k[D].z[S]*k[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 Qo=[{name:"random",run:VR},{name:"nelder-mead",run:qo},{name:"sep-cma-es",run:BR}];var T4=Math.PI/180;var Rl=Math.PI/180;var E4={Fz:100,alpha:.25*Rl,kappa:.005,gamma:.5*Rl,p:6900},$R={Fz:100,alpha:1*Rl,kappa:.02,gamma:.5*Rl,p:6900};var GR=Math.PI/180,B4={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:GR},gamma:{rad:1,deg:GR},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 z4=Math.PI/180;var eP=Math.PI/180;var Q4=3*eP;var rK=Math.PI/180;var fK=Math.PI/180;var cP={RCX1:1,RCY1:1,REX1:0,REY1:0,RBY3:0,RHX1:0,RHY1:0},zR={RBX1:15,RBX2:15,RBY1:18,RBY2:19,...cP};var AK=Math.PI/180;var fP=Math.PI/180,vl=[{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"}],$K=new Map(vl.map(e=>[e.id,e]));var GK=.01*fP;var ze=Math.PI/180;var jR=new Set(vl.filter(e=>e.group!=="inputs"&&(e.unit==="N"||e.unit==="N\xB7m"||e.unit==="N/rad")).map(e=>e.id)),UR={alpha:{from:-15*ze,to:15*ze,n:61},kappa:{from:-.25,to:.25,n:61},gamma:{from:-6*ze,to:6*ze,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}},hf={alpha:{from:0,to:12*ze,n:7},kappa:{from:-.2,to:.2,n:9},gamma:{from:-4*ze,to:4*ze,n:5},Fz:{from:400,to:1600,n:5},p:{from:6e4,to:12e4,n:4},V:{from:5,to:35,n:4}};var bf={alpha:{from:0,to:12*ze,n:25},kappa:{from:-.2,to:.2,n:25},gamma:{from:-4*ze,to:4*ze,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,...UR[t],...o}],x:t,y:r,...n}),kl=(e,[t,r],n,o,a={})=>({id:e,form:"carpet",sweep:[{input:t,...hf[t]},{input:r,...hf[r]}],x:n,y:[o],...a}),Mr=(e,t)=>({id:e,fixed:t}),Ot={input:"Fz",values:"car"},ff={alpha:0,kappa:0},ht={kappa:0},YR={alpha:0},gP={input:"Fz",values:[500,1e3,1500]},yP=[{id:"overview",name:"Overview",cards:[Mr("tyre","tyre"),ke("fy","alpha",["Fy"],{title:"Lateral force",hold:ht}),ke("mz","alpha",["Mz"],{title:"Aligning moment",hold:ht}),ke("fx","kappa",["Fx"],{title:"Longitudinal force",hold:YR}),kl("combined-carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Mr("ellipse","ellipse")]},{id:"lateral",name:"Lateral",cards:[ke("fy-load","alpha",["Fy"],{title:"Lateral force per wheel load",series:Ot,hold:ht}),ke("muy-load","alpha",["muY"],{title:"Lateral force per unit load",series:Ot,hold:ht}),ke("fy-peak","alpha",["Fy"],{title:"Lateral force over its peak",series:Ot,hold:ht,scale:{per:"peak"}},{from:0,to:15*ze,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:Ot,hold:ht}),ke("trail","alpha",["t"],{title:"Pneumatic trail",series:Ot,hold:ht},{from:0,to:12*ze,n:49}),ke("mzr","alpha",["Mzr"],{title:"Residual aligning moment",series:Ot,hold:ht},{from:0,to:12*ze,n:49}),kl("gough",["alpha","Fz"],"Fy","Mz",{title:"Gough plot",hold:ht}),ke("steering-feel","alpha",["t"],{title:"Steering feel",x:"FyRel",series:Ot,hold:ht},{from:0,to:12*ze,n:49})]},{id:"longitudinal",name:"Longitudinal",cards:[ke("fx-load","kappa",["Fx"],{title:"Longitudinal force per wheel load",series:Ot,hold:YR}),ke("mux-peak","Fz",["muXPeak"],{title:"Peak longitudinal \u03BC over load"}),ke("kx","Fz",["dFxdk"],{title:"Slip stiffness at zero slip over load",hold:ff}),ke("kappa-peak","Fz",["kappaPeak"],{title:"Slip ratio at the peak over load"})]},{id:"combined",name:"Combined",cards:[kl("carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),kl("envelope-load",["kappa","alpha"],"Fy","Fx",{title:"Friction envelope per load",scale:{per:"Fz"},facet:gP}),ke("fy-kappa","kappa",["Fy"],{title:"Side force while driving or braking",series:{input:"alpha",values:[2*ze,4*ze,8*ze]}}),ke("fx-kappa","kappa",["Fx"],{title:"Driving force while cornering",series:{input:"alpha",values:[0,4*ze,8*ze]}}),Mr("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*ze)},hold:ht}),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",...bf.gamma},{input:"Fz",...bf.Fz,follow:!0}],x:"gamma",y:["Fz"],z:"muYPeak"},ke("camber-stiffness","alpha",["dFydg"],{title:"Camber stiffness at the point",series:Ot,hold:ht}),ke("mx","alpha",["Mx"],{title:"Overturning moment",series:Ot,hold:ht})]},{id:"rolling",name:"Rolling and radius",cards:[ke("my","V",["My"],{title:"Rolling-resistance moment",series:Ot,hold:ff}),ke("radius","Fz",["R0","Rl","Re"],{title:"Radius over load"},{from:0}),ke("p-roll","V",["Proll"],{title:"Rolling power",series:Ot,hold:ff})]},{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:ht,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:[Mr("operating","operating"),Mr("wheels","wheels")]},{id:"fit",name:"Fit check",cards:[Mr("fitLateral","fitLateral"),Mr("fitLongitudinal","fitLongitudinal"),Mr("fitCoupling","fitCoupling"),Mr("fitEnvelope","fitEnvelope")]}];var AP=5670374e-14,gf=273.15,QR=.95,ZR=60,Ml=10,FP=.55,St=25,yf=-20,xf=50,Fs={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:[...Fs.tempC],factor:[...Fs.factor]}},Sl={...ws,discMassKg:.4,discOuterMm:200,padCurve:{tempC:[...Fs.tempC],factor:[...Fs.factor]}};function Rf(e,t){let r=t==="front"?ws:Sl,n=Math.round(2*e.effRadiusMm+40);return{...r,discOuterMm:n,discMassKg:Math.round(100*r.discMassKg*(n/r.discOuterMm)**2)/100,padCurve:{tempC:[...r.padCurve.tempC],factor:[...r.padCurve.factor]}}}var wP=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},As=(e,t,r,n)=>Math.min(r,Math.max(t,wP(e,n)));function CP(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 vf(e,t){return{discMassKg:As(e?.discMassKg,.05,20,t.discMassKg),discOuterMm:As(e?.discOuterMm,50,600,t.discOuterMm),specificHeatJPerKgK:As(e?.specificHeatJPerKgK,100,3e3,t.specificHeatJPerKgK),emissivity:As(e?.emissivity,.02,1,t.emissivity),coolingWPerM2K:As(e?.coolingWPerM2K,Ml,5e3,t.coolingWPerM2K),padCurve:CP(e?.padCurve,t.padCurve)}}function Al(e,t){let r=e.tempC,n=e.factor,o=Math.min(r.length,n.length);if(o===0)return 1;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=1;for(;a<o-1&&r[a]<t;)a++;return n[a-1]+(t-r[a-1])/(r[a]-r[a-1])*(n[a]-n[a-1])}function kf(e,t=1){let r=e.discMassKg*e.specificHeatJPerKgK,n=e.discOuterMm*.001/2,o=2*Math.PI*n*n,a=ZR/3.6,s=e.emissivity*AP*o,i=m=>Ml+(e.coolingWPerM2K-Ml)*Math.pow(Math.max(0,m)*t/a,FP),c=(m,f,p)=>{let d=m+gf,h=p+gf;return i(f)*o*(m-p)+s*(d**4-h**4)},l=(m,f)=>i(f)*o+4*s*Math.max(0,m+gf)**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 M=0;M<g;M++)m+=(R-c(m,p,h)*y)/r;return m},padFactor:m=>Al(e.padCurve,m),window:JR(e.padCurve)}}function Fl(e,t,r,n,o,a,s=St){let i=n.length,c=new Array(i),l=new Array(i),u=new Array(i),m=QR/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 M=g+1<i?n[g+1]:n[g],v=.5*(n[g]+M),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 JR(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])&&Al(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 Mf=1e5,nv=.001,Ln={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},Af={fullAtBar:10,maxPowerKw:0,fadeBelowKmh:0,distribution:"equal"};var Ff=av(Cl(Ln,"Formula Student brakes")),wf=40,ov={ideal:!1,barFront:Ln.barFront,pedalForceMaxN:0,testSpeedKmh:wf,regen:Af};function ev(e){let{heat:t,...r}=e;return t?{...r,heat:{...t,padCurve:{tempC:[...t.padCurve.tempC],factor:[...t.padCurve.factor]}}}:r}function av(e){let t=(r,n)=>r.heat?r:{...r,heat:Rf(r,n)};return{...e,front:t(e.front,"front"),rear:t(e.rear,"rear")}}function Cl(e,t){return{name:t,pedalRatio:e.pedalRatio,masterFrontMm:e.masterFrontMm,masterRearMm:e.masterRearMm,valve:e.valve,valveKneeBar:e.valveKneeBar,valveSlope:e.valveSlope,front:ev(e.front),rear:ev(e.rear),adjusterPitchMm:e.adjusterPitchMm,barLengthMm:e.barLengthMm}}function Cf(e,t){return sv({...e,barFront:t.barFront,pedalForceMaxN:t.pedalForceMaxN})}function Tf(e,t){let r=Ar(t),n=e?tr(e):void 0;return{mode:r.ideal?"tyre":n?"hydraulic":"balance",hydraulic:n?Cf(n,r):Ln,regen:r.regen}}var TP=["none","proportioning","limiter"],wl=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},Je=(e,t,r,n)=>Math.min(r,Math.max(t,wl(e,n))),PP=(e,t)=>{let r=wl(e,t);return r>0?r:t};function tv(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(wl(e?.discs,n==="inboard"?1:t.discs)))),pistonsPerSide:Math.max(1,Math.min(6,Math.round(wl(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:vf(e.heat,t.heat??r)}:{}}}function sv(e){let t=Ln;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:TP.includes(e?.valve)?e?.valve:t.valve,valveKneeBar:Je(e?.valveKneeBar,0,200,t.valveKneeBar),valveSlope:Je(e?.valveSlope,0,1,t.valveSlope),front:tv(e?.front,t.front,ws),rear:tv(e?.rear,t.rear,Sl),adjusterPitchMm:PP(e?.adjusterPitchMm,t.adjusterPitchMm),barLengthMm:Je(e?.barLengthMm,0,500,t.barLengthMm)}}function LP(e){let t=Af;return{fullAtBar:Je(e?.fullAtBar,0,200,t.fullAtBar),maxPowerKw:Je(e?.maxPowerKw,0,1e3,t.maxPowerKw),fadeBelowKmh:Je(e?.fadeBelowKmh,0,100,t.fadeBelowKmh),distribution:e?.distribution==="wheel"?"wheel":"equal"}}function tr(e){let t=sv(e??void 0),r=typeof e?.name=="string"&&e.name.trim()?e.name:DP;return Cl(t,r)}function Ar(e){return{ideal:e?.ideal===!0,barFront:Je(e?.barFront,.05,.95,Ln.barFront),pedalForceMaxN:Je(e?.pedalForceMaxN,0,5e3,0),testSpeedKmh:Je(e?.testSpeedKmh,5,150,wf),regen:LP(e?.regen)}}var DP="Formula Student brakes";var Sf=e=>Math.PI/4*(e*nv)**2;function en(e,t){let r=e.pistonsPerSide*Sf(e.pistonDiaMm)*Mf;return e.discs*2*e.padMu*r*e.effRadiusMm*nv*e.ratio/Math.max(.05,t)}function iv(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 Cs(e,t){let r=Math.max(0,t)*e.pedalRatio,n=e.barFront*r/Sf(e.masterFrontMm)/Mf,o=(1-e.barFront)*r/Sf(e.masterRearMm)/Mf;return{front:n,rearIn:o,rear:iv(e,o)}}function EP(e,t){let r=Cs(e,1);return{front:en(e.front,t)*r.front,rear:en(e.rear,t)*r.rearIn}}function Ts(e,t){let r=EP(e,t);return r.front/Math.max(1e-12,r.front+r.rear)}function Ps(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=cv(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 cv(e,t){let r=e.fadeBelowKmh/3.6;return r>0?Math.max(0,Math.min(1,t/r)):1}function Sr(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 rv=new WeakMap;function Dn(e){let t=rv.get(e);return t||(t=e.mode==="hydraulic"&&e.hydraulic?_P(e,e.hydraulic):IP(e),rv.set(e,t)),t}function IP(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 _P(e,t){let r=en(t.front,e.tyreRadiusM),n=en(t.rear,e.tyreRadiusM),o=e.regen,a=(c,l)=>{let u=Cs(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*Sr(o.v,o.front,l),f=p*Sr(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 Pf(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 Tl=ls,NP=.1,En=(e,t)=>e.a*Math.sqrt(Math.max(0,1-(t/Math.max(1e-9,e.b))**2));function Pl(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 Ef(e,t,r){let n=Math.max(0,r-Tl*t.b),o=Math.min(r,Tl*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 If(e,t,r,n,o=0){let a=Math.max(0,r),s=Ef(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/NP)),d=p>0&&a<Tl*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:M}=s,v=Pl(T=>{let S=En(e,T),A=En(t,a-T);return Math.min(S+A,2*Math.min(S,A)+y)},R,M),x=e.cap(v),k=t.cap(a-v),F=Math.max(2*l,Math.min(x+k,2*Math.min(x,k)+y)),w=(T,S,A)=>Math.min(y,Math.max(0,T-A))+Math.min(y,Math.max(0,S-A));return{...g,regenWheel:y,mixedMax:F,regenRoom:T=>{let S=w(i,c,T);if(!(a>0))return S;let A=I=>Tl*I.b*Math.sqrt(Math.max(0,1-(T/Math.max(1e-9,I.a))**2)),P=Math.max(R,a-A(t)),L=Math.min(M,A(e));if(!(P<=L))return S;let D=Pl(I=>Math.min(y,En(e,I)-T)+Math.min(y,En(t,a-I)-T),P,L);return Math.max(S,w(e.cap(D),t.cap(a-D),T))}}}var Lf=e=>Math.max(e.xNoLock,e.xLock),Df=e=>Math.max(e.mixedMax,2*e.xLock);function Zo(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 Jo(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 Ls(e,t,r,n){return e.shares?OP(e,e.shares,t,r,n):VP(e,t,r,n)}function lv(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 OP(e,t,r,n,o){let a=Df(r),s=Df(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=Jo(r,t.front*b),y=Jo(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}=lv(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 VP(e,t,r,n){let o=Lf(t),a=Lf(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 k=0,F=x;for(let w=0;w<60;w++){let C=.5*(k+F);v(e.demand(C,n))?k=C:F=C}return k},u=Number.isFinite(e.uMax)?e.uMax:100;if(!Number.isFinite(e.uMax))for(;c(u)&&u<1e7;)u*=2;let m=c(u)?u:l(v=>s(v)<=o&&i(v)<=a,u),f=Number.isFinite(e.uMax)&&m>=e.uMax,p=v=>{let x=e.demand(v,n),k=Zo(t,s(x),x.regenFront),F=Zo(r,i(x),x.regenRear);return Number.isFinite(k)&&Number.isFinite(F)?k+F:-1/0},d=e.demand(m,n),h=o>0?s(d)/o:1/0,b=a>0?i(d)/a:1/0,g=[{u:m,by:f?"pedal":h>=b?"front":"rear"}];if(t.xLock>t.xNoLock){let v=l(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}=lv(g,p),M=e.demand(y.u,n);return{force:Math.max(0,Number.isFinite(R)?R:0),control:y.u,demand:M,limitedBy:y.by,lockFront:s(M)>t.xNoLock*(1+1e-9),lockRear:i(M)>r.xNoLock*(1+1e-9)}}var Fr={regen:!0,regenEfficiency:.6};function wr(e,t){let r=e.energy??t??Fr;return{regen:r.regen===!0,regenEfficiency:Math.min(1,Math.max(0,Number.isFinite(r.regenEfficiency)?r.regenEfficiency:0))}}function Cr(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 uv(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 At(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 Ll(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],M=i(y)*(1+s(y)/(s(y)+s(R)))-i(R)*(s(y)/(s(y)+s(R)));return M*i(y)<=0?0:Math.abs(M)>2*Math.abs(i(y))?2*i(y):M}let h=i(d-1),b=i(d),g=(h*s(d)+b*s(d-1))/(s(d-1)+s(d));return(Math.sign(h)+Math.sign(b))*Math.min(Math.abs(h),Math.abs(b),.5*Math.abs(g))},l=s(o),u=i(o),m=c(o),f=c(o+1),p=r-e[o];return t[o]+p*(m+p*((3*u-2*m-f)/l+p*(m+f-2*u)/(l*l)))}function Ds(e,t,r){return r.map(n=>At(e,t,n))}var Es=e=>e.reduce((t,r)=>r>t?r:t,-1/0),ea=e=>e.reduce((t,r)=>r<t?r:t,1/0);var BP=[-.906179845938664,-.538469310105683,0,.538469310105683,.906179845938664],$P=[.236926885056189,.478628670499366,.568888888888889,.478628670499366,.236926885056189];function _f(e,t,r){let n=.5*(r-t),o=.5*(t+r),a=0;for(let s=0;s<5;s++)a+=$P[s]*e(n*BP[s]+o);return n*a}var GP=Math.PI*2,KP=.5/3.6;function Is(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 Nf(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*GP;c[g]=y*o/n,l[g]=s[g]*n/o}let u=Es(c),m=Cr(ea(c),u,u/KP),f=Ds(c,l,m),{front:p,rear:d}=Is(t,r),h=f.map(g=>g*p),b=f.map(g=>g*d);return{vVehicle:m,fFront:h,fRear:b,vMax:u}}var mv=60/(2*Math.PI),pv=.1,dv=.08,fv=0;function Of(e){let t=(r,n)=>r===void 0||!Number.isFinite(r)?n:Math.max(0,r);return{up:t(e.upshiftTime,pv),down:t(e.downshiftTime,dv)}}function Vf(e){let t=e.driveKept;return t===void 0||!Number.isFinite(t)?fv:Math.max(0,Math.min(1,t))}function Bf(e,t,r){let{primary:n,ratios:o,efficiency:a}=e.gearbox,s=t>0&&r>0&&n>0,i=(b,g)=>b/mv*r/g,c=s?o.filter(b=>b>0).map(b=>{let g=n*b*t;return{ratio:g,vIdle:i(e.idleRpm,g),vLimit:i(e.limitRpm,g)}}):[],l=Math.max(0,Math.min(1,a)),u=Math.max(0,e.inertia),m=b=>b>e.limitRpm?0:Math.max(0,Be(e.rpm,e.torque,b)),f=(b,g)=>{let y=c[g];return y?b*y.ratio/r*mv: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 ta(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 $f(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 hv=9.81,bv=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]*(bv/60),a[v]=t[v]/60*bv,s[v]=a[v]*u/l,i[v]=r[v]*l,c[v]=i[v]/u;let m=Es(s),f=m,p=.5/3.6,d=Cr(ea(s),m,m/p),h=Ds(s,c,d),b=Cr(ea(t),Es(t),250),g=Ds(t,o,b).map(v=>v*e.power_scale.value),y,R=f,M;if(e.motorModel?.kind==="ice"){M=Bf(e.motorModel,l,u);let v=Cr(0,M.vMax,Math.max(2,Math.ceil(M.vMax/p)+1)),x=v.map(w=>$f(M,w)),k=v.map(()=>0),F=e.motorPlacement==="front";y={vVehicle:v,fFront:F?x:k,fRear:F?k:x,vMax:M.vMax},R=M.vMax}else e.motorModel&&(y=Nf(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:hv,FG:e.m.value*hv,vMax:R,vVehicle:d,fRad:h,uMotor:b,pMotor:g,vRad:s,fAxle:y,...M?{engine:M}:{}}}var tn=e=>e.motorModel?.kind==="ice"?Is(1,e.motorPlacement==="front"?"front":"rear"):Is(Math.max(1,Math.round(e.motorCount??e.driven_wheels?.value??2)),e.motorPlacement??"rear");function gv(e){let t=tn(e);return t.front>=2||t.rear>=2}function yv(e){return gv(e)?e.motorMount??"hub":"chassis"}function Gf(e){if(!e.motorModel)return{front:!1,rear:!0};let t=tn(e);return{front:t.front>0,rear:t.rear>0}}function Kf(e){let t=tn(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=yv(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 lt(e){return Tf(e.brakeModel,e.brakeSetup)}function Dl(e){return Ar(e.brakeSetup).ideal?"tyre":e.brakeModel||e.brakeModelId?"hydraulic":"balance"}function xv(e,t){if(!(mt(e.motorModel)||!wr(e).regen))return Ps(El(Ft(e)),t??lt(e).regen)}function El(e){return e.fAxle??{vVehicle:e.vVehicle,fFront:e.vVehicle.map(()=>0),fRear:e.fRad.map(t=>t*e.params.driven_wheels.value)}}function Hf(e,t=lt(e)){if(t.mode==="hydraulic")return Ts(t.hydraulic,e.r_dyn.value);if(t.mode==="tyre"){let r=e.front_mass_diss.value>1?e.front_mass_diss.value/100:e.front_mass_diss.value;return Math.min(.95,Math.max(.05,r+Z(e,"cg_height")/Math.max(1,Z(e,"wheelbase"))))}return Z(e,"brake_balance")}function zf(e,t=lt(e)){return{front:t.hydraulic.front.location==="inboard",rear:t.hydraulic.rear.location==="inboard"}}function Yf(e){let t=lt(e);return{brakeBalanceFront:Hf(e,t),brakeInboard:zf(e,t)}}function Rv(e,t=lt(e)){if(t.mode==="tyre"||t.regen.distribution!=="wheel"||mt(e.motorModel))return;let r=tn(e),n={front:r.front>=2,rear:r.rear>=2};return n.front||n.rear?n:void 0}function _s(e){let t=lt(e),r=e.r_dyn.value,n=zf(e,t),o=Hf(e,t),a=Rv(e,t),s=t.mode==="hydraulic"||a?xv(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 zP=9.81;function Wf(e,t){if(mt(e.motorModel))return()=>0;let r=lt(e),n=Ps(t,r.regen);if(r.mode==="hydraulic"){let a=Dn({mode:"hydraulic",balanceFront:Ts(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"?YP(e):()=>Math.min(.99,Math.max(.01,Z(e,"brake_balance")));return(a,s,i)=>{if(!(a>0))return 0;let c=o(s,i);return Math.min(c*a,Sr(n.v,n.front,s))+Math.min((1-c)*a,Sr(n.v,n.rear,s))}}function YP(e){let t=e.m.value*zP,r=e.front_mass_diss.value>1?e.front_mass_diss.value/100:e.front_mass_diss.value,n=Z(e,"cg_height")/Math.max(1,Z(e,"wheelbase")),o=1-Math.max(0,Math.min(1,Z(e,"cop_long"))),a=.5*e.rho.value*e.c_l.value*e.A.value;return(s,i)=>{let c=Math.max(0,a*s*s),l=t*(r+Math.abs(i)*n)+c*o;return Math.min(.99,Math.max(.01,l/(t+c)))}}function vv(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 jf={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"},...vv("front"),...vv("rear")},Uf={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 Xf(e){let t=jf[e];return`${t.label}, ${t.section}`.toLowerCase()}function qf(e){let t=Uf[e];return t.section?`${t.section} ${t.label.charAt(0).toLowerCase()}${t.label.slice(1)}`:t.label}var kv=new WeakMap;function rr(e){if(e.brakes)return e.brakes;let t=kv.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},kv.set(e,t)}return t}var Tr=e=>Dn(rr(e));var XP=Math.PI/180,ra=Object.freeze({tbr:1,preloadN:0}),Il=Object.freeze({tbr:1/0,preloadN:0}),Zf=e=>e.faces*e.muClutch*e.rFrictionMm/e.rRampMm;function Jf(e,t){if(!(e>0)||Number.isNaN(t))return 0;let r=Math.tan(Math.min(90,t)*XP);return r>0?Math.min(1,e/r):1}function Sv(e){if(e>=1)return 1/0;let t=e>0?e:0;return(1+t)/(1-t)}function _l(e){return e===1/0?1:e>1?(e-1)/(e+1):0}function na(e,t){return e.tbr===1/0?1/0:(e.preloadN>0?e.preloadN:0)+_l(e.tbr)*Math.abs(t)}function Os(e,t,r){let n=o=>o!==void 0&&o>0&&r>0?o/r:0;switch(e.kind){case"open":return ra;case"spool":return Il;case"independent":return t==="hubs"?ra:Il;case"clutch":{let o=n(e.preloadNm);return t==="hubs"?{tbr:1,preloadN:o}:{tbr:Sv(Jf(Zf(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 Ns(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 Mv=4;function Qf(e,t){let r=0;for(let a of e)r=Math.max(r,Ns(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,Ns(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 Vs(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=Ef(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=Pl(b=>En(e,b)+En(t,c-b),l.lo,l.hi),f=[{m1:l.c1,m2:l.c2}];for(let b=1;b<=Mv&&m!==l.y1;b++){let g=l.y1+(m-l.y1)*b/Mv;f.push({m1:e.cap(g),m2:t.cap(c-g)})}let p=Qf(f,ra),d=Qf(f,Il);if(!(d>p))return u;let h=(Qf(f,{tbr:s,preloadN:i})-p)/(d-p);return Math.min(a,u+(a-u)*Math.min(1,Math.max(0,h)))}function Av(e,t,r,n,o,a){return eh(e,o,Vs(t,r,n,o,a))}function eh(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 th(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 Fv(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 Cv(e,s,c,d,h,b,n,l,a);s=d,c=b}return null}function wv(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 Cv(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 Cv(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 Nl(e,t){return Math.abs(e.fx-e.x)>t?e.x:e.fx}var qP=(e,t)=>{let r=e.brakes?.hydraulic?.[t];return!!r&&r.location==="inboard"&&r.discs===1};function Vt(e,t,r){let n=e.driveline?.[t];if(n)return r>=0?n.drive:qP(e,t)?n.coast:n.hubs}var Tv=e=>e.tbr>1||e.preloadN>0;var QP=9.81,Pv=["FL","FR","RL","RR"],rh=e=>e==="FL"||e==="FR",Ol=e=>rh(e)?"front":"rear",Lv={front:["FL","FR"],rear:["RL","RR"]},Gs=()=>({peak:new Map,freeBrake:new Map}),$s=25;function Bs(e,t){let r=Math.max(0,e)/$s,n=Math.floor(r),o=r-n,a=t(n);return o>0?a+o*(t(n+1)-a):a}var rn=1e-4,ZP=.05;function Pr(e,t,r,n=Gs(),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=qc(xe(t,S),Math.max(1,A*$s)),i.set(P,L)),L},l=(S,A)=>({aPeak:Bs(A,P=>c(S,P).aPeak),fyPeak:Bs(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*$s);L=Mt(xe(t,S),D,0,!0,c(S,A)),u.set(P,L)}return L},f=(S,A)=>A>0?Bs(A,P=>m(S,P)):0,p=Tr(e),d=rr(e),h=S=>d.regen&&d.regenPerWheel?.[S]?Sr(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(Ol(S),L);return Mt(xe(t,Ol(S)),L,P[S]*D.fyPeak,!0,D)},R=(S,A,P,L,D=!0)=>{let I=te=>{let fe=Math.max(0,A[te]),Y=xe(t,S),J=l(S,fe);return{Fz:fe,a:Math.abs(f(S,fe)),b:J.fyPeak,slide:fe>0?Math.abs(Y.forces({Fz:fe,kappa:-1,alpha:0}).Fx):0,cap:re=>Math.abs(Mt(Y,fe,re,!0,J))}},G=te=>Math.abs(P[te])*l(Ol(te),Math.max(0,A[te])).fyPeak,[O,W]=Lv[S],E=I(O),_=I(W),V=G(O)+G(W),N=If(E,_,V,L,S==="front"?b:g),$=D?N:{...N,xLock:0},K=Vt(e,S,-1),z=K&&Tv(K)?K:void 0;if(!z)return{axle:S,eq:$,cap:$};let j=Number.isFinite(L)?L:E.cap(G(O))+_.cap(G(W)),Q=Av($,E,_,V,z,j);return{axle:S,eq:$,cap:Q,law:z,strong:()=>E.cap(G(O))>=_.cap(G(W))?O:W}},M=(S,A,P,L)=>R(S,A,P,L).cap,v=(S,A,P)=>{let L=S.demand,D=p.shares?Jo(A,L.front):Zo(A,(L.front-L.regenFront)/2,L.regenFront),I=p.shares?Jo(P,L.rear):Zo(P,(L.rear-L.regenRear)/2,L.regenRear);return{front:Number.isFinite(D)?D:0,rear:Number.isFinite(I)?I:0}},x=S=>({muX:A=>A>0?Math.abs(f(S,A))/A:0,muY:A=>A>0?l(S,A).fyPeak/A:0}),k={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 I=L.cap,G=D.cap,O=Ls(p,I,G,a),W={arms:F,halfTrack:w,ayDir:Math.sign(S)};for(let E=0;E<2;E++){let _=v(O,I,G),V={};for(let $ of Pv){let K=Math.max(0,A[$]);V[$]={Fz:K,Fy:Math.abs(P[$])*l(Ol($),K).fyPeak,Fx:-(rh($)?_.front:_.rear)/2}}let N=$=>{if(!$.law||!$.strong)return $.cap;let K={axle:$.axle,strong:$.strong(),full:2*$.cap.xNoLock,open:2*$.eq.xNoLock,sense:-1};return eh($.eq,$.law,gl(K,V,k,W))};I=N(L),G=N(D),O=Ls(p,I,G,a)}return{limit:O,front:I,rear:G}};return{peakAt:l,axle:M,ceiling:(S,A,P)=>{let[L,D]=Lv[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},I=Le(e,S,0,a,0,A),G,O=fe=>(G?.ax!==fe&&(G={ax:fe,loads:Le(e,S,(fe+L)/QP,a,0,A)}),G.loads),W=Qc(fe=>zo(P,O(fe),I,l).short,-L,-1),E=P,_={front:0,rear:0},V,N,$=(fe,Y=!0)=>{let J=W.at(fe);D=O(J),E=zo(P,D,I,l).util;let re=0,pe=0,de=0;for(let ie of Pv){let oe=y(ie,D,E);re+=oe,rh(ie)?pe+=oe:de+=oe}if(_={front:Math.abs(pe),rear:Math.abs(de)},p.mode!=="tyre"){let ie=R("front",D,E,Math.abs(pe),Y),oe=R("rear",D,E,Math.abs(de),Y);if(o&&(ie.law||oe.law)){let ue=C(S,D,E,ie,oe);V=ue.limit,N={front:ue.front,rear:ue.rear}}else V=Ls(p,ie.cap,oe.cap,a),N={front:ie.cap,rear:oe.cap};re=-V.force}return re/s},K=th($,0,rn),z=Nl(K,rn),j=z;if(V?.lockFront||V?.lockRear){let fe=th(J=>$(J,!1),0,rn);j=Nl(fe,rn);let Y=Fv($,fe.x,K.x,rn,ZP);Y||$(K.x),z=Nl(Y??K,rn)}let Q=W.edge(),ne=Q!==void 0&&z<Q;ne&&(z=Math.min(0,Q),$(z),j=Math.max(j,z));let te={loads:D,ceiling:_,limit:V,axles:N};return{ax:z,axUnlocked:j,...ne?{edge:Q}:{},...te,split:()=>te.limit&&te.axles?v(te.limit,te.axles.front,te.axles.rear):{...te.ceiling}}}}}var Bl=9.81;function JP(e,t,r){let n=Le(e,0,t,r),o=Math.max(0,n.FL)+Math.max(0,n.FR),a=Math.max(0,n.RL)+Math.max(0,n.RR);return o+a>0?o/(o+a):e.frontMassFrac}var Iv=(e,t)=>t.mode==="hydraulic"&&!!rr(e).regen;function oa(e,t,r=0,n,o=0){if(!e.brakes&&e.brakeBalanceFront==null)return e.frontMassFrac;let a=Tr(e);if(a.shares&&a.mode!=="tyre")return a.shares.front;let s=n&&Iv(e,a)?_v(e,n):void 0,i=s?.shares??Dv.get(e);i||Dv.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=Nv(c,l,u),f=i.get(m);if(f===void 0){let p=-c*.005,d=l*.25,h=e.massTotal*Math.abs(p)*Bl;if(s){let b=Vv(a,Ov(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"?JP(e,p,d):Pf(a,h,d);i.size>5e4&&i.clear(),i.set(m,f)}return f}var Dv=new WeakMap;function $l(e,t,r,n,o=0){let a=Tr(e);if(!Iv(e,a))return;let s=Math.round(Math.max(0,r)/(e.massTotal*Bl)/.005),i=Math.round(Math.max(0,n)/.25);return Vv(a,Ov(e,_v(e,t),s,i,Math.round(o/.01)),Math.max(0,r),n)}var Ev=new WeakMap;function _v(e,t){let r=Ev.get(e);r||Ev.set(e,r=new WeakMap);let n=r.get(t);return n||r.set(t,n={ev:t,tyres:Gs(),shares:new Map,rooms:new Map,speeds:new Map}),n}var Nv=(e,t,r)=>(r*1001+e)*100003+t;function Ov(e,t,r,n,o){let a=Nv(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:Pr(e,t.ev,i,t.tyres),dragG:-Math.max(0,za(e,i).drag)/(e.massTotal*Bl)},t.speeds.set(n,l));let{cap:u}=l,m=Le(e,c,-r*.005+l.dragG,i),f=Math.abs(c)*e.massTotal*Bl,p=b=>{let[g,y]=b==="front"?["FL","FR"]:["RL","RR"],R=f*(b==="front"?e.frontMassFrac:1-e.frontMassFrac),M=u.peakAt(b,Math.max(0,m[g])).fyPeak+u.peakAt(b,Math.max(0,m[y])).fyPeak,v=R>0&&M>0?Math.min(1,R/M):0;return u.axle(b,m,{FL:v,FR:v,RL:v,RR:v},1/0)},d,h;s=(b,g)=>(b==="front"?d??=p("front"):h??=p("rear")).regenRoom(g),t.rooms.size>5e4&&t.rooms.clear(),t.rooms.set(a,s)}return s}function Vl(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 Vv(e,t,r,n){if(!(r>0))return Vl(e,t,1,n);let o=c=>c.front+c.rear,a=e.controlFor(r,n),s=Vl(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=Vl(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=Vl(e,t,l,n);o(u)<r?a=l:(i=l,s=u)}return s}var aa={rel:.003,abs:2,kappa:1e-5,iters:12},nh={rel:1e-6,abs:.001,kappa:1e-12,iters:40};function In(e,t,r,n=aa){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=rL(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 M=e(o*R),v=Math.abs(M.Fx)-a;if(h=M,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 Bv=1e-6,eL=40,tL=(3-Math.sqrt(5))/2;function rL(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-Bv),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<eL;g++){let y=Bv*Math.abs(o)+1e-10,R=.5*(r+c);if(Math.abs(o-R)<=2*y-.5*(c-r))break;let M=!0;if(Math.abs(h)>y){let F=(o-l)*(m-p),w=(o-u)*(m-f),C=(o-u)*w-(o-l)*F;w=2*(w-F),w>0&&(C=-C),w=Math.abs(w);let T=h;if(h=b,Math.abs(C)<Math.abs(.5*w*T)&&C>w*(r-o)&&C<w*(c-o)){b=C/w;let S=o+b;(S-r<2*y||c-S<2*y)&&(b=R>=o?y:-y),M=!1}}M&&(h=o>=R?r-o:c-o,b=tL*h);let v=Math.abs(b)>=y?o+b:o+(b>=0?y:-y),x=e(t*v),k=-Math.abs(x.Fx);k<=m?(v>=o?r=o:c=o,u=l,p=f,l=o,f=m,o=v,m=k,i=x):(v<o?r=v:c=v,k<=f||l===o?(u=l,p=f,l=v,f=k):(k<=p||u===o||u===l)&&(u=v,p=k))}return{kappa:o,forces:i}}var Gl=e=>Math.max(2,.003*Math.abs(e)),nL=(e,t)=>Math.max(t.abs,t.rel*Math.abs(e)),oh=.5,oL=.03;function aL(e,t,r,n,o){let a=.5*(e.vx+t.vx),s=v=>{let x=(1+v)*a/e.vx-1,k=(1+v)*a/t.vx-1,F=e.at(x),w=t.at(k);return{kappaM:v,kl:x,kr:k,fl:F,fr:w,g:F.Fx+w.Fx-r}},i=nL(r,o),c=Math.max(-oh,Math.min(oh,n)),l=s(c);if(Math.abs(c)>oL){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)>oh)break;let k=s(x);if(Math.abs(k.g)<i)return k;if(Math.abs(k.g)<Math.abs(d.g)&&(d=k),Math.sign(k.g)!==Math.sign(m.g)){f=k;break}if(u*(k.g-m.g)<=0)return d;m=k,p*=1.9}if(f===l)return d;let h=m,b=f,g=h.g,y=b.g,R=Math.abs(g)<Math.abs(y)?h:b,M=Math.min(1e-7,o.kappa);for(let v=0;v<30&&Math.abs(b.kappaM-h.kappaM)>M;v++){let x=y-g,k=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);k>F&&k<w||(k=.5*(F+w));let C=s(k);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 $v(e,t,r,n){let o=(e*(1+t*n)+t*r)/(1-t*n);return e+o>=0?o:(e*(1-t*n)+t*r)/(1+t*n)}function ah(e,t,r,n,o,a=aa){let s=aL(e,t,r,o,a),i=s.fr.Fx-s.fl.Fx,c=na(n,r);if(Math.abs(i)<=c){let R=r-(s.fl.Fx+s.fr.Fx),M=Math.max(0,Math.abs(R)-Gl(r))/2;return{left:{kappa:s.kl,forces:s.fl,want:s.fl.Fx+R/2,short:M},right:{kappa:s.kr,forces:s.fr,want:s.fr.Fx+R/2,short:M},locked:!0,spoolKappa:s.kappaM}}let l=Math.sign(i),u=r/2-l*c/2,m=r/2+l*c/2,f=In(e.at,u,e.seed||s.kl,a),p=In(t.at,m,t.seed||s.kr,a),d=Math.abs(u-f.forces.Fx)>Gl(u),h=Math.abs(m-p.forces.Fx)>Gl(m),b=Math.max(0,n.preloadN),g=_l(n.tbr);d&&!h?p=In(t.at,$v(f.forces.Fx,l,b,g),p.kappa,a):h&&!d&&(f=In(e.at,$v(p.forces.Fx,-l,b,g),f.kappa,a));let y=(R,M)=>({kappa:R.kappa,forces:R.forces,want:M,short:Math.max(0,Math.abs(M-R.forces.Fx)-Gl(M))});return{left:y(f,u),right:y(p,m),locked:!1,spoolKappa:s.kappaM}}var sL={front:["FL","FR"],rear:["RL","RR"]},iL=Object.freeze({Fx:0,Fy:0,Mz:0});function Kl(e,t,r,n){let o=r;for(let a of["front","rear"]){let[s,i]=sL[a],c=r[s]+r[i],l=Vt(e,a,c);if(!l||!(na(l,c)>0))continue;let u=xe(t,a),m=n.alpha[a],f=(a==="front"?e.trackFront:e.trackRear)/2e3,p=(h,b)=>{let g=Math.max(0,n.Fz[h]);return{at:g>0?y=>u.forces({Fz:g,kappa:y,alpha:m,gamma:0}):()=>iL,vx:Math.max(.05,1-b*n.curvature),seed:0}},d=ah(p(s,f),p(i,-f),c,l,n.seed?.[a]??0);n.seed&&(n.seed[a]=d.spoolKappa),o===r&&(o={...r}),o[s]=d.left.want,o[i]=d.right.want}return o}var Me=9.81,se=Math.PI/180,cL=8,lL=1e-6,on=["FL","FR","RL","RR"],zt=e=>e==="FL"||e==="FR",nn=e=>zt(e)?"front":"rear";function Hs(e,t){let r=xe(e,"front"),n=xe(e,"rear");return r===n?Nn(r,t):{front:Nn(r,t),rear:Nn(n,t)}}function Nn(e,t){return Qd(e,Math.min(t,Ht(e)))}var zl=e=>e==="FL"||e==="RL";function ia(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,oa(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 ph(e,t,r,n){return Math.abs(On(e,t,r,n!==void 0?{steerMaxDeg:n}:{}).peak.steerDeg)}function dh(e,t,r,n){let o=e.tv;if(!o?.enabled)return 0;let a=i1(o)(t,Math.abs(r),n);return r<0?-a:a}function fh(e,t,r=0,n,o=0,a=0,s){let i=ia(e,{axG:t,driveFrontFrac:a},r,n,o),c=i?i.fx:{FL:0,FR:0,RL:0,RR:0};return i&&s&&n?Kl(e,n,c,s):c}var zs=e=>zl(e)?-1:1,hh=(e,t,r,n,o)=>t*e.Fy(t*r,n,t*o);function uh(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 uL(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?$o(o,n/se,u?r.FL:r.FR,u?r.FR:r.FL):Go(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 Ys(e,t,r){let n=(e.toeFrontDeg??0)*se,o=(e.toeRearDeg??0)*se,a=uL(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 bh(e,t,r){if(r.Fz<=0)return 0;let n=ct(xe(e,nn(t))),o=zs(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 Gv(e,t,r,n){if(!Tn(e))return null;let o=ct(xe(t,"front")),a={};for(let s of["FL","FR"]){let i=n[s];a[s]={Fz:i.Fz,Fx:i.Fx,Fy:i.Fy,Mz:bh(o,s,i)}}return Rs(e,r/se,a,Zr(o.model),{FL:n.FL.travelMm,FR:n.FR.travelMm})}var Kv=()=>({totalNm:[],aligningNm:[],lateralNm:[],longitudinalNm:[],jackingNm:[]});function Hv(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 mL=Object.freeze({Fx:0,Fy:0,Mz:0});function zv(e,t,r){let n=t==="front"?(r?.FL??0)+(r?.FR??0):(r?.RL??0)+(r?.RR??0),o=Vt(e,t,n);return o&&na(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}=uh(e),h=zv(e,"front",l),b=zv(e,"rear",l),g={front:0,rear:0},y=i!==void 0&&i>0&&Number.isFinite(i)?i:null,R=Y=>y===null?r:Math.sqrt(Math.max(0,Y)*y),M=ct(xe(t,"front")),v=ct(xe(t,"rear")),x=e.trackFront/2e3,k=e.trackRear/2e3,F=!!(e.kinFront&&e.kinRear),w=F&&y===null?Uo(e,e.kinFront,e.kinRear,r):null,C=NaN,T=null,S=Y=>{if(!F)return null;if(y===null)return w;let J=R(Y);return J!==C&&(C=J,T=Uo(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,I=!!(L||D),G=!!(L?.toePerMz||D?.toePerMz),O=Y=>zt(Y)?L:D,W={FL:{fy:0,fx:0,mz:0},FR:{fy:0,fx:0,mz:0},RL:{fy:0,fx:0,mz:0},RR:{fy:0,fx:0,mz:0}},E=!1,_=Y=>{let J=Y/r,re=y===null?n+f*J/r:n+f/y,pe=y===null?n-p*J/r:n-p/y,de=S(Y),ie=R(Y),oe=de?de(Y/Me,u,n/se,o/se):null,ue=oe?{FL:oe.FL.travel,FR:oe.FR.travel}:void 0,Ve=Uc(e,Y/Me,u,ie,n/se,o/se,ue,oe?.steeringJacking),Ae=Ve.loads;E=Ve.overturned;let le=Ys(e,o,ue),Re=le.steer,we=0,Ge=be=>{let Fe=Math.max(0,Ae[be]),ye=zs(be),me=zt(be)?M:v,Te=O(be),Se=0,Ke=0;if(Te){let Rn=W[be];Se=Te.toePerFy*Rn.fy+Te.toePerFx*Rn.fx+Te.toePerMz*Rn.mz,Ke=Te.camberPerFy*Rn.fy+Te.camberPerFx*Rn.fx}let je=Re[be]+(oe?ye*oe[be].bumpToe*se:0)+ye*Se*se,Gt=je-(zt(be)?re:pe),xn=(oe?oe[be].camberRoad:0)*se+ye*(le.camber[be]+Ke)*se;return{Fz:Fe,mir:ye,t:me,gains:Te,complianceToe:Se,steerK:je,slip:Gt,camberRad:xn}},We=(be,Fe)=>{let ye=y===null?J/r:1/y,me=zt(be)?f:-p,Te=(zl(be)?1:-1)*(zt(be)?x:k),Se=(Math.cos(n)-Te*ye)*Math.cos(Fe.steerK)+(Math.sin(n)+me*ye)*Math.sin(Fe.steerK);return{at:Fe.Fz>0?Ke=>Fe.t.forces({Fz:Fe.Fz,kappa:Ke,alpha:Fe.mir*Fe.slip,gamma:Fe.mir*Fe.camberRad}):()=>mL,vx:Math.max(.05,Se),seed:P[be]}};for(let be=0;be<(I?cL:1);be++){we=0;let Fe=0,ye={};for(let me of on){let Te=zt(me)?h:b;if(Te&&!ye[me]){let[vo,Dt]=zt(me)?["FL","FR"]:["RL","RR"],gc=Ge(vo),j0=Ge(Dt),U0=nn(me),fp=ah(We(vo,gc),We(Dt,j0),Te.F,Te.law,g[U0],nh);g[U0]=fp.spoolKappa,ye[vo]={w:gc,share:fp.left},ye[Dt]={w:j0,share:fp.right}}let Se=ye[me]?.w??Ge(me),{Fz:Ke,mir:je,t:Gt,gains:xn,complianceToe:Rn,steerK:up,slip:mp,camberRad:pp}=Se,Ga=l?.[me]??0,yo,xo=0,dp=0,bc=0,Ro=ye[me]?.share;if(Ro)P[me]=Ro.kappa,dp=Ro.kappa,xo=Ro.forces.Fx,bc=Ro.short,yo=je*Ro.forces.Fy;else if(Ga===0||Ke<=0)yo=hh(Gt,je,mp,Ke,pp),bc=Ke<=0?Math.abs(Ga):0;else{let Dt=In(gc=>Gt.forces({Fz:Ke,kappa:gc,alpha:je*mp,gamma:je*pp}),Ga,P[me],nh);P[me]=Dt.kappa,dp=Dt.kappa,xo=Dt.forces.Fx,bc=Math.max(0,Math.abs(Ga-xo)-Math.max(aa.abs,aa.rel*Math.abs(Ga))),yo=je*Dt.forces.Fy}if(A[me]={Fz:Ke,travelMm:oe?.[me].travel??0,steerRad:up,slipRad:mp,camberRad:pp,Fy:yo,Fx:xo,kappa:dp,fxShort:bc,lifted:Ve.lifted[me]},xn){let vo=G&&xn.toePerMz?bh(Gt,me,A[me]):0;W[me]={fy:-je*yo,fx:xo,mz:-je*vo*1e3};let Dt=W[me];Fe=Math.max(Fe,Math.abs(xn.toePerFy*Dt.fy+xn.toePerFx*Dt.fx+xn.toePerMz*Dt.mz-Rn))}we+=yo*Math.cos(up)+xo*Math.sin(up)}if(Fe<lL)break}return we/d},V=Y=>{let J=Le(e,0,u,Y,0,o/se);return J.FL+J.FR+J.RL+J.RR},N=Math.max(20,3.5*V(r)/d);if(y!==null){N=4*Me;for(let Y=0;Y<8;Y++){let J=Math.min(40*Me,3.5*V(R(N))/d);if(J<=N)break;N=J}N=Math.max(20,N)}let $=Y=>_(Y)-Y,K=Math.max(.001,N*1e-4),z=(Y,J,re,pe)=>{let de=Y,ie=re,oe=J,ue=pe,Ve=de;for(let Ae=0;Ae<40;Ae++){let le=ue-oe,Re=Math.abs(le)>1e-12?(de*ue-ie*oe)/le:.5*(de+ie),we=Math.min(de,ie),Ge=Math.max(de,ie);Re>we&&Re<Ge||(Re=.5*(de+ie));let We=$(Re);if(Ve=Re,Math.abs(We)<1e-4||Ge-we<1e-6)break;We<0==oe<0?(de=Re,oe=We,ue*=.5):(ie=Re,ue=We,oe*=.5)}return Ve},j=(Y,J,re,pe=!1)=>{let de=(Ae,le)=>re>0?Ae>0&&le<0:le>0&&Ae<0,ie=Y,oe=J,ue=Y+re*Math.min(Math.abs(J),N);if(!pe&&Math.abs(ue-Y)>K){let Ae=$(ue);if(de(oe,Ae))return{root:z(ie,oe,ue,Ae),last:ie};ie=ue,oe=Ae}let Ve=pe?N/24:Math.max(N/24,Math.abs(ue-Y)/4);for(let Ae=1;Ae<=24;Ae++){let le=ie+re*Ve;if(Math.abs(le)>N)break;let Re=$(le);if(de(oe,Re))return{root:z(ie,oe,le,Re),last:ie};if(pe&&Re*re<0&&(Re-oe)*re<0)break;ie=le,oe=Re}return{root:null,last:ie}},Q=c??null;if(c===void 0&&a!==void 0&&Number.isFinite(a)&&Math.abs(a)<=N){let Y=$(a);if(Math.abs(Y)<=1e-4)$(a+K)<0&&$(a-K)>0&&(Q=a);else{let J=j(a,Y,Math.sign(Y)).root;Q=J!==null&&(J===0||Math.sign(J)===Math.sign(a))?J:null}}let ne=Q===null;if(Q===null){let Y=$(0),J=$(K),re=Math.abs(Y)<=1e-4,pe=re?y!==null?1:o!==0?Math.sign(o):J>0?1:-1:Math.sign(Y),de=re?pe*K:0,ie=re?pe>0?J:$(-K):Y,oe=j(de,ie,pe);Q=oe.root??(re?0:oe.last)}let te=_(Q);if(ne&&o!==0&&y===null){let Y=Math.sign(o);if(Q*Y<=0||(A.RL.Fy+A.RR.Fy)*Y<0){let J={...A},re=E,pe=Y*Math.max(Q*Y+K,n*Y*r*r/p),de=null;if(pe*Y<N){let ie=$(pe);if(ie*Y>0)de=j(pe,ie,Y).root;else{let oe=pe+Y*N/24,ue=$(oe);(ue-ie)*Y>0&&(de=j(oe,ue,Y,ue*Y<=0).root)}}de!==null&&de*Y>0?(Q=de,te=_(Q)):(Object.assign(A,J),E=re)}}let fe=f*(A.FL.Fy*Math.cos(A.FL.steerRad)+A.FR.Fy*Math.cos(A.FR.steerRad))-p*(A.RL.Fy+A.RR.Fy);if(s||h||b){let Y=J=>(zl(J)?1:-1)*(zt(J)?x:k);for(let J of on){let re=A[J],pe=zt(J)?f:-p;fe+=pe*re.Fx*Math.sin(re.steerRad)-Y(J)*re.Fx*Math.cos(re.steerRad)}}return y!==null&&Q<-1e-6?{ay:NaN,cn:NaN,wheels:A,overturned:E,res:NaN}:{ay:Q/Me,cn:fe/(d*Me*m),wheels:A,overturned:E,res:te-Q}}function pL(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 M=y===void 0?void 0:R.ay,v={pos:{b:h,cn:R.cn,ay:M},neg:{b:h,cn:R.cn,ay:M}},x=null,k=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),k=S),A.cn===0&&m(A.ay))return{beta:S,trimmed:!0};if(A.cn<0!=C.cn<0){let P={lo:C.b,hi:S,ayLo:C.ay},L=Yv(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:Yv(u,x),trimmed:!0}:g?{beta:k,trimmed:!1}:null},p=[.25,.75,2,5].map(h=>h*se);if(o!==void 0&&Number.isFinite(o)&&Math.abs(o)<=c){let h=f(o,p,!1,a);if(h)return h;if(!s&&i===0&&a!==void 0&&Number.isFinite(a)){let b=dL(e,t,r,n,o,a,c);if(b&&m(b.ay))return{beta:b.beta,trimmed:!0,ay:b.ay}}}let d=[1,3,7,15,20].map(h=>h*se).filter(h=>h<=c);return f(0,d,!0)??{beta:0,trimmed:!1}}function Yv(e,t){let{lo:r,hi:n}=t,o=t.ayLo,a=e(r,o).cn,s=e(n,o).cn,i=r;for(let c=0;c<40;c++){let l=s-a,u=Math.abs(l)>1e-12?(r*s-n*a)/l:.5*(r+n);u>Math.min(r,n)&&u<Math.max(r,n)||(u=.5*(r+n));let m=e(u,o),f=m.cn;if(o!==void 0&&(o=m.ay),i=u,Math.abs(f)<1e-5||Math.abs(n-r)<1e-5)break;f<0==a<0?(r=u,a=f,s*=.5):(n=u,s=f,a*=.5)}return i}function dL(e,t,r,n,o,a,s){let i=(f,p)=>{let d=wt(e,t,r,f,n,void 0,null,void 0,p);return{r:d.res,c:d.cn}},c=o,l=a,u=i(c,l),m=0;for(let f=0;f<fL;f++){let p=i(c+sh,l),d=i(c,l+ih),h=(p.r-u.r)/sh,b=(d.r-u.r)/ih,g=(p.c-u.c)/sh,y=(d.c-u.c)/ih,R=h*y-b*g;if(!Number.isFinite(R)||R===0||Math.abs(R)<yL*(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 M=(u.c*b-u.r*y)/R,v=(u.r*g-u.c*h)/R,x=Math.min(1,hL/Math.max(Math.abs(M),1e-300),bL/Math.max(Math.abs(v),1e-300));if(c+=x*M,l+=x*v,Math.abs(c-o)>gL||Math.abs(c)>s||l*a<0)return null;u=i(c,l)}return null}var fL=8,sh=1e-5,ih=.001,hL=1*se,bL=2,gL=5*se,yL=.5;function Zv(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 on){let h=c.wheels[d],b=xe(t,nn(d)),g=Ht(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:bh(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=Rs(e,o/se,u,Zr(xe(t,"front").model),{FL:c.wheels.FL.travelMm,FR:c.wheels.FR.travelMm}),p=Ys(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 Dr(e,t,r,n,o,a,s=0){let i=Math.max(8,r),c=_n(e,t,i,n,o,a,s);return n!==0&&o?.driving===void 0&&(c.driving=EL(e,t,i,c,a,s)),c}function _n(e,t,r,n,o,a,s){let i=n*se,c=ia(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}=pL(e,t,r,i,u,l,c,s),d=Zv(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)<=xL,h}var xL=3;function On(e,t,r,n={}){let o=Math.max(8,r),a=n.direction??1,s=n.yawDemandCn??0,i=n.steerMaxDeg??RL,c=typeof n.op=="function"?n.op:()=>n.op,l=typeof n.op=="function"?null:`${o}|${a}|${s}|${i}|${n.op?`${n.op.axG}|${n.op.driveFrontFrac??""}|${n.op.tvRearDiffN??""}`:""}`;if(l!==null){let x=ch.get(e)?.get(t)?.get(l);if(x)return x}let u=(x,k)=>k.trimmed&&Math.abs(k.beta-x.beta)<=Yl&&Math.abs(k.ay-x.ay)*Me<=Wl,m=!1,f=(x,k)=>{let F=_n(e,t,o,a*x,k,c(a*x),s);return u(k,F)?(F.driving=!0,F):(m=F.overturned,null)},p=[_n(e,t,o,0,void 0,c(0),s)],d=null,h=!1,b,g=x=>{let k=p.length-1;for(;k>1&&x.sb*(p[k].beta-p[k-1].beta)>=0;)k--;let F=a*(x.state.ay-p[k].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,k)&&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,k=!1)=>k||PL(p[p.length-1],x)?LL(e,t,o,a,p,x,c,s):null,R=p[0].trimmed?p[0]:null;if(!R){let x=0;for(let k=Wv;k<=i&&!R;k+=Wv){let F=_n(e,t,o,a*k,void 0,c(a*k),s);if(F.trimmed){let w=k;R=F;for(let C=0;C<6;C++){let T=.5*(x+w),S=_n(e,t,o,a*T,void 0,c(a*T),s);S.trimmed?(w=T,R=S):x=T}}else x=k}R&&(R.driving=!0,p.push(R))}if(R){let x=Math.abs(R.steerDeg),k=Math.min(lh,100/(o*o)),F=R;for(;x<i;){let w=Math.min(i,x+k),C=f(w,F);if(C){let L=y(C);if(L){g(L);break}if(p.push(C),w>=i||s1(e,a*w))break;Math.abs(C.beta-F.beta)<.5*Yl&&Math.abs(C.ay-F.ay)*Me<.5*Wl&&(k=Math.min(lh,1.5*k)),x=w,F=C;continue}if(k>vL){k*=.5;continue}let T=m,S=!1,A=null;for(let L of kL){let D=Math.min(i,x+L);if(D<=x)continue;let I=f(D,F);if(I){if(A=y(I,!0),A)break;p.push(I),x=D,F=I,k=Math.min(lh,100/(o*o)),S=!0;break}}if(S)continue;if(A){g(A);break}d=x,h=T;let P=T?null:TL(e,t,o,a,p,c,s);P&&g(P);break}}else d=0;let M=p[0];for(let x of p)a*x.ay>a*M.ay&&(M=x);let v={states:p,foldDeg:d,rollover:h,peak:M,...b?{fold:b}:{}};if(l!==null){let x=ch.get(e);x||(x=new WeakMap,ch.set(e,x));let k=x.get(t);k||(k=new Map,x.set(t,k)),k.size>256&&k.clear(),k.set(l,v)}return v}var ch=new WeakMap,RL=90,Yl=1.5,Wl=2.5,lh=5,vL=.002,kL=[.5,1],Wv=2.5,Jv=.01,Lr=.001,ML=.05,SL=.25,AL=5,FL=2,jv=1e-8,wL=1e-7,CL=1e-6;function e1(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,ia(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)<jv;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)>FL)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 M=0;M<60&&R!==0&&Math.abs(y-b)>jv;M++){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>Wl?null:{steerDeg:h.x,ay:h.ay}}function Ks(e,t,r,n,o){let a=Zv(e,t,r,n.beta*se,n.steerDeg*se,n.ay*Me,ia(e,o(n.steerDeg),r,t));return{...a,trimmed:!a.overturned,driving:!a.overturned}}function TL(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=t1(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=Jv;Math.abs(g.beta-c.beta)<=Yl;x*=1.5){let k=f(g.beta+y*x);if(!k)return null;if(n*k.steerDeg<=n*g.steerDeg){R=k;break}b=g,g=k}if(!R)return null;let M=r1(f,n,b,g,R);if(!M)return null;let v=Ks(e,t,r,M,a);return!v.trimmed||Math.abs(v.beta-c.beta)>Yl||Math.abs(v.ay-c.ay)*Me>Wl?null:{state:v,sb:m}}function t1(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=e1(e,t,r,s,i,n,o);if(!c)return null;let l={beta:s,...c};return a.push(l),l}}function PL(e,t){let r=Math.abs(t.beta-e.beta);return r>SL&&r>AL*Math.abs(t.steerDeg-e.steerDeg)}function LL(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=t1(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=Jv;f*(a.beta-g.beta)>0;R=Math.min(ML,1.5*R)){let M=p(f*(a.beta-g.beta)>R?g.beta+f*R:a.beta);if(!M)return null;let v=n*M.steerDeg<=n*g.steerDeg;if(!y)v&&(y=[b,g,M]);else if(!v){let x=r1(p,n,...y);if(!x)return null;let k=Ks(e,t,r,x,s);return k.trimmed?{state:k,sb:f}:null}b=g,g=M}return null}function r1(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*Lr-.5*(i-s))break;let h=!0;if(Math.abs(m)>Lr){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 M=m;if(m=f,Math.abs(R)<Math.abs(.5*y*M)&&R>y*(s-c.beta)&&R<y*(i-c.beta)){f=R/y;let v=c.beta+f;(v-s<2*Lr||i-v<2*Lr)&&(f=d>=c.beta?Lr:-Lr),h=!1}}h&&(m=c.beta>=d?s-c.beta:i-c.beta,f=o1*m);let b=e(Math.abs(f)>=Lr?c.beta+f:c.beta+(f>=0?Lr:-Lr));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 gh(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 Ks(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=e1(e,t,r,g,y,i,c);if(!R)return null;let M={beta:g,...R};u.push(M),h=M;let v=l(M);if(Math.abs(v)<("steerDeg"in a?wL:CL))break;v<0?(m=M,p=v,d*=.5):(f=M,d=v,p*=.5)}return Ks(e,t,r,h,i)}function DL(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 gh(e,t,r,n.fold,a,{steerDeg:o});let u=typeof a.op=="function"?a.op(o):a.op,m=_n(e,t,r,o,l,u,a.yawDemandCn??0);return m.driving?m:null}function EL(e,t,r,n,o,a){if(!n.trimmed)return!1;let s=n.steerDeg<0?-1:1,{states:i}=On(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 an(e,t,r,n,o){let a=Math.max(8,r),s=n>=0?1:-1,i=Math.abs(n),c=(b,g)=>Dr(e,t,a,s*b,g,o),l=On(e,t,a,{direction:s,op:o}),{fold:u}=l;if(u&&Math.abs(u.state.steerDeg)<=sa){if(i>Math.abs(u.state.ay))return Xv(e,t,a,s,i,o);if(i>Math.abs(u.stall.ay)){let b=gh(e,t,a,u,{direction:s,op:o},{ayG:i});if(b)return b}}let m=l.states.filter(b=>Math.abs(b.steerDeg)<=sa),f=m[m.length-1],p=l.states.length>m.length;p&&Math.abs(f.steerDeg)<sa&&m.push(c(sa,f));let d=m.findIndex(b=>Math.abs(b.ay)>=i);if(d===0)return Dr(e,t,a,0,void 0,o);if(d>0)return Uv(m[d-1],m[d],i,c);let h=n1(m,c,void 0,p||l.foldDeg===null);return h.ay>=i?Uv(h.below,h.state,i,c):l.foldDeg!==null&&l.foldDeg<sa?Xv(e,t,a,s,i,o):h.state}var sa=20;function Uv(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)<=IL||a.steer-o.steer<=_L)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 IL=1e-9,_L=1e-7;function n1(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=NL/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[k,F]=Math.abs(a.ay)>=Math.abs(x.ay)?[a,x]:[x,a];f=Math.abs(k.steerDeg),p=-Math.abs(k.ay),d=Math.abs(F.steerDeg),h=-Math.abs(F.ay)}else{let x=Math.abs(e[o].lockDeg??e[o].steerDeg),k=x-OL,F=o>0&&n&&k>Math.abs(a.steerDeg)?t(k,a):null;if(!F||Math.abs(F.ay)<=Math.abs(e[o].ay)){let w=t(s,a);return{state:w,below:a,ay:Math.abs(w.ay)}}g=w=>t(w,a),c=Math.abs(a.steerDeg),l=x,u=k,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 k=.5*(c+l);if(Math.abs(u-k)<=2*i-.5*(l-c))break;let F=!0;if(Math.abs(y)>i){let S=(u-f)*(m-h),A=(u-d)*(m-p),P=(u-d)*A-(u-f)*S;A=2*(A-S),A>0&&(P=-P),A=Math.abs(A);let L=y;if(y=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=k>=u?i:-i),F=!1}}F&&(y=u>=k?c-u:l-u,R=o1*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 M=b??t(s,a),v=Math.abs(M.steerDeg)>s?e[o]:a;return{state:M,below:v,ay:Math.abs(M.ay)}}var NL=.001,OL=.01,o1=(3-Math.sqrt(5))/2;function Xv(e,t,r,n,o,a){let s=l=>Math.abs(Dr(e,t,r,n*l,void 0,a).ay),i=0,c=sa;if(s(c)<o)return Dr(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 Dr(e,t,r,n*.5*(i+c),void 0,a)}function yh(e,t,r,n,o){let a=an(e,t,r,n,o);return a.steering?Math.abs(a.steering.totalNm):NaN}function xh(e,t,r,n,o){if(!Tn(e))return NaN;let a=n<0?-1:1,s=Math.abs(n),i=an(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=Dr(e,t,r,a*u,void 0,o),p=Dr(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 mh(e,t,r,n,o,a){let s=Math.max(8,r),i=wt(e,t,s,n*se,o*se,void 0,ia(e,a,s,t));return{ay:i.ay,cn:i.cn}}function Rh(e,t,r,n,o){let a=Math.max(8,r),s=an(e,t,a,n,o),i=.5,c=mh(e,t,a,s.beta+i,s.steerDeg,o).cn,l=mh(e,t,a,s.beta-i,s.steerDeg,o).cn;return(c-l)/(2*i*se)*e.massTotal*Me*(e.wheelbase/1e3)}function vh(e,t,r,n){let o=Math.max(8,r),{branch:a,opts:s}=VL(e,t,o,n);return a1(e,t,o,a,s)}function VL(e,t,r,n){if(!e.tv?.enabled){let s=n?{op:n}:{};return{branch:On(e,t,r,s),opts:s}}let o=ph(e,t,r),a={op:s=>{let i=dh(e,r,s,o);return i===0?n:{axG:n?.axG??0,driveFrontFrac:n?.driveFrontFrac,tvRearDiffN:i}}};return{branch:On(e,t,r,a),opts:a}}function a1(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 Ks(e,t,r,n.peak,a);let i=(l,u)=>_n(e,t,r,l,u,a(l),s),c=n.states[0].driving||!n.peak.driving?n.states:n.states.slice(1);return n1(c,i,c.indexOf(n.peak),n.foldDeg===null).state}function kh(e,t,r,n={}){let o=n.radius!==void 0&&n.radius>0&&Number.isFinite(n.radius)?n.radius:void 0,a=o===void 0?Math.max(8,r):Math.max(8,Math.sqrt(Me*o)),s=(n.betaMaxDeg??10)*se,i=(n.deltaMaxDeg??10)*se,[c,l]=n.betaRangeDeg?[n.betaRangeDeg[0]*se,n.betaRangeDeg[1]*se]:[-s,s],[u,m]=n.deltaRangeDeg?[n.deltaRangeDeg[0]*se,n.deltaRangeDeg[1]*se]:[-i,i],{lf:f,lr:p}=uh(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&&Tn(e),R=y?Zr(xe(t,"front").model):void 0,M=(E,_,V,N)=>V===1?E:E+(_-E)*N/(V-1),v=e.tv?.enabled?ph(e,t,a):0,x=E=>{let _=dh(e,a,E/se,v);return!n.axG&&_===0?null:ia(e,{axG:n.axG??0,driveFrontFrac:n.driveFrontFrac,tvRearDiffN:_},a,t)},{lf:k,lr:F}=uh(e),w=n.reserves?Hs(t,e.massTotal*Me*1.2):null,C=E=>w?xr(w,{FL:E.FL,FR:E.FR,RL:E.RL,RR:E.RR},{lf:k,lr:F}):null,T=[],S={ay:[],cn:[]},A=0;for(let E=0;E<b;E++){let _=M(u,m,b,E),V=x(_),N=[],$=[],K=[],z=[],j=w?{stabil:[],agil:[]}:void 0,Q=y?Kv():void 0,ne;for(let Y=0;Y<g;Y++){let J=M(c,l,g,Y),re=wt(e,t,a,J,_,ne,V,o);if(ne=Number.isFinite(re.ay)?re.ay*Me:void 0,N.push(re.ay),$.push(re.cn),K.push(J/se),z.push(_/se),j){let pe=C(re.wheels);j.stabil.push(pe.stabil),j.agil.push(pe.agil)}Q&&Hv(Q,Gv(e,t,_,re.wheels)),Math.abs(re.ay)>A&&(A=Math.abs(re.ay))}T.push({label:`\u03B4 ${(_/se).toFixed(0)}\xB0`,ay:N,cn:$,betaDeg:K,deltaDeg:z,reserve:j,steering:Q});let te=null,fe=1/0;for(let Y=1;Y<$.length;Y++){if(!Number.isFinite($[Y-1])||!Number.isFinite($[Y])||$[Y-1]!==0&&$[Y-1]<0==$[Y]<0)continue;let J=$[Y-1]===$[Y]?0:$[Y-1]/($[Y-1]-$[Y]),re=N[Y-1]+J*(N[Y]-N[Y-1]);if(o===void 0&&_!==0&&Math.abs(re)>=.05&&Math.sign(re)!==Math.sign(_))continue;let pe=Math.abs(K[Y-1]+J*(K[Y]-K[Y-1])-d/se);pe<fe&&(fe=pe,te=re)}te!==null&&(S.ay.push(te),S.cn.push(0))}let P=[];for(let E=0;E<b;E++){let _=M(c,l,b,E),V=[],N=[],$=[],K=[],z=w?{stabil:[],agil:[]}:void 0,j=y?Kv():void 0,Q;for(let ne=0;ne<g;ne++){let te=M(u,m,g,ne),fe=wt(e,t,a,_,te,Q,x(te),o);if(Q=Number.isFinite(fe.ay)?fe.ay*Me:void 0,V.push(fe.ay),N.push(fe.cn),$.push(_/se),K.push(te/se),z){let Y=C(fe.wheels);z.stabil.push(Y.stabil),z.agil.push(Y.agil)}j&&Hv(j,Gv(e,t,te,fe.wheels))}P.push({label:`\u03B2 ${(_/se).toFixed(0)}\xB0`,ay:V,cn:N,betaDeg:$,deltaDeg:K,reserve:z,steering:j})}let L=.5*se,D=x(h),I,G;if(o===void 0)I=(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),G=(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 E=(N,$)=>wt(e,t,a,N,$,void 0,x($),o).cn,_=(N,$,K)=>Number.isFinite(N)?(-3*N+4*$-K)/(2*L):(K-$)/L,V=E(d,h);I=-_(V,E(d-L,h),E(d-2*L,h)),G=_(V,E(d,h+L),E(d,h+2*L))}let O=0;if(D&&D.axG){let E=wt(e,t,a,d,h,void 0,D,o),_=0;for(let V of on)_+=E.wheels[V].fxShort;O=_/Math.abs(e.massTotal*D.axG*Me)}let W=S.ay.reduce((E,_)=>Math.max(E,Math.abs(_)),0);return{isoBeta:P,isoDelta:T,trim:S,maxAy:A,stability:I,control:G,speed:o===void 0?a:Math.sqrt(W*Me*o),...o!==void 0?{radius:o}:{},axG:D?.axG??0,axShortfall:O,...R?{steeringAligningSource:R}:{}}}function s1(e,t){return Ys(e,t*se).atLock}function BL(e,t,r,n,o=Pr(e,t,r)){let a=r,s=e.massTotal,i=on.filter(g=>zt(g)?n.drivenFront:n.drivenRear),c=o.peakAt,l={front:n.drivenFront?Vt(e,"front",1):void 0,rear:n.drivenRear?Vt(e,"rear",1):void 0},u=new Map,m=(g,y)=>{let R=`${g}:${y}`,M=u.get(R);if(M===void 0){let v=Math.max(1,y*$s);M=Mt(xe(t,g),v,0,!1,c(g,v)),u.set(R,M)}return M},f=(g,y)=>y>0?Bs(y,R=>m(g,R)):0,p=(g,y,R,M)=>{let v=xe(t,g),x=D=>{let I=Math.max(0,R[D]),G=c(g,I);return{Fz:I,a:f(g,I),b:G.fyPeak,slide:0,cap:O=>I>0?Mt(v,I,O,!1,G):0}},[k,F]=g==="front"?["FL","FR"]:["RL","RR"],w=x(k),C=x(F),T=M[k]*w.b,S=M[F]*C.b,A=w.cap(T)+C.cap(S),P=Vs(w,C,T+S,y,A);return{l:k,r:F,full:P,asHeld:()=>({axle:g,strong:w.cap(T)>=C.cap(S)?k:F,full:P,open:Vs(w,C,T+S,ra,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,M=0)=>{let v={FL:0,FR:0,RL:0,RR:0},x=Le(e,g,0,a,0,y),k,F=P=>(k?.ax!==P&&(k={ax:P,loads:Le(e,g,(P+M)/Me,a,0,y)}),k.loads),w=Qc(P=>zo(R,F(P),x,c).short,-M,1),C=R,T=P=>{let L=w.at(P);v=F(L),C=zo(R,v,x,c).util;let D=0,I=n.diffYaw?{fx:{FL:0,FR:0,RL:0,RR:0},axles:[]}:null;for(let G of i){let O=l[nn(G)];if(O){if(zl(G)){let V=p(nn(G),O,v,C);D+=V.full,I&&(I.fx[V.l]=I.fx[V.r]=V.full/2,I.axles.push(V.asHeld()))}continue}let W=Math.max(0,v[G]),E=c(nn(G),W),_=Mt(xe(t,nn(G)),W,C[G]*E.fyPeak,!1,E);D+=_,I&&(I.fx[G]=_)}if(I){let G={};for(let O of on){let W=Math.max(0,v[O]);G[O]={Fz:W,Fy:C[O]*c(nn(O),W).fyPeak,Fx:I.fx[O]}}for(let O of I.axles)D+=gl(O,G,h,b(g))-O.full}return D/s},S=wv(T,-M,rn).fx,A=w.edge();return A!==void 0&&S>A&&(S=A,T(S)),{ax:S,loads:v}}}}var Hl=.05,qv=.001,Qv=16,jl=8;function Mh(e,t,r,n){let o=Math.max(jl,r),a=n.nSteer??7,s=e.tv?.enabled?ph(e,t,o,n.steerMaxDeg):0,i=E=>{let _=dh(e,o,E,s);return _===0?void 0:{axG:0,tvRearDiffN:_}},c=n.yawDemandCn??0,l={op:i,yawDemandCn:c,...n.steerMaxDeg!==void 0?{steerMaxDeg:n.steerMaxDeg}:{}},u=On(e,t,o,l),m=E=>{let _={},V={};for(let N of on)_[N]=E.wheels[N].slipDeg*se,V[N]=Math.min(1,E.wheels[N].gripUtil);return{steerDeg:E.steerDeg,ayMs:Math.max(0,E.ay*Me),ayG:E.ay,slip:_,util:V,scrub:E.ay>0?$L(E,e.massTotal):0}},f=null,p=E=>{if(f&&E===f.steerDeg)return m(f);let _=DL(e,t,o,u,E,l);if(_)return m(_);let V=u.states[0];for(let N of u.states)N.steerDeg<=E&&(V=N);return m(V)},d=u.peak.driving&&u.peak.ay>0?a1(e,t,o,u,l):null,h=d?Math.max(0,d.ay*Me):0,b=d?[...u.states.filter(E=>E.steerDeg<d.steerDeg),d]:u.states,g=d?b.findIndex(E=>E.ay*Me>=.995*h):0,y=b[g].steerDeg,{fold:R}=u;if(d&&R&&u.peak===R.state){let E=.995*h/Me,_=u.states.indexOf(R.stall),V=_-1;for(;V>0&&u.states[V].beta===R.stall.beta;)V--;let N=Math.sign(R.stall.beta-u.states[V].beta),$=_;for(;$>0&&u.states[$].ay>=E&&Math.sign(u.states[$].beta-u.states[$-1].beta)!==-N;)$--;u.states[$].ay<E&&(f=gh(e,t,o,R,l,{ayG:E},u.states.slice($,_+1)))}if(f)y=f.steerDeg;else if(g>0){let E=b[g-1].steerDeg,_=y;for(let V=0;V<8&&_-E>.001;V++){let N=.5*(E+_);p(N).ayMs>=.995*h?_=N:E=N}y=_}let M=[];for(let E=0;E<(h>0?a:1);E++){let _=E/(a-1);M.push(p(y*(_+Math.sin(Math.PI/2*_))/2))}M[0].ayMs=0;let v=[],x=[],k=[],F=[],w=Pr(e,t,o,void 0,n.diffYaw===!0),C=BL(e,t,o,n,w),T=n.axDrag??0,S=E=>{let _=w.limitAt(E.ayMs/Me,E.steerDeg,E.util,T+E.scrub);return{axD:_.edge!==void 0&&_.edge>0?_.edge:_.ax,locked:_.axUnlocked-_.ax>Hl}},A=E=>C.limitAt(E.ayMs/Me,E.steerDeg,E.util,T+E.scrub).ax,P=M.map(E=>({p:E,axA:A(E),...S(E)})),L=[];for(let E=0;E+1<P.length;E++){let _=P[E],V=P[E+1],N=[];_.locked!==V.locked?N.push({read:S,past:$=>$.locked===V.locked,braking:!0}):(V.axA>_.axA+Hl&&N.push({read:$=>({axA:A($)}),past:$=>($.axA??-1/0)>_.axA}),-V.axD>-_.axD+Hl&&N.push({read:S,past:$=>-($.axD??0)>-_.axD}));for(let{read:$,past:K,braking:z}of N){let j=_.p.steerDeg,Q=V.p.steerDeg,ne=null,te=_.axD,fe=V.axD;for(let Y=0;Y<Qv&&Q-j>qv&&!(z&&Math.abs(fe-te)<=Hl);Y++){let J=.5*(j+Q),re=p(J),pe=$(re);K(pe)?(Q=J,ne={p:re,r:pe},fe=pe.axD??fe):(j=J,te=pe.axD??te)}if(ne){let{p:Y,r:J}=ne,re=J.axD!==void 0&&J.locked!==void 0?{axD:J.axD,locked:J.locked}:S(Y);L.push({p:Y,axA:J.axA??A(Y),...re})}}}P.push(...L),P.sort((E,_)=>E.p.steerDeg-_.p.steerDeg);let D=E=>E.axA+T+E.p.scrub,I=.001*Math.max(1,M[M.length-1].ayMs),G=[];for(let E=0;E+1<P.length;E++){let _=P[E],V=P[E+1];if(!(D(_)>=0&&D(V)<0))continue;let N=_.p.steerDeg,$=V.p.steerDeg,K=null,z=null;for(let Q=0;Q<Qv&&$-N>qv;Q++){let ne=.5*(N+$),te=p(ne);D({p:te,axA:A(te)})>=0?(N=ne,K=te):($=ne,z=te)}let j=K??z;j&&j.ayMs>_.p.ayMs&&j.ayMs<V.p.ayMs&&G.push({p:j,axA:-(T+j.scrub),steady:!0,...S(j)})}P.push(...G),P.sort((E,_)=>E.p.steerDeg-_.p.steerDeg);let O=!1;for(let{p:E,axA:_,axD:V,steady:N}of P){let $=v.length-1,K=$>=0&&(N||O?!(E.ayMs>v[$]):E.ayMs-v[$]<I);O=N===!0&&!K,K?(x[$]=Math.max(x[$],_),k[$]=Math.min(k[$],V)):(v.push(E.ayMs),x.push(_),k.push(V),F.push(E.scrub))}for(let E=v.length-2;E>=0;E--)x[E]=Math.max(x[E],x[E+1]),k[E]=Math.min(k[E],k[E+1]);return{ayMax:v[v.length-1],ay:v,axAccel:x,axDecel:k,axScrub:F,rollover:u.rollover,atLock:d!==null&&s1(e,d.steerDeg)}}function $L(e,t){let r=e.beta*se,n=0;for(let o of on){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 aW=Math.PI/180,sW={speeds:Array.from({length:23},(e,t)=>8+t),steerMaxDeg:14,steerSteps:29};function c1(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 ca={enabled:!1,kp:3e3,ffLow:150,ffHigh:300,vLow:18,vHigh:25},i1=e=>c1(e.ffLow,e.ffHigh,e.vLow,e.vHigh);var nr={power_limit_kw:{value:0,label:"battery power limit (0 = none)",unit:"kW"},v_limit_endurance:{value:0,label:"endurance speed limit (0 = none)",unit:"km/h"},endurance_reserve:{value:0,label:"endurance energy reserve (0 = flat out)",unit:"%"},grip_scale:{value:1,label:"grip scale (rig \u2192 road)",unit:"-"},stiffness_scale:{value:1,label:"stiffness scale (rig \u2192 road)",unit:"-"},camber_front_deg:{value:0,label:"static camber front (\u2212 top in)",unit:"\xB0"},camber_rear_deg:{value:0,label:"static camber rear (\u2212 top in)",unit:"\xB0"},cg_height:{value:300,label:"CG height",unit:"mm"},tire_vertical_rate:{value:100,label:"tyre vertical rate",unit:"N/mm"},tire_vertical_damping:{value:0,label:"tyre vertical damping",unit:"N\xB7s/mm"},arb_front:{value:20,label:"ARB front (@wheel)",unit:"N/mm"},arb_rear:{value:15,label:"ARB rear (@wheel)",unit:"N/mm"},heave_spring_front:{value:0,label:"Heave spring front (@wheel)",unit:"N/mm"},heave_spring_rear:{value:0,label:"Heave spring rear (@wheel)",unit:"N/mm"},unsprung_mass:{value:8,label:"unsprung mass/corner",unit:"kg"},brake_balance:{value:.6,label:"brake balance (front)",unit:"-"},damper_front:{value:2.5,label:"damper front",unit:"N\xB7s/mm"},damper_rear:{value:2.5,label:"damper rear",unit:"N\xB7s/mm"},cop_long:{value:.5,label:"CoP aft of front",unit:"\xB7wb"},cop_height:{value:300,label:"CoP height",unit:"mm"},ride_height_front:{value:30,label:"static ride height front (laden)",unit:"mm"},ride_height_rear:{value:35,label:"static ride height rear (laden)",unit:"mm"},I_yaw:{value:295,label:"yaw inertia Izz",unit:"kg\xB7m\xB2"},I_roll:{value:95,label:"roll inertia Ixx",unit:"kg\xB7m\xB2"},I_pitch:{value:380,label:"pitch inertia Iyy",unit:"kg\xB7m\xB2"},I_wheel:{value:0,label:"rotating inertia per wheel",unit:"kg\xB7m\xB2"},I_rotor:{value:0,label:"driveline inertia at the motor",unit:"kg\xB7m\xB2"},ackermann_pct:{value:50,label:"Ackermann",unit:"%"},toe_front_deg:{value:0,label:"static toe front (+ in)",unit:"\xB0"},toe_rear_deg:{value:0,label:"static toe rear (+ in)",unit:"\xB0"},spring_front:{value:35,label:"spring front (@spring)",unit:"N/mm"},spring_rear:{value:40,label:"spring rear (@spring)",unit:"N/mm"},mr_front:{value:1,label:"motion ratio front",unit:"-"},mr_rear:{value:1,label:"motion ratio rear",unit:"-"},track_front:{value:1200,label:"track front",unit:"mm"},track_rear:{value:1200,label:"track rear",unit:"mm"},wheelbase:{value:1535,label:"wheelbase",unit:"mm"},rc_front:{value:30,label:"roll centre front",unit:"mm"},rc_rear:{value:40,label:"roll centre rear",unit:"mm"},tv_enabled:{value:0,label:"torque vectoring",unit:"0/1"},tv_kp:{value:3e3,label:"TV yaw-rate gain",unit:"N per rad/s"},tv_ff_low:{value:150,label:"TV feedforward, low speed",unit:"N"},tv_ff_high:{value:300,label:"TV feedforward, high speed",unit:"N"},tv_v_low:{value:18,label:"TV feedforward ramp start",unit:"m/s"},tv_v_high:{value:25,label:"TV feedforward ramp end",unit:"m/s"}},GL=["k_yaw","k_roll","k_pitch"];function Ws(e){for(let t of GL)delete e[t];for(let t of Object.keys(nr)){let r=e[t];if(!r){e[t]={...nr[t]};continue}e[t]={...r,label:nr[t].label,unit:nr[t].unit}}return e}function Z(e,t){return e[t]?.value??nr[t].value}function Ul(e){let t=(r,n)=>e[r]?.value??n;return{enabled:t("tv_enabled",0)>=.5,kp:t("tv_kp",ca.kp),ffLow:t("tv_ff_low",ca.ffLow),ffHigh:t("tv_ff_high",ca.ffHigh),vLow:t("tv_v_low",ca.vLow),vHigh:t("tv_v_high",ca.vHigh)}}var l1=[10,25,50,100,200,300];function Sh(e,t,r,n,o){let s=l1.map(i=>Math.round(i<=25?r*i:r*25+n*(i-25)));return{id:e,label:t,speedMmS:[...l1],reboundN:s,bumpN:s.map(i=>Math.round(i*o))}}var Xl={name:"Generic FS damper",curves:[Sh("c1","Soft",1.6,1,.65),Sh("c2","Medium",3,1.6,.65),Sh("c3","Firm",8,2.4,.65)]};function ql(e){let t=e.curves.length;return t>0?e.curves[Math.floor((t-1)/2)].id:""}var sn=25;function la(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 u1(e,t){return t>=0?la(e.rebound,t):-la(e.bump,-t)}function m1(e,t,r){return t*u1(e,t*r)}var Ah=(e,t)=>e.curves.find(r=>r.id===t);function js(e,t){let r=Ah(e,ql(e)),n=(t&&Ah(e,t.bump))??r,o=(t&&Ah(e,t.rebound))??r;return{bump:{speedMmS:n?.speedMmS??[],forceN:n?.bumpN??[]},rebound:{speedMmS:o?.speedMmS??[],forceN:o?.reboundN??[]}}}var Ql=5e3;function Us(e,t){let r=t>0?t:1,n=[],o=[],a=e.bump.speedMmS.map(c=>c/r).filter(c=>c<Ql),s=e.rebound.speedMmS.map(c=>c/r).filter(c=>c<Ql),i=c=>{n.push(c),o.push(m1(e,r,c))};i(-Ql);for(let c=a.length-1;c>=0;c--)i(-a[c]);i(0);for(let c of s)i(c);return i(Ql),{kind:"map",input:"velocity",x:n,y:o}}var Fh=64;function Xs(e,t,r){let n=t>0?t:1,o=Math.max(r,1e-6),a=0;for(let s=0;s<Fh;s++){let i=Math.sin((s+.5)*Math.PI/Fh),c=n*o*i;a+=n*(la(e.rebound,c)+la(e.bump,c))*i}return a*(Math.PI/Fh)/(Math.PI*o)}function Vn(e,t,r,n,o=e){let a=(c,l,u)=>{if(!c||c.curves.length===0)return;let m=js(c,l);return{law:m,curve:Us(m,u),rate:Xs(m,u,sn)}},s=a(e,t?.front,r),i=a(o??e,t?.rear,n);return!s&&!i?null:{...s?{front:s}:{},...i?{rear:i}:{}}}var p1=(e,t)=>({...e,y:e.y.map(r=>r*t)}),KL=e=>({...e,x:e.x.map(t=>-t).reverse(),y:e.y.map(t=>-t).reverse()});function wh(e,t,r){let n=Math.abs(r)>0?Math.abs(r):1,o=js(e,t);return{law:o,curve:p1(Us(o,n),.5),rate:Xs(o,n,sn)/2,mr:n,ratio:n,share:.5}}function Ch(e,t,r,n,o){let a=n*(Math.abs(r)>0?Math.abs(r):1),s=js(e,t),i=p1(Us(s,a),1/n);return{law:s,curve:o?KL(i):i,rate:Xs(s,a,sn)/n,mr:a/n,ratio:a,share:1/n}}function qs(e,t){let r=e.damperModelIdRear?t(e.damperModelIdRear):void 0,n=e.heaveDamperModelId?t(e.heaveDamperModelId):void 0,o=e.rollDamperModelId?t(e.rollDamperModelId):void 0;return{...r?{damperModelRear:r}:{},...n?{heaveDamperModel:n}:{},...o?{rollDamperModel:o}:{}}}function Qs(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 Er(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 Js(e){return e.kind==="coil"?2:1}function Zs(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 f1(e){return Zs(e)/2}function h1(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 d1(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 HL(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 ei(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*Zs(e.section)/e.barLength,a=2*o/(n*n),s=f1(e.armSection??e.section),i=3*e.E*s/n**3,c=e.dropLinkRate??1/0;return{rateAtLink:d1([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*Zs(e.section)/e.barLength,a=2*o/(n*n),s=3*e.E*h1(e.blade)/n**3,i=e.dropLinkRate??1/0;return{rateAtLink:d1([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*Zs(e.section)/e.length,a=2*o/(n*n);return{rateAtLink:a,contributions:{barTwist:a},torsional:o}}case"coil":{let n=Er(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=HL(e.linkTravel,e.force,t);return{rateAtLink:Math.max(0,n),contributions:{},torsional:0}}}}function Zl(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?pd(t,r):1,o=t?dd(t,r):0,a=ei(e,o).rateAtLink;return{wheelRate:Math.max(0,a*n*n),motionRatio:n,rateAtLink:a}}function ti(e,t){let r=e.damper??0;return!r||e.design.kind==="none"?0:Js(e.design)*r*t*t}var zL=150;function YL(e){return X(e,[0,-.5,1])<-1e-9?U(e,-1):e}function b1(e){let t=e.hardpoints,r=H(t.rockerPivotB,t.rockerPivotA),n=ee(t.rockerPivotA,U(H(t.rockerToDamper,t.rockerPivotA),.6)),o=YL(q(ae(r,H(t.rockerToDamper,t.rockerPivotA))));return{outer:n,inner:ee(n,U(o,zL)),attach:"rocker"}}function Ct(e,t){let r={};for(let o of Lo)r[o]=et($e(e,o));let n={vehicle:e,ctx:r};return t&&(n.kc=Yc(n,t)),n}var Jl=.5;function WL(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 g1=e=>[(e[2][1]-e[1][2])/2,(e[0][2]-e[2][0])/2,(e[1][0]-e[0][1])/2];function eu(e,t,r){let n=Ze(t,e.vehicle.config),o=e.ctx[t],a=r.rigid?void 0:{loadedRadius:r.loadedRadius},s=r.state?null:ge(o,r.travel,r.steer,void 0,a),i=r.state??ot(s),c=ge(o,r.travel+Jl,r.steer,void 0,a),l=ge(o,r.travel-Jl,r.steer,void 0,a),u=(s?s.ok:r.converged)&&c.ok&&l.ok,m=ot(c),f=ot(l),p=(C,T)=>_t(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)],M=C=>WL(R,[p(C,d),p(C,"uprightLower"),p(C,y)]),v=M(m),x=M(f),k=g1(v.rot),F=g1(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*Jl)):w,omega:u?U(H(k,F),1/(2*Jl)):w}}function Th(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 y1(e,t,r){let n=eu(e,t,ft(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 x1(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 R1(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 jL(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 UL=.1*Math.PI/180;function v1(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]))*UL<=o*n}function tu(e,t){return!e.valid||!e.cpLeft||!e.cpRight?!1:v1([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 XL=1;function k1(e){let t=ri(e);if(!t||!e.cpLeft||!e.cpRight||Math.abs(t.left-t.right)>XL)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 ua(e){let t=(n,o,a)=>{if(!n)return Number.NaN;if(!o)return a?0:Number.NaN;let s=n[0]-o[0];return Math.abs(s)>1e-9?n[0]/s:Number.NaN},r=(t(e.cpLeft,e.icLeft,e.lineLeft)+t(e.cpRight,e.icRight,e.lineRight))/2;return e.valid&&Number.isFinite(r)?r:0}function or(e,t,r){let n=r==="front"?"FL":"RL",o=r==="front"?"FR":"RR",a=y1(e,n,t),s=y1(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=x1(a),c=x1(s),l=R1(a,i),u=R1(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=Th(a.cp,f,s.cp,p)??jL(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],M=Math.hypot(y,R)||1,v=y/M,x=R/M,k=(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]-k)*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 Ir(e,t){return{front:or(e,t,"front"),rear:or(e,t,"rear")}}function ru(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 qL(e,t){return{camber:ru(e.travel,e.camber,t),toe:ru(e.travel,e.toe,t),motionRatio:ru(e.travel,e.motionRatio,t),damperLen:e.damperLen?ru(e.travel,e.damperLen,t):0}}var M1=e=>qL(e,0).motionRatio;function Ph(e,t){if(e.kind!=="coil")return null;let r=t??e.motionRatio,n=Er(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 nu(e,t){if(e.kind==="none")return 0;if(e.kind==="tabulated"){let n=a=>QL(e,a);return(n(.5)-n(-.5))/(2*.5)/2}if((e.gap??0)>0)return 0;let r=t??e.motionRatio;return Er(e.rate,0)*r*r/2}function ni(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 QL(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 Lh={kind:"coil",rate:120,motionRatio:.7,gap:5,bothWays:!1};var S1=new WeakMap;function au(e,t){let r=S1.get(e);r||(r=new Map,S1.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=kn(e,t);return r.set(n,a),a}var ZL=32,oi=new Map,A1=new WeakMap,JL=1;function eD(e){let t=A1.get(e);return t===void 0&&(t=JL++,A1.set(e,t)),t}function Dh(e,t){if(!t.linkage)return null;let r=Qr(e,t.linkage,t.design.kind),n=`${eD(e)}|${r?"unit":"bar"}|${JSON.stringify(t.linkage)}`,o=oi.get(n);if(o)return o;let a=Oo(e,t.linkage,{kind:t.design.kind});return oi.size>=ZL&&oi.delete(oi.keys().next().value),oi.set(n,a),a}function $n(e,t,r=0){let n=(o,a)=>{if(!(!o||o.design.kind==="none"))return Zl(o.design,Dh(a,o),r).wheelRate};return{front:n(t.arbFrontDesign,e.front),rear:n(t.arbRearDesign,e.rear)}}function ma(e,t){let r=(n,o)=>{if(!n||n.design.kind==="none")return;let a=n.linkage?au(o,n.linkage).atDesign:void 0;return nu(n.design,a)};return{front:r(t.heaveFrontDesign,e.front),rear:r(t.heaveRearDesign,e.rear)}}function P1(e,t){let r=(a,s)=>{if(!a||a.design.kind!=="coil")return;let i=a.linkage?au(s,a.linkage).atDesign:void 0;return Ph(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 su(e,t){let r=(o,a)=>o?ni(o,Eh(o,a)):0,n=(o,a)=>o?ti(o,Ih(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 Eh=(e,t)=>e.linkage?au(t,e.linkage).atDesign:void 0,Ih=(e,t)=>Zl(e.design,Dh(t,e),0).motionRatio;function L1(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=Eh(f,p);if(ni(f,h)>0)return wh(n,r?.[d],h??(f.design.kind==="coil"?f.design.motionRatio:1))},s=(f,p,d)=>{if(!f||!o?.curves.length)return;let h=Ih(f,p);if(!(ti(f,h)>0))return;let b=Dh(p,f)!==null;return Ch(o,r?.[d],h,Js(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 D1(e,t){let r=t.heaveDamperModel??t.damperModel,n=t.rollDamperModel??t.damperModel,o=(i,c)=>Bn(i)?{source:"none"}:Qs(i.config.coilover,c),a=(i,c)=>{if(!i)return{source:"none"};let l=ni(i,Eh(i,c))>0;return Qs(i.coilover,l?r:void 0)},s=(i,c)=>{if(!i||i.design.kind!=="coil")return{source:"none"};let l=ti(i,Ih(i,c))>0;return Qs(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 E1(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 Bn=e=>e.config.actuation==="decoupled",Gn="a decoupled axle damps in its heave and roll elements, set below";function I1(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}=$n(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?au(f,m.linkage).atDesign:void 0;o(p,nu(m.design,d))}let i=rD(e,t,r),c=tD(e,i);n.kinFront=c.kinFront,n.kinRear=c.kinRear;let l=aD(e,i);n.steerFront=c.steerFront,Number.isFinite(l.ackermannPct)&&o("ackermann_pct",l.ackermannPct);let u=m=>Bn(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"]])Bn(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"]])Bn(m)&&(o(f,0),n.readouts={...n.readouts,[f]:Gn});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 tD(e,t){return{kinFront:w1(e.front),kinRear:w1(e.rear),steerFront:e.front.measured?void 0:iu(e.front,t)}}var F1=new WeakMap;function w1(e){let t=F1.get(e);return t||F1.set(e,t=jo(e)),t}function rD(e,t,r={}){return nD(e,t,r.front,r.rear)}function nD(e,t,r,n){let o=e.front.config.loadedRadius;if(!((er(r??t.tireModel)??0)>0))return o;let a={...t,surveyedRadiusFront:o,surveyedRadiusRear:e.rear.config.loadedRadius};return cu(a,r,n).front??o}var C1=new WeakMap;function iu(e,t=e.config.loadedRadius){let r=C1.get(e);r||(r=new Map,C1.set(e,r));let n=r.get(t);if(n)return n;let o=t===e.config.loadedRadius?void 0:{loadedRadius:t},a=Ld(e,Nt(e.config),void 0,void 0,void 0,void 0,o);return r.size>=4&&r.clear(),r.set(t,a),a}var T1=new WeakMap;function oD(e){return qe(e,{travelMin:-1,travelMax:1,steps:3}).samples[1].metrics.motionRatio??1}var ou=e=>e.measured?M1(e.measured):oD(e);function aD(e,t=e.front.config.loadedRadius){let r=()=>e.front.measured?void 0:iu(e.front,t);return{...sD(e),get steerFront(){return r()},get ackermannPct(){let n=r();return n?Dd(n,dt(e.front),e.config.wheelbase):Number.NaN}}}function sD(e){let t=T1.get(e);if(t)return t;let r=e.front.measured,n=e.rear.measured,a=!r||!n?Ir(Ct(e),{heave:0,pitch:0,roll:0,steer:0}):null,s={wheelbase:e.config.wheelbase,trackFront:r?r.track:dt(e.front),trackRear:n?n.track:dt(e.rear),mrFront:ou(e.front),mrRear:ou(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:ua(a.front),rcGainRear:n||!a?0:ua(a.rear),rcFrontValid:r?!0:!!a?.front.valid,rcRearValid:n?!0:!!a?.rear.valid};return T1.set(e,s),s}var bt={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}},O1=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),ar=(e,t,r,n=1/0)=>typeof e=="number"&&Number.isFinite(e)?Math.min(n,Math.max(r,e)):t;function Kn(e){if(O1(e))switch(e.kind){case"open":case"spool":return{kind:e.kind};case"clutch":{let t=bt.clutch;return{kind:"clutch",preloadNm:ar(e.preloadNm,t.preloadNm,0),rampDriveDeg:ar(e.rampDriveDeg,t.rampDriveDeg,1,90),rampCoastDeg:ar(e.rampCoastDeg,t.rampCoastDeg,1,90),faces:Math.round(ar(e.faces,t.faces,0)),muClutch:ar(e.muClutch,t.muClutch,0,1),rFrictionMm:ar(e.rFrictionMm,t.rFrictionMm,1),rRampMm:ar(e.rRampMm,t.rRampMm,1)}}case"torsen":{let t=bt.torsen,r=ar(e.preloadNm,0,0);return{kind:"torsen",tbrDrive:ar(e.tbrDrive,t.tbrDrive,1),tbrCoast:ar(e.tbrCoast,t.tbrCoast,1),...r>0?{preloadNm:r}:{}}}default:return}}function lu(e){if(!O1(e))return;let t=Kn(e.front),r=Kn(e.rear);return t||r?{...t?{front:t}:{},...r?{rear:r}:{}}:void 0}function ai(e){let t=tn(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=ai(e),r=e.r_dyn.value,n=s=>{if(t[s]!=="diff")return;let i=Kn(e.driveline?.[s]);if(!(!i||i.kind==="independent"))return{kind:i.kind,drive:Os(i,"drive",r),coast:Os(i,"coast",r),hubs:Os(i,"hubs",r)}},o=n("front"),a=n("rear");return o||a?{...o?{front:o}:{},...a?{rear:a}:{}}:void 0}var iD={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"}},_1=e=>{let t=e==="front"?"Front":"Rear";return Object.fromEntries(Object.entries(iD).map(([r,n])=>[`${e}.${r}`,{section:t,...n}]))},uu={..._1("front"),..._1("rear")},N1=e=>e.motorModel?.kind==="ice"?e.motorPlacement==="front"?"front":"rear":null;function V1(e,t){let r=N1(t);if(!(!r||N1(e)===r||t.driveline?.[r]))return{...t.driveline,[r]:{...bt.clutch}}}function Bt(e,t,r,n){return e>0?!(r>0)||!Number.isFinite(r)?e:Math.max(1,e-t/r):n}function mu(e,t,r){let n=Math.max(0,Math.min(1,r)),o=Bt(e.freeRadius,e.staticLoad,e.tyreRate,e.surveyed),a=Bt(t.freeRadius,t.staticLoad,t.tyreRate,t.surveyed);return n*o+(1-n)*a}function pa(e,t,r){if(t===void 0||r===void 0||!Number.isFinite(t)||!Number.isFinite(r))return e;let n=r-t;return n===0?e:Math.max(1,e+n)}function _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 ii(e,t){if(!e)return lD(t);let r=t-Jr(e,0).camber;return r?{...e,camber:e.camber.map(n=>n+r)}:e}function cD(e){return{kinFront:ii(e.kinFront,Z(e,"camber_front_deg")),kinRear:ii(e.kinRear,Z(e,"camber_rear_deg"))}}function lD(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 B1=9.81,$1=e=>e>1?e/100:e;function da(e,t,r){let n=t??e.tireModel??ks(),o=r??e.tireModelRear??n,a={grip:Z(e,"grip_scale"),stiffness:Z(e,"stiffness_scale")},s=yl(n,a);return{front:s,rear:o===n?s:yl(o,a)}}function sr(e,t,r){let n=da(e,t,r),o=Ie(n.front);return ct(n.rear===n.front?o:ll(o,Ie(n.rear)))}function _h(e,t,r){let n=$1(e.front_mass_diss.value),o=da(e,t,r),a=Ie(o.front),s=o.rear===o.front?a:Ie(o.rear),i=t??e.tireModel,c=r??e.tireModelRear??i,l=e.m.value*B1*n/2,u=e.m.value*B1*(1-n)/2,m=(i?a.verticalStiffness():0)||Z(e,"tire_vertical_rate"),f=(c?s.verticalStiffness():0)||Z(e,"tire_vertical_rate"),p=er(i)??0,d=er(c)??0,h=e.surveyedRadiusFront&&e.surveyedRadiusRear?mu({freeRadius:p,staticLoad:l,tyreRate:m,surveyed:e.surveyedRadiusFront},{freeRadius:d,staticLoad:u,tyreRate:f,surveyed:e.surveyedRadiusRear},n):void 0,b=e.surveyedRadiusFront?Bt(p,l,m,e.surveyedRadiusFront):void 0,g=e.surveyedRadiusRear?Bt(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 cu(e,t,r){let n=_h(e,t,r);return{front:n.standingFront,rear:n.standingRear}}function G1(e,t,r){return _h(e,t,r).cgStandingRadius}function ut(e,t,r){let n=$1(e.front_mass_diss.value),o=Z(e,"mr_front")||1,a=Z(e,"mr_rear")||1,{ev:s,evR:i,Wf:c,Wr:l,tireRate:u,tireRateRear:m,tyreFreeRadius:f,tyreFreeRadiusRear:p,cgStandingRadius:d,standingFront:h,standingRear:b}=_h(e,t,r),g=_s(e),y=si(e),R=Vn(e.damperModel,e.damperSetup,o,a,e.damperModelRear??e.damperModel),M=e.readouts?.damper_front===Gn,v=e.readouts?.damper_rear===Gn,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,Z(e,"cop_long"))),copHeight:Z(e,"cop_height"),...e.aeroModel?{model:e.aeroModel}:{},rideHeightFront:Z(e,"ride_height_front"),rideHeightRear:Z(e,"ride_height_rear")};return{massTotal:e.m.value,frontMassFrac:n,steeringSystem:e.steeringSystem,tv:Ul(e),cgHeight:pa(Z(e,"cg_height"),e.cgReference?.standingRadius,d),...d!==void 0?{cgStandingRadius:d}:{},wheelbase:Z(e,"wheelbase"),trackFront:Z(e,"track_front"),trackRear:Z(e,"track_rear"),wheelRateFront:Z(e,"spring_front")*o*o,wheelRateRear:Z(e,"spring_rear")*a*a,tireRate:u,...m!==u?{tireRateRear:m}:{},tireDamping:Z(e,"tire_vertical_damping"),arbFront:Z(e,"arb_front"),arbRear:Z(e,"arb_rear"),brakeBalanceFront:g.balanceFront,brakes:g,...y?{driveline:y}:{},heaveSpringFront:Z(e,"heave_spring_front"),heaveSpringRear:Z(e,"heave_spring_rear"),unsprungPerCorner:Z(e,"unsprung_mass"),unsprungCgHeight:uD(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(Z(e,"rc_front"),e.rcRoad?.gainFront,e.rcRoad?.radiusFront,h),rcHeightRear:_r(Z(e,"rc_rear"),e.rcRoad?.gainRear,e.rcRoad?.radiusRear,b),corneringStiffnessFront:s.corneringStiffness(c),corneringStiffnessRear:i.corneringStiffness(l),damperFront:R?.front&&!M?R.front.rate:Z(e,"damper_front")*o*o,damperRear:R?.rear&&!v?R.rear.rate:Z(e,"damper_rear")*a*a,...R?.front&&!M?{damperCurveFront:R.front.curve}:{},...R?.rear&&!v?{damperCurveRear:R.rear.curve}:{},aero:x,ackermannPct:Z(e,"ackermann_pct"),toeFrontDeg:Z(e,"toe_front_deg"),toeRearDeg:Z(e,"toe_rear_deg"),yawInertia:Z(e,"I_yaw"),steerFront:e.steerFront,...cD(e)}}function uD(e,t){let r=(a,s,i,c)=>a??(s>0?Bt(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 pu={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 K1(e,t=e.batteryModel){if(!t)return e;let r=fr(t),n=(o,a)=>({...o,value:a});return{...e,capacity:n(e.capacity,r.capacityAh),ocv:n(e.ocv,r.voltageAtFull)}}var z1={damper_front:`the damper part sets it: its front curve at ${sn} mm/s`,damper_rear:`the damper part sets it (the rear's own, where the car names one): its rear curve at ${sn} mm/s`};function du(e){let t=!!(e.damperModelId||e.damperModel),r=t||!!(e.damperModelIdRear||e.damperModelRear);return{...t?{damper_front:z1.damper_front}:{},...r?{damper_rear:z1.damper_rear}:{}}}function Y1(e,t=e.damperModel,r=e.damperModelRear??t){if(!t&&!r)return e;let n=Z(e,"mr_front")||1,o=Z(e,"mr_rear")||1,a=Vn(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!==Gn&&(i.damper_front=s(e.damper_front,"damper front",a.front.rate/(n*n))),a.rear&&e.readouts?.damper_rear!==Gn&&(i.damper_rear=s(e.damper_rear,"damper rear",a.rear.rate/(o*o))),i}var W1={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 Nr(e){return!!e&&typeof e=="object"&&"value"in e&&"label"in e}var hD={Batteriekapazit\u00E4t:"pack capacity",Rollwiderstandsbeiwert:"rolling-resistance coefficient"},U1=e=>hD[e]??e;function fu(e){let t=[];for(let r of Object.keys(e)){if(r==="motor"||r==="name")continue;let n=e[r];Nr(n)&&t.push({key:r,label:U1(n.label),value:n.value,unit:n.unit})}return t}var bD=[{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"]}],gD=.5,j1=e=>e==="infinite"?1/0:typeof e=="number"?e:null,yD=e=>/front/.test(e)?e.replace("front","rear"):/rear/.test(e)?e.replace("rear","front"):null,OU=(()=>{let e=W1.rows,t=o=>{let a=yD(o),s=j1(e[o]?.score),i=a&&e[a]?j1(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>=gD&&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 Nh={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 X1(e){let t=new Map;for(let a of fu(e))t.set(a.key,a);let r=new Set,n=[];for(let a of bD){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=fu(e).filter(a=>!r.has(a.key));return o.length&&n.push({title:"Other",rows:o}),n}var Oh={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"},Vh={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"},q1=e=>!!(e.aeroModelId||e.aeroModel);function xD(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 RD=e=>!!(e.batteryModelId||e.batteryModel);function vD(e,t){let r={};return t.geometry&&Object.assign(r,Nh,xD(e)),q1(e)&&Object.assign(r,Oh),RD(e)&&Object.assign(r,pu),Object.assign(r,du(e)),e.readouts&&Object.assign(r,e.readouts),r}function Q1(e,t){let r=vD(e,t);return q1(e)||Object.assign(r,Vh),r}function Bh(e){let t=e.cop_long;return Nr(t)?1-t.value:.5}function kD(e,t){let r=e.front_aero_diss,n=e.cop_long;!Nr(r)||!Nr(n)||(t===r.label?n.value=1-r.value:t===n.label&&(r.value=1-n.value))}function MD(e,t){kD(e,t);let r=e.c_l,n=e.c_w,o=e.l_to_d_ratio;!Nr(r)||!Nr(n)||(t===r.label||t===n.label?Nr(o)&&n.value!==0&&(o.value=r.value/n.value):Nr(o)&&t===o.label&&o.value!==0&&(n.value=r.value/o.value))}function hu(e,t,r){let n=!1;for(let o of Object.keys(e)){if(o==="motor"||o==="name")continue;let a=e[o];if(Nr(a)&&U1(a.label)===t){a.value=r,n=!0;break}}return n&&MD(e,t),n}function bu(e,t,r=0,n,o){let a=()=>({cl:e.c_l.value,cw:e.c_w.value,frontShare:Bh(e),A:e.A.value,platform:null});if(!e.aeroModel)return a();let s=Yr(n??ut(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:Bh(e),A:s.area,platform:s}}var Z1=e=>typeof e=="object"&&e!==null&&typeof e.value=="number"&&typeof e.label=="string";function J1(e,t=e.aeroModel){if(!t)return e;let r=zr(t,{wheelbase:Z(e,"wheelbase")}).at(Z(e,"ride_height_front"),Z(e,"ride_height_rear")),{cl:n,balanceFront:o}=Ip(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(Z1(e.cop_long)?e.cop_long:void 0,nr.cop_long,1-o)};return Z1(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 ci={dsTarget:.25,accelStep:.25,vTol:.002,scanSteps:24,seamIters:8,fitSpacing:1},SD=32;function ek(e,t,r){let n=Math.round(e/t);return Math.max(1,Math.min(Number.isFinite(n)?n:1,Math.floor(r/SD)||1))}function at(e){let t=ci,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 tk=Math.PI/180,gu=.02,rk=new WeakMap;function li(e){let t=rk.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)*tk,l=(e.bank?.[i]??0)*tk,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 rk.set(e,s),s}function yu(e,t,r){return e.n0[t]+e.k[t]*r*r}function nk(e,t){return e.k[t]<0?Math.sqrt(Math.max(0,e.n0[t])/-e.k[t]):1/0}function ok(e,t){if(!e)return null;let r=1/0,n=-1/0;for(let o=0;o<e.n0.length;o++){let a=yu(e,o,t[o]??0);a<r&&(r=a),a>n&&(n=a)}return r>=1-gu&&n<=1+gu?null:{lo:r,hi:n}}var fa=[.1,.25,.5,.75,1,1.25,1.5,2,2.5];function ak(e){let t=e.lo>=1-gu?1:1-1.25*(1-e.lo)-.05,r=e.hi<=1+gu?1:1+1.25*(e.hi-1)+.05,n=[...fa].reverse().find(a=>a<=t)??fa[0],o=fa.find(a=>a>=r)??fa[fa.length-1];return fa.filter(a=>a>=n&&a<=o)}function $h(e,t,r){return r<1?Math.max(e,t):Math.min(e,t)}function sk(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):$h(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 xu(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}=AD(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,M=4*y*(1-g),v=F=>{let{v:w,gear:C,tau:T,target:S}=F;d=0,h=0,b=0;for(let A=0;A<s;A++){let P=i(A),L=e[P];for(let G=0;T<=0&&G<n.count;G++){let O=C;if(w<L-1e-9?n.best(w)>C&&(n.rpm(w,C)>=n.limitRpm||c[A]>=w*M)?O=C+1:C>0&&w<n.vIdle(C)&&(O=C-1):L<w-1e-9&&C>0&&n.best(l[A])<C&&n.rpm(w,C-1)<=n.limitRpm&&(O=C-1),O===C)break;S=O,O>C?d++:h++,T=O>C?y: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 I=L;if(!D)w<L&&(I=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 G=o(A,w,g>0?g*n.share(w,C):0),O=Math.min(L,Math.sqrt(Math.max(0,w*w+2*G*t[A]))),W=w+O>0?2*t[A]/(w+O):1/0;if(W<=T)I=O,b+=W,T-=W;else{let E=Math.min(L,Math.max(0,w+G*T)),_=Math.max(0,t[A]-(w+E)*.5*T);b+=T,T=0,C=S,I=Math.min(L,Math.sqrt(Math.max(0,E*E+2*o(A,E,n.share(E,C))*_)))}}else{let G=w+I>0?2*t[A]/(w+I):0;b+=Math.min(G,T),T-=G,T<=0&&(C=S)}w=I}return{v:w,gear:C,tau:T,target:S}},x=n.best(e[0]),k={v:e[0],gear:x,tau:0,target:x};if(r)for(let F=0;F<6;F++){let w=v(k),C=Math.abs(w.v-k.v)<=1e-9&&w.gear===k.gear&&w.target===k.target&&Math.abs(w.tau-k.tau)<=1e-12;if(k=w,C)break}else{let F=v(k);u[a-1]=F.v,m[a-1]=F.gear+1,f[a-1]=n.rpm(F.v,F.gear),p[a-1]=F.tau>0?1:0}return{v:u,gear:m,rpm:f,shifting:p,upshifts:d,downshifts:h,gapTime:b}}function AD(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 Gh=.001,Kh=9.81,ui=(e,t)=>Hh(e?.gradient?.[t]??0);function Hh(e){return e===0?0:-Kh*Math.sin(e*Math.PI/180)}function ln(e,t){let r=new Array(t);for(let n=0;n<t;n++)r[n]=Hh(e?.[n]??0);return r}var cn=(e,t)=>{let r=e?.mu?.[t];return r!=null&&r>0?r:1},Hn=(e,t)=>e?.bank?.[t]??0;function FD(e,t,r,n,o,a){let s=e.ay(t,r,cn(o,a)),i=Hn(o,a);if(!i)return s;let c=i*Math.PI/180,l=n===0?0:-Math.sign(n)*Kh*Math.sin(c);return Math.max(0,(s+l)/Math.cos(c))}function Ye(e,t){if(!t)return e;let r=t*Math.PI/180;return e*Math.cos(r)+Kh*Math.sin(r)}function zh(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 zn=(e,t,r)=>t?t(r):e,wD=1e-4;function ha(e,t,r,n,o,a,s){let i=at(r),c=[];for(let l=0;l<t.length;l++){let u=t[l],m=Math.abs(u),f=zn(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:zh(b=>b*b*m-FD(f,b,0,u,n,l),Gh,d,i.scanSteps,Math.min(i.vTol,wD));c.push({v:h,ax:0,ay:h*h*u})}return c}function CD(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=Ye(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=zh(p=>u(p)-t.v,Gh,r.v,a.scanSteps,a.vTol),r.ay=r.v*r.v*n;let f=Math.abs(Ye(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 TD(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(Ye(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 ik(e,t,r,n,o,a){let s=at(n),i=r.npts,c=0;for(let l=0;l<s.seamIters;l++){let u=0;c++;for(let m=i-1;m>=0;m--){let f=(m+1)%i;u=Math.max(u,CD(zn(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],s,cn(r,m),ui(r,m),Hn(r,m),a?p=>a(m,p):void 0))}if(u<=s.vTol)break}return c}function ck(e,t,r,n,o,a){let s=at(n),i=r.npts,c=0;for(let l=0;l<s.seamIters;l++){let u=0;c++;for(let m=0;m<i;m++){let f=(m+1)%i;u=Math.max(u,TD(zn(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],cn(r,m),ui(r,m),Hn(r,m),a?a[m]:1))}if(u<=s.vTol)break}return c}function PD(e,t,r){let n=r.load?li(t):null;if(!n||!r.load)return{pick:r.envelope};let o=t.npts;return{pick:sk(n,r.load,e,r.envelope),cap:a=>nk(n,a%o),n:(a,s)=>yu(n,a,s)}}function lk(e,t,r,n,o,a,s){return xu(n,r.ds,o,a,(i,c,l)=>{let u=c*c*r.curvature[i];return zn(e,t,i).axAccel(c,Math.abs(Ye(u,Hn(r,i))),cn(r,i),s?l*s[i]:l)+ui(r,i)})}function uk(e,t){return{gear:e.gear.slice(0,t),engineRpm:e.rpm.slice(0,t),shifting:e.shifting.slice(0,t)}}function mk(e,t,r,n){if(!e.scrub)return{};let o=!1,a=n.map((s,i)=>{let c=zn(e,t,i),l=Ye(s*s*r.curvature[i],Hn(r,i)),u=c.scrub?c.scrub(s,Math.abs(l),cn(r,i)):0;return u!==0&&(o=!0),u});return o?{axScrub:a}:{}}function gt(e,t,r,n={}){let o=at(r),a=t.npts,s=t.closed&&!n.standingStart,{pick:i,cap:c,n:l}=PD(e,t,n),u=n.driveDerate,m=n.brakeFade;if(!s)return LD(e,t,o,n.standingStart===!0,i,u,n.vCeiling,m,c,l,n.shifts);let f=ha(e,t.curvature,o,t,i,n.vCeiling,c),p=ik(e,f,t,o,i,m),d=ck(e,f,t,o,i,u),h=n.shifts?lk(e,i,t,f.map(M=>M.v),!0,n.shifts,u):void 0;if(h)for(let M=0;M<a;M++)f[M].v=h.v[M];for(let M=0;M<a;M++){let v=f[M];v.ay=v.v*v.v*t.curvature[M];let x=f[(M+1)%a].v;v.ax=(x*x-v.v*v.v)/(2*t.ds[M])}let b=f.map(M=>M.v),g=f.map(M=>M.ax),y=f.map(M=>M.ay),R=0;for(let M=0;M<a;M++){let v=b[M]+b[(M+1)%a];v>0&&(R+=2*t.ds[M]/v)}return{states:f,v:b,ax:g,ay:y,laptime:R,sweeps:{backward:p,forward:d},...l?{loadFactor:b.map((M,v)=>l(v,M))}:{},...mk(e,i,t,b),...h?uk(h,a):{}}}function LD(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=ha(e,d,r,t,o,s,c);n&&(h[0].v=0);for(let R=f-1;R>=0;R--){let M=h[R],v=h[R+1];if(M.v<=v.v)continue;let x=zn(e,o,R),k=w=>{let C=Ye(w*w*t.curvature[R],Hn(t,R)),T=(i?x.axDecel(w,Math.abs(C),cn(t,R),i(R,w)):x.axDecel(w,Math.abs(C),cn(t,R)))+ui(t,R);return Math.sqrt(Math.max(0,w*w+2*T*t.ds[R]))},F=n&&R===0?M.v:Gh;M.v=zh(w=>k(w)-v.v,F,M.v,r.scanSteps,r.vTol)}for(let R=0;R<f;R++){let M=h[R],v=h[R+1];M.ay=M.v*M.v*t.curvature[R];let x=Ye(M.ay,Hn(t,R));M.ax=zn(e,o,R).axAccel(M.v,Math.abs(x),cn(t,R),a?a[R]:1)+ui(t,R),v.v=Math.min(v.v,Math.sqrt(Math.max(0,M.v*M.v+2*M.ax*t.ds[R])))}let b=u?lk(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 M=h[R].v+h[R+1].v;M>0&&(g+=2*t.ds[R]/M)}let y=h.slice(0,m);for(let R=0;R<m;R++){let M=y[R];M.ay=M.v*M.v*t.curvature[R];let v=R<f?h[R+1].v:M.v;M.ax=t.ds[R]>0?(v*v-M.v*M.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,M)=>l(M,R.v))}:{},...mk(e,o,t,y.map(R=>R.v)),...b?uk(b,m):{}}}var pk=(e,t)=>{let r=e[t]?.value;return Number.isFinite(r)&&r>0?r:0};function Yn(e,t,r){let n=e.m.value,o=e.r_dyn?.value??0,a=pk(e,"I_wheel"),s=e.motorModel?.kind==="ice"?0:pk(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 Wn(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 mi=36e5,bk=Math.PI*2,Yh=e=>Math.max(0,Math.min(1,e));function Wh(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=vc(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/bk),l=Math.max(0,i*o/(n*a)),u=r.efficiency(c,l);return u>.01?u:.5}}var dk=new WeakMap;function ba(e){if(e.batteryModel)return e.batteryModel;let t=e.capacity.value,r=e.ocv.value,n=dk.get(e);if(n&&n.capacityAh===t&&n.ocv===r)return n.model;let o=Mp(t,r);return dk.set(e,{capacityAh:t,ocv:r,model:o}),o}function jh(e){let t=e.params,r=Wf(t,El(e));if(mt(t.motorModel)||lt(t).mode!=="hydraulic")return r;let n;return(o,a,s,i=0)=>{if(!(o>0))return 0;n??=DD(e);let c=$l(n.inp,n.ev,o,a,i);return c?Math.min(o,c.regenFront+c.regenRear):r(o,a,s)}}var fk=new WeakMap;function DD(e){let t=e.params,r=fk.get(t);if(!r){let n=wr(t);r={inp:ut(n.regen?t:{...t,energy:{...n,regen:!0}}),ev:sr(t)},fk.set(t,r)}return r}var pi=e=>e.airTempC??St;function Ru(e,t){return e.thermal?e.thermal.startC??t:Mo}function hk(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 gk=()=>({windingC:[],derate:[],lossW:[],torqueNm:[],ampsRms:[]});function ED(e){let t=e.motorModel;if(!t?.thermal)return;let r=Sp(t.thermal),n=vc(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/bk),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 ID(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 _D(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 ND(e){let{drivenFront:t,drivenRear:r}=Wn(e);return Yn(e.params,t,r)}function ga(e,t,r,n,o=Fr,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?ut(m):void 0,g=Wh(m),y=fr(ba(m)),R=y.chargeC,M=Yh(a??m.soc.value),v=pi(m),x=s??Ru(y,v),k=x,F=0,w=0,C=0,T=0,S=-1,A=-1,P=-1,L=ED(m),D=L?L.th.startC:0,I=D,G=0,O=1,W=-1,E=0,_=0,V=jh(e),N=m.motorModel?.kind==="ice",$=u?.scrub,K=$?d/ND(e).tractionFactor:0,z=Math.min(t.length,r.length);for(let j=0;j<z;j++){let Q=r[j],ne=Q*Q,te=n[j]-(c?.[j]??0),{cl:fe,cw:Y,A:J}=bu(m,Q,te/9.81,b),re=.5*f*fe*J*ne,pe=.5*f*Y*J*ne,de=(h+re)*-p,ie=$?-K*($[j]??0):0,oe=de+pe+ie+d*te,ue=oe*t[j],Ve=j+1<r.length?r[j+1]:Q,Ae=.5*(Q+Ve),le=Ae>0?t[j]/Ae:0,Re=0,we=M,Ge=x,We=0,be=0,Fe=le;if(N){oe>0&&(be=ue/g(Q,oe),F+=be/mi),l?.netKwh.push(F-w),l?.powerKw?.push(le>0?be/le/1e3:0);continue}if(oe>0){let ye=ue/g(Q,oe),me=ID(y,ye,le,M,x);me.short&&S<0&&(S=j),me.cutoff&&A<0&&(A=j);let Te=M*R,Se=Math.min(me.dq,Te),Ke=me.dq>0?Se/me.dq:1;Se>=Te&&P<0&&(P=j),F+=me.energyJ*Ke/mi,be=me.energyJ*Ke,Fe=me.seconds,C+=me.lossJ*Ke,T+=Se,le>0&&(We=Se/me.seconds),M=Yh(M-Se/R),x=hk(y,x,me.dq>0&&le>0?Se/le:0,me.lossJ*Ke,le,v),x>k&&(k=x),Re=oe}else if(o.regen){let ye=u?Ye(u.ay[j],u.bank?.[j]??0)/9.81:0,me=V(-oe,Q,te/9.81,ye),Te=o.regenEfficiency*me*t[j],Se=_D(y,Te,le,M,x),Ke=(1-M)*R,je=Math.min(Se.dq,Ke),Gt=Se.dq>0?je/Se.dq:1;w+=Se.energyJ*Gt/mi,be=-Se.energyJ*Gt,C+=Se.lossJ*Gt,T-=je,le>0&&(We=-je/le),M=Yh(M+je/R),x=hk(y,x,je>0&&le>0?-je/le:0,Se.lossJ*Gt,le,v),x>k&&(k=x),Re=-me*Gt}if(l?.netKwh.push(F-w),l?.powerKw?.push(le>0?be/Fe/1e3:0),l?.pack){let ye=l.pack;ye.soc.push(we),ye.amps.push(We),ye.volts.push(y.ocv(we)-We*y.resistance(we,Ge)),ye.cellC.push(Ge)}if(L){let ye=L.rpm(Q),me=L.th.derate(ye,D,L.peak(ye));me<O&&(O=me),me<1&&W<0&&(W=j),_+=le,me<1&&(E+=le);let Te=L.torque(Re,ye,me),Se=L.th.lossW(ye,Te,D);G+=Se*le,i&&(i.windingC.push(D),i.derate.push(me),i.lossW.push(Se),i.torqueNm.push(Te),i.ampsRms.push(L.amps(Te))),D=L.th.step(D,Se,le),D>I&&(I=D)}}return{drive:F,regen:w,net:F-w,chargeAh:T/3600,loss:C/mi,socEnd:M,shortAt:S,cutoffAt:A,emptyAt:P,tempEndC:x,tempMaxC:k,...L?{motorTempEndC:D,motorTempMaxC:I,motorLossKwh:G/mi,motorDerateMin:O,motorDerateAt:W,motorDerateTimeFrac:_>0?E/_:0}:{}}}var OD=.5,VD=.02,BD=6;function yk(e,t,r,n,o,a,s,i){let c=n(),l=1,u=d=>{let h=gk(),b=ga(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<BD;d++){let h=n(f);l++;let b=Math.abs(h.laptime-c.laptime);if(c=h,m=u(c),b<VD){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]+OD*((g[R]??1)-f[R]);f=y}return{lap:c,derate:f,solves:l,converged:p,peakWindingC:m.peak,derateTimeFrac:m.frac}}var $D=.1;function xk(e){let t=e.power_limit_kw?.value??0;return t>0?t*1e3:0}function Uh(e,t,r){return e.motorModel?.kind==="ice"?1/0:fr(ba(e)).maxPower(t??e.soc.value,r,xk(e)).watts}function vu(e,t,r,n){let o=Uh(e,r,n);if(!Number.isFinite(o))return 1/0;if(o<=0)return 0;let a=Math.max($D,t),s=Wh(e),i=o*(e.effi_pgb?.value??.9)/a;return o*s(t,i)/a}var GD=180/Math.PI;function ku(e,t,r,n){let o=e*t,a=e*(1-t);return o/r-a/n}var Mu=e=>e*9.81*GD;var k9=Math.PI/180;function Su(e,t,r,n=0){let o=Le(e,t,0,n),a=typeof r=="function"?r:r.front,s=typeof r=="function"?r:r.rear,i=.5*(a(Math.max(0,o.FL))+a(Math.max(0,o.FR))),c=.5*(s(Math.max(0,o.RL))+s(Math.max(0,o.RR))),l=i>0&&c>0?ku(e.massTotal,e.frontMassFrac,2*i,2*c):0,u=Mu(l),m=u>.15?"understeer":u<-.15?"oversteer":"neutral";return{gradient:u,balance:m,cAlphaFront:i,cAlphaRear:c}}var P9=Math.PI/180,L9=180/Math.PI;var Rk=2220446049250313e-31;function zD(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 YD(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 WD(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])<=Rk*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 M=Math.abs(e[f][f-1])*(Math.abs(d)+Math.abs(h)),v=Math.abs(p)*(Math.abs(e[f-1][f-1])+Math.abs(b)+Math.abs(e[f+1][f+1]));if(M<=Rk*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 M=a<b+3?a:b+3;for(let v=c;v<=M;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 vk(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 zD(r),YD(r),WD(r)}function kk(e){let t=[],r=new Array(e.length).fill(!1),n=vk(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 Xh(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 jD(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 Xh(r,n)}function Au(e,t=r=>jD(e,r)){return kk(e).map(r=>({...r,vector:t(r.eigenvalue)}))}function ya(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 Mk(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 ya(Au(i),c,0)}function Sk(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=Mk({sprungMass:o,unsprungMass:e.unsprungCornerMass??e.unsprungPerCorner,springRate:s,damperRate:n,tireRate:Ue(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 Fu(e,t,r){let n=Ce(e);return{front:Sk(e,n,"front",t??n.rideDampingFront),rear:Sk(e,n,"rear",r??n.rideDampingRear)}}var z9=180/Math.PI;var qh=["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},xa=20,Ak=[ce.zFL,ce.zFR,ce.zRL,ce.zRR],Fk=[ce.vzFL,ce.vzFR,ce.vzRL,ce.vzRR],Or={fzFL:0,fzFR:1,fzRL:2,fzRR:3,fzBody:4,myBody:5,mxBody:6,fx:7,fy:8,mz:9},Qh=10;function wu(e){let t=Array.from({length:xa},()=>new Array(xa).fill(0)),r=Array.from({length:xa},()=>new Array(Qh).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[Ak[i]]-=c,s[Fk[i]]-=l,s[ce.zBody]+=c,s[ce.vzBody]+=l,s[ce.pitch]-=c*e.leverX[i],s[ce.pitchRate]-=l*e.leverX[i],s[ce.roll]+=c*e.leverY[i],s[ce.rollRate]+=l*e.leverY[i]};for(let s=0;s<4;s++){let i=s<2,c=k=>k?i?k.front:k.rear:0,l=e.springRate[s]+c(e.heaveSpring),u=e.springRate[s]+c(e.arb),m=e.damperRate[s]+c(e.heaveDamper),f=e.damperRate[s]+c(e.rollDamper),p=(l+u)/2,d=(l-u)/2,h=(m+f)/2,b=(m-f)/2,g=new Array(xa).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],M=e.leverY[s],v=Ak[s],x=Fk[s];for(let k=0;k<xa;k++){let F=g[k];F!==0&&(t[x][k]+=F/y,t[ce.vzBody][k]-=F/e.bodyMass,t[ce.pitchRate][k]+=R*F/n.yy,t[ce.rollRate][k]-=M*F/n.xx)}t[x][v]-=e.tyreRate[s]/y,t[x][x]-=e.tyreDamping[s]/y,r[x][Or.fzFL+s]=1/y}return r[ce.vzBody][Or.fzBody]=1/e.bodyMass,r[ce.pitchRate][Or.myBody]=1/n.yy,r[ce.rollRate][Or.mxBody]=1/n.xx,r[ce.vx][Or.fx]=1/e.totalMass,r[ce.vy][Or.fy]=1/e.totalMass,r[ce.yawRate][Or.mz]=1/n.zz,{A:t,B:r,params:e}}function Zh(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=Ue(e,"front")*1e3,p=Ue(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 wk=ce.rollRate+1;function Ck(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,wk).map(i=>i.slice(0,wk));if(!n.every(i=>i.every(Number.isFinite)))return{};let a=Au(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 Xh(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:ya(a,s,1),pitch:ya(a,s,2),roll:ya(a,s,3)}}function Tk(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 Cu(e){let t=Ce(e),r=e.wheelbase/1e3,n=r*(1-e.frontMassFrac),o=r*e.frontMassFrac,a=t.rollRateTotal*(180/Math.PI),s=e.rollInertia??t.sprungMass*.6*.6,i=2*t.rideRateFront*1e3,c=2*t.rideRateRear*1e3,l=i*n*n+c*o*o,u=e.pitchInertia??t.sprungMass*1.2*1.2,m=Ck(wu(Zh(e)));return{roll:Tk(m.roll,a,s),pitch:Tk(m.pitch,l,u)}}var Tu=9.81,Vr=Math.PI/180;function Pk(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 Ra(e,t,r,n,o){let{wb:a,lf:s,lr:i,m:c}=Pk(e),l=0;for(let R=0;R<16;R++){let M=l/r,v=o-n-s*M/r,x=-n+i*M/r,k=Le(e,l/Tu,0,r),F=Math.max(0,k.FL+k.FR),w=Math.max(0,k.RL+k.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=Le(e,l/Tu,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/Tu,cn:y/(c*Tu*a)}}function Jh(e,t,r,n={}){let o=Math.max(8,r),a=(n.betaMaxDeg??10)*Vr,s=(n.deltaMaxDeg??10)*Vr,i=n.nLines??9,c=n.nPts??21,l=(g,y,R,M)=>R===1?g:g+(y-g)*M/(R-1),u=[],m={ay:[],cn:[]},f=0;for(let g=0;g<i;g++){let y=l(-s,s,i,g),R=[],M=[],v=[],x=[];for(let k=0;k<c;k++){let F=l(-a,a,c,k),w=Ra(e,t,o,F,y);R.push(w.ay),M.push(w.cn),v.push(F/Vr),x.push(y/Vr),Math.abs(w.ay)>f&&(f=Math.abs(w.ay))}u.push({label:`\u03B4 ${(y/Vr).toFixed(0)}\xB0`,ay:R,cn:M,betaDeg:v,deltaDeg:x});for(let k=1;k<M.length;k++)if(M[k-1]===0||M[k-1]<0!=M[k]<0){let F=M[k-1]===M[k]?0:M[k-1]/(M[k-1]-M[k]);m.ay.push(R[k-1]+F*(R[k]-R[k-1])),m.cn.push(0);break}}let p=[];for(let g=0;g<i;g++){let y=l(-a,a,i,g),R=[],M=[],v=[],x=[];for(let k=0;k<c;k++){let F=l(-s,s,c,k),w=Ra(e,t,o,y,F);R.push(w.ay),M.push(w.cn),v.push(y/Vr),x.push(F/Vr)}p.push({label:`\u03B2 ${(y/Vr).toFixed(0)}\xB0`,ay:R,cn:M,betaDeg:v,deltaDeg:x})}let d=.5*Vr,h=(Ra(e,t,o,d,0).cn-Ra(e,t,o,-d,0).cn)/(2*d),b=(Ra(e,t,o,0,d).cn-Ra(e,t,o,0,-d).cn)/(2*d);return{isoBeta:p,isoDelta:u,trim:m,maxAy:f,stability:h,control:b,speed:o}}function UD(e){return!e.corneringStiffnessFront||!e.corneringStiffnessRear?null:{Cf:2*e.corneringStiffnessFront,Cr:2*e.corneringStiffnessRear}}function di(e,t){let r=UD(e);if(!r)return null;let{Cf:n,Cr:o}=r,{wb:a,lf:s,lr:i,m:c}=Pk(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,M;if(g<0)y=h/2,R=Math.sqrt(Math.max(0,b)),M=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)),M=R>0?-h/(2*R):1}let v=h<0&&b>0,x=ku(c,e.frontMassFrac,n,o),k=Mu(x),F=k>.15?"understeer":k<-.15?"oversteer":"neutral",w=s*n-i*o,C=P=>P*3.6,T=null,S=null;w>1e-6?S=C(Math.sqrt(n*o*a*a/(c*w))):w<-1e-6&&(T=C(Math.sqrt(n*o*a*a/(c*-w))));let A=u/(a+x*u*u);return{stable:v,yawFreq:R/(2*Math.PI),dampingRatio:M,eigReal:y,understeerGradient:k,balance:F,characteristicSpeed:T,criticalSpeed:S,yawRateGain:A}}var Lk=Math.PI/180;function Ik(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 Dk(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 _k(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 Nk(e,t,r){let n=e.isoDelta[0],o=(n.betaDeg[1]-n.betaDeg[0])*Lk||1,a=e.isoDelta.length>1?(e.isoDelta[1].deltaDeg[0]-e.isoDelta[0].deltaDeg[0])*Lk:1,s=x=>_k(e,t,r,x),i=s((x,k)=>x.ay[k]),c=s((x,k)=>x.cn[k]),l=s((x,k)=>x.betaDeg[k]),u=s((x,k)=>x.deltaDeg[k]),m=s((x,k)=>Dk(x.cn,k,o)),f=s((x,k,F)=>Dk(e.isoDelta.map(w=>w.cn[k]),F,a||1)),p=Math.max(1e-6,e.maxAy),d=Math.abs(i)/p,h=Math.max(1e-6,...e.isoDelta.flatMap(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(`${Ik(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 M=Math.abs(e.control),v=M>1e-9?Math.abs(f)/M:1;return v<.15?y.push("The steering has stopped working here: another degree of lock buys almost no yaw moment, which is what a saturated front axle looks like. This is understeer in its literal sense \u2014 the front tyres are already at their limit."):v<.5&&y.push(`Steering response is down to about ${(100*v).toFixed(0)} % of its straight-ahead value \u2014 the front is well into the non-linear part of its curve.`),d>.97?y.push(`At the edge of the diagram: ${Math.abs(i).toFixed(2)} g is essentially all this car has at this speed.`):d<.25&&y.push("Well inside the limit \u2014 this is the linear region the handling balance is measured in."),{ay:i,cn:c,betaDeg:l,deltaDeg:u,stability:m,control:f,gripUsed:d,notes:y}}var Ek=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+Ek)?!0:p<d*(1-Ek)?!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=Nk(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 XD=["tv_kp"];function Ok(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"},...XD.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 qD=Ok(0);function Vk(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 QD=Vk(0);var ZD=9.81;function JD(e){let t=e.wheelbase/1e3;return{lf:t*(1-e.frontMassFrac),lr:t*e.frontMassFrac}}function fi(e,t,r,n){let o=t.tire;if(!o)return null;let s=(r==="limit"?vh(e,o,t.speed):an(e,o,t.speed,t.ayG)).wheels;return xr(n??Nn(o,e.massTotal*ZD*1.2),{FL:s.FL,FR:s.FR,RL:s.RL,RR:s.RR},JD(e))}function eE(e){if(!e.tire)return e.cornerStiffness;let t=xe(e.tire,"front"),r=xe(e.tire,"rear");return{front:n=>t.corneringStiffness(n),rear:n=>r.corneringStiffness(n)}}var Bk=[{key:"understeer",label:"Understeer gradient",unit:"\xB0/g",compute:(e,t)=>Su(e,t.ayG,eE(t),t.speed).gradient},{key:"rollGradient",label:"Roll gradient",unit:"\xB0/g",compute:e=>Ce(e).rollGradient},{key:"pitchGradient",label:"Pitch gradient",unit:"\xB0/g",compute:e=>Ce(e).pitchGradient},{key:"tlltdFront",label:"TLLTD front",unit:"%",compute:e=>100*Id(e)},{key:"rollStiffFront",label:"Front roll-stiffness",unit:"%",compute:e=>100*Ce(e).frontRollStiffFrac},{key:"rideFreqFront",label:"Ride freq front",unit:"Hz",compute:e=>Ce(e).rideFreqFront},{key:"rideFreqRear",label:"Ride freq rear",unit:"Hz",compute:e=>Ce(e).rideFreqRear},{key:"rollFreq",label:"Roll-mode freq",unit:"Hz",compute:e=>Cu(e).roll.freq},{key:"pitchFreq",label:"Pitch-mode freq",unit:"Hz",compute:e=>Cu(e).pitch.freq},{key:"zetaFront",label:"Damping \u03B6 front",unit:"-",compute:e=>Fu(e).front.dampingRatio},{key:"zetaRear",label:"Damping \u03B6 rear",unit:"-",compute:e=>Fu(e).rear.dampingRatio},{key:"yawFreq",label:"Yaw natural freq",unit:"Hz",compute:(e,t)=>di(e,t.speed)?.yawFreq??NaN},{key:"yawZeta",label:"Yaw damping \u03B6",unit:"-",compute:(e,t)=>di(e,t.speed)?.dampingRatio??NaN},{key:"stabilitySpeed",label:"Char./critical speed",unit:"km/h",compute:(e,t)=>{let r=di(e,t.speed);return r?r.criticalSpeed??r.characteristicSpeed??NaN:NaN}},{key:"maxAy",label:"Max lateral accel",unit:"g",compute:(e,t)=>t.fyAxle?Jh(e,t.fyAxle,t.speed,{betaMaxDeg:12,deltaMaxDeg:12}).maxAy:NaN},{key:"yawReserveRear",label:"Yaw stability reserve",unit:"N\xB7m",compute:(e,t)=>fi(e,t,"operating")?.stabil??NaN},{key:"yawReserveFront",label:"Yaw agility reserve",unit:"N\xB7m",compute:(e,t)=>fi(e,t,"operating")?.agil??NaN},{key:"limitBalance",label:"Limit balance (+US / \u2212OS)",unit:"-",compute:(e,t)=>fi(e,t,"limit")?.rel??NaN},{key:"yawStiffness",label:"Yaw stiffness N_\u03B2",unit:"N\xB7m/rad",compute:(e,t)=>t.tire?Rh(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorque",label:"Steering holding torque",unit:"N\xB7m",compute:(e,t)=>t.tire?yh(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorqueGradient",label:"Steering feedback gradient",unit:"N\xB7m/g",compute:(e,t)=>t.tire?xh(e,t.tire,t.speed,t.ayG):NaN}],tb=Object.fromEntries(Bk.map(e=>[e.key,e]));var Br=9.81;function tE(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 rE={front:!1,rear:!0};function va(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 $k(e,t,r,n,o,a){let s=e[t]+e[r];if(!(s>0))return;let i=va(n,o[t],a[t]),c=va(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 Gk(e,t,r,n,o,a={},s="open"){if(!e.rear)return 1;if(!e.front)return 0;let i=(f,p,d)=>d?Ns(f,p,d):s==="own"?f+p:2*Math.min(f,p),c=i(va(n,t.FL,r.FL),va(n,t.FR,r.FR),a.front),l=i(va(o,t.RL,r.RL),va(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 rb(e,t,r,n){return{car:t?zk(t,r.loadFactor[n]):e,ayTyre:Ye(r.ay[n],r.bank?.[n]??0),axCar:r.ax[n]-(r.axGrade?.[n]??0)}}function Kk(e,t){if(!e.aero?.model)return 0;let r=Math.min(t.v.length,t.ax.length,t.ay.length),n=t.loadFactor?Lu(e):void 0,o=0,a=0;for(let s=0;s<r;s++){let i=t.ds?.[s]??1,c=rb(e,n,t,s);o+=i,Ed(c.car,t.v[s],c.axCar/Br,c.ayTyre/Br)&&(a+=i)}return o>0?a/o:0}function Hk(e,t,r){let n=Ht(xe(t,"front")),o=Ht(xe(t,"rear")),a=Math.min(r.v.length,r.ax.length,r.ay.length),s=r.loadFactor?Lu(e):void 0,i=0,c=0;for(let l=0;l<a;l++){let u=r.ds?.[l]??1,m=rb(e,s,r,l);i+=u;let f=Le(m.car,m.ayTyre/Br,m.axCar/Br,r.v[l]);(f.FL>n||f.FR>n||f.RL>o||f.RR>o)&&(c+=u)}return i>0?c/i:0}function Pu(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=Hs(t,e.massTotal*Br*1.2),l=Xo(c,"front"),u=Xo(c,"rear"),m=ct(xe(t,"front")),f=ct(xe(t,"rear")),p=n.perWheel?Vd(m,l):null,d=n.perWheel?f===m?p:Vd(f,u):null,h=n.driven??rE,b={front:Vt(e,"front",1),rear:Vt(e,"rear",1)},g={front:0,rear:0},y=new Array(o),R=new Array(o),M=new Array(o),v=1/0,x=0,k=0,F=Ht(m),w=Ht(f),C=0,T=0,S=0,A=0,P=0,L=0,D=["FL","FR","RL","RR"],I=n.perWheel?Object.fromEntries(D.map(O=>[O,{Fz:new Array(o),alpha:new Array(o),Fy:new Array(o),Fx:new Array(o),Mz:new Array(o),used:new Array(o),FxCap:new Array(o),FyCap:new Array(o)}])):void 0,G=r.loadFactor?Lu(e):void 0;for(let O=0;O<o;O++){let W=rb(e,G,r,O),{ayTyre:E,axCar:_}=W,V=E/Br,N=Le(W.car,V,_/Br,r.v[O]),$=e.massTotal*E,K=$*i/a,z=$*s/a,j=gs(m,K,N.FL,N.FR,P),Q=gs(f,z,N.RL,N.RR,L);P=j,L=Q;let ne={FL:Math.abs(m.Fy(j,N.FL,0)),FR:Math.abs(m.Fy(j,N.FR,0)),RL:Math.abs(f.Fy(Q,N.RL,0)),RR:Math.abs(f.Fy(Q,N.RR,0))},te=(_-(r.axDrag?.[O]??0)-(r.axScrub?.[O]??0))/Br,fe=te>0&&h.front?Gk(h,N,ne,l,u,b,"own"):0,Y=r.v[O]*r.v[O],J=e.driveline?{Fz:N,alpha:{front:j,rear:Q},curvature:Y>1?r.ay[O]/Y:0,seed:g}:void 0,re={...fh(e,te,r.v[O],t,V,fe,J)};te>0&&(b.front||$k(re,"FL","FR",l,N,ne),b.rear||$k(re,"RL","RR",u,N,ne));let pe=!1,de=!1;for(let ue of["FL","FR","RL","RR"]){let Ve=(ue==="FL"||ue==="FR"?l:u).muX(N[ue])*N[ue];Math.abs(re[ue])>Ve&&(pe=!0),N[ue]>(ue==="FL"||ue==="FR"?F:w)&&(de=!0)}de&&(k+=r.ds?.[O]??1);let ie=xr(c,{FL:{Fz:N.FL,Fy:ne.FL,Fx:re.FL},FR:{Fz:N.FR,Fy:ne.FR,Fx:re.FR},RL:{Fz:N.RL,Fy:ne.RL,Fx:re.RL},RR:{Fz:N.RR,Fy:ne.RR,Fx:re.RR}},{lf:s,lr:i});if(y[O]=ie.stabil,R[O]=ie.agil,M[O]=ie.rel,I){let ue=.5*(N.FL+N.FR),Ve=.5*(N.RL+N.RR),Ae=l.muX(ue)*ue,le=u.muX(Ve)*Ve;for(let Re of D){let we=N[Re],Ge=Re==="FL"||Re==="FR",We=Ge?l:u,be=We.muY(we)*we,Fe=We.muX(we)*we,ye=I[Re],me=Ge?j:Q;ye.Fz[O]=we,ye.alpha[O]=me,ye.Fy[O]=ne[Re],ye.Fx[O]=re[Re],ye.Mz[O]=we>0?(Ge?m:f).Mz(me,we,0):0,ye.FxCap[O]=Fe,ye.FyCap[O]=be;let Te=be>0?Math.min(1,Math.abs(ne[Re])/be):0,Se=tE(re[Re],Fe,Ge?Ae:le),Ke=Ge?p:d,je=Ke&&we>0?Ke.reach(we,Math.sign(re[Re])*Se,Te):1;ye.used[O]=Math.hypot(Te,Se)/je}}ie.stabil<v&&(v=ie.stabil,x=O);let oe=r.ds?.[O]??1;A+=oe,ie.diff>0&&(C+=oe),pe&&(T+=oe),Ed(W.car,r.v[O],_/Br,V)&&(S+=oe)}return{stabil:y,agil:R,rel:M,minStabil:Number.isFinite(v)?v:0,minStabilAt:x,pastTurnoverFrac:A>0?k/A:0,understeerFrac:A>0?C/A:0,beyondFrac:A>0?T/A:0,aeroOutsideFrac:A>0?S/A:0,wheels:I}}function Lu(e){return Object.create(e,{loadFactor:{value:1,writable:!0,enumerable:!0}})}function zk(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=Tr(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=Ye(r.ay[l],r.bank?.[l]??0)/nb,h=Math.min(.99,Math.max(.01,oa(e,f/nb,u,t,d)));c.front[l]=p*h,c.rear[l]=p*(1-h);let b=i?$l(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 e7=Math.PI/180;var t7=qh.map(zs);var r7=[ce.zFL,ce.zFR,ce.zRL,ce.zRR];var n7=Array.from({length:ce.rollRate+1},(e,t)=>t);var hE=9.81,bE=.001,gE=.6,yE=2,Uk=4;function Xk(e,t,r,n=Uk){let o=Math.min(e.v.length,t.npts),{ds:a,closed:s}=t,i=r.massTotal*hE*r.wheelbase,c=xE(e.ay.slice(0,o).map((m,f)=>m/Math.max(bE,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 xE(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 qk(e,t,r,n,o={}){let a=o.maxIter??20,s=o.tol??.001,i=Math.min(1,Math.max(.001,o.relax??gE)),c=o.smoothM??Uk,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=gt(e.steady,t,n,l),m=[u.laptime],f=new Array(t.npts).fill(0),p=f.slice(),d=u,h=0,b=!1,g=0;for(let M=0;M<a;M++){h=M+1;let v=Xk(d,t,r,c);f=v.demand.map((F,w)=>f[w]+i*(F-f[w])),p=v.rdot;let x=gt(e.steady,t,n,{...l,envelope:F=>e.at(f[F]??0)});m.push(x.laptime);let k=Math.abs(x.laptime-d.laptime);if(d=x,g=k<=s?g+1:0,g>=yE){b=!0;break}}let y=0,R=0;for(let M=0;M<t.npts;M++)R+=t.ds[M],e.clamps(f[M]??0)&&(y+=t.ds[M]);return{...d,steady:u,demand:f,rdot:p,history:m,iterations:h,converged:b,clampedFrac:R>0?y/R:0}}var p7=Math.PI/180;var z7=180/Math.PI;function ka(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 Zk(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=>ka(p.vs,h,d)),axDecelN:p.decel.map(h=>ka(p.vs,h,d)),axScrubN:p.scrub.map(h=>ka(p.vs,h,d))});if(!o){let p=a(e);return d=>({ayMax:ka(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/ka(i.vs,i.radius,p),f=p=>p>=u||c.vs.length<2?ka(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 NE(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 Jk(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=Zk(s,t),c=[],l=a,u=(f,p)=>{let d=.5*(f+p),h=e(d);l++;let b=NE(i(d),h);s.splice(s.findIndex(g=>g.v>d),0,h),i=Zk(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 OE=2,VE=.5,hi=Math.PI/180,eM=21,BE={nCoarse:11,nSteer:13,nNorm:41,nAngle:45},$E={nCoarse:11,nSteer:13,nNorm:41,nAngle:61},GE=.005,KE=.05,ab=e=>e<0?0:e>1?1:e;function HE(e,t,r,n){let o=e.massTotal,a=n.nSteer??7,s=(n.drivenFront?2:0)+(n.drivenRear?2:0),i=Le(e,0,0,r),c=Math.max(1,(i.FL+i.FR+i.RL+i.RR)/4),l=8*hi,u=0,m=(b,g,y)=>{for(let R=b;R<=g;R+=y){let M=Math.abs(t.Fy(R*hi,c,0));M>u&&(u=M,l=R*hi)}};m(1,45,1),m(Math.max(.1,l/hi-1),l/hi+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*Mt(t,c,R,!1)/o),d.push(4*Mt(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 ir(e,t=!1,r="twoTrack",n,o,a=0,s=1){if(a!==0&&r==="fast")throw new Error('the fast (point-mass) envelope has no yaw balance to shift; use mode "twoTrack" for a yaw-inertia demand');let i=n??(t?$E:BE),{nCoarse:c,nSteer:l,nAngle:u}=i,m=Cr(0,1,i.nNorm).map(V=>Math.sin(Math.PI/2*V)),f=e.params,p=f.m.value,d=f.rho.value,h=f.fr_0.value,b=f.driven_wheels.value,g=f.power_scale.value,y=e.FG,R=ut(f);s!==1&&(R.loadFactor=s);let M=sr(f),v=uv(0,n?.vRes??(e.engine?VE:OE),e.vMax);v[v.length-1]<e.vMax&&v.push(e.vMax);let x=e.fRad.map(V=>V*b),k=e.fAxle,{drivenFront:F,drivenRear:w}=Wn(e),C=Yn(f,F,w),T=(V,N)=>{let $=k?At(k.vVehicle,V,N):NaN;return Number.isFinite($)?$:1/0},S=V=>{let N=V*V,{cl:$,cw:K,A:z}=bu(f,V,0,R),j=.5*d*-K*z*N,Q=.5*d*-$*z*N,ne=h*(-Q+y);return j+ne},A=V=>{let N=S(V)/p*C.powerFactor,$=S(V)/p*C.tractionFactor,K;if(e.engine){let j=S(V);K=ta(e.engine,V,C.effective,j,g).accel-N}else if(k){let j=0;F&&(j+=T(k.fFront,V)),w&&(j+=T(k.fRear,V)),K=g*j/p*C.powerFactor}else{let j=At(e.vVehicle,x,V),Q=g*j/p*C.powerFactor;K=Number.isFinite(Q)?Q:1/0}let z=vu(f,V,o)/p*C.powerFactor;return{axDrag:N,axDragTyre:$,axDrive:K,axPackCap:z,axPower:Math.min(K,z)}},P=v.map(A),L=e.vMax;for(let V=1;V<v.length;V++){let N=P[V].axDrive+P[V].axDrag;if(N>0)continue;let $=P[V-1].axDrive+P[V-1].axDrag;L=$>0?v[V-1]+(v[V]-v[V-1])*$/($-N):v[V-1];break}let D=Math.min(e.vMax,(1+KE)*L),I=r==="fast"?HE:Mh,G=V=>{let N=I(R,M,V,{drivenFront:F,drivenRear:w,nSteer:l,yawDemandCn:a,axDrag:S(V)/p,...f.diffYaw?{diffYaw:!0}:{}}),$=N.ay[0],K=N.ay[N.ay.length-1],z=te=>Math.min(Math.max(te*N.ayMax,$),K),j=m.map(te=>Ll(N.ay,N.axAccel,z(te))*C.tractionFactor),Q=m.map(te=>Ll(N.ay,N.axDecel,z(te))),ne=m.map(te=>Ll(N.ay,N.axScrub,z(te))*C.tractionFactor);return{v:V,ayMax:N.ayMax,axAccelN:j,axDecelN:Q,axScrubN:ne,atLock:N.atLock===!0}},O=r==="fast"?0:Math.min(jl,D),W=Jk(G,O,D,c,i.anchorTol??GE),E=[],_=[];for(let V=0;V<v.length;V++){let N=v[V],{axDrag:$,axDragTyre:K,axDrive:z,axPackCap:j,axPower:Q}=P[V],{ayMax:ne,axAccelN:te,axDecelN:fe,axScrubN:Y}=W.at(N);E.push({v:N,ayMax:ne,axTyreAcc:te[0],axTyreDec:fe[0],axDrive:z,axPackCap:j,axPower:Q,axDrag:$,axDragTyre:K,axAccelN:te,axDecelN:fe,axScrubN:Y});let J=[],re=[];for(let de=0;de<u;de++){let ie=Math.PI*de/(u-1),oe=ne*Math.cos(ie),ue=ab(Math.abs(Math.cos(ie)));J.push({ax:Math.min(At(m,te,ue)+K,Q+$)+At(m,Y,ue),ay:oe,v:N})}for(let de=u-1;de>=0;de--){let ie=Math.PI*de/(u-1),oe=ne*Math.cos(ie),ue=ab(Math.abs(Math.cos(ie)));re.push({ax:At(m,fe,ue)+$+At(m,Y,ue),ay:oe,v:N})}let pe=(de,ie,oe)=>Array.from({length:eM},(ue,Ve)=>({ax:ie+(oe-ie)*(Ve+1)/(eM+1),ay:de,v:N}));_.push([...J,...pe(-ne,J[J.length-1].ax,re[0].ax),...re,...pe(ne,re[re.length-1].ax,J[0].ax)])}return{...rM(E,m),rows:E,norm:m,surf:_}}function Ma(e,t){return e?.length?t.map(r=>Eu(e,r)):t.map(()=>0)}function Eu(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 rM(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?At(t,h,g):a(d,At(t,h,g),At(t,b,g)),i=(d,h)=>h>=1?d.axPower:Math.min(h*d.axDrive,d.axPackCap),c=({a:d,b:h,t:b},g,y)=>d.axScrubN?y*s(b,d.axScrubN,h.axScrubN,g):0,l=d=>d.axDragTyre??d.axDrag,u=({a:d,b:h,t:b},g,y)=>{let R=y*a(b,d.ayMax,h.ayMax);return R>0?ab(g/R):1},m=(d,h,b=1,g=1)=>{let{a:y,b:R,t:M}=d,v=u(d,h,b),x=b*s(M,y.axAccelN,R.axAccelN,v)+a(M,l(y),l(R)),k=a(M,i(y,g),M===0?0:i(R,g))+a(M,y.axDrag,R.axDrag);return Math.min(x,k)+c(d,v,b)},f=(d,h,b=1,g=1)=>{let{a:y,b:R,t:M}=d,v=u(d,h,b),x=s(M,y.axDecelN,R.axDecelN,v);return(g===1||x>0?b*x:g*b*x)+a(M,y.axDrag,R.axDrag)+c(d,v,b)},p=({a:d,b:h,t:b},g,y=1)=>{let R=t.length-1,M=d.axAccelN,v=h.axAccelN,x=d.axDecelN,k=h.axDecelN,F=d.axScrubN,w=h.axScrubN,C=I=>M[I]+b*(v[I]-M[I]),T=I=>x[I]+b*(k[I]-x[I]),S=I=>F?y*(F[I]+b*(w[I]-F[I])):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 I=R;I>=0;I--){let G=Math.min(y*C(I)+L,D+P)+S(I),O=y*T(I)+P+S(I);if(!(g<=G+1e-6&&g>=O-1e-6))continue;if(I===R)return t[I]*y*A;let W=(N,$,K)=>{if(K($))return 1;let z=(N-g)/(N-$);return z>0?Math.min(z,1):0},E=N=>g<=N+1e-6,_=N=>g>=N-1e-6,V=Math.min(W(y*C(I)+L+S(I),y*C(I+1)+L+S(I+1),E),W(D+P+S(I),D+P+S(I+1),E),W(y*T(I)+P+S(I),y*T(I+1)+P+S(I+1),_));return(t[I]+V*(t[I+1]-t[I]))*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 zE(e,t,r){let n=e.params,o=n.m.value,{drivenFront:a,drivenRear:s}=Wn(e),i=Yn(n,a,s);return c=>vu(n,c,t,r)/o*i.powerFactor}function bi(e,t,r,n){let o=zE(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{...rM(a,e.norm),rows:a,norm:e.norm}}var YE=[-.2,-.08,0,.06,.12,.2,.3];function nM(e,t=!1,r="twoTrack",n,o,a=YE){let s=[...new Set([...a,0])].sort((d,h)=>d-h),i=s.map(d=>ir(e,t,r,n,o,d)),c=i[s.indexOf(0)],l=s[0],u=s[s.length-1],m=d=>{if(d<=l)return{i:0,t:0};if(d>=u)return{i:s.length-1,t:0};let h=0;for(;h<s.length-2&&s[h+1]<=d;)h++;return{i:h,t:(d-s[h])/(s[h+1]-s[h])}},f=d=>{let h=b=>{let{i:g,t:y}=m(b);return{a:d[g],b:d[Math.min(d.length-1,g+1)],t:y}};return b=>{let{a:g,b:y,t:R}=h(b);if(R===0)return g;let M=(v,x)=>v+R*(x-v);return{vMax:g.vMax,axAccel:(v,x,k=1,F=1)=>M(g.axAccel(v,x,k,F),y.axAccel(v,x,k,F)),axDecel:(v,x,k=1,F=1)=>M(g.axDecel(v,x,k,F),y.axDecel(v,x,k,F)),ay:(v,x,k=1)=>M(g.ay(v,x,k),y.ay(v,x,k)),scrub:(v,x,k=1)=>M(g.scrub?.(v,x,k)??0,y.scrub?.(v,x,k)??0)}}},p=d=>d<l||d>u;return{anchors:s,steady:c,clamps:p,at:f(i),atSoc(d,h,b){let g=i.map(y=>bi(y,d,h,b));return{anchors:s,steady:g[s.indexOf(0)],clamps:p,at:f(g)}}}}function oM(e,t,r,n="twoTrack",o){let a=[...new Set([...t,1])].sort((i,c)=>i-c),s=a.map(i=>i===1?r:ir(e,!1,n,o,void 0,0,i));return{...tM(a,s),atSoc:(i,c,l)=>tM(a,s.map(u=>bi(u,i,c,l)))}}function tM(e,t){let r=e.length-1,n=1,o=0,a=0,s=0,i=1,c=0,l=0,u=p=>{if(n=1,!(p>e[0]))return void(o=0);if(p>=e[r])return void(o=r);let d=0;for(;d<r-1&&e[d+1]<=p;)d++;if(o=d,p===e[d])return;a=d+1;let h=e[d],b=e[d+1];if(r<2){n=2,c=(p-h)/(b-h),i=1-c;return}s=d===0?2:d+1===r||p-e[d-1]<e[d+2]-p?d-1:d+2;let g=e[s];n=3,i=(p-b)*(p-g)/((h-b)*(h-g)),c=(p-h)*(p-g)/((b-h)*(b-g)),l=(p-h)*(p-b)/((g-h)*(g-b))},m=p=>{let d=p(t[o]);if(n===1)return d;let h=p(t[a]);if(n===2)return i*d+c*h;let b=i*d+c*h+l*p(t[s]);return Math.min(Math.max(d,h),Math.max(Math.min(d,h),b))},f=(p,d,h,b,g)=>{if(u(p),n===1||h===0)return m(M=>g(M,h));let y=m(M=>M.ay(d,0,b));if(!(y>0))return m(M=>g(M,h));let R=h/y;return m(M=>g(M,R*M.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,(M,v)=>M.axDecel(d,v,b,R));return g===1?y(1):$h(y(g),y(1),g)},scrub:(p,d,h,b=1)=>f(p,d,h,b,(g,y)=>g.scrub?.(d,y,b)??0),ay:(p,d,h,b=1)=>{if(u(p),n===1||h===0)return m(M=>M.ay(d,h,b));let g=M=>h>0?M.axAccel(d,0,b):-M.axDecel(d,0,b),y=m(g);if(!(y>0))return m(M=>M.ay(d,h,b));let R=h/y;return m(M=>M.ay(d,R*g(M),b))}}}var aM=new WeakMap;function sb(e,t){let r=aM.get(e);if(!r){let n=wr(e).regen?jh(t??Ft(e)):void 0;r={inp:ut(e),ev:sr(e),...n?{regen:n}:{}},aM.set(e,r)}return r}function ib(e,t,r){let n=sb(e,r);return ob(n.inp,n.ev,t,n.regen?{regen:n.regen}:{})}function cb(e){let t=lt(e);if(t.mode!=="hydraulic")return null;let r=a=>a.heat?{heat:kf(a.heat,a.ratio),discs:a.discs}:void 0,n=r(t.hydraulic.front),o=r(t.hydraulic.rear);return n||o?{...n?{front:n}:{},...o?{rear:o}:{}}:null}function WE(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 lb(e,t,r,n,o,a=St){if(!e)return null;let s=WE(t);return{...e.front?{front:Fl(e.front.heat,e.front.discs,s.front,r,n,o.front,a)}:{},...e.rear?{rear:Fl(e.rear.heat,e.rear.discs,s.rear,r,n,o.rear,a)}:{}}}var jE=.5,UE=.02,XE=6,Iu=9,sM=1e-9,qE={FL:0,FR:0,RL:0,RR:0};function ub(e){return e?[...new Set([...e.padCurve.factor,1])].sort((t,r)=>t-r):[1]}function QE(e,t,r){let n=rr(e),o=n.hydraulic;return n.mode!=="hydraulic"||!o?e:{...e,brakes:{...n,hydraulic:{...o,front:{...o.front,padMu:o.front.padMu*t},rear:{...o.rear,padMu:o.rear.padMu*r}}}}}function iM(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 cM(e,t,r,n,o=()=>0){let a=Array.from({length:Iu},(m,f)=>r*f/(Iu-1)),s=Gs(),{front:i,rear:c}=n,l=a.map(m=>{let f=o(m),p=h=>Pr(h,t,m,s).limitAt(0,0,qE,f).ax,d=p(e);return i.map(h=>c.map(b=>{if(h===1&&b===1)return 1;let g=d<0?p(QE(e,h,b))/d:1;return Math.abs(g-1)<sM?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(Iu-2,Math.max(0,Math.floor(m/u))):0,h=u>0?Math.min(1,Math.max(0,(m-a[d])/u)):0,b=iM(i,f),g=iM(c,p),y=M=>{let v=l[M],x=Math.min(i.length-1,b.i+1),k=Math.min(c.length-1,g.i+1),F=v[b.i][g.i]+g.t*(v[b.i][k]-v[b.i][g.i]),w=v[x][g.i]+g.t*(v[x][k]-v[x][g.i]);return F+b.t*(w-F)},R=y(d)+h*(y(Math.min(Iu-1,d+1))-y(d));return Math.abs(R-1)<sM?1:R}}}function ZE(e,t){let{front:r,rear:n}=t;return(o,a)=>e.share(a,r?.[o]??1,n?.[o]??1)}var JE=e=>(e.front??[]).every(t=>t===1)&&(e.rear??[]).every(t=>t===1);function lM(e,t,r){let n=e(),o=1,a=t(n);if(JE(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<XE;c++){let l=e(ZE(r,s));o++;let u=Math.abs(l.laptime-n.laptime);if(n=l,u<UE){i=!0;break}a=t(n);let m=(d,h)=>d&&h?d.map((b,g)=>b+jE*((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 un(e,t){let r=e.engine;if(!r||r.gears.length===0||t.length===0)return;let n=e.params,{drivenFront:o,drivenRear:a}=Wn(e),s=Yn(n,o,a).effective,i=n.power_scale.value,{up:c,down:l}=Of(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:Vf(r.engine.gearbox),limitRpm:r.engine.limitRpm,best:f=>ta(r,f,s,Eu(t,f)*s,i).gear,share:(f,p)=>{let d=Eu(t,f),h=d*s,b=ta(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 uM=new WeakMap;function pb(e){let t=uM.get(e.ggv);return t===void 0&&(t=un(e.vehicle,e.ggv.rows)??null,uM.set(e.ggv,t)),t??void 0}function eI(e){return e.gear&&e.engineRpm&&e.shifting?{gear:e.gear,rpm:e.engineRpm,shifting:e.shifting}:{}}var Nu=class extends Error{constructor(t){super(t),this.name="EventError"}};function tI(e,t){let{ggv:r}=t,n=at(t.numerics),o=n.accelStep,a=Math.max(1,Math.round(e.distance/o)),s=ha(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=pb(t),c=i?xu(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:xM(t,f,[...u,s[a].v],m,1)}}function rI(e,t){let r=Math.max(1,Math.round(e.laps??1)),[n]=ha(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=xM(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 Ou(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 nI(e,t){let r=e.distance!=null?t.v_limit_endurance?.value??0:0;return r>0?r/3.6:void 0}function oI(e,t){if(e.distance==null||mt(t.motorModel))return 0;let r=t.endurance_reserve?.value??0;return r>0?Math.min(r,95)/100:0}var mM=1;function bM(e,t,r,n){return{v:r.v,ax:r.ax,ay:r.ay,ds:t.ds,axDrag:Ma(e.ggv.rows,r.v),...r.axScrub?{axScrub:r.axScrub}:{},axGrade:n,...t.bank?{bank:t.bank}:{}}}var pM=new WeakMap;function gM(e){let t=e.vehicle.params;if(!t.brakeFade)return null;let r=pM.get(t);if(r===void 0){let n=cb(t),o=n?lt(t):null;if(!n||!o||o.mode!=="hydraulic")r=null;else{let a=sb(t,e.vehicle),s=e.ggv.rows,i=cM(a.inp,a.ev,e.vehicle.vMax,{front:ub(o.hydraulic.front.heat),rear:ub(o.hydraulic.rear.heat)},c=>Ma(s,[c])[0]);r={discs:n,table:i}}pM.set(t,r)}return r}function aI(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=pb(e),u=(g,y)=>e.yaw?qk(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}:{}}):gt(bi(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=ln(t.gradient,t.npts),f=g=>n.motorThermal?yk(e.vehicle,t.ds,e.energyOpts??Fr,y=>u(y,g),o,a,m,t.bank).lap:u(void 0,g),p=gM(e);if(!p)return f();let d=pi(n),h=r.discC??{front:d,rear:d};return lM(f,g=>{let y=lb(p.discs,ib(n,bM(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 sI(e,t){let r=nI(e,t.vehicle.params),n=oI(e,t.vehicle.params);return n>0?lI(e,t,n,r):gi(e,t,r)}function _u(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 dM=5,iI=.1,cI=.005,fM=12;function lI(e,t,r,n){let o=gi(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=_u(o,r);if(i>=0)return s(o,n,!0);let c=Math.min(n??1/0,t.ggv.vMax),l=c/2,u=gi(e,t,l);a++;let m=_u(u,r);for(;m<0&&l>dM&&a<fM;)c=l,i=m,l=Math.max(dM,l/2),u=gi(e,t,l),a++,m=_u(u,r);if(m<0)return s(u,l,!1);let f=l,p=0;for(;a<fM&&c-l>iI&&m>cI;){let d=c-l,h=Math.min(c-.05*d,Math.max(l+.05*d,l+m*d/(m-i))),b=gi(e,t,h);a++;let g=_u(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 yM(e,t,r){return r===0?e:e&&!t}function gi(e,t,r){let n=t.track;if(!n)throw new Nu(`Event "${e.id}" needs a track.`);let o=Ou(e,n),a=e.standingStart??t.standingStart??!1,s=K=>yM(a,n.closed,K),i=t.vehicle.params,c=fr(ba(i)),l=c.capacityAh,u=i.soc.value,m=pi(i),f=Ru(c,m),p=0,d=0,h=0,b=0,g=[],y=!1,R=-1/0,M=0,v=0,x=!1,k=-1/0,F=0,w=0,C=-1/0,T=(K,z,j=1)=>{K.tempMaxC>C&&(C=K.tempMaxC),K.motorTempMaxC!==void 0&&(y=!0,x=!0,K.motorTempMaxC>R&&(R=K.motorTempMaxC),K.motorTempMaxC>k&&(k=K.motorTempMaxC),M+=(K.motorDerateTimeFrac??0)*z,F+=(K.motorDerateTimeFrac??0)*z,v+=(K.motorLossKwh??0)/j,w+=(K.motorLossKwh??0)/j)},S=null,A,P=cb(i),L={front:m,rear:m},D=null,I=gM(t)!==null,G=(K,z)=>I&&(Math.abs(K.front-z.front)>mM||Math.abs(K.rear-z.rear)>mM),O=(K,z,j)=>{let Q=Uh(i,K,z);if(D&&D.launch===j&&!pI(Q,D.pw)&&!G(L,D.discC))return D.lap;let ne=aI(t,n,{soc:K,packTempC:z,launched:j,...r?{vCeiling:r}:{},...I?{discC:L}:{}});return D={pw:Q,launch:j,discC:L,lap:ne},ne},W=ln(n.gradient,n.npts),E=(K,z,j)=>ga(t.vehicle,n.ds,K.v,K.ax,t.energyOpts,z,j,void 0,W,void 0,{ay:K.ay,bank:n.bank,...K.axScrub?{scrub:K.axScrub}:{}}),_=new WeakMap,V=(K,z)=>{let j=_.get(K);return j||(j=ib(i,bM(t,n,K,W),t.vehicle),_.set(K,j)),lb(P,j,K.v,n.ds,z,m)},N=(K,z,j)=>{let Q=`${(100*j/n.npts).toFixed(0)} % of the way through lap ${K+1}`,ne=z.cutoffAt>=0&&z.cutoffAt<=z.emptyAt;return{lapsCompleted:K,lapsAsked:o,why:ne?`the pack reached its ${c.voltageFloor.toFixed(0)} V cut-off ${Q}`:`the pack ran out ${Q}`}};for(let K=0;K<o;K++){if(u<=0){A={lapsCompleted:K,lapsAsked:o,why:"the pack was empty"};break}let z=s(K),j=u,Q=f;x=!1,k=-1/0,F=0,w=0,C=-1/0;let ne=O(u,f,z),te=E(ne,u,f);if(te.emptyAt>=0){A=N(K,te,te.emptyAt);break}let Y=O(te.socEnd,te.tempEndC,z).laptime-ne.laptime,J,re,pe,de,ie=f,oe=-1,ue=null,Ve=1;if(Y<=mb)J=ne.laptime,re=te.net,pe=te.loss,de=te.chargeAh,ie=te.tempEndC,T(te,J),Ve=1;else{let le=Math.min(uI,Math.max(2,Math.ceil(Y/(2*mb))));Ve=le;let Re=u,we=f;J=0,re=0,pe=0,de=0;for(let Ge=0;Ge<le;Ge++){let We=O(Re,we,z),be=E(We,Re,we),Fe=be.emptyAt>=0?be.emptyAt/n.npts:1;if(Fe*le<1){oe=Math.round(n.npts*(Ge/le+Fe)),ue=be;break}if(J+=We.laptime/le,T(be,We.laptime/le,le),re+=be.net/le/Fe,pe+=be.loss/le/Fe,de+=be.chargeAh/le/Fe,Re-=be.chargeAh/le/Fe/l,we+=(be.tempEndC-we)/le,Re<=0){oe=Math.round(n.npts*(Ge+1)/le),ue=be;break}}if(ie=we,oe>=0&&ue){A=N(K,ue,oe);break}u=Re}p+=J,d+=re,h+=pe,b+=de,Y<=mb&&(u=te.socEnd),f=ie;let Ae=P?V(ne,L):null;Ae&&(L={front:Ae.front?.endC??L.front,rear:Ae.rear?.endC??L.rear}),g.push({lap:K+1,time:J,elapsed:p,entryTime:ne.laptime,socStart:j,socEnd:u,packTempStartC:Q,packTempEndC:f,packTempMaxC:Number.isFinite(C)?C:Q,energyKwh:re,lossKwh:pe,chargeAh:de,launched:z,substeps:Ve,...r?{vCeiling:r}:{},...x?{motor:{peakWindingC:k,derateTimeFrac:J>0?F/J:0,lossKwh:w}}:{},...Ae?{brakes:{...Ae.front?{front:hM(Ae.front)}:{},...Ae.rear?{rear:hM(Ae.rear)}:{}}}:{}}),S=ne}if(!S){let K=pb(t);S=gt(bi(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.length;return{id:e.id,label:e.label,kind:e.kind,time:p,distance:n.length*$,laps:$,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}:{},...eI(S)},energy:{consumed:d,loss:h,...mt(i.motorModel)?{}:{native:{value:b,unit:"Ah"}},remainingFraction:mt(i.motorModel)?1:u,...y?{motor:{peakWindingC:R,derateTimeFrac:p>0?M/p:0,lossKwh:v}}:{}},lapLog:g,...A?{incomplete:A}:{}}}var mb=.05;function hM(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 uI=4,mI=.001;function pI(e,t){return e===t?!1:!Number.isFinite(e)||!Number.isFinite(t)?!0:Math.abs(e-t)>mI*Math.max(1,Math.abs(t))}function xM(e,t,r,n,o,a){return dI(e,t,o,()=>({v:r,ax:n,...a?{lateral:a}:{}}))}function dI(e,t,r,n){let o=e.energyOpts,a=e.vehicle.params.soc.value,s=0,i=0,c=0;for(let l=0;l<r;l++){let u=n(l),m=ga(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 mt(e.vehicle.params.motorModel)?{consumed:s,loss:i,remainingFraction:1}:{consumed:s,loss:i,native:{value:c,unit:"Ah"},remainingFraction:a}}function RM(e,t){switch(e.kind){case"straightLineAccel":return tI(e,t);case"constantRadius":return rI(e,t);case"trackLap":return sI(e,t)}}function db(e,t){let r={};for(let n of e)r[n.id]=RM(n,t);return r}function vM(e,t){if(e.kind!=="trackLap")return e;let{distance:r,...n}=e;return{...n,laps:Math.max(1,Math.round(t))}}function jn(e,t,r,n,o="twoTrack",a){let s=1/0,i=-1/0;for(let f of r){let p=li(f);if(!p)continue;let d=ok(p,gt(t,f,n).v);d&&(s=Math.min(s,d.lo),i=Math.max(i,d.hi))}if(!(i>=s))return;let c=ak({lo:s,hi:i}),l=c.join(","),u=a?.get(l);if(u)return u;let m=oM(e,c,t,o);return a?.set(l,m),m}var Vu=e=>e.distance/Math.max(1,e.laps);function Bu(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 fI=e=>e.v.map(t=>t*3.6),hI=e=>e.ax.map(t=>t/9.81),bI=e=>e.ay.map(t=>t/9.81),gI=e=>e.ay.map((t,r)=>e.v[r]>1e-6?t/(e.v[r]*e.v[r]):0),$u=(e,t,r)=>e?.slice()??new Array(t.s.length).fill(r),yI=e=>$u(e.z,e,0),xI=e=>e.gradient?e.gradient.map(t=>100*Math.tan(t*Math.PI/180)):$u(void 0,e,0),RI=e=>$u(e.bank,e,0),vI=e=>$u(e.mu,e,1);function kI(e){let t=e.s.length,r=Bu(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 fb=[{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 kM(e){let t=Bu(e);return{ds:t,vars:{s:e.s,ds:t,t:kI(e),v:e.v,speed:fI(e),ax:e.ax,ay:e.ay,axg:hI(e),ayg:bI(e),curv:gI(e),z:yI(e),grade:xI(e),bank:RI(e),grip:vI(e)}}}function MM(e,t){return{v:e.v,ax:e.ax,ay:e.ay,ds:Bu({s:e.s,length:t}),axGrade:ln(e.gradient,e.v.length),...e.bank?{bank:e.bank}:{},...e.loadFactor?{loadFactor:e.loadFactor}:{}}}function SM(e,t){let r=ut(e);return{pastTurnover:Hk(r,sr(e),t),...e.aeroModel?{aeroOutside:Kk(r,t)}:{}}}var Gu="Flying lap";function hb(e,t){return e.kind!=="trackLap"||e.label!==Gu?e.label:e.standingStart??t?"Run":e.label}function MI(e){let t=ut(e);return{yawInertia:t.yawInertia??0,massTotal:t.massTotal,wheelbase:t.wheelbase/1e3}}function SI(e,t,r){let n=e.params,o=n.ggvMode??"twoTrack",a=n.quasiTransient?nM(e,!1,o):null,s=a?a.steady:ir(e,!1,o),i=t?jn(e,s,[t],r,o):void 0;return{ggv:s,...a?{yaw:{family:a,car:MI(n)}}:{},...i?{load:i}:{}}}function AI(e,t){let r=t.lapCounts,n=t.standingStart??!1,o=!1,a=e.events.map(s=>{let i=r?.[s.id]!=null?vM(s,r[s.id]):s,c=hb(i,n),l=c===i.label?i:{...i,label:c};return l!==s&&(o=!0),l});return o?a:e.events}function FI(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=Ou(o,r.track),i=Math.max(1,Math.round(a));i!==s&&e[o.id]&&(e[o.id]={...e[o.id],lapsOverridden:{asked:i,defined:s}})}}function wI(e,t){for(let[r,n]of Object.entries(e))n.trace&&(e[r]={...n,...SM(t,MM(n.trace,Vu(n)))})}function yi(e,t,r={}){let n=Ft(e),o=SI(n,r.track,r.numerics),{ggv:a}=o,s=db(AI(t,r),{vehicle:n,...o,track:r.track,energyOpts:wr(e,r.energyOpts),numerics:r.numerics,standingStart:r.standingStart});return FI(s,t,r),wI(s,n.params),{name:e.name,rulesetId:t.id,events:s,ggv:a}}function bb(e){return{...e,ggv:{rows:e.ggv.rows,vMax:e.ggv.vMax,surf:e.ggv.surf}}}var gb=["<","<=",">",">=","==","!="],_e=class extends Error{at;constructor(t,r){super(t),this.name="ExprError",this.at=r}},xi=e=>e>="0"&&e<="9",AM=e=>/[A-Za-z_]/.test(e),CI=e=>/[A-Za-z0-9_]/.test(e);function TI(e){let t=[],r=0;for(;r<e.length;){let n=e[r];if(n===" "||n===" "||n===`
|
|
223
|
+
`}function Rr(e){let t=vs(CR(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 TR={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},PR={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},LR={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},DR={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},ER={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},IR={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},_R={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},NR={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},Jd=()=>Rr(TR),ef=()=>Rr(PR),tf=()=>Rr(LR),rf=()=>Rr(DR),nf=()=>Rr(ER),of=()=>Rr(IR),af=()=>Rr(_R),sf=()=>Rr(NR);var OR=e=>Number.isFinite(e)&&e>0;function yl(e,t){let r=OR(t.grip)?t.grip:1,n=OR(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 Ms={ok:!0,violation:0},Pn=1e7;function vr(e,t){let r;try{r=e.build(t)}catch(s){return{total:Pn*2,feasible:!1,terms:[],reason:`build failed: ${String(s)}`}}let n=e.feasible(r);if(!n.ok)return{total:Pn+Math.max(0,n.violation),feasible:!1,terms:[],reason:n.reason};let o;try{o=e.terms(r)}catch(s){return{total:Pn*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:Pn*2,feasible:!1,terms:o,reason:"objective was not finite"}}var Ss=(e,t)=>!t||(e.feasible!==t.feasible?e.feasible:e.total<t.total);function cf(e,t){return t.map((r,n)=>Math.min(e[n].hi,Math.max(e[n].lo,r)))}var kr=e=>e.map(t=>t.start);function xl(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 KT(e){let t=0;for(;t===0;)t=e();return Math.sqrt(-2*Math.log(t))*Math.cos(2*Math.PI*e())}function lf(e,t){let{budget:r}=t,n=Math.max(1,Math.floor(t.progressEvery??1)),o=e.variables,a=p=>cf(o,p.map((d,h)=>o[h].lo+d*(o[h].hi-o[h].lo))),s=p=>p.map((d,h)=>(d-o[h].lo)/(o[h].hi-o[h].lo)),i=0,c=0,l=null,u=null,m=[];return{vars:o,denorm:a,norm:s,evaluate:p=>{if(i>=r)return l?.total??Number.POSITIVE_INFINITY;i++;let d=p.map(g=>Math.min(1,Math.max(0,g))),h=vr(e,a(d));h.feasible||c++;let b=Ss(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):kr(o),score:l??vr(e,kr(o)),evaluations:i,history:m,infeasible:c})}}var uf=(e,t,r,n=0,o)=>{let a=t?r.norm(kr(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 VR(e,t){let r=lf(e,t),n=xl(t.seed??1),o=e.variables.length;for(r.evaluate(uf(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 qo(e,t){let r=lf(e,t),n=e.variables.length,o=xl(t.seed??1),a=1,s=2,i=.5,c=.5,l=uf(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],M=0;for(let v=1;v<=n;v++)for(let x=0;x<n;x++)M=Math.max(M,Math.abs(m[v].u[x]-R.u[x]));if(M<1e-4)break;for(let v=1;v<=n&&r.left()>0;v++){let x=m[v].u.map((k,F)=>R.u[F]+c*(k-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 BR(e,t){let r=lf(e,t),n=e.variables.length,o=xl(t.seed??1),a=4+Math.floor(3*Math.log(n)),s=Math.floor(a/2),i=[];for(let k=1;k<=s;k++)i.push(Math.log(s+.5)-Math.log(k));let c=i.reduce((k,F)=>k+F,0);for(let k=0;k<s;k++)i[k]/=c;let l=1/i.reduce((k,F)=>k+F*F,0),u=(l+2)/(n+l+5),m=1+2*Math.max(0,Math.sqrt((l-1)/(n+1))-1)+u,f=(4+l/n)/(n+4+2*l/n),p=(n+2)/3,d=Math.min(1,p*2/((n+1.3)**2+l)),h=Math.min(1-d,p*2*(l-2+1/l)/((n+2)**2+l)),b=Math.sqrt(n)*(1-1/(4*n)+1/(21*n*n)),g=uf(e,t.warmStart!==!1,r,t.startJitter,o),y=.25,R=new Array(n).fill(1),M=new Array(n).fill(0),v=new Array(n).fill(0),x=0;for(;r.left()>0;){x++;let k=[];for(let S=0;S<a&&r.left()>0;S++){let A=[];for(let L=0;L<n;L++)A.push(KT(o));let P=g.map((L,D)=>L+y*R[D]*A[D]);k.push({z:A,u:P,f:r.evaluate(P)})}if(k.length<s)break;k.sort((S,A)=>S.f-A.f);let F=g.slice(),w=new Array(n).fill(0);g=new Array(n).fill(0);for(let S=0;S<s;S++)for(let A=0;A<n;A++)g[A]+=i[S]*k[S].u[A],w[A]+=i[S]*k[S].z[A];g=g.map(S=>Math.min(1,Math.max(0,S)));for(let S=0;S<n;S++)M[S]=(1-u)*M[S]+Math.sqrt(u*(2-u)*l)*w[S];let C=Math.sqrt(M.reduce((S,A)=>S+A*A,0)),T=C/Math.sqrt(1-(1-u)**(2*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]*k[D].z[S]*k[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 Qo=[{name:"random",run:VR},{name:"nelder-mead",run:qo},{name:"sep-cma-es",run:BR}];var P4=Math.PI/180;var Rl=Math.PI/180;var I4={Fz:100,alpha:.25*Rl,kappa:.005,gamma:.5*Rl,p:6900},$R={Fz:100,alpha:1*Rl,kappa:.02,gamma:.5*Rl,p:6900};var GR=Math.PI/180,$4={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:GR},gamma:{rad:1,deg:GR},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 Y4=Math.PI/180;var eP=Math.PI/180;var Z4=3*eP;var nK=Math.PI/180;var hK=Math.PI/180;var cP={RCX1:1,RCY1:1,REX1:0,REY1:0,RBY3:0,RHX1:0,RHY1:0},zR={RBX1:15,RBX2:15,RBY1:18,RBY2:19,...cP};var FK=Math.PI/180;var fP=Math.PI/180,vl=[{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"}],GK=new Map(vl.map(e=>[e.id,e]));var KK=.01*fP;var ze=Math.PI/180;var jR=new Set(vl.filter(e=>e.group!=="inputs"&&(e.unit==="N"||e.unit==="N\xB7m"||e.unit==="N/rad")).map(e=>e.id)),UR={alpha:{from:-15*ze,to:15*ze,n:61},kappa:{from:-.25,to:.25,n:61},gamma:{from:-6*ze,to:6*ze,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}},hf={alpha:{from:0,to:12*ze,n:7},kappa:{from:-.2,to:.2,n:9},gamma:{from:-4*ze,to:4*ze,n:5},Fz:{from:400,to:1600,n:5},p:{from:6e4,to:12e4,n:4},V:{from:5,to:35,n:4}};var bf={alpha:{from:0,to:12*ze,n:25},kappa:{from:-.2,to:.2,n:25},gamma:{from:-4*ze,to:4*ze,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,...UR[t],...o}],x:t,y:r,...n}),kl=(e,[t,r],n,o,a={})=>({id:e,form:"carpet",sweep:[{input:t,...hf[t]},{input:r,...hf[r]}],x:n,y:[o],...a}),Mr=(e,t)=>({id:e,fixed:t}),Ot={input:"Fz",values:"car"},ff={alpha:0,kappa:0},ht={kappa:0},YR={alpha:0},gP={input:"Fz",values:[500,1e3,1500]},yP=[{id:"overview",name:"Overview",cards:[Mr("tyre","tyre"),ke("fy","alpha",["Fy"],{title:"Lateral force",hold:ht}),ke("mz","alpha",["Mz"],{title:"Aligning moment",hold:ht}),ke("fx","kappa",["Fx"],{title:"Longitudinal force",hold:YR}),kl("combined-carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Mr("ellipse","ellipse")]},{id:"lateral",name:"Lateral",cards:[ke("fy-load","alpha",["Fy"],{title:"Lateral force per wheel load",series:Ot,hold:ht}),ke("muy-load","alpha",["muY"],{title:"Lateral force per unit load",series:Ot,hold:ht}),ke("fy-peak","alpha",["Fy"],{title:"Lateral force over its peak",series:Ot,hold:ht,scale:{per:"peak"}},{from:0,to:15*ze,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:Ot,hold:ht}),ke("trail","alpha",["t"],{title:"Pneumatic trail",series:Ot,hold:ht},{from:0,to:12*ze,n:49}),ke("mzr","alpha",["Mzr"],{title:"Residual aligning moment",series:Ot,hold:ht},{from:0,to:12*ze,n:49}),kl("gough",["alpha","Fz"],"Fy","Mz",{title:"Gough plot",hold:ht}),ke("steering-feel","alpha",["t"],{title:"Steering feel",x:"FyRel",series:Ot,hold:ht},{from:0,to:12*ze,n:49})]},{id:"longitudinal",name:"Longitudinal",cards:[ke("fx-load","kappa",["Fx"],{title:"Longitudinal force per wheel load",series:Ot,hold:YR}),ke("mux-peak","Fz",["muXPeak"],{title:"Peak longitudinal \u03BC over load"}),ke("kx","Fz",["dFxdk"],{title:"Slip stiffness at zero slip over load",hold:ff}),ke("kappa-peak","Fz",["kappaPeak"],{title:"Slip ratio at the peak over load"})]},{id:"combined",name:"Combined",cards:[kl("carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),kl("envelope-load",["kappa","alpha"],"Fy","Fx",{title:"Friction envelope per load",scale:{per:"Fz"},facet:gP}),ke("fy-kappa","kappa",["Fy"],{title:"Side force while driving or braking",series:{input:"alpha",values:[2*ze,4*ze,8*ze]}}),ke("fx-kappa","kappa",["Fx"],{title:"Driving force while cornering",series:{input:"alpha",values:[0,4*ze,8*ze]}}),Mr("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*ze)},hold:ht}),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",...bf.gamma},{input:"Fz",...bf.Fz,follow:!0}],x:"gamma",y:["Fz"],z:"muYPeak"},ke("camber-stiffness","alpha",["dFydg"],{title:"Camber stiffness at the point",series:Ot,hold:ht}),ke("mx","alpha",["Mx"],{title:"Overturning moment",series:Ot,hold:ht})]},{id:"rolling",name:"Rolling and radius",cards:[ke("my","V",["My"],{title:"Rolling-resistance moment",series:Ot,hold:ff}),ke("radius","Fz",["R0","Rl","Re"],{title:"Radius over load"},{from:0}),ke("p-roll","V",["Proll"],{title:"Rolling power",series:Ot,hold:ff})]},{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:ht,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:[Mr("operating","operating"),Mr("wheels","wheels")]},{id:"fit",name:"Fit check",cards:[Mr("fitLateral","fitLateral"),Mr("fitLongitudinal","fitLongitudinal"),Mr("fitCoupling","fitCoupling"),Mr("fitEnvelope","fitEnvelope")]}];var AP=5670374e-14,gf=273.15,QR=.95,ZR=60,Ml=10,FP=.55,St=25,yf=-20,xf=50,Fs={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:[...Fs.tempC],factor:[...Fs.factor]}},Sl={...ws,discMassKg:.4,discOuterMm:200,padCurve:{tempC:[...Fs.tempC],factor:[...Fs.factor]}};function Rf(e,t){let r=t==="front"?ws:Sl,n=Math.round(2*e.effRadiusMm+40);return{...r,discOuterMm:n,discMassKg:Math.round(100*r.discMassKg*(n/r.discOuterMm)**2)/100,padCurve:{tempC:[...r.padCurve.tempC],factor:[...r.padCurve.factor]}}}var wP=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},As=(e,t,r,n)=>Math.min(r,Math.max(t,wP(e,n)));function CP(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 vf(e,t){return{discMassKg:As(e?.discMassKg,.05,20,t.discMassKg),discOuterMm:As(e?.discOuterMm,50,600,t.discOuterMm),specificHeatJPerKgK:As(e?.specificHeatJPerKgK,100,3e3,t.specificHeatJPerKgK),emissivity:As(e?.emissivity,.02,1,t.emissivity),coolingWPerM2K:As(e?.coolingWPerM2K,Ml,5e3,t.coolingWPerM2K),padCurve:CP(e?.padCurve,t.padCurve)}}function Al(e,t){let r=e.tempC,n=e.factor,o=Math.min(r.length,n.length);if(o===0)return 1;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=1;for(;a<o-1&&r[a]<t;)a++;return n[a-1]+(t-r[a-1])/(r[a]-r[a-1])*(n[a]-n[a-1])}function kf(e,t=1){let r=e.discMassKg*e.specificHeatJPerKgK,n=e.discOuterMm*.001/2,o=2*Math.PI*n*n,a=ZR/3.6,s=e.emissivity*AP*o,i=m=>Ml+(e.coolingWPerM2K-Ml)*Math.pow(Math.max(0,m)*t/a,FP),c=(m,f,p)=>{let d=m+gf,h=p+gf;return i(f)*o*(m-p)+s*(d**4-h**4)},l=(m,f)=>i(f)*o+4*s*Math.max(0,m+gf)**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 M=0;M<g;M++)m+=(R-c(m,p,h)*y)/r;return m},padFactor:m=>Al(e.padCurve,m),window:JR(e.padCurve)}}function Fl(e,t,r,n,o,a,s=St){let i=n.length,c=new Array(i),l=new Array(i),u=new Array(i),m=QR/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 M=g+1<i?n[g+1]:n[g],v=.5*(n[g]+M),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 JR(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])&&Al(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 Mf=1e5,nv=.001,Ln={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},Af={fullAtBar:10,maxPowerKw:0,fadeBelowKmh:0,distribution:"equal"};var Ff=av(Cl(Ln,"Formula Student brakes")),wf=40,ov={ideal:!1,barFront:Ln.barFront,pedalForceMaxN:0,testSpeedKmh:wf,regen:Af};function ev(e){let{heat:t,...r}=e;return t?{...r,heat:{...t,padCurve:{tempC:[...t.padCurve.tempC],factor:[...t.padCurve.factor]}}}:r}function av(e){let t=(r,n)=>r.heat?r:{...r,heat:Rf(r,n)};return{...e,front:t(e.front,"front"),rear:t(e.rear,"rear")}}function Cl(e,t){return{name:t,pedalRatio:e.pedalRatio,masterFrontMm:e.masterFrontMm,masterRearMm:e.masterRearMm,valve:e.valve,valveKneeBar:e.valveKneeBar,valveSlope:e.valveSlope,front:ev(e.front),rear:ev(e.rear),adjusterPitchMm:e.adjusterPitchMm,barLengthMm:e.barLengthMm}}function Cf(e,t){return sv({...e,barFront:t.barFront,pedalForceMaxN:t.pedalForceMaxN})}function Tf(e,t){let r=Ar(t),n=e?tr(e):void 0;return{mode:r.ideal?"tyre":n?"hydraulic":"balance",hydraulic:n?Cf(n,r):Ln,regen:r.regen}}var TP=["none","proportioning","limiter"],wl=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},Je=(e,t,r,n)=>Math.min(r,Math.max(t,wl(e,n))),PP=(e,t)=>{let r=wl(e,t);return r>0?r:t};function tv(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(wl(e?.discs,n==="inboard"?1:t.discs)))),pistonsPerSide:Math.max(1,Math.min(6,Math.round(wl(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:vf(e.heat,t.heat??r)}:{}}}function sv(e){let t=Ln;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:TP.includes(e?.valve)?e?.valve:t.valve,valveKneeBar:Je(e?.valveKneeBar,0,200,t.valveKneeBar),valveSlope:Je(e?.valveSlope,0,1,t.valveSlope),front:tv(e?.front,t.front,ws),rear:tv(e?.rear,t.rear,Sl),adjusterPitchMm:PP(e?.adjusterPitchMm,t.adjusterPitchMm),barLengthMm:Je(e?.barLengthMm,0,500,t.barLengthMm)}}function LP(e){let t=Af;return{fullAtBar:Je(e?.fullAtBar,0,200,t.fullAtBar),maxPowerKw:Je(e?.maxPowerKw,0,1e3,t.maxPowerKw),fadeBelowKmh:Je(e?.fadeBelowKmh,0,100,t.fadeBelowKmh),distribution:e?.distribution==="wheel"?"wheel":"equal"}}function tr(e){let t=sv(e??void 0),r=typeof e?.name=="string"&&e.name.trim()?e.name:DP;return Cl(t,r)}function Ar(e){return{ideal:e?.ideal===!0,barFront:Je(e?.barFront,.05,.95,Ln.barFront),pedalForceMaxN:Je(e?.pedalForceMaxN,0,5e3,0),testSpeedKmh:Je(e?.testSpeedKmh,5,150,wf),regen:LP(e?.regen)}}var DP="Formula Student brakes";var Sf=e=>Math.PI/4*(e*nv)**2;function en(e,t){let r=e.pistonsPerSide*Sf(e.pistonDiaMm)*Mf;return e.discs*2*e.padMu*r*e.effRadiusMm*nv*e.ratio/Math.max(.05,t)}function iv(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 Cs(e,t){let r=Math.max(0,t)*e.pedalRatio,n=e.barFront*r/Sf(e.masterFrontMm)/Mf,o=(1-e.barFront)*r/Sf(e.masterRearMm)/Mf;return{front:n,rearIn:o,rear:iv(e,o)}}function EP(e,t){let r=Cs(e,1);return{front:en(e.front,t)*r.front,rear:en(e.rear,t)*r.rearIn}}function Ts(e,t){let r=EP(e,t);return r.front/Math.max(1e-12,r.front+r.rear)}function Ps(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=cv(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 cv(e,t){let r=e.fadeBelowKmh/3.6;return r>0?Math.max(0,Math.min(1,t/r)):1}function Sr(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 rv=new WeakMap;function Dn(e){let t=rv.get(e);return t||(t=e.mode==="hydraulic"&&e.hydraulic?_P(e,e.hydraulic):IP(e),rv.set(e,t)),t}function IP(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 _P(e,t){let r=en(t.front,e.tyreRadiusM),n=en(t.rear,e.tyreRadiusM),o=e.regen,a=(c,l)=>{let u=Cs(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*Sr(o.v,o.front,l),f=p*Sr(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 Pf(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 Tl=ls,NP=.1,En=(e,t)=>e.a*Math.sqrt(Math.max(0,1-(t/Math.max(1e-9,e.b))**2));function Pl(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 Ef(e,t,r){let n=Math.max(0,r-Tl*t.b),o=Math.min(r,Tl*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 If(e,t,r,n,o=0){let a=Math.max(0,r),s=Ef(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/NP)),d=p>0&&a<Tl*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:M}=s,v=Pl(T=>{let S=En(e,T),A=En(t,a-T);return Math.min(S+A,2*Math.min(S,A)+y)},R,M),x=e.cap(v),k=t.cap(a-v),F=Math.max(2*l,Math.min(x+k,2*Math.min(x,k)+y)),w=(T,S,A)=>Math.min(y,Math.max(0,T-A))+Math.min(y,Math.max(0,S-A));return{...g,regenWheel:y,mixedMax:F,regenRoom:T=>{let S=w(i,c,T);if(!(a>0))return S;let A=I=>Tl*I.b*Math.sqrt(Math.max(0,1-(T/Math.max(1e-9,I.a))**2)),P=Math.max(R,a-A(t)),L=Math.min(M,A(e));if(!(P<=L))return S;let D=Pl(I=>Math.min(y,En(e,I)-T)+Math.min(y,En(t,a-I)-T),P,L);return Math.max(S,w(e.cap(D),t.cap(a-D),T))}}}var Lf=e=>Math.max(e.xNoLock,e.xLock),Df=e=>Math.max(e.mixedMax,2*e.xLock);function Zo(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 Jo(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 Ls(e,t,r,n){return e.shares?OP(e,e.shares,t,r,n):VP(e,t,r,n)}function lv(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 OP(e,t,r,n,o){let a=Df(r),s=Df(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=Jo(r,t.front*b),y=Jo(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}=lv(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 VP(e,t,r,n){let o=Lf(t),a=Lf(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 k=0,F=x;for(let w=0;w<60;w++){let C=.5*(k+F);v(e.demand(C,n))?k=C:F=C}return k},u=Number.isFinite(e.uMax)?e.uMax:100;if(!Number.isFinite(e.uMax))for(;c(u)&&u<1e7;)u*=2;let m=c(u)?u:l(v=>s(v)<=o&&i(v)<=a,u),f=Number.isFinite(e.uMax)&&m>=e.uMax,p=v=>{let x=e.demand(v,n),k=Zo(t,s(x),x.regenFront),F=Zo(r,i(x),x.regenRear);return Number.isFinite(k)&&Number.isFinite(F)?k+F:-1/0},d=e.demand(m,n),h=o>0?s(d)/o:1/0,b=a>0?i(d)/a:1/0,g=[{u:m,by:f?"pedal":h>=b?"front":"rear"}];if(t.xLock>t.xNoLock){let v=l(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}=lv(g,p),M=e.demand(y.u,n);return{force:Math.max(0,Number.isFinite(R)?R:0),control:y.u,demand:M,limitedBy:y.by,lockFront:s(M)>t.xNoLock*(1+1e-9),lockRear:i(M)>r.xNoLock*(1+1e-9)}}var Fr={regen:!0,regenEfficiency:.6};function wr(e,t){let r=e.energy??t??Fr;return{regen:r.regen===!0,regenEfficiency:Math.min(1,Math.max(0,Number.isFinite(r.regenEfficiency)?r.regenEfficiency:0))}}function Cr(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 uv(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 At(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 Ll(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],M=i(y)*(1+s(y)/(s(y)+s(R)))-i(R)*(s(y)/(s(y)+s(R)));return M*i(y)<=0?0:Math.abs(M)>2*Math.abs(i(y))?2*i(y):M}let h=i(d-1),b=i(d),g=(h*s(d)+b*s(d-1))/(s(d-1)+s(d));return(Math.sign(h)+Math.sign(b))*Math.min(Math.abs(h),Math.abs(b),.5*Math.abs(g))},l=s(o),u=i(o),m=c(o),f=c(o+1),p=r-e[o];return t[o]+p*(m+p*((3*u-2*m-f)/l+p*(m+f-2*u)/(l*l)))}function Ds(e,t,r){return r.map(n=>At(e,t,n))}var Es=e=>e.reduce((t,r)=>r>t?r:t,-1/0),ea=e=>e.reduce((t,r)=>r<t?r:t,1/0);var BP=[-.906179845938664,-.538469310105683,0,.538469310105683,.906179845938664],$P=[.236926885056189,.478628670499366,.568888888888889,.478628670499366,.236926885056189];function _f(e,t,r){let n=.5*(r-t),o=.5*(t+r),a=0;for(let s=0;s<5;s++)a+=$P[s]*e(n*BP[s]+o);return n*a}var GP=Math.PI*2,KP=.5/3.6;function Is(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 Nf(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*GP;c[g]=y*o/n,l[g]=s[g]*n/o}let u=Es(c),m=Cr(ea(c),u,u/KP),f=Ds(c,l,m),{front:p,rear:d}=Is(t,r),h=f.map(g=>g*p),b=f.map(g=>g*d);return{vVehicle:m,fFront:h,fRear:b,vMax:u}}var mv=60/(2*Math.PI),pv=.1,dv=.08,fv=0;function Of(e){let t=(r,n)=>r===void 0||!Number.isFinite(r)?n:Math.max(0,r);return{up:t(e.upshiftTime,pv),down:t(e.downshiftTime,dv)}}function Vf(e){let t=e.driveKept;return t===void 0||!Number.isFinite(t)?fv:Math.max(0,Math.min(1,t))}function Bf(e,t,r){let{primary:n,ratios:o,efficiency:a}=e.gearbox,s=t>0&&r>0&&n>0,i=(b,g)=>b/mv*r/g,c=s?o.filter(b=>b>0).map(b=>{let g=n*b*t;return{ratio:g,vIdle:i(e.idleRpm,g),vLimit:i(e.limitRpm,g)}}):[],l=Math.max(0,Math.min(1,a)),u=Math.max(0,e.inertia),m=b=>b>e.limitRpm?0:Math.max(0,Be(e.rpm,e.torque,b)),f=(b,g)=>{let y=c[g];return y?b*y.ratio/r*mv: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 ta(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 $f(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 hv=9.81,bv=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]*(bv/60),a[v]=t[v]/60*bv,s[v]=a[v]*u/l,i[v]=r[v]*l,c[v]=i[v]/u;let m=Es(s),f=m,p=.5/3.6,d=Cr(ea(s),m,m/p),h=Ds(s,c,d),b=Cr(ea(t),Es(t),250),g=Ds(t,o,b).map(v=>v*e.power_scale.value),y,R=f,M;if(e.motorModel?.kind==="ice"){M=Bf(e.motorModel,l,u);let v=Cr(0,M.vMax,Math.max(2,Math.ceil(M.vMax/p)+1)),x=v.map(w=>$f(M,w)),k=v.map(()=>0),F=e.motorPlacement==="front";y={vVehicle:v,fFront:F?x:k,fRear:F?k:x,vMax:M.vMax},R=M.vMax}else e.motorModel&&(y=Nf(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:hv,FG:e.m.value*hv,vMax:R,vVehicle:d,fRad:h,uMotor:b,pMotor:g,vRad:s,fAxle:y,...M?{engine:M}:{}}}var tn=e=>e.motorModel?.kind==="ice"?Is(1,e.motorPlacement==="front"?"front":"rear"):Is(Math.max(1,Math.round(e.motorCount??e.driven_wheels?.value??2)),e.motorPlacement??"rear");function gv(e){let t=tn(e);return t.front>=2||t.rear>=2}function yv(e){return gv(e)?e.motorMount??"hub":"chassis"}function Gf(e){if(!e.motorModel)return{front:!1,rear:!0};let t=tn(e);return{front:t.front>0,rear:t.rear>0}}function Kf(e){let t=tn(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=yv(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 lt(e){return Tf(e.brakeModel,e.brakeSetup)}function Dl(e){return Ar(e.brakeSetup).ideal?"tyre":e.brakeModel||e.brakeModelId?"hydraulic":"balance"}function xv(e,t){if(!(mt(e.motorModel)||!wr(e).regen))return Ps(El(Ft(e)),t??lt(e).regen)}function El(e){return e.fAxle??{vVehicle:e.vVehicle,fFront:e.vVehicle.map(()=>0),fRear:e.fRad.map(t=>t*e.params.driven_wheels.value)}}function Hf(e,t=lt(e)){if(t.mode==="hydraulic")return Ts(t.hydraulic,e.r_dyn.value);if(t.mode==="tyre"){let r=e.front_mass_diss.value>1?e.front_mass_diss.value/100:e.front_mass_diss.value;return Math.min(.95,Math.max(.05,r+Z(e,"cg_height")/Math.max(1,Z(e,"wheelbase"))))}return Z(e,"brake_balance")}function zf(e,t=lt(e)){return{front:t.hydraulic.front.location==="inboard",rear:t.hydraulic.rear.location==="inboard"}}function Yf(e){let t=lt(e);return{brakeBalanceFront:Hf(e,t),brakeInboard:zf(e,t)}}function Rv(e,t=lt(e)){if(t.mode==="tyre"||t.regen.distribution!=="wheel"||mt(e.motorModel))return;let r=tn(e),n={front:r.front>=2,rear:r.rear>=2};return n.front||n.rear?n:void 0}function _s(e){let t=lt(e),r=e.r_dyn.value,n=zf(e,t),o=Hf(e,t),a=Rv(e,t),s=t.mode==="hydraulic"||a?xv(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 zP=9.81;function Wf(e,t){if(mt(e.motorModel))return()=>0;let r=lt(e),n=Ps(t,r.regen);if(r.mode==="hydraulic"){let a=Dn({mode:"hydraulic",balanceFront:Ts(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"?YP(e):()=>Math.min(.99,Math.max(.01,Z(e,"brake_balance")));return(a,s,i)=>{if(!(a>0))return 0;let c=o(s,i);return Math.min(c*a,Sr(n.v,n.front,s))+Math.min((1-c)*a,Sr(n.v,n.rear,s))}}function YP(e){let t=e.m.value*zP,r=e.front_mass_diss.value>1?e.front_mass_diss.value/100:e.front_mass_diss.value,n=Z(e,"cg_height")/Math.max(1,Z(e,"wheelbase")),o=1-Math.max(0,Math.min(1,Z(e,"cop_long"))),a=.5*e.rho.value*e.c_l.value*e.A.value;return(s,i)=>{let c=Math.max(0,a*s*s),l=t*(r+Math.abs(i)*n)+c*o;return Math.min(.99,Math.max(.01,l/(t+c)))}}function vv(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 jf={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"},...vv("front"),...vv("rear")},Uf={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 Xf(e){let t=jf[e];return`${t.label}, ${t.section}`.toLowerCase()}function qf(e){let t=Uf[e];return t.section?`${t.section} ${t.label.charAt(0).toLowerCase()}${t.label.slice(1)}`:t.label}var kv=new WeakMap;function rr(e){if(e.brakes)return e.brakes;let t=kv.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},kv.set(e,t)}return t}var Tr=e=>Dn(rr(e));var XP=Math.PI/180,ra=Object.freeze({tbr:1,preloadN:0}),Il=Object.freeze({tbr:1/0,preloadN:0}),Zf=e=>e.faces*e.muClutch*e.rFrictionMm/e.rRampMm;function Jf(e,t){if(!(e>0)||Number.isNaN(t))return 0;let r=Math.tan(Math.min(90,t)*XP);return r>0?Math.min(1,e/r):1}function Sv(e){if(e>=1)return 1/0;let t=e>0?e:0;return(1+t)/(1-t)}function _l(e){return e===1/0?1:e>1?(e-1)/(e+1):0}function na(e,t){return e.tbr===1/0?1/0:(e.preloadN>0?e.preloadN:0)+_l(e.tbr)*Math.abs(t)}function Os(e,t,r){let n=o=>o!==void 0&&o>0&&r>0?o/r:0;switch(e.kind){case"open":return ra;case"spool":return Il;case"independent":return t==="hubs"?ra:Il;case"clutch":{let o=n(e.preloadNm);return t==="hubs"?{tbr:1,preloadN:o}:{tbr:Sv(Jf(Zf(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 Ns(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 Mv=4;function Qf(e,t){let r=0;for(let a of e)r=Math.max(r,Ns(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,Ns(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 Vs(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=Ef(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=Pl(b=>En(e,b)+En(t,c-b),l.lo,l.hi),f=[{m1:l.c1,m2:l.c2}];for(let b=1;b<=Mv&&m!==l.y1;b++){let g=l.y1+(m-l.y1)*b/Mv;f.push({m1:e.cap(g),m2:t.cap(c-g)})}let p=Qf(f,ra),d=Qf(f,Il);if(!(d>p))return u;let h=(Qf(f,{tbr:s,preloadN:i})-p)/(d-p);return Math.min(a,u+(a-u)*Math.min(1,Math.max(0,h)))}function Av(e,t,r,n,o,a){return eh(e,o,Vs(t,r,n,o,a))}function eh(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 th(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 Fv(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 Cv(e,s,c,d,h,b,n,l,a);s=d,c=b}return null}function wv(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 Cv(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 Cv(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 Nl(e,t){return Math.abs(e.fx-e.x)>t?e.x:e.fx}var qP=(e,t)=>{let r=e.brakes?.hydraulic?.[t];return!!r&&r.location==="inboard"&&r.discs===1};function Vt(e,t,r){let n=e.driveline?.[t];if(n)return r>=0?n.drive:qP(e,t)?n.coast:n.hubs}var Tv=e=>e.tbr>1||e.preloadN>0;var QP=9.81,Pv=["FL","FR","RL","RR"],rh=e=>e==="FL"||e==="FR",Ol=e=>rh(e)?"front":"rear",Lv={front:["FL","FR"],rear:["RL","RR"]},Gs=()=>({peak:new Map,freeBrake:new Map}),$s=25;function Bs(e,t){let r=Math.max(0,e)/$s,n=Math.floor(r),o=r-n,a=t(n);return o>0?a+o*(t(n+1)-a):a}var rn=1e-4,ZP=.05;function Pr(e,t,r,n=Gs(),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=qc(xe(t,S),Math.max(1,A*$s)),i.set(P,L)),L},l=(S,A)=>({aPeak:Bs(A,P=>c(S,P).aPeak),fyPeak:Bs(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*$s);L=Mt(xe(t,S),D,0,!0,c(S,A)),u.set(P,L)}return L},f=(S,A)=>A>0?Bs(A,P=>m(S,P)):0,p=Tr(e),d=rr(e),h=S=>d.regen&&d.regenPerWheel?.[S]?Sr(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(Ol(S),L);return Mt(xe(t,Ol(S)),L,P[S]*D.fyPeak,!0,D)},R=(S,A,P,L,D=!0)=>{let I=te=>{let fe=Math.max(0,A[te]),Y=xe(t,S),J=l(S,fe);return{Fz:fe,a:Math.abs(f(S,fe)),b:J.fyPeak,slide:fe>0?Math.abs(Y.forces({Fz:fe,kappa:-1,alpha:0}).Fx):0,cap:re=>Math.abs(Mt(Y,fe,re,!0,J))}},G=te=>Math.abs(P[te])*l(Ol(te),Math.max(0,A[te])).fyPeak,[O,W]=Lv[S],E=I(O),_=I(W),V=G(O)+G(W),N=If(E,_,V,L,S==="front"?b:g),$=D?N:{...N,xLock:0},K=Vt(e,S,-1),z=K&&Tv(K)?K:void 0;if(!z)return{axle:S,eq:$,cap:$};let j=Number.isFinite(L)?L:E.cap(G(O))+_.cap(G(W)),Q=Av($,E,_,V,z,j);return{axle:S,eq:$,cap:Q,law:z,strong:()=>E.cap(G(O))>=_.cap(G(W))?O:W}},M=(S,A,P,L)=>R(S,A,P,L).cap,v=(S,A,P)=>{let L=S.demand,D=p.shares?Jo(A,L.front):Zo(A,(L.front-L.regenFront)/2,L.regenFront),I=p.shares?Jo(P,L.rear):Zo(P,(L.rear-L.regenRear)/2,L.regenRear);return{front:Number.isFinite(D)?D:0,rear:Number.isFinite(I)?I:0}},x=S=>({muX:A=>A>0?Math.abs(f(S,A))/A:0,muY:A=>A>0?l(S,A).fyPeak/A:0}),k={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 I=L.cap,G=D.cap,O=Ls(p,I,G,a),W={arms:F,halfTrack:w,ayDir:Math.sign(S)};for(let E=0;E<2;E++){let _=v(O,I,G),V={};for(let $ of Pv){let K=Math.max(0,A[$]);V[$]={Fz:K,Fy:Math.abs(P[$])*l(Ol($),K).fyPeak,Fx:-(rh($)?_.front:_.rear)/2}}let N=$=>{if(!$.law||!$.strong)return $.cap;let K={axle:$.axle,strong:$.strong(),full:2*$.cap.xNoLock,open:2*$.eq.xNoLock,sense:-1};return eh($.eq,$.law,gl(K,V,k,W))};I=N(L),G=N(D),O=Ls(p,I,G,a)}return{limit:O,front:I,rear:G}};return{peakAt:l,axle:M,ceiling:(S,A,P)=>{let[L,D]=Lv[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},I=Le(e,S,0,a,0,A),G,O=fe=>(G?.ax!==fe&&(G={ax:fe,loads:Le(e,S,(fe+L)/QP,a,0,A)}),G.loads),W=Qc(fe=>zo(P,O(fe),I,l).short,-L,-1),E=P,_={front:0,rear:0},V,N,$=(fe,Y=!0)=>{let J=W.at(fe);D=O(J),E=zo(P,D,I,l).util;let re=0,pe=0,de=0;for(let ie of Pv){let oe=y(ie,D,E);re+=oe,rh(ie)?pe+=oe:de+=oe}if(_={front:Math.abs(pe),rear:Math.abs(de)},p.mode!=="tyre"){let ie=R("front",D,E,Math.abs(pe),Y),oe=R("rear",D,E,Math.abs(de),Y);if(o&&(ie.law||oe.law)){let ue=C(S,D,E,ie,oe);V=ue.limit,N={front:ue.front,rear:ue.rear}}else V=Ls(p,ie.cap,oe.cap,a),N={front:ie.cap,rear:oe.cap};re=-V.force}return re/s},K=th($,0,rn),z=Nl(K,rn),j=z;if(V?.lockFront||V?.lockRear){let fe=th(J=>$(J,!1),0,rn);j=Nl(fe,rn);let Y=Fv($,fe.x,K.x,rn,ZP);Y||$(K.x),z=Nl(Y??K,rn)}let Q=W.edge(),ne=Q!==void 0&&z<Q;ne&&(z=Math.min(0,Q),$(z),j=Math.max(j,z));let te={loads:D,ceiling:_,limit:V,axles:N};return{ax:z,axUnlocked:j,...ne?{edge:Q}:{},...te,split:()=>te.limit&&te.axles?v(te.limit,te.axles.front,te.axles.rear):{...te.ceiling}}}}}var Bl=9.81;function JP(e,t,r){let n=Le(e,0,t,r),o=Math.max(0,n.FL)+Math.max(0,n.FR),a=Math.max(0,n.RL)+Math.max(0,n.RR);return o+a>0?o/(o+a):e.frontMassFrac}var Iv=(e,t)=>t.mode==="hydraulic"&&!!rr(e).regen;function oa(e,t,r=0,n,o=0){if(!e.brakes&&e.brakeBalanceFront==null)return e.frontMassFrac;let a=Tr(e);if(a.shares&&a.mode!=="tyre")return a.shares.front;let s=n&&Iv(e,a)?_v(e,n):void 0,i=s?.shares??Dv.get(e);i||Dv.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=Nv(c,l,u),f=i.get(m);if(f===void 0){let p=-c*.005,d=l*.25,h=e.massTotal*Math.abs(p)*Bl;if(s){let b=Vv(a,Ov(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"?JP(e,p,d):Pf(a,h,d);i.size>5e4&&i.clear(),i.set(m,f)}return f}var Dv=new WeakMap;function $l(e,t,r,n,o=0){let a=Tr(e);if(!Iv(e,a))return;let s=Math.round(Math.max(0,r)/(e.massTotal*Bl)/.005),i=Math.round(Math.max(0,n)/.25);return Vv(a,Ov(e,_v(e,t),s,i,Math.round(o/.01)),Math.max(0,r),n)}var Ev=new WeakMap;function _v(e,t){let r=Ev.get(e);r||Ev.set(e,r=new WeakMap);let n=r.get(t);return n||r.set(t,n={ev:t,tyres:Gs(),shares:new Map,rooms:new Map,speeds:new Map}),n}var Nv=(e,t,r)=>(r*1001+e)*100003+t;function Ov(e,t,r,n,o){let a=Nv(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:Pr(e,t.ev,i,t.tyres),dragG:-Math.max(0,za(e,i).drag)/(e.massTotal*Bl)},t.speeds.set(n,l));let{cap:u}=l,m=Le(e,c,-r*.005+l.dragG,i),f=Math.abs(c)*e.massTotal*Bl,p=b=>{let[g,y]=b==="front"?["FL","FR"]:["RL","RR"],R=f*(b==="front"?e.frontMassFrac:1-e.frontMassFrac),M=u.peakAt(b,Math.max(0,m[g])).fyPeak+u.peakAt(b,Math.max(0,m[y])).fyPeak,v=R>0&&M>0?Math.min(1,R/M):0;return u.axle(b,m,{FL:v,FR:v,RL:v,RR:v},1/0)},d,h;s=(b,g)=>(b==="front"?d??=p("front"):h??=p("rear")).regenRoom(g),t.rooms.size>5e4&&t.rooms.clear(),t.rooms.set(a,s)}return s}function Vl(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 Vv(e,t,r,n){if(!(r>0))return Vl(e,t,1,n);let o=c=>c.front+c.rear,a=e.controlFor(r,n),s=Vl(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=Vl(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=Vl(e,t,l,n);o(u)<r?a=l:(i=l,s=u)}return s}var aa={rel:.003,abs:2,kappa:1e-5,iters:12},nh={rel:1e-6,abs:.001,kappa:1e-12,iters:40};function In(e,t,r,n=aa){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=rL(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 M=e(o*R),v=Math.abs(M.Fx)-a;if(h=M,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 Bv=1e-6,eL=40,tL=(3-Math.sqrt(5))/2;function rL(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-Bv),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<eL;g++){let y=Bv*Math.abs(o)+1e-10,R=.5*(r+c);if(Math.abs(o-R)<=2*y-.5*(c-r))break;let M=!0;if(Math.abs(h)>y){let F=(o-l)*(m-p),w=(o-u)*(m-f),C=(o-u)*w-(o-l)*F;w=2*(w-F),w>0&&(C=-C),w=Math.abs(w);let T=h;if(h=b,Math.abs(C)<Math.abs(.5*w*T)&&C>w*(r-o)&&C<w*(c-o)){b=C/w;let S=o+b;(S-r<2*y||c-S<2*y)&&(b=R>=o?y:-y),M=!1}}M&&(h=o>=R?r-o:c-o,b=tL*h);let v=Math.abs(b)>=y?o+b:o+(b>=0?y:-y),x=e(t*v),k=-Math.abs(x.Fx);k<=m?(v>=o?r=o:c=o,u=l,p=f,l=o,f=m,o=v,m=k,i=x):(v<o?r=v:c=v,k<=f||l===o?(u=l,p=f,l=v,f=k):(k<=p||u===o||u===l)&&(u=v,p=k))}return{kappa:o,forces:i}}var Gl=e=>Math.max(2,.003*Math.abs(e)),nL=(e,t)=>Math.max(t.abs,t.rel*Math.abs(e)),oh=.5,oL=.03;function aL(e,t,r,n,o){let a=.5*(e.vx+t.vx),s=v=>{let x=(1+v)*a/e.vx-1,k=(1+v)*a/t.vx-1,F=e.at(x),w=t.at(k);return{kappaM:v,kl:x,kr:k,fl:F,fr:w,g:F.Fx+w.Fx-r}},i=nL(r,o),c=Math.max(-oh,Math.min(oh,n)),l=s(c);if(Math.abs(c)>oL){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)>oh)break;let k=s(x);if(Math.abs(k.g)<i)return k;if(Math.abs(k.g)<Math.abs(d.g)&&(d=k),Math.sign(k.g)!==Math.sign(m.g)){f=k;break}if(u*(k.g-m.g)<=0)return d;m=k,p*=1.9}if(f===l)return d;let h=m,b=f,g=h.g,y=b.g,R=Math.abs(g)<Math.abs(y)?h:b,M=Math.min(1e-7,o.kappa);for(let v=0;v<30&&Math.abs(b.kappaM-h.kappaM)>M;v++){let x=y-g,k=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);k>F&&k<w||(k=.5*(F+w));let C=s(k);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 $v(e,t,r,n){let o=(e*(1+t*n)+t*r)/(1-t*n);return e+o>=0?o:(e*(1-t*n)+t*r)/(1+t*n)}function ah(e,t,r,n,o,a=aa){let s=aL(e,t,r,o,a),i=s.fr.Fx-s.fl.Fx,c=na(n,r);if(Math.abs(i)<=c){let R=r-(s.fl.Fx+s.fr.Fx),M=Math.max(0,Math.abs(R)-Gl(r))/2;return{left:{kappa:s.kl,forces:s.fl,want:s.fl.Fx+R/2,short:M},right:{kappa:s.kr,forces:s.fr,want:s.fr.Fx+R/2,short:M},locked:!0,spoolKappa:s.kappaM}}let l=Math.sign(i),u=r/2-l*c/2,m=r/2+l*c/2,f=In(e.at,u,e.seed||s.kl,a),p=In(t.at,m,t.seed||s.kr,a),d=Math.abs(u-f.forces.Fx)>Gl(u),h=Math.abs(m-p.forces.Fx)>Gl(m),b=Math.max(0,n.preloadN),g=_l(n.tbr);d&&!h?p=In(t.at,$v(f.forces.Fx,l,b,g),p.kappa,a):h&&!d&&(f=In(e.at,$v(p.forces.Fx,-l,b,g),f.kappa,a));let y=(R,M)=>({kappa:R.kappa,forces:R.forces,want:M,short:Math.max(0,Math.abs(M-R.forces.Fx)-Gl(M))});return{left:y(f,u),right:y(p,m),locked:!1,spoolKappa:s.kappaM}}var sL={front:["FL","FR"],rear:["RL","RR"]},iL=Object.freeze({Fx:0,Fy:0,Mz:0});function Kl(e,t,r,n){let o=r;for(let a of["front","rear"]){let[s,i]=sL[a],c=r[s]+r[i],l=Vt(e,a,c);if(!l||!(na(l,c)>0))continue;let u=xe(t,a),m=n.alpha[a],f=(a==="front"?e.trackFront:e.trackRear)/2e3,p=(h,b)=>{let g=Math.max(0,n.Fz[h]);return{at:g>0?y=>u.forces({Fz:g,kappa:y,alpha:m,gamma:0}):()=>iL,vx:Math.max(.05,1-b*n.curvature),seed:0}},d=ah(p(s,f),p(i,-f),c,l,n.seed?.[a]??0);n.seed&&(n.seed[a]=d.spoolKappa),o===r&&(o={...r}),o[s]=d.left.want,o[i]=d.right.want}return o}var Me=9.81,se=Math.PI/180,cL=8,lL=1e-6,on=["FL","FR","RL","RR"],zt=e=>e==="FL"||e==="FR",nn=e=>zt(e)?"front":"rear";function Hs(e,t){let r=xe(e,"front"),n=xe(e,"rear");return r===n?Nn(r,t):{front:Nn(r,t),rear:Nn(n,t)}}function Nn(e,t){return Qd(e,Math.min(t,Ht(e)))}var zl=e=>e==="FL"||e==="RL";function ia(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,oa(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 ph(e,t,r,n){return Math.abs(On(e,t,r,n!==void 0?{steerMaxDeg:n}:{}).peak.steerDeg)}function dh(e,t,r,n){let o=e.tv;if(!o?.enabled)return 0;let a=i1(o)(t,Math.abs(r),n);return r<0?-a:a}function fh(e,t,r=0,n,o=0,a=0,s){let i=ia(e,{axG:t,driveFrontFrac:a},r,n,o),c=i?i.fx:{FL:0,FR:0,RL:0,RR:0};return i&&s&&n?Kl(e,n,c,s):c}var zs=e=>zl(e)?-1:1,hh=(e,t,r,n,o)=>t*e.Fy(t*r,n,t*o);function uh(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 uL(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?$o(o,n/se,u?r.FL:r.FR,u?r.FR:r.FL):Go(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 Ys(e,t,r){let n=(e.toeFrontDeg??0)*se,o=(e.toeRearDeg??0)*se,a=uL(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 bh(e,t,r){if(r.Fz<=0)return 0;let n=ct(xe(e,nn(t))),o=zs(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 Gv(e,t,r,n){if(!Tn(e))return null;let o=ct(xe(t,"front")),a={};for(let s of["FL","FR"]){let i=n[s];a[s]={Fz:i.Fz,Fx:i.Fx,Fy:i.Fy,Mz:bh(o,s,i)}}return Rs(e,r/se,a,Zr(o.model),{FL:n.FL.travelMm,FR:n.FR.travelMm})}var Kv=()=>({totalNm:[],aligningNm:[],lateralNm:[],longitudinalNm:[],jackingNm:[]});function Hv(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 mL=Object.freeze({Fx:0,Fy:0,Mz:0});function zv(e,t,r){let n=t==="front"?(r?.FL??0)+(r?.FR??0):(r?.RL??0)+(r?.RR??0),o=Vt(e,t,n);return o&&na(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}=uh(e),h=zv(e,"front",l),b=zv(e,"rear",l),g={front:0,rear:0},y=i!==void 0&&i>0&&Number.isFinite(i)?i:null,R=Y=>y===null?r:Math.sqrt(Math.max(0,Y)*y),M=ct(xe(t,"front")),v=ct(xe(t,"rear")),x=e.trackFront/2e3,k=e.trackRear/2e3,F=!!(e.kinFront&&e.kinRear),w=F&&y===null?Uo(e,e.kinFront,e.kinRear,r):null,C=NaN,T=null,S=Y=>{if(!F)return null;if(y===null)return w;let J=R(Y);return J!==C&&(C=J,T=Uo(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,I=!!(L||D),G=!!(L?.toePerMz||D?.toePerMz),O=Y=>zt(Y)?L:D,W={FL:{fy:0,fx:0,mz:0},FR:{fy:0,fx:0,mz:0},RL:{fy:0,fx:0,mz:0},RR:{fy:0,fx:0,mz:0}},E=!1,_=Y=>{let J=Y/r,re=y===null?n+f*J/r:n+f/y,pe=y===null?n-p*J/r:n-p/y,de=S(Y),ie=R(Y),oe=de?de(Y/Me,u,n/se,o/se):null,ue=oe?{FL:oe.FL.travel,FR:oe.FR.travel}:void 0,Ve=Uc(e,Y/Me,u,ie,n/se,o/se,ue,oe?.steeringJacking),Ae=Ve.loads;E=Ve.overturned;let le=Ys(e,o,ue),Re=le.steer,we=0,Ge=be=>{let Fe=Math.max(0,Ae[be]),ye=zs(be),me=zt(be)?M:v,Te=O(be),Se=0,Ke=0;if(Te){let Rn=W[be];Se=Te.toePerFy*Rn.fy+Te.toePerFx*Rn.fx+Te.toePerMz*Rn.mz,Ke=Te.camberPerFy*Rn.fy+Te.camberPerFx*Rn.fx}let je=Re[be]+(oe?ye*oe[be].bumpToe*se:0)+ye*Se*se,Gt=je-(zt(be)?re:pe),xn=(oe?oe[be].camberRoad:0)*se+ye*(le.camber[be]+Ke)*se;return{Fz:Fe,mir:ye,t:me,gains:Te,complianceToe:Se,steerK:je,slip:Gt,camberRad:xn}},We=(be,Fe)=>{let ye=y===null?J/r:1/y,me=zt(be)?f:-p,Te=(zl(be)?1:-1)*(zt(be)?x:k),Se=(Math.cos(n)-Te*ye)*Math.cos(Fe.steerK)+(Math.sin(n)+me*ye)*Math.sin(Fe.steerK);return{at:Fe.Fz>0?Ke=>Fe.t.forces({Fz:Fe.Fz,kappa:Ke,alpha:Fe.mir*Fe.slip,gamma:Fe.mir*Fe.camberRad}):()=>mL,vx:Math.max(.05,Se),seed:P[be]}};for(let be=0;be<(I?cL:1);be++){we=0;let Fe=0,ye={};for(let me of on){let Te=zt(me)?h:b;if(Te&&!ye[me]){let[vo,Dt]=zt(me)?["FL","FR"]:["RL","RR"],gc=Ge(vo),j0=Ge(Dt),U0=nn(me),fp=ah(We(vo,gc),We(Dt,j0),Te.F,Te.law,g[U0],nh);g[U0]=fp.spoolKappa,ye[vo]={w:gc,share:fp.left},ye[Dt]={w:j0,share:fp.right}}let Se=ye[me]?.w??Ge(me),{Fz:Ke,mir:je,t:Gt,gains:xn,complianceToe:Rn,steerK:up,slip:mp,camberRad:pp}=Se,Ga=l?.[me]??0,yo,xo=0,dp=0,bc=0,Ro=ye[me]?.share;if(Ro)P[me]=Ro.kappa,dp=Ro.kappa,xo=Ro.forces.Fx,bc=Ro.short,yo=je*Ro.forces.Fy;else if(Ga===0||Ke<=0)yo=hh(Gt,je,mp,Ke,pp),bc=Ke<=0?Math.abs(Ga):0;else{let Dt=In(gc=>Gt.forces({Fz:Ke,kappa:gc,alpha:je*mp,gamma:je*pp}),Ga,P[me],nh);P[me]=Dt.kappa,dp=Dt.kappa,xo=Dt.forces.Fx,bc=Math.max(0,Math.abs(Ga-xo)-Math.max(aa.abs,aa.rel*Math.abs(Ga))),yo=je*Dt.forces.Fy}if(A[me]={Fz:Ke,travelMm:oe?.[me].travel??0,steerRad:up,slipRad:mp,camberRad:pp,Fy:yo,Fx:xo,kappa:dp,fxShort:bc,lifted:Ve.lifted[me]},xn){let vo=G&&xn.toePerMz?bh(Gt,me,A[me]):0;W[me]={fy:-je*yo,fx:xo,mz:-je*vo*1e3};let Dt=W[me];Fe=Math.max(Fe,Math.abs(xn.toePerFy*Dt.fy+xn.toePerFx*Dt.fx+xn.toePerMz*Dt.mz-Rn))}we+=yo*Math.cos(up)+xo*Math.sin(up)}if(Fe<lL)break}return we/d},V=Y=>{let J=Le(e,0,u,Y,0,o/se);return J.FL+J.FR+J.RL+J.RR},N=Math.max(20,3.5*V(r)/d);if(y!==null){N=4*Me;for(let Y=0;Y<8;Y++){let J=Math.min(40*Me,3.5*V(R(N))/d);if(J<=N)break;N=J}N=Math.max(20,N)}let $=Y=>_(Y)-Y,K=Math.max(.001,N*1e-4),z=(Y,J,re,pe)=>{let de=Y,ie=re,oe=J,ue=pe,Ve=de;for(let Ae=0;Ae<40;Ae++){let le=ue-oe,Re=Math.abs(le)>1e-12?(de*ue-ie*oe)/le:.5*(de+ie),we=Math.min(de,ie),Ge=Math.max(de,ie);Re>we&&Re<Ge||(Re=.5*(de+ie));let We=$(Re);if(Ve=Re,Math.abs(We)<1e-4||Ge-we<1e-6)break;We<0==oe<0?(de=Re,oe=We,ue*=.5):(ie=Re,ue=We,oe*=.5)}return Ve},j=(Y,J,re,pe=!1)=>{let de=(Ae,le)=>re>0?Ae>0&&le<0:le>0&&Ae<0,ie=Y,oe=J,ue=Y+re*Math.min(Math.abs(J),N);if(!pe&&Math.abs(ue-Y)>K){let Ae=$(ue);if(de(oe,Ae))return{root:z(ie,oe,ue,Ae),last:ie};ie=ue,oe=Ae}let Ve=pe?N/24:Math.max(N/24,Math.abs(ue-Y)/4);for(let Ae=1;Ae<=24;Ae++){let le=ie+re*Ve;if(Math.abs(le)>N)break;let Re=$(le);if(de(oe,Re))return{root:z(ie,oe,le,Re),last:ie};if(pe&&Re*re<0&&(Re-oe)*re<0)break;ie=le,oe=Re}return{root:null,last:ie}},Q=c??null;if(c===void 0&&a!==void 0&&Number.isFinite(a)&&Math.abs(a)<=N){let Y=$(a);if(Math.abs(Y)<=1e-4)$(a+K)<0&&$(a-K)>0&&(Q=a);else{let J=j(a,Y,Math.sign(Y)).root;Q=J!==null&&(J===0||Math.sign(J)===Math.sign(a))?J:null}}let ne=Q===null;if(Q===null){let Y=$(0),J=$(K),re=Math.abs(Y)<=1e-4,pe=re?y!==null?1:o!==0?Math.sign(o):J>0?1:-1:Math.sign(Y),de=re?pe*K:0,ie=re?pe>0?J:$(-K):Y,oe=j(de,ie,pe);Q=oe.root??(re?0:oe.last)}let te=_(Q);if(ne&&o!==0&&y===null){let Y=Math.sign(o);if(Q*Y<=0||(A.RL.Fy+A.RR.Fy)*Y<0){let J={...A},re=E,pe=Y*Math.max(Q*Y+K,n*Y*r*r/p),de=null;if(pe*Y<N){let ie=$(pe);if(ie*Y>0)de=j(pe,ie,Y).root;else{let oe=pe+Y*N/24,ue=$(oe);(ue-ie)*Y>0&&(de=j(oe,ue,Y,ue*Y<=0).root)}}de!==null&&de*Y>0?(Q=de,te=_(Q)):(Object.assign(A,J),E=re)}}let fe=f*(A.FL.Fy*Math.cos(A.FL.steerRad)+A.FR.Fy*Math.cos(A.FR.steerRad))-p*(A.RL.Fy+A.RR.Fy);if(s||h||b){let Y=J=>(zl(J)?1:-1)*(zt(J)?x:k);for(let J of on){let re=A[J],pe=zt(J)?f:-p;fe+=pe*re.Fx*Math.sin(re.steerRad)-Y(J)*re.Fx*Math.cos(re.steerRad)}}return y!==null&&Q<-1e-6?{ay:NaN,cn:NaN,wheels:A,overturned:E,res:NaN}:{ay:Q/Me,cn:fe/(d*Me*m),wheels:A,overturned:E,res:te-Q}}function pL(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 M=y===void 0?void 0:R.ay,v={pos:{b:h,cn:R.cn,ay:M},neg:{b:h,cn:R.cn,ay:M}},x=null,k=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),k=S),A.cn===0&&m(A.ay))return{beta:S,trimmed:!0};if(A.cn<0!=C.cn<0){let P={lo:C.b,hi:S,ayLo:C.ay},L=Yv(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:Yv(u,x),trimmed:!0}:g?{beta:k,trimmed:!1}:null},p=[.25,.75,2,5].map(h=>h*se);if(o!==void 0&&Number.isFinite(o)&&Math.abs(o)<=c){let h=f(o,p,!1,a);if(h)return h;if(!s&&i===0&&a!==void 0&&Number.isFinite(a)){let b=dL(e,t,r,n,o,a,c);if(b&&m(b.ay))return{beta:b.beta,trimmed:!0,ay:b.ay}}}let d=[1,3,7,15,20].map(h=>h*se).filter(h=>h<=c);return f(0,d,!0)??{beta:0,trimmed:!1}}function Yv(e,t){let{lo:r,hi:n}=t,o=t.ayLo,a=e(r,o).cn,s=e(n,o).cn,i=r;for(let c=0;c<40;c++){let l=s-a,u=Math.abs(l)>1e-12?(r*s-n*a)/l:.5*(r+n);u>Math.min(r,n)&&u<Math.max(r,n)||(u=.5*(r+n));let m=e(u,o),f=m.cn;if(o!==void 0&&(o=m.ay),i=u,Math.abs(f)<1e-5||Math.abs(n-r)<1e-5)break;f<0==a<0?(r=u,a=f,s*=.5):(n=u,s=f,a*=.5)}return i}function dL(e,t,r,n,o,a,s){let i=(f,p)=>{let d=wt(e,t,r,f,n,void 0,null,void 0,p);return{r:d.res,c:d.cn}},c=o,l=a,u=i(c,l),m=0;for(let f=0;f<fL;f++){let p=i(c+sh,l),d=i(c,l+ih),h=(p.r-u.r)/sh,b=(d.r-u.r)/ih,g=(p.c-u.c)/sh,y=(d.c-u.c)/ih,R=h*y-b*g;if(!Number.isFinite(R)||R===0||Math.abs(R)<yL*(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 M=(u.c*b-u.r*y)/R,v=(u.r*g-u.c*h)/R,x=Math.min(1,hL/Math.max(Math.abs(M),1e-300),bL/Math.max(Math.abs(v),1e-300));if(c+=x*M,l+=x*v,Math.abs(c-o)>gL||Math.abs(c)>s||l*a<0)return null;u=i(c,l)}return null}var fL=8,sh=1e-5,ih=.001,hL=1*se,bL=2,gL=5*se,yL=.5;function Zv(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 on){let h=c.wheels[d],b=xe(t,nn(d)),g=Ht(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:bh(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=Rs(e,o/se,u,Zr(xe(t,"front").model),{FL:c.wheels.FL.travelMm,FR:c.wheels.FR.travelMm}),p=Ys(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 Dr(e,t,r,n,o,a,s=0){let i=Math.max(8,r),c=_n(e,t,i,n,o,a,s);return n!==0&&o?.driving===void 0&&(c.driving=EL(e,t,i,c,a,s)),c}function _n(e,t,r,n,o,a,s){let i=n*se,c=ia(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}=pL(e,t,r,i,u,l,c,s),d=Zv(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)<=xL,h}var xL=3;function On(e,t,r,n={}){let o=Math.max(8,r),a=n.direction??1,s=n.yawDemandCn??0,i=n.steerMaxDeg??RL,c=typeof n.op=="function"?n.op:()=>n.op,l=typeof n.op=="function"?null:`${o}|${a}|${s}|${i}|${n.op?`${n.op.axG}|${n.op.driveFrontFrac??""}|${n.op.tvRearDiffN??""}`:""}`;if(l!==null){let x=ch.get(e)?.get(t)?.get(l);if(x)return x}let u=(x,k)=>k.trimmed&&Math.abs(k.beta-x.beta)<=Yl&&Math.abs(k.ay-x.ay)*Me<=Wl,m=!1,f=(x,k)=>{let F=_n(e,t,o,a*x,k,c(a*x),s);return u(k,F)?(F.driving=!0,F):(m=F.overturned,null)},p=[_n(e,t,o,0,void 0,c(0),s)],d=null,h=!1,b,g=x=>{let k=p.length-1;for(;k>1&&x.sb*(p[k].beta-p[k-1].beta)>=0;)k--;let F=a*(x.state.ay-p[k].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,k)&&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,k=!1)=>k||PL(p[p.length-1],x)?LL(e,t,o,a,p,x,c,s):null,R=p[0].trimmed?p[0]:null;if(!R){let x=0;for(let k=Wv;k<=i&&!R;k+=Wv){let F=_n(e,t,o,a*k,void 0,c(a*k),s);if(F.trimmed){let w=k;R=F;for(let C=0;C<6;C++){let T=.5*(x+w),S=_n(e,t,o,a*T,void 0,c(a*T),s);S.trimmed?(w=T,R=S):x=T}}else x=k}R&&(R.driving=!0,p.push(R))}if(R){let x=Math.abs(R.steerDeg),k=Math.min(lh,100/(o*o)),F=R;for(;x<i;){let w=Math.min(i,x+k),C=f(w,F);if(C){let L=y(C);if(L){g(L);break}if(p.push(C),w>=i||s1(e,a*w))break;Math.abs(C.beta-F.beta)<.5*Yl&&Math.abs(C.ay-F.ay)*Me<.5*Wl&&(k=Math.min(lh,1.5*k)),x=w,F=C;continue}if(k>vL){k*=.5;continue}let T=m,S=!1,A=null;for(let L of kL){let D=Math.min(i,x+L);if(D<=x)continue;let I=f(D,F);if(I){if(A=y(I,!0),A)break;p.push(I),x=D,F=I,k=Math.min(lh,100/(o*o)),S=!0;break}}if(S)continue;if(A){g(A);break}d=x,h=T;let P=T?null:TL(e,t,o,a,p,c,s);P&&g(P);break}}else d=0;let M=p[0];for(let x of p)a*x.ay>a*M.ay&&(M=x);let v={states:p,foldDeg:d,rollover:h,peak:M,...b?{fold:b}:{}};if(l!==null){let x=ch.get(e);x||(x=new WeakMap,ch.set(e,x));let k=x.get(t);k||(k=new Map,x.set(t,k)),k.size>256&&k.clear(),k.set(l,v)}return v}var ch=new WeakMap,RL=90,Yl=1.5,Wl=2.5,lh=5,vL=.002,kL=[.5,1],Wv=2.5,Jv=.01,Lr=.001,ML=.05,SL=.25,AL=5,FL=2,jv=1e-8,wL=1e-7,CL=1e-6;function e1(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,ia(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)<jv;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)>FL)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 M=0;M<60&&R!==0&&Math.abs(y-b)>jv;M++){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>Wl?null:{steerDeg:h.x,ay:h.ay}}function Ks(e,t,r,n,o){let a=Zv(e,t,r,n.beta*se,n.steerDeg*se,n.ay*Me,ia(e,o(n.steerDeg),r,t));return{...a,trimmed:!a.overturned,driving:!a.overturned}}function TL(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=t1(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=Jv;Math.abs(g.beta-c.beta)<=Yl;x*=1.5){let k=f(g.beta+y*x);if(!k)return null;if(n*k.steerDeg<=n*g.steerDeg){R=k;break}b=g,g=k}if(!R)return null;let M=r1(f,n,b,g,R);if(!M)return null;let v=Ks(e,t,r,M,a);return!v.trimmed||Math.abs(v.beta-c.beta)>Yl||Math.abs(v.ay-c.ay)*Me>Wl?null:{state:v,sb:m}}function t1(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=e1(e,t,r,s,i,n,o);if(!c)return null;let l={beta:s,...c};return a.push(l),l}}function PL(e,t){let r=Math.abs(t.beta-e.beta);return r>SL&&r>AL*Math.abs(t.steerDeg-e.steerDeg)}function LL(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=t1(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=Jv;f*(a.beta-g.beta)>0;R=Math.min(ML,1.5*R)){let M=p(f*(a.beta-g.beta)>R?g.beta+f*R:a.beta);if(!M)return null;let v=n*M.steerDeg<=n*g.steerDeg;if(!y)v&&(y=[b,g,M]);else if(!v){let x=r1(p,n,...y);if(!x)return null;let k=Ks(e,t,r,x,s);return k.trimmed?{state:k,sb:f}:null}b=g,g=M}return null}function r1(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*Lr-.5*(i-s))break;let h=!0;if(Math.abs(m)>Lr){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 M=m;if(m=f,Math.abs(R)<Math.abs(.5*y*M)&&R>y*(s-c.beta)&&R<y*(i-c.beta)){f=R/y;let v=c.beta+f;(v-s<2*Lr||i-v<2*Lr)&&(f=d>=c.beta?Lr:-Lr),h=!1}}h&&(m=c.beta>=d?s-c.beta:i-c.beta,f=o1*m);let b=e(Math.abs(f)>=Lr?c.beta+f:c.beta+(f>=0?Lr:-Lr));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 gh(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 Ks(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=e1(e,t,r,g,y,i,c);if(!R)return null;let M={beta:g,...R};u.push(M),h=M;let v=l(M);if(Math.abs(v)<("steerDeg"in a?wL:CL))break;v<0?(m=M,p=v,d*=.5):(f=M,d=v,p*=.5)}return Ks(e,t,r,h,i)}function DL(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 gh(e,t,r,n.fold,a,{steerDeg:o});let u=typeof a.op=="function"?a.op(o):a.op,m=_n(e,t,r,o,l,u,a.yawDemandCn??0);return m.driving?m:null}function EL(e,t,r,n,o,a){if(!n.trimmed)return!1;let s=n.steerDeg<0?-1:1,{states:i}=On(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 an(e,t,r,n,o){let a=Math.max(8,r),s=n>=0?1:-1,i=Math.abs(n),c=(b,g)=>Dr(e,t,a,s*b,g,o),l=On(e,t,a,{direction:s,op:o}),{fold:u}=l;if(u&&Math.abs(u.state.steerDeg)<=sa){if(i>Math.abs(u.state.ay))return Xv(e,t,a,s,i,o);if(i>Math.abs(u.stall.ay)){let b=gh(e,t,a,u,{direction:s,op:o},{ayG:i});if(b)return b}}let m=l.states.filter(b=>Math.abs(b.steerDeg)<=sa),f=m[m.length-1],p=l.states.length>m.length;p&&Math.abs(f.steerDeg)<sa&&m.push(c(sa,f));let d=m.findIndex(b=>Math.abs(b.ay)>=i);if(d===0)return Dr(e,t,a,0,void 0,o);if(d>0)return Uv(m[d-1],m[d],i,c);let h=n1(m,c,void 0,p||l.foldDeg===null);return h.ay>=i?Uv(h.below,h.state,i,c):l.foldDeg!==null&&l.foldDeg<sa?Xv(e,t,a,s,i,o):h.state}var sa=20;function Uv(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)<=IL||a.steer-o.steer<=_L)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 IL=1e-9,_L=1e-7;function n1(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=NL/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[k,F]=Math.abs(a.ay)>=Math.abs(x.ay)?[a,x]:[x,a];f=Math.abs(k.steerDeg),p=-Math.abs(k.ay),d=Math.abs(F.steerDeg),h=-Math.abs(F.ay)}else{let x=Math.abs(e[o].lockDeg??e[o].steerDeg),k=x-OL,F=o>0&&n&&k>Math.abs(a.steerDeg)?t(k,a):null;if(!F||Math.abs(F.ay)<=Math.abs(e[o].ay)){let w=t(s,a);return{state:w,below:a,ay:Math.abs(w.ay)}}g=w=>t(w,a),c=Math.abs(a.steerDeg),l=x,u=k,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 k=.5*(c+l);if(Math.abs(u-k)<=2*i-.5*(l-c))break;let F=!0;if(Math.abs(y)>i){let S=(u-f)*(m-h),A=(u-d)*(m-p),P=(u-d)*A-(u-f)*S;A=2*(A-S),A>0&&(P=-P),A=Math.abs(A);let L=y;if(y=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=k>=u?i:-i),F=!1}}F&&(y=u>=k?c-u:l-u,R=o1*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 M=b??t(s,a),v=Math.abs(M.steerDeg)>s?e[o]:a;return{state:M,below:v,ay:Math.abs(M.ay)}}var NL=.001,OL=.01,o1=(3-Math.sqrt(5))/2;function Xv(e,t,r,n,o,a){let s=l=>Math.abs(Dr(e,t,r,n*l,void 0,a).ay),i=0,c=sa;if(s(c)<o)return Dr(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 Dr(e,t,r,n*.5*(i+c),void 0,a)}function yh(e,t,r,n,o){let a=an(e,t,r,n,o);return a.steering?Math.abs(a.steering.totalNm):NaN}function xh(e,t,r,n,o){if(!Tn(e))return NaN;let a=n<0?-1:1,s=Math.abs(n),i=an(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=Dr(e,t,r,a*u,void 0,o),p=Dr(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 mh(e,t,r,n,o,a){let s=Math.max(8,r),i=wt(e,t,s,n*se,o*se,void 0,ia(e,a,s,t));return{ay:i.ay,cn:i.cn}}function Rh(e,t,r,n,o){let a=Math.max(8,r),s=an(e,t,a,n,o),i=.5,c=mh(e,t,a,s.beta+i,s.steerDeg,o).cn,l=mh(e,t,a,s.beta-i,s.steerDeg,o).cn;return(c-l)/(2*i*se)*e.massTotal*Me*(e.wheelbase/1e3)}function vh(e,t,r,n){let o=Math.max(8,r),{branch:a,opts:s}=VL(e,t,o,n);return a1(e,t,o,a,s)}function VL(e,t,r,n){if(!e.tv?.enabled){let s=n?{op:n}:{};return{branch:On(e,t,r,s),opts:s}}let o=ph(e,t,r),a={op:s=>{let i=dh(e,r,s,o);return i===0?n:{axG:n?.axG??0,driveFrontFrac:n?.driveFrontFrac,tvRearDiffN:i}}};return{branch:On(e,t,r,a),opts:a}}function a1(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 Ks(e,t,r,n.peak,a);let i=(l,u)=>_n(e,t,r,l,u,a(l),s),c=n.states[0].driving||!n.peak.driving?n.states:n.states.slice(1);return n1(c,i,c.indexOf(n.peak),n.foldDeg===null).state}function kh(e,t,r,n={}){let o=n.radius!==void 0&&n.radius>0&&Number.isFinite(n.radius)?n.radius:void 0,a=o===void 0?Math.max(8,r):Math.max(8,Math.sqrt(Me*o)),s=(n.betaMaxDeg??10)*se,i=(n.deltaMaxDeg??10)*se,[c,l]=n.betaRangeDeg?[n.betaRangeDeg[0]*se,n.betaRangeDeg[1]*se]:[-s,s],[u,m]=n.deltaRangeDeg?[n.deltaRangeDeg[0]*se,n.deltaRangeDeg[1]*se]:[-i,i],{lf:f,lr:p}=uh(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&&Tn(e),R=y?Zr(xe(t,"front").model):void 0,M=(E,_,V,N)=>V===1?E:E+(_-E)*N/(V-1),v=e.tv?.enabled?ph(e,t,a):0,x=E=>{let _=dh(e,a,E/se,v);return!n.axG&&_===0?null:ia(e,{axG:n.axG??0,driveFrontFrac:n.driveFrontFrac,tvRearDiffN:_},a,t)},{lf:k,lr:F}=uh(e),w=n.reserves?Hs(t,e.massTotal*Me*1.2):null,C=E=>w?xr(w,{FL:E.FL,FR:E.FR,RL:E.RL,RR:E.RR},{lf:k,lr:F}):null,T=[],S={ay:[],cn:[]},A=0;for(let E=0;E<b;E++){let _=M(u,m,b,E),V=x(_),N=[],$=[],K=[],z=[],j=w?{stabil:[],agil:[]}:void 0,Q=y?Kv():void 0,ne;for(let Y=0;Y<g;Y++){let J=M(c,l,g,Y),re=wt(e,t,a,J,_,ne,V,o);if(ne=Number.isFinite(re.ay)?re.ay*Me:void 0,N.push(re.ay),$.push(re.cn),K.push(J/se),z.push(_/se),j){let pe=C(re.wheels);j.stabil.push(pe.stabil),j.agil.push(pe.agil)}Q&&Hv(Q,Gv(e,t,_,re.wheels)),Math.abs(re.ay)>A&&(A=Math.abs(re.ay))}T.push({label:`\u03B4 ${(_/se).toFixed(0)}\xB0`,ay:N,cn:$,betaDeg:K,deltaDeg:z,reserve:j,steering:Q});let te=null,fe=1/0;for(let Y=1;Y<$.length;Y++){if(!Number.isFinite($[Y-1])||!Number.isFinite($[Y])||$[Y-1]!==0&&$[Y-1]<0==$[Y]<0)continue;let J=$[Y-1]===$[Y]?0:$[Y-1]/($[Y-1]-$[Y]),re=N[Y-1]+J*(N[Y]-N[Y-1]);if(o===void 0&&_!==0&&Math.abs(re)>=.05&&Math.sign(re)!==Math.sign(_))continue;let pe=Math.abs(K[Y-1]+J*(K[Y]-K[Y-1])-d/se);pe<fe&&(fe=pe,te=re)}te!==null&&(S.ay.push(te),S.cn.push(0))}let P=[];for(let E=0;E<b;E++){let _=M(c,l,b,E),V=[],N=[],$=[],K=[],z=w?{stabil:[],agil:[]}:void 0,j=y?Kv():void 0,Q;for(let ne=0;ne<g;ne++){let te=M(u,m,g,ne),fe=wt(e,t,a,_,te,Q,x(te),o);if(Q=Number.isFinite(fe.ay)?fe.ay*Me:void 0,V.push(fe.ay),N.push(fe.cn),$.push(_/se),K.push(te/se),z){let Y=C(fe.wheels);z.stabil.push(Y.stabil),z.agil.push(Y.agil)}j&&Hv(j,Gv(e,t,te,fe.wheels))}P.push({label:`\u03B2 ${(_/se).toFixed(0)}\xB0`,ay:V,cn:N,betaDeg:$,deltaDeg:K,reserve:z,steering:j})}let L=.5*se,D=x(h),I,G;if(o===void 0)I=(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),G=(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 E=(N,$)=>wt(e,t,a,N,$,void 0,x($),o).cn,_=(N,$,K)=>Number.isFinite(N)?(-3*N+4*$-K)/(2*L):(K-$)/L,V=E(d,h);I=-_(V,E(d-L,h),E(d-2*L,h)),G=_(V,E(d,h+L),E(d,h+2*L))}let O=0;if(D&&D.axG){let E=wt(e,t,a,d,h,void 0,D,o),_=0;for(let V of on)_+=E.wheels[V].fxShort;O=_/Math.abs(e.massTotal*D.axG*Me)}let W=S.ay.reduce((E,_)=>Math.max(E,Math.abs(_)),0);return{isoBeta:P,isoDelta:T,trim:S,maxAy:A,stability:I,control:G,speed:o===void 0?a:Math.sqrt(W*Me*o),...o!==void 0?{radius:o}:{},axG:D?.axG??0,axShortfall:O,...R?{steeringAligningSource:R}:{}}}function s1(e,t){return Ys(e,t*se).atLock}function BL(e,t,r,n,o=Pr(e,t,r)){let a=r,s=e.massTotal,i=on.filter(g=>zt(g)?n.drivenFront:n.drivenRear),c=o.peakAt,l={front:n.drivenFront?Vt(e,"front",1):void 0,rear:n.drivenRear?Vt(e,"rear",1):void 0},u=new Map,m=(g,y)=>{let R=`${g}:${y}`,M=u.get(R);if(M===void 0){let v=Math.max(1,y*$s);M=Mt(xe(t,g),v,0,!1,c(g,v)),u.set(R,M)}return M},f=(g,y)=>y>0?Bs(y,R=>m(g,R)):0,p=(g,y,R,M)=>{let v=xe(t,g),x=D=>{let I=Math.max(0,R[D]),G=c(g,I);return{Fz:I,a:f(g,I),b:G.fyPeak,slide:0,cap:O=>I>0?Mt(v,I,O,!1,G):0}},[k,F]=g==="front"?["FL","FR"]:["RL","RR"],w=x(k),C=x(F),T=M[k]*w.b,S=M[F]*C.b,A=w.cap(T)+C.cap(S),P=Vs(w,C,T+S,y,A);return{l:k,r:F,full:P,asHeld:()=>({axle:g,strong:w.cap(T)>=C.cap(S)?k:F,full:P,open:Vs(w,C,T+S,ra,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,M=0)=>{let v={FL:0,FR:0,RL:0,RR:0},x=Le(e,g,0,a,0,y),k,F=P=>(k?.ax!==P&&(k={ax:P,loads:Le(e,g,(P+M)/Me,a,0,y)}),k.loads),w=Qc(P=>zo(R,F(P),x,c).short,-M,1),C=R,T=P=>{let L=w.at(P);v=F(L),C=zo(R,v,x,c).util;let D=0,I=n.diffYaw?{fx:{FL:0,FR:0,RL:0,RR:0},axles:[]}:null;for(let G of i){let O=l[nn(G)];if(O){if(zl(G)){let V=p(nn(G),O,v,C);D+=V.full,I&&(I.fx[V.l]=I.fx[V.r]=V.full/2,I.axles.push(V.asHeld()))}continue}let W=Math.max(0,v[G]),E=c(nn(G),W),_=Mt(xe(t,nn(G)),W,C[G]*E.fyPeak,!1,E);D+=_,I&&(I.fx[G]=_)}if(I){let G={};for(let O of on){let W=Math.max(0,v[O]);G[O]={Fz:W,Fy:C[O]*c(nn(O),W).fyPeak,Fx:I.fx[O]}}for(let O of I.axles)D+=gl(O,G,h,b(g))-O.full}return D/s},S=wv(T,-M,rn).fx,A=w.edge();return A!==void 0&&S>A&&(S=A,T(S)),{ax:S,loads:v}}}}var Hl=.05,qv=.001,Qv=16,jl=8;function Mh(e,t,r,n){let o=Math.max(jl,r),a=n.nSteer??7,s=e.tv?.enabled?ph(e,t,o,n.steerMaxDeg):0,i=E=>{let _=dh(e,o,E,s);return _===0?void 0:{axG:0,tvRearDiffN:_}},c=n.yawDemandCn??0,l={op:i,yawDemandCn:c,...n.steerMaxDeg!==void 0?{steerMaxDeg:n.steerMaxDeg}:{}},u=On(e,t,o,l),m=E=>{let _={},V={};for(let N of on)_[N]=E.wheels[N].slipDeg*se,V[N]=Math.min(1,E.wheels[N].gripUtil);return{steerDeg:E.steerDeg,ayMs:Math.max(0,E.ay*Me),ayG:E.ay,slip:_,util:V,scrub:E.ay>0?$L(E,e.massTotal):0}},f=null,p=E=>{if(f&&E===f.steerDeg)return m(f);let _=DL(e,t,o,u,E,l);if(_)return m(_);let V=u.states[0];for(let N of u.states)N.steerDeg<=E&&(V=N);return m(V)},d=u.peak.driving&&u.peak.ay>0?a1(e,t,o,u,l):null,h=d?Math.max(0,d.ay*Me):0,b=d?[...u.states.filter(E=>E.steerDeg<d.steerDeg),d]:u.states,g=d?b.findIndex(E=>E.ay*Me>=.995*h):0,y=b[g].steerDeg,{fold:R}=u;if(d&&R&&u.peak===R.state){let E=.995*h/Me,_=u.states.indexOf(R.stall),V=_-1;for(;V>0&&u.states[V].beta===R.stall.beta;)V--;let N=Math.sign(R.stall.beta-u.states[V].beta),$=_;for(;$>0&&u.states[$].ay>=E&&Math.sign(u.states[$].beta-u.states[$-1].beta)!==-N;)$--;u.states[$].ay<E&&(f=gh(e,t,o,R,l,{ayG:E},u.states.slice($,_+1)))}if(f)y=f.steerDeg;else if(g>0){let E=b[g-1].steerDeg,_=y;for(let V=0;V<8&&_-E>.001;V++){let N=.5*(E+_);p(N).ayMs>=.995*h?_=N:E=N}y=_}let M=[];for(let E=0;E<(h>0?a:1);E++){let _=E/(a-1);M.push(p(y*(_+Math.sin(Math.PI/2*_))/2))}M[0].ayMs=0;let v=[],x=[],k=[],F=[],w=Pr(e,t,o,void 0,n.diffYaw===!0),C=BL(e,t,o,n,w),T=n.axDrag??0,S=E=>{let _=w.limitAt(E.ayMs/Me,E.steerDeg,E.util,T+E.scrub);return{axD:_.edge!==void 0&&_.edge>0?_.edge:_.ax,locked:_.axUnlocked-_.ax>Hl}},A=E=>C.limitAt(E.ayMs/Me,E.steerDeg,E.util,T+E.scrub).ax,P=M.map(E=>({p:E,axA:A(E),...S(E)})),L=[];for(let E=0;E+1<P.length;E++){let _=P[E],V=P[E+1],N=[];_.locked!==V.locked?N.push({read:S,past:$=>$.locked===V.locked,braking:!0}):(V.axA>_.axA+Hl&&N.push({read:$=>({axA:A($)}),past:$=>($.axA??-1/0)>_.axA}),-V.axD>-_.axD+Hl&&N.push({read:S,past:$=>-($.axD??0)>-_.axD}));for(let{read:$,past:K,braking:z}of N){let j=_.p.steerDeg,Q=V.p.steerDeg,ne=null,te=_.axD,fe=V.axD;for(let Y=0;Y<Qv&&Q-j>qv&&!(z&&Math.abs(fe-te)<=Hl);Y++){let J=.5*(j+Q),re=p(J),pe=$(re);K(pe)?(Q=J,ne={p:re,r:pe},fe=pe.axD??fe):(j=J,te=pe.axD??te)}if(ne){let{p:Y,r:J}=ne,re=J.axD!==void 0&&J.locked!==void 0?{axD:J.axD,locked:J.locked}:S(Y);L.push({p:Y,axA:J.axA??A(Y),...re})}}}P.push(...L),P.sort((E,_)=>E.p.steerDeg-_.p.steerDeg);let D=E=>E.axA+T+E.p.scrub,I=.001*Math.max(1,M[M.length-1].ayMs),G=[];for(let E=0;E+1<P.length;E++){let _=P[E],V=P[E+1];if(!(D(_)>=0&&D(V)<0))continue;let N=_.p.steerDeg,$=V.p.steerDeg,K=null,z=null;for(let Q=0;Q<Qv&&$-N>qv;Q++){let ne=.5*(N+$),te=p(ne);D({p:te,axA:A(te)})>=0?(N=ne,K=te):($=ne,z=te)}let j=K??z;j&&j.ayMs>_.p.ayMs&&j.ayMs<V.p.ayMs&&G.push({p:j,axA:-(T+j.scrub),steady:!0,...S(j)})}P.push(...G),P.sort((E,_)=>E.p.steerDeg-_.p.steerDeg);let O=!1;for(let{p:E,axA:_,axD:V,steady:N}of P){let $=v.length-1,K=$>=0&&(N||O?!(E.ayMs>v[$]):E.ayMs-v[$]<I);O=N===!0&&!K,K?(x[$]=Math.max(x[$],_),k[$]=Math.min(k[$],V)):(v.push(E.ayMs),x.push(_),k.push(V),F.push(E.scrub))}for(let E=v.length-2;E>=0;E--)x[E]=Math.max(x[E],x[E+1]),k[E]=Math.min(k[E],k[E+1]);return{ayMax:v[v.length-1],ay:v,axAccel:x,axDecel:k,axScrub:F,rollover:u.rollover,atLock:d!==null&&s1(e,d.steerDeg)}}function $L(e,t){let r=e.beta*se,n=0;for(let o of on){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 sW=Math.PI/180,iW={speeds:Array.from({length:23},(e,t)=>8+t),steerMaxDeg:14,steerSteps:29};function c1(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 ca={enabled:!1,kp:3e3,ffLow:150,ffHigh:300,vLow:18,vHigh:25},i1=e=>c1(e.ffLow,e.ffHigh,e.vLow,e.vHigh);var nr={power_limit_kw:{value:0,label:"battery power limit (0 = none)",unit:"kW"},v_limit_endurance:{value:0,label:"endurance speed limit (0 = none)",unit:"km/h"},endurance_reserve:{value:0,label:"endurance energy reserve (0 = flat out)",unit:"%"},grip_scale:{value:1,label:"grip scale (rig \u2192 road)",unit:"-"},stiffness_scale:{value:1,label:"stiffness scale (rig \u2192 road)",unit:"-"},camber_front_deg:{value:0,label:"static camber front (\u2212 top in)",unit:"\xB0"},camber_rear_deg:{value:0,label:"static camber rear (\u2212 top in)",unit:"\xB0"},cg_height:{value:300,label:"CG height",unit:"mm"},tire_vertical_rate:{value:100,label:"tyre vertical rate",unit:"N/mm"},tire_vertical_damping:{value:0,label:"tyre vertical damping",unit:"N\xB7s/mm"},arb_front:{value:20,label:"ARB front (@wheel)",unit:"N/mm"},arb_rear:{value:15,label:"ARB rear (@wheel)",unit:"N/mm"},heave_spring_front:{value:0,label:"Heave spring front (@wheel)",unit:"N/mm"},heave_spring_rear:{value:0,label:"Heave spring rear (@wheel)",unit:"N/mm"},unsprung_mass:{value:8,label:"unsprung mass/corner",unit:"kg"},brake_balance:{value:.6,label:"brake balance (front)",unit:"-"},damper_front:{value:2.5,label:"damper front",unit:"N\xB7s/mm"},damper_rear:{value:2.5,label:"damper rear",unit:"N\xB7s/mm"},cop_long:{value:.5,label:"CoP aft of front",unit:"\xB7wb"},cop_height:{value:300,label:"CoP height",unit:"mm"},ride_height_front:{value:30,label:"static ride height front (laden)",unit:"mm"},ride_height_rear:{value:35,label:"static ride height rear (laden)",unit:"mm"},I_yaw:{value:295,label:"yaw inertia Izz",unit:"kg\xB7m\xB2"},I_roll:{value:95,label:"roll inertia Ixx",unit:"kg\xB7m\xB2"},I_pitch:{value:380,label:"pitch inertia Iyy",unit:"kg\xB7m\xB2"},I_wheel:{value:0,label:"rotating inertia per wheel",unit:"kg\xB7m\xB2"},I_rotor:{value:0,label:"driveline inertia at the motor",unit:"kg\xB7m\xB2"},ackermann_pct:{value:50,label:"Ackermann",unit:"%"},toe_front_deg:{value:0,label:"static toe front (+ in)",unit:"\xB0"},toe_rear_deg:{value:0,label:"static toe rear (+ in)",unit:"\xB0"},spring_front:{value:35,label:"spring front (@spring)",unit:"N/mm"},spring_rear:{value:40,label:"spring rear (@spring)",unit:"N/mm"},mr_front:{value:1,label:"motion ratio front",unit:"-"},mr_rear:{value:1,label:"motion ratio rear",unit:"-"},track_front:{value:1200,label:"track front",unit:"mm"},track_rear:{value:1200,label:"track rear",unit:"mm"},wheelbase:{value:1535,label:"wheelbase",unit:"mm"},rc_front:{value:30,label:"roll centre front",unit:"mm"},rc_rear:{value:40,label:"roll centre rear",unit:"mm"},tv_enabled:{value:0,label:"torque vectoring",unit:"0/1"},tv_kp:{value:3e3,label:"TV yaw-rate gain",unit:"N per rad/s"},tv_ff_low:{value:150,label:"TV feedforward, low speed",unit:"N"},tv_ff_high:{value:300,label:"TV feedforward, high speed",unit:"N"},tv_v_low:{value:18,label:"TV feedforward ramp start",unit:"m/s"},tv_v_high:{value:25,label:"TV feedforward ramp end",unit:"m/s"}},GL=["k_yaw","k_roll","k_pitch"];function Ws(e){for(let t of GL)delete e[t];for(let t of Object.keys(nr)){let r=e[t];if(!r){e[t]={...nr[t]};continue}e[t]={...r,label:nr[t].label,unit:nr[t].unit}}return e}function Z(e,t){return e[t]?.value??nr[t].value}function Ul(e){let t=(r,n)=>e[r]?.value??n;return{enabled:t("tv_enabled",0)>=.5,kp:t("tv_kp",ca.kp),ffLow:t("tv_ff_low",ca.ffLow),ffHigh:t("tv_ff_high",ca.ffHigh),vLow:t("tv_v_low",ca.vLow),vHigh:t("tv_v_high",ca.vHigh)}}var l1=[10,25,50,100,200,300];function Sh(e,t,r,n,o){let s=l1.map(i=>Math.round(i<=25?r*i:r*25+n*(i-25)));return{id:e,label:t,speedMmS:[...l1],reboundN:s,bumpN:s.map(i=>Math.round(i*o))}}var Xl={name:"Generic FS damper",curves:[Sh("c1","Soft",1.6,1,.65),Sh("c2","Medium",3,1.6,.65),Sh("c3","Firm",8,2.4,.65)]};function ql(e){let t=e.curves.length;return t>0?e.curves[Math.floor((t-1)/2)].id:""}var sn=25;function la(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 u1(e,t){return t>=0?la(e.rebound,t):-la(e.bump,-t)}function m1(e,t,r){return t*u1(e,t*r)}var Ah=(e,t)=>e.curves.find(r=>r.id===t);function js(e,t){let r=Ah(e,ql(e)),n=(t&&Ah(e,t.bump))??r,o=(t&&Ah(e,t.rebound))??r;return{bump:{speedMmS:n?.speedMmS??[],forceN:n?.bumpN??[]},rebound:{speedMmS:o?.speedMmS??[],forceN:o?.reboundN??[]}}}var Ql=5e3;function Us(e,t){let r=t>0?t:1,n=[],o=[],a=e.bump.speedMmS.map(c=>c/r).filter(c=>c<Ql),s=e.rebound.speedMmS.map(c=>c/r).filter(c=>c<Ql),i=c=>{n.push(c),o.push(m1(e,r,c))};i(-Ql);for(let c=a.length-1;c>=0;c--)i(-a[c]);i(0);for(let c of s)i(c);return i(Ql),{kind:"map",input:"velocity",x:n,y:o}}var Fh=64;function Xs(e,t,r){let n=t>0?t:1,o=Math.max(r,1e-6),a=0;for(let s=0;s<Fh;s++){let i=Math.sin((s+.5)*Math.PI/Fh),c=n*o*i;a+=n*(la(e.rebound,c)+la(e.bump,c))*i}return a*(Math.PI/Fh)/(Math.PI*o)}function Vn(e,t,r,n,o=e){let a=(c,l,u)=>{if(!c||c.curves.length===0)return;let m=js(c,l);return{law:m,curve:Us(m,u),rate:Xs(m,u,sn)}},s=a(e,t?.front,r),i=a(o??e,t?.rear,n);return!s&&!i?null:{...s?{front:s}:{},...i?{rear:i}:{}}}var p1=(e,t)=>({...e,y:e.y.map(r=>r*t)}),KL=e=>({...e,x:e.x.map(t=>-t).reverse(),y:e.y.map(t=>-t).reverse()});function wh(e,t,r){let n=Math.abs(r)>0?Math.abs(r):1,o=js(e,t);return{law:o,curve:p1(Us(o,n),.5),rate:Xs(o,n,sn)/2,mr:n,ratio:n,share:.5}}function Ch(e,t,r,n,o){let a=n*(Math.abs(r)>0?Math.abs(r):1),s=js(e,t),i=p1(Us(s,a),1/n);return{law:s,curve:o?KL(i):i,rate:Xs(s,a,sn)/n,mr:a/n,ratio:a,share:1/n}}function qs(e,t){let r=e.damperModelIdRear?t(e.damperModelIdRear):void 0,n=e.heaveDamperModelId?t(e.heaveDamperModelId):void 0,o=e.rollDamperModelId?t(e.rollDamperModelId):void 0;return{...r?{damperModelRear:r}:{},...n?{heaveDamperModel:n}:{},...o?{rollDamperModel:o}:{}}}function Qs(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 Er(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 Js(e){return e.kind==="coil"?2:1}function Zs(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 f1(e){return Zs(e)/2}function h1(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 d1(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 HL(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 ei(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*Zs(e.section)/e.barLength,a=2*o/(n*n),s=f1(e.armSection??e.section),i=3*e.E*s/n**3,c=e.dropLinkRate??1/0;return{rateAtLink:d1([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*Zs(e.section)/e.barLength,a=2*o/(n*n),s=3*e.E*h1(e.blade)/n**3,i=e.dropLinkRate??1/0;return{rateAtLink:d1([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*Zs(e.section)/e.length,a=2*o/(n*n);return{rateAtLink:a,contributions:{barTwist:a},torsional:o}}case"coil":{let n=Er(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=HL(e.linkTravel,e.force,t);return{rateAtLink:Math.max(0,n),contributions:{},torsional:0}}}}function Zl(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?pd(t,r):1,o=t?dd(t,r):0,a=ei(e,o).rateAtLink;return{wheelRate:Math.max(0,a*n*n),motionRatio:n,rateAtLink:a}}function ti(e,t){let r=e.damper??0;return!r||e.design.kind==="none"?0:Js(e.design)*r*t*t}var zL=150;function YL(e){return X(e,[0,-.5,1])<-1e-9?U(e,-1):e}function b1(e){let t=e.hardpoints,r=H(t.rockerPivotB,t.rockerPivotA),n=ee(t.rockerPivotA,U(H(t.rockerToDamper,t.rockerPivotA),.6)),o=YL(q(ae(r,H(t.rockerToDamper,t.rockerPivotA))));return{outer:n,inner:ee(n,U(o,zL)),attach:"rocker"}}function Ct(e,t){let r={};for(let o of Lo)r[o]=et($e(e,o));let n={vehicle:e,ctx:r};return t&&(n.kc=Yc(n,t)),n}var Jl=.5;function WL(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 g1=e=>[(e[2][1]-e[1][2])/2,(e[0][2]-e[2][0])/2,(e[1][0]-e[0][1])/2];function eu(e,t,r){let n=Ze(t,e.vehicle.config),o=e.ctx[t],a=r.rigid?void 0:{loadedRadius:r.loadedRadius},s=r.state?null:ge(o,r.travel,r.steer,void 0,a),i=r.state??ot(s),c=ge(o,r.travel+Jl,r.steer,void 0,a),l=ge(o,r.travel-Jl,r.steer,void 0,a),u=(s?s.ok:r.converged)&&c.ok&&l.ok,m=ot(c),f=ot(l),p=(C,T)=>_t(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)],M=C=>WL(R,[p(C,d),p(C,"uprightLower"),p(C,y)]),v=M(m),x=M(f),k=g1(v.rot),F=g1(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*Jl)):w,omega:u?U(H(k,F),1/(2*Jl)):w}}function Th(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 y1(e,t,r){let n=eu(e,t,ft(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 x1(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 R1(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 jL(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 UL=.1*Math.PI/180;function v1(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]))*UL<=o*n}function tu(e,t){return!e.valid||!e.cpLeft||!e.cpRight?!1:v1([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 XL=1;function k1(e){let t=ri(e);if(!t||!e.cpLeft||!e.cpRight||Math.abs(t.left-t.right)>XL)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 ua(e){let t=(n,o,a)=>{if(!n)return Number.NaN;if(!o)return a?0:Number.NaN;let s=n[0]-o[0];return Math.abs(s)>1e-9?n[0]/s:Number.NaN},r=(t(e.cpLeft,e.icLeft,e.lineLeft)+t(e.cpRight,e.icRight,e.lineRight))/2;return e.valid&&Number.isFinite(r)?r:0}function or(e,t,r){let n=r==="front"?"FL":"RL",o=r==="front"?"FR":"RR",a=y1(e,n,t),s=y1(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=x1(a),c=x1(s),l=R1(a,i),u=R1(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=Th(a.cp,f,s.cp,p)??jL(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],M=Math.hypot(y,R)||1,v=y/M,x=R/M,k=(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]-k)*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 Ir(e,t){return{front:or(e,t,"front"),rear:or(e,t,"rear")}}function ru(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 qL(e,t){return{camber:ru(e.travel,e.camber,t),toe:ru(e.travel,e.toe,t),motionRatio:ru(e.travel,e.motionRatio,t),damperLen:e.damperLen?ru(e.travel,e.damperLen,t):0}}var M1=e=>qL(e,0).motionRatio;function Ph(e,t){if(e.kind!=="coil")return null;let r=t??e.motionRatio,n=Er(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 nu(e,t){if(e.kind==="none")return 0;if(e.kind==="tabulated"){let n=a=>QL(e,a);return(n(.5)-n(-.5))/(2*.5)/2}if((e.gap??0)>0)return 0;let r=t??e.motionRatio;return Er(e.rate,0)*r*r/2}function ni(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 QL(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 Lh={kind:"coil",rate:120,motionRatio:.7,gap:5,bothWays:!1};var S1=new WeakMap;function au(e,t){let r=S1.get(e);r||(r=new Map,S1.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=kn(e,t);return r.set(n,a),a}var ZL=32,oi=new Map,A1=new WeakMap,JL=1;function eD(e){let t=A1.get(e);return t===void 0&&(t=JL++,A1.set(e,t)),t}function Dh(e,t){if(!t.linkage)return null;let r=Qr(e,t.linkage,t.design.kind),n=`${eD(e)}|${r?"unit":"bar"}|${JSON.stringify(t.linkage)}`,o=oi.get(n);if(o)return o;let a=Oo(e,t.linkage,{kind:t.design.kind});return oi.size>=ZL&&oi.delete(oi.keys().next().value),oi.set(n,a),a}function $n(e,t,r=0){let n=(o,a)=>{if(!(!o||o.design.kind==="none"))return Zl(o.design,Dh(a,o),r).wheelRate};return{front:n(t.arbFrontDesign,e.front),rear:n(t.arbRearDesign,e.rear)}}function ma(e,t){let r=(n,o)=>{if(!n||n.design.kind==="none")return;let a=n.linkage?au(o,n.linkage).atDesign:void 0;return nu(n.design,a)};return{front:r(t.heaveFrontDesign,e.front),rear:r(t.heaveRearDesign,e.rear)}}function P1(e,t){let r=(a,s)=>{if(!a||a.design.kind!=="coil")return;let i=a.linkage?au(s,a.linkage).atDesign:void 0;return Ph(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 su(e,t){let r=(o,a)=>o?ni(o,Eh(o,a)):0,n=(o,a)=>o?ti(o,Ih(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 Eh=(e,t)=>e.linkage?au(t,e.linkage).atDesign:void 0,Ih=(e,t)=>Zl(e.design,Dh(t,e),0).motionRatio;function L1(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=Eh(f,p);if(ni(f,h)>0)return wh(n,r?.[d],h??(f.design.kind==="coil"?f.design.motionRatio:1))},s=(f,p,d)=>{if(!f||!o?.curves.length)return;let h=Ih(f,p);if(!(ti(f,h)>0))return;let b=Dh(p,f)!==null;return Ch(o,r?.[d],h,Js(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 D1(e,t){let r=t.heaveDamperModel??t.damperModel,n=t.rollDamperModel??t.damperModel,o=(i,c)=>Bn(i)?{source:"none"}:Qs(i.config.coilover,c),a=(i,c)=>{if(!i)return{source:"none"};let l=ni(i,Eh(i,c))>0;return Qs(i.coilover,l?r:void 0)},s=(i,c)=>{if(!i||i.design.kind!=="coil")return{source:"none"};let l=ti(i,Ih(i,c))>0;return Qs(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 E1(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 Bn=e=>e.config.actuation==="decoupled",Gn="a decoupled axle damps in its heave and roll elements, set below";function I1(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}=$n(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?au(f,m.linkage).atDesign:void 0;o(p,nu(m.design,d))}let i=rD(e,t,r),c=tD(e,i);n.kinFront=c.kinFront,n.kinRear=c.kinRear;let l=aD(e,i);n.steerFront=c.steerFront,Number.isFinite(l.ackermannPct)&&o("ackermann_pct",l.ackermannPct);let u=m=>Bn(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"]])Bn(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"]])Bn(m)&&(o(f,0),n.readouts={...n.readouts,[f]:Gn});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 tD(e,t){return{kinFront:w1(e.front),kinRear:w1(e.rear),steerFront:e.front.measured?void 0:iu(e.front,t)}}var F1=new WeakMap;function w1(e){let t=F1.get(e);return t||F1.set(e,t=jo(e)),t}function rD(e,t,r={}){return nD(e,t,r.front,r.rear)}function nD(e,t,r,n){let o=e.front.config.loadedRadius;if(!((er(r??t.tireModel)??0)>0))return o;let a={...t,surveyedRadiusFront:o,surveyedRadiusRear:e.rear.config.loadedRadius};return cu(a,r,n).front??o}var C1=new WeakMap;function iu(e,t=e.config.loadedRadius){let r=C1.get(e);r||(r=new Map,C1.set(e,r));let n=r.get(t);if(n)return n;let o=t===e.config.loadedRadius?void 0:{loadedRadius:t},a=Ld(e,Nt(e.config),void 0,void 0,void 0,void 0,o);return r.size>=4&&r.clear(),r.set(t,a),a}var T1=new WeakMap;function oD(e){return qe(e,{travelMin:-1,travelMax:1,steps:3}).samples[1].metrics.motionRatio??1}var ou=e=>e.measured?M1(e.measured):oD(e);function aD(e,t=e.front.config.loadedRadius){let r=()=>e.front.measured?void 0:iu(e.front,t);return{...sD(e),get steerFront(){return r()},get ackermannPct(){let n=r();return n?Dd(n,dt(e.front),e.config.wheelbase):Number.NaN}}}function sD(e){let t=T1.get(e);if(t)return t;let r=e.front.measured,n=e.rear.measured,a=!r||!n?Ir(Ct(e),{heave:0,pitch:0,roll:0,steer:0}):null,s={wheelbase:e.config.wheelbase,trackFront:r?r.track:dt(e.front),trackRear:n?n.track:dt(e.rear),mrFront:ou(e.front),mrRear:ou(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:ua(a.front),rcGainRear:n||!a?0:ua(a.rear),rcFrontValid:r?!0:!!a?.front.valid,rcRearValid:n?!0:!!a?.rear.valid};return T1.set(e,s),s}var bt={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}},O1=e=>typeof e=="object"&&e!==null&&!Array.isArray(e),ar=(e,t,r,n=1/0)=>typeof e=="number"&&Number.isFinite(e)?Math.min(n,Math.max(r,e)):t;function Kn(e){if(O1(e))switch(e.kind){case"open":case"spool":return{kind:e.kind};case"clutch":{let t=bt.clutch;return{kind:"clutch",preloadNm:ar(e.preloadNm,t.preloadNm,0),rampDriveDeg:ar(e.rampDriveDeg,t.rampDriveDeg,1,90),rampCoastDeg:ar(e.rampCoastDeg,t.rampCoastDeg,1,90),faces:Math.round(ar(e.faces,t.faces,0)),muClutch:ar(e.muClutch,t.muClutch,0,1),rFrictionMm:ar(e.rFrictionMm,t.rFrictionMm,1),rRampMm:ar(e.rRampMm,t.rRampMm,1)}}case"torsen":{let t=bt.torsen,r=ar(e.preloadNm,0,0);return{kind:"torsen",tbrDrive:ar(e.tbrDrive,t.tbrDrive,1),tbrCoast:ar(e.tbrCoast,t.tbrCoast,1),...r>0?{preloadNm:r}:{}}}default:return}}function lu(e){if(!O1(e))return;let t=Kn(e.front),r=Kn(e.rear);return t||r?{...t?{front:t}:{},...r?{rear:r}:{}}:void 0}function ai(e){let t=tn(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=ai(e),r=e.r_dyn.value,n=s=>{if(t[s]!=="diff")return;let i=Kn(e.driveline?.[s]);if(!(!i||i.kind==="independent"))return{kind:i.kind,drive:Os(i,"drive",r),coast:Os(i,"coast",r),hubs:Os(i,"hubs",r)}},o=n("front"),a=n("rear");return o||a?{...o?{front:o}:{},...a?{rear:a}:{}}:void 0}var iD={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"}},_1=e=>{let t=e==="front"?"Front":"Rear";return Object.fromEntries(Object.entries(iD).map(([r,n])=>[`${e}.${r}`,{section:t,...n}]))},uu={..._1("front"),..._1("rear")},N1=e=>e.motorModel?.kind==="ice"?e.motorPlacement==="front"?"front":"rear":null;function V1(e,t){let r=N1(t);if(!(!r||N1(e)===r||t.driveline?.[r]))return{...t.driveline,[r]:{...bt.clutch}}}function Bt(e,t,r,n){return e>0?!(r>0)||!Number.isFinite(r)?e:Math.max(1,e-t/r):n}function mu(e,t,r){let n=Math.max(0,Math.min(1,r)),o=Bt(e.freeRadius,e.staticLoad,e.tyreRate,e.surveyed),a=Bt(t.freeRadius,t.staticLoad,t.tyreRate,t.surveyed);return n*o+(1-n)*a}function pa(e,t,r){if(t===void 0||r===void 0||!Number.isFinite(t)||!Number.isFinite(r))return e;let n=r-t;return n===0?e:Math.max(1,e+n)}function _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 ii(e,t){if(!e)return lD(t);let r=t-Jr(e,0).camber;return r?{...e,camber:e.camber.map(n=>n+r)}:e}function cD(e){return{kinFront:ii(e.kinFront,Z(e,"camber_front_deg")),kinRear:ii(e.kinRear,Z(e,"camber_rear_deg"))}}function lD(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 B1=9.81,$1=e=>e>1?e/100:e;function da(e,t,r){let n=t??e.tireModel??ks(),o=r??e.tireModelRear??n,a={grip:Z(e,"grip_scale"),stiffness:Z(e,"stiffness_scale")},s=yl(n,a);return{front:s,rear:o===n?s:yl(o,a)}}function sr(e,t,r){let n=da(e,t,r),o=Ie(n.front);return ct(n.rear===n.front?o:ll(o,Ie(n.rear)))}function _h(e,t,r){let n=$1(e.front_mass_diss.value),o=da(e,t,r),a=Ie(o.front),s=o.rear===o.front?a:Ie(o.rear),i=t??e.tireModel,c=r??e.tireModelRear??i,l=e.m.value*B1*n/2,u=e.m.value*B1*(1-n)/2,m=(i?a.verticalStiffness():0)||Z(e,"tire_vertical_rate"),f=(c?s.verticalStiffness():0)||Z(e,"tire_vertical_rate"),p=er(i)??0,d=er(c)??0,h=e.surveyedRadiusFront&&e.surveyedRadiusRear?mu({freeRadius:p,staticLoad:l,tyreRate:m,surveyed:e.surveyedRadiusFront},{freeRadius:d,staticLoad:u,tyreRate:f,surveyed:e.surveyedRadiusRear},n):void 0,b=e.surveyedRadiusFront?Bt(p,l,m,e.surveyedRadiusFront):void 0,g=e.surveyedRadiusRear?Bt(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 cu(e,t,r){let n=_h(e,t,r);return{front:n.standingFront,rear:n.standingRear}}function G1(e,t,r){return _h(e,t,r).cgStandingRadius}function ut(e,t,r){let n=$1(e.front_mass_diss.value),o=Z(e,"mr_front")||1,a=Z(e,"mr_rear")||1,{ev:s,evR:i,Wf:c,Wr:l,tireRate:u,tireRateRear:m,tyreFreeRadius:f,tyreFreeRadiusRear:p,cgStandingRadius:d,standingFront:h,standingRear:b}=_h(e,t,r),g=_s(e),y=si(e),R=Vn(e.damperModel,e.damperSetup,o,a,e.damperModelRear??e.damperModel),M=e.readouts?.damper_front===Gn,v=e.readouts?.damper_rear===Gn,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,Z(e,"cop_long"))),copHeight:Z(e,"cop_height"),...e.aeroModel?{model:e.aeroModel}:{},rideHeightFront:Z(e,"ride_height_front"),rideHeightRear:Z(e,"ride_height_rear")};return{massTotal:e.m.value,frontMassFrac:n,steeringSystem:e.steeringSystem,tv:Ul(e),cgHeight:pa(Z(e,"cg_height"),e.cgReference?.standingRadius,d),...d!==void 0?{cgStandingRadius:d}:{},wheelbase:Z(e,"wheelbase"),trackFront:Z(e,"track_front"),trackRear:Z(e,"track_rear"),wheelRateFront:Z(e,"spring_front")*o*o,wheelRateRear:Z(e,"spring_rear")*a*a,tireRate:u,...m!==u?{tireRateRear:m}:{},tireDamping:Z(e,"tire_vertical_damping"),arbFront:Z(e,"arb_front"),arbRear:Z(e,"arb_rear"),brakeBalanceFront:g.balanceFront,brakes:g,...y?{driveline:y}:{},heaveSpringFront:Z(e,"heave_spring_front"),heaveSpringRear:Z(e,"heave_spring_rear"),unsprungPerCorner:Z(e,"unsprung_mass"),unsprungCgHeight:uD(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(Z(e,"rc_front"),e.rcRoad?.gainFront,e.rcRoad?.radiusFront,h),rcHeightRear:_r(Z(e,"rc_rear"),e.rcRoad?.gainRear,e.rcRoad?.radiusRear,b),corneringStiffnessFront:s.corneringStiffness(c),corneringStiffnessRear:i.corneringStiffness(l),damperFront:R?.front&&!M?R.front.rate:Z(e,"damper_front")*o*o,damperRear:R?.rear&&!v?R.rear.rate:Z(e,"damper_rear")*a*a,...R?.front&&!M?{damperCurveFront:R.front.curve}:{},...R?.rear&&!v?{damperCurveRear:R.rear.curve}:{},aero:x,ackermannPct:Z(e,"ackermann_pct"),toeFrontDeg:Z(e,"toe_front_deg"),toeRearDeg:Z(e,"toe_rear_deg"),yawInertia:Z(e,"I_yaw"),steerFront:e.steerFront,...cD(e)}}function uD(e,t){let r=(a,s,i,c)=>a??(s>0?Bt(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 pu={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 K1(e,t=e.batteryModel){if(!t)return e;let r=fr(t),n=(o,a)=>({...o,value:a});return{...e,capacity:n(e.capacity,r.capacityAh),ocv:n(e.ocv,r.voltageAtFull)}}var z1={damper_front:`the damper part sets it: its front curve at ${sn} mm/s`,damper_rear:`the damper part sets it (the rear's own, where the car names one): its rear curve at ${sn} mm/s`};function du(e){let t=!!(e.damperModelId||e.damperModel),r=t||!!(e.damperModelIdRear||e.damperModelRear);return{...t?{damper_front:z1.damper_front}:{},...r?{damper_rear:z1.damper_rear}:{}}}function Y1(e,t=e.damperModel,r=e.damperModelRear??t){if(!t&&!r)return e;let n=Z(e,"mr_front")||1,o=Z(e,"mr_rear")||1,a=Vn(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!==Gn&&(i.damper_front=s(e.damper_front,"damper front",a.front.rate/(n*n))),a.rear&&e.readouts?.damper_rear!==Gn&&(i.damper_rear=s(e.damper_rear,"damper rear",a.rear.rate/(o*o))),i}var W1={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 Nr(e){return!!e&&typeof e=="object"&&"value"in e&&"label"in e}var hD={Batteriekapazit\u00E4t:"pack capacity",Rollwiderstandsbeiwert:"rolling-resistance coefficient"},U1=e=>hD[e]??e;function fu(e){let t=[];for(let r of Object.keys(e)){if(r==="motor"||r==="name")continue;let n=e[r];Nr(n)&&t.push({key:r,label:U1(n.label),value:n.value,unit:n.unit})}return t}var bD=[{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"]}],gD=.5,j1=e=>e==="infinite"?1/0:typeof e=="number"?e:null,yD=e=>/front/.test(e)?e.replace("front","rear"):/rear/.test(e)?e.replace("rear","front"):null,VU=(()=>{let e=W1.rows,t=o=>{let a=yD(o),s=j1(e[o]?.score),i=a&&e[a]?j1(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>=gD&&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 Nh={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 X1(e){let t=new Map;for(let a of fu(e))t.set(a.key,a);let r=new Set,n=[];for(let a of bD){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=fu(e).filter(a=>!r.has(a.key));return o.length&&n.push({title:"Other",rows:o}),n}var Oh={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"},Vh={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"},q1=e=>!!(e.aeroModelId||e.aeroModel);function xD(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 RD=e=>!!(e.batteryModelId||e.batteryModel);function vD(e,t){let r={};return t.geometry&&Object.assign(r,Nh,xD(e)),q1(e)&&Object.assign(r,Oh),RD(e)&&Object.assign(r,pu),Object.assign(r,du(e)),e.readouts&&Object.assign(r,e.readouts),r}function Q1(e,t){let r=vD(e,t);return q1(e)||Object.assign(r,Vh),r}function Bh(e){let t=e.cop_long;return Nr(t)?1-t.value:.5}function kD(e,t){let r=e.front_aero_diss,n=e.cop_long;!Nr(r)||!Nr(n)||(t===r.label?n.value=1-r.value:t===n.label&&(r.value=1-n.value))}function MD(e,t){kD(e,t);let r=e.c_l,n=e.c_w,o=e.l_to_d_ratio;!Nr(r)||!Nr(n)||(t===r.label||t===n.label?Nr(o)&&n.value!==0&&(o.value=r.value/n.value):Nr(o)&&t===o.label&&o.value!==0&&(n.value=r.value/o.value))}function hu(e,t,r){let n=!1;for(let o of Object.keys(e)){if(o==="motor"||o==="name")continue;let a=e[o];if(Nr(a)&&U1(a.label)===t){a.value=r,n=!0;break}}return n&&MD(e,t),n}function bu(e,t,r=0,n,o){let a=()=>({cl:e.c_l.value,cw:e.c_w.value,frontShare:Bh(e),A:e.A.value,platform:null});if(!e.aeroModel)return a();let s=Yr(n??ut(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:Bh(e),A:s.area,platform:s}}var Z1=e=>typeof e=="object"&&e!==null&&typeof e.value=="number"&&typeof e.label=="string";function J1(e,t=e.aeroModel){if(!t)return e;let r=zr(t,{wheelbase:Z(e,"wheelbase")}).at(Z(e,"ride_height_front"),Z(e,"ride_height_rear")),{cl:n,balanceFront:o}=Ip(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(Z1(e.cop_long)?e.cop_long:void 0,nr.cop_long,1-o)};return Z1(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 ci={dsTarget:.25,accelStep:.25,vTol:.002,scanSteps:24,seamIters:8,fitSpacing:1},SD=32;function ek(e,t,r){let n=Math.round(e/t);return Math.max(1,Math.min(Number.isFinite(n)?n:1,Math.floor(r/SD)||1))}function at(e){let t=ci,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 tk=Math.PI/180,gu=.02,rk=new WeakMap;function li(e){let t=rk.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)*tk,l=(e.bank?.[i]??0)*tk,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 rk.set(e,s),s}function yu(e,t,r){return e.n0[t]+e.k[t]*r*r}function nk(e,t){return e.k[t]<0?Math.sqrt(Math.max(0,e.n0[t])/-e.k[t]):1/0}function ok(e,t){if(!e)return null;let r=1/0,n=-1/0;for(let o=0;o<e.n0.length;o++){let a=yu(e,o,t[o]??0);a<r&&(r=a),a>n&&(n=a)}return r>=1-gu&&n<=1+gu?null:{lo:r,hi:n}}var fa=[.1,.25,.5,.75,1,1.25,1.5,2,2.5];function ak(e){let t=e.lo>=1-gu?1:1-1.25*(1-e.lo)-.05,r=e.hi<=1+gu?1:1+1.25*(e.hi-1)+.05,n=[...fa].reverse().find(a=>a<=t)??fa[0],o=fa.find(a=>a>=r)??fa[fa.length-1];return fa.filter(a=>a>=n&&a<=o)}function $h(e,t,r){return r<1?Math.max(e,t):Math.min(e,t)}function sk(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):$h(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 xu(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}=AD(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,M=4*y*(1-g),v=F=>{let{v:w,gear:C,tau:T,target:S}=F;d=0,h=0,b=0;for(let A=0;A<s;A++){let P=i(A),L=e[P];for(let G=0;T<=0&&G<n.count;G++){let O=C;if(w<L-1e-9?n.best(w)>C&&(n.rpm(w,C)>=n.limitRpm||c[A]>=w*M)?O=C+1:C>0&&w<n.vIdle(C)&&(O=C-1):L<w-1e-9&&C>0&&n.best(l[A])<C&&n.rpm(w,C-1)<=n.limitRpm&&(O=C-1),O===C)break;S=O,O>C?d++:h++,T=O>C?y: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 I=L;if(!D)w<L&&(I=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 G=o(A,w,g>0?g*n.share(w,C):0),O=Math.min(L,Math.sqrt(Math.max(0,w*w+2*G*t[A]))),W=w+O>0?2*t[A]/(w+O):1/0;if(W<=T)I=O,b+=W,T-=W;else{let E=Math.min(L,Math.max(0,w+G*T)),_=Math.max(0,t[A]-(w+E)*.5*T);b+=T,T=0,C=S,I=Math.min(L,Math.sqrt(Math.max(0,E*E+2*o(A,E,n.share(E,C))*_)))}}else{let G=w+I>0?2*t[A]/(w+I):0;b+=Math.min(G,T),T-=G,T<=0&&(C=S)}w=I}return{v:w,gear:C,tau:T,target:S}},x=n.best(e[0]),k={v:e[0],gear:x,tau:0,target:x};if(r)for(let F=0;F<6;F++){let w=v(k),C=Math.abs(w.v-k.v)<=1e-9&&w.gear===k.gear&&w.target===k.target&&Math.abs(w.tau-k.tau)<=1e-12;if(k=w,C)break}else{let F=v(k);u[a-1]=F.v,m[a-1]=F.gear+1,f[a-1]=n.rpm(F.v,F.gear),p[a-1]=F.tau>0?1:0}return{v:u,gear:m,rpm:f,shifting:p,upshifts:d,downshifts:h,gapTime:b}}function AD(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 Gh=.001,Kh=9.81,ui=(e,t)=>Hh(e?.gradient?.[t]??0);function Hh(e){return e===0?0:-Kh*Math.sin(e*Math.PI/180)}function ln(e,t){let r=new Array(t);for(let n=0;n<t;n++)r[n]=Hh(e?.[n]??0);return r}var cn=(e,t)=>{let r=e?.mu?.[t];return r!=null&&r>0?r:1},Hn=(e,t)=>e?.bank?.[t]??0;function FD(e,t,r,n,o,a){let s=e.ay(t,r,cn(o,a)),i=Hn(o,a);if(!i)return s;let c=i*Math.PI/180,l=n===0?0:-Math.sign(n)*Kh*Math.sin(c);return Math.max(0,(s+l)/Math.cos(c))}function Ye(e,t){if(!t)return e;let r=t*Math.PI/180;return e*Math.cos(r)+Kh*Math.sin(r)}function zh(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 zn=(e,t,r)=>t?t(r):e,wD=1e-4;function ha(e,t,r,n,o,a,s){let i=at(r),c=[];for(let l=0;l<t.length;l++){let u=t[l],m=Math.abs(u),f=zn(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:zh(b=>b*b*m-FD(f,b,0,u,n,l),Gh,d,i.scanSteps,Math.min(i.vTol,wD));c.push({v:h,ax:0,ay:h*h*u})}return c}function CD(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=Ye(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=zh(p=>u(p)-t.v,Gh,r.v,a.scanSteps,a.vTol),r.ay=r.v*r.v*n;let f=Math.abs(Ye(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 TD(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(Ye(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 ik(e,t,r,n,o,a){let s=at(n),i=r.npts,c=0;for(let l=0;l<s.seamIters;l++){let u=0;c++;for(let m=i-1;m>=0;m--){let f=(m+1)%i;u=Math.max(u,CD(zn(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],s,cn(r,m),ui(r,m),Hn(r,m),a?p=>a(m,p):void 0))}if(u<=s.vTol)break}return c}function ck(e,t,r,n,o,a){let s=at(n),i=r.npts,c=0;for(let l=0;l<s.seamIters;l++){let u=0;c++;for(let m=0;m<i;m++){let f=(m+1)%i;u=Math.max(u,TD(zn(e,o,m),t[f],t[m],r.curvature[m],r.ds[m],cn(r,m),ui(r,m),Hn(r,m),a?a[m]:1))}if(u<=s.vTol)break}return c}function PD(e,t,r){let n=r.load?li(t):null;if(!n||!r.load)return{pick:r.envelope};let o=t.npts;return{pick:sk(n,r.load,e,r.envelope),cap:a=>nk(n,a%o),n:(a,s)=>yu(n,a,s)}}function lk(e,t,r,n,o,a,s){return xu(n,r.ds,o,a,(i,c,l)=>{let u=c*c*r.curvature[i];return zn(e,t,i).axAccel(c,Math.abs(Ye(u,Hn(r,i))),cn(r,i),s?l*s[i]:l)+ui(r,i)})}function uk(e,t){return{gear:e.gear.slice(0,t),engineRpm:e.rpm.slice(0,t),shifting:e.shifting.slice(0,t)}}function mk(e,t,r,n){if(!e.scrub)return{};let o=!1,a=n.map((s,i)=>{let c=zn(e,t,i),l=Ye(s*s*r.curvature[i],Hn(r,i)),u=c.scrub?c.scrub(s,Math.abs(l),cn(r,i)):0;return u!==0&&(o=!0),u});return o?{axScrub:a}:{}}function gt(e,t,r,n={}){let o=at(r),a=t.npts,s=t.closed&&!n.standingStart,{pick:i,cap:c,n:l}=PD(e,t,n),u=n.driveDerate,m=n.brakeFade;if(!s)return LD(e,t,o,n.standingStart===!0,i,u,n.vCeiling,m,c,l,n.shifts);let f=ha(e,t.curvature,o,t,i,n.vCeiling,c),p=ik(e,f,t,o,i,m),d=ck(e,f,t,o,i,u),h=n.shifts?lk(e,i,t,f.map(M=>M.v),!0,n.shifts,u):void 0;if(h)for(let M=0;M<a;M++)f[M].v=h.v[M];for(let M=0;M<a;M++){let v=f[M];v.ay=v.v*v.v*t.curvature[M];let x=f[(M+1)%a].v;v.ax=(x*x-v.v*v.v)/(2*t.ds[M])}let b=f.map(M=>M.v),g=f.map(M=>M.ax),y=f.map(M=>M.ay),R=0;for(let M=0;M<a;M++){let v=b[M]+b[(M+1)%a];v>0&&(R+=2*t.ds[M]/v)}return{states:f,v:b,ax:g,ay:y,laptime:R,sweeps:{backward:p,forward:d},...l?{loadFactor:b.map((M,v)=>l(v,M))}:{},...mk(e,i,t,b),...h?uk(h,a):{}}}function LD(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=ha(e,d,r,t,o,s,c);n&&(h[0].v=0);for(let R=f-1;R>=0;R--){let M=h[R],v=h[R+1];if(M.v<=v.v)continue;let x=zn(e,o,R),k=w=>{let C=Ye(w*w*t.curvature[R],Hn(t,R)),T=(i?x.axDecel(w,Math.abs(C),cn(t,R),i(R,w)):x.axDecel(w,Math.abs(C),cn(t,R)))+ui(t,R);return Math.sqrt(Math.max(0,w*w+2*T*t.ds[R]))},F=n&&R===0?M.v:Gh;M.v=zh(w=>k(w)-v.v,F,M.v,r.scanSteps,r.vTol)}for(let R=0;R<f;R++){let M=h[R],v=h[R+1];M.ay=M.v*M.v*t.curvature[R];let x=Ye(M.ay,Hn(t,R));M.ax=zn(e,o,R).axAccel(M.v,Math.abs(x),cn(t,R),a?a[R]:1)+ui(t,R),v.v=Math.min(v.v,Math.sqrt(Math.max(0,M.v*M.v+2*M.ax*t.ds[R])))}let b=u?lk(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 M=h[R].v+h[R+1].v;M>0&&(g+=2*t.ds[R]/M)}let y=h.slice(0,m);for(let R=0;R<m;R++){let M=y[R];M.ay=M.v*M.v*t.curvature[R];let v=R<f?h[R+1].v:M.v;M.ax=t.ds[R]>0?(v*v-M.v*M.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,M)=>l(M,R.v))}:{},...mk(e,o,t,y.map(R=>R.v)),...b?uk(b,m):{}}}var pk=(e,t)=>{let r=e[t]?.value;return Number.isFinite(r)&&r>0?r:0};function Yn(e,t,r){let n=e.m.value,o=e.r_dyn?.value??0,a=pk(e,"I_wheel"),s=e.motorModel?.kind==="ice"?0:pk(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 Wn(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 mi=36e5,bk=Math.PI*2,Yh=e=>Math.max(0,Math.min(1,e));function Wh(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=vc(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/bk),l=Math.max(0,i*o/(n*a)),u=r.efficiency(c,l);return u>.01?u:.5}}var dk=new WeakMap;function ba(e){if(e.batteryModel)return e.batteryModel;let t=e.capacity.value,r=e.ocv.value,n=dk.get(e);if(n&&n.capacityAh===t&&n.ocv===r)return n.model;let o=Mp(t,r);return dk.set(e,{capacityAh:t,ocv:r,model:o}),o}function jh(e){let t=e.params,r=Wf(t,El(e));if(mt(t.motorModel)||lt(t).mode!=="hydraulic")return r;let n;return(o,a,s,i=0)=>{if(!(o>0))return 0;n??=DD(e);let c=$l(n.inp,n.ev,o,a,i);return c?Math.min(o,c.regenFront+c.regenRear):r(o,a,s)}}var fk=new WeakMap;function DD(e){let t=e.params,r=fk.get(t);if(!r){let n=wr(t);r={inp:ut(n.regen?t:{...t,energy:{...n,regen:!0}}),ev:sr(t)},fk.set(t,r)}return r}var pi=e=>e.airTempC??St;function Ru(e,t){return e.thermal?e.thermal.startC??t:Mo}function hk(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 gk=()=>({windingC:[],derate:[],lossW:[],torqueNm:[],ampsRms:[]});function ED(e){let t=e.motorModel;if(!t?.thermal)return;let r=Sp(t.thermal),n=vc(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/bk),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 ID(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 _D(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 ND(e){let{drivenFront:t,drivenRear:r}=Wn(e);return Yn(e.params,t,r)}function ga(e,t,r,n,o=Fr,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?ut(m):void 0,g=Wh(m),y=fr(ba(m)),R=y.chargeC,M=Yh(a??m.soc.value),v=pi(m),x=s??Ru(y,v),k=x,F=0,w=0,C=0,T=0,S=-1,A=-1,P=-1,L=ED(m),D=L?L.th.startC:0,I=D,G=0,O=1,W=-1,E=0,_=0,V=jh(e),N=m.motorModel?.kind==="ice",$=u?.scrub,K=$?d/ND(e).tractionFactor:0,z=Math.min(t.length,r.length);for(let j=0;j<z;j++){let Q=r[j],ne=Q*Q,te=n[j]-(c?.[j]??0),{cl:fe,cw:Y,A:J}=bu(m,Q,te/9.81,b),re=.5*f*fe*J*ne,pe=.5*f*Y*J*ne,de=(h+re)*-p,ie=$?-K*($[j]??0):0,oe=de+pe+ie+d*te,ue=oe*t[j],Ve=j+1<r.length?r[j+1]:Q,Ae=.5*(Q+Ve),le=Ae>0?t[j]/Ae:0,Re=0,we=M,Ge=x,We=0,be=0,Fe=le;if(N){oe>0&&(be=ue/g(Q,oe),F+=be/mi),l?.netKwh.push(F-w),l?.powerKw?.push(le>0?be/le/1e3:0);continue}if(oe>0){let ye=ue/g(Q,oe),me=ID(y,ye,le,M,x);me.short&&S<0&&(S=j),me.cutoff&&A<0&&(A=j);let Te=M*R,Se=Math.min(me.dq,Te),Ke=me.dq>0?Se/me.dq:1;Se>=Te&&P<0&&(P=j),F+=me.energyJ*Ke/mi,be=me.energyJ*Ke,Fe=me.seconds,C+=me.lossJ*Ke,T+=Se,le>0&&(We=Se/me.seconds),M=Yh(M-Se/R),x=hk(y,x,me.dq>0&&le>0?Se/le:0,me.lossJ*Ke,le,v),x>k&&(k=x),Re=oe}else if(o.regen){let ye=u?Ye(u.ay[j],u.bank?.[j]??0)/9.81:0,me=V(-oe,Q,te/9.81,ye),Te=o.regenEfficiency*me*t[j],Se=_D(y,Te,le,M,x),Ke=(1-M)*R,je=Math.min(Se.dq,Ke),Gt=Se.dq>0?je/Se.dq:1;w+=Se.energyJ*Gt/mi,be=-Se.energyJ*Gt,C+=Se.lossJ*Gt,T-=je,le>0&&(We=-je/le),M=Yh(M+je/R),x=hk(y,x,je>0&&le>0?-je/le:0,Se.lossJ*Gt,le,v),x>k&&(k=x),Re=-me*Gt}if(l?.netKwh.push(F-w),l?.powerKw?.push(le>0?be/Fe/1e3:0),l?.pack){let ye=l.pack;ye.soc.push(we),ye.amps.push(We),ye.volts.push(y.ocv(we)-We*y.resistance(we,Ge)),ye.cellC.push(Ge)}if(L){let ye=L.rpm(Q),me=L.th.derate(ye,D,L.peak(ye));me<O&&(O=me),me<1&&W<0&&(W=j),_+=le,me<1&&(E+=le);let Te=L.torque(Re,ye,me),Se=L.th.lossW(ye,Te,D);G+=Se*le,i&&(i.windingC.push(D),i.derate.push(me),i.lossW.push(Se),i.torqueNm.push(Te),i.ampsRms.push(L.amps(Te))),D=L.th.step(D,Se,le),D>I&&(I=D)}}return{drive:F,regen:w,net:F-w,chargeAh:T/3600,loss:C/mi,socEnd:M,shortAt:S,cutoffAt:A,emptyAt:P,tempEndC:x,tempMaxC:k,...L?{motorTempEndC:D,motorTempMaxC:I,motorLossKwh:G/mi,motorDerateMin:O,motorDerateAt:W,motorDerateTimeFrac:_>0?E/_:0}:{}}}var OD=.5,VD=.02,BD=6;function yk(e,t,r,n,o,a,s,i){let c=n(),l=1,u=d=>{let h=gk(),b=ga(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<BD;d++){let h=n(f);l++;let b=Math.abs(h.laptime-c.laptime);if(c=h,m=u(c),b<VD){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]+OD*((g[R]??1)-f[R]);f=y}return{lap:c,derate:f,solves:l,converged:p,peakWindingC:m.peak,derateTimeFrac:m.frac}}var $D=.1;function xk(e){let t=e.power_limit_kw?.value??0;return t>0?t*1e3:0}function Uh(e,t,r){return e.motorModel?.kind==="ice"?1/0:fr(ba(e)).maxPower(t??e.soc.value,r,xk(e)).watts}function vu(e,t,r,n){let o=Uh(e,r,n);if(!Number.isFinite(o))return 1/0;if(o<=0)return 0;let a=Math.max($D,t),s=Wh(e),i=o*(e.effi_pgb?.value??.9)/a;return o*s(t,i)/a}var GD=180/Math.PI;function ku(e,t,r,n){let o=e*t,a=e*(1-t);return o/r-a/n}var Mu=e=>e*9.81*GD;var M9=Math.PI/180;function Su(e,t,r,n=0){let o=Le(e,t,0,n),a=typeof r=="function"?r:r.front,s=typeof r=="function"?r:r.rear,i=.5*(a(Math.max(0,o.FL))+a(Math.max(0,o.FR))),c=.5*(s(Math.max(0,o.RL))+s(Math.max(0,o.RR))),l=i>0&&c>0?ku(e.massTotal,e.frontMassFrac,2*i,2*c):0,u=Mu(l),m=u>.15?"understeer":u<-.15?"oversteer":"neutral";return{gradient:u,balance:m,cAlphaFront:i,cAlphaRear:c}}var L9=Math.PI/180,D9=180/Math.PI;var Rk=2220446049250313e-31;function zD(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 YD(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 WD(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])<=Rk*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 M=Math.abs(e[f][f-1])*(Math.abs(d)+Math.abs(h)),v=Math.abs(p)*(Math.abs(e[f-1][f-1])+Math.abs(b)+Math.abs(e[f+1][f+1]));if(M<=Rk*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 M=a<b+3?a:b+3;for(let v=c;v<=M;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 vk(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 zD(r),YD(r),WD(r)}function kk(e){let t=[],r=new Array(e.length).fill(!1),n=vk(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 Xh(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 jD(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 Xh(r,n)}function Au(e,t=r=>jD(e,r)){return kk(e).map(r=>({...r,vector:t(r.eigenvalue)}))}function ya(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 Mk(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 ya(Au(i),c,0)}function Sk(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=Mk({sprungMass:o,unsprungMass:e.unsprungCornerMass??e.unsprungPerCorner,springRate:s,damperRate:n,tireRate:Ue(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 Fu(e,t,r){let n=Ce(e);return{front:Sk(e,n,"front",t??n.rideDampingFront),rear:Sk(e,n,"rear",r??n.rideDampingRear)}}var Y9=180/Math.PI;var qh=["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},xa=20,Ak=[ce.zFL,ce.zFR,ce.zRL,ce.zRR],Fk=[ce.vzFL,ce.vzFR,ce.vzRL,ce.vzRR],Or={fzFL:0,fzFR:1,fzRL:2,fzRR:3,fzBody:4,myBody:5,mxBody:6,fx:7,fy:8,mz:9},Qh=10;function wu(e){let t=Array.from({length:xa},()=>new Array(xa).fill(0)),r=Array.from({length:xa},()=>new Array(Qh).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[Ak[i]]-=c,s[Fk[i]]-=l,s[ce.zBody]+=c,s[ce.vzBody]+=l,s[ce.pitch]-=c*e.leverX[i],s[ce.pitchRate]-=l*e.leverX[i],s[ce.roll]+=c*e.leverY[i],s[ce.rollRate]+=l*e.leverY[i]};for(let s=0;s<4;s++){let i=s<2,c=k=>k?i?k.front:k.rear:0,l=e.springRate[s]+c(e.heaveSpring),u=e.springRate[s]+c(e.arb),m=e.damperRate[s]+c(e.heaveDamper),f=e.damperRate[s]+c(e.rollDamper),p=(l+u)/2,d=(l-u)/2,h=(m+f)/2,b=(m-f)/2,g=new Array(xa).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],M=e.leverY[s],v=Ak[s],x=Fk[s];for(let k=0;k<xa;k++){let F=g[k];F!==0&&(t[x][k]+=F/y,t[ce.vzBody][k]-=F/e.bodyMass,t[ce.pitchRate][k]+=R*F/n.yy,t[ce.rollRate][k]-=M*F/n.xx)}t[x][v]-=e.tyreRate[s]/y,t[x][x]-=e.tyreDamping[s]/y,r[x][Or.fzFL+s]=1/y}return r[ce.vzBody][Or.fzBody]=1/e.bodyMass,r[ce.pitchRate][Or.myBody]=1/n.yy,r[ce.rollRate][Or.mxBody]=1/n.xx,r[ce.vx][Or.fx]=1/e.totalMass,r[ce.vy][Or.fy]=1/e.totalMass,r[ce.yawRate][Or.mz]=1/n.zz,{A:t,B:r,params:e}}function Zh(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=Ue(e,"front")*1e3,p=Ue(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 wk=ce.rollRate+1;function Ck(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,wk).map(i=>i.slice(0,wk));if(!n.every(i=>i.every(Number.isFinite)))return{};let a=Au(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 Xh(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:ya(a,s,1),pitch:ya(a,s,2),roll:ya(a,s,3)}}function Tk(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 Cu(e){let t=Ce(e),r=e.wheelbase/1e3,n=r*(1-e.frontMassFrac),o=r*e.frontMassFrac,a=t.rollRateTotal*(180/Math.PI),s=e.rollInertia??t.sprungMass*.6*.6,i=2*t.rideRateFront*1e3,c=2*t.rideRateRear*1e3,l=i*n*n+c*o*o,u=e.pitchInertia??t.sprungMass*1.2*1.2,m=Ck(wu(Zh(e)));return{roll:Tk(m.roll,a,s),pitch:Tk(m.pitch,l,u)}}var Tu=9.81,Vr=Math.PI/180;function Pk(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 Ra(e,t,r,n,o){let{wb:a,lf:s,lr:i,m:c}=Pk(e),l=0;for(let R=0;R<16;R++){let M=l/r,v=o-n-s*M/r,x=-n+i*M/r,k=Le(e,l/Tu,0,r),F=Math.max(0,k.FL+k.FR),w=Math.max(0,k.RL+k.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=Le(e,l/Tu,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/Tu,cn:y/(c*Tu*a)}}function Jh(e,t,r,n={}){let o=Math.max(8,r),a=(n.betaMaxDeg??10)*Vr,s=(n.deltaMaxDeg??10)*Vr,i=n.nLines??9,c=n.nPts??21,l=(g,y,R,M)=>R===1?g:g+(y-g)*M/(R-1),u=[],m={ay:[],cn:[]},f=0;for(let g=0;g<i;g++){let y=l(-s,s,i,g),R=[],M=[],v=[],x=[];for(let k=0;k<c;k++){let F=l(-a,a,c,k),w=Ra(e,t,o,F,y);R.push(w.ay),M.push(w.cn),v.push(F/Vr),x.push(y/Vr),Math.abs(w.ay)>f&&(f=Math.abs(w.ay))}u.push({label:`\u03B4 ${(y/Vr).toFixed(0)}\xB0`,ay:R,cn:M,betaDeg:v,deltaDeg:x});for(let k=1;k<M.length;k++)if(M[k-1]===0||M[k-1]<0!=M[k]<0){let F=M[k-1]===M[k]?0:M[k-1]/(M[k-1]-M[k]);m.ay.push(R[k-1]+F*(R[k]-R[k-1])),m.cn.push(0);break}}let p=[];for(let g=0;g<i;g++){let y=l(-a,a,i,g),R=[],M=[],v=[],x=[];for(let k=0;k<c;k++){let F=l(-s,s,c,k),w=Ra(e,t,o,y,F);R.push(w.ay),M.push(w.cn),v.push(y/Vr),x.push(F/Vr)}p.push({label:`\u03B2 ${(y/Vr).toFixed(0)}\xB0`,ay:R,cn:M,betaDeg:v,deltaDeg:x})}let d=.5*Vr,h=(Ra(e,t,o,d,0).cn-Ra(e,t,o,-d,0).cn)/(2*d),b=(Ra(e,t,o,0,d).cn-Ra(e,t,o,0,-d).cn)/(2*d);return{isoBeta:p,isoDelta:u,trim:m,maxAy:f,stability:h,control:b,speed:o}}function UD(e){return!e.corneringStiffnessFront||!e.corneringStiffnessRear?null:{Cf:2*e.corneringStiffnessFront,Cr:2*e.corneringStiffnessRear}}function di(e,t){let r=UD(e);if(!r)return null;let{Cf:n,Cr:o}=r,{wb:a,lf:s,lr:i,m:c}=Pk(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,M;if(g<0)y=h/2,R=Math.sqrt(Math.max(0,b)),M=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)),M=R>0?-h/(2*R):1}let v=h<0&&b>0,x=ku(c,e.frontMassFrac,n,o),k=Mu(x),F=k>.15?"understeer":k<-.15?"oversteer":"neutral",w=s*n-i*o,C=P=>P*3.6,T=null,S=null;w>1e-6?S=C(Math.sqrt(n*o*a*a/(c*w))):w<-1e-6&&(T=C(Math.sqrt(n*o*a*a/(c*-w))));let A=u/(a+x*u*u);return{stable:v,yawFreq:R/(2*Math.PI),dampingRatio:M,eigReal:y,understeerGradient:k,balance:F,characteristicSpeed:T,criticalSpeed:S,yawRateGain:A}}var Lk=Math.PI/180;function Ik(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 Dk(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 _k(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 Nk(e,t,r){let n=e.isoDelta[0],o=(n.betaDeg[1]-n.betaDeg[0])*Lk||1,a=e.isoDelta.length>1?(e.isoDelta[1].deltaDeg[0]-e.isoDelta[0].deltaDeg[0])*Lk:1,s=x=>_k(e,t,r,x),i=s((x,k)=>x.ay[k]),c=s((x,k)=>x.cn[k]),l=s((x,k)=>x.betaDeg[k]),u=s((x,k)=>x.deltaDeg[k]),m=s((x,k)=>Dk(x.cn,k,o)),f=s((x,k,F)=>Dk(e.isoDelta.map(w=>w.cn[k]),F,a||1)),p=Math.max(1e-6,e.maxAy),d=Math.abs(i)/p,h=Math.max(1e-6,...e.isoDelta.flatMap(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(`${Ik(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 M=Math.abs(e.control),v=M>1e-9?Math.abs(f)/M:1;return v<.15?y.push("The steering has stopped working here: another degree of lock buys almost no yaw moment, which is what a saturated front axle looks like. This is understeer in its literal sense \u2014 the front tyres are already at their limit."):v<.5&&y.push(`Steering response is down to about ${(100*v).toFixed(0)} % of its straight-ahead value \u2014 the front is well into the non-linear part of its curve.`),d>.97?y.push(`At the edge of the diagram: ${Math.abs(i).toFixed(2)} g is essentially all this car has at this speed.`):d<.25&&y.push("Well inside the limit \u2014 this is the linear region the handling balance is measured in."),{ay:i,cn:c,betaDeg:l,deltaDeg:u,stability:m,control:f,gripUsed:d,notes:y}}var Ek=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+Ek)?!0:p<d*(1-Ek)?!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=Nk(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 XD=["tv_kp"];function Ok(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"},...XD.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 qD=Ok(0);function Vk(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 QD=Vk(0);var ZD=9.81;function JD(e){let t=e.wheelbase/1e3;return{lf:t*(1-e.frontMassFrac),lr:t*e.frontMassFrac}}function fi(e,t,r,n){let o=t.tire;if(!o)return null;let s=(r==="limit"?vh(e,o,t.speed):an(e,o,t.speed,t.ayG)).wheels;return xr(n??Nn(o,e.massTotal*ZD*1.2),{FL:s.FL,FR:s.FR,RL:s.RL,RR:s.RR},JD(e))}function eE(e){if(!e.tire)return e.cornerStiffness;let t=xe(e.tire,"front"),r=xe(e.tire,"rear");return{front:n=>t.corneringStiffness(n),rear:n=>r.corneringStiffness(n)}}var Bk=[{key:"understeer",label:"Understeer gradient",unit:"\xB0/g",compute:(e,t)=>Su(e,t.ayG,eE(t),t.speed).gradient},{key:"rollGradient",label:"Roll gradient",unit:"\xB0/g",compute:e=>Ce(e).rollGradient},{key:"pitchGradient",label:"Pitch gradient",unit:"\xB0/g",compute:e=>Ce(e).pitchGradient},{key:"tlltdFront",label:"TLLTD front",unit:"%",compute:e=>100*Id(e)},{key:"rollStiffFront",label:"Front roll-stiffness",unit:"%",compute:e=>100*Ce(e).frontRollStiffFrac},{key:"rideFreqFront",label:"Ride freq front",unit:"Hz",compute:e=>Ce(e).rideFreqFront},{key:"rideFreqRear",label:"Ride freq rear",unit:"Hz",compute:e=>Ce(e).rideFreqRear},{key:"rollFreq",label:"Roll-mode freq",unit:"Hz",compute:e=>Cu(e).roll.freq},{key:"pitchFreq",label:"Pitch-mode freq",unit:"Hz",compute:e=>Cu(e).pitch.freq},{key:"zetaFront",label:"Damping \u03B6 front",unit:"-",compute:e=>Fu(e).front.dampingRatio},{key:"zetaRear",label:"Damping \u03B6 rear",unit:"-",compute:e=>Fu(e).rear.dampingRatio},{key:"yawFreq",label:"Yaw natural freq",unit:"Hz",compute:(e,t)=>di(e,t.speed)?.yawFreq??NaN},{key:"yawZeta",label:"Yaw damping \u03B6",unit:"-",compute:(e,t)=>di(e,t.speed)?.dampingRatio??NaN},{key:"stabilitySpeed",label:"Char./critical speed",unit:"km/h",compute:(e,t)=>{let r=di(e,t.speed);return r?r.criticalSpeed??r.characteristicSpeed??NaN:NaN}},{key:"maxAy",label:"Max lateral accel",unit:"g",compute:(e,t)=>t.fyAxle?Jh(e,t.fyAxle,t.speed,{betaMaxDeg:12,deltaMaxDeg:12}).maxAy:NaN},{key:"yawReserveRear",label:"Yaw stability reserve",unit:"N\xB7m",compute:(e,t)=>fi(e,t,"operating")?.stabil??NaN},{key:"yawReserveFront",label:"Yaw agility reserve",unit:"N\xB7m",compute:(e,t)=>fi(e,t,"operating")?.agil??NaN},{key:"limitBalance",label:"Limit balance (+US / \u2212OS)",unit:"-",compute:(e,t)=>fi(e,t,"limit")?.rel??NaN},{key:"yawStiffness",label:"Yaw stiffness N_\u03B2",unit:"N\xB7m/rad",compute:(e,t)=>t.tire?Rh(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorque",label:"Steering holding torque",unit:"N\xB7m",compute:(e,t)=>t.tire?yh(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorqueGradient",label:"Steering feedback gradient",unit:"N\xB7m/g",compute:(e,t)=>t.tire?xh(e,t.tire,t.speed,t.ayG):NaN}],tb=Object.fromEntries(Bk.map(e=>[e.key,e]));var Br=9.81;function tE(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 rE={front:!1,rear:!0};function va(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 $k(e,t,r,n,o,a){let s=e[t]+e[r];if(!(s>0))return;let i=va(n,o[t],a[t]),c=va(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 Gk(e,t,r,n,o,a={},s="open"){if(!e.rear)return 1;if(!e.front)return 0;let i=(f,p,d)=>d?Ns(f,p,d):s==="own"?f+p:2*Math.min(f,p),c=i(va(n,t.FL,r.FL),va(n,t.FR,r.FR),a.front),l=i(va(o,t.RL,r.RL),va(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 rb(e,t,r,n){return{car:t?zk(t,r.loadFactor[n]):e,ayTyre:Ye(r.ay[n],r.bank?.[n]??0),axCar:r.ax[n]-(r.axGrade?.[n]??0)}}function Kk(e,t){if(!e.aero?.model)return 0;let r=Math.min(t.v.length,t.ax.length,t.ay.length),n=t.loadFactor?Lu(e):void 0,o=0,a=0;for(let s=0;s<r;s++){let i=t.ds?.[s]??1,c=rb(e,n,t,s);o+=i,Ed(c.car,t.v[s],c.axCar/Br,c.ayTyre/Br)&&(a+=i)}return o>0?a/o:0}function Hk(e,t,r){let n=Ht(xe(t,"front")),o=Ht(xe(t,"rear")),a=Math.min(r.v.length,r.ax.length,r.ay.length),s=r.loadFactor?Lu(e):void 0,i=0,c=0;for(let l=0;l<a;l++){let u=r.ds?.[l]??1,m=rb(e,s,r,l);i+=u;let f=Le(m.car,m.ayTyre/Br,m.axCar/Br,r.v[l]);(f.FL>n||f.FR>n||f.RL>o||f.RR>o)&&(c+=u)}return i>0?c/i:0}function Pu(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=Hs(t,e.massTotal*Br*1.2),l=Xo(c,"front"),u=Xo(c,"rear"),m=ct(xe(t,"front")),f=ct(xe(t,"rear")),p=n.perWheel?Vd(m,l):null,d=n.perWheel?f===m?p:Vd(f,u):null,h=n.driven??rE,b={front:Vt(e,"front",1),rear:Vt(e,"rear",1)},g={front:0,rear:0},y=new Array(o),R=new Array(o),M=new Array(o),v=1/0,x=0,k=0,F=Ht(m),w=Ht(f),C=0,T=0,S=0,A=0,P=0,L=0,D=["FL","FR","RL","RR"],I=n.perWheel?Object.fromEntries(D.map(O=>[O,{Fz:new Array(o),alpha:new Array(o),Fy:new Array(o),Fx:new Array(o),Mz:new Array(o),used:new Array(o),FxCap:new Array(o),FyCap:new Array(o)}])):void 0,G=r.loadFactor?Lu(e):void 0;for(let O=0;O<o;O++){let W=rb(e,G,r,O),{ayTyre:E,axCar:_}=W,V=E/Br,N=Le(W.car,V,_/Br,r.v[O]),$=e.massTotal*E,K=$*i/a,z=$*s/a,j=gs(m,K,N.FL,N.FR,P),Q=gs(f,z,N.RL,N.RR,L);P=j,L=Q;let ne={FL:Math.abs(m.Fy(j,N.FL,0)),FR:Math.abs(m.Fy(j,N.FR,0)),RL:Math.abs(f.Fy(Q,N.RL,0)),RR:Math.abs(f.Fy(Q,N.RR,0))},te=(_-(r.axDrag?.[O]??0)-(r.axScrub?.[O]??0))/Br,fe=te>0&&h.front?Gk(h,N,ne,l,u,b,"own"):0,Y=r.v[O]*r.v[O],J=e.driveline?{Fz:N,alpha:{front:j,rear:Q},curvature:Y>1?r.ay[O]/Y:0,seed:g}:void 0,re={...fh(e,te,r.v[O],t,V,fe,J)};te>0&&(b.front||$k(re,"FL","FR",l,N,ne),b.rear||$k(re,"RL","RR",u,N,ne));let pe=!1,de=!1;for(let ue of["FL","FR","RL","RR"]){let Ve=(ue==="FL"||ue==="FR"?l:u).muX(N[ue])*N[ue];Math.abs(re[ue])>Ve&&(pe=!0),N[ue]>(ue==="FL"||ue==="FR"?F:w)&&(de=!0)}de&&(k+=r.ds?.[O]??1);let ie=xr(c,{FL:{Fz:N.FL,Fy:ne.FL,Fx:re.FL},FR:{Fz:N.FR,Fy:ne.FR,Fx:re.FR},RL:{Fz:N.RL,Fy:ne.RL,Fx:re.RL},RR:{Fz:N.RR,Fy:ne.RR,Fx:re.RR}},{lf:s,lr:i});if(y[O]=ie.stabil,R[O]=ie.agil,M[O]=ie.rel,I){let ue=.5*(N.FL+N.FR),Ve=.5*(N.RL+N.RR),Ae=l.muX(ue)*ue,le=u.muX(Ve)*Ve;for(let Re of D){let we=N[Re],Ge=Re==="FL"||Re==="FR",We=Ge?l:u,be=We.muY(we)*we,Fe=We.muX(we)*we,ye=I[Re],me=Ge?j:Q;ye.Fz[O]=we,ye.alpha[O]=me,ye.Fy[O]=ne[Re],ye.Fx[O]=re[Re],ye.Mz[O]=we>0?(Ge?m:f).Mz(me,we,0):0,ye.FxCap[O]=Fe,ye.FyCap[O]=be;let Te=be>0?Math.min(1,Math.abs(ne[Re])/be):0,Se=tE(re[Re],Fe,Ge?Ae:le),Ke=Ge?p:d,je=Ke&&we>0?Ke.reach(we,Math.sign(re[Re])*Se,Te):1;ye.used[O]=Math.hypot(Te,Se)/je}}ie.stabil<v&&(v=ie.stabil,x=O);let oe=r.ds?.[O]??1;A+=oe,ie.diff>0&&(C+=oe),pe&&(T+=oe),Ed(W.car,r.v[O],_/Br,V)&&(S+=oe)}return{stabil:y,agil:R,rel:M,minStabil:Number.isFinite(v)?v:0,minStabilAt:x,pastTurnoverFrac:A>0?k/A:0,understeerFrac:A>0?C/A:0,beyondFrac:A>0?T/A:0,aeroOutsideFrac:A>0?S/A:0,wheels:I}}function Lu(e){return Object.create(e,{loadFactor:{value:1,writable:!0,enumerable:!0}})}function zk(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=Tr(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=Ye(r.ay[l],r.bank?.[l]??0)/nb,h=Math.min(.99,Math.max(.01,oa(e,f/nb,u,t,d)));c.front[l]=p*h,c.rear[l]=p*(1-h);let b=i?$l(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 t7=Math.PI/180;var r7=qh.map(zs);var n7=[ce.zFL,ce.zFR,ce.zRL,ce.zRR];var o7=Array.from({length:ce.rollRate+1},(e,t)=>t);var hE=9.81,bE=.001,gE=.6,yE=2,Uk=4;function Xk(e,t,r,n=Uk){let o=Math.min(e.v.length,t.npts),{ds:a,closed:s}=t,i=r.massTotal*hE*r.wheelbase,c=xE(e.ay.slice(0,o).map((m,f)=>m/Math.max(bE,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 xE(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 qk(e,t,r,n,o={}){let a=o.maxIter??20,s=o.tol??.001,i=Math.min(1,Math.max(.001,o.relax??gE)),c=o.smoothM??Uk,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=gt(e.steady,t,n,l),m=[u.laptime],f=new Array(t.npts).fill(0),p=f.slice(),d=u,h=0,b=!1,g=0;for(let M=0;M<a;M++){h=M+1;let v=Xk(d,t,r,c);f=v.demand.map((F,w)=>f[w]+i*(F-f[w])),p=v.rdot;let x=gt(e.steady,t,n,{...l,envelope:F=>e.at(f[F]??0)});m.push(x.laptime);let k=Math.abs(x.laptime-d.laptime);if(d=x,g=k<=s?g+1:0,g>=yE){b=!0;break}}let y=0,R=0;for(let M=0;M<t.npts;M++)R+=t.ds[M],e.clamps(f[M]??0)&&(y+=t.ds[M]);return{...d,steady:u,demand:f,rdot:p,history:m,iterations:h,converged:b,clampedFrac:R>0?y/R:0}}var d7=Math.PI/180;var Y7=180/Math.PI;function ka(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 Zk(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=>ka(p.vs,h,d)),axDecelN:p.decel.map(h=>ka(p.vs,h,d)),axScrubN:p.scrub.map(h=>ka(p.vs,h,d))});if(!o){let p=a(e);return d=>({ayMax:ka(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/ka(i.vs,i.radius,p),f=p=>p>=u||c.vs.length<2?ka(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 NE(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 Jk(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=Zk(s,t),c=[],l=a,u=(f,p)=>{let d=.5*(f+p),h=e(d);l++;let b=NE(i(d),h);s.splice(s.findIndex(g=>g.v>d),0,h),i=Zk(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 OE=2,VE=.5,hi=Math.PI/180,eM=21,BE={nCoarse:11,nSteer:13,nNorm:41,nAngle:45},$E={nCoarse:11,nSteer:13,nNorm:41,nAngle:61},GE=.005,KE=.05,ab=e=>e<0?0:e>1?1:e;function HE(e,t,r,n){let o=e.massTotal,a=n.nSteer??7,s=(n.drivenFront?2:0)+(n.drivenRear?2:0),i=Le(e,0,0,r),c=Math.max(1,(i.FL+i.FR+i.RL+i.RR)/4),l=8*hi,u=0,m=(b,g,y)=>{for(let R=b;R<=g;R+=y){let M=Math.abs(t.Fy(R*hi,c,0));M>u&&(u=M,l=R*hi)}};m(1,45,1),m(Math.max(.1,l/hi-1),l/hi+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*Mt(t,c,R,!1)/o),d.push(4*Mt(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 ir(e,t=!1,r="twoTrack",n,o,a=0,s=1){if(a!==0&&r==="fast")throw new Error('the fast (point-mass) envelope has no yaw balance to shift; use mode "twoTrack" for a yaw-inertia demand');let i=n??(t?$E:BE),{nCoarse:c,nSteer:l,nAngle:u}=i,m=Cr(0,1,i.nNorm).map(V=>Math.sin(Math.PI/2*V)),f=e.params,p=f.m.value,d=f.rho.value,h=f.fr_0.value,b=f.driven_wheels.value,g=f.power_scale.value,y=e.FG,R=ut(f);s!==1&&(R.loadFactor=s);let M=sr(f),v=uv(0,n?.vRes??(e.engine?VE:OE),e.vMax);v[v.length-1]<e.vMax&&v.push(e.vMax);let x=e.fRad.map(V=>V*b),k=e.fAxle,{drivenFront:F,drivenRear:w}=Wn(e),C=Yn(f,F,w),T=(V,N)=>{let $=k?At(k.vVehicle,V,N):NaN;return Number.isFinite($)?$:1/0},S=V=>{let N=V*V,{cl:$,cw:K,A:z}=bu(f,V,0,R),j=.5*d*-K*z*N,Q=.5*d*-$*z*N,ne=h*(-Q+y);return j+ne},A=V=>{let N=S(V)/p*C.powerFactor,$=S(V)/p*C.tractionFactor,K;if(e.engine){let j=S(V);K=ta(e.engine,V,C.effective,j,g).accel-N}else if(k){let j=0;F&&(j+=T(k.fFront,V)),w&&(j+=T(k.fRear,V)),K=g*j/p*C.powerFactor}else{let j=At(e.vVehicle,x,V),Q=g*j/p*C.powerFactor;K=Number.isFinite(Q)?Q:1/0}let z=vu(f,V,o)/p*C.powerFactor;return{axDrag:N,axDragTyre:$,axDrive:K,axPackCap:z,axPower:Math.min(K,z)}},P=v.map(A),L=e.vMax;for(let V=1;V<v.length;V++){let N=P[V].axDrive+P[V].axDrag;if(N>0)continue;let $=P[V-1].axDrive+P[V-1].axDrag;L=$>0?v[V-1]+(v[V]-v[V-1])*$/($-N):v[V-1];break}let D=Math.min(e.vMax,(1+KE)*L),I=r==="fast"?HE:Mh,G=V=>{let N=I(R,M,V,{drivenFront:F,drivenRear:w,nSteer:l,yawDemandCn:a,axDrag:S(V)/p,...f.diffYaw?{diffYaw:!0}:{}}),$=N.ay[0],K=N.ay[N.ay.length-1],z=te=>Math.min(Math.max(te*N.ayMax,$),K),j=m.map(te=>Ll(N.ay,N.axAccel,z(te))*C.tractionFactor),Q=m.map(te=>Ll(N.ay,N.axDecel,z(te))),ne=m.map(te=>Ll(N.ay,N.axScrub,z(te))*C.tractionFactor);return{v:V,ayMax:N.ayMax,axAccelN:j,axDecelN:Q,axScrubN:ne,atLock:N.atLock===!0}},O=r==="fast"?0:Math.min(jl,D),W=Jk(G,O,D,c,i.anchorTol??GE),E=[],_=[];for(let V=0;V<v.length;V++){let N=v[V],{axDrag:$,axDragTyre:K,axDrive:z,axPackCap:j,axPower:Q}=P[V],{ayMax:ne,axAccelN:te,axDecelN:fe,axScrubN:Y}=W.at(N);E.push({v:N,ayMax:ne,axTyreAcc:te[0],axTyreDec:fe[0],axDrive:z,axPackCap:j,axPower:Q,axDrag:$,axDragTyre:K,axAccelN:te,axDecelN:fe,axScrubN:Y});let J=[],re=[];for(let de=0;de<u;de++){let ie=Math.PI*de/(u-1),oe=ne*Math.cos(ie),ue=ab(Math.abs(Math.cos(ie)));J.push({ax:Math.min(At(m,te,ue)+K,Q+$)+At(m,Y,ue),ay:oe,v:N})}for(let de=u-1;de>=0;de--){let ie=Math.PI*de/(u-1),oe=ne*Math.cos(ie),ue=ab(Math.abs(Math.cos(ie)));re.push({ax:At(m,fe,ue)+$+At(m,Y,ue),ay:oe,v:N})}let pe=(de,ie,oe)=>Array.from({length:eM},(ue,Ve)=>({ax:ie+(oe-ie)*(Ve+1)/(eM+1),ay:de,v:N}));_.push([...J,...pe(-ne,J[J.length-1].ax,re[0].ax),...re,...pe(ne,re[re.length-1].ax,J[0].ax)])}return{...rM(E,m),rows:E,norm:m,surf:_}}function Ma(e,t){return e?.length?t.map(r=>Eu(e,r)):t.map(()=>0)}function Eu(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 rM(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?At(t,h,g):a(d,At(t,h,g),At(t,b,g)),i=(d,h)=>h>=1?d.axPower:Math.min(h*d.axDrive,d.axPackCap),c=({a:d,b:h,t:b},g,y)=>d.axScrubN?y*s(b,d.axScrubN,h.axScrubN,g):0,l=d=>d.axDragTyre??d.axDrag,u=({a:d,b:h,t:b},g,y)=>{let R=y*a(b,d.ayMax,h.ayMax);return R>0?ab(g/R):1},m=(d,h,b=1,g=1)=>{let{a:y,b:R,t:M}=d,v=u(d,h,b),x=b*s(M,y.axAccelN,R.axAccelN,v)+a(M,l(y),l(R)),k=a(M,i(y,g),M===0?0:i(R,g))+a(M,y.axDrag,R.axDrag);return Math.min(x,k)+c(d,v,b)},f=(d,h,b=1,g=1)=>{let{a:y,b:R,t:M}=d,v=u(d,h,b),x=s(M,y.axDecelN,R.axDecelN,v);return(g===1||x>0?b*x:g*b*x)+a(M,y.axDrag,R.axDrag)+c(d,v,b)},p=({a:d,b:h,t:b},g,y=1)=>{let R=t.length-1,M=d.axAccelN,v=h.axAccelN,x=d.axDecelN,k=h.axDecelN,F=d.axScrubN,w=h.axScrubN,C=I=>M[I]+b*(v[I]-M[I]),T=I=>x[I]+b*(k[I]-x[I]),S=I=>F?y*(F[I]+b*(w[I]-F[I])):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 I=R;I>=0;I--){let G=Math.min(y*C(I)+L,D+P)+S(I),O=y*T(I)+P+S(I);if(!(g<=G+1e-6&&g>=O-1e-6))continue;if(I===R)return t[I]*y*A;let W=(N,$,K)=>{if(K($))return 1;let z=(N-g)/(N-$);return z>0?Math.min(z,1):0},E=N=>g<=N+1e-6,_=N=>g>=N-1e-6,V=Math.min(W(y*C(I)+L+S(I),y*C(I+1)+L+S(I+1),E),W(D+P+S(I),D+P+S(I+1),E),W(y*T(I)+P+S(I),y*T(I+1)+P+S(I+1),_));return(t[I]+V*(t[I+1]-t[I]))*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 zE(e,t,r){let n=e.params,o=n.m.value,{drivenFront:a,drivenRear:s}=Wn(e),i=Yn(n,a,s);return c=>vu(n,c,t,r)/o*i.powerFactor}function bi(e,t,r,n){let o=zE(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{...rM(a,e.norm),rows:a,norm:e.norm}}var YE=[-.2,-.08,0,.06,.12,.2,.3];function nM(e,t=!1,r="twoTrack",n,o,a=YE){let s=[...new Set([...a,0])].sort((d,h)=>d-h),i=s.map(d=>ir(e,t,r,n,o,d)),c=i[s.indexOf(0)],l=s[0],u=s[s.length-1],m=d=>{if(d<=l)return{i:0,t:0};if(d>=u)return{i:s.length-1,t:0};let h=0;for(;h<s.length-2&&s[h+1]<=d;)h++;return{i:h,t:(d-s[h])/(s[h+1]-s[h])}},f=d=>{let h=b=>{let{i:g,t:y}=m(b);return{a:d[g],b:d[Math.min(d.length-1,g+1)],t:y}};return b=>{let{a:g,b:y,t:R}=h(b);if(R===0)return g;let M=(v,x)=>v+R*(x-v);return{vMax:g.vMax,axAccel:(v,x,k=1,F=1)=>M(g.axAccel(v,x,k,F),y.axAccel(v,x,k,F)),axDecel:(v,x,k=1,F=1)=>M(g.axDecel(v,x,k,F),y.axDecel(v,x,k,F)),ay:(v,x,k=1)=>M(g.ay(v,x,k),y.ay(v,x,k)),scrub:(v,x,k=1)=>M(g.scrub?.(v,x,k)??0,y.scrub?.(v,x,k)??0)}}},p=d=>d<l||d>u;return{anchors:s,steady:c,clamps:p,at:f(i),atSoc(d,h,b){let g=i.map(y=>bi(y,d,h,b));return{anchors:s,steady:g[s.indexOf(0)],clamps:p,at:f(g)}}}}function oM(e,t,r,n="twoTrack",o){let a=[...new Set([...t,1])].sort((i,c)=>i-c),s=a.map(i=>i===1?r:ir(e,!1,n,o,void 0,0,i));return{...tM(a,s),atSoc:(i,c,l)=>tM(a,s.map(u=>bi(u,i,c,l)))}}function tM(e,t){let r=e.length-1,n=1,o=0,a=0,s=0,i=1,c=0,l=0,u=p=>{if(n=1,!(p>e[0]))return void(o=0);if(p>=e[r])return void(o=r);let d=0;for(;d<r-1&&e[d+1]<=p;)d++;if(o=d,p===e[d])return;a=d+1;let h=e[d],b=e[d+1];if(r<2){n=2,c=(p-h)/(b-h),i=1-c;return}s=d===0?2:d+1===r||p-e[d-1]<e[d+2]-p?d-1:d+2;let g=e[s];n=3,i=(p-b)*(p-g)/((h-b)*(h-g)),c=(p-h)*(p-g)/((b-h)*(b-g)),l=(p-h)*(p-b)/((g-h)*(g-b))},m=p=>{let d=p(t[o]);if(n===1)return d;let h=p(t[a]);if(n===2)return i*d+c*h;let b=i*d+c*h+l*p(t[s]);return Math.min(Math.max(d,h),Math.max(Math.min(d,h),b))},f=(p,d,h,b,g)=>{if(u(p),n===1||h===0)return m(M=>g(M,h));let y=m(M=>M.ay(d,0,b));if(!(y>0))return m(M=>g(M,h));let R=h/y;return m(M=>g(M,R*M.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,(M,v)=>M.axDecel(d,v,b,R));return g===1?y(1):$h(y(g),y(1),g)},scrub:(p,d,h,b=1)=>f(p,d,h,b,(g,y)=>g.scrub?.(d,y,b)??0),ay:(p,d,h,b=1)=>{if(u(p),n===1||h===0)return m(M=>M.ay(d,h,b));let g=M=>h>0?M.axAccel(d,0,b):-M.axDecel(d,0,b),y=m(g);if(!(y>0))return m(M=>M.ay(d,h,b));let R=h/y;return m(M=>M.ay(d,R*g(M),b))}}}var aM=new WeakMap;function sb(e,t){let r=aM.get(e);if(!r){let n=wr(e).regen?jh(t??Ft(e)):void 0;r={inp:ut(e),ev:sr(e),...n?{regen:n}:{}},aM.set(e,r)}return r}function ib(e,t,r){let n=sb(e,r);return ob(n.inp,n.ev,t,n.regen?{regen:n.regen}:{})}function cb(e){let t=lt(e);if(t.mode!=="hydraulic")return null;let r=a=>a.heat?{heat:kf(a.heat,a.ratio),discs:a.discs}:void 0,n=r(t.hydraulic.front),o=r(t.hydraulic.rear);return n||o?{...n?{front:n}:{},...o?{rear:o}:{}}:null}function WE(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 lb(e,t,r,n,o,a=St){if(!e)return null;let s=WE(t);return{...e.front?{front:Fl(e.front.heat,e.front.discs,s.front,r,n,o.front,a)}:{},...e.rear?{rear:Fl(e.rear.heat,e.rear.discs,s.rear,r,n,o.rear,a)}:{}}}var jE=.5,UE=.02,XE=6,Iu=9,sM=1e-9,qE={FL:0,FR:0,RL:0,RR:0};function ub(e){return e?[...new Set([...e.padCurve.factor,1])].sort((t,r)=>t-r):[1]}function QE(e,t,r){let n=rr(e),o=n.hydraulic;return n.mode!=="hydraulic"||!o?e:{...e,brakes:{...n,hydraulic:{...o,front:{...o.front,padMu:o.front.padMu*t},rear:{...o.rear,padMu:o.rear.padMu*r}}}}}function iM(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 cM(e,t,r,n,o=()=>0){let a=Array.from({length:Iu},(m,f)=>r*f/(Iu-1)),s=Gs(),{front:i,rear:c}=n,l=a.map(m=>{let f=o(m),p=h=>Pr(h,t,m,s).limitAt(0,0,qE,f).ax,d=p(e);return i.map(h=>c.map(b=>{if(h===1&&b===1)return 1;let g=d<0?p(QE(e,h,b))/d:1;return Math.abs(g-1)<sM?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(Iu-2,Math.max(0,Math.floor(m/u))):0,h=u>0?Math.min(1,Math.max(0,(m-a[d])/u)):0,b=iM(i,f),g=iM(c,p),y=M=>{let v=l[M],x=Math.min(i.length-1,b.i+1),k=Math.min(c.length-1,g.i+1),F=v[b.i][g.i]+g.t*(v[b.i][k]-v[b.i][g.i]),w=v[x][g.i]+g.t*(v[x][k]-v[x][g.i]);return F+b.t*(w-F)},R=y(d)+h*(y(Math.min(Iu-1,d+1))-y(d));return Math.abs(R-1)<sM?1:R}}}function ZE(e,t){let{front:r,rear:n}=t;return(o,a)=>e.share(a,r?.[o]??1,n?.[o]??1)}var JE=e=>(e.front??[]).every(t=>t===1)&&(e.rear??[]).every(t=>t===1);function lM(e,t,r){let n=e(),o=1,a=t(n);if(JE(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<XE;c++){let l=e(ZE(r,s));o++;let u=Math.abs(l.laptime-n.laptime);if(n=l,u<UE){i=!0;break}a=t(n);let m=(d,h)=>d&&h?d.map((b,g)=>b+jE*((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 un(e,t){let r=e.engine;if(!r||r.gears.length===0||t.length===0)return;let n=e.params,{drivenFront:o,drivenRear:a}=Wn(e),s=Yn(n,o,a).effective,i=n.power_scale.value,{up:c,down:l}=Of(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:Vf(r.engine.gearbox),limitRpm:r.engine.limitRpm,best:f=>ta(r,f,s,Eu(t,f)*s,i).gear,share:(f,p)=>{let d=Eu(t,f),h=d*s,b=ta(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 uM=new WeakMap;function pb(e){let t=uM.get(e.ggv);return t===void 0&&(t=un(e.vehicle,e.ggv.rows)??null,uM.set(e.ggv,t)),t??void 0}function eI(e){return e.gear&&e.engineRpm&&e.shifting?{gear:e.gear,rpm:e.engineRpm,shifting:e.shifting}:{}}var Nu=class extends Error{constructor(t){super(t),this.name="EventError"}};function tI(e,t){let{ggv:r}=t,n=at(t.numerics),o=n.accelStep,a=Math.max(1,Math.round(e.distance/o)),s=ha(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=pb(t),c=i?xu(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:xM(t,f,[...u,s[a].v],m,1)}}function rI(e,t){let r=Math.max(1,Math.round(e.laps??1)),[n]=ha(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=xM(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 Ou(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 nI(e,t){let r=e.distance!=null?t.v_limit_endurance?.value??0:0;return r>0?r/3.6:void 0}function oI(e,t){if(e.distance==null||mt(t.motorModel))return 0;let r=t.endurance_reserve?.value??0;return r>0?Math.min(r,95)/100:0}var mM=1;function bM(e,t,r,n){return{v:r.v,ax:r.ax,ay:r.ay,ds:t.ds,axDrag:Ma(e.ggv.rows,r.v),...r.axScrub?{axScrub:r.axScrub}:{},axGrade:n,...t.bank?{bank:t.bank}:{}}}var pM=new WeakMap;function gM(e){let t=e.vehicle.params;if(!t.brakeFade)return null;let r=pM.get(t);if(r===void 0){let n=cb(t),o=n?lt(t):null;if(!n||!o||o.mode!=="hydraulic")r=null;else{let a=sb(t,e.vehicle),s=e.ggv.rows,i=cM(a.inp,a.ev,e.vehicle.vMax,{front:ub(o.hydraulic.front.heat),rear:ub(o.hydraulic.rear.heat)},c=>Ma(s,[c])[0]);r={discs:n,table:i}}pM.set(t,r)}return r}function aI(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=pb(e),u=(g,y)=>e.yaw?qk(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}:{}}):gt(bi(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=ln(t.gradient,t.npts),f=g=>n.motorThermal?yk(e.vehicle,t.ds,e.energyOpts??Fr,y=>u(y,g),o,a,m,t.bank).lap:u(void 0,g),p=gM(e);if(!p)return f();let d=pi(n),h=r.discC??{front:d,rear:d};return lM(f,g=>{let y=lb(p.discs,ib(n,bM(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 sI(e,t){let r=nI(e,t.vehicle.params),n=oI(e,t.vehicle.params);return n>0?lI(e,t,n,r):gi(e,t,r)}function _u(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 dM=5,iI=.1,cI=.005,fM=12;function lI(e,t,r,n){let o=gi(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=_u(o,r);if(i>=0)return s(o,n,!0);let c=Math.min(n??1/0,t.ggv.vMax),l=c/2,u=gi(e,t,l);a++;let m=_u(u,r);for(;m<0&&l>dM&&a<fM;)c=l,i=m,l=Math.max(dM,l/2),u=gi(e,t,l),a++,m=_u(u,r);if(m<0)return s(u,l,!1);let f=l,p=0;for(;a<fM&&c-l>iI&&m>cI;){let d=c-l,h=Math.min(c-.05*d,Math.max(l+.05*d,l+m*d/(m-i))),b=gi(e,t,h);a++;let g=_u(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 yM(e,t,r){return r===0?e:e&&!t}function gi(e,t,r){let n=t.track;if(!n)throw new Nu(`Event "${e.id}" needs a track.`);let o=Ou(e,n),a=e.standingStart??t.standingStart??!1,s=K=>yM(a,n.closed,K),i=t.vehicle.params,c=fr(ba(i)),l=c.capacityAh,u=i.soc.value,m=pi(i),f=Ru(c,m),p=0,d=0,h=0,b=0,g=[],y=!1,R=-1/0,M=0,v=0,x=!1,k=-1/0,F=0,w=0,C=-1/0,T=(K,z,j=1)=>{K.tempMaxC>C&&(C=K.tempMaxC),K.motorTempMaxC!==void 0&&(y=!0,x=!0,K.motorTempMaxC>R&&(R=K.motorTempMaxC),K.motorTempMaxC>k&&(k=K.motorTempMaxC),M+=(K.motorDerateTimeFrac??0)*z,F+=(K.motorDerateTimeFrac??0)*z,v+=(K.motorLossKwh??0)/j,w+=(K.motorLossKwh??0)/j)},S=null,A,P=cb(i),L={front:m,rear:m},D=null,I=gM(t)!==null,G=(K,z)=>I&&(Math.abs(K.front-z.front)>mM||Math.abs(K.rear-z.rear)>mM),O=(K,z,j)=>{let Q=Uh(i,K,z);if(D&&D.launch===j&&!pI(Q,D.pw)&&!G(L,D.discC))return D.lap;let ne=aI(t,n,{soc:K,packTempC:z,launched:j,...r?{vCeiling:r}:{},...I?{discC:L}:{}});return D={pw:Q,launch:j,discC:L,lap:ne},ne},W=ln(n.gradient,n.npts),E=(K,z,j)=>ga(t.vehicle,n.ds,K.v,K.ax,t.energyOpts,z,j,void 0,W,void 0,{ay:K.ay,bank:n.bank,...K.axScrub?{scrub:K.axScrub}:{}}),_=new WeakMap,V=(K,z)=>{let j=_.get(K);return j||(j=ib(i,bM(t,n,K,W),t.vehicle),_.set(K,j)),lb(P,j,K.v,n.ds,z,m)},N=(K,z,j)=>{let Q=`${(100*j/n.npts).toFixed(0)} % of the way through lap ${K+1}`,ne=z.cutoffAt>=0&&z.cutoffAt<=z.emptyAt;return{lapsCompleted:K,lapsAsked:o,why:ne?`the pack reached its ${c.voltageFloor.toFixed(0)} V cut-off ${Q}`:`the pack ran out ${Q}`}};for(let K=0;K<o;K++){if(u<=0){A={lapsCompleted:K,lapsAsked:o,why:"the pack was empty"};break}let z=s(K),j=u,Q=f;x=!1,k=-1/0,F=0,w=0,C=-1/0;let ne=O(u,f,z),te=E(ne,u,f);if(te.emptyAt>=0){A=N(K,te,te.emptyAt);break}let Y=O(te.socEnd,te.tempEndC,z).laptime-ne.laptime,J,re,pe,de,ie=f,oe=-1,ue=null,Ve=1;if(Y<=mb)J=ne.laptime,re=te.net,pe=te.loss,de=te.chargeAh,ie=te.tempEndC,T(te,J),Ve=1;else{let le=Math.min(uI,Math.max(2,Math.ceil(Y/(2*mb))));Ve=le;let Re=u,we=f;J=0,re=0,pe=0,de=0;for(let Ge=0;Ge<le;Ge++){let We=O(Re,we,z),be=E(We,Re,we),Fe=be.emptyAt>=0?be.emptyAt/n.npts:1;if(Fe*le<1){oe=Math.round(n.npts*(Ge/le+Fe)),ue=be;break}if(J+=We.laptime/le,T(be,We.laptime/le,le),re+=be.net/le/Fe,pe+=be.loss/le/Fe,de+=be.chargeAh/le/Fe,Re-=be.chargeAh/le/Fe/l,we+=(be.tempEndC-we)/le,Re<=0){oe=Math.round(n.npts*(Ge+1)/le),ue=be;break}}if(ie=we,oe>=0&&ue){A=N(K,ue,oe);break}u=Re}p+=J,d+=re,h+=pe,b+=de,Y<=mb&&(u=te.socEnd),f=ie;let Ae=P?V(ne,L):null;Ae&&(L={front:Ae.front?.endC??L.front,rear:Ae.rear?.endC??L.rear}),g.push({lap:K+1,time:J,elapsed:p,entryTime:ne.laptime,socStart:j,socEnd:u,packTempStartC:Q,packTempEndC:f,packTempMaxC:Number.isFinite(C)?C:Q,energyKwh:re,lossKwh:pe,chargeAh:de,launched:z,substeps:Ve,...r?{vCeiling:r}:{},...x?{motor:{peakWindingC:k,derateTimeFrac:J>0?F/J:0,lossKwh:w}}:{},...Ae?{brakes:{...Ae.front?{front:hM(Ae.front)}:{},...Ae.rear?{rear:hM(Ae.rear)}:{}}}:{}}),S=ne}if(!S){let K=pb(t);S=gt(bi(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.length;return{id:e.id,label:e.label,kind:e.kind,time:p,distance:n.length*$,laps:$,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}:{},...eI(S)},energy:{consumed:d,loss:h,...mt(i.motorModel)?{}:{native:{value:b,unit:"Ah"}},remainingFraction:mt(i.motorModel)?1:u,...y?{motor:{peakWindingC:R,derateTimeFrac:p>0?M/p:0,lossKwh:v}}:{}},lapLog:g,...A?{incomplete:A}:{}}}var mb=.05;function hM(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 uI=4,mI=.001;function pI(e,t){return e===t?!1:!Number.isFinite(e)||!Number.isFinite(t)?!0:Math.abs(e-t)>mI*Math.max(1,Math.abs(t))}function xM(e,t,r,n,o,a){return dI(e,t,o,()=>({v:r,ax:n,...a?{lateral:a}:{}}))}function dI(e,t,r,n){let o=e.energyOpts,a=e.vehicle.params.soc.value,s=0,i=0,c=0;for(let l=0;l<r;l++){let u=n(l),m=ga(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 mt(e.vehicle.params.motorModel)?{consumed:s,loss:i,remainingFraction:1}:{consumed:s,loss:i,native:{value:c,unit:"Ah"},remainingFraction:a}}function RM(e,t){switch(e.kind){case"straightLineAccel":return tI(e,t);case"constantRadius":return rI(e,t);case"trackLap":return sI(e,t)}}function db(e,t){let r={};for(let n of e)r[n.id]=RM(n,t);return r}function vM(e,t){if(e.kind!=="trackLap")return e;let{distance:r,...n}=e;return{...n,laps:Math.max(1,Math.round(t))}}function jn(e,t,r,n,o="twoTrack",a){let s=1/0,i=-1/0;for(let f of r){let p=li(f);if(!p)continue;let d=ok(p,gt(t,f,n).v);d&&(s=Math.min(s,d.lo),i=Math.max(i,d.hi))}if(!(i>=s))return;let c=ak({lo:s,hi:i}),l=c.join(","),u=a?.get(l);if(u)return u;let m=oM(e,c,t,o);return a?.set(l,m),m}var Vu=e=>e.distance/Math.max(1,e.laps);function Bu(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 fI=e=>e.v.map(t=>t*3.6),hI=e=>e.ax.map(t=>t/9.81),bI=e=>e.ay.map(t=>t/9.81),gI=e=>e.ay.map((t,r)=>e.v[r]>1e-6?t/(e.v[r]*e.v[r]):0),$u=(e,t,r)=>e?.slice()??new Array(t.s.length).fill(r),yI=e=>$u(e.z,e,0),xI=e=>e.gradient?e.gradient.map(t=>100*Math.tan(t*Math.PI/180)):$u(void 0,e,0),RI=e=>$u(e.bank,e,0),vI=e=>$u(e.mu,e,1);function kI(e){let t=e.s.length,r=Bu(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 fb=[{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 kM(e){let t=Bu(e);return{ds:t,vars:{s:e.s,ds:t,t:kI(e),v:e.v,speed:fI(e),ax:e.ax,ay:e.ay,axg:hI(e),ayg:bI(e),curv:gI(e),z:yI(e),grade:xI(e),bank:RI(e),grip:vI(e)}}}function MM(e,t){return{v:e.v,ax:e.ax,ay:e.ay,ds:Bu({s:e.s,length:t}),axGrade:ln(e.gradient,e.v.length),...e.bank?{bank:e.bank}:{},...e.loadFactor?{loadFactor:e.loadFactor}:{}}}function SM(e,t){let r=ut(e);return{pastTurnover:Hk(r,sr(e),t),...e.aeroModel?{aeroOutside:Kk(r,t)}:{}}}var Gu="Flying lap";function hb(e,t){return e.kind!=="trackLap"||e.label!==Gu?e.label:e.standingStart??t?"Run":e.label}function MI(e){let t=ut(e);return{yawInertia:t.yawInertia??0,massTotal:t.massTotal,wheelbase:t.wheelbase/1e3}}function SI(e,t,r){let n=e.params,o=n.ggvMode??"twoTrack",a=n.quasiTransient?nM(e,!1,o):null,s=a?a.steady:ir(e,!1,o),i=t?jn(e,s,[t],r,o):void 0;return{ggv:s,...a?{yaw:{family:a,car:MI(n)}}:{},...i?{load:i}:{}}}function AI(e,t){let r=t.lapCounts,n=t.standingStart??!1,o=!1,a=e.events.map(s=>{let i=r?.[s.id]!=null?vM(s,r[s.id]):s,c=hb(i,n),l=c===i.label?i:{...i,label:c};return l!==s&&(o=!0),l});return o?a:e.events}function FI(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=Ou(o,r.track),i=Math.max(1,Math.round(a));i!==s&&e[o.id]&&(e[o.id]={...e[o.id],lapsOverridden:{asked:i,defined:s}})}}function wI(e,t){for(let[r,n]of Object.entries(e))n.trace&&(e[r]={...n,...SM(t,MM(n.trace,Vu(n)))})}function yi(e,t,r={}){let n=Ft(e),o=SI(n,r.track,r.numerics),{ggv:a}=o,s=db(AI(t,r),{vehicle:n,...o,track:r.track,energyOpts:wr(e,r.energyOpts),numerics:r.numerics,standingStart:r.standingStart});return FI(s,t,r),wI(s,n.params),{name:e.name,rulesetId:t.id,events:s,ggv:a}}function bb(e){return{...e,ggv:{rows:e.ggv.rows,vMax:e.ggv.vMax,surf:e.ggv.surf}}}var gb=["<","<=",">",">=","==","!="],_e=class extends Error{at;constructor(t,r){super(t),this.name="ExprError",this.at=r}},xi=e=>e>="0"&&e<="9",AM=e=>/[A-Za-z_]/.test(e),CI=e=>/[A-Za-z0-9_]/.test(e);function TI(e){let t=[],r=0;for(;r<e.length;){let n=e[r];if(n===" "||n===" "||n===`
|
|
224
224
|
`||n==="\r"){r++;continue}if(xi(n)||n==="."&&xi(e[r+1]??"")){let o=r;for(;r<e.length&&(xi(e[r])||e[r]===".");)r++;if(e[r]==="e"||e[r]==="E"){let i=r;if(r++,(e[r]==="+"||e[r]==="-")&&r++,xi(e[r]??""))for(;r<e.length&&xi(e[r]);)r++;else r=i}let a=e.slice(o,r),s=Number(a);if(!Number.isFinite(s))throw new _e(`"${a}" is not a number`,o);t.push({t:"num",value:s,at:o});continue}if(AM(n)){let o=r;for(;;){for(;r<e.length&&CI(e[r]);)r++;if(e[r]==="."&&AM(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(gb.includes(o)){t.push({t:"op",value:o,at:r}),r+=2;continue}if(n==="<"||n===">"){t.push({t:"op",value:n,at:r}),r++;continue}throw new _e(n==="="?'Compare with "==", not "="':'Write not(x) rather than "!x"',r)}if("+-*/^(),".includes(n)){t.push({t:"op",value:n,at:r}),r++;continue}throw new _e(`"${n}" is not something this expression can contain`,r)}return t.push({t:"end",at:e.length}),t}function yb(e){let t=TI(e),r=0,n=()=>t[r],o=h=>{let b=n();return b.t==="op"&&b.value===h},a=h=>o(h)?(r++,!0):!1,s=(h,b)=>{if(!a(h))throw new _e(`Expected ${b} here`,n().at)};function i(){let h=c(),b=n();if(b.t!=="op"||!gb.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"&&gb.includes(y.value))throw new _e("Comparisons do not chain \u2014 write and(a < b, b < c)",y.at);return g}function c(){let h=l();for(;;){let b=n().at;if(a("+"))h={kind:"binary",op:"+",left:h,right:l(),at:b};else if(a("-"))h={kind:"binary",op:"-",left:h,right:l(),at:b};else return h}}function l(){let h=u();for(;;){let b=n().at;if(a("*"))h={kind:"binary",op:"*",left:h,right:u(),at:b};else if(a("/"))h={kind:"binary",op:"/",left:h,right:u(),at:b};else return h}}function u(){return a("-")?{kind:"unary",op:"-",arg:u()}:a("+")?u():m()}function m(){let h=f(),b=n().at;return a("^")?{kind:"binary",op:"^",left:h,right:u(),at:b}:h}function f(){let h=n();if(h.t==="num")return r++,{kind:"num",value:h.value};if(h.t==="name"){if(r++,a("(")){let b=[];if(!o(")"))do b.push(i());while(a(","));return s(")","a closing bracket"),{kind:"call",name:h.value,args:b,at:h.at}}return{kind:"var",name:h.value,at:h.at}}if(a("(")){let b=i();return s(")","a closing bracket"),b}throw h.t==="end"?new _e("The expression ends before it is finished",h.at):new _e(`"${h.value}" cannot start a value`,h.at)}let p=i(),d=n();if(d.t!=="end")throw new _e(`"${d.value}" is left over \u2014 check for a missing operator`,d.at);return p}function xb(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 Ri=(e,t)=>typeof e=="number"?new Array(t).fill(e):e;function PI(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=PI(e),n=e.map(a=>Ri(a,r)),o=new Array(r);for(let a=0;a<r;a++)o[a]=t(...n.map(s=>s[Math.min(a,s.length-1)]));return o}var Ne=(e,t)=>({arity:e,call:r=>Tt(r,t)}),Un=e=>e!==0&&!Number.isNaN(e),cr=e=>e?1:0;function FM(e,t,r){let n=wM(t,r,"integrate"),o=n.length,a=Ri(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 wM(e,t,r){if(!e.ds||e.ds.length===0)throw new _e(`${r}() needs to know the sample spacing, and this context has none`,t);return e.ds}var Ku={abs:Ne(1,Math.abs),sqrt:Ne(1,Math.sqrt),sign:Ne(1,Math.sign),floor:Ne(1,Math.floor),ceil:Ne(1,Math.ceil),round:Ne(1,Math.round),exp:Ne(1,Math.exp),log:Ne(1,Math.log),sin:Ne(1,Math.sin),cos:Ne(1,Math.cos),tan:Ne(1,Math.tan),atan:Ne(1,Math.atan),atan2:Ne(2,Math.atan2),hypot:Ne(2,Math.hypot),min:Ne(2,Math.min),max:Ne(2,Math.max),clamp:Ne(3,(e,t,r)=>Math.min(r,Math.max(t,e))),if:Ne(3,(e,t,r)=>Un(e)?t:r),and:Ne(2,(e,t)=>cr(Un(e)&&Un(t))),or:Ne(2,(e,t)=>cr(Un(e)||Un(t))),not:Ne(1,e=>cr(!Un(e))),finite:Ne(1,e=>cr(Number.isFinite(e))),peak:{arity:1,call:([e])=>{let t=Array.isArray(e)?e:[e],r=0;for(let n of t)r=Math.max(r,Math.abs(n));return r}},mean:{arity:1,call:([e])=>{let t=Array.isArray(e)?e:[e];return t.length?t.reduce((r,n)=>r+n,0)/t.length:0}},total:{arity:1,call:([e],t)=>{let r=FM(e,t,0),n=t.ds,o=Ri(e,n.length),a=n.length-1;return r[a]+(o[a]+o[0])/2*n[a]}},integrate:{arity:1,call:([e],t)=>FM(e,t,0)},cum:{arity:1,call:([e],t)=>{let r=t.ds?.length??(Array.isArray(e)?e.length:1),n=Ri(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=wM(t,0,"deriv"),n=r.length,o=Ri(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}}},Sa={g:9.81,pi:Math.PI,e:Math.E,nan:NaN,inf:1/0},vi={fleetmin:"min",fleetmax:"max"};function Xn(e){switch(e.kind){case"call":return Object.hasOwn(vi,e.name)||e.args.some(Xn);case"unary":return Xn(e.arg);case"binary":return Xn(e.left)||Xn(e.right);default:return!1}}var LI=e=>typeof e=="number"?`${e}`:`between ${e[0]} and ${e[1]}`;function DI(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 EI(e,t){let r=t.map(c=>({k:c,d:DI(c,e)})).filter(c=>c.d<=Math.max(1,Math.floor(e.length/4))),n=Math.min(...r.map(c=>c.d)),o=r.filter(c=>c.d===n).map(c=>c.k).slice(0,3);if(o.length)return`"${e}" is not a name here \u2014 did you mean ${o.join(" or ")}?`;let a=e.indexOf(".");if(a>0){let c=t.filter(l=>l.startsWith(e.slice(0,a+1)));if(c.length)return`"${e}" is not a name here. ${e.slice(0,a)} has ${c.join(", ")}`}let s=new Set,i=[];for(let c of t){let l=c.indexOf(".");l>0?s.add(`${c.slice(0,l)}.\u2026`):i.push(c)}return`"${e}" is not a name here. Available: ${[...s,...i].join(", ")}`}function lr(e,t){switch(e.kind){case"num":return e.value;case"var":{if(Object.hasOwn(t.vars,e.name))return t.vars[e.name];if(Object.hasOwn(Sa,e.name))return Sa[e.name];let r=[...Object.keys(t.vars),...Object.keys(Sa)].sort();throw new _e(EI(e.name,r),e.at)}case"unary":return Tt([lr(e.arg,t)],r=>-r);case"binary":{let r=lr(e.left,t),n=lr(e.right,t);switch(e.op){case"+":return Tt([r,n],(o,a)=>o+a);case"-":return Tt([r,n],(o,a)=>o-a);case"*":return Tt([r,n],(o,a)=>o*a);case"/":return Tt([r,n],(o,a)=>a===0?0:o/a);case"^":return Tt([r,n],(o,a)=>o**a);case"<":return Tt([r,n],(o,a)=>cr(o<a));case"<=":return Tt([r,n],(o,a)=>cr(o<=a));case">":return Tt([r,n],(o,a)=>cr(o>a));case">=":return Tt([r,n],(o,a)=>cr(o>=a));case"==":return Tt([r,n],(o,a)=>cr(o===a));case"!=":return Tt([r,n],(o,a)=>cr(o!==a))}break}case"call":{let r=Object.hasOwn(vi,e.name)?vi[e.name]:void 0;if(r){if(!t.fleet)throw new _e(`${e.name}() compares the cars in a field, so it belongs in a ruleset's KPIs, not in a channel`,e.at);if(e.args.length!==1)throw new _e(`${e.name}() takes 1 argument, not ${e.args.length}`,e.at);return t.fleet(e.args[0],r,e.at)}let n=Object.hasOwn(Ku,e.name)?Ku[e.name]:void 0;if(!n){let s=[...Object.keys(Ku),...t.fleet?Object.keys(vi):[]];throw new _e(`There is no function called "${e.name}". Available: ${s.sort().join(", ")}`,e.at)}let o=typeof n.arity=="number"?n.arity:n.arity[0],a=typeof n.arity=="number"?n.arity:n.arity[1];if(e.args.length<o||e.args.length>a)throw new _e(`${e.name}() takes ${LI(n.arity)} argument${o===1&&a===1?"":"s"}, not ${e.args.length}`,e.at);return n.call(e.args.map(s=>lr(s,t)),t)}}throw new _e("Unreachable node",0)}var Aa=e=>Number.isFinite(e)?e:NaN,Rb=[{name:"time",unit:"s",what:"the whole event, every lap",read:e=>Aa(e?.time)},{name:"lapTime",unit:"s",what:"one lap \u2014 the last one completed",read:e=>Aa(e?.lapTime)},{name:"distance",unit:"m",what:"distance covered",read:e=>Aa(e?.distance)},{name:"laps",unit:"-",what:"laps completed",read:e=>Aa(e?.laps)},{name:"energy",unit:"kWh",what:"energy drawn over the event",read:e=>Aa(e?.energy?.consumed)},{name:"remaining",unit:"-",what:"share of the pack or tank left afterwards",read:e=>Aa(e?.energy?.remainingFraction)},{name:"finished",unit:"-",what:"1 when the car ran the whole event, else 0",read:e=>e&&!e.incomplete?1:0}],CM=/^[A-Za-z_][A-Za-z0-9_]*$/,II=new Set([...Object.keys(Sa),...fb.map(e=>e.name)]);function Hu(e,t,r=[]){let n=[],o=new Set(r),a=t.map(b=>b.id),s=new Set;for(let b of a)CM.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(!CM.test(b.key)){n.push({key:b.key,message:`"${b.key}" must be one word \u2014 letters, digits and _`});continue}if(II.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,yb(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,[...xb(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 _e("fleetmin() and fleetmax() cannot sit inside one another",y)},p=new Set,d={};for(let b of a)for(let g of Rb)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 fb)h[b.name]=[1,1];for(let b of m){let g=i.get(b),y=c.get(b);(Xn(y)||l.get(b).some(x=>p.has(x)))&&p.add(b);let R=g.over!=null?{...d,...h}:d,M=g.over!=null?[1,1]:void 0,v=(x,k,F)=>{let w=lr(x,{vars:R,ds:M,fleet:f});if(Array.isArray(w))throw new _e("fleetmin() and fleetmax() compare one number per car \u2014 reduce the channel first, e.g. peak(v)",F);return w};try{let x=lr(y,{vars:R,ds:M,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 k=x;n.push({key:b,message:k.message,at:k.at})}}return n.length?{plan:null,problems:n}:{plan:{order:m.map(b=>({def:i.get(b),node:c.get(b)})),field:p,eventIds:a},problems:n}}function _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 NI(e,t,r={}){let n={...r};for(let o of e.eventIds){let a=t.events[o];for(let s of Rb)n[`${o}.${s.name}`]=s.read(a)}return{vars:n,laps:new Map,events:t.events}}function TM(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?kM({...n.trace,length:Vu(n)}):null,e.laps.set(t.over,r)}return r?{vars:{...e.vars,...r.vars},ds:r.ds}:null}var PM=e=>Array.isArray(e)?NaN:e;function LM(e,t,r,n={}){let o=Object.keys(t),a=o.map(i=>NI(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=TM(b,i);if(!g)continue;let y=PM(lr(f,g));Number.isFinite(y)&&(Number.isNaN(h)||(p==="min"?y<h:y>h))&&(h=y)}return u.set(f,h),h};for(let f of a){let p=TM(f,i);f.vars[i.key]=p?PM(lr(c,l?{...p,fleet:m}:p)):NaN}}let s={};return o.forEach((i,c)=>{let l={};for(let{def:u}of e.order)l[u.key]=a[c].vars[u.key];s[i]=l}),s}function ki(e,t,r){return LM(e,t,!0,r)}function vb(e,t,r){return LM(e,{car:t},!1,r?{car:r}:void 0).car}var zu=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}},Si=e=>typeof e=="number"&&Number.isFinite(e),Mi=e=>Si(e)&&e>0,Pt=(e,t)=>e===void 0||t(e);function OI(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":Mi(a.distance)||r(`${s} needs a distance above zero, in metres`),Pt(a.vStart,i=>Si(i)&&i>=0)||r(`${s}'s entry speed must be zero or more`);break;case"constantRadius":Mi(a.radius)||r(`${s} needs a radius above zero, in metres`),Pt(a.laps,i=>Si(i)&&i>=1)||r(`${s} runs at least one lap`);break;case"trackLap":Pt(a.laps,i=>Si(i)&&i>=1)||r(`${s} runs at least one lap`),Pt(a.distance,Mi)||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,Si)||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,Mi)||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],Mi)||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 DM(e){let t=OI(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}=Hu(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 Yu(e){return DM(e).problems}var kb=e=>Number.isFinite(e)?e:NaN;function VI(e){return e.unit&&e.format!=="time"?`${e.label} (${e.unit})`:e.label}function mn(e){let t=structuredClone(e),{plan:r,problems:n}=DM(t);if(!r)throw new zu(t.id,n);let o=new WeakMap,a=p=>{let d=o.get(p);return d||(d=vb(r,p),o.set(p,d)),d},s=new Map(t.kpis.map(p=>[p.key,p])),i=new Map;for(let[p,d]of Object.entries(t.score?.parts??{}))i.has(d)||i.set(d,p);let c=p=>(d,h)=>{if(!h)return NaN;let b=h.kpis?.[p];if(b!==void 0)return kb(b);let g=h,y=i.get(p);return y!==void 0?kb(g.parts?.[y]):p===t.score?.total?kb(g.total):NaN},l=t.kpis.filter(p=>!p.hidden).map(p=>{let d=r.field.has(p.key);return{key:p.key,label:VI(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[M,v]of Object.entries(u.parts)){y[M]=g[v];let x=s.get(v)?.max;x!=null&&(R[M]=x)}h[b]={total:g[u.total],parts:y,...Object.keys(R).length?{maxima:R}:{},kpis:Object.fromEntries(t.kpis.map(M=>[M.key,g[M.key]]))}}return h}:void 0,f=m||(r.field.size>0?p=>{let d=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 Yt={accel:"accel",skidpad:"skidpad",autocross:"autocross",endurance:"endurance"},EM=[{kind:"straightLineAccel",id:Yt.accel,label:"Acceleration (75 m)",distance:75},{kind:"constantRadius",id:Yt.skidpad,label:"Skidpad",radius:8.375},{kind:"trackLap",id:Yt.autocross,label:"Autocross (1 lap)",laps:1},{kind:"trackLap",id:Yt.endurance,label:"Endurance (22 km)",distance:22e3}],IM=[{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"}],_M={total:"overall",parts:{[Yt.accel]:"accelPts",[Yt.skidpad]:"skidpadPts",[Yt.autocross]:"autocrossPts",[Yt.endurance]:"endurancePts",efficiency:"efficiencyPts"}},NM={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:EM,kpis:IM,score:_M,track:{minTurnRadius:4.5},battery:X0,traceEventId:Yt.autocross},OM={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:EM,kpis:IM,score:_M,track:{minTurnRadius:4.5},traceEventId:Yt.autocross},Ai=mn(NM),Mb=mn(OM);var Sb="lap",BI=[{kind:"trackLap",id:Sb,label:Gu,laps:1}],VM={id:"trackday",label:"Track day",description:"One flying lap of the selected track. Times and traces only \u2014 no scoring.",events:BI,kpis:[{key:"lap",label:"Lap time",format:"time",lowerBetter:!0,expr:"lap.time"},{key:"topSpeed",label:"Top speed",unit:"km/h",over:Sb,expr:"peak(speed)"},{key:"energy",label:"Energy / lap",unit:"kWh",lowerBetter:!0,expr:"lap.energy"}],traceEventId:Sb},Ab=mn(VM);function pn(e){if(e===null||typeof e!="object")return JSON.stringify(e)??"null";if(Array.isArray(e))return`[${e.map(pn).join(",")}]`;let t=e,r=Object.keys(t).sort(),n=[];for(let o of r)t[o]!==void 0&&n.push(`${JSON.stringify(o)}:${pn(t[o])}`);return`{${n.join(",")}}`}function qn(e){let t=pn(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 Fa=[Ai,Mb,Ab],Qn=Ai.id,wa=e=>Fa.some(t=>t.id===e),BM=new WeakMap,Fi=new Map,$I=64;function Wu(e){let t=BM.get(e);if(t!==void 0)return t;let r=pn(e),n=Fi.get(r);return n===void 0&&(n=Yu(e).length?null:mn(e),Fi.size>=$I&&Fi.delete(Fi.keys().next().value),Fi.set(r,n)),BM.set(e,n),n}function ju(e,t=[]){if(e==null)return;if(typeof e!="string")return Wu(e)??void 0;let r=Fa.find(o=>o.id===e);if(r)return r;let n=t.find(o=>o.id===e);return n?Wu(n)??void 0:void 0}function Zn(e,t=[]){return ju(e,t)??Ai}function Fb(e=[]){let t=e.filter(r=>!wa(r.id)).map(r=>Wu(r)).filter(r=>r!==null);return[...Fa,...t]}var wi=e=>e.definition??e.id;function Uu(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=GI(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 Cb(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=wb(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 GI(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=wb(e,c,r,n),u=new Array(o).fill(0);u[0]=i,u[o-1]=s;let m=wb(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 wb(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 Ci(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 $M(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 GM(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 KM(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=>$M(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=GM([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 KI(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=$M(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 HI(e,t,r){let{j:n,t:o}=KI(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=GM([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 Tb(e,t){return t>0?e.z.map((r,n)=>{let o=HI(e,n,t/2);return o?o.value.reduce((a,s,i)=>a+s*e.z[o.j[i]],0):r}):[...e.z]}function zI(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 Xu(e){let t=Ci(e);if(!t)return 0;let r=KM(t);return r>1e-6?Math.max(10,zI(r,YI(t))):0}function YI(e){let t=[];for(let r=1;r<e.pos.length;r++)t.push(e.pos[r]-e.pos[r-1]);return e.closed&&e.pos.length&&t.push(e.length-e.pos[e.pos.length-1]+e.pos[0]),t.sort((r,n)=>r-n),t.length?t[t.length>>1]:0}function ur(e,t,r){let n=e.n;if(e.closed===!1){let a=r-t;return a===0?e.diag[t]:a===1?e.off1[t]:a===2?e.off2[t]:a===-1?e.off1[r]:a===-2?e.off2[r]:0}let o=((r-t)%n+n)%n;return o===0?e.diag[t]:o===1?e.off1[t]:o===2?e.off2[t]:o===n-1?e.off1[r]:o===n-2?e.off2[r]:0}function Qu(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 HM(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 qu(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 WI(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 Pb(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=HM(r,(y,R)=>ur(e,y,R));if(!b)return null;let g=qu(b,t);return g.every(Number.isFinite)?g:null}let n=r-2,a=HM(n,(b,g)=>ur(e,b,g));if(!a)return null;let s=new Array(n).fill(0),i=new Array(n).fill(0);for(let b=0;b<n;b++)s[b]=ur(e,b,r-2),i[b]=ur(e,b,r-1);let c=qu(a,t.slice(0,n)),l=qu(a,s),u=qu(a,i),m=(b,g)=>{let y=0;for(let R=0;R<b.length;R++)y+=b[R]*g[R];return y},f=[[ur(e,r-2,r-2)-m(s,l),ur(e,r-2,r-1)-m(s,u)],[ur(e,r-1,r-2)-m(i,l),ur(e,r-1,r-1)-m(i,u)]],p=[t[r-2]-m(s,c),t[r-1]-m(i,c)],d=WI(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 zM(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=Pb(i,t);if(c){let l=Qu(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 YM=4,jI=8,Lb=.001;function UI(e,t,r){let n=[];for(let c=1;c<e.length;c++){let l=e[c]-e[c-1];l>=Lb&&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/ek(r,s,i)))}function XI(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])<Lb||(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:UI(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])<Lb;)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?Uu(b.slice(0,d),n,b[d]):Cb(b,n),y=r?Uu(b.slice(0,d),o,b[d]):Cb(b,o),R=new Array(h);for(let F=0;F<h;F++)R[F]=b[F+1]-b[F];let M=[0],v=[0],x=[0],k=0;for(let F=0;F<h;F++){let w=R[F]/YM;for(let C=0;C<YM;C++){let T=C*w;k+=_f(S=>Math.hypot(g.d1(F,S),y.d1(F,S)),T,T+w),M.push(k),v.push(F),x.push(T+w)}}return{closed:r,sx:g,sy:y,h:R,sTable:M,segTable:v,uTable:x,length:k,rawCum:c,rawLength:l}}function Ti(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 qI=.01,QI=3,WM=10;function ZI(e,t,r,n=WM){let o={step:0,uncertainty:1/0},a=e.length;if(a<8||!(r>0))return o;let s=Math.max(WM,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,M,v)=>{let x=R/s;m.push([1,x,x*x,x*x*x,M]),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,M)=>{for(let v=0;v<5;v++){h[v]+=R[v]*f[M];for(let x=0;x<5;x++)d[v][x]+=R[v]*R[x]}});let b=qt(d,h),g=qt(d,[0,0,0,0,1]);if(b.singular||g.singular)return o;let y=0;return m.forEach((R,M)=>{let v=0;for(let x=0;x<5;x++)v+=R[x]*b.x[x];y+=(f[M]-v)**2}),{step:b.x[4],uncertainty:Math.sqrt(y/(m.length-5)*g.x[4])}}function JI(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 e2(e,t,r){let{pos:n,loop:o}=JI(e.length,t),{step:a,uncertainty:s}=ZI(e,n,o,r);return Math.abs(a)>Math.max(qI,QI*s)?{z:e.map((i,c)=>i+a*n[c]/o),drift:-a}:{z:e,drift:0}}function t2(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+_f(v=>Math.hypot(s.d1(p,v),i.d1(p,v)),h,g),M=Math.hypot(s.d1(p,g),i.d1(p,g));if(M<1e-12)break;g-=(R-t)/M}return{seg:p,du:Math.min(Math.max(g,0),a[p])}}var r2=3,Db=5;function n2(e,t,r,n=Db){return Ju(e,t,r,n)}function Ju(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 Pb({n:a,diag:i,off1:c,off2:l,closed:r},u)??[...e]}function yt(e,t){let r=at(t),n=XI(e,r.fitSpacing),o=n.length,a=Math.max(jI,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}=t2(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),I=n.sy.d2(S,A),G=Math.hypot(P,L),O=Math.pow(P*P+L*L,1.5);f[C]=O>0?(P*I-L*D)/O:0,p[C]=G>0?-L/G:0,d[C]=G>0?P/G: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?e2(e.z,n.rawCum,g):null,R=y?y.z:e.z,M=g>0?Ci(e):null,v=M?Tb({...M,z:R},g):R,x=Ti(v,0,h,n),k=new Array(s).fill(0);if(b){for(let T=0;T<s;T++){let S=n.closed?(T+1)%s:Math.min(T+1,s-1),A=n.closed?(T-1+s)%s:Math.max(T-1,0),P=n.closed?2:S-A,L=x[S]-x[A];k[T]=P>0?Math.atan2(L,P*i)*180/Math.PI:0}for(let T=0;T<s;T++){if(m[T]===0)continue;let S=n.closed?(T+1)%s:T+1,A=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(r2,e.zReach??Xu(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 I=n.closed?D:Math.min(Math.max(D,T),s-1-T),G=0,O=0;for(let _=-T;_<=T;_++){let V=x[n.closed?(I+_+s)%s:I+_];G+=(_*_-S/P)*V,O+=_*V}let W=2*G/L/(i*i),E=O/S/i;w[D]=W/Math.pow(1+E*E,1.5)}}}return{name:e.name,closed:n.closed,x:c,y:l,s:u,ds:m,curvature:e.turnReach?n2(f,i,n.closed,e.turnReach):f,npts:s,length:F,nx:p,ny:d,z:x,gradient:k,...w?{verticalCurvature:w}:{},widthLeft:Ti(e.widthLeft,1.5,h,n),widthRight:Ti(e.widthRight,1.5,h,n),bank:Ti(e.bank,0,h,n),mu:Ti(e.mu,1,h,n),...y?.drift?{elevationDrift:y.drift}:{}}}function jM(e,t,r){let n=Qu(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 o2(e,t,r,n){let o=e.n,a=e.closed!==!1,s=(l,u)=>{let m=l+u;return a?(m%o+o)%o:m>=0&&m<o?m:null},i=[...t];for(let l=0;l<o;l++){if(r[l]==="free")continue;let u=n(l);if(u!==0)for(let m of[-2,-1,1,2]){let f=s(l,m);f!=null&&(i[f]-=ur(e,f,l)*u)}}let c={n:o,closed:e.closed,diag:[...e.diag],off1:[...e.off1],off2:[...e.off2]};for(let l=0;l<o;l++){if(r[l]==="free")continue;c.diag[l]=1,c.off1[l]=0,c.off2[l]=0;let u=s(l,-1),m=s(l,-2);u!=null&&(c.off1[u]=0),m!=null&&(c.off2[m]=0),i[l]=n(l)}return zM(c,i)}var a2=1e-4;function UM(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=jM(e,t,u),f=new Array(a).fill("free"),p=!1;for(let d=0;d<s;d++){let h=Qu(e,u).map((R,M)=>R-t[M]),b=!1;for(let R=0;R<a;R++){let M=u[R]<=r[R]+i&&h[R]>=-i?"lo":u[R]>=n[R]-i&&h[R]<=i?"hi":"free";M!==f[R]&&(f[R]=M,b=!0)}if(p&&!b)return{x:u,iterations:d+1,converged:!0,bounds:f};let g=o2(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 M=!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&&(M=!0),T}),x=jM(e,t,v),k=0;for(let F=0;F<a;F++)k+=h[F]*(v[F]-u[F]);if(R===1&&!M||x<m&&x<=m+a2*k){u=v,m=x,p=R===1&&!M,y=!0;break}}if(!y)return{x:u,iterations:d+1,converged:!1,bounds:f}}return{x:u,iterations:s,converged:!1,bounds:f}}var Eb={lineStep:2,carHalfWidth:.75,margin:.1,foldMargin:.25,referenceReach:5,passes:40,iterations:400},s2=[1,.5,.25,.125,.0625,.03125,.015625,.0078125,.00390625,.001953125,.0009765625],i2=e=>Math.sqrt(e.reduce((t,r)=>t+r*r,0)/(e.length||1));function Pi(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 c2=Math.PI/180,XM=20;function l2(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?XM:Math.min(XM,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 u2(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?l2(t,r):t.z;return{...n||o?{z:s.map((i,c)=>i+r[c]*Math.tan(t.bank[c]*c2))}:{},...n?{zReach:e.zReach??Xu(e)}:{},...o?{bank:[...t.bank]}:{},...a?{mu:[...t.mu]}:{}}}function qM(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 m2(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),M=Math.hypot(b,g),v=y*R*M;if(!(v>1e-12))continue;let x=2*c(f,p,d,h)/v,k=Math.sqrt(.5*(y+R)),F=x/(2*k),w=(f*r[u]+p*n[u])/y,C=(b*r[u]+g*n[u])/M,T=(f*r[l]+p*n[l])/y,S=(d*r[l]+h*n[l])/R,A=(d*r[m]+h*n[m])/R,P=(b*r[m]+g*n[m])/M,L=-2*c(r[u],n[u],d,h)/v+x*(w/y+C/M),D=2*c(r[l],n[l],b,g)/v-x*(T/y-S/R),I=2*c(f,p,r[m],n[m])/v-x*(A/R+P/M);s[l]=x*k,i.l[l]=k*L-F*.5*w,i.d[l]=k*D+F*.5*(T-S),i.r[l]=k*I+F*.5*A}return{res:s,jac:i}}function p2(e,t,r,n,o){let a=n-r+1,s=e.l.slice(r,n+1),i=e.d.slice(r,n+1),c=e.r.slice(r,n+1),l=t.slice(r,n+1);o||(i[0]+=s[0],s[0]=0,i[a-1]+=c[a-1],c[a-1]=0);let u=(h,b)=>o?h[(b+a)%a]:b>=0&&b<a?h[b]:0,m=new Array(a),f=new Array(a),p=new Array(a),d=new Array(a);for(let h=0;h<a;h++){let b=u(c,h-1),g=u(s,h+1);m[h]=b*b+i[h]*i[h]+g*g,f[h]=i[h]*c[h]+g*u(i,h+1),p[h]=g*u(c,h+1),d[h]=-(b*u(l,h-1)+i[h]*l[h]+g*u(l,h+1))}return{M:{n:a,closed:o,diag:m,off1:f,off2:p},b:d}}function d2(e,t){let r=e.npts,n=e.closed;if(!(t>0)||r<7)return e;let o=n?r:r-1,a=0;for(let f=0;f<o;f++){let p=(f+1)%r;a+=Math.hypot(e.x[p]-e.x[f],e.y[p]-e.y[f])}let s=a/o,i=Ju(e.x,s,n,t,!0),c=Ju(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=Pi(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 f2=6;function h2(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(f2/(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 Ib(e,t={}){let r={...Eb,...t},n=yt(e,{dsTarget:r.lineStep}),o=d2(n,r.referenceReach),a=o.npts,s=T=>({x:o.x.map((S,A)=>S+o.nx[A]*T[A]),y:o.y.map((S,A)=>S+o.ny[A]*T[A])}),i=T=>{let S=Pi(T.x,T.y,o.closed),A=qM(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=i2(n.curvature),l=qM(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];h2(o,f,p,r.foldMargin);let g=T=>{let S=s(T),A=u2(e,o,T),P={name:`${e.name} \u2014 racing line`,x:S.x,y:S.y,closed:o.closed,widthLeft:h.map((E,_)=>Math.max(0,E-T[_])),widthRight:b.map((E,_)=>Math.max(0,T[_]-E)),...A,fit:"interpolate",turnReach:Db},L=1e-6,D=T.filter((E,_)=>E>=f[_]-L||E<=p[_]+L).length,I=Pi(S.x,S.y,o.closed),G=E=>1/Math.max(...E.map(Math.abs),1e-9),O=0,W=o.closed?S.x.length:S.x.length-1;for(let E=0;E<W;E++){let _=(E+1)%S.x.length,V=S.x[_]-S.x[E],N=S.y[_]-S.y[E];O+=A.z?Math.hypot(V,N,A.z[_]-A.z[E]):Math.hypot(V,N)}return{offset:T,s:[...o.s],asset:P,curvatureRms:{centreLine:c,racingLine:Math.sqrt(i(S)/(l||1))},infeasibleSamples:d,atBoundary:a?D/a:0,length:{centreLine:n.length,racingLine:O},worstRadius:{centreLine:G(n.curvature),racingLine:G(I)}}},y=o.closed?0:1,R=o.closed?a-1:a-2,M=R-y+1,v=new Array(M),x=new Array(M);for(let T=0;T<M;T++)v[T]=p[y+T],x[T]=f[y+T];if(!o.closed&&M>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(M-1,a-1),v[0]=x[0]=Math.min(x[0],Math.max(v[0],0))}if(M<7)return g(u);let k=T=>{let S=s(T),P=[...Pi(S.x,S.y,o.closed).map(Math.abs)].sort((L,D)=>L-D);return{integral:i(S),tail:P[Math.floor(.99*(P.length-1))]}},F=[...u],w=k(u),C;for(let T=0;T<r.passes;T++){let S=s(F),{res:A,jac:P}=m2(S.x,S.y,o.nx,o.ny,o.closed),{M:L,b:D}=p2(P,A,y,R,o.closed),I=UM(L,D,v.map((W,E)=>W-F[y+E]),x.map((W,E)=>W-F[y+E]),{maxIter:r.iterations,bounds:C});C=I.bounds;let G=new Array(a).fill(0);for(let W=0;W<M;W++)G[y+W]=I.x[W];o.closed||(G[0]=G[1],G[a-1]=G[a-2]);let O=!1;for(let W of s2){let E=F.map((V,N)=>V+W*G[N]),_=k(E);if(_.integral<w.integral*(1-1e-6)){F=E,w=_,O=!0;break}}if(!O)break}return g(F)}function _b(e){let t=Math.max(Z(e,"track_front"),Z(e,"track_rear"));return(t>0?t/2e3:.6)+.1}function em(e,t,r={}){if(!r.racingLine)return{asset:e,numerics:t,line:null};let n=r.params?_b(r.params):void 0,o=Ib(e,{...r.line,...n?{carHalfWidth:n}:{}});return{asset:o.asset,numerics:{...t,fitSpacing:0},line:o}}function Li(e,t,r={}){let n=em(e,t,r);return{track:yt(n.asset,n.numerics),line:n.line}}function Nb(e=4,t=Li){let r=new WeakMap;return(n,o,a={})=>{let s=a.racingLine===!0,i=s?[a.params?_b(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 QM={racingLine:!1,standingStart:!1},tm=256;function Di(e,t,r,n,o=QM,a=Li){let s=Zn(n),{racingLine:i,standingStart:c,lapCounts:l}=o;return e.map(u=>{let{track:m}=a(t,r,{racingLine:i,params:u});return bb(yi(u,s,{track:m,numerics:r,standingStart:c,lapCounts:l}))})}function Ob(e,t){let r=Zn(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 Vb(e,t,r){let n={};for(let o of Zn(e).metrics)n[o.key]=o.value(t,r);return n}var rm=36;var Gb=287.05287,g2=461.495,nm=9.80665/(Gb*.0065),y2=101325/(Gb*288.15),x2=273.15,R2=-500,v2=6e3,k2=400,M2=1100,om={source:"car",altitudeM:0,pressure:{kind:"standard"},humidityPct:0};function S2(e){return 101325*Math.pow(1-.0065*e/288.15,nm)}function A2(e){return 288.15/.0065*(1-Math.pow(e/y2,1/(nm-1)))}function F2(e){return 288.15/.0065*(1-Math.pow(e/101325,1/nm))}function w2(e,t){return e*Math.pow(1-.0065*t/288.15,nm)}function C2(e){return 611.21*Math.exp((18.678-e/234.5)*(e/(257.14+e)))}function T2(e,t){switch(e.kind){case"standard":return S2(t);case"qnh":return w2(e.hPa*100,t);case"station":return e.hPa*100}}function Ei(e,t,r=0,n=F2(e)){let o=t+x2,a=Math.min(.5*e,Math.max(0,Math.min(100,r))/100*C2(t)),s=e-a,i=s/(Gb*o)+a/(g2*o);return{altitudeM:n,p:e,pDry:s,T:o,rho:i,densityAltitudeM:A2(i)}}function ZM(e,t){return Ei(T2(e.pressure,e.altitudeM),t,e.humidityPct,e.altitudeM)}var Bb=(e,t,r)=>Math.min(r,Math.max(t,e)),$b=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function am(e){if(!e||typeof e!="object")return structuredClone(om);let t=e,r=t.pressure??{},n=Bb($b(r.hPa,1013.25),k2,M2),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:Bb($b(t.altitudeM,0),R2,v2),pressure:o,humidityPct:Bb($b(t.humidityPct,0),0,100)}}var Ii=e=>e?.source==="venue";var P2=Math.PI/180;function L2(){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 D2(){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 Kb(e){let t=-e*P2;return q([0,Math.cos(t),Math.sin(t)])}function sm(){let e={rodType:"push",pushrodAttach:"lowerArm",steerMode:"rack",spinAxis:Kb(-1),loadedRadius:230,springRate:35,rackAxis:[0,1,0]};return{hardpoints:L2(),config:e}}function _i(){let e={rodType:"pull",pushrodAttach:"lowerArm",steerMode:"fixed",spinAxis:Kb(-1.5),loadedRadius:232,springRate:40,rackAxis:[0,1,0]};return{hardpoints:D2(),config:e}}function im(){let e=[-25,635,460],t=[-40,600,710],r={layout:"mcpherson",actuation:"direct",rodType:"push",pushrodAttach:"upright",steerMode:"rack",spinAxis:Kb(-.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 Hb(){return{front:sm(),rear:_i(),config:{wheelbase:1600,trackFront:1200,trackRear:1220,frontAxleX:800}}}var E2=Math.PI/180;function JM(e){let t=-e*E2;return q([0,Math.cos(t),Math.sin(t)])}function zb(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:JM(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]=I2(o[l]);return{hardpoints:o,config:c}}function I2(e){return e.map(t=>Math.round(t*10)/10+0)}function eo(e){return{name:e.name,front:zb(sm(),e.front),rear:zb(_i(),e.rear),config:{wheelbase:e.wheelbase,trackFront:e.trackFront,trackRear:e.trackRear,frontAxleX:e.wheelbase/2}}}function Ca(e,t,r){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:t}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:r}}}}var Ta=600,to=610,Pa=230,ro=232;function no(){let e=Hb();return{...e,name:"Formula Student",front:{...e.front,config:{...e.front.config,actuation:"rocker"}},rear:{...e.rear,config:{...e.rear.config,actuation:"rocker"}}}}function Yb(){return eo({name:"Formula 1",wheelbase:3600,trackFront:1600,trackRear:1600,front:{kx:1.3,ky:800/Ta,kz:355/Pa,lowerInnerDz:-5,upperInnerDz:0,camberDeg:-3,loadedRadius:355,springRate:200},rear:{kx:1.3,ky:800/to,kz:355/ro,lowerInnerDz:35,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:220}})}function Ni(){return Ca(eo({name:"GT car",wheelbase:2700,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/Ta,kz:325/Pa,lowerInnerDz:18,upperInnerDz:5,camberDeg:-3.5,loadedRadius:325,springRate:110,actuation:"direct"},rear:{kx:1.2,ky:825/to,kz:325/ro,lowerInnerDz:36,upperInnerDz:15,camberDeg:-2,loadedRadius:325,springRate:120,actuation:"direct"}}),318.6,318.6)}function Oi(){return Ca(eo({name:"Sports car",wheelbase:2750,trackFront:1550,trackRear:1550,front:{kx:1.15,ky:775/Ta,kz:320/Pa,lowerInnerDz:36,upperInnerDz:15,camberDeg:-.5,loadedRadius:320,springRate:55,actuation:"direct"},rear:{kx:1.15,ky:775/to,kz:320/ro,lowerInnerDz:57,upperInnerDz:25,camberDeg:-1,loadedRadius:320,springRate:60,actuation:"direct"}}),305.4,309)}function _2(e,t,r,n,o,a){let s=im(),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:JM(n),springRate:o,rackTravel:a}}}function eS(){return Ca({name:"Cup car",front:_2(55,-25,-23,-3.5,150,55),rear:zb(_i(),{kx:1.15,ky:820/to,kz:320/ro,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 tS(){return{...Ca(eo({name:"Stock car",wheelbase:2794,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/Ta,kz:355/Pa,lowerInnerDz:20,upperInnerDz:5,camberDeg:-2.5,loadedRadius:355,springRate:175,actuation:"direct"},rear:{kx:1.2,ky:825/to,kz:355/ro,lowerInnerDz:40,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:150,actuation:"direct"}}),343.8,345.3),chassis:{boxes:[],body:"nascar"}}}function rS(){let e=Ca(eo({name:"Hill-climb prototype",wheelbase:2550,trackFront:1580,trackRear:1540,front:{kx:1.1,ky:790/Ta,kz:300/Pa,lowerInnerDz:10,upperInnerDz:5,camberDeg:-2.5,loadedRadius:300,springRate:90},rear:{kx:1.1,ky:770/to,kz:300/ro,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 nS(){let e=Ca(eo({name:"Race truck",wheelbase:3700,trackFront:2050,trackRear:1950,front:{kx:1.5,ky:1025/Ta,kz:506/Pa,lowerInnerDz:40,upperInnerDz:10,camberDeg:-.5,loadedRadius:506,springRate:200,actuation:"direct"},rear:{kx:1.5,ky:975/to,kz:506/ro,lowerInnerDz:60,upperInnerDz:20,camberDeg:-.25,loadedRadius:506,springRate:160,actuation:"direct"}}),490.4,495.6);return{...e,front:{...e.front,config:{...e.front.config,rackTravel:60}},chassis:{boxes:[],body:"truck"}}}var tt=(e,t,r)=>({value:e,label:t,unit:r}),oS=(e,t)=>({...nr[e],value:t});function aS(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 oo(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 $r(e){let t={name:e.name,m:tt(e.m,"vehicle mass (with driver)","kg"),A:tt(e.A,"frontal area","m^2"),c_l:tt(e.cl,"downforce coefficient","-"),c_w:tt(e.cw,"drag coefficient","-"),l_to_d_ratio:tt(e.cw>0?e.cl/e.cw:0,"lift-to-drag ratio","-"),driven_wheels:tt(e.drivenWheels,"driven wheels","-"),fr_0:tt(-.012,"rolling-resistance coefficient","-"),front_aero_diss:tt(e.frontAero,"front aero distribution","-"),front_mass_diss:tt(e.frontMass,"front mass distribution","-"),r_dyn:tt(e.rDyn,"dynamic tyre radius","m"),rho:tt(1.2,"air density","kg/m^3"),gear_ratio:tt(e.gearRatio,"gear ratio","-"),effi_pgb:tt(e.drivetrainEfficiency,"drivetrain efficiency","-"),capacity:tt(e.capacityAh,"pack capacity","Ah"),soc:tt(1,"state of charge","-"),ocv:tt(e.ocv,"pack open-circuit voltage","V"),power_scale:tt(1,"power scaling factor","-"),power_limit_kw:oS("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]=oS(r,n);return t}var La={name:"Formula Student",m:300,A:1,cl:3,cw:1.3,frontMass:.47,frontAero:.45,rDyn:.222,drivenWheels:2,gearRatio:11.5,motor:aS(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}},jb={name:"Formula 1",m:798,A:1.5,cl:3,cw:.9,frontMass:.46,frontAero:.44,rDyn:.35,drivenWheels:2,gearRatio:4.9,motor:oo(735,2e3,12500,2500,2),motorCount:1,driveline:{rear:bt.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}},cm={name:"GT car",m:1300,A:2,cl:1.4,cw:.42,frontMass:.5,frontAero:.42,rDyn:.33,drivenWheels:2,gearRatio:3.43,motor:oo(410,2e3,8e3,2e3,2),motorCount:1,driveline:{rear:bt.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}},lm={name:"Sports car",m:1600,A:2.2,cl:-.1,cw:.3,frontMass:.55,frontAero:.5,rDyn:.32,drivenWheels:2,gearRatio:3.14,motor:oo(220,1500,6500,1400,2),motorCount:1,driveline:{rear:bt.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}},Ub={name:"Cup car",m:1265,A:2.1,cl:.45,cw:.4,frontMass:.62,frontAero:.45,rDyn:.31,drivenWheels:2,gearRatio:3.5,motor:oo(250,2e3,7e3,1190,2),motorCount:1,motorPlacement:"front",driveline:{front:bt.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}},Xb={name:"Stock car",m:1620,A:2.2,cl:.6,cw:.45,frontMass:.53,frontAero:.45,rDyn:.35,drivenWheels:2,gearRatio:4.1,motor:oo(500,2500,9e3,1680,2),motorCount:1,driveline:{rear:bt.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}},qb={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:oo(330,3e3,8500,1240,2),motorCount:1,driveline:{rear:bt.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}},Qb={name:"Race truck",m:5300,A:6.2,cl:-.1,cw:.65,frontMass:.6,frontAero:.6,rDyn:.502,drivenWheels:2,gearRatio:3.55,motor:oo(880,100,3e3,88e3,2),motorCount:1,driveline:{rear:bt.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 Wb(e,t,r){return $r(r({...structuredClone(e),name:t}))}var um={[La.name]:$r(La),"Formula Student +15% downforce":Wb(La,"Formula Student +15% downforce",e=>({...e,cl:e.cl*1.15,cw:e.cw*1.08})),"Formula Student -15 kg":Wb(La,"Formula Student -15 kg",e=>({...e,m:e.m-15})),"Formula Student +15% power":Wb(La,"Formula Student +15% power",e=>({...e,motor:aS(25*1.15,15e3,2e4),powerLimitKw:80*1.15})),[jb.name]:$r(jb),[cm.name]:$r(cm),[lm.name]:$r(lm),[Ub.name]:$r(Ub),[Xb.name]:$r(Xb),[qb.name]:$r(qb),[Qb.name]:$r(Qb)},sS=Object.keys(um),Zb=sS.slice(0,4),Jb=[La.name,jb.name,cm.name,lm.name,Ub.name,Xb.name,qb.name,Qb.name];var Bee={"Touring car":cm.name,"Street car":lm.name};var N2={bg:"#0e1116",panel:"#161b22",panel2:"#1c232d",border:"#2a323d",borderBright:"#39424e",sunken:"#11161c",ink:"#06090d"},O2={normal:"#d6dde6",dim:"#8b96a3",bright:"#e7ecf3",white:"#ffffff"},V2={label:"#c8d2dc",grid:"#39424e",gridFaint:"#232b35",empty:"#1a2028"},B2={accent:"#4aa3ff",accentInk:"#04121f",warn:"#ffb454",good:"#4ec9a0",bad:"#ff6b6b",badSoft:"#ff8f8f"},$2=["#f0e442","#7b68ee","#f7a8b8","#d55e00","#d8b4fe","#b5e48c"],mm={front:"#a6e22e",rear:"#00b4d8"},iS=["#5b4bd6","#4aa3ff","#4ec9a0","#f0e442"],eg={power:"#ffb454",traction:"#f0845c",front:mm.front,rear:mm.rear,grip:"#73c9b3",braking:"#b48aff",crest:"#e88fd0",below:"rgba(214, 221, 230, 0.32)"},G2={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"},K2={x:"#ff6b6b",y:"#57c75a",z:"#4aa3ff"},H2={line:"#b4bfcb"},z2={compression:"#b48aff",tension:"#ff6b6b"},Y2={fz:"#e7ecf3",fx:"#7ad7f0",fy:"#ff54c8"},W2={drivenLine:"#4d7cff",axis:"#eef3fa",slip:"#ffe81a",drive:eg.power,brake:eg.braking},j2={ground:"#101920",grid:"#1a2630",gridMajor:"#26343f",horizon:"#1d2833",bridge:"#6f7a86",coneLeft:"#2f63c9",coneRight:"#d9b51f",coneStart:"#ee7a2c"},U2={chassis:"#435160",volume:"#303b47",tyre:"#435160",tyreLine:"#39424e",tyreFace:"#1c232d"},X2={centreLine:"#4aa3ff",corridorFill:"rgba(74,163,255,0.10)",boundary:"#3d4956",racingLine:"#ffb454",start:"#e7ecf3",finish:"#ff6b6b",direction:"#8b96a3"},q2={SURFACE:N2,TEXT:O2,CHART:V2,ROLE:B2,SERIES:$2,AXLE:mm,LAP_SPEED:iS,LIMITER:eg,RIG:G2,AXIS:K2,CONSTRUCTION:H2,FORCE:z2,TYRE_FORCE:Y2,REPLAY:W2,SCENERY:j2,BODY:U2,TRACK:X2},cS=e=>Object.fromEntries(Object.entries(e).map(([t,r])=>[t,Array.isArray(r)?Object.freeze([...r]):Object.freeze({...r})])),pm=cS(q2),xt=pm.SERIES,lS=(()=>{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 cS({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 uS=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},Gee=(()=>{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=pm[r],o=lS[r];for(let a of Object.keys(n)){let s=uS(n[a]);s&&!e.has(s)&&e.set(s,o[a])}}return e})();var mS=(e,t)=>new Set(t.flatMap(r=>{let n=e[r];return Array.isArray(n)?[...n]:Object.values(n)}).map(uS).filter(r=>r!==null)),Kee=mS(lS,["SERIES","AXLE","LAP_SPEED","LIMITER","ROLE","RIG","FORCE","TYRE_FORCE","REPLAY","AXIS","TRACK","CONSTRUCTION"]),Hee=mS(pm,Object.keys(pm).filter(e=>e!=="SURFACE"));function tg(){return{kind:"simple",name:"Simple motor",rpm:[0,16e3,2e4],torque:[21,21,14],efficiency:.95}}function rg(){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 ag(){return{kind:"ice",name:"Formula 1 power unit (example)",rpm:[4e3,5e3,6e3,7e3,8e3,9e3,1e4,10500,11e3,11500,12e3,12500],torque:[896,822,773,738,712,692,675,668,638,610,585,545],idleRpm:4e3,limitRpm:12500,inertia:.02,gearbox:{primary:1,ratios:[4,3.15,2.575,2.175,1.85,1.6,1.375,1.18],efficiency:.94,upshiftTime:0,downshiftTime:0,driveKept:1},breathing:{induction:{kind:"boosted",boostKPa:350,maxPressureRatio:5}}}}function pS(){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 dS(){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 fS(){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 hS(){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 bS(){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 gS(){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 yS(e){return qn(Q2(e))}function Q2(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 Vi(e,t){return{...t,fingerprint:yS(e)}}var xS="CC-BY-4.0",Z2={title:"PaceDynamics built-in library",url:"https://pacedyn.dev/",licence:xS},RS={fidelity:"generic",licence:xS,sources:[Z2]};var dm=e=>Vi(e,RS);var vS=["raw.githubusercontent.com"],kS=["tum-csv"],e_=/^[0-9a-f]{64}$/;function $i(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"||!e_.test(r)||!kS.includes(n))return!1;try{let o=new URL(t);return o.protocol==="https:"&&vS.includes(o.hostname)&&!o.username&&!o.password&&!o.port}catch{return!1}}var fm=e=>new URL(e.url).hostname;async function MS(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 t_(e){let t=new URL(e).pathname.split("/").pop()??"";return decodeURIComponent(t).replace(/\.[^.]*$/,"")||"Linked track"}function r_(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 n_={"tum-csv":r_};function SS(e,t){return n_[t.format](e,t_(t.url))}async function sg(e,t,r){let n=await MS(e);if(n!==t.sha256)throw new Error(`${fm(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=SS(new TextDecoder().decode(e),t),a=await hm(o);if(a!==r)throw new Error(`Linked track ${r} does not convert to its name (it is ${a}).`);return o}var ig=20,a_=new RegExp(`^[0-9a-f]{${ig}}$`),Gi=e=>typeof e=="string"&&a_.test(e);async function hm(e){let t=new TextEncoder().encode(pn(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,ig)}var cg=e=>`tracks/${e}.json`;var s_=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function lg(e){return{model:{name:e.name,source:e.source},...e.provenance?{provenance:e.provenance}:{}}}async function ug(e,t){if(!s_(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 hm(e);if(r!==t)throw new Error(`Catalogue track ${t} does not match its name (it is ${r}).`);return e}var ao=(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}),dn=[ao("suspensions","suspensionId","suspension"),ao("tires","tireModelId","tyre",[{key:"tiresRear",ref:"tireModelIdRear",label:"rear tyre"}]),ao("motors","motorModelId","motor"),ao("aeros","aeroModelId","aero map"),ao("batteries","batteryModelId","battery"),ao("brakes","brakeModelId","brakes"),ao("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 bm(e){let t={...e};for(let r of dn)for(let n of r.refs)delete t[n];return t}var gm=xt,Ki=gm,mg=gm,fn=[...xt.slice(3),...xt.slice(0,3)],fg=[...xt.slice(1),xt[0]],pg=[...xt.slice(2),...xt.slice(0,2)],dg=[...xt.slice(4),...xt.slice(0,4)],hg=[...xt.slice(5),...xt.slice(0,5)],Hi=[...xt.slice(2),...xt.slice(0,2)];function bg(){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 gg(e,t,r){let n=um[e];if(!n)throw new Error(`no preset vehicle named "${e}"`);return{id:t,params:{...Ws(structuredClone(n)),energy:{...Fr},suspensionId:"sus1"},visible:!0,color:Ki[r%Ki.length]}}function l_(){return Zb.map((e,t)=>gg(e,`v${t+1}`,t))}function u_(){return[ks(),Zd(),Jd(),ef(),tf(),rf(),nf(),of(),af(),sf()].map((t,r)=>({id:`t${r+1}`,color:mg[r%mg.length],model:t}))}function m_(){return[_p(),Np(),Op(),Vp(),Bp(),$p(),Gp(),Kp()].map((t,r)=>({id:`a${r+1}`,color:pg[r%pg.length],model:t}))}function p_(){return[Rp(),vp(),kp()].map((t,r)=>({id:`b${r+1}`,color:dg[r%dg.length],model:t}))}function d_(){return[{id:"brk1",color:hg[0],model:structuredClone(Ff)}]}function f_(){return[{id:"dmp1",color:Hi[0],model:structuredClone(Xl)}]}function h_(){return[tg(),rg()].map((t,r)=>({id:`m${r+1}`,color:fn[r%fn.length],model:t}))}function yg(e){let t=r=>({...r,provenance:dm(r.model)});return{...e,suspensions:e.suspensions.map(t),vehicles:e.vehicles.map(r=>({...r,provenance:dm(bm(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 zi(e="Untitled project"){let t=new Date().toISOString(),r=l_();return yg({schemaVersion:rm,meta:{id:bg(),name:e,domain:"racecar",rulesetId:Qn,createdAt:t,updatedAt:t},suspensions:[{id:"sus1",color:fg[0],model:no()}],activeSuspensionId:"sus1",vehicles:r,activeVehicleId:r[0]?.id??null,tires:u_(),motors:h_(),aeros:m_(),batteries:p_(),brakes:d_(),dampers:f_(),tracks:[],activeTrackId:null,mathChannels:[],rulesets:[],studies:[],activeStudyId:null,loadCases:[],reportLayouts:[],tyreSheets:[],kinSheets:[],plans:[],results:[],settings:{numerics:{...ci},ggvMode:"twoTrack",quasiTransient:!1,motorThermal:!1,brakeFade:!1,airTempC:St,air:structuredClone(om),diffYaw:!1,lapCounts:{},pathPlanId:null,useRacingLine:!0,standingStart:!1}})}var b_=9.81,Yi={speed:20,ayG:1.2};function xg(e,t={}){let r=t.operating??Yi,n=t.assemble,o,a,s,i=new Map,c=new Map,l=new Map,u=new Map,m=g=>({speed:g?.speed!==void 0&&Number.isFinite(g.speed)&&g.speed>0?g.speed:r.speed,ayG:g?.ayG!==void 0&&Number.isFinite(g.ayG)?g.ayG:r.ayG}),f=()=>{if(o!==void 0)return o;if(!n)return o=null;try{o=n(e)}catch{o=null}return o},p=()=>{if(a!==void 0)return a;try{a=sr(e.params)}catch{a=null}return a},d=g=>{let y=m(g),R=`${y.speed}|${y.ayG}`,M=i.get(R);if(M!==void 0)return M;let v=p();if(!v)return i.set(R,null),null;let x={cornerStiffness:k=>v.corneringStiffness(k),ayG:y.ayG,speed:y.speed,fyAxle:(k,F)=>2*v.Fy(k,F/2),tire:v};return i.set(R,x),x},h=()=>{if(s!==void 0)return s;let g=f(),y=p();if(!g||!y)return s=null;try{s=Nn(y,g.massTotal*b_*1.2)}catch{s=null}return s},b=g=>{let y=m(g).speed,R=`${y}`,M=c.get(R);if(M!==void 0)return M;let v=f(),x=p(),k=null;if(v&&x)try{k=kh(v,x,y,{steering:!1})}catch{k=null}return c.set(R,k),k};return{operating:r,dynAvailable:!!n,operatingAt:m,dynInput:f,tyre:p,dynCtx:d,grip:h,ymd:b,ymdLimit:g=>{let y=`${m(g).speed}`,R=l.get(y);if(R!==void 0)return R;let M=b(g),v=M?eb(M):null;return l.set(y,v),v},reserves:(g,y)=>{let R=m(y),M=`${g}|${R.speed}|${R.ayG}`,v=u.get(M);if(v!==void 0)return v;let x=f(),k=d(y),F=null;if(x&&k)try{F=fi(x,k,g,h()??void 0)}catch{F=null}return u.set(M,F),F}}}var AS=["widthLeft","widthRight","bank","mu"];function Wi(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 Rg(e){let t=Wi(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 xm(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 AS){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 Rm(e,t,r){if(!t.length)return e;let n=Wi(e),o=n.length,a={widthLeft:ym(e.widthLeft,r.widthLeft),widthRight:ym(e.widthRight,r.widthRight),bank:ym(e.bank,r.bank),mu:ym(e.mu,r.mu)},s={};for(let c of AS){let l=e[c];Array.isArray(l)&&l.length===o&&(s[c]=l)}let i=xm(t,n,a,s);return{...e,...i}}function ym(e,t){return typeof e=="number"?e:t}var CS=1,FS=4,km=Math.PI/180,vg=e=>e===null||!Number.isFinite(e)||e===0?0:1/e;function kg(e){return e.kind==="arc"?Math.abs(e.radius)*Math.abs(e.angle)*km:e.length}function vm(e,t){return e.kind==="straight"?0:e.kind==="arc"?vg(e.radius):t}function wS(e){return e.kind==="straight"?0:e.kind==="arc"?vg(e.radius):vg(e.endRadius)}var ji=(e,t,r,n,o)=>e+t*o+(n>0?(r-t)*o*o/(2*n):0);function Ui(e,t={}){let r=Math.max(.05,t.spacing??CS),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+kg(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*km,b=e.length?vm(e[0],0):0,g=0,y=f,R=(S,A,P)=>{s.push(S),i.push(A),c.push(P)};R(p,d,0);let M=(S,A,P,L,D)=>{let I=D-L;if(I<=0)return;if(Math.abs(A-S)<1e-12){let O=ji(h,S,S,P,L);if(Math.abs(S)<1e-12)p+=I*Math.cos(O),d+=I*Math.sin(O);else{let W=O+S*I;p+=(Math.sin(W)-Math.sin(O))/S,d+=-(Math.cos(W)-Math.cos(O))/S}return}let G=I/FS;for(let O=0;O<FS;O++){let W=L+O*G,E=ji(h,S,A,P,W),_=ji(h,S,A,P,W+G/2),V=ji(h,S,A,P,W+G);p+=G/6*(Math.cos(E)+4*Math.cos(_)+Math.cos(V)),d+=G/6*(Math.sin(E)+4*Math.sin(_)+Math.sin(V))}};for(let S of e){let A=kg(S),P=vm(S,b),L=wS(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 I=Math.min(A,y-g);M(P,L,A,D,I),D=I,R(p,d,g+I),y+=f}M(P,L,A,D,A),h=ji(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 k=e.length?vm(e[0],b):0,F={gap:v,headingError:g_((h-o.heading*km)/km),curvatureError:b-k},w=[];for(let S=0;S<e.length;S++){let A=wS(e[S]),P=S+1<e.length?e[S+1]:n?e[0]:null;if(!P)continue;let L=vm(P,A);w.push({index:S,before:A,after:L,jump:Math.abs(L-A)})}let C=xm(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 g_(e){let t=e%360;return t>180&&(t-=360),t<-180&&(t+=360),t}var y_={halfWidthM:1.5,spacingM:.5};function Xi(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 ${PS(e).toFixed(0)} m`}}}function PS(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 LS=e=>e.kind==="skidpad"||e.kind==="curves"&&e.closed===!0,DS=e=>e.kind==="acceleration",ES=1.5,IS=3;function x_(e,t){let r=e.offsetM,n=e.pitchM,o=Math.max(1,e.gates)*n,a=Math.max(0,e.leadInM),s=ES*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*(IS*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:Xi(e),x:m,y:f,closed:!1,widthLeft:t.halfWidthM,widthRight:t.halfWidthM,fit:"interpolate"}}function R_(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 Mg(e,t={}){let r={...y_,...t},n=DS(e),o=R_(e);if(!o){let u=x_(e,r);return{asset:u,peakCurvature:TS(u),worstJoint:0,standingStart:n}}let a=LS(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*(IS*Math.PI/180))):r.spacingM,c=Ui(o,{name:Xi(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:TS(c.asset),worstJoint:l.reduce((u,m)=>Math.max(u,m.jump),0),standingStart:n}}function TS(e){try{return Math.max(...yt(e).curvature.map(Math.abs))}catch{return NaN}}var Sm={courses:[{id:"c1",course:{kind:"manoeuvre",spec:{kind:"skidpad",radiusM:8.375}}}],ggvMode:"twoTrack"};function Sg(e){return e.course.kind==="project"?"the project\u2019s track":e.course.kind==="track"?e.course.name:Xi(e.course.spec)}var _S=new WeakMap,Mm=new Map;function NS(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=Mm.get(n);if(o)return{...o,numerics:r};let a=Mg(e.spec),s={asset:a.asset,standingStart:a.standingStart};return Mm.size>64&&Mm.clear(),Mm.set(n,s),{...s,numerics:r}}function Ag(e,t,r={}){let n=r.lap??Sm,o=r.simParams,a=r.numerics??{},s=n.courses.length?n.courses:Sm.courses,i,c,l,u=new Map,m=new Map,f=new Map,p=new Map,d=M=>(M?.courseId?s.find(v=>v.id===M.courseId):void 0)??s[0],h=()=>{if(i!==void 0)return i;if(!o)return i=null;try{i={...o(e),ggvMode:n.ggvMode}}catch{i=null}return i},b=M=>{let v=d(M);if(!v)return null;let x=m.get(v.id);if(x!==void 0)return x;let k=NS(v.course,r,a),F=null;if(k)try{let w=JSON.stringify(k.numerics),C=_S.get(k.asset);C||(C=new Map,_S.set(k.asset,C));let T=C.get(w);T||(T=yt(k.asset,k.numerics),C.set(w,T)),F={id:v.id,track:T,standingStart:k.standingStart,numerics:k.numerics,name:k.asset.name}}catch{F=null}return m.set(v.id,F),F},g=()=>{if(c!==void 0)return c;let M=h();if(!M)return c=null;try{l=Ft(M),c=ir(l,!1,n.ggvMode)}catch{c=null}return c},y=M=>{let v=b(M);if(!v)return null;let x=f.get(v.id);if(x!==void 0)return x;let k=g(),F=null;if(k)try{let w=l?jn(l,k,[v.track],v.numerics,n.ggvMode,u):void 0,C=l?un(l,k.rows):void 0;F=gt(k,v.track,v.numerics,{standingStart:v.standingStart,...w?{load:w}:{},...C?{shifts:C}:{}})}catch{F=null}return f.set(v.id,F),F};return{lapSettings:n,get lapAvailable(){return!!o&&s.some(M=>!!NS(M.course,r,a))},lapParams:h,courses:()=>s,course:b,ggv:g,lap:y,lapReserve:M=>{let v=b(M);if(!v)return null;let x=p.get(v.id);if(x!==void 0)return x;let k=y(M),F=t.dynInput(),w=t.tyre(),C=null;if(k&&F&&w)try{let T=h();C=Pu(F,w,{v:k.v,ax:k.ax,ay:k.ay,ds:v.track.ds,axDrag:Ma(g()?.rows,k.v),...k.axScrub?{axScrub:k.axScrub}:{},axGrade:ln(v.track.gradient,k.v.length),bank:v.track.bank,...k.loadFactor?{loadFactor:k.loadFactor}:{}},T?{driven:Gf(T)}:{})}catch{C=null}return p.set(v.id,C),C}}}var OS=180/Math.PI,Fg={rise:0,sinPitch:0,sinRoll:0};function VS(e){let t=e.kc;return t?BS(e.vehicle,r=>t.ground0[r]):Fg}function BS(e,t){let r=e.config,n=Do(r),o=0,a=0,s=0,i=0,c=0,l=0,u=0,m=0,f=0;for(let g of Lo){let y=Ze(g,r),R=y.axleX-n,M=y.sideSign*Ur(e,y.isFront)/2,v=t(g);if(!Number.isFinite(v))return Fg;o++,a+=R,s+=M,i+=v,c+=R*R,l+=M*M,u+=R*M,m+=R*v,f+=M*v}let p=o*(c*l-u*u)-a*(a*l-u*s)+s*(a*u-c*s);if(!(Math.abs(p)>1e-9))return{rise:i/o,sinPitch:0,sinRoll:0};let d=(i*(c*l-u*u)-a*(m*l-u*f)+s*(m*u-c*f))/p,h=(o*(m*l-u*f)-i*(a*l-u*s)+s*(a*f-m*s))/p,b=(o*(c*f-m*u)-a*(a*f-m*s)+i*(a*u-c*s))/p;return{rise:d,sinPitch:h,sinRoll:-b}}function qi(e,t){let r=e.kc,n=BS(e.vehicle,o=>(r?r.ground0[o]:0)+t[o]);return q([-n.sinPitch,n.sinRoll,1])}function wg(e,t,r,n){let o=q(Xr(e,Ze(t,r)));return-Math.asin(Math.max(-1,Math.min(1,X(o,n))))*OS}function Am(e,t,r,n,o){let a=q(Xr(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=Xa({uprightUpper:c(u.uprightUpper),uprightLower:c(u.uprightLower),wheelCenter:c(u.wheelCenter),spinAxis:m,tieOuter:c(u.tieOuter),loadedRadius:o.loadedRadius,patchShift:o.patchShift&&v_(o.patchShift,e.metrics.toe/OS,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 v_(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 $S(e,t){let r=VS(t);if(r===Fg)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 Cg(e,t,r){let n=$S({heave:0,pitch:0,roll:0,steer:0},r);return e-rd(n,[t,0,0],Do(r.vehicle.config))}var k_=180/Math.PI;function Tg(e,t){return!e.valid||!e.ic?!1:Math.hypot(e.ic[0]-e.cp[0],e.ic[1]-e.cp[1])<=t}function Fm(e,t,r){let n=Ze(t,e.vehicle.config),o=ft(e,r),a=eu(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=qi(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},M=a.omega[1],v=Math.hypot(m[0],m[1]),x=Math.abs(M)*1e9>v?[p[0]+m[1]/M,p[1]-m[0]/M]: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)*k_,tanTheta:S,tanThetaHub:R(f),valid:!0,sinAngle:F}}function GS(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 S_=180/Math.PI,A_=Math.PI/180,Pg=.5,wm=2,Lg=.25,F_={heave:0,pitch:0,roll:0,steer:0},w_={FL:"FR",FR:"FL",RL:"RR",RR:"RL"},Cm=e=>e.ok?e.state:{...e.nearest,converged:!1};function Dg(e,t,r){return t.state?t.solved===!1?{...t.state,converged:!1}:t.state:Cm(ge(e,t.travel,t.steer,void 0,r))}var KS=new WeakMap;function HS(e,t){let r=e.ctx[t],n=$e(e.vehicle,t).config.loadedRadius,o=Qt(n,e.kc,t),a=KS.get(r);a||(a=new Map,KS.set(r,a));let s=a.get(o);if(!s){let i=qr(t,e.vehicle.config,F_,e.vehicle);s=Cm(ge(r,i.travel,i.steer,void 0,o===n?void 0:{loadedRadius:o})),a.set(o,s)}return s}var mr=(e,t)=>!e||!e.lo.converged||!e.hi.converged?NaN:(t(e.hi)-t(e.lo))/(2*e.step),zS=(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 WS(e,t,r,n,o){let a=e.vehicle.config,s=Po(r),i=$e(e.vehicle,r),c=Ze(r,a),l=e.ctx[r],u=ft(e,t),m=u[r],f={travel:m.travel,steer:m.steer},p=m.rigid?void 0:{loadedRadius:m.loadedRadius},d=Dg(l,m,p),h=HS(e,r),b={lo:Cm(ge(l,f.travel-Pg,f.steer,void 0,p)),hi:Cm(ge(l,f.travel+Pg,f.steer,void 0,p)),step:Pg},g=c.isFront?{lo:Ee(l,d.beta,f.steer-wm,void 0,p),hi:Ee(l,d.beta,f.steer+wm,void 0,p),step:wm}:null,y=z=>{let j=ft(e,{...t,roll:t.roll+z*A_})[r];return Dg(l,j,j.rigid?void 0:{loadedRadius:j.loadedRadius})},R={lo:y(-Lg),hi:y(Lg),step:Lg},M=T_(e,t,r,c.isFront,u,g),v=_t(d.points.contactPatch,c),x=_t(h.points.contactPatch,c),k=Math.abs(v[1])-Math.abs(x[1]),F=w_[r],w=u[F],C=Dg(e.ctx[F],w,w.rigid?void 0:{loadedRadius:w.loadedRadius}),T=C.converged?k+Math.abs(C.points.contactPatch[1])-Math.abs(HS(e,F).points.contactPatch[1]):NaN,S=o??or(e,t,s),A=tu(S,dt(i)),P=A?null:k1(S),L=c.sideSign>0?S.icRight:S.icLeft,D=L?Math.hypot(L[0]-v[1],L[1]-v[2]):1/0,I=Fm(e,r,t),G=I.ic?Math.hypot(I.ic[0]-I.cp[0],I.ic[1]-I.cp[1]):1/0,O=GS(I,s,a.wheelbase,n),W=-mr(b,z=>z.points.damperLength),E=i.config.springRate,_=mr(R,z=>z.metrics.camber),V=qi(e,{FL:u.FL.ground,FR:u.FR.ground,RL:u.RL.ground,RR:u.RR.ground}),N=e.kc?.loadCase,$=z=>N?Am(z,r,a,V,{loadedRadius:m.loadedRadius,patchShift:N.patchShift[r]}):z.metrics,K=$(d);return{id:r,converged:d.converged,travel:d.travel,camber:d.metrics.camber,camberRoad:wg(d.points.spinAxis,r,a,V),toe:d.metrics.toe,caster:K.caster,kpi:K.kpi,scrubRadius:K.scrubRadius,mechanicalTrail:K.mechanicalTrail,scrubAtWheel:K.scrubAtWheel,trailAtWheel:K.trailAtWheel,kingpinOffset:K.kingpinOffset,casterOffset:K.casterOffset,steeringArm:d.metrics.steeringArm,camberGain:mr(b,z=>z.metrics.camber),bumpSteer:mr(b,z=>z.metrics.toe),trackScrubRate:mr(b,z=>Math.abs(_t(z.points.contactPatch,c)[1])),casterGain:mr(b,z=>$(z).caster),kpiGain:mr(b,z=>$(z).kpi),scrubGain:mr(b,z=>$(z).scrubRadius),trailGain:mr(b,z=>$(z).mechanicalTrail),...c.isFront?{camberPerSteer:zS(g,z=>z.metrics.camber,z=>z.metrics.toe),steerJacking:-zS(g,z=>z.points.contactPatch[2],z=>z.metrics.toe),...M!==void 0?{steerLoad:M}:{}}:{},rollCamber:_,camberRecovery:-100*c.sideSign*_,rollSteer:c.sideSign*mr(R,z=>z.metrics.toe),halfTrackChange:k,trackChange:T,longitudinal:v[0]-x[0],rollCentreHeight:P?P.heightAboveGround:S.heightAboveGround,rollCentreHeightChassis:(P?P.height:S.height)-Cg(0,c.axleX,e),rollCentreLateral:S.lateralAlongGround,rollCentreValid:S.valid,rollCentreUsable:A,rollCentreHeightUsable:A||P!==null,rollCentreSinAngle:S.sinAngle,fvsaLength:D,svsaLength:G,swingArmAngle:I.swingArmAngleDeg,svsaUsable:Tg(I,a.wheelbase),svsaSinAngle:I.sinAngle,...s==="front"?{antiDive:O.brake,antiLift:O.drive}:{antiSquat:O.drive,antiLift:O.brake},decoupled:i.config.actuation==="decoupled",mcpherson:i.config.layout==="mcpherson",springRate:E,motionRatio:W,wheelRate:E*W*W,damperLength:d.points.damperLength,damperTravel:h.points.damperLength-d.points.damperLength,...C_(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)*S_,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 C_(e,t,r,n){if(e.config.actuation==="decoupled")return{};let o=n?{droop:n.droopStated?n.droop:null,bump:n.bump}:Io(t,e.config.coilover),a=t-r;return{...o.droop!==null?{damperToExtended:a-o.droop}:{},...o.bump!==null?{damperToClosed:o.bump-a}:{}}}function T_(e,t,r,n,o,a){if(!a||!n)return;let s=Wc(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)*wm,k=g.state?{q:[...g.state.pose.t,...g.state.pose.omega],phi:g.state.points.rockerAngle}:void 0,F=pt(ge(y,g.travel,g.steer-x,k,R)),w=pt(ge(y,g.travel,g.steer+x,k,R));if(!F||!w)return NaN;l[h]=w.points.contactPatch[2]-F.points.contactPatch[2],u[h]=br(i.curve[b],g.travel,w.points.damperLength)-br(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=as(p,h,[m.hi[0],m.hi[1]]),g=as(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 Qi(e,t,r,n,o){return WS(e,t,r==="front"?"FL":"RL",n,o)}function Eg(e,t,r,n){let o=Qi(e,t,"front",r,n?.front),a=Qi(e,t,"rear",r,n?.rear);return{front:o,rear:a,wheelbaseChange:o.longitudinal-a.longitudinal}}var Ig=Math.PI/180,Tm={travelSteps:9,heaveSteps:5,rollSteps:4,rackSteps:6},Pm={travelMin:-25,travelMax:25,rollMaxDeg:3,rollAtLimitDeg:2.5};function P_(e){let t=e.params;return{cgHeight:t.cg_height?ut({...t,surveyedRadiusFront:e.vehicle.front.config.loadedRadius,surveyedRadiusRear:e.vehicle.rear.config.loadedRadius}).cgHeight:300,...Yf(t),drive:Kf(t)}}function _g(e,t=Tm,r=Pm,n){let o=null,a=(S,A)=>(o||(o={violation:S,reason:A}),null),s=e.vehicle,i=S=>S==="front"?s.front:s.rear,c=null,l=null,u=()=>{if(c)return c;if(n)try{let S=n();if(S)return c=Ct(s,S.kc),l=S.cgHeight,c}catch{a(500,"the car could not be stood on its tyre: its rates did not assemble")}return c=Ct(s)},m=S=>S==="front"?"FL":"RL",f=S=>{let A=u();if(!A.kc)return;let P=i(S).config.loadedRadius,L=Qt(P,A.kc,m(S));return L===P?void 0:{loadedRadius:L}},p=(S,A)=>-ss(u(),m(S),A),d=new Map,h=new Map,b=new Map,g=new Map,y=new Map,R=new Map,M=new Map,v=null,x=()=>{if(v)return v;u();let S=P_(e);return v=l!==null&&Number.isFinite(l)?{...S,cgHeight:l}:S},k,F,w=()=>{if(F!==void 0)return F;let S=Zc(u().ctx.FL,Nt(s.front.config));return F=S?Jc(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,()=>jd(i(S))??null),sweep:S=>C(d,S,()=>{let A;try{A=qe(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(G=>G.travel),D=Math.max(...L)-Math.min(...L),I=r.travelMax-r.travelMin;return a(Math.max(0,I-D),`the ${S} linkage reaches only ${D.toFixed(0)} mm of the ${I.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 D=0;D<L;D++){let I=r.travelMin+(r.travelMax-r.travelMin)*D/(L-1);A.push(I),P.push(or(u(),{heave:p(S,I),pitch:0,roll:0,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in heave`)}return{at:A,rc:P}}),rcRoll:S=>C(g,S,()=>{let A=[],P=[],L=Math.max(2,t.rollSteps);try{for(let D=0;D<L;D++){let I=r.rollMaxDeg*D/(L-1);A.push(I),P.push(or(u(),{heave:0,pitch:0,roll:I*Ig,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in roll`)}return{at:A,rc:P}}),steer:()=>{if(k!==void 0)return k;try{k=Cd(u(),{steerMax:Nt(s.front.config),steps:t.rackSteps})}catch{k=a(500,"the steering sweep threw")}let S=k?.filter(A=>!A.converged).length??0;if(k&&S>0){let A=w();k=A?a(A.violation,A.reason):a(100+10*S,`${S} of ${k.length} steering solves did not converge`)}return k??null},solveAt:(S,A,P=0)=>C(y,`${S}:${A}:${P}`,()=>{try{let L=ge(u().ctx[m(S)],A,P,void 0,f(S));return L.ok?L.state:L.why==="unconverged"?a(100,`the ${S} corner did not solve at ${A.toFixed(0)} mm of travel`):a(100+Math.abs(L.travelMiss),`the ${S} corner reaches only ${(A+L.travelMiss).toFixed(0)} of ${A.toFixed(0)} mm of travel`)}catch{return a(150,`the ${S} corner solve threw at ${A.toFixed(0)} mm of travel`)}}),readout:S=>C(R,`${S.heave}:${S.pitch}:${S.roll}:${S.steer}`,()=>{try{return Eg(u(),S,x())}catch{return a(500,"the derived readout threw")}}),readoutAtTravel:(S,A)=>C(M,`${S}:${A}`,()=>{try{return Qi(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*Ig),L=u();if(!L.kc)return P;try{let D=ft(L,{heave:0,pitch:0,roll:A*Ig,steer:0}),I=S==="front"?Math.max(D.FL.travel,D.FR.travel):Math.max(D.RL.travel,D.RR.travel);return Number.isFinite(I)?I:P}catch{return a(500,`the ${S} axle could not be rolled on its tyre`),P}},onTyre:()=>!!u().kc}}var L_=Nb();function Ng(e,t={}){let r=new Map;return{session(n){if(r.has(n))return r.get(n);let o=null,a=t.session?.();if(t.sessionParams&&a)try{let s=ju(n,a.rulesets),i=s?.events.some(c=>c.kind==="trackLap");if(s&&(a.track||!i)){let c=t.sessionParams(e),{standingStart:l,lapCounts:u}=a.settings,m=a.track?Di([c],a.track,a.numerics,wi(s),a.settings,L_)[0]:yi(c,s,{numerics:a.numerics,standingStart:l,lapCounts:u});o={};for(let f of s.metrics)yc(f)&&(o[f.key]=f.value(m,void 0))}}catch{o=null}return r.set(n,o),o}}}var Lm=Math.PI/180,Dm=1e-6;function US(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 Zi(e){let t=e.measured;if(t)return US(t.travel,t.camber);let r=q(e.config.spinAxis);return-Math.asin(Math.max(-1,Math.min(1,r[2])))/Lm}function Ji(e){let t=e.measured;if(t)return US(t.travel,t.toe);let[r,n]=e.config.spinAxis;return Math.atan2(r,n)/Lm}function Og(e,t){let r=Math.abs(t.camber)>=Dm,n=Math.abs(t.toe)>=Dm;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=(Zi(e)+t.camber)*Lm,l=(Ji(e)+t.toe)*Lm,[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 Em(e){let t=e&&typeof e=="object"?e.value:void 0;return typeof t=="number"&&Number.isFinite(t)?t:void 0}function D_(e,t){let r=t;return{front:Em(r.camber_front_deg)??Zi(e.front),rear:Em(r.camber_rear_deg)??Zi(e.rear)}}function E_(e,t){let r=t;return{front:Em(r.toe_front_deg)??Ji(e.front),rear:Em(r.toe_rear_deg)??Ji(e.rear)}}function I_(e){return{camber:{front:Zi(e.front),rear:Zi(e.rear)},toe:{front:Ji(e.front),rear:Ji(e.rear)}}}var jS=new WeakMap;function __(e,t){let r=I_(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)<Dm&&Math.abs(u.toe)<Dm;if(o(n.front)&&o(n.rear))return e;let a=`${t.camber.front}|${t.camber.rear}|${t.toe.front}|${t.toe.rear}`,s=jS.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&&Og(m,n[Po(u)])])):void 0,l={...e,front:Og(e.front,n.front),rear:Og(e.rear,n.rear),...c?{corners:c}:{}};return s||jS.set(e,s=new Map),s.size>=16&&s.clear(),s.set(a,l),l}function Im(e,t){return t?__(e,{camber:D_(e,t),toe:E_(e,t)}):e}var N_=9.81;function Da(e){let t=An(e),r=Math.max(0,e.unsprungPerCorner)*N_,n=a=>{let s=a==="FL"||a==="FR",i=s?"front":"rear",c=Ue(e,i),l=c>0?c:1/0,u=Ap(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:Bt(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 XS=new WeakMap;function O_(e){let t=Im(e.vehicle,e.params);if(t===e.vehicle)return e;let r=XS.get(e);return(!r||r.vehicle!==t)&&XS.set(e,r={...e,vehicle:t}),r}function Ea(e,t={}){let r=O_(e),n=xg(r,t),o=t.assemble?()=>{let c=n.dynInput();if(!c)throw new Error("the car did not assemble");return{kc:Da(c),cgHeight:c.cgHeight}}:void 0,a=_g(r,t.density,t.envelope,o),s=Ag(r,n,t),i=Ng(r,t);return{...a,...n,...s,...i,get failure(){return a.failure},values:new Map}}var V_=["x","y","z"],B_=/^(line|plane)\((-?\d+),(-?\d+)\)([uv]?)$/,qS=Math.PI/18e3,QS=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],ZS=(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]],$_=e=>Math.hypot(e[0],e[1],e[2]),Vg=(e,t)=>[e[0]*t,e[1]*t,e[2]*t];function Bg(e){let t=$_(e);return t>1e-9?Vg(e,1/t):null}function G_(e,t){let r=e*qS,n=t*qS;return[Math.cos(n)*Math.cos(r),Math.cos(n)*Math.sin(r),Math.sin(n)]}function pr(e){let t=e.lastIndexOf(".");if(t<0)return null;let r=B_.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:G_(Number(r[2]),Number(r[3]))},coord:n==="line"?"along":r[4]}}function JS(e){let t=Bg(ZS([0,0,1],e))??[1,0,0];(t[0]<-1e-9||Math.abs(t[0])<=1e-9&&t[1]<0)&&(t=Vg(t,-1));let r=Bg(ZS(e,t))??[0,1,0];return(r[2]<-1e-9||Math.abs(r[2])<=1e-9&&r[1]<0)&&(r=Vg(r,-1)),[t,r]}function $g(e){if(e.coord==="along")return e.shape.dir;let[t,r]=JS(e.shape.dir);return e.coord==="u"?t:r}function eA(e,t){let r=pr(t);if(!r)return;let n=V_.map(u=>e[`${r.point}.${u}`]);if(n.some(u=>!u))return;let o=$g(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=>QS(s(u),o),write:(u,m)=>{let f=s(u),p=m-QS(f,o),d=u;for(let h of a)d=n[h].write(d,f[h]+p*o[h]);return d},...c?{supersededBy:c}:{}}}var _m=["x","y","z"];var K_=/^(?:hp\.(?:front|rear)\.\w+|(?:heave|roll)\.(?:front|rear)\.(?:outer|inner|anchor))$/;function ec(e){let t=e.lastIndexOf("."),r=e.slice(0,t);if(t<0||!K_.test(r))return null;let n=e.slice(t+1);if(n==="x"||n==="y"||n==="z")return{point:r,axis:n};let o=pr(e);return o?{point:r,axis:o.coord}:null}function Gg(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 Kg=e=>e?.reads==="speed"||e?.reads==="operating",Hg=e=>e?.reads==="lateral"||e?.reads==="operating";function so(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}`),t.join(",")}function Wt(e,t,r){let n=`${t.id}@${so(r)}`,o=e.values.get(n);if(o!==void 0)return o;let a;try{a=r?.courseId==="*"&&t.reads==="course"?H_(e,t,r):t.read(e,r)}catch{a=NaN}return e.values.set(n,a),a}function H_(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:Wt(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 Rt(e){return`${e.quantity??e.groupShort??e.group} \xB7 ${e.label}`}var z_={front:"Front",rear:"Rear"},tc={heave:0,pitch:0,roll:0,steer:0};function tA(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 Y_(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 rc=e=>e.length?Math.max(...e)-Math.min(...e):NaN;function rA(e){let t=(e??[]).filter(Number.isFinite);if(!t.length)return NaN;let r=t.reduce((n,o)=>n+o,0)/t.length;return Math.abs(r)>0?(Math.max(...t)-Math.min(...t))/Math.abs(r):NaN}function nA(e,t){if(!e.length)return;let r=0;for(let n=1;n<e.length;n++)Math.abs(e[n])<Math.abs(e[r])&&(r=n);return t[r]}function oA(e){let t=z_[e],r=x=>`kin.${e}.${x}`,n=(x,k)=>{let F=x.sweep(e);return F?{x:F.samples.map(w=>w.travel),y:F.samples.map(k)}:{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 k=a(x);return k&&k.design.kind!=="none"?null:`${i} has no heave element`}function u(x){let k=a(x);return k?.design.kind==="coil"&&k.linkage?null:`${i} has no heave element on a linkage`}function m(x){let k=s(x);return k&&k.design.kind!=="none"?null:`${i} has no roll element`}function f(x){let k=s(x);return k?.linkage&&k.design.kind!=="none"&&k.design.kind!=="direct"?null:`${i} has no roll element on a linkage`}let p=x=>{if(u(x.car))return null;let k=x.sweep(e);return k?fd(o(x.car),a(x.car).linkage,k.samples):null},d=x=>{if(f(x.car))return null;let k=x.sweep(e);if(!k)return null;let F=s(x.car),w=md(o(x.car),F.linkage,F.design.kind,k.samples),C=w.atDesign<0?-1:1;return{travel:w.travel,ratio:w.ratio.map(T=>T*C),atDesign:w.atDesign*C}},h=x=>x.readout(tc)?.[e],b=x=>x.readoutAtTravel(e,x.envelope.travelMax),g=x=>{let k=n(x,F=>F.metrics.camber);return k.x.length?{key:r("camberGain"),title:`${t} camber vs travel`,xLabel:"travel [mm]",yLabel:"camber [\xB0]",...k}:null},y=x=>{let k=n(x,F=>F.metrics.toe);return k.x.length?{key:r("bumpSteer"),title:`${t} toe vs travel`,xLabel:"travel [mm]",yLabel:"toe [\xB0]",...k}: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 k=x.rcHeave(e);return k?Y_(k.at,k.rc.map(F=>F.height)):NaN},curve:x=>{let k=x.rcHeave(e);return k?{key:r("rcHeaveWorst"),title:`${t} roll-centre height vs wheel travel`,xLabel:"travel [mm]",yLabel:"RC height [mm]",x:k.at,y:k.rc.map(F=>F.height)}:null}},{id:r("rcRollSpan"),group:`${t} roll centre`,label:"height span over the roll envelope",unit:"mm",scale:15,scope:e,cost:"cheap",read:x=>{let k=x.rcRoll(e);return k?rc(k.rc.map(F=>F.height)):NaN},curve:x=>{let k=x.rcRoll(e);return k?{key:r("rcRollSpan"),title:`${t} roll-centre height vs body roll`,xLabel:"roll [\xB0]",yLabel:"RC height [mm]",x:k.at,y:k.rc.map(F=>F.height)}:null}},{id:r("rcLateralSpan"),group:`${t} roll centre`,label:"lateral migration over roll",unit:"mm",scale:50,scope:e,cost:"cheap",read:x=>{let k=x.rcRoll(e);return k?rc(k.rc.map(F=>F.lateral)):NaN},curve:x=>{let k=x.rcRoll(e);return k?{key:r("rcLateralSpan"),title:`${t} roll-centre lateral position vs body roll`,xLabel:"roll [\xB0]",yLabel:"RC lateral [mm]",x:k.at,y:k.rc.map(F=>F.lateral)}:null}},{id:r("minSinAngle"),group:`${t} roll centre`,label:"construction conditioning (min sinAngle)",unit:"-",scale:.04,scope:e,cost:"cheap",read:x=>{let k=x.rcHeave(e),F=x.rcRoll(e);return!k||!F?NaN:Math.min(...k.rc.map(w=>w.sinAngle),...F.rc.map(w=>w.sinAngle))},curve:x=>{let k=x.rcHeave(e);return k?{key:r("minSinAngle"),title:`${t} construction conditioning vs travel`,xLabel:"travel [mm]",yLabel:"sinAngle",x:k.at,y:k.rc.map(F=>F.sinAngle)}:null}},{id:r("fvsaLength"),group:`${t} roll centre`,label:"front-view swing-arm length",unit:"mm",scale:500,scope:e,cost:"readout",read: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 k=x.solveAt(e,0);return k?k.metrics.camber:NaN}},{id:r("staticToe"),group:`${t} camber & toe`,label:"static toe",unit:"\xB0",scale:.5,scope:e,cost:"cheap",read: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 k=n(x,F=>F.metrics.toe);return k.x.length?tA(k.x,k.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 k=n(x,F=>F.metrics.camber);return k.x.length?tA(k.x,k.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=>rc(n(x,k=>k.metrics.camber).y)},{id:r("toeSpan"),group:`${t} camber & toe`,label:"toe range over travel",unit:"\xB0",scale:.5,scope:e,cost:"cheap",read:x=>rc(n(x,k=>k.metrics.toe).y)},{id:r("camberRecovery"),group:`${t} camber & toe`,label:"outer camber at limit roll",unit:"\xB0",scale:2,scope:e,cost:"cheap",read:x=>{let k=x.solveAt(e,x.travelAtRoll(e,x.envelope.rollAtLimitDeg)),F=x.solveAt(e,0);return!k||!F?NaN:Math.abs(k.metrics.camber-F.metrics.camber+x.envelope.rollAtLimitDeg)}},{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 k=x.sweep(e);return k?nA(k.samples.map(F=>F.travel),k.samples.map(F=>F.metrics.motionRatio??NaN))??NaN:NaN},curve:x=>{if(c(x.car))return null;let k=n(x,F=>F.metrics.motionRatio??NaN);return k.x.length?{key:r("motionRatio"),title:`${t} motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",...k}:null}},{id:r("mrSpread"),group:`${t} rates`,label:"motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let k=x.sweep(e);if(!k)return NaN;let F=k.samples.map(C=>C.metrics.motionRatio??NaN).filter(Number.isFinite);if(!F.length)return NaN;let w=F.reduce((C,T)=>C+T,0)/F.length;return w>0?(Math.max(...F)-Math.min(...F))/w:NaN}},{id:r("wheelRate"),group:`${t} rates`,label:"wheel rate at design",unit:"N/mm",scale:10,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let k=x.sweep(e);return k?nA(k.samples.map(F=>F.travel),k.samples.map(F=>F.metrics.wheelRate??NaN))??NaN:NaN}},{id:r("heaveMotionRatio"),group:`${t} rates`,label:"heave element motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:u,read:x=>p(x)?.atDesign??NaN,curve:x=>{let k=p(x);return k?{key:r("heaveMotionRatio"),title:`${t} heave element motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",x:k.travel,y:k.ratio}:null}},{id:r("heaveMrSpread"),group:`${t} rates`,label:"heave element motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:u,read:x=>rA(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:ma(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 k=d(x);return k?{key:r("rollMotionRatio"),title:`${t} roll element motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",x:k.travel,y:k.ratio}:null}},{id:r("rollMrSpread"),group:`${t} rates`,label:"roll element motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:f,read:x=>rA(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:$n(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(tc)?.[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("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:rc(n(x,k=>k.metrics.damperLength).y),curve:x=>{if(c(x.car))return null;let k=n(x,F=>F.metrics.damperLength);return k.x.length?{key:r("damperStroke"),title:`${t} damper length vs travel`,xLabel:"travel [mm]",yLabel:"length [mm]",...k}:null}}];e==="front"&&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(tc)?.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(tc)?.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(tc)?.rear.antiLift??NaN});let M=x=>{let k=x.slice(t.length+1);return k.charAt(0).toUpperCase()+k.slice(1)};return[...new Set(R.map(x=>x.group))].flatMap(x=>R.filter(k=>k.group===x)).map(x=>({...x,quantity:`${t} \xB7 ${M(x.group)}`}))}function aA(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 W_=[{id:"kin.front.ackermannCentre",group:"Steering",label:"Ackermann near centre",unit:"%",scale:25,scope:"front",cost:"cheap",read:e=>aA(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=>aA(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}}],j_=[{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.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}}],zg=[...oA("front"),...oA("rear"),...W_,...j_];var sA={understeer:"operating",yawFreq:"speed",yawZeta:"speed",yawStiffness:"operating",steeringTorque:"operating",steeringTorqueGradient:"operating"};function rt(e,t,r,n="cheap"){let o=tb[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,...sA[e]?{reads:sA[e]}:{},read:(a,s)=>{let i=a.dynInput(),c=a.dynCtx(s);return i&&c?o.compute(i,c):NaN}}}var U_=[rt("understeer","Handling \u2014 balance",.1),rt("tlltdFront","Handling \u2014 balance",5),rt("rollStiffFront","Handling \u2014 balance",5)],X_=[rt("yawFreq","Handling \u2014 response",.5),rt("yawZeta","Handling \u2014 response",.2),rt("stabilitySpeed","Handling \u2014 response",50),rt("yawStiffness","Handling \u2014 response",2e4,"trim")],q_=[rt("steeringTorque","Steering feel",1,"trim"),rt("steeringTorqueGradient","Steering feel",2,"trim")],Q_=[rt("rollGradient","Ride & body",.5),rt("pitchGradient","Ride & body",.5),rt("rideFreqFront","Ride & body",.5),rt("rideFreqRear","Ride & body",.5),rt("rollFreq","Ride & body",.5),rt("pitchFreq","Ride & body",.5),rt("zetaFront","Ride & body",.2),rt("zetaRear","Ride & body",.2)],Z_=[{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}],J_=[{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}],Yg=[...U_,...X_,...q_,...Q_,...Z_,...J_];function eN(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 Wg=[{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)=>eN(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 tN(e,t){let r=/^(.*?)\s*\(([^)]+)\)\s*$/.exec(e);return r?{label:r[1],unit:r[2]}:{label:e,unit:t?"s":""}}function rN(e){return e==="s"||e==="kWh"?.1:e==="km/h"?2:1}var iA=new WeakMap;function Nm(e){let t=iA.get(e);return t||(t=e.metrics.filter(yc).map(r=>{let{label:n,unit:o}=tN(r.label,r.format==="time");return{id:`event.${e.id}.${r.key}`,group:`Events \xB7 ${e.label}`,groupShort:"Events",label:n,unit:o,scale:rN(o),scope:"car",cost:"session",read:a=>a.session(e.id)?.[r.key]??NaN}}),iA.set(e,t),t)}var jg=Fa.flatMap(Nm);var Om=[...zg,...Yg,...Wg,...jg],Ia=Object.fromEntries(Om.map(e=>[e.id,e]));var cA={all:Om,byId:Ia},lA=new WeakMap;function Gr(e=[]){if(e.length===0)return cA;let t=lA.get(e);if(t)return t;let r=Fb(e).filter(n=>!wa(n.id)).flatMap(Nm);return t=r.length?{all:[...Om,...r],byId:{...Ia,...Object.fromEntries(r.map(n=>[n.id,n]))}}:cA,lA.set(e,t),t}var nc=180/Math.PI,_a=Math.PI/180,oN=.2;function Vm(e,t){let r=H(t,e);return q(r[0]<0?jp(r):r)}var Bm=e=>({side:Math.atan2(e[2],e[0])*nc,plan:Math.atan2(e[1],e[0])*nc}),$m=(e,t)=>q([1,Math.tan(t*_a),Math.tan(e*_a)]),oc=e=>Math.abs(e[0])>=oN,Gm=(e,t)=>Math.atan(t/Math.max(e,1))*nc,Km=(e,t)=>Math.tan(t*_a)*Math.max(e,1);var hn=["side","plan","clock","len"],jt={uca:{fore:"ucaFront",aft:"ucaRear",ball:"uprightUpper"},lca:{fore:"lcaFront",aft:"lcaRear",ball:"uprightLower"}},ac={uca:"upper arm",lca:"lower arm"},aN=1,uA=(e,t)=>Vm(e[jt[t].fore],e[jt[t].aft]);function mA(e){let t=q(H(Wp,U(e,X(Wp,e))));return{e1:t,e2:ae(e,t)}}function Ug(e,t){let r=uA(e,t);if(!oc(r))return`the ${ac[t]}'s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it`;let n=jt[t],o=jr(e[n.ball],e[n.fore],r);return Math.hypot(...H(o,e[n.ball]))>=aN?null:`the ${ac[t]}'s ball joint sits on its own pivot axis, so the arm has no length to swing on`}function Kr(e,t){let r=jt[t],n=e[r.ball],o=uA(e,t),a=jr(n,e[r.fore],o),s=H(a,n),i=Math.hypot(s[0],s[1],s[2]),{e1:c,e2:l}=mA(o),u=i>0?U(s,1/i):c;return{...Bm(o),clock:Math.atan2(X(u,l),X(u,c))*nc,len:i,sFront:X(H(e[r.fore],a),o),sRear:X(H(e[r.aft],a),o)}}function Xg(e,t){let r=$m(e.side,e.plan),{e1:n,e2:o}=mA(r),a=ee(U(n,Math.cos(e.clock*_a)),U(o,Math.sin(e.clock*_a))),s=ee(t,U(a,e.len));return{fore:ee(s,U(r,e.sFront)),aft:ee(s,U(r,e.sRear))}}function pA(e,t,r,n){let o=jt[t],a={...Kr(e,t),[r]:n},{fore:s,aft:i}=Xg(a,e[o.ball]);return{...e,[o.fore]:s,[o.aft]:i}}function dA(e,t){return t==="clock"?e.len:Math.abs(e.sFront-e.sRear)/2}function Hm(e,t,r){return t==="len"?r:Gm(dA(e,t),r)}function qg(e,t,r){return t==="len"?r:Km(dA(e,t),r)}var io=["side","plan","atY","atZ"],co={fore:"rockerPivotA",aft:"rockerPivotB"},sN=5,fA=e=>Vm(e.rockerPivotA,e.rockerPivotB);function Na(e){return Math.hypot(...H(e.rockerPivotB,e.rockerPivotA))<sN?"the rocker\u2019s two pivots are the same point, so there is no axis to describe":oc(fA(e))?null:"the rocker\u2019s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it"}function bn(e){let t=fA(e),r=oc(t)?t:[1,0,0],n=e.rockerPivotA,o=ee(n,U(r,-n[0]/r[0]));return{...Bm(r),atY:o[1],atZ:o[2],sA:X(H(n,o),r),sB:X(H(e.rockerPivotB,o),r)}}function Qg(e){let t=$m(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 hA(e,t,r){if(Na(e))return e;let{a:n,b:o}=Qg({...bn(e),[t]:r});return{...e,rockerPivotA:n,rockerPivotB:o}}var bA=e=>Math.abs(e.sA-e.sB)/2;function Zg(e,t,r){return t==="side"||t==="plan"?Gm(bA(e),r):r}function Jg(e,t,r){return t==="side"||t==="plan"?Km(bA(e),r):r}var Xt={front:"Front",rear:"Rear"},Ut=["x","y","z"],Oe=(e,t)=>t==="front"?e.front:e.rear,sc=(e,t,r)=>t==="front"?{...e,front:r}:{...e,rear:r},gA=[{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"}]}],yA={damperChassis:"strut top mount",pushrodOuter:"strut lower mount"},lo=30;function iN(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).config.layout==="mcpherson";for(let o of gA)for(let{key:a,label:s}of o.keys){let i=n&&yA[a]||s;for(let c=0;c<3;c++)t.push({id:`hp.${r}.${a}.${Ut[c]}`,group:`${Xt[r]} hardpoints \u2014 ${o.kind}`,label:`${i} ${Ut[c]}`,scope:Xt[r],unit:"mm",defaultSpan:lo,read:l=>Oe(l.vehicle,r).hardpoints[a][c],write:(l,u)=>{let m=Oe(l.vehicle,r),f=[...m.hardpoints[a]];f[c]=u;let p={...m.hardpoints,[a]:f};return{...l,vehicle:sc(l.vehicle,r,{...m,hardpoints:p})}}})}}return t}var cN={side:"axis side-view angle",plan:"axis plan-view angle",clock:"arm clock angle",len:"effective arm length"},lN={side:"\xB0",plan:"\xB0",clock:"\xB0",len:"mm"};function uN(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).config.layout==="mcpherson";for(let o of["uca","lca"]){let a=Oe(e.vehicle,r).hardpoints,s=Ug(a,o)?null:Kr(a,o);for(let i of hn)t.push({id:`arm.${r}.${o}.${i}`,group:`${Xt[r]} ${n?"arm axes":"wishbone axes"}`,label:`${ac[o]} \u2014 ${cN[i]}`,scope:Xt[r],unit:lN[i],defaultSpan:s?Hm(s,i,lo):lo,read:c=>Kr(Oe(c.vehicle,r).hardpoints,o)[i],write:(c,l)=>{let u=Oe(c.vehicle,r),m=pA(u.hardpoints,o,i,l);return{...c,vehicle:sc(c.vehicle,r,{...u,hardpoints:m})}}})}}return t}var mN={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"},pN={side:"\xB0",plan:"\xB0",atY:"mm",atZ:"mm"};function dN(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).hardpoints,o=Na(n)?null:bn(n);for(let a of io)t.push({id:`rocker.${r}.${a}`,group:`${Xt[r]} rocker axis`,label:`rocker \u2014 ${mN[a]}`,scope:Xt[r],unit:pN[a],defaultSpan:o?Zg(o,a,lo):lo,read:s=>bn(Oe(s.vehicle,r).hardpoints)[a],write:(s,i)=>{let c=Oe(s.vehicle,r),l=hA(c.hardpoints,a,i);return{...s,vehicle:sc(s.vehicle,r,{...c,hardpoints:l})}}})}return t}var zm={front:"heaveFrontDesign",rear:"heaveRearDesign"},e0={front:"arbFrontDesign",rear:"arbRearDesign"};function fN(e,t){return{heave:e.config.actuation==="decoupled"?"heave element":"third spring",roll:t?.design.kind==="coil"?"roll shock":"anti-roll bar"}}var Ym=e=>/^(heave|roll)\.(front|rear)\.(outer|inner|anchor)\.[xyz]$/.test(e);function hN(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r),o=e.params[zm[r]],a=e.params[e0[r]],s=fN(n,a),i=d=>d.params[zm[r]],c=d=>d.params[e0[r]],l=(d,h)=>({...d,params:{...d.params,[zm[r]]:h}}),u=(d,h)=>({...d,params:{...d.params,[e0[r]]:h}}),m={group:`${Xt[r]} heave & roll elements`,scope:Xt[r]},f=(d,h,b,g,y)=>{for(let R of b)t.push({...m,id:`${d}.${Ut[R]}`,label:`${h} ${Ut[R]}`,unit:"mm",defaultSpan:lo,read:M=>g(M)[R],write:(M,v)=>{let x=[...g(M)];return x[R]=v,y(M,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=Qr(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,M)=>u(R,{...c(R),linkage:{...h(R),outer:M}})),f(`roll.${r}.inner`,`${s.roll} ${y}`,[0,1,2],R=>h(R).inner,(R,M)=>u(R,{...c(R),linkage:{...h(R),inner:M}}))}let d=a.design;if(d.kind==="coil"&&typeof d.rate=="number"){let h=b=>c(b).design;p(`roll.${r}.rate`,`${s.roll} spring rate (@element)`,d.rate,b=>h(b).rate,(b,g)=>u(b,{...c(b),design:{kind:"coil",rate:g}}))}else d.kind==="direct"&&p(`roll.${r}.wheelRate`,`${s.roll} rate (@wheel)`,d.wheelRate,h=>c(h).design.wheelRate,(h,b)=>u(h,{...c(h),design:{kind:"direct",wheelRate:b}}))}}return t}var bN=[{axle:"front",field:"springRate",group:"Springs & bars",label:"spring rate (@spring)",unit:"N/mm",fallback:35,span:e=>Math.max(5,e*.4)},{axle:"rear",field:"springRate",group:"Springs & bars",label:"spring rate (@spring)",unit:"N/mm",fallback:40,span:e=>Math.max(5,e*.4)},{axle:"front",field:"rackTravel",group:"Steering",label:"rack travel from centre",unit:"mm",fallback:35,span:()=>15,frontOnly:!0},{axle:"front",field:"rackRatio",group:"Steering",label:"rack per steering-wheel turn",unit:"mm/rev",fallback:55,span:()=>15,frontOnly:!0},{axle:"front",field:"loadedRadius",group:"Wheel & tyre",label:"loaded radius",unit:"mm",fallback:228,span:()=>15},{axle:"rear",field:"loadedRadius",group:"Wheel & tyre",label:"loaded radius",unit:"mm",fallback:228,span:()=>15}];function gN(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).compliance;if(!n)continue;let o=(a,s,i,c)=>{let l=i(n);l===void 0||!(l>0)||!Number.isFinite(l)||t.push({id:`kc.${r}.${a}`,group:"Compliance",label:s,scope:Xt[r],unit:"N/mm",defaultSpan:Math.max(500,l*.4),read:u=>i(Oe(u.vehicle,r).compliance??{})??l,write:(u,m)=>{let f=Oe(u.vehicle,r),p={...f,compliance:c(f.compliance??{},Math.max(1,m))};return{...u,vehicle:sc(u.vehicle,r,p)}}})};for(let a of["ucaFront","ucaRear","lcaFront","lcaRear","tieRod","pushRod"])o(`link.${a}`,`${yN[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}`,`${xN[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 yN={ucaFront:"UCA front leg",ucaRear:"UCA rear leg",lcaFront:"LCA front leg",lcaRear:"LCA rear leg",tieRod:"tie rod",pushRod:"push/pull rod"},xN={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 RN(){return bN.map(e=>({id:`cfg.${e.axle}.${e.field}`,group:e.group,label:e.label,scope:Xt[e.axle],unit:e.unit,defaultSpan:e.span(e.fallback),read:t=>Oe(t.vehicle,e.axle).config[e.field]??e.fallback,write:(t,r)=>{let n=Oe(t.vehicle,e.axle),o={...n,config:{...n.config,[e.field]:r}};return{...t,vehicle:sc(t.vehicle,e.axle,o)}}}))}function vN(e){let t=Cn(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=>Cn(c.params.steeringSystem)[n],write:(c,l)=>({...c,params:{...c.params,steeringSystem:Cn({...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 kN(e){let t=ai(e.params),r=[];for(let n of["front","rear"]){if(t[n]!=="diff")continue;let o=Kn(e.params.driveline?.[n]);if(o?.kind!=="clutch"&&o?.kind!=="torsen")continue;let a=(s,i)=>{let c=uu[`${n}.${s}`];return{id:`driveline.${n}.${s}`,group:"Differential",label:c.label.charAt(0).toLowerCase()+c.label.slice(1),scope:Xt[n],unit:c.unit===": 1"?"":c.unit??"",defaultSpan:i,read:l=>Kn(l.params.driveline?.[n])?.[s],write:(l,u)=>({...l,params:{...l.params,driveline:lu({...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 MN(e){if(Dl(e.params)!=="hydraulic")return[];let t=[{id:"brakeSetup.barFront",group:"Brakes",label:`${qf("barFront").toLowerCase()}, front share`,unit:"-",defaultSpan:.05,read:a=>Ar(a.params.brakeSetup).barFront,write:(a,s)=>({...a,params:{...a.params,brakeSetup:Ar({...Ar(a.params.brakeSetup),barFront:s})}})}];if(!e.params.brakeModel)return t;let r=tr(e.params.brakeModel),n=(a,s)=>s.circuit?a[s.circuit][s.key]:a[s.key],o=(a,s,i)=>({id:`brakeModel.${a.circuit?`${a.circuit}.`:""}${String(a.key)}`,group:"Brakes",label:Xf(a.circuit?`${a.circuit}.${String(a.key)}`:a.key),unit:s,defaultSpan:i,read:c=>n(tr(c.params.brakeModel),a),write:(c,l)=>{let u=tr(c.params.brakeModel),m=a.circuit?{...u,[a.circuit]:{...u[a.circuit],[a.key]:l}}:{...u,[a.key]:l};return{...c,params:{...c.params,brakeModel:tr(m)}}}});return t.push(o({key:"masterFrontMm"},"mm",1.5),o({key:"masterRearMm"},"mm",1.5),o({key:"pedalRatio"},"-",.5),o({key:"pistonDiaMm",circuit:"front"},"mm",2),o({key:"pistonDiaMm",circuit:"rear"},"mm",2),o({key:"effRadiusMm",circuit:"front"},"mm",10),o({key:"effRadiusMm",circuit:"rear"},"mm",10)),r.valve!=="none"&&t.push(o({key:"valveKneeBar"},"bar",5)),r.valve==="proportioning"&&t.push(o({key:"valveSlope"},"-",.1)),t}var xA=e=>!!e&&typeof e=="object"&&"value"in e&&"label"in e;function RA(e){let t={...e};for(let r of Object.keys(t)){let n=t[r];xA(n)&&(t[r]={...n})}return t}function SN(e){let t=[];for(let r of X1(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 xA(s)?s.value:NaN},write:(a,s)=>{let i=RA(a.params);return hu(i,n.label,s),{...a,params:i}}})}return t}function vA(e){let t={};for(let s of["front","rear"]){if(!Oe(e.vehicle,s).measured)continue;let c="this axle is described by measured curves, so its linkage is not solved";for(let l of gA)for(let{key:u}of l.keys)for(let m of Ut)t[`hp.${s}.${u}.${m}`]={why:c};for(let l of["uca","lca"])for(let u of hn)t[`arm.${s}.${l}.${u}`]={why:c};for(let l of io)t[`rocker.${s}.${l}`]={why:c};for(let l of["heave.outer","heave.anchor","roll.outer","roll.inner"]){let[u,m]=l.split(".");for(let f of Ut)t[`${u}.${s}.${m}.${f}`]={why:c}}t[`cfg.${s}.springRate`]={why:"the measured curve set carries its own spring rate"}}let r=["rockerPivotA","rockerPivotB","rockerToPushrod","rockerToDamper"];for(let s of["front","rear"]){if(Oe(e.vehicle,s).config.actuation!=="direct")continue;let i="this axle is direct-acting \u2014 there is no bell-crank";for(let c of r)for(let l of Ut)t[`hp.${s}.${c}.${l}`]={why:i};for(let c of io)t[`rocker.${s}.${c}`]={why:i}}for(let s of["front","rear"]){let i=Oe(e.vehicle,s);if(i.measured||i.config.actuation!=="decoupled")continue;let c="this axle is decoupled \u2014 the corner damper is out of circuit";for(let l of["rockerToDamper","damperChassis"])for(let u of Ut)t[`hp.${s}.${l}.${u}`]={why:c,useInstead:`heave.${s}.outer.${u}`};t[`cfg.${s}.springRate`]={why:"a decoupled axle has no corner spring \u2014 its elements hold it up",useInstead:`heave.${s}.rate`}}for(let s of["front","rear"]){let i=Oe(e.vehicle,s),c=e.params[zm[s]]?.linkage;if(i.measured||!c||c.attach!=="rocker"||c.mount?.kind==="chassis")continue;let l=i.hardpoints,u=[0,1,2].map(f=>l.rockerPivotB[f]-l.rockerPivotA[f]),m=Math.hypot(u[0],u[1],u[2]);if(m>0)for(let f=0;f<3;f++)Math.abs(u[f]/m)<1-1e-12||(t[`heave.${s}.outer.${Ut[f]}`]={why:`the rocker shaft runs along ${Ut[f]} \u2014 this only slides the eye along it`})}for(let s of["front","rear"]){let i=Oe(e.vehicle,s);if(i.measured||i.config.layout!=="mcpherson")continue;let c="this axle is a McPherson strut \u2014 there is no upper arm";for(let l of["ucaFront","ucaRear","uprightUpper"])for(let u of Ut)t[`hp.${s}.${l}.${u}`]={why:c,useInstead:`hp.${s}.damperChassis.${u}`};for(let l of hn)t[`arm.${s}.uca.${l}`]={why:c};for(let l of["link.ucaFront","link.ucaRear","bush.ucaFront","bush.ucaRear"])t[`kc.${s}.${l}`]={why:c}}for(let s of["front","rear"]){let i=Oe(e.vehicle,s);if(i.measured)continue;for(let l of["uca","lca"]){if(l==="uca"&&i.config.layout==="mcpherson")continue;let u=Ug(i.hardpoints,l);if(u)for(let m of hn)t[`arm.${s}.${l}.${m}`]={why:u,useInstead:`hp.${s}.${jt[l].fore}.z`}}let c=Na(i.hardpoints);if(c&&i.config.actuation!=="direct")for(let l of io)t[`rocker.${s}.${l}`]={why:c,useInstead:`hp.${s}.${co.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?Oh:Vh;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(pu))t[`param.${s}`]={why:i};for(let[s,i]of Object.entries(du(e.params)))t[`param.${s}`]={why:i};let a=Dl(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 kA(e){let t={...FN,...vA(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[...iN(e),...uN(e),...dN(e),...hN(e),...RN(),...vN(e),...MN(e),...kN(e),...gN(e),...SN(e.params)].map(r)}var AN={spring_front:"cfg.front.springRate",spring_rear:"cfg.rear.springRate"},FN=Object.fromEntries(Object.entries(Nh).map(([e,t])=>[`param.${e}`,{why:t,useInstead:AN[e]}])),st=e=>e.scope?`${e.scope} \xB7 ${e.label}`:e.label;function $t(e){let t={};for(let n of kA(e))t[n.id]=n;let r=(n,o)=>{if(typeof o!="string")return;let a=eA(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 t0=e=>e.step!==void 0&&Number.isFinite(e.step)&&e.step>0?e.step:0,r0=e=>t0(e)>0||(e.values?.length??0)>0,n0=e=>e.some(r0),MA=e=>1e-9*Math.max(1,Math.abs(e.lo),Math.abs(e.hi));function SA(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=t0(e);if(!r||!Number.isFinite(e.start))return t;let n=MA(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 AA=(e,t)=>t.map((r,n)=>e[n]&&r0(e[n])?SA(e[n],r):r);function o0(e,t=1e3){if(e.values?.length)return e.values.length;let r=t0(e);if(!r||!Number.isFinite(e.start))return 1/0;let n=MA(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 a0(e,t,r){let n=AA(e.variables,t),o=n.every((a,s)=>a===t[s]);return{x:n,score:o?r:vr(e,n)}}function l0(e,t){if(!e.variables.some(wA))return e;let r=e.variables.filter(o=>o.follows&&!o.fixed).map(o=>({id:o.id,follows:o.follows})),n=e.variables.filter(o=>!o.fixed&&!o.follows).map(o=>{if(CA(o))return{...o,lo:Math.min(...o.values),hi:Math.max(...o.values)};if(!o.around)return o;let{around:a,fixed:s,...i}=o,c=t(o.id);return Number.isFinite(c)?{...i,lo:c-a.minus,hi:c+a.plus}:i});return r.length?{...e,variables:n,followers:r}:{...e,variables:n}}var wA=e=>!!(e.fixed||e.around||e.follows)||CA(e),CA=e=>!!e.values?.length&&(e.lo!==Math.min(...e.values)||e.hi!==Math.max(...e.values));function Lt(e,t){if(!t.variables.some(wA))return t;let r=$t(e);return l0(t,n=>{let o=r[n];if(!o)return NaN;try{return o.read(e)}catch{return NaN}})}function uo(e){return[...e.objectives,...e.constraints,...e.watches??[]]}var u0=e=>(e.metrics??Gr()).byId;function m0(e,t){t=Lt(e,t);let r=$t(e),n=[];for(let o of t.variables){let a=r[o.id];a&&n.push({id:a.id,name:st(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 Wm(e,t,r){t=Lt(e,t);let n=$t(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]))}),p0(e,o,t.followers,n)}function p0(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 ic(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 TA=(e,t="")=>t&&t!=="-"?`${e} ${t}`:`${e}`;function PA(e,t,r){let n=t??Ia[e.metricId],o=(n?Rt(n):e.metricId)+cc(e.at,n,r),a=s=>TA(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 cc(e,t,r){if(!e)return"";let n=[];if(e.speed!==void 0&&Kg(t)&&n.push(`${(e.speed*3.6).toFixed(0)} km/h`),e.ayG!==void 0&&Hg(t)&&n.push(`${e.ayG.toFixed(2)} g`),e.courseId==="*"&&t?.reads==="course")n.push(Gg(t));else if(e.courseId&&t?.reads==="course"){let o=r?.lap.courses.find(a=>a.id===e.courseId);o&&n.push(Sg(o))}return n.length?` @ ${n.join(", ")}`:""}function LA(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 DA=5e-4;function EA(e,t){return e.cost!=="lap"&&e.cost!=="session"?0:Number.isFinite(t)?DA*Math.abs(t):0}function jm(e,t,r={}){t=Lt(e,t);let n=m0(e,t),o=$t(e),a=u0(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=Wt(f,b,h.at);if(!Number.isFinite(g))return{ok:!1,violation:f.failure?.violation??400,reason:f.failure?.reason??`${Rt(b)} could not be computed`};let y=ic(h,g);y>0&&(p+=y/b.scale,d.push(`${PA(h,b,t)} (${TA(g.toFixed(3),b.unit)})`))}return d.length===0?Ms:{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=p0(e,f,t.followers,o),{car:f,ev:Ea(f,{density:t.density,envelope:t.envelope,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)Wt(m,d,p.at);for(let{spec:p,metric:d}of l)Wt(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=Wt(m,p,f.at);return{name:Rt(p)+cc(f.at,p,t),raw:d,unit:p.unit,weight:f.weight,contribution:LA(f,p,d),resolution:Math.abs(f.weight)*EA(p,d)/p.scale}})}}function s0(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 IA(e,t){if(e.variables.some(o=>o.id===t))return!0;let r=ec(t);if(!r||!_m.includes(r.axis))return!1;if(e.variables.some(o=>pr(o.id)?.point===r.point))return!0;let n=s0(t);return!!n&&e.variables.some(o=>/^(arm|rocker)\./.test(o.id)&&s0(o.id)===n)}function wN(e,t){let r=e.followers??[],n=new Map(r.map(i=>[i.id,i.follows])),o=i=>{let c=t[i],l=ec(i);return c&&l&&_m.includes(l.axis)?{name:st({...c,label:c.label.replace(/ [xyz]$/,"")}),axis:l.axis}:{name:c?st(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 IA(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 d0(e,t,r={}){let n=t.variables.length>0&&t.variables.every(g=>g.fixed||g.follows),o=t.variables.some(g=>g.follows&&!g.fixed);t=Lt(e,t);let a=$t(e),s=[],i=u0(r),c=uo(t).map(g=>g.metricId),l=c.some(g=>g.startsWith("dyn.")),u=c.some(g=>g.startsWith("lap."));if(c.some(g=>g.startsWith("kin."))){let g=t.envelope;g.travelMin<0&&g.travelMax>0||s.push("The travel the linkage is read over must reach both ways from the design ride: droop below zero, bump above."),(!(g.rollMaxDeg>0)||!(g.rollAtLimitDeg>=0))&&s.push("The roll the linkage is read over must be 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(g=>g.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 g of t.lap.courses)g.course.kind==="track"&&!r.libraryTrack?.(g.course.trackId)&&s.push(`This study drives ${g.course.name}, which is not in the project\u2019s tracks, or has not loaded yet.`);let m=new Set([...t.lap.courses.map(g=>g.id),"*"]);for(let g of uo(t))if(g.at?.courseId&&!m.has(g.at.courseId)){let y=i[g.metricId];s.push(`${y?Rt(y):g.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(y=>/arb_|spring|heave_|front_mass_diss|cg_height|^hp\./.test(y.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 g of t.variables){let y=a[g.id];if(!y){s.push(`\u201C${g.id}\u201D is not a variable this car has.`);continue}if(g.values&&g.values.length<2?s.push(`${st(y)}: list two values or more, or fix it where it is.`):g.hi>g.lo?g.step!==void 0&&o0({...g,start:y.read(e)})<2&&s.push(`${st(y)}: a step of ${g.step} ${y.unit} leaves no other place to land in its box. Make the step finer or the box wider, or fix it.`):s.push(`${st(y)}: the upper bound must be above the lower one (${g.lo} to ${g.hi}).`),y.supersededBy){let M=y.supersededBy.useInstead?a[y.supersededBy.useInstead]:void 0,v=M?st(M):void 0;s.push(`${st(y)} cannot be searched: ${y.supersededBy.why}.`+(v?` Use ${v} instead.`:""))}let R=y.read(e);Number.isFinite(R)&&(R<g.lo||R>g.hi)&&s.push(`${st(y)} starts at ${R.toFixed(1)} ${y.unit}, outside its own bounds.`)}let f=t.followers??[],p=new Map;for(let g of[...t.variables.map(y=>y.id),...f.map(y=>y.id)]){let y=s0(g);if(!y)continue;let R=p.get(y);R||p.set(y,R={arms:[],coords:[]}),(/^(arm|rocker)\./.test(g)?R.arms:R.coords).push(g)}for(let[g,y]of p){if(y.arms.length===0||y.coords.length===0)continue;let R=v=>a[v]?st(a[v]):v,M=g.endsWith("rocker")?"rocker":`${g.endsWith("uca")?"upper":"lower"} arm`;s.push(`${g.startsWith("front")?"The front":"The rear"} ${M} is being moved two ways at once \u2014 as an axis (${y.arms.map(R).join(", ")}) and as pivot coordinates (${y.coords.map(R).join(", ")}). They describe the same ${M}, so whichever is applied second overwrites the other. Keep one.`)}let d=new Map,h=new Set(f.map(g=>g.id));for(let g of[...t.variables.map(y=>y.id),...h]){let y=ec(g);if(!y)continue;let R=pr(g),M=h.has(g)?"with":R?`${R.shape.kind}:${g.slice(g.lastIndexOf(".")+1).replace(/[uv]$/,"")}`:"axes",v=d.get(y.point);v||d.set(y.point,v=new Set),v.add(M)}for(let[g,y]of d){if(y.size<2||y.size===2&&y.has("axes")&&y.has("with"))continue;let R=[...y].map(F=>F.split(":")[0]),M=F=>R.filter(w=>w===F).length,v=[M("axes")?"in its axes":"",M("line")===1?"along a line":M("line")>1?"along two lines":"",M("plane")===1?"in a plane":M("plane")>1?"in two planes":"",M("with")?"with another point":""].filter(Boolean),x=a[`${g}.x`],k=x?st({...x,label:x.label.replace(/ x$/,"")}):g;s.push(`${k} is moved more than one way at once \u2014 ${v.join(" and ")}. Each write moves it off the other's, so keep one.`)}s.push(...wN(t,a));for(let g of t.constraints){let y=i[g.metricId];if(!y){s.push(`\u201C${g.metricId}\u201D is not a metric.`);continue}g.op==="band"&&!((g.limit2??g.limit)>g.limit)&&s.push(`${Rt(y)}: 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 g of uo(t))if(g.at?.speed!==void 0&&!(g.at.speed>0)){let y=i[g.metricId];s.push(`${y?Rt(y):g.metricId} is asked for at rest, where a yaw-moment diagram is degenerate.`)}for(let g of t.watches??[])i[g.metricId]||s.push(`\u201C${g.metricId}\u201D is not a metric.`);let b=new Set;for(let g of uo(t)){let y=i[g.metricId],R=y?.unavailable?.(e);!y||!R||b.has(y.id)||(b.add(y.id),s.push(`${Rt(y)} cannot be read on this car: ${R}.`))}for(let g of t.objectives)i[g.metricId]?g.weight>0?g.goal==="target"&&!Number.isFinite(g.target)?s.push(`${Rt(i[g.metricId])}: \u201Chit a value\u201D needs a value.`):g.goal==="target"&&g.tolerance!==void 0&&!(g.tolerance>=0)&&s.push(`${Rt(i[g.metricId])}: the tolerance must be zero or more.`):s.push(`${Rt(i[g.metricId])}: weight must be positive.`):s.push(`\u201C${g.metricId}\u201D is not a metric.`);return s}var _A=.1,NA=2e3,i0=3;function f0(e,t,r={},n=NA){t=Lt(e,t);let o=jm(e,t,r),a=u0(r),s=$t(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}@${so(L.at)}`]=Wt(S.ev,D,L.at))}return P},p=S=>m.map(A=>S[`${A.metricId}@${so(A.at)}`]).map(A=>Number.isFinite(A)?A.toFixed(9):"x").join("|"),d=f(l,uo(t)),h=p(d),b=[],g=[],y={},R=[],M=0;t.variables.forEach((S,A)=>{let P=s[S.id];if(!P)return;if(R.length>=i0&&M>n){g.push(P);return}let L=[...i];L[A]=i[A]+(S.hi-i[A])*.25||S.hi;let D=performance.now(),I=c(L),G=performance.now()-D;M+=G,R.push(G);let O=f(I);y[P.id]=O,p(O)===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<i0;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 k=[...R].sort((S,A)=>S-A),F=k.length?k[k.length>>1]:0,w=[],C=uo(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?Zr(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>=_A?w.push(`Over ${P} % of this course, some wheel is asked for more longitudinal force than its own tyre ellipse allows \u2014 the speed profile and the per-wheel reconstruction disagree that far. A reserve read there is the two models disagreeing rather than the car having nothing left, and a search pointed at one will optimise the disagreement. It concentrates in high-speed braking, so a shorter straight into the first corner is the usual cure.`):A>0&&w.push(`${P} % of this course is beyond the per-wheel tyre ellipse, which is the usual level of disagreement between the speed profile and the reconstruction. Reserves are readable; treat small differences between designs as smaller than they look.`)}}return{msPerEval:F,values:d,samples: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 TN=[{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:PN.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 PN=["setup:m","characteristics:peak_power","characteristics:power_to_weight","characteristics:cla","characteristics:cda","characteristics:pack_energy","characteristics:maxAy","characteristics:top_speed"];var Voe=new Set(TN.map(e=>e.kind));var OA={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 h0=["FL","FR","RL","RR"],vt=(e,t,r)=>({input:e,from:r?r[0]:OA[e].from,to:r?r[1]:OA[e].to,n:t}),Koe=[{id:"sides",name:"Inside and outside",cards:[{id:"camber-roll",form:"curves",title:"Camber to the road through roll",sweep:vt("roll",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"toe-rack",form:"curves",title:"Wheel angle against the rack",sweep:vt("steer",25),wheels:["FL","FR"],y:["toe"]},{id:"camber-rack",form:"curves",title:"Camber to the road through the steer",sweep:vt("steer",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"load-roll",form:"curves",title:"Wheel loads through roll",sweep:vt("roll",25),wheels:h0,y:["wheelLoad"]},{id:"travel-roll",form:"curves",title:"Wheel travel through roll",sweep:vt("roll",25),wheels:h0,y:["travel"]},{id:"toe-roll",form:"curves",title:"Roll steer, all four",sweep:vt("roll",25),wheels:h0,y:["toe"]}]},{id:"maps",name:"Travel and steer together",cards:[{id:"camber-map",form:"surface",title:"Camber over travel and rack",sweep:vt("travel",17),second:vt("steer",13),wheels:["FL"],y:["camber"]},{id:"bump-steer-map",form:"map",title:"Bump steer over travel and rack",sweep:vt("travel",17),second:vt("steer",13),wheels:["FL"],y:["bumpSteer"]},{id:"bump-steer-family",form:"curves",title:"Bump steer through travel, at five rack positions",sweep:vt("travel",25),second:vt("steer",5,[-20,20]),wheels:["FL"],y:["bumpSteer"]},{id:"scrub-map",form:"surface",title:"Scrub radius over travel and rack",sweep:vt("travel",17),second:vt("steer",13),wheels:["FL"],y:["scrubRadius"]}]}];function b0(e){let t=Number(e);return Number.isFinite(t)?Math.min(xf,Math.max(yf,t)):St}var BA=6e4;var _ae=[{within:60*6e4,every:BA},{within:1440*6e4,every:60*6e4},{within:720*60*6e4,every:1440*6e4},{within:1/0,every:10080*6e4}];var GN=new Set(["color","visible","source","origin"]),Wae=["id",...GN];var KA=.18/1.18,HA={induction:{kind:"natural"}},zA=e=>e.breathing??HA;function Um(e){switch(e?.kind){case"sae-j1349":return Ei(99e3,25);case"measured":return Ei(e.hPa*100,e.tempC);default:return Ei(101325,20)}}var HN=Um(void 0);function YA(e,t){let r=Um(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 WA(e,t){let r=e.induction;if(r.kind==="table"){let o=s=>Be(r.densityAltitudeM,r.powerPct,s),a=o(Um(e.rated).densityAltitudeM);return a>0?Math.max(0,o(t.densityAltitudeM)/a):0}let n=e.frictionShare??KA;return Math.max(0,(YA(e,t)-n)/(1-n))}var GA=new WeakMap;function y0(e,t){let r=e.asRated??e,n=`${t.p}|${t.pDry}|${t.T}`,o=GA.get(r);o||GA.set(r,o=new Map);let a=o.get(n);if(a)return a;let s=WA(zA(r),t),i={...r,torque:r.torque.map(c=>c*s),asRated:r};return o.set(n,i),i}function jN(e){return JSON.parse(x0(R0(e,"public/laptime/index.json"),"utf8")).tracks}var UN=async e=>{let t=await fetch(e.url);if(!t.ok)throw new Error(`The track could not be read from ${fm(e)} (${t.status}).`);return new Uint8Array(await t.arrayBuffer())};function jA(e,t=new Map,r=UN){let n=jN(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(!Gi(o.address))throw new Error(`"${o.address}" is not a catalogue address`);if(!$i(o.link))throw new Error("This track is linked to a source this version does not read from.");i=await sg(await r(o.link),o.link,o.address)}else if(o.kind==="catalogue"){if(!Gi(o.address))throw new Error(`"${o.address}" is not a catalogue address`);let c=JSON.parse(x0(R0(e,"public/catalogue",cg(o.address)),"utf8"));i=await ug(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(x0(R0(e,"public/laptime",c),"utf8"))}return t.set(a,i),structuredClone(i)}}var XN=9.81;function UA(e,t=e.tireModel,r=e.tireModelRear){if(!t)return e;let n=e.m.value*XN/4,o=da(e,t,r),a=Ie(o.front).rollingRadius(n),s=o.rear===o.front?a:Ie(o.rear).rollingRadius(n),i=qN(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 qN(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 QN=1e-6;function XA(e,t,r){let n=e.cgReference;if(!n||!e.cg_height)return e;let o=G1(e,t,r);if(o===void 0||Math.abs(o-n.standingRadius)<QN)return e;let a=n.typed??e.cg_height.value;return{...e,cg_height:{...e.cg_height,value:pa(e.cg_height.value,n.standingRadius,o)},cgReference:{...n,standingRadius:o,typed:a}}}function qA(e,t,r){let n=e.rcRoad,o=e.rc_front,a=e.rc_rear;if(!n||!o||!a)return e;let s=cu(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 QA=e=>({brakeFade:e.brakeFade,airTempC:e.airTempC,diffYaw:e.diffYaw,...Ii(e.air)?{air:e.air}:{}});var mo=(e,t)=>t?e.find(r=>r.id===t)?.model:void 0;function po(e){return{tire:t=>mo(e.tires,t),motor:t=>mo(e.motors,t),aero:t=>mo(e.aeros,t),battery:t=>mo(e.batteries,t),brake:t=>mo(e.brakes??[],t),damper:t=>mo(e.dampers??[],t),suspensionOf:t=>Im(v0(e,t),t)}}function v0(e,t){let r=mo(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 k0(I1(t.suspensionOf(e),e,n),t,r)}function ZN(e){return Ii(e.air)?ZM(e.air,e.airTempC??St):void 0}var JN="the air the session states, at its venue";function eO(e,t){return t?{...e,rho:{...e.rho,value:t.rho},readouts:{...e.readouts,rho:JN}}:e}function tO(e,t,r){if(!r)return{rho:e.rho,motorModel:t,readouts:e.readouts};let{rho:n,readouts:o}=eO(e,r);return{rho:n,motorModel:t&&mt(t)?y0(t,r):t,air:r,readouts:o}}function k0(e,t,r){let n=t.tire(e.tireModelId),o=t.tire(e.tireModelIdRear),a=qA(XA(UA(Y1(K1(J1(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}=tO(a,t.motor(e.motorModelId),ZN(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),...qs(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 aO=e=>e!==!1,sO=(e,t,r)=>r&&t>0?(e%t+t)%t:Math.min(Math.max(e,0),t);function iO(e,t,r){let n=e.points.filter(o=>Number.isFinite(o.at)&&Number.isFinite(o.z)).map(o=>({...o,at:sO(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 cO(e,t,r){let n=iO(e,t,r),o=n.length;if(o===0)return[];let a=p=>p<o-1?n[p+1].at-n[p].at:r?n[0].at+t-n[p].at:1/0,s=p=>p<o-1?(n[p+1].z-n[p].z)/a(p):r&&o>1?(n[0].z-n[p].z)/a(p):0,i=n.map(p=>Math.max(0,Number.isFinite(p.curve)?p.curve:0)/2),c=(p,d,h)=>i[p]+i[d]>h?h*i[p]/(i[p]+i[d]):i[p],l=p=>p<o-1||r?c(p,p<o-1?p+1:0,a(p)):Math.max(0,t-n[p].at),u=p=>p>0?c(p,p-1,a(p-1)):r?c(p,o-1,a(o-1)):n[p].at,m=p=>p>0?s(p-1):r&&o>1?s(o-1):n[p].at<=1e-9?s(p):0,f=p=>!r&&p===o-1&&o>1&&n[p].at>=t-1e-9?s(p-1):s(p);return n.map((p,d)=>{let h=l(d),b=u(d),g=Math.min(i[d],h,b),y=!r&&g<i[d]&&(d===o-1&&g===h||d===0&&g===b);return{at:p.at,z:p.z,gIn:m(d),gOut:f(d),half:g,asked:i[d],atEnd:y}})}function lO(e,t,r,n){let o=t-e.at;return n&&r>0?o-r*Math.round(o/r):o}function uO(e,t,r,n){for(let s of e){let i=lO(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 ZA(e,t,r,n){let o=aO(n),a=cO(e,r,o);return a.length?t.map(s=>uO(a,s,r,o)):t.map(()=>0)}function lc(e,t){if(!t?.points.length)return e;let r=Wi(e),{zSmoothing:n,...o}=e;return{...o,z:ZA(t,r,Rg(e),e.closed)}}var Xm={widthLeft:1.5,widthRight:1.5,bank:0,mu:1};function JA(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 uc(e,t){let r=JA(e.source);return eF(e,r?await t(r):void 0)}function eF(e,t){let{source:r}=e;if(r.kind==="segments"){let{segments:i,closed:c,spacing:l}=r,{asset:u}=Ui(i,{name:e.name,closed:c,spacing:l,base:Xm});return lc(u,r.profile)}let n=r.sections??[];if(r.kind==="inline")return lc(Rm(r.asset,n,Xm),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 lc(Rm({...t,...o!==void 0?{widthLeft:o}:{},...a!==void 0?{widthRight:a}:{},...s!==void 0?{closed:s}:{}},n,Xm),r.profile)}var vce=1/500;var kce=5*Math.PI/180;var Lce=1/3;var fO=[4,2,1,.5,.25,.125];function tF(e,t,r={}){let n=[...r.steps??fO].sort((g,y)=>y-g),o=at(r.numerics),a=r.tolPct??.5,s=Ft(e),i=e.ggvMode??"twoTrack",c=ir(s,!1,i),l={...o,dsTarget:n[0]??o.dsTarget},u=n.length?jn(s,c,[yt(t,l)],l,i):void 0,m=un(s,c.rows),f=n.map((g,y)=>{let R={...o,dsTarget:g},M=Date.now(),v=yt(t,R),x=gt(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()-M}}),p=f[f.length-1]?.lapTime??NaN,d=f.map(g=>{let y=g.lapTime-p;return{...g,delta:y,deltaPct:p?100*y/p:NaN}}),h=d.filter(g=>Math.abs(g.deltaPct)<=a),b=h.length?Math.max(...h.map(g=>g.dsTarget)):null;return{points:d,reference:p,recommended:b,tolPct:a}}function Oa(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:b0(t.airTempC??r.airTempC),...Ii(am(t.air??r.air))?{air:am(t.air??r.air)}:{},diffYaw:t.diffYaw??r.diffYaw,racingLine:t.racingLine??r.useRacingLine,standingStart:t.standingStart??(a?a.standingStart===!0:r.standingStart),lapCounts:t.lapCounts??r.lapCounts,numerics:at(r.numerics)}}async function qm(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 uc(r,t)}}function gO(e,t){let r=structuredClone(e);for(let[n,o]of Object.entries(t))if(!hu(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 M0=(e,t)=>{let r=e?.name;return typeof r=="string"&&r?r:t};function yO(e,t){let r={};for(let n of dn){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:M0(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:M0(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:M0(i.model,i.id),byFallback:!0}:null;continue}r[n.doc]=null}return r}function xO(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 rF(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 nF=e=>e.length<2?e[0]??"":`${e.slice(0,-1).join(", ")} and ${e[e.length-1]}`;async function Qm(e,t,r={}){let n=Oa(e,r.settings),{entry:o,asset:a}=await qm(e,t),s=po(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]?gO(d.params,r.overrides[d.id]):d.params;return fo(structuredClone(h),s,n)}),l=wi(Zn(e.meta.rulesetId,e.rulesets)),u=Di(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}=Ob(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:xO(u[h]),metrics:Vb(l,u[h],p?.[d.id]),fitted:yO(e,d.params),...f?.[d.id]?{score:{total:f[d.id].total,parts:{...f[d.id].parts}}}:{}})),raw:{results:m,scores:f,field:p}}}async function oF(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=Oa(e),{asset:a}=await qm(e,t),s=fo(structuredClone(n.params),po(e),o);return tF(s,a,{...r.steps?{steps:r.steps}:{},numerics:o.numerics,...r.tolPct!==void 0?{tolPct:r.tolPct}:{},...r.onStep?{onStep:r.onStep}:{}})}var RO=(e,t)=>e[t]??[],vO=(e,t,r)=>r<=1?[e]:Array.from({length:r},(n,o)=>e+(t-e)*o/(r-1));function Zm(e){return e.kind==="param"?vO(e.start,e.end,Math.max(1,Math.round(e.steps))):e.kind==="part"?[...e.partIds]:[...e.values]}var aF=e=>e.kind==="param"?e.label:e.kind==="part"?`${e.part} model`:e.setting;function kO(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),po(e),Oa(e)),o=Q1(n,{geometry:!0}),a=fu(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=dn.find(l=>l.doc===i.part);if(!c)throw new Error(`"${i.part}" is not a library \u2014 it is one of ${dn.map(l=>l.doc).join(", ")}`);for(let l of i.partIds)if(!RO(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*Zm(c).length,1);if(s>tm)throw new Error(`that grid is ${s} runs, over the ${tm} cap \u2014 a run is a whole session. Drop an axis or use fewer steps.`)}var MO=e=>e.map(t=>String(typeof t=="number"?Number(t.toPrecision(4)):t)).join(" \xD7 ");function SO(e,t){let r=[...new Set(e.flatMap(o=>(o.didNotFinish??[]).map(a=>a.label)))],n=e.map(o=>({name:MO(o.at),events:r.map(a=>({label:a,incomplete:o.didNotFinish?.find(s=>s.label===a)}))}));return rF(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`:nF(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 AO(e){let t=[[]];for(let r of e){let n=Zm(r),o=[];for(let a of n)for(let s of t)o.push([...s,a]);t=o}return t}async function sF(e,t,r,n){kO(e,r);let o=AO(r.axes),a=[],s=!1;for(let[u,m]of o.entries()){let f=structuredClone(e),p=f.vehicles.find(M=>M.id===r.vehicleId),d={...r.settings},h={};r.axes.forEach((M,v)=>{let x=m[v];if(M.kind==="param")h[M.label]=x;else if(M.kind==="part"){let k=dn.find(F=>F.doc===M.part);p.params[k.ref]=x}else d[M.setting]=x});let b=r.fleet?f.vehicles.filter(M=>M.visible||M.id===r.vehicleId).map(M=>M.id):[r.vehicleId],g=await Qm(f,t,{vehicleIds:b,settings:d,...Object.keys(h).length?{overrides:{[r.vehicleId]:h}}:{}});s=g.fleetScored;let y=g.vehicles.find(M=>M.id===r.vehicleId),R=y.events.flatMap(M=>M.incomplete?[{label:M.label,...M.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(Zm(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(aF(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(...SO(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:aF(u),values:Zm(u)})),runs:a,metricKeys:i,fleetScored:s,flat:c,caveats:l}}var Oue=Math.PI/180;function S0(e){if(!e.chassis)return e;let{chassis:t,...r}=e;return r}var kfe=180/Math.PI;var fV={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:Qn,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 Uhe=fV.id;var mc=.02;function xF(e){let t=Math.max(mc,Math.abs(e.heaveMotionRatio)),r=Math.max(mc,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 bV=(e,t)=>({od:t,id:Math.min(e.id,t-.5)}),gV=(e,t)=>e/(2*t*t);function yF(e,t){switch(e.kind){case"ubar":case"blade":case"torsionTube":return{...e,section:bV(e.section,t)};default:return e}}function RF(e,t,r){let n=Math.max(mc,Math.abs(r));if(e?.kind==="coil"){let l=gV(t,n),u=e.rate;if(typeof u=="number")return{...e,rate:l};let m=Er(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=>ei(yF(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 yF(a,c)}function vF(e,t,r,n){let o=e?.design,a=RF(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 yV=Math.PI/180,Jm=1e-6;function xV(e){return!(ve(e.rockerPivotA,e.rockerPivotB)<Jm||ve(e.rockerToPushrod,e.rockerPivotA)<Jm||ve(e.rockerToDamper,e.rockerPivotA)<Jm||ve(e.rockerToDamper,e.damperChassis)<Jm)}function AF(e){if(!xV(e.hardpoints))return!1;let t={...e,config:{...e.config,actuation:"rocker"}};try{let r=et(t);for(let n of[-20,-1,0,1,20]){let o=ge(r,n,0);if(!o.ok||!Number.isFinite(o.state.metrics.damperLength))return!1}return!0}catch{return!1}}function FF(e){if(e.config.actuation!=="direct"||AF(e))return;let{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}=vV(e);return{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}}var kF=40;function ep(e,t={}){let r=e.hardpoints,n=r.pushrodOuter,o=r.damperChassis,a=ve(n,o),s=ee(n,U(H(o,n),RV)),i=t.armRod??Math.max(25,.15*a),c=t.armDamper??i,l=[s[0]-kF,s[1],s[2]],u=[s[0]+kF,s[1],s[2]],m=q(H(u,l)),f=H(n,s),p=q(H(f,U(m,MF(f,m)))),d=Et(p,m,(t.armAngleDeg??60)*yV),h=ee(s,U(d,i)),b=H(o,s),g=q(H(b,U(m,MF(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 RV=.72,MF=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2];function SF(e){let t=qe(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 vV(e,t={}){let r=t.target??SF(e),n=t.armAngleDeg,o=ep(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=ep(e,{armRod:s,armAngleDeg:n,damperSide:p}),h={...e,config:{...e.config,actuation:"rocker"},hardpoints:d};try{let b=et(h),g=ge(b,15,0),y=ge(b,-15,0);if(g.ok&&y.ok&&g.state.metrics.damperLength<y.state.metrics.damperLength)return p}catch{}}return 1})(),c=(p,d)=>{try{return SF({...e,config:{...e.config,actuation:"rocker"},hardpoints:ep(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,M=c(p,R);if(!Number.isFinite(M))break;b=R,M<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 ep(e,{armRod:u,armAngleDeg:n,armDamper:m,damperSide:i})}var cbe=Array.from({length:19},(e,t)=>-45+5*t);var lbe=Math.PI/180;function kV(e){let t=e.hardpoints,r=q(H(t.rockerPivotB,t.rockerPivotA)),n=jr(t.rockerToDamper,t.rockerPivotA,r),o=.6*Wr(H(t.rockerToDamper,n)),a=ae(r,Cy),s=Wr(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 MV=(e,t)=>({...e,config:{...e.config,actuation:t}});function w0(e,t,r,n){let o=r==="front"?e.front:e.rear,a=ou(o),s=o.config.springRate*a*a,i=Z(t,r==="front"?"damper_front":"damper_rear")*a*a,c=r==="front"?t.arbFrontDesign:t.arbRearDesign,l=$n(e,t)[r]??Z(t,r==="front"?"arb_front":"arb_rear"),u=ma(e,t)[r]??Z(t,r==="front"?"heave_spring_front":"heave_spring_rear"),m=FF(o),f=MV(m?{...o,hardpoints:{...o.hardpoints,...m}}:o,"decoupled"),p=r==="front"?t.heaveFrontDesign:t.heaveRearDesign,d=n?.heave??wF(p?.linkage,w=>kn(f,w).atDesign)??bd(f,"rockerToRocker"),h=!c||c.design.kind==="none"||c.design.kind==="coil",b=h?"coil":"ubar",g=c?.linkage&&(c.design.kind==="none"||c.linkage.attach!=="rocker")?c.linkage:void 0,y=n?.roll??wF(h?g:c?.linkage,w=>Oo(f,w,{kind:b}).atDesign)??(h?kV(f):b1(f)),R=kn(f,d).atDesign,M=Oo(f,y,{kind:b}).atDesign,v=su(e,t),x=xF({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:M}),k=!c||c.design.kind==="none"?{design:{kind:"coil",rate:1},linkage:y}:{...c,linkage:y},F=vF({design:p?.design??{kind:"none"},linkage:d,damper:p?.damper},k,x,M);return m?{...F,crank:m}:F}function wF(e,t){return e&&Math.abs(t(e))>=mc?e:void 0}var tp=[{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"]}],C0=()=>({arbFront:void 0,arbRear:void 0,heaveFront:void 0,heaveRear:void 0}),SV={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]}},AV={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]}},FV=()=>({outer:[0,189,486],attach:"rocker",mount:{kind:"chassis",anchor:[-225,0,486]}}),wV={rate:60,motionRatio:1},CV={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]}},TV=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]}},PV={kind:"coil",rate:1560,motionRatio:1,gap:0,bothWays:!0},LV=40,DV={rockerPivotA:[50,130,440],rockerPivotB:[-50,130,440],rockerToPushrod:[10,170,460],rockerToDamper:[-20,64,440],damperChassis:[-20,64,215]},CF=()=>({outer:[-50,130,480],attach:"rocker",shaftStation:-50}),TF=()=>({outer:[50,130,400],inner:[50,130,480],attach:"rocker",shaftStationOuter:50,shaftStationInner:50}),EV=e=>[e[0],e[1],e[2]];function IV(e){let t=r=>({...r,hardpoints:{...r.hardpoints,...LF(DV)},config:{...r.config,actuation:"decoupled"}});return{...e,front:t(e.front),rear:t(e.rear)}}function LF(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,EV(r)]))}function DF(e,t=no(),r=e==="pull"?AV:SV){let n=(o,a)=>({...o,hardpoints:{...o.hardpoints,...LF(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 rp(e,t){let r=T0(e),n=Va(e);if(e==="heave")return{meta:r,vehicle:n,components:{...C0(),heaveFront:{design:{...Lh,...wV},linkage:FV()}}};if(e!=="decoupled")return{meta:r,vehicle:n,components:C0()};let o=w0(n,t,"front",{heave:CF(),roll:TF()}),a=w0(n,t,"rear",{heave:CF(),roll:TF()});return{meta:r,vehicle:n,components:{arbFront:o.arb,arbRear:a.arb,heaveFront:o.heave,heaveRear:a.heave}}}function Va(e){let{name:t}=T0(e);if(e==="direct")return{...Ni(),name:t};if(e==="mcpherson"){let n=Oi(),o=im();return{...n,front:{...o,config:{...o.config,loadedRadius:n.front.config.loadedRadius}},name:t}}let r=_V(DF(e==="pullrod"?"pull":"push"));return{...e==="decoupled"?IV(r):r,name:t}}var PF={front:221.7,rear:220.9};function _V(e){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:PF.front}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:PF.rear}}}}function T0(e){let t=tp.find(r=>r.id===e);if(!t)throw new Error(`Unknown suspension template: ${e}`);return t}function np(){let e=t=>({design:{...PV},linkage:TV(t),damper:LV});return{meta:T0("heave"),vehicle:DF("push",Yb(),CV),components:{...C0(),heaveFront:e("front"),heaveRear:e("rear")}}}var EF=[10,25,50,100,200,300],NV=[{id:"c1",label:"Soft",scale:.7},{id:"c2",label:"Medium",scale:1},{id:"c3",label:"Firm",scale:1.4}],IF=e=>Math.round(e*100)/100;function OV(e,t,r){let n=EF.map(o=>IF(r*o));return{id:e,label:t,speedMmS:[...EF],bumpN:n,reboundN:[...n]}}function VV(e){return{name:e.name,body:{...e.body},curves:NV.map(t=>OV(t.id,t.label,IF(e.coefficient*t.scale)))}}function pc(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 dr(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:Hi[e.dampers.length%Hi.length],model:VV(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 it=e=>`${e} (typical)`,P0={car:{name:it("Formula Student damper"),coefficient:2.5,body:{extended:249,stroke:55}}},op={car:P0.car,heave:{name:it("Formula Student heave damper"),coefficient:3.4,body:{extended:270,stroke:47}},roll:{name:it("Formula Student roll damper"),coefficient:3.7,body:{extended:322,stroke:100}}},ap={car:{name:it("Formula 1 damper"),coefficient:6,body:{extended:240,stroke:40}},heave:{name:it("Formula 1 heave damper"),coefficient:40,body:{extended:240,stroke:40}}},_F={car:{name:it("GT damper"),coefficient:4.5,body:{extended:510,stroke:80}}},L0={car:{name:it("Sports car damper"),coefficient:2.4,body:{extended:515,stroke:110}}},NF={car:{name:it("Sports car strut"),coefficient:2.4,body:{extended:310,stroke:120}},rear:L0.car},OF={car:{name:it("Cup car strut"),coefficient:4,body:{extended:285,stroke:75}},rear:{name:it("Cup car rear damper"),coefficient:3.5,body:{extended:505,stroke:80}}},VF={car:{name:it("Stock car front damper"),coefficient:7.5,body:{extended:555,stroke:110}},rear:{name:it("Stock car rear damper"),coefficient:6.75,body:{extended:555,stroke:110}}},BF={car:{name:it("Hill-climb front damper"),coefficient:3,body:{extended:285,stroke:65}},rear:{name:it("Hill-climb rear damper"),coefficient:3.5,body:{extended:285,stroke:65}}},$F={car:{name:it("Race truck front damper"),coefficient:12,body:{extended:780,stroke:160}},rear:{name:it("Race truck rear damper"),coefficient:8.5,body:{extended:780,stroke:160}}};function $a(e){return e.vehicles=e.vehicles.slice(0,1),e.activeVehicleId=e.vehicles[0]?.id??null,e}function gn(e,t){let r=zi(e);return r.meta.rulesetId=t,r}function ho(e,t,r,n){let o=gn(e,t);return o.suspensions=[{...o.suspensions[0],model:n()}],o.vehicles=[gg(r,"v1",0)],o.activeVehicleId="v1",o}var[,BV,$V,GV,KV,HV,zV,YV]=Jb;function D0(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 GF(){return{...Va("decoupled"),name:no().name}}var WV=[{label:"Formula Student (decoupled)",vehicle:GF,components:e=>pc(rp("decoupled",e).components,op)},{label:"Formula 1 (third springs)",vehicle:()=>np().vehicle,components:()=>pc(np().components,ap)}],E0={"direct-coilover":"direct",pushrod:"pushrod",pullrod:"pullrod","third-spring":"heave","mcpherson-strut":"mcpherson"},jV=[...WV.map(e=>e.vehicle),...Object.values(E0).map(e=>()=>Va(e))];function Ba(e){let t=pc(rp("decoupled",e.vehicles[0].params).components,op);e.suspensions=[{...e.suspensions[0],model:GF()}];for(let r of e.vehicles)D0(r.params,t);return dr(e,op),e}var bo={title:"OpenStreetMap",url:"https://www.openstreetmap.org/copyright",licence:"ODbL-1.0",credit:"\xA9 OpenStreetMap contributors"},sp={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"},KF={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]"},HF={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"},UV={id:"cota",name:"Circuit of the Americas, Austin",address:"e0c6ea889d708cf15f9c",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[bo,sp,HF]}},XV={id:"laguna-seca",name:"Laguna Seca, Monterey",address:"185b5811b9c423ef44ef",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[bo,sp,HF]}},qV={id:"nordschleife",name:"Nordschleife, N\xFCrburg",address:"74c49603c7b2f15985c6",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[bo,KF]}},QV={id:"brands-hatch",name:"Brands Hatch, Kent",address:"c4953e3c25eaba4a5b7e",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[bo,{title:"Environment Agency LIDAR Composite DTM, 1 m",url:"https://environment.data.gov.uk/dataset/13787b9a-26a4-4775-8523-806d13af58fc",licence:"OGL-UK-3.0",credit:"\xA9 Environment Agency copyright and/or database right 2022. All rights reserved."}]}},ZV={id:"bristol",name:"Bristol, Tennessee",address:"f0e23953669a414ad600",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[bo,sp]}},JV={id:"pikes-peak",name:"Pikes Peak, Colorado",address:"3de137fe33b5c2875036",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[bo,sp]},standingStart:!0},e5={source:"venue",altitudeM:3580,pressure:{kind:"standard"},humidityPct:0},t5=10,r5={id:"nurburg-sprint",name:"Sprintstrecke, N\xFCrburg",address:"1875636cdbb615aa2756",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[bo,KF]}};function go(e,t){let{id:r,name:n,address:o,provenance:a,standingStart:s}=t,i={kind:"catalogue",id:r,address:o},c=Vi(lg({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 yn(e,t,r){let n=e.vehicles[0].params,o=`m${e.motors.length+1}`;e.motors=[...e.motors,{id:o,color:fn[e.motors.length%fn.length],model:t}];let a=V1({},{...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 n5=3.8,ip={hubPlanetary:14.5,inboardChain:4,engineChain:3.4},o5="Hub motor, 35 kW (example)";function I0(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 zF(e){let t=e.motors.find(r=>r.id==="m1");return t.model={...t.model,name:o5},t.id}function cp(e,t,r){let n=$a(Ba(gn(e,r)));return n.vehicles[0].params.name=t,n}function a5(){let e=cp("Formula Student combustion car","Formula Student combustion","fs-cv");yn(e,og(),ip.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 s5(){let e=cp("Formula Student AWD car","Formula Student AWD","fs-ev");return I0(e,zF(e),4,"awd",ip.hubPlanetary,"hub"),e}function i5(){let e=cp("Formula Student RWD hub-motor car","Formula Student RWD hub motors","fs-ev");return I0(e,zF(e),2,"rear",ip.hubPlanetary,"hub"),e}function c5(){let e=cp("Formula Student one-motor car","Formula Student RWD one motor","fs-ev"),t=`m${e.motors.length+1}`;return e.motors=[...e.motors,{id:t,color:fn[e.motors.length%fn.length],model:ng()}],I0(e,t,1,"rear",ip.inboardChain),e.vehicles[0].params.driveline={rear:structuredClone(bt.clutch)},e}function l5(){let e=$a(Ba(gn("Formula Student endurance energy","fs-ev"))),t=e.vehicles[0],r=structuredClone(t);if(r.id="v2",r.color=Ki[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 u5(){let e=np(),t=ho("Formula 1 car","trackday",BV,()=>e.vehicle);return D0(t.vehicles[0].params,pc(e.components,ap)),dr(t,ap),yn(t,ag(),n5),go(t,UV)}function YF(e="GT car",t=Ni){let r=ho(e,"trackday",$V,t);return dr(r,_F),yn(r,pS(),r.vehicles[0].params.gear_ratio.value),go(r,XV)}function WF(e="Sports car",t=Oi,r=L0){let n=ho(e,"trackday",GV,t);return dr(n,r),yn(n,dS(),n.vehicles[0].params.gear_ratio.value),go(n,qV)}function m5(){let e=ho("Cup car","trackday",KV,eS);return dr(e,OF),yn(e,fS(),e.vehicles[0].params.gear_ratio.value),go(e,QV)}function p5(){let e=ho("Stock car","trackday",HV,tS);return dr(e,VF),yn(e,hS(),e.vehicles[0].params.gear_ratio.value),go(e,ZV)}function d5(){let e=ho("Hill-climb prototype","trackday",zV,rS);return dr(e,BF),yn(e,bS(),e.vehicles[0].params.gear_ratio.value),e.settings.air=structuredClone(e5),e.settings.airTempC=t5,go(e,JV)}function f5(){let e=ho("Race truck","trackday",YV,nS);return dr(e,$F),yn(e,gS(),e.vehicles[0].params.gear_ratio.value),go(e,r5)}function h5(e){let t=tp.find(o=>o.id===e);if(e==="direct")return YF(t.name,()=>Va(e));if(e==="mcpherson")return WF(t.name,()=>Va(e),NF);let r=$a(gn(t.name,"trackday")),n=rp(e,r.vehicles[0].params);return r.suspensions=[{...r.suspensions[0],model:n.vehicle}],D0(r.vehicles[0].params,n.components),dr(r,P0),r}function dc(e,t,r){let n=E0[e],o=tp.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:()=>h5(n)}}var b5=[{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:()=>Ba(gn("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:l5},{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:()=>$a(Ba(gn("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:a5},{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:s5},{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:i5},{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:c5},{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:u5},{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:YF},{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:WF},{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:m5},{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:p5},{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:d5},{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:f5},{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:()=>$a(Ba(gn("Suspension study","trackday")))},dc("direct-coilover","The GT car\u2019s wishbones driving coilovers straight into the towers, at Laguna Seca.","On the GT car, at Laguna Seca."),dc("pushrod","The FS car on pushrods: a rod from each lower wishbone works a rocker.","On the Formula Student car, at FSG."),dc("pullrod","The FS car on pullrods: a rod from each upper wishbone pulls a low rocker.","On the Formula Student car, at FSG."),dc("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."),dc("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:()=>$a(Ba(gn("Tyre study","fs-ev")))}],jF=b5.map(e=>({...e,load:()=>yg(e.load())}));var UF={width:320,height:200},jbe=[.6*UF.width-9,.6*UF.height-9];var XF=new WeakMap,qF=new WeakMap,_0=e=>JSON.stringify(e,(t,r)=>r===1/0?"Infinity":r);function QF(e,t){if(!t){let a=XF.get(e);return a||(a=Ct(e),XF.set(e,a)),a}let r=qF.get(e);r||(r=new Map,qF.set(e,r));let n=_0(t),o=r.get(n);return o||(r.size>=4&&r.clear(),o=Ct(e,t),r.set(n,o)),o}var x5=Math.PI/180,R5=e=>e>1?e/100:e;function fc(e){let t=null;return()=>(t??={v:e()}).v}function ZF(e){let t=qe(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 JF=new WeakMap,N0={heave:0,pitch:0,roll:0,steer:0},ew=[0,1,2,3,4],tw=[-20,-10,0,10,20];function nw(e,t){let r=Ir(e,N0),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 ew){let l=c===0?null:Ir(e,{...N0,roll:c*x5});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 tw){let l=c===0?null:Ir(e,{...N0,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:ew,rcFront:s[0].rc,rcRear:s[1].rc,rcSplitFront:s[0].split,rcSplitRear:s[1].split},heave:{drop:tw,rcFront:i[0],rcRear:i[1]}}}var rw=new WeakMap;function v5(e,t,r,n){let o=rw.get(e);o||(o=new Map,rw.set(e,o));let a=`${_0(r)}|${n[0]}|${n[1]}`,s=o.get(a);if(!s){o.size>=4&&o.clear();try{s=nw(QF(e,r),n)}catch{s=t.rigidMigration(n)}o.set(a,s)}return s}function k5(e){let t=JF.get(e);if(t)return t;let r=Ct(e),n=Ir(r,{heave:0,pitch:0,roll:0,steer:0}),o=ZF(e.front),a=ZF(e.rear),s={wheelbase:e.config.wheelbase,trackFront:dt(e.front),trackRear:dt(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:ua(n.front),rcGainRear:ua(n.rear),rigidMigration:i=>nw(r,i),kinFront:fc(()=>jo(e.front)),kinRear:fc(()=>jo(e.rear))};return JF.set(e,s),s}function ow(e,t,r,n){let o=k5(e),a=$n(e,t),s=ma(e,t),i=P1(e,t),c=su(e,t),l=L1(e,t),u=E1(t),m=D1(e,t),f=Bn(e.front),p=Bn(e.rear),d=Vn(t.damperModel,t.damperSetup,o.mrFront,o.mrRear,t.damperModelRear??t.damperModel),h={rho:t.rho.value,area:t.A.value,cl:t.c_l.value,cw:t.c_w.value,copLongFront:1-Math.max(0,Math.min(1,Z(t,"cop_long"))),copHeight:Z(t,"cop_height"),...t.aeroModel?{model:t.aeroModel}:{},rideHeightFront:Z(t,"ride_height_front"),rideHeightRear:Z(t,"ride_height_rear")},b=9.81,g=R5(t.front_mass_diss.value),y=da(t,r,n),R=Ie(y.front),M=y.rear===y.front?R:Ie(y.rear),v=n??t.tireModelRear??r,x=t.m.value*b*g/2,k=t.m.value*b*(1-g)/2,F=R.corneringStiffness(x),w=M.corneringStiffness(k),C=(r?R.verticalStiffness():0)||Z(t,"tire_vertical_rate"),T=(v?M.verticalStiffness():0)||Z(t,"tire_vertical_rate"),S=er(r)??0,A=er(v)??0,P=mu({freeRadius:S,staticLoad:x,tyreRate:C,surveyed:e.front.config.loadedRadius},{freeRadius:A,staticLoad:k,tyreRate:T,surveyed:e.rear.config.loadedRadius},g),L=Bt(S,x,C,e.front.config.loadedRadius),D=Bt(A,k,T,e.rear.config.loadedRadius),I=[_r(o.rcHeightFront,o.rcGainFront,e.front.config.loadedRadius,L),_r(o.rcHeightRear,o.rcGainRear,e.rear.config.loadedRadius,D)],G=fc(()=>ii(o.kinFront(),Z(t,"camber_front_deg"))),O=fc(()=>ii(o.kinRear(),Z(t,"camber_rear_deg"))),W=fc(()=>v5(e,o,Da(V),I)),E=_s({...t,wheelbase:{...t.wheelbase,value:o.wheelbase}}),_=si(t),V={massTotal:t.m.value,frontMassFrac:g,steeringSystem:t.steeringSystem,tv:Ul(t),cgHeight:pa(Z(t,"cg_height"),t.cgReference?.standingRadius,P),cgStandingRadius:P,wheelbase:o.wheelbase,trackFront:o.trackFront,trackRear:o.trackRear,wheelRateFront:f?0:o.wheelRateFront,wheelRateRear:p?0:o.wheelRateRear,decoupledFront:f,decoupledRear:p,...u.front?{elementLinkagesFront:u.front}:{},...u.rear?{elementLinkagesRear:u.rear}:{},...m.front.source==="part"?{cornerCoiloverFront:m.front.coilover}:{},...m.rear.source==="part"?{cornerCoiloverRear:m.rear.coilover}:{},...m.heaveFront.coilover?{heaveCoiloverFront:m.heaveFront.coilover}:{},...m.heaveRear.coilover?{heaveCoiloverRear:m.heaveRear.coilover}:{},...i.front&&!f?{heaveSeatFront:i.front}:{},...i.rear&&!p?{heaveSeatRear:i.rear}:{},...m.rollFront.coilover?{rollCoiloverFront:m.rollFront.coilover}:{},...m.rollRear.coilover?{rollCoiloverRear:m.rollRear.coilover}:{},tireRate:C,...T!==C?{tireRateRear:T}:{},tireDamping:Z(t,"tire_vertical_damping"),arbFront:a.front??Z(t,"arb_front"),arbRear:a.rear??Z(t,"arb_rear"),brakeBalanceFront:E.balanceFront,brakes:E,..._?{driveline:_}:{},heaveSpringFront:s.front??Z(t,"heave_spring_front"),heaveSpringRear:s.rear??Z(t,"heave_spring_rear"),unsprungPerCorner:Z(t,"unsprung_mass"),unsprungCgHeight:Bt(S,x,C,o.unsprungCgHeight),tyreFreeRadius:S,...A!==S?{tyreFreeRadiusRear:A}:{},rcHeightFront:I[0],rcHeightRear:I[1],corneringStiffnessFront:F,corneringStiffnessRear:w,get kinFront(){return G()},get kinRear(){return O()},damperFront:f?0:d?.front?.rate??Z(t,"damper_front")*o.mrFront*o.mrFront,damperRear:p?0:d?.rear?.rate??Z(t,"damper_rear")*o.mrRear*o.mrRear,...d?.front&&!f?{damperCurveFront:d.front.curve}:{},...d?.rear&&!p?{damperCurveRear:d.rear.curve}:{},heaveDamperFront:l.heaveFront?.rate??c.heaveFront,heaveDamperRear:l.heaveRear?.rate??c.heaveRear,rollDamperFront:l.rollFront?.rate??c.rollFront,rollDamperRear:l.rollRear?.rate??c.rollRear,...l.heaveFront?{heaveDamperCurveFront:l.heaveFront.curve}:{},...l.heaveRear?{heaveDamperCurveRear:l.heaveRear.curve}:{},...l.rollFront?{rollDamperCurveFront:l.rollFront.curve}:{},...l.rollRear?{rollDamperCurveRear:l.rollRear.curve}:{},unsprungCornerMass:Z(t,"unsprung_mass"),get rollCentreCurve(){return W().roll},get rcHeaveCurve(){return W().heave},aero:h,yawInertia:Z(t,"I_yaw"),rollInertia:Z(t,"I_roll"),pitchInertia:Z(t,"I_pitch"),get steerFront(){return iu(e.front,L)},ackermannPct:Z(t,"ackermann_pct"),toeFrontDeg:Z(t,"toe_front_deg"),toeRearDeg:Z(t,"toe_rear_deg")};return V}var sw=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}),V0={ggvMode:"twoTrack"},aw=new WeakMap;function B0(e,t=V0){let r=aw.get(e.vehicle);r||aw.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={...sw(e.params),suspensionOf:()=>e.vehicle};n.set(o,a=fo(e.params,s,t))}return a}var iw=(e=V0)=>t=>B0(t,e),cw=(e=V0)=>t=>ow(t.vehicle,k0(t.params,sw(t.params),e),t.params.tireModel,t.params.tireModelRear);function M5(e,t){return B0(e,t.switches)}var $0=e=>Gr(e?.rulesets);function lw(e,t,r,n,o={},a=()=>r.standingStart){let s=B0(n,r.switches),i=(l,u)=>{let m=em(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 uw=e=>[...new Set(e.lap.courses.flatMap(t=>t.course.kind==="track"?[t.course.trackId]:[]))],mw=e=>{let t=e?.session;return t?{sessionParams:r=>M5(r,t),session:()=>t}:{}},lp=e=>({metrics:$0(e),assemble:cw(e?.switches),simParams:iw(e?.switches),projectTrack:()=>e?.course??null,libraryTrack:t=>e?.tracks?.[t]??null,numerics:e?.numerics,...mw(e)}),S5=(e,t)=>({density:e.density,envelope:e.envelope,operating:e.operating,lap:e.lap,assemble:cw(t?.switches),simParams:iw(t?.switches),projectTrack:()=>t?.course??null,libraryTrack:r=>t?.tracks?.[r]??null,numerics:t?.numerics,...mw(t)}),pw="nelder-mead",dw=600,hc=[0,.15,.15];function fw(e,t,r,n=hc.length){let o=H0(t);return hc.slice(0,Math.max(1,n)).map((a,s)=>({...e,seed:s+1,startJitter:a,car:o,...r?{lap:r}:{}}))}function hw(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 bw(e,t,r,n,o=.01){let a=$0(n).byId;return A5(e,t,r,n).filter(s=>s.excess>-o*(a[s.metricId]?.scale??1))}function A5(e,t,r,n){let o;try{o=Ea(Wm(e,t,r),S5(t,n))}catch{return[]}return F5(o,t,$0(n))}function F5(e,t,r){let n=[];for(let o of t.constraints){let a=r.byId[o.metricId];if(!a)continue;let s=Wt(e,a,o.at);if(!Number.isFinite(s))continue;let i=`${Rt(a)}${cc(o.at,a)}`;n.push({key:o.key,metricId:o.metricId,label:i,unit:a.unit==="-"?"":a.unit,value:s,excess:ic(o,s)})}return n}var w5=.05;function C5(e,t){if(t.id.startsWith("hp.")||Ym(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 Jg(bn(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 qg(Kr(o.hardpoints,n[2]),n[3],1)}function gw(e,t,r){let n=r.filter(f=>f.score.feasible);if(n.length<2)return null;let o=t.map(f=>C5(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(w5,m),unit:a}}var T5={steeringSystem:!0,brakeSetup:!0,driveline:!0,heaveFrontDesign:!0,heaveRearDesign:!0,arbFrontDesign:!0,arbRearDesign:!0},yw=e=>Object.hasOwn(T5,e);function O0(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 P5(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":yw(t)||O0(e)?"block":null}function G0(e,t){t=Lt(e,t);let r=$t(e);return[...t.variables,...t.followers??[]].filter(n=>r[n.id]&&!r[n.id].supersededBy&&!P5(n.id)).map(n=>st(r[n.id]))}function xw(e,t,r){t=Lt(e,t);let n=$t(e),o=Wm(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[co.fore,co.aft]){let y=b.hardpoints[g];for(let R=0;R<3;R++)a.push({kind:"hardpoint",axle:f,key:g,axis:R,value:y[R]})}}else if(m==="arm"){let h=`${f}.${p}`;if(i.has(h))continue;i.add(h);let b=f==="front"?o.vehicle.front:o.vehicle.rear,g=jt[p];for(let y of[g.fore,g.aft]){let R=b.hardpoints[y];for(let M=0;M<3;M++)a.push({kind:"hardpoint",axle:f,key:y,axis:M,value:R[M]})}}else if(m==="hp"&&pr(c.id)){let h=`${f}.${p}`;if(i.has(h))continue;i.add(h);let b=(f==="front"?o.vehicle.front:o.vehicle.rear).hardpoints[p];for(let g=0;g<3;g++)a.push({kind:"hardpoint",axle:f,key:p,axis:g,value:b[g]})}else if(m==="hp")a.push({kind:"hardpoint",axle:f,key:p,axis:"xyz".indexOf(d),value:u});else if(m==="cfg")a.push({kind:"config",axle:f,field:p,value:u});else if(m==="kc"){if(s.has(`kc.${f}`))continue;s.add(`kc.${f}`);let h=f==="front"?o.vehicle.front:o.vehicle.rear;a.push({kind:"compliance",axle:f,value:h.compliance})}else if(m==="param")a.push({kind:"param",label:st(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(yw(m)||O0(c.id)){let h=O0(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 K0(e){let t=performance.now(),{dead:r,unprobed:n,...o}=f0(e.car,e.spec,lp(e.lap));return{...o,deadIds:r.map(a=>a.id),unprobedIds:n.map(a=>a.id),elapsedMs:performance.now()-t}}var H0=e=>e.vehicle.chassis?{...e,vehicle:S0(e.vehicle)}:e;function Rw(e,t){try{let r=z0(e.car,e.spec,e.lap),n=Qo.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:kr(r.variables),score:vr(r,kr(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&&n0(r.variables)?a0(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 z0=(e,t,r)=>jm(e,t,lp(r));function vw(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),...qs(e,t.damper)}}function kw(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 Mw=e=>({ggvMode:e.ggvMode,quasiTransient:e.quasiTransient===!0&&e.ggvMode!=="fast",motorThermal:e.motorThermal===!0,...QA({brakeFade:e.brakeFade===!0,airTempC:e.airTempC,diffYaw:e.diffYaw===!0,...e.air?{air:e.air}:{}})});function L5(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 Sw(e,t){let r=t.plannedPath!==void 0,n=L5(t);return{...lw(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 Y0(e,t){let r=e.vehicles.find(o=>o.id===t);if(!r)throw new Error(`this project holds no vehicle "${t}"`);let n=po(e);return kw(structuredClone(v0(e,r.params)),structuredClone(r.params),vw(r.params,n))}var D5="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 W0(e,t,r,n){if(e.settings.pathPlanId)throw new Error(D5);let o=Oa(e),a=e.tracks.length?(await qm(e,t)).asset:null,s={};for(let i of n?uw(n):[]){let c=e.tracks.find(l=>l.id===i);c&&(s[i]=await uc(c,t))}return Sw(r,{track:a,numerics:o.numerics,racingLine:o.racingLine,standingStart:o.standingStart,lapCounts:o.lapCounts??{},switches:Mw(o),rulesets:e.rulesets??[],library:s,standingOf:i=>e.tracks.find(c=>c.id===i)?.standingStart===!0})}async function Aw(e,t,r,n){let o=Y0(e,r),a=Lt(o,n),s=await W0(e,t,o,a);return K0({id:0,car:o,spec:a,lap:s})}async function Fw(e,t,r,n){let o=Y0(e,r),a=Lt(o,n),s=G0(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 W0(e,t,o,a)}catch(l){return{problems:[l instanceof Error?l.message:String(l)]}}let c=d0(o,a,{...lp(i),metrics:Gr(e.rulesets)});return c.length?{problems:c}:{problems:[],msPerEval:K0({id:0,car:o,spec:a,lap:i}).msPerEval,carFingerprint:qn(H0(o))}}async function E5(e,t,r,n,o,a=[]){let s=fw(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(Rw(m,y=>{y.kind==="progress"?(f.push([y.progress.evaluations,y.progress.score.total]),y.progress.evaluations===0&&(c??=y.progress.score),o?.progress(u*t.budget+y.progress.evaluations,i)):y.kind==="done"?p={result:y.result,elapsedMs:y.elapsedMs}:d=y.message}),d)throw new Error(d);if(!p)throw new Error("the search stopped without a result");let{result:h,elapsedMs:b}=p,g={seed:m.seed,startJitter:m.startJitter,x:h.x,score:h.score,evaluations:h.evaluations,infeasible:h.infeasible,history:h.history,trace:f,elapsedMs:b,...h.snapped?{snapped:h.snapped}:{}};l.push(g),o?.progress((u+1)*t.budget,i),await o?.finished?.(g)}if(!c)throw new Error("the search never scored the starting design");return{method:t.method,budget:t.budget,designScore:c,runs:l}}async function ww(e,t,r,n){let o=Y0(e,r.vehicleId),a=Lt(o,r.spec),s=G0(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 W0(e,t,o,a),c=r.method??pw;if(!Qo.some(b=>b.name===c))throw new Error(`unknown method "${c}" \u2014 it is one of ${Qo.map(b=>b.name).join(", ")}`);let l=r.budget??dw,u=Math.max(1,Math.min(r.seeds??hc.length,hc.length)),m=await E5(o,{spec:a,method:c,budget:l},i,u,n),f=z0(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:hw(f.variables,b.x),constraints:bw(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)=>Ss(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?gw(o,f.variables,m.runs.map(b=>({x:b.x,score:b.score}))):null,writes:xw(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 Tw(){if(typeof process.threadCpuUsage!="function")return performance.now();let e=process.threadCpuUsage();return(e.user+e.system)/1e3}async function _5(e,t){let r=jA(e.root);switch(e.kind){case"sweep":return sF(e.doc,r,e.req,t);case"convergence":return oF(e.doc,r,{vehicleId:e.vehicleId,...e.steps?{steps:e.steps}:{},...e.tolPct!==void 0?{tolPct:e.tolPct}:{},onStep:t});case"study":return ww(e.doc,r,{vehicleId:e.vehicleId,spec:e.spec,...e.method?{method:e.method}:{},...e.budget?{budget:e.budget}:{},...e.seeds?{seeds:e.seeds}:{}},{progress:t,cancelled:()=>!1,tick:async()=>{}});case"fleet":return Qm(e.doc,r,{...e.vehicleIds?{vehicleIds:e.vehicleIds}:{},...e.settings?{settings:e.settings}:{},...e.overrides?{overrides:e.overrides}:{}});case"probe":return Aw(e.doc,r,e.vehicleId,e.spec);case"quote":return Fw(e.doc,r,e.vehicleId,e.spec)}}if(Cw){let e=Cw,t=r=>e.postMessage(r);(async()=>{try{let r=await _5(I5,(n,o)=>t({type:"progress",done:n,total:o}));t({type:"done",result:r,cpuMs:Tw()})}catch(r){t({type:"failed",message:r instanceof Error?r.message:String(r),cpuMs:Tw()})}})()}export{_5 as runJob,Tw as threadCpuMs};
|
|
226
|
+
`)),this.name="RulesetDefError",this.problems=r}},Si=e=>typeof e=="number"&&Number.isFinite(e),Mi=e=>Si(e)&&e>0,Pt=(e,t)=>e===void 0||t(e);function OI(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":Mi(a.distance)||r(`${s} needs a distance above zero, in metres`),Pt(a.vStart,i=>Si(i)&&i>=0)||r(`${s}'s entry speed must be zero or more`);break;case"constantRadius":Mi(a.radius)||r(`${s} needs a radius above zero, in metres`),Pt(a.laps,i=>Si(i)&&i>=1)||r(`${s} runs at least one lap`);break;case"trackLap":Pt(a.laps,i=>Si(i)&&i>=1)||r(`${s} runs at least one lap`),Pt(a.distance,Mi)||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,Si)||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,Mi)||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],Mi)||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 DM(e){let t=OI(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}=Hu(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 Yu(e){return DM(e).problems}var kb=e=>Number.isFinite(e)?e:NaN;function VI(e){return e.unit&&e.format!=="time"?`${e.label} (${e.unit})`:e.label}function mn(e){let t=structuredClone(e),{plan:r,problems:n}=DM(t);if(!r)throw new zu(t.id,n);let o=new WeakMap,a=p=>{let d=o.get(p);return d||(d=vb(r,p),o.set(p,d)),d},s=new Map(t.kpis.map(p=>[p.key,p])),i=new Map;for(let[p,d]of Object.entries(t.score?.parts??{}))i.has(d)||i.set(d,p);let c=p=>(d,h)=>{if(!h)return NaN;let b=h.kpis?.[p];if(b!==void 0)return kb(b);let g=h,y=i.get(p);return y!==void 0?kb(g.parts?.[y]):p===t.score?.total?kb(g.total):NaN},l=t.kpis.filter(p=>!p.hidden).map(p=>{let d=r.field.has(p.key);return{key:p.key,label:VI(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[M,v]of Object.entries(u.parts)){y[M]=g[v];let x=s.get(v)?.max;x!=null&&(R[M]=x)}h[b]={total:g[u.total],parts:y,...Object.keys(R).length?{maxima:R}:{},kpis:Object.fromEntries(t.kpis.map(M=>[M.key,g[M.key]]))}}return h}:void 0,f=m||(r.field.size>0?p=>{let d=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 Yt={accel:"accel",skidpad:"skidpad",autocross:"autocross",endurance:"endurance"},EM=[{kind:"straightLineAccel",id:Yt.accel,label:"Acceleration (75 m)",distance:75},{kind:"constantRadius",id:Yt.skidpad,label:"Skidpad",radius:8.375},{kind:"trackLap",id:Yt.autocross,label:"Autocross (1 lap)",laps:1},{kind:"trackLap",id:Yt.endurance,label:"Endurance (22 km)",distance:22e3}],IM=[{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"}],_M={total:"overall",parts:{[Yt.accel]:"accelPts",[Yt.skidpad]:"skidpadPts",[Yt.autocross]:"autocrossPts",[Yt.endurance]:"endurancePts",efficiency:"efficiencyPts"}},NM={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:EM,kpis:IM,score:_M,track:{minTurnRadius:4.5},battery:X0,traceEventId:Yt.autocross},OM={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:EM,kpis:IM,score:_M,track:{minTurnRadius:4.5},traceEventId:Yt.autocross},Ai=mn(NM),Mb=mn(OM);var Sb="lap",BI=[{kind:"trackLap",id:Sb,label:Gu,laps:1}],VM={id:"trackday",label:"Track day",description:"One flying lap of the selected track. Times and traces only \u2014 no scoring.",events:BI,kpis:[{key:"lap",label:"Lap time",format:"time",lowerBetter:!0,expr:"lap.time"},{key:"topSpeed",label:"Top speed",unit:"km/h",over:Sb,expr:"peak(speed)"},{key:"energy",label:"Energy / lap",unit:"kWh",lowerBetter:!0,expr:"lap.energy"}],traceEventId:Sb},Ab=mn(VM);function pn(e){if(e===null||typeof e!="object")return JSON.stringify(e)??"null";if(Array.isArray(e))return`[${e.map(pn).join(",")}]`;let t=e,r=Object.keys(t).sort(),n=[];for(let o of r)t[o]!==void 0&&n.push(`${JSON.stringify(o)}:${pn(t[o])}`);return`{${n.join(",")}}`}function qn(e){let t=pn(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 Fa=[Ai,Mb,Ab],Qn=Ai.id,wa=e=>Fa.some(t=>t.id===e),BM=new WeakMap,Fi=new Map,$I=64;function Wu(e){let t=BM.get(e);if(t!==void 0)return t;let r=pn(e),n=Fi.get(r);return n===void 0&&(n=Yu(e).length?null:mn(e),Fi.size>=$I&&Fi.delete(Fi.keys().next().value),Fi.set(r,n)),BM.set(e,n),n}function ju(e,t=[]){if(e==null)return;if(typeof e!="string")return Wu(e)??void 0;let r=Fa.find(o=>o.id===e);if(r)return r;let n=t.find(o=>o.id===e);return n?Wu(n)??void 0:void 0}function Zn(e,t=[]){return ju(e,t)??Ai}function Fb(e=[]){let t=e.filter(r=>!wa(r.id)).map(r=>Wu(r)).filter(r=>r!==null);return[...Fa,...t]}var wi=e=>e.definition??e.id;function Uu(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=GI(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 Cb(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=wb(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 GI(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=wb(e,c,r,n),u=new Array(o).fill(0);u[0]=i,u[o-1]=s;let m=wb(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 wb(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 Ci(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 $M(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 GM(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 KM(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=>$M(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=GM([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 KI(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=$M(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 HI(e,t,r){let{j:n,t:o}=KI(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=GM([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 Tb(e,t){return t>0?e.z.map((r,n)=>{let o=HI(e,n,t/2);return o?o.value.reduce((a,s,i)=>a+s*e.z[o.j[i]],0):r}):[...e.z]}function zI(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 Xu(e){let t=Ci(e);if(!t)return 0;let r=KM(t);return r>1e-6?Math.max(10,zI(r,YI(t))):0}function YI(e){let t=[];for(let r=1;r<e.pos.length;r++)t.push(e.pos[r]-e.pos[r-1]);return e.closed&&e.pos.length&&t.push(e.length-e.pos[e.pos.length-1]+e.pos[0]),t.sort((r,n)=>r-n),t.length?t[t.length>>1]:0}function ur(e,t,r){let n=e.n;if(e.closed===!1){let a=r-t;return a===0?e.diag[t]:a===1?e.off1[t]:a===2?e.off2[t]:a===-1?e.off1[r]:a===-2?e.off2[r]:0}let o=((r-t)%n+n)%n;return o===0?e.diag[t]:o===1?e.off1[t]:o===2?e.off2[t]:o===n-1?e.off1[r]:o===n-2?e.off2[r]:0}function Qu(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 HM(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 qu(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 WI(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 Pb(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=HM(r,(y,R)=>ur(e,y,R));if(!b)return null;let g=qu(b,t);return g.every(Number.isFinite)?g:null}let n=r-2,a=HM(n,(b,g)=>ur(e,b,g));if(!a)return null;let s=new Array(n).fill(0),i=new Array(n).fill(0);for(let b=0;b<n;b++)s[b]=ur(e,b,r-2),i[b]=ur(e,b,r-1);let c=qu(a,t.slice(0,n)),l=qu(a,s),u=qu(a,i),m=(b,g)=>{let y=0;for(let R=0;R<b.length;R++)y+=b[R]*g[R];return y},f=[[ur(e,r-2,r-2)-m(s,l),ur(e,r-2,r-1)-m(s,u)],[ur(e,r-1,r-2)-m(i,l),ur(e,r-1,r-1)-m(i,u)]],p=[t[r-2]-m(s,c),t[r-1]-m(i,c)],d=WI(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 zM(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=Pb(i,t);if(c){let l=Qu(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 YM=4,jI=8,Lb=.001;function UI(e,t,r){let n=[];for(let c=1;c<e.length;c++){let l=e[c]-e[c-1];l>=Lb&&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/ek(r,s,i)))}function XI(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])<Lb||(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:UI(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])<Lb;)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?Uu(b.slice(0,d),n,b[d]):Cb(b,n),y=r?Uu(b.slice(0,d),o,b[d]):Cb(b,o),R=new Array(h);for(let F=0;F<h;F++)R[F]=b[F+1]-b[F];let M=[0],v=[0],x=[0],k=0;for(let F=0;F<h;F++){let w=R[F]/YM;for(let C=0;C<YM;C++){let T=C*w;k+=_f(S=>Math.hypot(g.d1(F,S),y.d1(F,S)),T,T+w),M.push(k),v.push(F),x.push(T+w)}}return{closed:r,sx:g,sy:y,h:R,sTable:M,segTable:v,uTable:x,length:k,rawCum:c,rawLength:l}}function Ti(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 qI=.01,QI=3,WM=10;function ZI(e,t,r,n=WM){let o={step:0,uncertainty:1/0},a=e.length;if(a<8||!(r>0))return o;let s=Math.max(WM,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,M,v)=>{let x=R/s;m.push([1,x,x*x,x*x*x,M]),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,M)=>{for(let v=0;v<5;v++){h[v]+=R[v]*f[M];for(let x=0;x<5;x++)d[v][x]+=R[v]*R[x]}});let b=qt(d,h),g=qt(d,[0,0,0,0,1]);if(b.singular||g.singular)return o;let y=0;return m.forEach((R,M)=>{let v=0;for(let x=0;x<5;x++)v+=R[x]*b.x[x];y+=(f[M]-v)**2}),{step:b.x[4],uncertainty:Math.sqrt(y/(m.length-5)*g.x[4])}}function JI(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 e2(e,t,r){let{pos:n,loop:o}=JI(e.length,t),{step:a,uncertainty:s}=ZI(e,n,o,r);return Math.abs(a)>Math.max(qI,QI*s)?{z:e.map((i,c)=>i+a*n[c]/o),drift:-a}:{z:e,drift:0}}function t2(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+_f(v=>Math.hypot(s.d1(p,v),i.d1(p,v)),h,g),M=Math.hypot(s.d1(p,g),i.d1(p,g));if(M<1e-12)break;g-=(R-t)/M}return{seg:p,du:Math.min(Math.max(g,0),a[p])}}var r2=3,Db=5;function n2(e,t,r,n=Db){return Ju(e,t,r,n)}function Ju(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 Pb({n:a,diag:i,off1:c,off2:l,closed:r},u)??[...e]}function yt(e,t){let r=at(t),n=XI(e,r.fitSpacing),o=n.length,a=Math.max(jI,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}=t2(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),I=n.sy.d2(S,A),G=Math.hypot(P,L),O=Math.pow(P*P+L*L,1.5);f[C]=O>0?(P*I-L*D)/O:0,p[C]=G>0?-L/G:0,d[C]=G>0?P/G: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?e2(e.z,n.rawCum,g):null,R=y?y.z:e.z,M=g>0?Ci(e):null,v=M?Tb({...M,z:R},g):R,x=Ti(v,0,h,n),k=new Array(s).fill(0);if(b){for(let T=0;T<s;T++){let S=n.closed?(T+1)%s:Math.min(T+1,s-1),A=n.closed?(T-1+s)%s:Math.max(T-1,0),P=n.closed?2:S-A,L=x[S]-x[A];k[T]=P>0?Math.atan2(L,P*i)*180/Math.PI:0}for(let T=0;T<s;T++){if(m[T]===0)continue;let S=n.closed?(T+1)%s:T+1,A=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(r2,e.zReach??Xu(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 I=n.closed?D:Math.min(Math.max(D,T),s-1-T),G=0,O=0;for(let _=-T;_<=T;_++){let V=x[n.closed?(I+_+s)%s:I+_];G+=(_*_-S/P)*V,O+=_*V}let W=2*G/L/(i*i),E=O/S/i;w[D]=W/Math.pow(1+E*E,1.5)}}}return{name:e.name,closed:n.closed,x:c,y:l,s:u,ds:m,curvature:e.turnReach?n2(f,i,n.closed,e.turnReach):f,npts:s,length:F,nx:p,ny:d,z:x,gradient:k,...w?{verticalCurvature:w}:{},widthLeft:Ti(e.widthLeft,1.5,h,n),widthRight:Ti(e.widthRight,1.5,h,n),bank:Ti(e.bank,0,h,n),mu:Ti(e.mu,1,h,n),...y?.drift?{elevationDrift:y.drift}:{}}}function jM(e,t,r){let n=Qu(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 o2(e,t,r,n){let o=e.n,a=e.closed!==!1,s=(l,u)=>{let m=l+u;return a?(m%o+o)%o:m>=0&&m<o?m:null},i=[...t];for(let l=0;l<o;l++){if(r[l]==="free")continue;let u=n(l);if(u!==0)for(let m of[-2,-1,1,2]){let f=s(l,m);f!=null&&(i[f]-=ur(e,f,l)*u)}}let c={n:o,closed:e.closed,diag:[...e.diag],off1:[...e.off1],off2:[...e.off2]};for(let l=0;l<o;l++){if(r[l]==="free")continue;c.diag[l]=1,c.off1[l]=0,c.off2[l]=0;let u=s(l,-1),m=s(l,-2);u!=null&&(c.off1[u]=0),m!=null&&(c.off2[m]=0),i[l]=n(l)}return zM(c,i)}var a2=1e-4;function UM(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=jM(e,t,u),f=new Array(a).fill("free"),p=!1;for(let d=0;d<s;d++){let h=Qu(e,u).map((R,M)=>R-t[M]),b=!1;for(let R=0;R<a;R++){let M=u[R]<=r[R]+i&&h[R]>=-i?"lo":u[R]>=n[R]-i&&h[R]<=i?"hi":"free";M!==f[R]&&(f[R]=M,b=!0)}if(p&&!b)return{x:u,iterations:d+1,converged:!0,bounds:f};let g=o2(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 M=!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&&(M=!0),T}),x=jM(e,t,v),k=0;for(let F=0;F<a;F++)k+=h[F]*(v[F]-u[F]);if(R===1&&!M||x<m&&x<=m+a2*k){u=v,m=x,p=R===1&&!M,y=!0;break}}if(!y)return{x:u,iterations:d+1,converged:!1,bounds:f}}return{x:u,iterations:s,converged:!1,bounds:f}}var Eb={lineStep:2,carHalfWidth:.75,margin:.1,foldMargin:.25,referenceReach:5,passes:40,iterations:400},s2=[1,.5,.25,.125,.0625,.03125,.015625,.0078125,.00390625,.001953125,.0009765625],i2=e=>Math.sqrt(e.reduce((t,r)=>t+r*r,0)/(e.length||1));function Pi(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 c2=Math.PI/180,XM=20;function l2(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?XM:Math.min(XM,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 u2(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?l2(t,r):t.z;return{...n||o?{z:s.map((i,c)=>i+r[c]*Math.tan(t.bank[c]*c2))}:{},...n?{zReach:e.zReach??Xu(e)}:{},...o?{bank:[...t.bank]}:{},...a?{mu:[...t.mu]}:{}}}function qM(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 m2(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),M=Math.hypot(b,g),v=y*R*M;if(!(v>1e-12))continue;let x=2*c(f,p,d,h)/v,k=Math.sqrt(.5*(y+R)),F=x/(2*k),w=(f*r[u]+p*n[u])/y,C=(b*r[u]+g*n[u])/M,T=(f*r[l]+p*n[l])/y,S=(d*r[l]+h*n[l])/R,A=(d*r[m]+h*n[m])/R,P=(b*r[m]+g*n[m])/M,L=-2*c(r[u],n[u],d,h)/v+x*(w/y+C/M),D=2*c(r[l],n[l],b,g)/v-x*(T/y-S/R),I=2*c(f,p,r[m],n[m])/v-x*(A/R+P/M);s[l]=x*k,i.l[l]=k*L-F*.5*w,i.d[l]=k*D+F*.5*(T-S),i.r[l]=k*I+F*.5*A}return{res:s,jac:i}}function p2(e,t,r,n,o){let a=n-r+1,s=e.l.slice(r,n+1),i=e.d.slice(r,n+1),c=e.r.slice(r,n+1),l=t.slice(r,n+1);o||(i[0]+=s[0],s[0]=0,i[a-1]+=c[a-1],c[a-1]=0);let u=(h,b)=>o?h[(b+a)%a]:b>=0&&b<a?h[b]:0,m=new Array(a),f=new Array(a),p=new Array(a),d=new Array(a);for(let h=0;h<a;h++){let b=u(c,h-1),g=u(s,h+1);m[h]=b*b+i[h]*i[h]+g*g,f[h]=i[h]*c[h]+g*u(i,h+1),p[h]=g*u(c,h+1),d[h]=-(b*u(l,h-1)+i[h]*l[h]+g*u(l,h+1))}return{M:{n:a,closed:o,diag:m,off1:f,off2:p},b:d}}function d2(e,t){let r=e.npts,n=e.closed;if(!(t>0)||r<7)return e;let o=n?r:r-1,a=0;for(let f=0;f<o;f++){let p=(f+1)%r;a+=Math.hypot(e.x[p]-e.x[f],e.y[p]-e.y[f])}let s=a/o,i=Ju(e.x,s,n,t,!0),c=Ju(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=Pi(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 f2=6;function h2(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(f2/(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 Ib(e,t={}){let r={...Eb,...t},n=yt(e,{dsTarget:r.lineStep}),o=d2(n,r.referenceReach),a=o.npts,s=T=>({x:o.x.map((S,A)=>S+o.nx[A]*T[A]),y:o.y.map((S,A)=>S+o.ny[A]*T[A])}),i=T=>{let S=Pi(T.x,T.y,o.closed),A=qM(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=i2(n.curvature),l=qM(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];h2(o,f,p,r.foldMargin);let g=T=>{let S=s(T),A=u2(e,o,T),P={name:`${e.name} \u2014 racing line`,x:S.x,y:S.y,closed:o.closed,widthLeft:h.map((E,_)=>Math.max(0,E-T[_])),widthRight:b.map((E,_)=>Math.max(0,T[_]-E)),...A,fit:"interpolate",turnReach:Db},L=1e-6,D=T.filter((E,_)=>E>=f[_]-L||E<=p[_]+L).length,I=Pi(S.x,S.y,o.closed),G=E=>1/Math.max(...E.map(Math.abs),1e-9),O=0,W=o.closed?S.x.length:S.x.length-1;for(let E=0;E<W;E++){let _=(E+1)%S.x.length,V=S.x[_]-S.x[E],N=S.y[_]-S.y[E];O+=A.z?Math.hypot(V,N,A.z[_]-A.z[E]):Math.hypot(V,N)}return{offset:T,s:[...o.s],asset:P,curvatureRms:{centreLine:c,racingLine:Math.sqrt(i(S)/(l||1))},infeasibleSamples:d,atBoundary:a?D/a:0,length:{centreLine:n.length,racingLine:O},worstRadius:{centreLine:G(n.curvature),racingLine:G(I)}}},y=o.closed?0:1,R=o.closed?a-1:a-2,M=R-y+1,v=new Array(M),x=new Array(M);for(let T=0;T<M;T++)v[T]=p[y+T],x[T]=f[y+T];if(!o.closed&&M>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(M-1,a-1),v[0]=x[0]=Math.min(x[0],Math.max(v[0],0))}if(M<7)return g(u);let k=T=>{let S=s(T),P=[...Pi(S.x,S.y,o.closed).map(Math.abs)].sort((L,D)=>L-D);return{integral:i(S),tail:P[Math.floor(.99*(P.length-1))]}},F=[...u],w=k(u),C;for(let T=0;T<r.passes;T++){let S=s(F),{res:A,jac:P}=m2(S.x,S.y,o.nx,o.ny,o.closed),{M:L,b:D}=p2(P,A,y,R,o.closed),I=UM(L,D,v.map((W,E)=>W-F[y+E]),x.map((W,E)=>W-F[y+E]),{maxIter:r.iterations,bounds:C});C=I.bounds;let G=new Array(a).fill(0);for(let W=0;W<M;W++)G[y+W]=I.x[W];o.closed||(G[0]=G[1],G[a-1]=G[a-2]);let O=!1;for(let W of s2){let E=F.map((V,N)=>V+W*G[N]),_=k(E);if(_.integral<w.integral*(1-1e-6)){F=E,w=_,O=!0;break}}if(!O)break}return g(F)}function _b(e){let t=Math.max(Z(e,"track_front"),Z(e,"track_rear"));return(t>0?t/2e3:.6)+.1}function em(e,t,r={}){if(!r.racingLine)return{asset:e,numerics:t,line:null};let n=r.params?_b(r.params):void 0,o=Ib(e,{...r.line,...n?{carHalfWidth:n}:{}});return{asset:o.asset,numerics:{...t,fitSpacing:0},line:o}}function Li(e,t,r={}){let n=em(e,t,r);return{track:yt(n.asset,n.numerics),line:n.line}}function Nb(e=4,t=Li){let r=new WeakMap;return(n,o,a={})=>{let s=a.racingLine===!0,i=s?[a.params?_b(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 QM={racingLine:!1,standingStart:!1},tm=256;function Di(e,t,r,n,o=QM,a=Li){let s=Zn(n),{racingLine:i,standingStart:c,lapCounts:l}=o;return e.map(u=>{let{track:m}=a(t,r,{racingLine:i,params:u});return bb(yi(u,s,{track:m,numerics:r,standingStart:c,lapCounts:l}))})}function Ob(e,t){let r=Zn(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 Vb(e,t,r){let n={};for(let o of Zn(e).metrics)n[o.key]=o.value(t,r);return n}var rm=36;var Gb=287.05287,g2=461.495,nm=9.80665/(Gb*.0065),y2=101325/(Gb*288.15),x2=273.15,R2=-500,v2=6e3,k2=400,M2=1100,om={source:"car",altitudeM:0,pressure:{kind:"standard"},humidityPct:0};function S2(e){return 101325*Math.pow(1-.0065*e/288.15,nm)}function A2(e){return 288.15/.0065*(1-Math.pow(e/y2,1/(nm-1)))}function F2(e){return 288.15/.0065*(1-Math.pow(e/101325,1/nm))}function w2(e,t){return e*Math.pow(1-.0065*t/288.15,nm)}function C2(e){return 611.21*Math.exp((18.678-e/234.5)*(e/(257.14+e)))}function T2(e,t){switch(e.kind){case"standard":return S2(t);case"qnh":return w2(e.hPa*100,t);case"station":return e.hPa*100}}function Ei(e,t,r=0,n=F2(e)){let o=t+x2,a=Math.min(.5*e,Math.max(0,Math.min(100,r))/100*C2(t)),s=e-a,i=s/(Gb*o)+a/(g2*o);return{altitudeM:n,p:e,pDry:s,T:o,rho:i,densityAltitudeM:A2(i)}}function ZM(e,t){return Ei(T2(e.pressure,e.altitudeM),t,e.humidityPct,e.altitudeM)}var Bb=(e,t,r)=>Math.min(r,Math.max(t,e)),$b=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function am(e){if(!e||typeof e!="object")return structuredClone(om);let t=e,r=t.pressure??{},n=Bb($b(r.hPa,1013.25),k2,M2),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:Bb($b(t.altitudeM,0),R2,v2),pressure:o,humidityPct:Bb($b(t.humidityPct,0),0,100)}}var Ii=e=>e?.source==="venue";var P2=Math.PI/180;function L2(){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 D2(){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 Kb(e){let t=-e*P2;return q([0,Math.cos(t),Math.sin(t)])}function sm(){let e={rodType:"push",pushrodAttach:"lowerArm",steerMode:"rack",spinAxis:Kb(-1),loadedRadius:230,springRate:35,rackAxis:[0,1,0]};return{hardpoints:L2(),config:e}}function _i(){let e={rodType:"pull",pushrodAttach:"lowerArm",steerMode:"fixed",spinAxis:Kb(-1.5),loadedRadius:232,springRate:40,rackAxis:[0,1,0]};return{hardpoints:D2(),config:e}}function im(){let e=[-25,635,460],t=[-40,600,710],r={layout:"mcpherson",actuation:"direct",rodType:"push",pushrodAttach:"upright",steerMode:"rack",spinAxis:Kb(-.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 Hb(){return{front:sm(),rear:_i(),config:{wheelbase:1600,trackFront:1200,trackRear:1220,frontAxleX:800}}}var E2=Math.PI/180;function JM(e){let t=-e*E2;return q([0,Math.cos(t),Math.sin(t)])}function zb(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:JM(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]=I2(o[l]);return{hardpoints:o,config:c}}function I2(e){return e.map(t=>Math.round(t*10)/10+0)}function eo(e){return{name:e.name,front:zb(sm(),e.front),rear:zb(_i(),e.rear),config:{wheelbase:e.wheelbase,trackFront:e.trackFront,trackRear:e.trackRear,frontAxleX:e.wheelbase/2}}}function Ca(e,t,r){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:t}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:r}}}}var Ta=600,to=610,Pa=230,ro=232;function no(){let e=Hb();return{...e,name:"Formula Student",front:{...e.front,config:{...e.front.config,actuation:"rocker"}},rear:{...e.rear,config:{...e.rear.config,actuation:"rocker"}}}}function Yb(){return eo({name:"Formula 1",wheelbase:3600,trackFront:1600,trackRear:1600,front:{kx:1.3,ky:800/Ta,kz:355/Pa,lowerInnerDz:-5,upperInnerDz:0,camberDeg:-3,loadedRadius:355,springRate:200},rear:{kx:1.3,ky:800/to,kz:355/ro,lowerInnerDz:35,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:220}})}function Ni(){return Ca(eo({name:"GT car",wheelbase:2700,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/Ta,kz:325/Pa,lowerInnerDz:18,upperInnerDz:5,camberDeg:-3.5,loadedRadius:325,springRate:110,actuation:"direct"},rear:{kx:1.2,ky:825/to,kz:325/ro,lowerInnerDz:36,upperInnerDz:15,camberDeg:-2,loadedRadius:325,springRate:120,actuation:"direct"}}),318.6,318.6)}function Oi(){return Ca(eo({name:"Sports car",wheelbase:2750,trackFront:1550,trackRear:1550,front:{kx:1.15,ky:775/Ta,kz:320/Pa,lowerInnerDz:36,upperInnerDz:15,camberDeg:-.5,loadedRadius:320,springRate:55,actuation:"direct"},rear:{kx:1.15,ky:775/to,kz:320/ro,lowerInnerDz:57,upperInnerDz:25,camberDeg:-1,loadedRadius:320,springRate:60,actuation:"direct"}}),305.4,309)}function _2(e,t,r,n,o,a){let s=im(),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:JM(n),springRate:o,rackTravel:a}}}function eS(){return Ca({name:"Cup car",front:_2(55,-25,-23,-3.5,150,55),rear:zb(_i(),{kx:1.15,ky:820/to,kz:320/ro,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 tS(){return{...Ca(eo({name:"Stock car",wheelbase:2794,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/Ta,kz:355/Pa,lowerInnerDz:20,upperInnerDz:5,camberDeg:-2.5,loadedRadius:355,springRate:175,actuation:"direct"},rear:{kx:1.2,ky:825/to,kz:355/ro,lowerInnerDz:40,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:150,actuation:"direct"}}),343.8,345.3),chassis:{boxes:[],body:"nascar"}}}function rS(){let e=Ca(eo({name:"Hill-climb prototype",wheelbase:2550,trackFront:1580,trackRear:1540,front:{kx:1.1,ky:790/Ta,kz:300/Pa,lowerInnerDz:10,upperInnerDz:5,camberDeg:-2.5,loadedRadius:300,springRate:90},rear:{kx:1.1,ky:770/to,kz:300/ro,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 nS(){let e=Ca(eo({name:"Race truck",wheelbase:3700,trackFront:2050,trackRear:1950,front:{kx:1.5,ky:1025/Ta,kz:506/Pa,lowerInnerDz:40,upperInnerDz:10,camberDeg:-.5,loadedRadius:506,springRate:200,actuation:"direct"},rear:{kx:1.5,ky:975/to,kz:506/ro,lowerInnerDz:60,upperInnerDz:20,camberDeg:-.25,loadedRadius:506,springRate:160,actuation:"direct"}}),490.4,495.6);return{...e,front:{...e.front,config:{...e.front.config,rackTravel:60}},chassis:{boxes:[],body:"truck"}}}var tt=(e,t,r)=>({value:e,label:t,unit:r}),oS=(e,t)=>({...nr[e],value:t});function aS(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 oo(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 $r(e){let t={name:e.name,m:tt(e.m,"vehicle mass (with driver)","kg"),A:tt(e.A,"frontal area","m^2"),c_l:tt(e.cl,"downforce coefficient","-"),c_w:tt(e.cw,"drag coefficient","-"),l_to_d_ratio:tt(e.cw>0?e.cl/e.cw:0,"lift-to-drag ratio","-"),driven_wheels:tt(e.drivenWheels,"driven wheels","-"),fr_0:tt(-.012,"rolling-resistance coefficient","-"),front_aero_diss:tt(e.frontAero,"front aero distribution","-"),front_mass_diss:tt(e.frontMass,"front mass distribution","-"),r_dyn:tt(e.rDyn,"dynamic tyre radius","m"),rho:tt(1.2,"air density","kg/m^3"),gear_ratio:tt(e.gearRatio,"gear ratio","-"),effi_pgb:tt(e.drivetrainEfficiency,"drivetrain efficiency","-"),capacity:tt(e.capacityAh,"pack capacity","Ah"),soc:tt(1,"state of charge","-"),ocv:tt(e.ocv,"pack open-circuit voltage","V"),power_scale:tt(1,"power scaling factor","-"),power_limit_kw:oS("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]=oS(r,n);return t}var La={name:"Formula Student",m:300,A:1,cl:3,cw:1.3,frontMass:.47,frontAero:.45,rDyn:.222,drivenWheels:2,gearRatio:11.5,motor:aS(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}},jb={name:"Formula 1",m:798,A:1.5,cl:3,cw:.9,frontMass:.46,frontAero:.44,rDyn:.35,drivenWheels:2,gearRatio:4.9,motor:oo(735,2e3,12500,2500,2),motorCount:1,driveline:{rear:bt.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}},cm={name:"GT car",m:1300,A:2,cl:1.4,cw:.42,frontMass:.5,frontAero:.42,rDyn:.33,drivenWheels:2,gearRatio:3.43,motor:oo(410,2e3,8e3,2e3,2),motorCount:1,driveline:{rear:bt.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}},lm={name:"Sports car",m:1600,A:2.2,cl:-.1,cw:.3,frontMass:.55,frontAero:.5,rDyn:.32,drivenWheels:2,gearRatio:3.14,motor:oo(220,1500,6500,1400,2),motorCount:1,driveline:{rear:bt.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}},Ub={name:"Cup car",m:1265,A:2.1,cl:.45,cw:.4,frontMass:.62,frontAero:.45,rDyn:.31,drivenWheels:2,gearRatio:3.5,motor:oo(250,2e3,7e3,1190,2),motorCount:1,motorPlacement:"front",driveline:{front:bt.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}},Xb={name:"Stock car",m:1620,A:2.2,cl:.6,cw:.45,frontMass:.53,frontAero:.45,rDyn:.35,drivenWheels:2,gearRatio:4.1,motor:oo(500,2500,9e3,1680,2),motorCount:1,driveline:{rear:bt.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}},qb={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:oo(330,3e3,8500,1240,2),motorCount:1,driveline:{rear:bt.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}},Qb={name:"Race truck",m:5300,A:6.2,cl:-.1,cw:.65,frontMass:.6,frontAero:.6,rDyn:.502,drivenWheels:2,gearRatio:3.55,motor:oo(880,100,3e3,88e3,2),motorCount:1,driveline:{rear:bt.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 Wb(e,t,r){return $r(r({...structuredClone(e),name:t}))}var um={[La.name]:$r(La),"Formula Student +15% downforce":Wb(La,"Formula Student +15% downforce",e=>({...e,cl:e.cl*1.15,cw:e.cw*1.08})),"Formula Student -15 kg":Wb(La,"Formula Student -15 kg",e=>({...e,m:e.m-15})),"Formula Student +15% power":Wb(La,"Formula Student +15% power",e=>({...e,motor:aS(25*1.15,15e3,2e4),powerLimitKw:80*1.15})),[jb.name]:$r(jb),[cm.name]:$r(cm),[lm.name]:$r(lm),[Ub.name]:$r(Ub),[Xb.name]:$r(Xb),[qb.name]:$r(qb),[Qb.name]:$r(Qb)},sS=Object.keys(um),Zb=sS.slice(0,4),Jb=[La.name,jb.name,cm.name,lm.name,Ub.name,Xb.name,qb.name,Qb.name];var $ee={"Touring car":cm.name,"Street car":lm.name};var N2={bg:"#0e1116",panel:"#161b22",panel2:"#1c232d",border:"#2a323d",borderBright:"#39424e",sunken:"#11161c",ink:"#06090d"},O2={normal:"#d6dde6",dim:"#8b96a3",bright:"#e7ecf3",white:"#ffffff"},V2={label:"#c8d2dc",grid:"#39424e",gridFaint:"#232b35",empty:"#1a2028"},B2={accent:"#4aa3ff",accentInk:"#04121f",warn:"#ffb454",good:"#4ec9a0",bad:"#ff6b6b",badSoft:"#ff8f8f"},$2=["#f0e442","#7b68ee","#f7a8b8","#d55e00","#d8b4fe","#b5e48c"],mm={front:"#a6e22e",rear:"#00b4d8"},iS=["#5b4bd6","#4aa3ff","#4ec9a0","#f0e442"],eg={power:"#ffb454",traction:"#f0845c",front:mm.front,rear:mm.rear,grip:"#73c9b3",braking:"#b48aff",crest:"#e88fd0",below:"rgba(214, 221, 230, 0.32)"},G2={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"},K2={x:"#ff6b6b",y:"#57c75a",z:"#4aa3ff"},H2={line:"#b4bfcb"},z2={compression:"#b48aff",tension:"#ff6b6b"},Y2={fz:"#e7ecf3",fx:"#7ad7f0",fy:"#ff54c8"},W2={drivenLine:"#4d7cff",axis:"#eef3fa",slip:"#ffe81a",drive:eg.power,brake:eg.braking},j2={ground:"#101920",grid:"#1a2630",gridMajor:"#26343f",horizon:"#1d2833",bridge:"#6f7a86",coneLeft:"#2f63c9",coneRight:"#d9b51f",coneStart:"#ee7a2c"},U2={chassis:"#435160",volume:"#303b47",tyre:"#435160",tyreLine:"#39424e",tyreFace:"#1c232d"},X2={centreLine:"#4aa3ff",corridorFill:"rgba(74,163,255,0.10)",boundary:"#3d4956",racingLine:"#ffb454",start:"#e7ecf3",finish:"#ff6b6b",direction:"#8b96a3"},q2={SURFACE:N2,TEXT:O2,CHART:V2,ROLE:B2,SERIES:$2,AXLE:mm,LAP_SPEED:iS,LIMITER:eg,RIG:G2,AXIS:K2,CONSTRUCTION:H2,FORCE:z2,TYRE_FORCE:Y2,REPLAY:W2,SCENERY:j2,BODY:U2,TRACK:X2},cS=e=>Object.fromEntries(Object.entries(e).map(([t,r])=>[t,Array.isArray(r)?Object.freeze([...r]):Object.freeze({...r})])),pm=cS(q2),xt=pm.SERIES,lS=(()=>{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 cS({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 uS=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},Kee=(()=>{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=pm[r],o=lS[r];for(let a of Object.keys(n)){let s=uS(n[a]);s&&!e.has(s)&&e.set(s,o[a])}}return e})();var mS=(e,t)=>new Set(t.flatMap(r=>{let n=e[r];return Array.isArray(n)?[...n]:Object.values(n)}).map(uS).filter(r=>r!==null)),Hee=mS(lS,["SERIES","AXLE","LAP_SPEED","LIMITER","ROLE","RIG","FORCE","TYRE_FORCE","REPLAY","AXIS","TRACK","CONSTRUCTION"]),zee=mS(pm,Object.keys(pm).filter(e=>e!=="SURFACE"));function tg(){return{kind:"simple",name:"Simple motor",rpm:[0,16e3,2e4],torque:[21,21,14],efficiency:.95}}function rg(){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 ag(){return{kind:"ice",name:"Formula 1 power unit (example)",rpm:[4e3,5e3,6e3,7e3,8e3,9e3,1e4,10500,11e3,11500,12e3,12500],torque:[896,822,773,738,712,692,675,668,638,610,585,545],idleRpm:4e3,limitRpm:12500,inertia:.02,gearbox:{primary:1,ratios:[4,3.15,2.575,2.175,1.85,1.6,1.375,1.18],efficiency:.94,upshiftTime:0,downshiftTime:0,driveKept:1},breathing:{induction:{kind:"boosted",boostKPa:350,maxPressureRatio:5}}}}function pS(){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 dS(){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 fS(){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 hS(){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 bS(){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 gS(){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 yS(e){return qn(Q2(e))}function Q2(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 Vi(e,t){return{...t,fingerprint:yS(e)}}var xS="CC-BY-4.0",Z2={title:"PaceDynamics built-in library",url:"https://pacedyn.dev/",licence:xS},RS={fidelity:"generic",licence:xS,sources:[Z2]};var dm=e=>Vi(e,RS);var vS=["raw.githubusercontent.com"],kS=["tum-csv"],e_=/^[0-9a-f]{64}$/;function $i(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"||!e_.test(r)||!kS.includes(n))return!1;try{let o=new URL(t);return o.protocol==="https:"&&vS.includes(o.hostname)&&!o.username&&!o.password&&!o.port}catch{return!1}}var fm=e=>new URL(e.url).hostname;async function MS(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 t_(e){let t=new URL(e).pathname.split("/").pop()??"";return decodeURIComponent(t).replace(/\.[^.]*$/,"")||"Linked track"}function r_(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 n_={"tum-csv":r_};function SS(e,t){return n_[t.format](e,t_(t.url))}async function sg(e,t,r){let n=await MS(e);if(n!==t.sha256)throw new Error(`${fm(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=SS(new TextDecoder().decode(e),t),a=await hm(o);if(a!==r)throw new Error(`Linked track ${r} does not convert to its name (it is ${a}).`);return o}var ig=20,a_=new RegExp(`^[0-9a-f]{${ig}}$`),Gi=e=>typeof e=="string"&&a_.test(e);async function hm(e){let t=new TextEncoder().encode(pn(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,ig)}var cg=e=>`tracks/${e}.json`;var s_=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function lg(e){return{model:{name:e.name,source:e.source},...e.provenance?{provenance:e.provenance}:{}}}async function ug(e,t){if(!s_(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 hm(e);if(r!==t)throw new Error(`Catalogue track ${t} does not match its name (it is ${r}).`);return e}var ao=(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}),dn=[ao("suspensions","suspensionId","suspension"),ao("tires","tireModelId","tyre",[{key:"tiresRear",ref:"tireModelIdRear",label:"rear tyre"}]),ao("motors","motorModelId","motor"),ao("aeros","aeroModelId","aero map"),ao("batteries","batteryModelId","battery"),ao("brakes","brakeModelId","brakes"),ao("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 bm(e){let t={...e};for(let r of dn)for(let n of r.refs)delete t[n];return t}var gm=xt,Ki=gm,mg=gm,fn=[...xt.slice(3),...xt.slice(0,3)],fg=[...xt.slice(1),xt[0]],pg=[...xt.slice(2),...xt.slice(0,2)],dg=[...xt.slice(4),...xt.slice(0,4)],hg=[...xt.slice(5),...xt.slice(0,5)],Hi=[...xt.slice(2),...xt.slice(0,2)];function bg(){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 gg(e,t,r){let n=um[e];if(!n)throw new Error(`no preset vehicle named "${e}"`);return{id:t,params:{...Ws(structuredClone(n)),energy:{...Fr},suspensionId:"sus1"},visible:!0,color:Ki[r%Ki.length]}}function l_(){return Zb.map((e,t)=>gg(e,`v${t+1}`,t))}function u_(){return[ks(),Zd(),Jd(),ef(),tf(),rf(),nf(),of(),af(),sf()].map((t,r)=>({id:`t${r+1}`,color:mg[r%mg.length],model:t}))}function m_(){return[_p(),Np(),Op(),Vp(),Bp(),$p(),Gp(),Kp()].map((t,r)=>({id:`a${r+1}`,color:pg[r%pg.length],model:t}))}function p_(){return[Rp(),vp(),kp()].map((t,r)=>({id:`b${r+1}`,color:dg[r%dg.length],model:t}))}function d_(){return[{id:"brk1",color:hg[0],model:structuredClone(Ff)}]}function f_(){return[{id:"dmp1",color:Hi[0],model:structuredClone(Xl)}]}function h_(){return[tg(),rg()].map((t,r)=>({id:`m${r+1}`,color:fn[r%fn.length],model:t}))}function yg(e){let t=r=>({...r,provenance:dm(r.model)});return{...e,suspensions:e.suspensions.map(t),vehicles:e.vehicles.map(r=>({...r,provenance:dm(bm(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 zi(e="Untitled project"){let t=new Date().toISOString(),r=l_();return yg({schemaVersion:rm,meta:{id:bg(),name:e,domain:"racecar",rulesetId:Qn,createdAt:t,updatedAt:t},suspensions:[{id:"sus1",color:fg[0],model:no()}],activeSuspensionId:"sus1",vehicles:r,activeVehicleId:r[0]?.id??null,tires:u_(),motors:h_(),aeros:m_(),batteries:p_(),brakes:d_(),dampers:f_(),tracks:[],activeTrackId:null,mathChannels:[],rulesets:[],studies:[],activeStudyId:null,loadCases:[],reportLayouts:[],tyreSheets:[],kinSheets:[],plans:[],results:[],settings:{numerics:{...ci},ggvMode:"twoTrack",quasiTransient:!1,motorThermal:!1,brakeFade:!1,airTempC:St,air:structuredClone(om),diffYaw:!1,lapCounts:{},pathPlanId:null,useRacingLine:!0,standingStart:!1}})}var b_=9.81,Yi={speed:20,ayG:1.2};function xg(e,t={}){let r=t.operating??Yi,n=t.assemble,o,a,s,i=new Map,c=new Map,l=new Map,u=new Map,m=g=>({speed:g?.speed!==void 0&&Number.isFinite(g.speed)&&g.speed>0?g.speed:r.speed,ayG:g?.ayG!==void 0&&Number.isFinite(g.ayG)?g.ayG:r.ayG}),f=()=>{if(o!==void 0)return o;if(!n)return o=null;try{o=n(e)}catch{o=null}return o},p=()=>{if(a!==void 0)return a;try{a=sr(e.params)}catch{a=null}return a},d=g=>{let y=m(g),R=`${y.speed}|${y.ayG}`,M=i.get(R);if(M!==void 0)return M;let v=p();if(!v)return i.set(R,null),null;let x={cornerStiffness:k=>v.corneringStiffness(k),ayG:y.ayG,speed:y.speed,fyAxle:(k,F)=>2*v.Fy(k,F/2),tire:v};return i.set(R,x),x},h=()=>{if(s!==void 0)return s;let g=f(),y=p();if(!g||!y)return s=null;try{s=Nn(y,g.massTotal*b_*1.2)}catch{s=null}return s},b=g=>{let y=m(g).speed,R=`${y}`,M=c.get(R);if(M!==void 0)return M;let v=f(),x=p(),k=null;if(v&&x)try{k=kh(v,x,y,{steering:!1})}catch{k=null}return c.set(R,k),k};return{operating:r,dynAvailable:!!n,operatingAt:m,dynInput:f,tyre:p,dynCtx:d,grip:h,ymd:b,ymdLimit:g=>{let y=`${m(g).speed}`,R=l.get(y);if(R!==void 0)return R;let M=b(g),v=M?eb(M):null;return l.set(y,v),v},reserves:(g,y)=>{let R=m(y),M=`${g}|${R.speed}|${R.ayG}`,v=u.get(M);if(v!==void 0)return v;let x=f(),k=d(y),F=null;if(x&&k)try{F=fi(x,k,g,h()??void 0)}catch{F=null}return u.set(M,F),F}}}var AS=["widthLeft","widthRight","bank","mu"];function Wi(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 Rg(e){let t=Wi(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 xm(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 AS){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 Rm(e,t,r){if(!t.length)return e;let n=Wi(e),o=n.length,a={widthLeft:ym(e.widthLeft,r.widthLeft),widthRight:ym(e.widthRight,r.widthRight),bank:ym(e.bank,r.bank),mu:ym(e.mu,r.mu)},s={};for(let c of AS){let l=e[c];Array.isArray(l)&&l.length===o&&(s[c]=l)}let i=xm(t,n,a,s);return{...e,...i}}function ym(e,t){return typeof e=="number"?e:t}var CS=1,FS=4,km=Math.PI/180,vg=e=>e===null||!Number.isFinite(e)||e===0?0:1/e;function kg(e){return e.kind==="arc"?Math.abs(e.radius)*Math.abs(e.angle)*km:e.length}function vm(e,t){return e.kind==="straight"?0:e.kind==="arc"?vg(e.radius):t}function wS(e){return e.kind==="straight"?0:e.kind==="arc"?vg(e.radius):vg(e.endRadius)}var ji=(e,t,r,n,o)=>e+t*o+(n>0?(r-t)*o*o/(2*n):0);function Ui(e,t={}){let r=Math.max(.05,t.spacing??CS),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+kg(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*km,b=e.length?vm(e[0],0):0,g=0,y=f,R=(S,A,P)=>{s.push(S),i.push(A),c.push(P)};R(p,d,0);let M=(S,A,P,L,D)=>{let I=D-L;if(I<=0)return;if(Math.abs(A-S)<1e-12){let O=ji(h,S,S,P,L);if(Math.abs(S)<1e-12)p+=I*Math.cos(O),d+=I*Math.sin(O);else{let W=O+S*I;p+=(Math.sin(W)-Math.sin(O))/S,d+=-(Math.cos(W)-Math.cos(O))/S}return}let G=I/FS;for(let O=0;O<FS;O++){let W=L+O*G,E=ji(h,S,A,P,W),_=ji(h,S,A,P,W+G/2),V=ji(h,S,A,P,W+G);p+=G/6*(Math.cos(E)+4*Math.cos(_)+Math.cos(V)),d+=G/6*(Math.sin(E)+4*Math.sin(_)+Math.sin(V))}};for(let S of e){let A=kg(S),P=vm(S,b),L=wS(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 I=Math.min(A,y-g);M(P,L,A,D,I),D=I,R(p,d,g+I),y+=f}M(P,L,A,D,A),h=ji(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 k=e.length?vm(e[0],b):0,F={gap:v,headingError:g_((h-o.heading*km)/km),curvatureError:b-k},w=[];for(let S=0;S<e.length;S++){let A=wS(e[S]),P=S+1<e.length?e[S+1]:n?e[0]:null;if(!P)continue;let L=vm(P,A);w.push({index:S,before:A,after:L,jump:Math.abs(L-A)})}let C=xm(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 g_(e){let t=e%360;return t>180&&(t-=360),t<-180&&(t+=360),t}var y_={halfWidthM:1.5,spacingM:.5};function Xi(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 ${PS(e).toFixed(0)} m`}}}function PS(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 LS=e=>e.kind==="skidpad"||e.kind==="curves"&&e.closed===!0,DS=e=>e.kind==="acceleration",ES=1.5,IS=3;function x_(e,t){let r=e.offsetM,n=e.pitchM,o=Math.max(1,e.gates)*n,a=Math.max(0,e.leadInM),s=ES*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*(IS*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:Xi(e),x:m,y:f,closed:!1,widthLeft:t.halfWidthM,widthRight:t.halfWidthM,fit:"interpolate"}}function R_(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 Mg(e,t={}){let r={...y_,...t},n=DS(e),o=R_(e);if(!o){let u=x_(e,r);return{asset:u,peakCurvature:TS(u),worstJoint:0,standingStart:n}}let a=LS(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*(IS*Math.PI/180))):r.spacingM,c=Ui(o,{name:Xi(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:TS(c.asset),worstJoint:l.reduce((u,m)=>Math.max(u,m.jump),0),standingStart:n}}function TS(e){try{return Math.max(...yt(e).curvature.map(Math.abs))}catch{return NaN}}var Sm={courses:[{id:"c1",course:{kind:"manoeuvre",spec:{kind:"skidpad",radiusM:8.375}}}],ggvMode:"twoTrack"};function Sg(e){return e.course.kind==="project"?"the project\u2019s track":e.course.kind==="track"?e.course.name:Xi(e.course.spec)}var _S=new WeakMap,Mm=new Map;function NS(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=Mm.get(n);if(o)return{...o,numerics:r};let a=Mg(e.spec),s={asset:a.asset,standingStart:a.standingStart};return Mm.size>64&&Mm.clear(),Mm.set(n,s),{...s,numerics:r}}function Ag(e,t,r={}){let n=r.lap??Sm,o=r.simParams,a=r.numerics??{},s=n.courses.length?n.courses:Sm.courses,i,c,l,u=new Map,m=new Map,f=new Map,p=new Map,d=M=>(M?.courseId?s.find(v=>v.id===M.courseId):void 0)??s[0],h=()=>{if(i!==void 0)return i;if(!o)return i=null;try{i={...o(e),ggvMode:n.ggvMode}}catch{i=null}return i},b=M=>{let v=d(M);if(!v)return null;let x=m.get(v.id);if(x!==void 0)return x;let k=NS(v.course,r,a),F=null;if(k)try{let w=JSON.stringify(k.numerics),C=_S.get(k.asset);C||(C=new Map,_S.set(k.asset,C));let T=C.get(w);T||(T=yt(k.asset,k.numerics),C.set(w,T)),F={id:v.id,track:T,standingStart:k.standingStart,numerics:k.numerics,name:k.asset.name}}catch{F=null}return m.set(v.id,F),F},g=()=>{if(c!==void 0)return c;let M=h();if(!M)return c=null;try{l=Ft(M),c=ir(l,!1,n.ggvMode)}catch{c=null}return c},y=M=>{let v=b(M);if(!v)return null;let x=f.get(v.id);if(x!==void 0)return x;let k=g(),F=null;if(k)try{let w=l?jn(l,k,[v.track],v.numerics,n.ggvMode,u):void 0,C=l?un(l,k.rows):void 0;F=gt(k,v.track,v.numerics,{standingStart:v.standingStart,...w?{load:w}:{},...C?{shifts:C}:{}})}catch{F=null}return f.set(v.id,F),F};return{lapSettings:n,get lapAvailable(){return!!o&&s.some(M=>!!NS(M.course,r,a))},lapParams:h,courses:()=>s,course:b,ggv:g,lap:y,lapReserve:M=>{let v=b(M);if(!v)return null;let x=p.get(v.id);if(x!==void 0)return x;let k=y(M),F=t.dynInput(),w=t.tyre(),C=null;if(k&&F&&w)try{let T=h();C=Pu(F,w,{v:k.v,ax:k.ax,ay:k.ay,ds:v.track.ds,axDrag:Ma(g()?.rows,k.v),...k.axScrub?{axScrub:k.axScrub}:{},axGrade:ln(v.track.gradient,k.v.length),bank:v.track.bank,...k.loadFactor?{loadFactor:k.loadFactor}:{}},T?{driven:Gf(T)}:{})}catch{C=null}return p.set(v.id,C),C}}}var OS=180/Math.PI,Fg={rise:0,sinPitch:0,sinRoll:0};function VS(e){let t=e.kc;return t?BS(e.vehicle,r=>t.ground0[r]):Fg}function BS(e,t){let r=e.config,n=Do(r),o=0,a=0,s=0,i=0,c=0,l=0,u=0,m=0,f=0;for(let g of Lo){let y=Ze(g,r),R=y.axleX-n,M=y.sideSign*Ur(e,y.isFront)/2,v=t(g);if(!Number.isFinite(v))return Fg;o++,a+=R,s+=M,i+=v,c+=R*R,l+=M*M,u+=R*M,m+=R*v,f+=M*v}let p=o*(c*l-u*u)-a*(a*l-u*s)+s*(a*u-c*s);if(!(Math.abs(p)>1e-9))return{rise:i/o,sinPitch:0,sinRoll:0};let d=(i*(c*l-u*u)-a*(m*l-u*f)+s*(m*u-c*f))/p,h=(o*(m*l-u*f)-i*(a*l-u*s)+s*(a*f-m*s))/p,b=(o*(c*f-m*u)-a*(a*f-m*s)+i*(a*u-c*s))/p;return{rise:d,sinPitch:h,sinRoll:-b}}function qi(e,t){let r=e.kc,n=BS(e.vehicle,o=>(r?r.ground0[o]:0)+t[o]);return q([-n.sinPitch,n.sinRoll,1])}function wg(e,t,r,n){let o=q(Xr(e,Ze(t,r)));return-Math.asin(Math.max(-1,Math.min(1,X(o,n))))*OS}function Am(e,t,r,n,o){let a=q(Xr(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=Xa({uprightUpper:c(u.uprightUpper),uprightLower:c(u.uprightLower),wheelCenter:c(u.wheelCenter),spinAxis:m,tieOuter:c(u.tieOuter),loadedRadius:o.loadedRadius,patchShift:o.patchShift&&v_(o.patchShift,e.metrics.toe/OS,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 v_(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 $S(e,t){let r=VS(t);if(r===Fg)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 Cg(e,t,r){let n=$S({heave:0,pitch:0,roll:0,steer:0},r);return e-rd(n,[t,0,0],Do(r.vehicle.config))}var k_=180/Math.PI;function Tg(e,t){return!e.valid||!e.ic?!1:Math.hypot(e.ic[0]-e.cp[0],e.ic[1]-e.cp[1])<=t}function Fm(e,t,r){let n=Ze(t,e.vehicle.config),o=ft(e,r),a=eu(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=qi(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},M=a.omega[1],v=Math.hypot(m[0],m[1]),x=Math.abs(M)*1e9>v?[p[0]+m[1]/M,p[1]-m[0]/M]: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)*k_,tanTheta:S,tanThetaHub:R(f),valid:!0,sinAngle:F}}function GS(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 S_=180/Math.PI,A_=Math.PI/180,Pg=.5,wm=2,Lg=.25,F_={heave:0,pitch:0,roll:0,steer:0},w_={FL:"FR",FR:"FL",RL:"RR",RR:"RL"},Cm=e=>e.ok?e.state:{...e.nearest,converged:!1};function Dg(e,t,r){return t.state?t.solved===!1?{...t.state,converged:!1}:t.state:Cm(ge(e,t.travel,t.steer,void 0,r))}var KS=new WeakMap;function HS(e,t){let r=e.ctx[t],n=$e(e.vehicle,t).config.loadedRadius,o=Qt(n,e.kc,t),a=KS.get(r);a||(a=new Map,KS.set(r,a));let s=a.get(o);if(!s){let i=qr(t,e.vehicle.config,F_,e.vehicle);s=Cm(ge(r,i.travel,i.steer,void 0,o===n?void 0:{loadedRadius:o})),a.set(o,s)}return s}var mr=(e,t)=>!e||!e.lo.converged||!e.hi.converged?NaN:(t(e.hi)-t(e.lo))/(2*e.step),zS=(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 WS(e,t,r,n,o){let a=e.vehicle.config,s=Po(r),i=$e(e.vehicle,r),c=Ze(r,a),l=e.ctx[r],u=ft(e,t),m=u[r],f={travel:m.travel,steer:m.steer},p=m.rigid?void 0:{loadedRadius:m.loadedRadius},d=Dg(l,m,p),h=HS(e,r),b={lo:Cm(ge(l,f.travel-Pg,f.steer,void 0,p)),hi:Cm(ge(l,f.travel+Pg,f.steer,void 0,p)),step:Pg},g=c.isFront?{lo:Ee(l,d.beta,f.steer-wm,void 0,p),hi:Ee(l,d.beta,f.steer+wm,void 0,p),step:wm}:null,y=z=>{let j=ft(e,{...t,roll:t.roll+z*A_})[r];return Dg(l,j,j.rigid?void 0:{loadedRadius:j.loadedRadius})},R={lo:y(-Lg),hi:y(Lg),step:Lg},M=T_(e,t,r,c.isFront,u,g),v=_t(d.points.contactPatch,c),x=_t(h.points.contactPatch,c),k=Math.abs(v[1])-Math.abs(x[1]),F=w_[r],w=u[F],C=Dg(e.ctx[F],w,w.rigid?void 0:{loadedRadius:w.loadedRadius}),T=C.converged?k+Math.abs(C.points.contactPatch[1])-Math.abs(HS(e,F).points.contactPatch[1]):NaN,S=o??or(e,t,s),A=tu(S,dt(i)),P=A?null:k1(S),L=c.sideSign>0?S.icRight:S.icLeft,D=L?Math.hypot(L[0]-v[1],L[1]-v[2]):1/0,I=Fm(e,r,t),G=I.ic?Math.hypot(I.ic[0]-I.cp[0],I.ic[1]-I.cp[1]):1/0,O=GS(I,s,a.wheelbase,n),W=-mr(b,z=>z.points.damperLength),E=i.config.springRate,_=mr(R,z=>z.metrics.camber),V=qi(e,{FL:u.FL.ground,FR:u.FR.ground,RL:u.RL.ground,RR:u.RR.ground}),N=e.kc?.loadCase,$=z=>N?Am(z,r,a,V,{loadedRadius:m.loadedRadius,patchShift:N.patchShift[r]}):z.metrics,K=$(d);return{id:r,converged:d.converged,travel:d.travel,camber:d.metrics.camber,camberRoad:wg(d.points.spinAxis,r,a,V),toe:d.metrics.toe,caster:K.caster,kpi:K.kpi,scrubRadius:K.scrubRadius,mechanicalTrail:K.mechanicalTrail,scrubAtWheel:K.scrubAtWheel,trailAtWheel:K.trailAtWheel,kingpinOffset:K.kingpinOffset,casterOffset:K.casterOffset,steeringArm:d.metrics.steeringArm,camberGain:mr(b,z=>z.metrics.camber),bumpSteer:mr(b,z=>z.metrics.toe),trackScrubRate:mr(b,z=>Math.abs(_t(z.points.contactPatch,c)[1])),casterGain:mr(b,z=>$(z).caster),kpiGain:mr(b,z=>$(z).kpi),scrubGain:mr(b,z=>$(z).scrubRadius),trailGain:mr(b,z=>$(z).mechanicalTrail),...c.isFront?{camberPerSteer:zS(g,z=>z.metrics.camber,z=>z.metrics.toe),steerJacking:-zS(g,z=>z.points.contactPatch[2],z=>z.metrics.toe),...M!==void 0?{steerLoad:M}:{}}:{},rollCamber:_,camberRecovery:-100*c.sideSign*_,rollSteer:c.sideSign*mr(R,z=>z.metrics.toe),halfTrackChange:k,trackChange:T,longitudinal:v[0]-x[0],rollCentreHeight:P?P.heightAboveGround:S.heightAboveGround,rollCentreHeightChassis:(P?P.height:S.height)-Cg(0,c.axleX,e),rollCentreLateral:S.lateralAlongGround,rollCentreValid:S.valid,rollCentreUsable:A,rollCentreHeightUsable:A||P!==null,rollCentreSinAngle:S.sinAngle,fvsaLength:D,svsaLength:G,swingArmAngle:I.swingArmAngleDeg,svsaUsable:Tg(I,a.wheelbase),svsaSinAngle:I.sinAngle,...s==="front"?{antiDive:O.brake,antiLift:O.drive}:{antiSquat:O.drive,antiLift:O.brake},decoupled:i.config.actuation==="decoupled",mcpherson:i.config.layout==="mcpherson",springRate:E,motionRatio:W,wheelRate:E*W*W,damperLength:d.points.damperLength,damperTravel:h.points.damperLength-d.points.damperLength,...C_(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)*S_,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 C_(e,t,r,n){if(e.config.actuation==="decoupled")return{};let o=n?{droop:n.droopStated?n.droop:null,bump:n.bump}:Io(t,e.config.coilover),a=t-r;return{...o.droop!==null?{damperToExtended:a-o.droop}:{},...o.bump!==null?{damperToClosed:o.bump-a}:{}}}function T_(e,t,r,n,o,a){if(!a||!n)return;let s=Wc(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)*wm,k=g.state?{q:[...g.state.pose.t,...g.state.pose.omega],phi:g.state.points.rockerAngle}:void 0,F=pt(ge(y,g.travel,g.steer-x,k,R)),w=pt(ge(y,g.travel,g.steer+x,k,R));if(!F||!w)return NaN;l[h]=w.points.contactPatch[2]-F.points.contactPatch[2],u[h]=br(i.curve[b],g.travel,w.points.damperLength)-br(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=as(p,h,[m.hi[0],m.hi[1]]),g=as(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 Qi(e,t,r,n,o){return WS(e,t,r==="front"?"FL":"RL",n,o)}function Eg(e,t,r,n){let o=Qi(e,t,"front",r,n?.front),a=Qi(e,t,"rear",r,n?.rear);return{front:o,rear:a,wheelbaseChange:o.longitudinal-a.longitudinal}}var Ig=Math.PI/180,Tm={travelSteps:9,heaveSteps:5,rollSteps:4,rackSteps:6},Pm={travelMin:-25,travelMax:25,rollMaxDeg:3,rollAtLimitDeg:2.5};function P_(e){let t=e.params;return{cgHeight:t.cg_height?ut({...t,surveyedRadiusFront:e.vehicle.front.config.loadedRadius,surveyedRadiusRear:e.vehicle.rear.config.loadedRadius}).cgHeight:300,...Yf(t),drive:Kf(t)}}function _g(e,t=Tm,r=Pm,n){let o=null,a=(S,A)=>(o||(o={violation:S,reason:A}),null),s=e.vehicle,i=S=>S==="front"?s.front:s.rear,c=null,l=null,u=()=>{if(c)return c;if(n)try{let S=n();if(S)return c=Ct(s,S.kc),l=S.cgHeight,c}catch{a(500,"the car could not be stood on its tyre: its rates did not assemble")}return c=Ct(s)},m=S=>S==="front"?"FL":"RL",f=S=>{let A=u();if(!A.kc)return;let P=i(S).config.loadedRadius,L=Qt(P,A.kc,m(S));return L===P?void 0:{loadedRadius:L}},p=(S,A)=>-ss(u(),m(S),A),d=new Map,h=new Map,b=new Map,g=new Map,y=new Map,R=new Map,M=new Map,v=null,x=()=>{if(v)return v;u();let S=P_(e);return v=l!==null&&Number.isFinite(l)?{...S,cgHeight:l}:S},k,F,w=()=>{if(F!==void 0)return F;let S=Zc(u().ctx.FL,Nt(s.front.config));return F=S?Jc(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,()=>jd(i(S))??null),sweep:S=>C(d,S,()=>{let A;try{A=qe(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(G=>G.travel),D=Math.max(...L)-Math.min(...L),I=r.travelMax-r.travelMin;return a(Math.max(0,I-D),`the ${S} linkage reaches only ${D.toFixed(0)} mm of the ${I.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 D=0;D<L;D++){let I=r.travelMin+(r.travelMax-r.travelMin)*D/(L-1);A.push(I),P.push(or(u(),{heave:p(S,I),pitch:0,roll:0,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in heave`)}return{at:A,rc:P}}),rcRoll:S=>C(g,S,()=>{let A=[],P=[],L=Math.max(2,t.rollSteps);try{for(let D=0;D<L;D++){let I=r.rollMaxDeg*D/(L-1);A.push(I),P.push(or(u(),{heave:0,pitch:0,roll:I*Ig,steer:0},S))}}catch{return a(500,`the ${S} roll-centre construction threw in roll`)}return{at:A,rc:P}}),steer:()=>{if(k!==void 0)return k;try{k=Cd(u(),{steerMax:Nt(s.front.config),steps:t.rackSteps})}catch{k=a(500,"the steering sweep threw")}let S=k?.filter(A=>!A.converged).length??0;if(k&&S>0){let A=w();k=A?a(A.violation,A.reason):a(100+10*S,`${S} of ${k.length} steering solves did not converge`)}return k??null},solveAt:(S,A,P=0)=>C(y,`${S}:${A}:${P}`,()=>{try{let L=ge(u().ctx[m(S)],A,P,void 0,f(S));return L.ok?L.state:L.why==="unconverged"?a(100,`the ${S} corner did not solve at ${A.toFixed(0)} mm of travel`):a(100+Math.abs(L.travelMiss),`the ${S} corner reaches only ${(A+L.travelMiss).toFixed(0)} of ${A.toFixed(0)} mm of travel`)}catch{return a(150,`the ${S} corner solve threw at ${A.toFixed(0)} mm of travel`)}}),readout:S=>C(R,`${S.heave}:${S.pitch}:${S.roll}:${S.steer}`,()=>{try{return Eg(u(),S,x())}catch{return a(500,"the derived readout threw")}}),readoutAtTravel:(S,A)=>C(M,`${S}:${A}`,()=>{try{return Qi(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*Ig),L=u();if(!L.kc)return P;try{let D=ft(L,{heave:0,pitch:0,roll:A*Ig,steer:0}),I=S==="front"?Math.max(D.FL.travel,D.FR.travel):Math.max(D.RL.travel,D.RR.travel);return Number.isFinite(I)?I:P}catch{return a(500,`the ${S} axle could not be rolled on its tyre`),P}},onTyre:()=>!!u().kc}}var L_=Nb();function Ng(e,t={}){let r=new Map;return{session(n){if(r.has(n))return r.get(n);let o=null,a=t.session?.();if(t.sessionParams&&a)try{let s=ju(n,a.rulesets),i=s?.events.some(c=>c.kind==="trackLap");if(s&&(a.track||!i)){let c=t.sessionParams(e),{standingStart:l,lapCounts:u}=a.settings,m=a.track?Di([c],a.track,a.numerics,wi(s),a.settings,L_)[0]:yi(c,s,{numerics:a.numerics,standingStart:l,lapCounts:u});o={};for(let f of s.metrics)yc(f)&&(o[f.key]=f.value(m,void 0))}}catch{o=null}return r.set(n,o),o}}}var Lm=Math.PI/180,Dm=1e-6;function US(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 Zi(e){let t=e.measured;if(t)return US(t.travel,t.camber);let r=q(e.config.spinAxis);return-Math.asin(Math.max(-1,Math.min(1,r[2])))/Lm}function Ji(e){let t=e.measured;if(t)return US(t.travel,t.toe);let[r,n]=e.config.spinAxis;return Math.atan2(r,n)/Lm}function Og(e,t){let r=Math.abs(t.camber)>=Dm,n=Math.abs(t.toe)>=Dm;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=(Zi(e)+t.camber)*Lm,l=(Ji(e)+t.toe)*Lm,[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 Em(e){let t=e&&typeof e=="object"?e.value:void 0;return typeof t=="number"&&Number.isFinite(t)?t:void 0}function D_(e,t){let r=t;return{front:Em(r.camber_front_deg)??Zi(e.front),rear:Em(r.camber_rear_deg)??Zi(e.rear)}}function E_(e,t){let r=t;return{front:Em(r.toe_front_deg)??Ji(e.front),rear:Em(r.toe_rear_deg)??Ji(e.rear)}}function I_(e){return{camber:{front:Zi(e.front),rear:Zi(e.rear)},toe:{front:Ji(e.front),rear:Ji(e.rear)}}}var jS=new WeakMap;function __(e,t){let r=I_(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)<Dm&&Math.abs(u.toe)<Dm;if(o(n.front)&&o(n.rear))return e;let a=`${t.camber.front}|${t.camber.rear}|${t.toe.front}|${t.toe.rear}`,s=jS.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&&Og(m,n[Po(u)])])):void 0,l={...e,front:Og(e.front,n.front),rear:Og(e.rear,n.rear),...c?{corners:c}:{}};return s||jS.set(e,s=new Map),s.size>=16&&s.clear(),s.set(a,l),l}function Im(e,t){return t?__(e,{camber:D_(e,t),toe:E_(e,t)}):e}var N_=9.81;function Da(e){let t=An(e),r=Math.max(0,e.unsprungPerCorner)*N_,n=a=>{let s=a==="FL"||a==="FR",i=s?"front":"rear",c=Ue(e,i),l=c>0?c:1/0,u=Ap(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:Bt(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 XS=new WeakMap;function O_(e){let t=Im(e.vehicle,e.params);if(t===e.vehicle)return e;let r=XS.get(e);return(!r||r.vehicle!==t)&&XS.set(e,r={...e,vehicle:t}),r}function Ea(e,t={}){let r=O_(e),n=xg(r,t),o=t.assemble?()=>{let c=n.dynInput();if(!c)throw new Error("the car did not assemble");return{kc:Da(c),cgHeight:c.cgHeight}}:void 0,a=_g(r,t.density,t.envelope,o),s=Ag(r,n,t),i=Ng(r,t);return{...a,...n,...s,...i,get failure(){return a.failure},values:new Map}}var V_=["x","y","z"],B_=/^(line|plane)\((-?\d+),(-?\d+)\)([uv]?)$/,qS=Math.PI/18e3,QS=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],ZS=(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]],$_=e=>Math.hypot(e[0],e[1],e[2]),Vg=(e,t)=>[e[0]*t,e[1]*t,e[2]*t];function Bg(e){let t=$_(e);return t>1e-9?Vg(e,1/t):null}function G_(e,t){let r=e*qS,n=t*qS;return[Math.cos(n)*Math.cos(r),Math.cos(n)*Math.sin(r),Math.sin(n)]}function pr(e){let t=e.lastIndexOf(".");if(t<0)return null;let r=B_.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:G_(Number(r[2]),Number(r[3]))},coord:n==="line"?"along":r[4]}}function JS(e){let t=Bg(ZS([0,0,1],e))??[1,0,0];(t[0]<-1e-9||Math.abs(t[0])<=1e-9&&t[1]<0)&&(t=Vg(t,-1));let r=Bg(ZS(e,t))??[0,1,0];return(r[2]<-1e-9||Math.abs(r[2])<=1e-9&&r[1]<0)&&(r=Vg(r,-1)),[t,r]}function $g(e){if(e.coord==="along")return e.shape.dir;let[t,r]=JS(e.shape.dir);return e.coord==="u"?t:r}function eA(e,t){let r=pr(t);if(!r)return;let n=V_.map(u=>e[`${r.point}.${u}`]);if(n.some(u=>!u))return;let o=$g(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=>QS(s(u),o),write:(u,m)=>{let f=s(u),p=m-QS(f,o),d=u;for(let h of a)d=n[h].write(d,f[h]+p*o[h]);return d},...c?{supersededBy:c}:{}}}var _m=["x","y","z"];var K_=/^(?:hp\.(?:front|rear)\.\w+|(?:heave|roll)\.(?:front|rear)\.(?:outer|inner|anchor))$/;function ec(e){let t=e.lastIndexOf("."),r=e.slice(0,t);if(t<0||!K_.test(r))return null;let n=e.slice(t+1);if(n==="x"||n==="y"||n==="z")return{point:r,axis:n};let o=pr(e);return o?{point:r,axis:o.coord}:null}function Gg(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 Kg=e=>e?.reads==="speed"||e?.reads==="operating",Hg=e=>e?.reads==="lateral"||e?.reads==="operating";function so(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}`),t.join(",")}function Wt(e,t,r){let n=`${t.id}@${so(r)}`,o=e.values.get(n);if(o!==void 0)return o;let a;try{a=r?.courseId==="*"&&t.reads==="course"?H_(e,t,r):t.read(e,r)}catch{a=NaN}return e.values.set(n,a),a}function H_(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:Wt(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 Rt(e){return`${e.quantity??e.groupShort??e.group} \xB7 ${e.label}`}var z_={front:"Front",rear:"Rear"},tc={heave:0,pitch:0,roll:0,steer:0};function tA(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 Y_(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 rc=e=>e.length?Math.max(...e)-Math.min(...e):NaN;function rA(e){let t=(e??[]).filter(Number.isFinite);if(!t.length)return NaN;let r=t.reduce((n,o)=>n+o,0)/t.length;return Math.abs(r)>0?(Math.max(...t)-Math.min(...t))/Math.abs(r):NaN}function nA(e,t){if(!e.length)return;let r=0;for(let n=1;n<e.length;n++)Math.abs(e[n])<Math.abs(e[r])&&(r=n);return t[r]}function oA(e){let t=z_[e],r=x=>`kin.${e}.${x}`,n=(x,k)=>{let F=x.sweep(e);return F?{x:F.samples.map(w=>w.travel),y:F.samples.map(k)}:{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 k=a(x);return k&&k.design.kind!=="none"?null:`${i} has no heave element`}function u(x){let k=a(x);return k?.design.kind==="coil"&&k.linkage?null:`${i} has no heave element on a linkage`}function m(x){let k=s(x);return k&&k.design.kind!=="none"?null:`${i} has no roll element`}function f(x){let k=s(x);return k?.linkage&&k.design.kind!=="none"&&k.design.kind!=="direct"?null:`${i} has no roll element on a linkage`}let p=x=>{if(u(x.car))return null;let k=x.sweep(e);return k?fd(o(x.car),a(x.car).linkage,k.samples):null},d=x=>{if(f(x.car))return null;let k=x.sweep(e);if(!k)return null;let F=s(x.car),w=md(o(x.car),F.linkage,F.design.kind,k.samples),C=w.atDesign<0?-1:1;return{travel:w.travel,ratio:w.ratio.map(T=>T*C),atDesign:w.atDesign*C}},h=x=>x.readout(tc)?.[e],b=x=>x.readoutAtTravel(e,x.envelope.travelMax),g=x=>{let k=n(x,F=>F.metrics.camber);return k.x.length?{key:r("camberGain"),title:`${t} camber vs travel`,xLabel:"travel [mm]",yLabel:"camber [\xB0]",...k}:null},y=x=>{let k=n(x,F=>F.metrics.toe);return k.x.length?{key:r("bumpSteer"),title:`${t} toe vs travel`,xLabel:"travel [mm]",yLabel:"toe [\xB0]",...k}: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 k=x.rcHeave(e);return k?Y_(k.at,k.rc.map(F=>F.height)):NaN},curve:x=>{let k=x.rcHeave(e);return k?{key:r("rcHeaveWorst"),title:`${t} roll-centre height vs wheel travel`,xLabel:"travel [mm]",yLabel:"RC height [mm]",x:k.at,y:k.rc.map(F=>F.height)}:null}},{id:r("rcRollSpan"),group:`${t} roll centre`,label:"height span over the roll envelope",unit:"mm",scale:15,scope:e,cost:"cheap",read:x=>{let k=x.rcRoll(e);return k?rc(k.rc.map(F=>F.height)):NaN},curve:x=>{let k=x.rcRoll(e);return k?{key:r("rcRollSpan"),title:`${t} roll-centre height vs body roll`,xLabel:"roll [\xB0]",yLabel:"RC height [mm]",x:k.at,y:k.rc.map(F=>F.height)}:null}},{id:r("rcLateralSpan"),group:`${t} roll centre`,label:"lateral migration over roll",unit:"mm",scale:50,scope:e,cost:"cheap",read:x=>{let k=x.rcRoll(e);return k?rc(k.rc.map(F=>F.lateral)):NaN},curve:x=>{let k=x.rcRoll(e);return k?{key:r("rcLateralSpan"),title:`${t} roll-centre lateral position vs body roll`,xLabel:"roll [\xB0]",yLabel:"RC lateral [mm]",x:k.at,y:k.rc.map(F=>F.lateral)}:null}},{id:r("minSinAngle"),group:`${t} roll centre`,label:"construction conditioning (min sinAngle)",unit:"-",scale:.04,scope:e,cost:"cheap",read:x=>{let k=x.rcHeave(e),F=x.rcRoll(e);return!k||!F?NaN:Math.min(...k.rc.map(w=>w.sinAngle),...F.rc.map(w=>w.sinAngle))},curve:x=>{let k=x.rcHeave(e);return k?{key:r("minSinAngle"),title:`${t} construction conditioning vs travel`,xLabel:"travel [mm]",yLabel:"sinAngle",x:k.at,y:k.rc.map(F=>F.sinAngle)}:null}},{id:r("fvsaLength"),group:`${t} roll centre`,label:"front-view swing-arm length",unit:"mm",scale:500,scope:e,cost:"readout",read: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 k=x.solveAt(e,0);return k?k.metrics.camber:NaN}},{id:r("staticToe"),group:`${t} camber & toe`,label:"static toe",unit:"\xB0",scale:.5,scope:e,cost:"cheap",read: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 k=n(x,F=>F.metrics.toe);return k.x.length?tA(k.x,k.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 k=n(x,F=>F.metrics.camber);return k.x.length?tA(k.x,k.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=>rc(n(x,k=>k.metrics.camber).y)},{id:r("toeSpan"),group:`${t} camber & toe`,label:"toe range over travel",unit:"\xB0",scale:.5,scope:e,cost:"cheap",read:x=>rc(n(x,k=>k.metrics.toe).y)},{id:r("camberRecovery"),group:`${t} camber & toe`,label:"outer camber at limit roll",unit:"\xB0",scale:2,scope:e,cost:"cheap",read:x=>{let k=x.solveAt(e,x.travelAtRoll(e,x.envelope.rollAtLimitDeg)),F=x.solveAt(e,0);return!k||!F?NaN:Math.abs(k.metrics.camber-F.metrics.camber+x.envelope.rollAtLimitDeg)}},{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 k=x.sweep(e);return k?nA(k.samples.map(F=>F.travel),k.samples.map(F=>F.metrics.motionRatio??NaN))??NaN:NaN},curve:x=>{if(c(x.car))return null;let k=n(x,F=>F.metrics.motionRatio??NaN);return k.x.length?{key:r("motionRatio"),title:`${t} motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",...k}:null}},{id:r("mrSpread"),group:`${t} rates`,label:"motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let k=x.sweep(e);if(!k)return NaN;let F=k.samples.map(C=>C.metrics.motionRatio??NaN).filter(Number.isFinite);if(!F.length)return NaN;let w=F.reduce((C,T)=>C+T,0)/F.length;return w>0?(Math.max(...F)-Math.min(...F))/w:NaN}},{id:r("wheelRate"),group:`${t} rates`,label:"wheel rate at design",unit:"N/mm",scale:10,scope:e,cost:"cheap",unavailable:c,read:x=>{if(c(x.car))return NaN;let k=x.sweep(e);return k?nA(k.samples.map(F=>F.travel),k.samples.map(F=>F.metrics.wheelRate??NaN))??NaN:NaN}},{id:r("heaveMotionRatio"),group:`${t} rates`,label:"heave element motion ratio at design",unit:"-",scale:.2,scope:e,cost:"cheap",unavailable:u,read:x=>p(x)?.atDesign??NaN,curve:x=>{let k=p(x);return k?{key:r("heaveMotionRatio"),title:`${t} heave element motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",x:k.travel,y:k.ratio}:null}},{id:r("heaveMrSpread"),group:`${t} rates`,label:"heave element motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:u,read:x=>rA(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:ma(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 k=d(x);return k?{key:r("rollMotionRatio"),title:`${t} roll element motion ratio vs travel`,xLabel:"travel [mm]",yLabel:"MR [-]",x:k.travel,y:k.ratio}:null}},{id:r("rollMrSpread"),group:`${t} rates`,label:"roll element motion-ratio spread",unit:"frac",scale:.1,scope:e,cost:"cheap",unavailable:f,read:x=>rA(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:$n(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(tc)?.[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("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:rc(n(x,k=>k.metrics.damperLength).y),curve:x=>{if(c(x.car))return null;let k=n(x,F=>F.metrics.damperLength);return k.x.length?{key:r("damperStroke"),title:`${t} damper length vs travel`,xLabel:"travel [mm]",yLabel:"length [mm]",...k}:null}}];e==="front"&&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(tc)?.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(tc)?.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(tc)?.rear.antiLift??NaN});let M=x=>{let k=x.slice(t.length+1);return k.charAt(0).toUpperCase()+k.slice(1)};return[...new Set(R.map(x=>x.group))].flatMap(x=>R.filter(k=>k.group===x)).map(x=>({...x,quantity:`${t} \xB7 ${M(x.group)}`}))}function aA(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 W_=[{id:"kin.front.ackermannCentre",group:"Steering",label:"Ackermann near centre",unit:"%",scale:25,scope:"front",cost:"cheap",read:e=>aA(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=>aA(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}}],j_=[{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.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}}],zg=[...oA("front"),...oA("rear"),...W_,...j_];var sA={understeer:"operating",yawFreq:"speed",yawZeta:"speed",yawStiffness:"operating",steeringTorque:"operating",steeringTorqueGradient:"operating"};function rt(e,t,r,n="cheap"){let o=tb[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,...sA[e]?{reads:sA[e]}:{},read:(a,s)=>{let i=a.dynInput(),c=a.dynCtx(s);return i&&c?o.compute(i,c):NaN}}}var U_=[rt("understeer","Handling \u2014 balance",.1),rt("tlltdFront","Handling \u2014 balance",5),rt("rollStiffFront","Handling \u2014 balance",5)],X_=[rt("yawFreq","Handling \u2014 response",.5),rt("yawZeta","Handling \u2014 response",.2),rt("stabilitySpeed","Handling \u2014 response",50),rt("yawStiffness","Handling \u2014 response",2e4,"trim")],q_=[rt("steeringTorque","Steering feel",1,"trim"),rt("steeringTorqueGradient","Steering feel",2,"trim")],Q_=[rt("rollGradient","Ride & body",.5),rt("pitchGradient","Ride & body",.5),rt("rideFreqFront","Ride & body",.5),rt("rideFreqRear","Ride & body",.5),rt("rollFreq","Ride & body",.5),rt("pitchFreq","Ride & body",.5),rt("zetaFront","Ride & body",.2),rt("zetaRear","Ride & body",.2)],Z_=[{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}],J_=[{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}],Yg=[...U_,...X_,...q_,...Q_,...Z_,...J_];function eN(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 Wg=[{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)=>eN(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 tN(e,t){let r=/^(.*?)\s*\(([^)]+)\)\s*$/.exec(e);return r?{label:r[1],unit:r[2]}:{label:e,unit:t?"s":""}}function rN(e){return e==="s"||e==="kWh"?.1:e==="km/h"?2:1}var iA=new WeakMap;function Nm(e){let t=iA.get(e);return t||(t=e.metrics.filter(yc).map(r=>{let{label:n,unit:o}=tN(r.label,r.format==="time");return{id:`event.${e.id}.${r.key}`,group:`Events \xB7 ${e.label}`,groupShort:"Events",label:n,unit:o,scale:rN(o),scope:"car",cost:"session",read:a=>a.session(e.id)?.[r.key]??NaN}}),iA.set(e,t),t)}var jg=Fa.flatMap(Nm);var Om=[...zg,...Yg,...Wg,...jg],Ia=Object.fromEntries(Om.map(e=>[e.id,e]));var cA={all:Om,byId:Ia},lA=new WeakMap;function Gr(e=[]){if(e.length===0)return cA;let t=lA.get(e);if(t)return t;let r=Fb(e).filter(n=>!wa(n.id)).flatMap(Nm);return t=r.length?{all:[...Om,...r],byId:{...Ia,...Object.fromEntries(r.map(n=>[n.id,n]))}}:cA,lA.set(e,t),t}var nc=180/Math.PI,_a=Math.PI/180,oN=.2;function Vm(e,t){let r=H(t,e);return q(r[0]<0?jp(r):r)}var Bm=e=>({side:Math.atan2(e[2],e[0])*nc,plan:Math.atan2(e[1],e[0])*nc}),$m=(e,t)=>q([1,Math.tan(t*_a),Math.tan(e*_a)]),oc=e=>Math.abs(e[0])>=oN,Gm=(e,t)=>Math.atan(t/Math.max(e,1))*nc,Km=(e,t)=>Math.tan(t*_a)*Math.max(e,1);var hn=["side","plan","clock","len"],jt={uca:{fore:"ucaFront",aft:"ucaRear",ball:"uprightUpper"},lca:{fore:"lcaFront",aft:"lcaRear",ball:"uprightLower"}},ac={uca:"upper arm",lca:"lower arm"},aN=1,uA=(e,t)=>Vm(e[jt[t].fore],e[jt[t].aft]);function mA(e){let t=q(H(Wp,U(e,X(Wp,e))));return{e1:t,e2:ae(e,t)}}function Ug(e,t){let r=uA(e,t);if(!oc(r))return`the ${ac[t]}'s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it`;let n=jt[t],o=jr(e[n.ball],e[n.fore],r);return Math.hypot(...H(o,e[n.ball]))>=aN?null:`the ${ac[t]}'s ball joint sits on its own pivot axis, so the arm has no length to swing on`}function Kr(e,t){let r=jt[t],n=e[r.ball],o=uA(e,t),a=jr(n,e[r.fore],o),s=H(a,n),i=Math.hypot(s[0],s[1],s[2]),{e1:c,e2:l}=mA(o),u=i>0?U(s,1/i):c;return{...Bm(o),clock:Math.atan2(X(u,l),X(u,c))*nc,len:i,sFront:X(H(e[r.fore],a),o),sRear:X(H(e[r.aft],a),o)}}function Xg(e,t){let r=$m(e.side,e.plan),{e1:n,e2:o}=mA(r),a=ee(U(n,Math.cos(e.clock*_a)),U(o,Math.sin(e.clock*_a))),s=ee(t,U(a,e.len));return{fore:ee(s,U(r,e.sFront)),aft:ee(s,U(r,e.sRear))}}function pA(e,t,r,n){let o=jt[t],a={...Kr(e,t),[r]:n},{fore:s,aft:i}=Xg(a,e[o.ball]);return{...e,[o.fore]:s,[o.aft]:i}}function dA(e,t){return t==="clock"?e.len:Math.abs(e.sFront-e.sRear)/2}function Hm(e,t,r){return t==="len"?r:Gm(dA(e,t),r)}function qg(e,t,r){return t==="len"?r:Km(dA(e,t),r)}var io=["side","plan","atY","atZ"],co={fore:"rockerPivotA",aft:"rockerPivotB"},sN=5,fA=e=>Vm(e.rockerPivotA,e.rockerPivotB);function Na(e){return Math.hypot(...H(e.rockerPivotB,e.rockerPivotA))<sN?"the rocker\u2019s two pivots are the same point, so there is no axis to describe":oc(fA(e))?null:"the rocker\u2019s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it"}function bn(e){let t=fA(e),r=oc(t)?t:[1,0,0],n=e.rockerPivotA,o=ee(n,U(r,-n[0]/r[0]));return{...Bm(r),atY:o[1],atZ:o[2],sA:X(H(n,o),r),sB:X(H(e.rockerPivotB,o),r)}}function Qg(e){let t=$m(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 hA(e,t,r){if(Na(e))return e;let{a:n,b:o}=Qg({...bn(e),[t]:r});return{...e,rockerPivotA:n,rockerPivotB:o}}var bA=e=>Math.abs(e.sA-e.sB)/2;function Zg(e,t,r){return t==="side"||t==="plan"?Gm(bA(e),r):r}function Jg(e,t,r){return t==="side"||t==="plan"?Km(bA(e),r):r}var Xt={front:"Front",rear:"Rear"},Ut=["x","y","z"],Oe=(e,t)=>t==="front"?e.front:e.rear,sc=(e,t,r)=>t==="front"?{...e,front:r}:{...e,rear:r},gA=[{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"}]}],yA={damperChassis:"strut top mount",pushrodOuter:"strut lower mount"},lo=30;function iN(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).config.layout==="mcpherson";for(let o of gA)for(let{key:a,label:s}of o.keys){let i=n&&yA[a]||s;for(let c=0;c<3;c++)t.push({id:`hp.${r}.${a}.${Ut[c]}`,group:`${Xt[r]} hardpoints \u2014 ${o.kind}`,label:`${i} ${Ut[c]}`,scope:Xt[r],unit:"mm",defaultSpan:lo,read:l=>Oe(l.vehicle,r).hardpoints[a][c],write:(l,u)=>{let m=Oe(l.vehicle,r),f=[...m.hardpoints[a]];f[c]=u;let p={...m.hardpoints,[a]:f};return{...l,vehicle:sc(l.vehicle,r,{...m,hardpoints:p})}}})}}return t}var cN={side:"axis side-view angle",plan:"axis plan-view angle",clock:"arm clock angle",len:"effective arm length"},lN={side:"\xB0",plan:"\xB0",clock:"\xB0",len:"mm"};function uN(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).config.layout==="mcpherson";for(let o of["uca","lca"]){let a=Oe(e.vehicle,r).hardpoints,s=Ug(a,o)?null:Kr(a,o);for(let i of hn)t.push({id:`arm.${r}.${o}.${i}`,group:`${Xt[r]} ${n?"arm axes":"wishbone axes"}`,label:`${ac[o]} \u2014 ${cN[i]}`,scope:Xt[r],unit:lN[i],defaultSpan:s?Hm(s,i,lo):lo,read:c=>Kr(Oe(c.vehicle,r).hardpoints,o)[i],write:(c,l)=>{let u=Oe(c.vehicle,r),m=pA(u.hardpoints,o,i,l);return{...c,vehicle:sc(c.vehicle,r,{...u,hardpoints:m})}}})}}return t}var mN={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"},pN={side:"\xB0",plan:"\xB0",atY:"mm",atZ:"mm"};function dN(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).hardpoints,o=Na(n)?null:bn(n);for(let a of io)t.push({id:`rocker.${r}.${a}`,group:`${Xt[r]} rocker axis`,label:`rocker \u2014 ${mN[a]}`,scope:Xt[r],unit:pN[a],defaultSpan:o?Zg(o,a,lo):lo,read:s=>bn(Oe(s.vehicle,r).hardpoints)[a],write:(s,i)=>{let c=Oe(s.vehicle,r),l=hA(c.hardpoints,a,i);return{...s,vehicle:sc(s.vehicle,r,{...c,hardpoints:l})}}})}return t}var zm={front:"heaveFrontDesign",rear:"heaveRearDesign"},e0={front:"arbFrontDesign",rear:"arbRearDesign"};function fN(e,t){return{heave:e.config.actuation==="decoupled"?"heave element":"third spring",roll:t?.design.kind==="coil"?"roll shock":"anti-roll bar"}}var Ym=e=>/^(heave|roll)\.(front|rear)\.(outer|inner|anchor)\.[xyz]$/.test(e);function hN(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r),o=e.params[zm[r]],a=e.params[e0[r]],s=fN(n,a),i=d=>d.params[zm[r]],c=d=>d.params[e0[r]],l=(d,h)=>({...d,params:{...d.params,[zm[r]]:h}}),u=(d,h)=>({...d,params:{...d.params,[e0[r]]:h}}),m={group:`${Xt[r]} heave & roll elements`,scope:Xt[r]},f=(d,h,b,g,y)=>{for(let R of b)t.push({...m,id:`${d}.${Ut[R]}`,label:`${h} ${Ut[R]}`,unit:"mm",defaultSpan:lo,read:M=>g(M)[R],write:(M,v)=>{let x=[...g(M)];return x[R]=v,y(M,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=Qr(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,M)=>u(R,{...c(R),linkage:{...h(R),outer:M}})),f(`roll.${r}.inner`,`${s.roll} ${y}`,[0,1,2],R=>h(R).inner,(R,M)=>u(R,{...c(R),linkage:{...h(R),inner:M}}))}let d=a.design;if(d.kind==="coil"&&typeof d.rate=="number"){let h=b=>c(b).design;p(`roll.${r}.rate`,`${s.roll} spring rate (@element)`,d.rate,b=>h(b).rate,(b,g)=>u(b,{...c(b),design:{kind:"coil",rate:g}}))}else d.kind==="direct"&&p(`roll.${r}.wheelRate`,`${s.roll} rate (@wheel)`,d.wheelRate,h=>c(h).design.wheelRate,(h,b)=>u(h,{...c(h),design:{kind:"direct",wheelRate:b}}))}}return t}var bN=[{axle:"front",field:"springRate",group:"Springs & bars",label:"spring rate (@spring)",unit:"N/mm",fallback:35,span:e=>Math.max(5,e*.4)},{axle:"rear",field:"springRate",group:"Springs & bars",label:"spring rate (@spring)",unit:"N/mm",fallback:40,span:e=>Math.max(5,e*.4)},{axle:"front",field:"rackTravel",group:"Steering",label:"rack travel from centre",unit:"mm",fallback:35,span:()=>15,frontOnly:!0},{axle:"front",field:"rackRatio",group:"Steering",label:"rack per steering-wheel turn",unit:"mm/rev",fallback:55,span:()=>15,frontOnly:!0},{axle:"front",field:"loadedRadius",group:"Wheel & tyre",label:"loaded radius",unit:"mm",fallback:228,span:()=>15},{axle:"rear",field:"loadedRadius",group:"Wheel & tyre",label:"loaded radius",unit:"mm",fallback:228,span:()=>15}];function gN(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).compliance;if(!n)continue;let o=(a,s,i,c)=>{let l=i(n);l===void 0||!(l>0)||!Number.isFinite(l)||t.push({id:`kc.${r}.${a}`,group:"Compliance",label:s,scope:Xt[r],unit:"N/mm",defaultSpan:Math.max(500,l*.4),read:u=>i(Oe(u.vehicle,r).compliance??{})??l,write:(u,m)=>{let f=Oe(u.vehicle,r),p={...f,compliance:c(f.compliance??{},Math.max(1,m))};return{...u,vehicle:sc(u.vehicle,r,p)}}})};for(let a of["ucaFront","ucaRear","lcaFront","lcaRear","tieRod","pushRod"])o(`link.${a}`,`${yN[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}`,`${xN[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 yN={ucaFront:"UCA front leg",ucaRear:"UCA rear leg",lcaFront:"LCA front leg",lcaRear:"LCA rear leg",tieRod:"tie rod",pushRod:"push/pull rod"},xN={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 RN(){return bN.map(e=>({id:`cfg.${e.axle}.${e.field}`,group:e.group,label:e.label,scope:Xt[e.axle],unit:e.unit,defaultSpan:e.span(e.fallback),read:t=>Oe(t.vehicle,e.axle).config[e.field]??e.fallback,write:(t,r)=>{let n=Oe(t.vehicle,e.axle),o={...n,config:{...n.config,[e.field]:r}};return{...t,vehicle:sc(t.vehicle,e.axle,o)}}}))}function vN(e){let t=Cn(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=>Cn(c.params.steeringSystem)[n],write:(c,l)=>({...c,params:{...c.params,steeringSystem:Cn({...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 kN(e){let t=ai(e.params),r=[];for(let n of["front","rear"]){if(t[n]!=="diff")continue;let o=Kn(e.params.driveline?.[n]);if(o?.kind!=="clutch"&&o?.kind!=="torsen")continue;let a=(s,i)=>{let c=uu[`${n}.${s}`];return{id:`driveline.${n}.${s}`,group:"Differential",label:c.label.charAt(0).toLowerCase()+c.label.slice(1),scope:Xt[n],unit:c.unit===": 1"?"":c.unit??"",defaultSpan:i,read:l=>Kn(l.params.driveline?.[n])?.[s],write:(l,u)=>({...l,params:{...l.params,driveline:lu({...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 MN(e){if(Dl(e.params)!=="hydraulic")return[];let t=[{id:"brakeSetup.barFront",group:"Brakes",label:`${qf("barFront").toLowerCase()}, front share`,unit:"-",defaultSpan:.05,read:a=>Ar(a.params.brakeSetup).barFront,write:(a,s)=>({...a,params:{...a.params,brakeSetup:Ar({...Ar(a.params.brakeSetup),barFront:s})}})}];if(!e.params.brakeModel)return t;let r=tr(e.params.brakeModel),n=(a,s)=>s.circuit?a[s.circuit][s.key]:a[s.key],o=(a,s,i)=>({id:`brakeModel.${a.circuit?`${a.circuit}.`:""}${String(a.key)}`,group:"Brakes",label:Xf(a.circuit?`${a.circuit}.${String(a.key)}`:a.key),unit:s,defaultSpan:i,read:c=>n(tr(c.params.brakeModel),a),write:(c,l)=>{let u=tr(c.params.brakeModel),m=a.circuit?{...u,[a.circuit]:{...u[a.circuit],[a.key]:l}}:{...u,[a.key]:l};return{...c,params:{...c.params,brakeModel:tr(m)}}}});return t.push(o({key:"masterFrontMm"},"mm",1.5),o({key:"masterRearMm"},"mm",1.5),o({key:"pedalRatio"},"-",.5),o({key:"pistonDiaMm",circuit:"front"},"mm",2),o({key:"pistonDiaMm",circuit:"rear"},"mm",2),o({key:"effRadiusMm",circuit:"front"},"mm",10),o({key:"effRadiusMm",circuit:"rear"},"mm",10)),r.valve!=="none"&&t.push(o({key:"valveKneeBar"},"bar",5)),r.valve==="proportioning"&&t.push(o({key:"valveSlope"},"-",.1)),t}var xA=e=>!!e&&typeof e=="object"&&"value"in e&&"label"in e;function RA(e){let t={...e};for(let r of Object.keys(t)){let n=t[r];xA(n)&&(t[r]={...n})}return t}function SN(e){let t=[];for(let r of X1(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 xA(s)?s.value:NaN},write:(a,s)=>{let i=RA(a.params);return hu(i,n.label,s),{...a,params:i}}})}return t}function vA(e){let t={};for(let s of["front","rear"]){if(!Oe(e.vehicle,s).measured)continue;let c="this axle is described by measured curves, so its linkage is not solved";for(let l of gA)for(let{key:u}of l.keys)for(let m of Ut)t[`hp.${s}.${u}.${m}`]={why:c};for(let l of["uca","lca"])for(let u of hn)t[`arm.${s}.${l}.${u}`]={why:c};for(let l of io)t[`rocker.${s}.${l}`]={why:c};for(let l of["heave.outer","heave.anchor","roll.outer","roll.inner"]){let[u,m]=l.split(".");for(let f of Ut)t[`${u}.${s}.${m}.${f}`]={why:c}}t[`cfg.${s}.springRate`]={why:"the measured curve set carries its own spring rate"}}let r=["rockerPivotA","rockerPivotB","rockerToPushrod","rockerToDamper"];for(let s of["front","rear"]){if(Oe(e.vehicle,s).config.actuation!=="direct")continue;let i="this axle is direct-acting \u2014 there is no bell-crank";for(let c of r)for(let l of Ut)t[`hp.${s}.${c}.${l}`]={why:i};for(let c of io)t[`rocker.${s}.${c}`]={why:i}}for(let s of["front","rear"]){let i=Oe(e.vehicle,s);if(i.measured||i.config.actuation!=="decoupled")continue;let c="this axle is decoupled \u2014 the corner damper is out of circuit";for(let l of["rockerToDamper","damperChassis"])for(let u of Ut)t[`hp.${s}.${l}.${u}`]={why:c,useInstead:`heave.${s}.outer.${u}`};t[`cfg.${s}.springRate`]={why:"a decoupled axle has no corner spring \u2014 its elements hold it up",useInstead:`heave.${s}.rate`}}for(let s of["front","rear"]){let i=Oe(e.vehicle,s),c=e.params[zm[s]]?.linkage;if(i.measured||!c||c.attach!=="rocker"||c.mount?.kind==="chassis")continue;let l=i.hardpoints,u=[0,1,2].map(f=>l.rockerPivotB[f]-l.rockerPivotA[f]),m=Math.hypot(u[0],u[1],u[2]);if(m>0)for(let f=0;f<3;f++)Math.abs(u[f]/m)<1-1e-12||(t[`heave.${s}.outer.${Ut[f]}`]={why:`the rocker shaft runs along ${Ut[f]} \u2014 this only slides the eye along it`})}for(let s of["front","rear"]){let i=Oe(e.vehicle,s);if(i.measured||i.config.layout!=="mcpherson")continue;let c="this axle is a McPherson strut \u2014 there is no upper arm";for(let l of["ucaFront","ucaRear","uprightUpper"])for(let u of Ut)t[`hp.${s}.${l}.${u}`]={why:c,useInstead:`hp.${s}.damperChassis.${u}`};for(let l of hn)t[`arm.${s}.uca.${l}`]={why:c};for(let l of["link.ucaFront","link.ucaRear","bush.ucaFront","bush.ucaRear"])t[`kc.${s}.${l}`]={why:c}}for(let s of["front","rear"]){let i=Oe(e.vehicle,s);if(i.measured)continue;for(let l of["uca","lca"]){if(l==="uca"&&i.config.layout==="mcpherson")continue;let u=Ug(i.hardpoints,l);if(u)for(let m of hn)t[`arm.${s}.${l}.${m}`]={why:u,useInstead:`hp.${s}.${jt[l].fore}.z`}}let c=Na(i.hardpoints);if(c&&i.config.actuation!=="direct")for(let l of io)t[`rocker.${s}.${l}`]={why:c,useInstead:`hp.${s}.${co.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?Oh:Vh;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(pu))t[`param.${s}`]={why:i};for(let[s,i]of Object.entries(du(e.params)))t[`param.${s}`]={why:i};let a=Dl(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 kA(e){let t={...FN,...vA(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[...iN(e),...uN(e),...dN(e),...hN(e),...RN(),...vN(e),...MN(e),...kN(e),...gN(e),...SN(e.params)].map(r)}var AN={spring_front:"cfg.front.springRate",spring_rear:"cfg.rear.springRate"},FN=Object.fromEntries(Object.entries(Nh).map(([e,t])=>[`param.${e}`,{why:t,useInstead:AN[e]}])),st=e=>e.scope?`${e.scope} \xB7 ${e.label}`:e.label;function $t(e){let t={};for(let n of kA(e))t[n.id]=n;let r=(n,o)=>{if(typeof o!="string")return;let a=eA(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 t0=e=>e.step!==void 0&&Number.isFinite(e.step)&&e.step>0?e.step:0,r0=e=>t0(e)>0||(e.values?.length??0)>0,n0=e=>e.some(r0),MA=e=>1e-9*Math.max(1,Math.abs(e.lo),Math.abs(e.hi));function SA(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=t0(e);if(!r||!Number.isFinite(e.start))return t;let n=MA(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 AA=(e,t)=>t.map((r,n)=>e[n]&&r0(e[n])?SA(e[n],r):r);function o0(e,t=1e3){if(e.values?.length)return e.values.length;let r=t0(e);if(!r||!Number.isFinite(e.start))return 1/0;let n=MA(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 a0(e,t,r){let n=AA(e.variables,t),o=n.every((a,s)=>a===t[s]);return{x:n,score:o?r:vr(e,n)}}function l0(e,t){if(!e.variables.some(wA))return e;let r=e.variables.filter(o=>o.follows&&!o.fixed).map(o=>({id:o.id,follows:o.follows})),n=e.variables.filter(o=>!o.fixed&&!o.follows).map(o=>{if(CA(o))return{...o,lo:Math.min(...o.values),hi:Math.max(...o.values)};if(!o.around)return o;let{around:a,fixed:s,...i}=o,c=t(o.id);return Number.isFinite(c)?{...i,lo:c-a.minus,hi:c+a.plus}:i});return r.length?{...e,variables:n,followers:r}:{...e,variables:n}}var wA=e=>!!(e.fixed||e.around||e.follows)||CA(e),CA=e=>!!e.values?.length&&(e.lo!==Math.min(...e.values)||e.hi!==Math.max(...e.values));function Lt(e,t){if(!t.variables.some(wA))return t;let r=$t(e);return l0(t,n=>{let o=r[n];if(!o)return NaN;try{return o.read(e)}catch{return NaN}})}function uo(e){return[...e.objectives,...e.constraints,...e.watches??[]]}var u0=e=>(e.metrics??Gr()).byId;function m0(e,t){t=Lt(e,t);let r=$t(e),n=[];for(let o of t.variables){let a=r[o.id];a&&n.push({id:a.id,name:st(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 Wm(e,t,r){t=Lt(e,t);let n=$t(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]))}),p0(e,o,t.followers,n)}function p0(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 ic(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 TA=(e,t="")=>t&&t!=="-"?`${e} ${t}`:`${e}`;function PA(e,t,r){let n=t??Ia[e.metricId],o=(n?Rt(n):e.metricId)+cc(e.at,n,r),a=s=>TA(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 cc(e,t,r){if(!e)return"";let n=[];if(e.speed!==void 0&&Kg(t)&&n.push(`${(e.speed*3.6).toFixed(0)} km/h`),e.ayG!==void 0&&Hg(t)&&n.push(`${e.ayG.toFixed(2)} g`),e.courseId==="*"&&t?.reads==="course")n.push(Gg(t));else if(e.courseId&&t?.reads==="course"){let o=r?.lap.courses.find(a=>a.id===e.courseId);o&&n.push(Sg(o))}return n.length?` @ ${n.join(", ")}`:""}function LA(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 DA=5e-4;function EA(e,t){return e.cost!=="lap"&&e.cost!=="session"?0:Number.isFinite(t)?DA*Math.abs(t):0}function jm(e,t,r={}){t=Lt(e,t);let n=m0(e,t),o=$t(e),a=u0(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=Wt(f,b,h.at);if(!Number.isFinite(g))return{ok:!1,violation:f.failure?.violation??400,reason:f.failure?.reason??`${Rt(b)} could not be computed`};let y=ic(h,g);y>0&&(p+=y/b.scale,d.push(`${PA(h,b,t)} (${TA(g.toFixed(3),b.unit)})`))}return d.length===0?Ms:{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=p0(e,f,t.followers,o),{car:f,ev:Ea(f,{density:t.density,envelope:t.envelope,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)Wt(m,d,p.at);for(let{spec:p,metric:d}of l)Wt(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=Wt(m,p,f.at);return{name:Rt(p)+cc(f.at,p,t),raw:d,unit:p.unit,weight:f.weight,contribution:LA(f,p,d),resolution:Math.abs(f.weight)*EA(p,d)/p.scale}})}}function s0(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 IA(e,t){if(e.variables.some(o=>o.id===t))return!0;let r=ec(t);if(!r||!_m.includes(r.axis))return!1;if(e.variables.some(o=>pr(o.id)?.point===r.point))return!0;let n=s0(t);return!!n&&e.variables.some(o=>/^(arm|rocker)\./.test(o.id)&&s0(o.id)===n)}function wN(e,t){let r=e.followers??[],n=new Map(r.map(i=>[i.id,i.follows])),o=i=>{let c=t[i],l=ec(i);return c&&l&&_m.includes(l.axis)?{name:st({...c,label:c.label.replace(/ [xyz]$/,"")}),axis:l.axis}:{name:c?st(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 IA(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 d0(e,t,r={}){let n=t.variables.length>0&&t.variables.every(g=>g.fixed||g.follows),o=t.variables.some(g=>g.follows&&!g.fixed);t=Lt(e,t);let a=$t(e),s=[],i=u0(r),c=uo(t).map(g=>g.metricId),l=c.some(g=>g.startsWith("dyn.")),u=c.some(g=>g.startsWith("lap."));if(c.some(g=>g.startsWith("kin."))){let g=t.envelope;g.travelMin<0&&g.travelMax>0||s.push("The travel the linkage is read over must reach both ways from the design ride: droop below zero, bump above."),(!(g.rollMaxDeg>0)||!(g.rollAtLimitDeg>=0))&&s.push("The roll the linkage is read over must be 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(g=>g.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 g of t.lap.courses)g.course.kind==="track"&&!r.libraryTrack?.(g.course.trackId)&&s.push(`This study drives ${g.course.name}, which is not in the project\u2019s tracks, or has not loaded yet.`);let m=new Set([...t.lap.courses.map(g=>g.id),"*"]);for(let g of uo(t))if(g.at?.courseId&&!m.has(g.at.courseId)){let y=i[g.metricId];s.push(`${y?Rt(y):g.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(y=>/arb_|spring|heave_|front_mass_diss|cg_height|^hp\./.test(y.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 g of t.variables){let y=a[g.id];if(!y){s.push(`\u201C${g.id}\u201D is not a variable this car has.`);continue}if(g.values&&g.values.length<2?s.push(`${st(y)}: list two values or more, or fix it where it is.`):g.hi>g.lo?g.step!==void 0&&o0({...g,start:y.read(e)})<2&&s.push(`${st(y)}: a step of ${g.step} ${y.unit} leaves no other place to land in its box. Make the step finer or the box wider, or fix it.`):s.push(`${st(y)}: the upper bound must be above the lower one (${g.lo} to ${g.hi}).`),y.supersededBy){let M=y.supersededBy.useInstead?a[y.supersededBy.useInstead]:void 0,v=M?st(M):void 0;s.push(`${st(y)} cannot be searched: ${y.supersededBy.why}.`+(v?` Use ${v} instead.`:""))}let R=y.read(e);Number.isFinite(R)&&(R<g.lo||R>g.hi)&&s.push(`${st(y)} starts at ${R.toFixed(1)} ${y.unit}, outside its own bounds.`)}let f=t.followers??[],p=new Map;for(let g of[...t.variables.map(y=>y.id),...f.map(y=>y.id)]){let y=s0(g);if(!y)continue;let R=p.get(y);R||p.set(y,R={arms:[],coords:[]}),(/^(arm|rocker)\./.test(g)?R.arms:R.coords).push(g)}for(let[g,y]of p){if(y.arms.length===0||y.coords.length===0)continue;let R=v=>a[v]?st(a[v]):v,M=g.endsWith("rocker")?"rocker":`${g.endsWith("uca")?"upper":"lower"} arm`;s.push(`${g.startsWith("front")?"The front":"The rear"} ${M} is being moved two ways at once \u2014 as an axis (${y.arms.map(R).join(", ")}) and as pivot coordinates (${y.coords.map(R).join(", ")}). They describe the same ${M}, so whichever is applied second overwrites the other. Keep one.`)}let d=new Map,h=new Set(f.map(g=>g.id));for(let g of[...t.variables.map(y=>y.id),...h]){let y=ec(g);if(!y)continue;let R=pr(g),M=h.has(g)?"with":R?`${R.shape.kind}:${g.slice(g.lastIndexOf(".")+1).replace(/[uv]$/,"")}`:"axes",v=d.get(y.point);v||d.set(y.point,v=new Set),v.add(M)}for(let[g,y]of d){if(y.size<2||y.size===2&&y.has("axes")&&y.has("with"))continue;let R=[...y].map(F=>F.split(":")[0]),M=F=>R.filter(w=>w===F).length,v=[M("axes")?"in its axes":"",M("line")===1?"along a line":M("line")>1?"along two lines":"",M("plane")===1?"in a plane":M("plane")>1?"in two planes":"",M("with")?"with another point":""].filter(Boolean),x=a[`${g}.x`],k=x?st({...x,label:x.label.replace(/ x$/,"")}):g;s.push(`${k} is moved more than one way at once \u2014 ${v.join(" and ")}. Each write moves it off the other's, so keep one.`)}s.push(...wN(t,a));for(let g of t.constraints){let y=i[g.metricId];if(!y){s.push(`\u201C${g.metricId}\u201D is not a metric.`);continue}g.op==="band"&&!((g.limit2??g.limit)>g.limit)&&s.push(`${Rt(y)}: 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 g of uo(t))if(g.at?.speed!==void 0&&!(g.at.speed>0)){let y=i[g.metricId];s.push(`${y?Rt(y):g.metricId} is asked for at rest, where a yaw-moment diagram is degenerate.`)}for(let g of t.watches??[])i[g.metricId]||s.push(`\u201C${g.metricId}\u201D is not a metric.`);let b=new Set;for(let g of uo(t)){let y=i[g.metricId],R=y?.unavailable?.(e);!y||!R||b.has(y.id)||(b.add(y.id),s.push(`${Rt(y)} cannot be read on this car: ${R}.`))}for(let g of t.objectives)i[g.metricId]?g.weight>0?g.goal==="target"&&!Number.isFinite(g.target)?s.push(`${Rt(i[g.metricId])}: \u201Chit a value\u201D needs a value.`):g.goal==="target"&&g.tolerance!==void 0&&!(g.tolerance>=0)&&s.push(`${Rt(i[g.metricId])}: the tolerance must be zero or more.`):s.push(`${Rt(i[g.metricId])}: weight must be positive.`):s.push(`\u201C${g.metricId}\u201D is not a metric.`);return s}var _A=.1,NA=2e3,i0=3;function f0(e,t,r={},n=NA){t=Lt(e,t);let o=jm(e,t,r),a=u0(r),s=$t(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}@${so(L.at)}`]=Wt(S.ev,D,L.at))}return P},p=S=>m.map(A=>S[`${A.metricId}@${so(A.at)}`]).map(A=>Number.isFinite(A)?A.toFixed(9):"x").join("|"),d=f(l,uo(t)),h=p(d),b=[],g=[],y={},R=[],M=0;t.variables.forEach((S,A)=>{let P=s[S.id];if(!P)return;if(R.length>=i0&&M>n){g.push(P);return}let L=[...i];L[A]=i[A]+(S.hi-i[A])*.25||S.hi;let D=performance.now(),I=c(L),G=performance.now()-D;M+=G,R.push(G);let O=f(I);y[P.id]=O,p(O)===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<i0;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 k=[...R].sort((S,A)=>S-A),F=k.length?k[k.length>>1]:0,w=[],C=uo(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?Zr(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>=_A?w.push(`Over ${P} % of this course, some wheel is asked for more longitudinal force than its own tyre ellipse allows \u2014 the speed profile and the per-wheel reconstruction disagree that far. A reserve read there is the two models disagreeing rather than the car having nothing left, and a search pointed at one will optimise the disagreement. It concentrates in high-speed braking, so a shorter straight into the first corner is the usual cure.`):A>0&&w.push(`${P} % of this course is beyond the per-wheel tyre ellipse, which is the usual level of disagreement between the speed profile and the reconstruction. Reserves are readable; treat small differences between designs as smaller than they look.`)}}return{msPerEval:F,values:d,samples: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 TN=[{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:PN.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 PN=["setup:m","characteristics:peak_power","characteristics:power_to_weight","characteristics:cla","characteristics:cda","characteristics:pack_energy","characteristics:maxAy","characteristics:top_speed"];var Boe=new Set(TN.map(e=>e.kind));var OA={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 h0=["FL","FR","RL","RR"],vt=(e,t,r)=>({input:e,from:r?r[0]:OA[e].from,to:r?r[1]:OA[e].to,n:t}),Hoe=[{id:"sides",name:"Inside and outside",cards:[{id:"camber-roll",form:"curves",title:"Camber to the road through roll",sweep:vt("roll",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"toe-rack",form:"curves",title:"Wheel angle against the rack",sweep:vt("steer",25),wheels:["FL","FR"],y:["toe"]},{id:"camber-rack",form:"curves",title:"Camber to the road through the steer",sweep:vt("steer",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"load-roll",form:"curves",title:"Wheel loads through roll",sweep:vt("roll",25),wheels:h0,y:["wheelLoad"]},{id:"travel-roll",form:"curves",title:"Wheel travel through roll",sweep:vt("roll",25),wheels:h0,y:["travel"]},{id:"toe-roll",form:"curves",title:"Roll steer, all four",sweep:vt("roll",25),wheels:h0,y:["toe"]}]},{id:"maps",name:"Travel and steer together",cards:[{id:"camber-map",form:"surface",title:"Camber over travel and rack",sweep:vt("travel",17),second:vt("steer",13),wheels:["FL"],y:["camber"]},{id:"bump-steer-map",form:"map",title:"Bump steer over travel and rack",sweep:vt("travel",17),second:vt("steer",13),wheels:["FL"],y:["bumpSteer"]},{id:"bump-steer-family",form:"curves",title:"Bump steer through travel, at five rack positions",sweep:vt("travel",25),second:vt("steer",5,[-20,20]),wheels:["FL"],y:["bumpSteer"]},{id:"scrub-map",form:"surface",title:"Scrub radius over travel and rack",sweep:vt("travel",17),second:vt("steer",13),wheels:["FL"],y:["scrubRadius"]}]}];function b0(e){let t=Number(e);return Number.isFinite(t)?Math.min(xf,Math.max(yf,t)):St}var BA=6e4;var Nae=[{within:60*6e4,every:BA},{within:1440*6e4,every:60*6e4},{within:720*60*6e4,every:1440*6e4},{within:1/0,every:10080*6e4}];var GN=new Set(["color","visible","source","origin"]),jae=["id",...GN];var KA=.18/1.18,HA={induction:{kind:"natural"}},zA=e=>e.breathing??HA;function Um(e){switch(e?.kind){case"sae-j1349":return Ei(99e3,25);case"measured":return Ei(e.hPa*100,e.tempC);default:return Ei(101325,20)}}var HN=Um(void 0);function YA(e,t){let r=Um(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 WA(e,t){let r=e.induction;if(r.kind==="table"){let o=s=>Be(r.densityAltitudeM,r.powerPct,s),a=o(Um(e.rated).densityAltitudeM);return a>0?Math.max(0,o(t.densityAltitudeM)/a):0}let n=e.frictionShare??KA;return Math.max(0,(YA(e,t)-n)/(1-n))}var GA=new WeakMap;function y0(e,t){let r=e.asRated??e,n=`${t.p}|${t.pDry}|${t.T}`,o=GA.get(r);o||GA.set(r,o=new Map);let a=o.get(n);if(a)return a;let s=WA(zA(r),t),i={...r,torque:r.torque.map(c=>c*s),asRated:r};return o.set(n,i),i}function jN(e){return JSON.parse(x0(R0(e,"public/laptime/index.json"),"utf8")).tracks}var UN=async e=>{let t=await fetch(e.url);if(!t.ok)throw new Error(`The track could not be read from ${fm(e)} (${t.status}).`);return new Uint8Array(await t.arrayBuffer())};function jA(e,t=new Map,r=UN){let n=jN(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(!Gi(o.address))throw new Error(`"${o.address}" is not a catalogue address`);if(!$i(o.link))throw new Error("This track is linked to a source this version does not read from.");i=await sg(await r(o.link),o.link,o.address)}else if(o.kind==="catalogue"){if(!Gi(o.address))throw new Error(`"${o.address}" is not a catalogue address`);let c=JSON.parse(x0(R0(e,"public/catalogue",cg(o.address)),"utf8"));i=await ug(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(x0(R0(e,"public/laptime",c),"utf8"))}return t.set(a,i),structuredClone(i)}}var XN=9.81;function UA(e,t=e.tireModel,r=e.tireModelRear){if(!t)return e;let n=e.m.value*XN/4,o=da(e,t,r),a=Ie(o.front).rollingRadius(n),s=o.rear===o.front?a:Ie(o.rear).rollingRadius(n),i=qN(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 qN(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 QN=1e-6;function XA(e,t,r){let n=e.cgReference;if(!n||!e.cg_height)return e;let o=G1(e,t,r);if(o===void 0||Math.abs(o-n.standingRadius)<QN)return e;let a=n.typed??e.cg_height.value;return{...e,cg_height:{...e.cg_height,value:pa(e.cg_height.value,n.standingRadius,o)},cgReference:{...n,standingRadius:o,typed:a}}}function qA(e,t,r){let n=e.rcRoad,o=e.rc_front,a=e.rc_rear;if(!n||!o||!a)return e;let s=cu(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 QA=e=>({brakeFade:e.brakeFade,airTempC:e.airTempC,diffYaw:e.diffYaw,...Ii(e.air)?{air:e.air}:{}});var mo=(e,t)=>t?e.find(r=>r.id===t)?.model:void 0;function po(e){return{tire:t=>mo(e.tires,t),motor:t=>mo(e.motors,t),aero:t=>mo(e.aeros,t),battery:t=>mo(e.batteries,t),brake:t=>mo(e.brakes??[],t),damper:t=>mo(e.dampers??[],t),suspensionOf:t=>Im(v0(e,t),t)}}function v0(e,t){let r=mo(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 k0(I1(t.suspensionOf(e),e,n),t,r)}function ZN(e){return Ii(e.air)?ZM(e.air,e.airTempC??St):void 0}var JN="the air the session states, at its venue";function eO(e,t){return t?{...e,rho:{...e.rho,value:t.rho},readouts:{...e.readouts,rho:JN}}:e}function tO(e,t,r){if(!r)return{rho:e.rho,motorModel:t,readouts:e.readouts};let{rho:n,readouts:o}=eO(e,r);return{rho:n,motorModel:t&&mt(t)?y0(t,r):t,air:r,readouts:o}}function k0(e,t,r){let n=t.tire(e.tireModelId),o=t.tire(e.tireModelIdRear),a=qA(XA(UA(Y1(K1(J1(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}=tO(a,t.motor(e.motorModelId),ZN(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),...qs(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 aO=e=>e!==!1,sO=(e,t,r)=>r&&t>0?(e%t+t)%t:Math.min(Math.max(e,0),t);function iO(e,t,r){let n=e.points.filter(o=>Number.isFinite(o.at)&&Number.isFinite(o.z)).map(o=>({...o,at:sO(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 cO(e,t,r){let n=iO(e,t,r),o=n.length;if(o===0)return[];let a=p=>p<o-1?n[p+1].at-n[p].at:r?n[0].at+t-n[p].at:1/0,s=p=>p<o-1?(n[p+1].z-n[p].z)/a(p):r&&o>1?(n[0].z-n[p].z)/a(p):0,i=n.map(p=>Math.max(0,Number.isFinite(p.curve)?p.curve:0)/2),c=(p,d,h)=>i[p]+i[d]>h?h*i[p]/(i[p]+i[d]):i[p],l=p=>p<o-1||r?c(p,p<o-1?p+1:0,a(p)):Math.max(0,t-n[p].at),u=p=>p>0?c(p,p-1,a(p-1)):r?c(p,o-1,a(o-1)):n[p].at,m=p=>p>0?s(p-1):r&&o>1?s(o-1):n[p].at<=1e-9?s(p):0,f=p=>!r&&p===o-1&&o>1&&n[p].at>=t-1e-9?s(p-1):s(p);return n.map((p,d)=>{let h=l(d),b=u(d),g=Math.min(i[d],h,b),y=!r&&g<i[d]&&(d===o-1&&g===h||d===0&&g===b);return{at:p.at,z:p.z,gIn:m(d),gOut:f(d),half:g,asked:i[d],atEnd:y}})}function lO(e,t,r,n){let o=t-e.at;return n&&r>0?o-r*Math.round(o/r):o}function uO(e,t,r,n){for(let s of e){let i=lO(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 ZA(e,t,r,n){let o=aO(n),a=cO(e,r,o);return a.length?t.map(s=>uO(a,s,r,o)):t.map(()=>0)}function lc(e,t){if(!t?.points.length)return e;let r=Wi(e),{zSmoothing:n,...o}=e;return{...o,z:ZA(t,r,Rg(e),e.closed)}}var Xm={widthLeft:1.5,widthRight:1.5,bank:0,mu:1};function JA(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 uc(e,t){let r=JA(e.source);return eF(e,r?await t(r):void 0)}function eF(e,t){let{source:r}=e;if(r.kind==="segments"){let{segments:i,closed:c,spacing:l}=r,{asset:u}=Ui(i,{name:e.name,closed:c,spacing:l,base:Xm});return lc(u,r.profile)}let n=r.sections??[];if(r.kind==="inline")return lc(Rm(r.asset,n,Xm),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 lc(Rm({...t,...o!==void 0?{widthLeft:o}:{},...a!==void 0?{widthRight:a}:{},...s!==void 0?{closed:s}:{}},n,Xm),r.profile)}var kce=1/500;var Mce=5*Math.PI/180;var Dce=1/3;var fO=[4,2,1,.5,.25,.125];function tF(e,t,r={}){let n=[...r.steps??fO].sort((g,y)=>y-g),o=at(r.numerics),a=r.tolPct??.5,s=Ft(e),i=e.ggvMode??"twoTrack",c=ir(s,!1,i),l={...o,dsTarget:n[0]??o.dsTarget},u=n.length?jn(s,c,[yt(t,l)],l,i):void 0,m=un(s,c.rows),f=n.map((g,y)=>{let R={...o,dsTarget:g},M=Date.now(),v=yt(t,R),x=gt(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()-M}}),p=f[f.length-1]?.lapTime??NaN,d=f.map(g=>{let y=g.lapTime-p;return{...g,delta:y,deltaPct:p?100*y/p:NaN}}),h=d.filter(g=>Math.abs(g.deltaPct)<=a),b=h.length?Math.max(...h.map(g=>g.dsTarget)):null;return{points:d,reference:p,recommended:b,tolPct:a}}function Oa(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:b0(t.airTempC??r.airTempC),...Ii(am(t.air??r.air))?{air:am(t.air??r.air)}:{},diffYaw:t.diffYaw??r.diffYaw,racingLine:t.racingLine??r.useRacingLine,standingStart:t.standingStart??(a?a.standingStart===!0:r.standingStart),lapCounts:t.lapCounts??r.lapCounts,numerics:at(r.numerics)}}async function qm(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 uc(r,t)}}function gO(e,t){let r=structuredClone(e);for(let[n,o]of Object.entries(t))if(!hu(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 M0=(e,t)=>{let r=e?.name;return typeof r=="string"&&r?r:t};function yO(e,t){let r={};for(let n of dn){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:M0(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:M0(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:M0(i.model,i.id),byFallback:!0}:null;continue}r[n.doc]=null}return r}function xO(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 rF(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 nF=e=>e.length<2?e[0]??"":`${e.slice(0,-1).join(", ")} and ${e[e.length-1]}`;async function Qm(e,t,r={}){let n=Oa(e,r.settings),{entry:o,asset:a}=await qm(e,t),s=po(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]?gO(d.params,r.overrides[d.id]):d.params;return fo(structuredClone(h),s,n)}),l=wi(Zn(e.meta.rulesetId,e.rulesets)),u=Di(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}=Ob(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:xO(u[h]),metrics:Vb(l,u[h],p?.[d.id]),fitted:yO(e,d.params),...f?.[d.id]?{score:{total:f[d.id].total,parts:{...f[d.id].parts}}}:{}})),raw:{results:m,scores:f,field:p}}}async function oF(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=Oa(e),{asset:a}=await qm(e,t),s=fo(structuredClone(n.params),po(e),o);return tF(s,a,{...r.steps?{steps:r.steps}:{},numerics:o.numerics,...r.tolPct!==void 0?{tolPct:r.tolPct}:{},...r.onStep?{onStep:r.onStep}:{}})}var RO=(e,t)=>e[t]??[],vO=(e,t,r)=>r<=1?[e]:Array.from({length:r},(n,o)=>e+(t-e)*o/(r-1));function Zm(e){return e.kind==="param"?vO(e.start,e.end,Math.max(1,Math.round(e.steps))):e.kind==="part"?[...e.partIds]:[...e.values]}var aF=e=>e.kind==="param"?e.label:e.kind==="part"?`${e.part} model`:e.setting;function kO(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),po(e),Oa(e)),o=Q1(n,{geometry:!0}),a=fu(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=dn.find(l=>l.doc===i.part);if(!c)throw new Error(`"${i.part}" is not a library \u2014 it is one of ${dn.map(l=>l.doc).join(", ")}`);for(let l of i.partIds)if(!RO(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*Zm(c).length,1);if(s>tm)throw new Error(`that grid is ${s} runs, over the ${tm} cap \u2014 a run is a whole session. Drop an axis or use fewer steps.`)}var MO=e=>e.map(t=>String(typeof t=="number"?Number(t.toPrecision(4)):t)).join(" \xD7 ");function SO(e,t){let r=[...new Set(e.flatMap(o=>(o.didNotFinish??[]).map(a=>a.label)))],n=e.map(o=>({name:MO(o.at),events:r.map(a=>({label:a,incomplete:o.didNotFinish?.find(s=>s.label===a)}))}));return rF(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`:nF(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 AO(e){let t=[[]];for(let r of e){let n=Zm(r),o=[];for(let a of n)for(let s of t)o.push([...s,a]);t=o}return t}async function sF(e,t,r,n){kO(e,r);let o=AO(r.axes),a=[],s=!1;for(let[u,m]of o.entries()){let f=structuredClone(e),p=f.vehicles.find(M=>M.id===r.vehicleId),d={...r.settings},h={};r.axes.forEach((M,v)=>{let x=m[v];if(M.kind==="param")h[M.label]=x;else if(M.kind==="part"){let k=dn.find(F=>F.doc===M.part);p.params[k.ref]=x}else d[M.setting]=x});let b=r.fleet?f.vehicles.filter(M=>M.visible||M.id===r.vehicleId).map(M=>M.id):[r.vehicleId],g=await Qm(f,t,{vehicleIds:b,settings:d,...Object.keys(h).length?{overrides:{[r.vehicleId]:h}}:{}});s=g.fleetScored;let y=g.vehicles.find(M=>M.id===r.vehicleId),R=y.events.flatMap(M=>M.incomplete?[{label:M.label,...M.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(Zm(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(aF(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(...SO(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:aF(u),values:Zm(u)})),runs:a,metricKeys:i,fleetScored:s,flat:c,caveats:l}}var Vue=Math.PI/180;function S0(e){if(!e.chassis)return e;let{chassis:t,...r}=e;return r}var Cfe=180/Math.PI;var hV={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:Qn,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 nbe=hV.id;var mc=.02;function xF(e){let t=Math.max(mc,Math.abs(e.heaveMotionRatio)),r=Math.max(mc,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 gV=(e,t)=>({od:t,id:Math.min(e.id,t-.5)}),yV=(e,t)=>e/(2*t*t);function yF(e,t){switch(e.kind){case"ubar":case"blade":case"torsionTube":return{...e,section:gV(e.section,t)};default:return e}}function RF(e,t,r){let n=Math.max(mc,Math.abs(r));if(e?.kind==="coil"){let l=yV(t,n),u=e.rate;if(typeof u=="number")return{...e,rate:l};let m=Er(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=>ei(yF(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 yF(a,c)}function vF(e,t,r,n){let o=e?.design,a=RF(t?.design,r.rollWheelRate,n);return{heave:{design:{kind:"coil",rate:r.heaveRate,motionRatio:o?.kind==="coil"?o.motionRatio:1,gap:0,bothWays:!0},linkage:e?.linkage,damper:r.heaveDamper},arb:{design:a,linkage:t?.linkage,damper:a.kind==="coil"?r.rollDamper/2:r.rollDamper}}}var xV=Math.PI/180,Jm=1e-6;function RV(e){return!(ve(e.rockerPivotA,e.rockerPivotB)<Jm||ve(e.rockerToPushrod,e.rockerPivotA)<Jm||ve(e.rockerToDamper,e.rockerPivotA)<Jm||ve(e.rockerToDamper,e.damperChassis)<Jm)}function AF(e){if(!RV(e.hardpoints))return!1;let t={...e,config:{...e.config,actuation:"rocker"}};try{let r=et(t);for(let n of[-20,-1,0,1,20]){let o=ge(r,n,0);if(!o.ok||!Number.isFinite(o.state.metrics.damperLength))return!1}return!0}catch{return!1}}function FF(e){if(e.config.actuation!=="direct"||AF(e))return;let{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}=kV(e);return{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}}var kF=40;function ep(e,t={}){let r=e.hardpoints,n=r.pushrodOuter,o=r.damperChassis,a=ve(n,o),s=ee(n,U(H(o,n),vV)),i=t.armRod??Math.max(25,.15*a),c=t.armDamper??i,l=[s[0]-kF,s[1],s[2]],u=[s[0]+kF,s[1],s[2]],m=q(H(u,l)),f=H(n,s),p=q(H(f,U(m,MF(f,m)))),d=Et(p,m,(t.armAngleDeg??60)*xV),h=ee(s,U(d,i)),b=H(o,s),g=q(H(b,U(m,MF(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 vV=.72,MF=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2];function SF(e){let t=qe(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 kV(e,t={}){let r=t.target??SF(e),n=t.armAngleDeg,o=ep(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=ep(e,{armRod:s,armAngleDeg:n,damperSide:p}),h={...e,config:{...e.config,actuation:"rocker"},hardpoints:d};try{let b=et(h),g=ge(b,15,0),y=ge(b,-15,0);if(g.ok&&y.ok&&g.state.metrics.damperLength<y.state.metrics.damperLength)return p}catch{}}return 1})(),c=(p,d)=>{try{return SF({...e,config:{...e.config,actuation:"rocker"},hardpoints:ep(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,M=c(p,R);if(!Number.isFinite(M))break;b=R,M<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 ep(e,{armRod:u,armAngleDeg:n,armDamper:m,damperSide:i})}var gbe=Array.from({length:19},(e,t)=>-45+5*t);var ybe=Math.PI/180;function MV(e){let t=e.hardpoints,r=q(H(t.rockerPivotB,t.rockerPivotA)),n=jr(t.rockerToDamper,t.rockerPivotA,r),o=.6*Wr(H(t.rockerToDamper,n)),a=ae(r,Cy),s=Wr(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 SV=(e,t)=>({...e,config:{...e.config,actuation:t}});function w0(e,t,r,n){let o=r==="front"?e.front:e.rear,a=ou(o),s=o.config.springRate*a*a,i=Z(t,r==="front"?"damper_front":"damper_rear")*a*a,c=r==="front"?t.arbFrontDesign:t.arbRearDesign,l=$n(e,t)[r]??Z(t,r==="front"?"arb_front":"arb_rear"),u=ma(e,t)[r]??Z(t,r==="front"?"heave_spring_front":"heave_spring_rear"),m=FF(o),f=SV(m?{...o,hardpoints:{...o.hardpoints,...m}}:o,"decoupled"),p=r==="front"?t.heaveFrontDesign:t.heaveRearDesign,d=n?.heave??wF(p?.linkage,w=>kn(f,w).atDesign)??bd(f,"rockerToRocker"),h=!c||c.design.kind==="none"||c.design.kind==="coil",b=h?"coil":"ubar",g=c?.linkage&&(c.design.kind==="none"||c.linkage.attach!=="rocker")?c.linkage:void 0,y=n?.roll??wF(h?g:c?.linkage,w=>Oo(f,w,{kind:b}).atDesign)??(h?MV(f):b1(f)),R=kn(f,d).atDesign,M=Oo(f,y,{kind:b}).atDesign,v=su(e,t),x=xF({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:M}),k=!c||c.design.kind==="none"?{design:{kind:"coil",rate:1},linkage:y}:{...c,linkage:y},F=vF({design:p?.design??{kind:"none"},linkage:d,damper:p?.damper},k,x,M);return m?{...F,crank:m}:F}function wF(e,t){return e&&Math.abs(t(e))>=mc?e:void 0}var tp=[{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"]}],C0=()=>({arbFront:void 0,arbRear:void 0,heaveFront:void 0,heaveRear:void 0}),AV={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]}},FV={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]}},wV=()=>({outer:[0,189,486],attach:"rocker",mount:{kind:"chassis",anchor:[-225,0,486]}}),CV={rate:60,motionRatio:1},TV={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]}},PV=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]}},LV={kind:"coil",rate:1560,motionRatio:1,gap:0,bothWays:!0},DV=40,EV={rockerPivotA:[50,130,440],rockerPivotB:[-50,130,440],rockerToPushrod:[10,170,460],rockerToDamper:[-20,64,440],damperChassis:[-20,64,215]},CF=()=>({outer:[-50,130,480],attach:"rocker",shaftStation:-50}),TF=()=>({outer:[50,130,400],inner:[50,130,480],attach:"rocker",shaftStationOuter:50,shaftStationInner:50}),IV=e=>[e[0],e[1],e[2]];function _V(e){let t=r=>({...r,hardpoints:{...r.hardpoints,...LF(EV)},config:{...r.config,actuation:"decoupled"}});return{...e,front:t(e.front),rear:t(e.rear)}}function LF(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,IV(r)]))}function DF(e,t=no(),r=e==="pull"?FV:AV){let n=(o,a)=>({...o,hardpoints:{...o.hardpoints,...LF(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 rp(e,t){let r=T0(e),n=Va(e);if(e==="heave")return{meta:r,vehicle:n,components:{...C0(),heaveFront:{design:{...Lh,...CV},linkage:wV()}}};if(e!=="decoupled")return{meta:r,vehicle:n,components:C0()};let o=w0(n,t,"front",{heave:CF(),roll:TF()}),a=w0(n,t,"rear",{heave:CF(),roll:TF()});return{meta:r,vehicle:n,components:{arbFront:o.arb,arbRear:a.arb,heaveFront:o.heave,heaveRear:a.heave}}}function Va(e){let{name:t}=T0(e);if(e==="direct")return{...Ni(),name:t};if(e==="mcpherson"){let n=Oi(),o=im();return{...n,front:{...o,config:{...o.config,loadedRadius:n.front.config.loadedRadius}},name:t}}let r=NV(DF(e==="pullrod"?"pull":"push"));return{...e==="decoupled"?_V(r):r,name:t}}var PF={front:221.7,rear:220.9};function NV(e){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:PF.front}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:PF.rear}}}}function T0(e){let t=tp.find(r=>r.id===e);if(!t)throw new Error(`Unknown suspension template: ${e}`);return t}function np(){let e=t=>({design:{...LV},linkage:PV(t),damper:DV});return{meta:T0("heave"),vehicle:DF("push",Yb(),TV),components:{...C0(),heaveFront:e("front"),heaveRear:e("rear")}}}var EF=[10,25,50,100,200,300],OV=[{id:"c1",label:"Soft",scale:.7},{id:"c2",label:"Medium",scale:1},{id:"c3",label:"Firm",scale:1.4}],IF=e=>Math.round(e*100)/100;function VV(e,t,r){let n=EF.map(o=>IF(r*o));return{id:e,label:t,speedMmS:[...EF],bumpN:n,reboundN:[...n]}}function BV(e){return{name:e.name,body:{...e.body},curves:OV.map(t=>VV(t.id,t.label,IF(e.coefficient*t.scale)))}}function pc(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 dr(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:Hi[e.dampers.length%Hi.length],model:BV(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 it=e=>`${e} (typical)`,P0={car:{name:it("Formula Student damper"),coefficient:2.5,body:{extended:249,stroke:55}}},op={car:P0.car,heave:{name:it("Formula Student heave damper"),coefficient:3.4,body:{extended:270,stroke:47}},roll:{name:it("Formula Student roll damper"),coefficient:3.7,body:{extended:322,stroke:100}}},ap={car:{name:it("Formula 1 damper"),coefficient:6,body:{extended:240,stroke:40}},heave:{name:it("Formula 1 heave damper"),coefficient:40,body:{extended:240,stroke:40}}},_F={car:{name:it("GT damper"),coefficient:4.5,body:{extended:510,stroke:80}}},L0={car:{name:it("Sports car damper"),coefficient:2.4,body:{extended:515,stroke:110}}},NF={car:{name:it("Sports car strut"),coefficient:2.4,body:{extended:310,stroke:120}},rear:L0.car},OF={car:{name:it("Cup car strut"),coefficient:4,body:{extended:285,stroke:75}},rear:{name:it("Cup car rear damper"),coefficient:3.5,body:{extended:505,stroke:80}}},VF={car:{name:it("Stock car front damper"),coefficient:7.5,body:{extended:555,stroke:110}},rear:{name:it("Stock car rear damper"),coefficient:6.75,body:{extended:555,stroke:110}}},BF={car:{name:it("Hill-climb front damper"),coefficient:3,body:{extended:285,stroke:65}},rear:{name:it("Hill-climb rear damper"),coefficient:3.5,body:{extended:285,stroke:65}}},$F={car:{name:it("Race truck front damper"),coefficient:12,body:{extended:780,stroke:160}},rear:{name:it("Race truck rear damper"),coefficient:8.5,body:{extended:780,stroke:160}}};function $a(e){return e.vehicles=e.vehicles.slice(0,1),e.activeVehicleId=e.vehicles[0]?.id??null,e}function gn(e,t){let r=zi(e);return r.meta.rulesetId=t,r}function ho(e,t,r,n){let o=gn(e,t);return o.suspensions=[{...o.suspensions[0],model:n()}],o.vehicles=[gg(r,"v1",0)],o.activeVehicleId="v1",o}var[,$V,GV,KV,HV,zV,YV,WV]=Jb;function D0(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 GF(){return{...Va("decoupled"),name:no().name}}var jV=[{label:"Formula Student (decoupled)",vehicle:GF,components:e=>pc(rp("decoupled",e).components,op)},{label:"Formula 1 (third springs)",vehicle:()=>np().vehicle,components:()=>pc(np().components,ap)}],E0={"direct-coilover":"direct",pushrod:"pushrod",pullrod:"pullrod","third-spring":"heave","mcpherson-strut":"mcpherson"},UV=[...jV.map(e=>e.vehicle),...Object.values(E0).map(e=>()=>Va(e))];function Ba(e){let t=pc(rp("decoupled",e.vehicles[0].params).components,op);e.suspensions=[{...e.suspensions[0],model:GF()}];for(let r of e.vehicles)D0(r.params,t);return dr(e,op),e}var bo={title:"OpenStreetMap",url:"https://www.openstreetmap.org/copyright",licence:"ODbL-1.0",credit:"\xA9 OpenStreetMap contributors"},sp={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"},KF={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]"},HF={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"},XV={id:"cota",name:"Circuit of the Americas, Austin",address:"e0c6ea889d708cf15f9c",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[bo,sp,HF]}},qV={id:"laguna-seca",name:"Laguna Seca, Monterey",address:"185b5811b9c423ef44ef",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[bo,sp,HF]}},QV={id:"nordschleife",name:"Nordschleife, N\xFCrburg",address:"74c49603c7b2f15985c6",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[bo,KF]}},ZV={id:"brands-hatch",name:"Brands Hatch, Kent",address:"c4953e3c25eaba4a5b7e",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[bo,{title:"Environment Agency LIDAR Composite DTM, 1 m",url:"https://environment.data.gov.uk/dataset/13787b9a-26a4-4775-8523-806d13af58fc",licence:"OGL-UK-3.0",credit:"\xA9 Environment Agency copyright and/or database right 2022. All rights reserved."}]}},JV={id:"bristol",name:"Bristol, Tennessee",address:"f0e23953669a414ad600",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[bo,sp]}},e5={id:"pikes-peak",name:"Pikes Peak, Colorado",address:"3de137fe33b5c2875036",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[bo,sp]},standingStart:!0},t5={source:"venue",altitudeM:3580,pressure:{kind:"standard"},humidityPct:0},r5=10,n5={id:"nurburg-sprint",name:"Sprintstrecke, N\xFCrburg",address:"1875636cdbb615aa2756",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[bo,KF]}};function go(e,t){let{id:r,name:n,address:o,provenance:a,standingStart:s}=t,i={kind:"catalogue",id:r,address:o},c=Vi(lg({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 yn(e,t,r){let n=e.vehicles[0].params,o=`m${e.motors.length+1}`;e.motors=[...e.motors,{id:o,color:fn[e.motors.length%fn.length],model:t}];let a=V1({},{...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 o5=3.8,ip={hubPlanetary:14.5,inboardChain:4,engineChain:3.4},a5="Hub motor, 35 kW (example)";function I0(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 zF(e){let t=e.motors.find(r=>r.id==="m1");return t.model={...t.model,name:a5},t.id}function cp(e,t,r){let n=$a(Ba(gn(e,r)));return n.vehicles[0].params.name=t,n}function s5(){let e=cp("Formula Student combustion car","Formula Student combustion","fs-cv");yn(e,og(),ip.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 i5(){let e=cp("Formula Student AWD car","Formula Student AWD","fs-ev");return I0(e,zF(e),4,"awd",ip.hubPlanetary,"hub"),e}function c5(){let e=cp("Formula Student RWD hub-motor car","Formula Student RWD hub motors","fs-ev");return I0(e,zF(e),2,"rear",ip.hubPlanetary,"hub"),e}function l5(){let e=cp("Formula Student one-motor car","Formula Student RWD one motor","fs-ev"),t=`m${e.motors.length+1}`;return e.motors=[...e.motors,{id:t,color:fn[e.motors.length%fn.length],model:ng()}],I0(e,t,1,"rear",ip.inboardChain),e.vehicles[0].params.driveline={rear:structuredClone(bt.clutch)},e}function u5(){let e=$a(Ba(gn("Formula Student endurance energy","fs-ev"))),t=e.vehicles[0],r=structuredClone(t);if(r.id="v2",r.color=Ki[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 m5(){let e=np(),t=ho("Formula 1 car","trackday",$V,()=>e.vehicle);return D0(t.vehicles[0].params,pc(e.components,ap)),dr(t,ap),yn(t,ag(),o5),go(t,XV)}function YF(e="GT car",t=Ni){let r=ho(e,"trackday",GV,t);return dr(r,_F),yn(r,pS(),r.vehicles[0].params.gear_ratio.value),go(r,qV)}function WF(e="Sports car",t=Oi,r=L0){let n=ho(e,"trackday",KV,t);return dr(n,r),yn(n,dS(),n.vehicles[0].params.gear_ratio.value),go(n,QV)}function p5(){let e=ho("Cup car","trackday",HV,eS);return dr(e,OF),yn(e,fS(),e.vehicles[0].params.gear_ratio.value),go(e,ZV)}function d5(){let e=ho("Stock car","trackday",zV,tS);return dr(e,VF),yn(e,hS(),e.vehicles[0].params.gear_ratio.value),go(e,JV)}function f5(){let e=ho("Hill-climb prototype","trackday",YV,rS);return dr(e,BF),yn(e,bS(),e.vehicles[0].params.gear_ratio.value),e.settings.air=structuredClone(t5),e.settings.airTempC=r5,go(e,e5)}function h5(){let e=ho("Race truck","trackday",WV,nS);return dr(e,$F),yn(e,gS(),e.vehicles[0].params.gear_ratio.value),go(e,n5)}function b5(e){let t=tp.find(o=>o.id===e);if(e==="direct")return YF(t.name,()=>Va(e));if(e==="mcpherson")return WF(t.name,()=>Va(e),NF);let r=$a(gn(t.name,"trackday")),n=rp(e,r.vehicles[0].params);return r.suspensions=[{...r.suspensions[0],model:n.vehicle}],D0(r.vehicles[0].params,n.components),dr(r,P0),r}function dc(e,t,r){let n=E0[e],o=tp.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:()=>b5(n)}}var g5=[{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:()=>Ba(gn("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:u5},{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:()=>$a(Ba(gn("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:s5},{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:i5},{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:c5},{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:l5},{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:m5},{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:YF},{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:WF},{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:p5},{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:d5},{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:f5},{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:h5},{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:()=>$a(Ba(gn("Suspension study","trackday")))},dc("direct-coilover","The GT car\u2019s wishbones driving coilovers straight into the towers, at Laguna Seca.","On the GT car, at Laguna Seca."),dc("pushrod","The FS car on pushrods: a rod from each lower wishbone works a rocker.","On the Formula Student car, at FSG."),dc("pullrod","The FS car on pullrods: a rod from each upper wishbone pulls a low rocker.","On the Formula Student car, at FSG."),dc("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."),dc("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:()=>$a(Ba(gn("Tyre study","fs-ev")))}],jF=g5.map(e=>({...e,load:()=>yg(e.load())}));var UF={width:320,height:200},rge=[.6*UF.width-9,.6*UF.height-9];var XF=new WeakMap,qF=new WeakMap,_0=e=>JSON.stringify(e,(t,r)=>r===1/0?"Infinity":r);function QF(e,t){if(!t){let a=XF.get(e);return a||(a=Ct(e),XF.set(e,a)),a}let r=qF.get(e);r||(r=new Map,qF.set(e,r));let n=_0(t),o=r.get(n);return o||(r.size>=4&&r.clear(),o=Ct(e,t),r.set(n,o)),o}var R5=Math.PI/180,v5=e=>e>1?e/100:e;function fc(e){let t=null;return()=>(t??={v:e()}).v}function ZF(e){let t=qe(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 JF=new WeakMap,N0={heave:0,pitch:0,roll:0,steer:0},ew=[0,1,2,3,4],tw=[-20,-10,0,10,20];function nw(e,t){let r=Ir(e,N0),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 ew){let l=c===0?null:Ir(e,{...N0,roll:c*R5});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 tw){let l=c===0?null:Ir(e,{...N0,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:ew,rcFront:s[0].rc,rcRear:s[1].rc,rcSplitFront:s[0].split,rcSplitRear:s[1].split},heave:{drop:tw,rcFront:i[0],rcRear:i[1]}}}var rw=new WeakMap;function k5(e,t,r,n){let o=rw.get(e);o||(o=new Map,rw.set(e,o));let a=`${_0(r)}|${n[0]}|${n[1]}`,s=o.get(a);if(!s){o.size>=4&&o.clear();try{s=nw(QF(e,r),n)}catch{s=t.rigidMigration(n)}o.set(a,s)}return s}function M5(e){let t=JF.get(e);if(t)return t;let r=Ct(e),n=Ir(r,{heave:0,pitch:0,roll:0,steer:0}),o=ZF(e.front),a=ZF(e.rear),s={wheelbase:e.config.wheelbase,trackFront:dt(e.front),trackRear:dt(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:ua(n.front),rcGainRear:ua(n.rear),rigidMigration:i=>nw(r,i),kinFront:fc(()=>jo(e.front)),kinRear:fc(()=>jo(e.rear))};return JF.set(e,s),s}function ow(e,t,r,n){let o=M5(e),a=$n(e,t),s=ma(e,t),i=P1(e,t),c=su(e,t),l=L1(e,t),u=E1(t),m=D1(e,t),f=Bn(e.front),p=Bn(e.rear),d=Vn(t.damperModel,t.damperSetup,o.mrFront,o.mrRear,t.damperModelRear??t.damperModel),h={rho:t.rho.value,area:t.A.value,cl:t.c_l.value,cw:t.c_w.value,copLongFront:1-Math.max(0,Math.min(1,Z(t,"cop_long"))),copHeight:Z(t,"cop_height"),...t.aeroModel?{model:t.aeroModel}:{},rideHeightFront:Z(t,"ride_height_front"),rideHeightRear:Z(t,"ride_height_rear")},b=9.81,g=v5(t.front_mass_diss.value),y=da(t,r,n),R=Ie(y.front),M=y.rear===y.front?R:Ie(y.rear),v=n??t.tireModelRear??r,x=t.m.value*b*g/2,k=t.m.value*b*(1-g)/2,F=R.corneringStiffness(x),w=M.corneringStiffness(k),C=(r?R.verticalStiffness():0)||Z(t,"tire_vertical_rate"),T=(v?M.verticalStiffness():0)||Z(t,"tire_vertical_rate"),S=er(r)??0,A=er(v)??0,P=mu({freeRadius:S,staticLoad:x,tyreRate:C,surveyed:e.front.config.loadedRadius},{freeRadius:A,staticLoad:k,tyreRate:T,surveyed:e.rear.config.loadedRadius},g),L=Bt(S,x,C,e.front.config.loadedRadius),D=Bt(A,k,T,e.rear.config.loadedRadius),I=[_r(o.rcHeightFront,o.rcGainFront,e.front.config.loadedRadius,L),_r(o.rcHeightRear,o.rcGainRear,e.rear.config.loadedRadius,D)],G=fc(()=>ii(o.kinFront(),Z(t,"camber_front_deg"))),O=fc(()=>ii(o.kinRear(),Z(t,"camber_rear_deg"))),W=fc(()=>k5(e,o,Da(V),I)),E=_s({...t,wheelbase:{...t.wheelbase,value:o.wheelbase}}),_=si(t),V={massTotal:t.m.value,frontMassFrac:g,steeringSystem:t.steeringSystem,tv:Ul(t),cgHeight:pa(Z(t,"cg_height"),t.cgReference?.standingRadius,P),cgStandingRadius:P,wheelbase:o.wheelbase,trackFront:o.trackFront,trackRear:o.trackRear,wheelRateFront:f?0:o.wheelRateFront,wheelRateRear:p?0:o.wheelRateRear,decoupledFront:f,decoupledRear:p,...u.front?{elementLinkagesFront:u.front}:{},...u.rear?{elementLinkagesRear:u.rear}:{},...m.front.source==="part"?{cornerCoiloverFront:m.front.coilover}:{},...m.rear.source==="part"?{cornerCoiloverRear:m.rear.coilover}:{},...m.heaveFront.coilover?{heaveCoiloverFront:m.heaveFront.coilover}:{},...m.heaveRear.coilover?{heaveCoiloverRear:m.heaveRear.coilover}:{},...i.front&&!f?{heaveSeatFront:i.front}:{},...i.rear&&!p?{heaveSeatRear:i.rear}:{},...m.rollFront.coilover?{rollCoiloverFront:m.rollFront.coilover}:{},...m.rollRear.coilover?{rollCoiloverRear:m.rollRear.coilover}:{},tireRate:C,...T!==C?{tireRateRear:T}:{},tireDamping:Z(t,"tire_vertical_damping"),arbFront:a.front??Z(t,"arb_front"),arbRear:a.rear??Z(t,"arb_rear"),brakeBalanceFront:E.balanceFront,brakes:E,..._?{driveline:_}:{},heaveSpringFront:s.front??Z(t,"heave_spring_front"),heaveSpringRear:s.rear??Z(t,"heave_spring_rear"),unsprungPerCorner:Z(t,"unsprung_mass"),unsprungCgHeight:Bt(S,x,C,o.unsprungCgHeight),tyreFreeRadius:S,...A!==S?{tyreFreeRadiusRear:A}:{},rcHeightFront:I[0],rcHeightRear:I[1],corneringStiffnessFront:F,corneringStiffnessRear:w,get kinFront(){return G()},get kinRear(){return O()},damperFront:f?0:d?.front?.rate??Z(t,"damper_front")*o.mrFront*o.mrFront,damperRear:p?0:d?.rear?.rate??Z(t,"damper_rear")*o.mrRear*o.mrRear,...d?.front&&!f?{damperCurveFront:d.front.curve}:{},...d?.rear&&!p?{damperCurveRear:d.rear.curve}:{},heaveDamperFront:l.heaveFront?.rate??c.heaveFront,heaveDamperRear:l.heaveRear?.rate??c.heaveRear,rollDamperFront:l.rollFront?.rate??c.rollFront,rollDamperRear:l.rollRear?.rate??c.rollRear,...l.heaveFront?{heaveDamperCurveFront:l.heaveFront.curve}:{},...l.heaveRear?{heaveDamperCurveRear:l.heaveRear.curve}:{},...l.rollFront?{rollDamperCurveFront:l.rollFront.curve}:{},...l.rollRear?{rollDamperCurveRear:l.rollRear.curve}:{},unsprungCornerMass:Z(t,"unsprung_mass"),get rollCentreCurve(){return W().roll},get rcHeaveCurve(){return W().heave},aero:h,yawInertia:Z(t,"I_yaw"),rollInertia:Z(t,"I_roll"),pitchInertia:Z(t,"I_pitch"),get steerFront(){return iu(e.front,L)},ackermannPct:Z(t,"ackermann_pct"),toeFrontDeg:Z(t,"toe_front_deg"),toeRearDeg:Z(t,"toe_rear_deg")};return V}var sw=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}),V0={ggvMode:"twoTrack"},aw=new WeakMap;function B0(e,t=V0){let r=aw.get(e.vehicle);r||aw.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={...sw(e.params),suspensionOf:()=>e.vehicle};n.set(o,a=fo(e.params,s,t))}return a}var iw=(e=V0)=>t=>B0(t,e),cw=(e=V0)=>t=>ow(t.vehicle,k0(t.params,sw(t.params),e),t.params.tireModel,t.params.tireModelRear);function S5(e,t){return B0(e,t.switches)}var $0=e=>Gr(e?.rulesets);function lw(e,t,r,n,o={},a=()=>r.standingStart){let s=B0(n,r.switches),i=(l,u)=>{let m=em(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 uw=e=>[...new Set(e.lap.courses.flatMap(t=>t.course.kind==="track"?[t.course.trackId]:[]))],mw=e=>{let t=e?.session;return t?{sessionParams:r=>S5(r,t),session:()=>t}:{}},lp=e=>({metrics:$0(e),assemble:cw(e?.switches),simParams:iw(e?.switches),projectTrack:()=>e?.course??null,libraryTrack:t=>e?.tracks?.[t]??null,numerics:e?.numerics,...mw(e)}),A5=(e,t)=>({density:e.density,envelope:e.envelope,operating:e.operating,lap:e.lap,assemble:cw(t?.switches),simParams:iw(t?.switches),projectTrack:()=>t?.course??null,libraryTrack:r=>t?.tracks?.[r]??null,numerics:t?.numerics,...mw(t)}),pw="nelder-mead",dw=600,hc=[0,.15,.15];function fw(e,t,r,n=hc.length){let o=H0(t);return hc.slice(0,Math.max(1,n)).map((a,s)=>({...e,seed:s+1,startJitter:a,car:o,...r?{lap:r}:{}}))}function hw(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 bw(e,t,r,n,o=.01){let a=$0(n).byId;return F5(e,t,r,n).filter(s=>s.excess>-o*(a[s.metricId]?.scale??1))}function F5(e,t,r,n){let o;try{o=Ea(Wm(e,t,r),A5(t,n))}catch{return[]}return w5(o,t,$0(n))}function w5(e,t,r){let n=[];for(let o of t.constraints){let a=r.byId[o.metricId];if(!a)continue;let s=Wt(e,a,o.at);if(!Number.isFinite(s))continue;let i=`${Rt(a)}${cc(o.at,a)}`;n.push({key:o.key,metricId:o.metricId,label:i,unit:a.unit==="-"?"":a.unit,value:s,excess:ic(o,s)})}return n}var C5=.05;function T5(e,t){if(t.id.startsWith("hp.")||Ym(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 Jg(bn(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 qg(Kr(o.hardpoints,n[2]),n[3],1)}function gw(e,t,r){let n=r.filter(f=>f.score.feasible);if(n.length<2)return null;let o=t.map(f=>T5(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(C5,m),unit:a}}var P5={steeringSystem:!0,brakeSetup:!0,driveline:!0,heaveFrontDesign:!0,heaveRearDesign:!0,arbFrontDesign:!0,arbRearDesign:!0},yw=e=>Object.hasOwn(P5,e);function O0(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 L5(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":yw(t)||O0(e)?"block":null}function G0(e,t){t=Lt(e,t);let r=$t(e);return[...t.variables,...t.followers??[]].filter(n=>r[n.id]&&!r[n.id].supersededBy&&!L5(n.id)).map(n=>st(r[n.id]))}function xw(e,t,r){t=Lt(e,t);let n=$t(e),o=Wm(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[co.fore,co.aft]){let y=b.hardpoints[g];for(let R=0;R<3;R++)a.push({kind:"hardpoint",axle:f,key:g,axis:R,value:y[R]})}}else if(m==="arm"){let h=`${f}.${p}`;if(i.has(h))continue;i.add(h);let b=f==="front"?o.vehicle.front:o.vehicle.rear,g=jt[p];for(let y of[g.fore,g.aft]){let R=b.hardpoints[y];for(let M=0;M<3;M++)a.push({kind:"hardpoint",axle:f,key:y,axis:M,value:R[M]})}}else if(m==="hp"&&pr(c.id)){let h=`${f}.${p}`;if(i.has(h))continue;i.add(h);let b=(f==="front"?o.vehicle.front:o.vehicle.rear).hardpoints[p];for(let g=0;g<3;g++)a.push({kind:"hardpoint",axle:f,key:p,axis:g,value:b[g]})}else if(m==="hp")a.push({kind:"hardpoint",axle:f,key:p,axis:"xyz".indexOf(d),value:u});else if(m==="cfg")a.push({kind:"config",axle:f,field:p,value:u});else if(m==="kc"){if(s.has(`kc.${f}`))continue;s.add(`kc.${f}`);let h=f==="front"?o.vehicle.front:o.vehicle.rear;a.push({kind:"compliance",axle:f,value:h.compliance})}else if(m==="param")a.push({kind:"param",label:st(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(yw(m)||O0(c.id)){let h=O0(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 K0(e){let t=performance.now(),{dead:r,unprobed:n,...o}=f0(e.car,e.spec,lp(e.lap));return{...o,deadIds:r.map(a=>a.id),unprobedIds:n.map(a=>a.id),elapsedMs:performance.now()-t}}var H0=e=>e.vehicle.chassis?{...e,vehicle:S0(e.vehicle)}:e;function Rw(e,t){try{let r=z0(e.car,e.spec,e.lap),n=Qo.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:kr(r.variables),score:vr(r,kr(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&&n0(r.variables)?a0(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 z0=(e,t,r)=>jm(e,t,lp(r));function vw(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),...qs(e,t.damper)}}function kw(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 Mw=e=>({ggvMode:e.ggvMode,quasiTransient:e.quasiTransient===!0&&e.ggvMode!=="fast",motorThermal:e.motorThermal===!0,...QA({brakeFade:e.brakeFade===!0,airTempC:e.airTempC,diffYaw:e.diffYaw===!0,...e.air?{air:e.air}:{}})});function D5(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 Sw(e,t){let r=t.plannedPath!==void 0,n=D5(t);return{...lw(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 Y0(e,t){let r=e.vehicles.find(o=>o.id===t);if(!r)throw new Error(`this project holds no vehicle "${t}"`);let n=po(e);return kw(structuredClone(v0(e,r.params)),structuredClone(r.params),vw(r.params,n))}var E5="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 W0(e,t,r,n){if(e.settings.pathPlanId)throw new Error(E5);let o=Oa(e),a=e.tracks.length?(await qm(e,t)).asset:null,s={};for(let i of n?uw(n):[]){let c=e.tracks.find(l=>l.id===i);c&&(s[i]=await uc(c,t))}return Sw(r,{track:a,numerics:o.numerics,racingLine:o.racingLine,standingStart:o.standingStart,lapCounts:o.lapCounts??{},switches:Mw(o),rulesets:e.rulesets??[],library:s,standingOf:i=>e.tracks.find(c=>c.id===i)?.standingStart===!0})}async function Aw(e,t,r,n){let o=Y0(e,r),a=Lt(o,n),s=await W0(e,t,o,a);return K0({id:0,car:o,spec:a,lap:s})}async function Fw(e,t,r,n){let o=Y0(e,r),a=Lt(o,n),s=G0(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 W0(e,t,o,a)}catch(l){return{problems:[l instanceof Error?l.message:String(l)]}}let c=d0(o,a,{...lp(i),metrics:Gr(e.rulesets)});return c.length?{problems:c}:{problems:[],msPerEval:K0({id:0,car:o,spec:a,lap:i}).msPerEval,carFingerprint:qn(H0(o))}}async function I5(e,t,r,n,o,a=[]){let s=fw(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(Rw(m,y=>{y.kind==="progress"?(f.push([y.progress.evaluations,y.progress.score.total]),y.progress.evaluations===0&&(c??=y.progress.score),o?.progress(u*t.budget+y.progress.evaluations,i)):y.kind==="done"?p={result:y.result,elapsedMs:y.elapsedMs}:d=y.message}),d)throw new Error(d);if(!p)throw new Error("the search stopped without a result");let{result:h,elapsedMs:b}=p,g={seed:m.seed,startJitter:m.startJitter,x:h.x,score:h.score,evaluations:h.evaluations,infeasible:h.infeasible,history:h.history,trace:f,elapsedMs:b,...h.snapped?{snapped:h.snapped}:{}};l.push(g),o?.progress((u+1)*t.budget,i),await o?.finished?.(g)}if(!c)throw new Error("the search never scored the starting design");return{method:t.method,budget:t.budget,designScore:c,runs:l}}async function ww(e,t,r,n){let o=Y0(e,r.vehicleId),a=Lt(o,r.spec),s=G0(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 W0(e,t,o,a),c=r.method??pw;if(!Qo.some(b=>b.name===c))throw new Error(`unknown method "${c}" \u2014 it is one of ${Qo.map(b=>b.name).join(", ")}`);let l=r.budget??dw,u=Math.max(1,Math.min(r.seeds??hc.length,hc.length)),m=await I5(o,{spec:a,method:c,budget:l},i,u,n),f=z0(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:hw(f.variables,b.x),constraints:bw(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)=>Ss(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?gw(o,f.variables,m.runs.map(b=>({x:b.x,score:b.score}))):null,writes:xw(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 Tw(){if(typeof process.threadCpuUsage!="function")return performance.now();let e=process.threadCpuUsage();return(e.user+e.system)/1e3}async function N5(e,t){let r=jA(e.root);switch(e.kind){case"sweep":return sF(e.doc,r,e.req,t);case"convergence":return oF(e.doc,r,{vehicleId:e.vehicleId,...e.steps?{steps:e.steps}:{},...e.tolPct!==void 0?{tolPct:e.tolPct}:{},onStep:t});case"study":return ww(e.doc,r,{vehicleId:e.vehicleId,spec:e.spec,...e.method?{method:e.method}:{},...e.budget?{budget:e.budget}:{},...e.seeds?{seeds:e.seeds}:{}},{progress:t,cancelled:()=>!1,tick:async()=>{}});case"fleet":return Qm(e.doc,r,{...e.vehicleIds?{vehicleIds:e.vehicleIds}:{},...e.settings?{settings:e.settings}:{},...e.overrides?{overrides:e.overrides}:{}});case"probe":return Aw(e.doc,r,e.vehicleId,e.spec);case"quote":return Fw(e.doc,r,e.vehicleId,e.spec)}}if(Cw){let e=Cw,t=r=>e.postMessage(r);(async()=>{try{let r=await N5(_5,(n,o)=>t({type:"progress",done:n,total:o}));t({type:"done",result:r,cpuMs:Tw()})}catch(r){t({type:"failed",message:r instanceof Error?r.message:String(r),cpuMs:Tw()})}})()}export{N5 as runJob,Tw as threadCpuMs};
|