@pacedyn/mcp 0.375.0 → 0.380.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/worker.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{parentPort as dC,workerData as dV}from"node:worker_threads";import{readFileSync as p0}from"node:fs";import{join as d0}from"node:path";var bc=e=>e.format!=="points"&&!e.field;var ut=e=>e?.kind==="ice";var K0={packVoltageMax:600,segmentVoltageMax:120,powerLimitKw:80};var De=e=>typeof e=="number"&&Number.isFinite(e);function hC(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 bC(e){return!e||typeof e!="object"?"The cell has no curve.":e.kind==="table"?hC(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 gc(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=bC(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 xn(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 yc(e,t,r,n,o){let a=e.length,s=t.length;if(a===0||s===0)return 0;let i=xn(e,n),c=xn(t,o),l=Math.min(i.i+1,a-1),u=Math.min(c.i+1,s-1),m=r[c.i][i.i],h=r[c.i][l],d=r[u][i.i],p=r[u][l],f=m+i.t*(h-m),b=d+i.t*(p-d);return f+c.t*(b-f)}var vo=[0,.05,.1,.2,.3,.4,.5,.6,.7,.8,.9,1],pp={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]},H0=[0,.05,.1,.2,.5,.8,1],z0=[2.2,1.55,1.3,1.12,1,.97,.98];function Y0(e){return Be(H0,z0,e)}var W0=[-20,-10,0,10,25,40,60],j0=[4,2.8,2,1.4,1,.82,.75];function dp(e){return Be(W0,j0,e)}var U0=.5;function fp(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=pp[t]??pp.other,l=e.socAtNom??U0,u=vo.includes(l)?[...vo]:[...vo,l].sort((f,b)=>f-b),m=Be(vo,c,l),h=m>0&&m<1?Math.log(i)/Math.log(m):1,d=[],p=[];for(let f of u){let b=Be(vo,c,f);d.push(o+s*Math.pow(b,h)),p.push(e.constantResistance?a:a*Y0(f))}return{kind:"table",soc:u,ocv:d,r0:p}}function hp(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 ko=25,X0=new WeakMap;function dr(e){let t=X0.get(e);if(t)return t;let r=gc(e);if(r)throw new Error(r);let{cell:n,pack:o}=e,a=n.curve.kind==="table"?n.curve:fp(n.curve,n.chemistry),s=o.series,i=o.parallel,c=s/i,l=a.rTempC,u=a.rGrid,m=i*n.capacityAh,h=s*n.vMin,d=n.iMaxA>0?i*n.iMaxA:1/0,p=n.iMaxChargeA!==void 0&&n.iMaxChargeA>0?n.iMaxChargeA:n.iMaxA/4,f=p>0?i*p:1/0,b=F=>s*Be(a.soc,a.ocv,F),g=(F,C=ko)=>{let w=l&&u?yc(a.soc,l,u,F,C):Be(a.soc,a.r0,F)*dp(C);return c*w+o.busResistance},y=(F,C,w)=>b(F)-C*g(F,w),R=(F,C,w)=>{if(!(F>0))return 0;let T=b(C),S=g(C,w);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,C,w)=>{if(!(F>0))return 0;let T=b(C),S=g(C,w);return S>0?2*F/(T+Math.sqrt(T*T+4*S*F)):F/T},v=F=>{let C=e.thermal;if(!C||C.derateFromC===void 0)return 1;let w=C.derateToC??C.derateFromC;return F<=C.derateFromC?1:!(w>C.derateFromC)||F>=w?0:1-(F-C.derateFromC)/(w-C.derateFromC)},x=(F,C,w=0)=>{let T=b(F),S=g(F,C),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-h)/S):1/0,D=w>0&&Number.isFinite(w)?w:1/0,I=S>0?P(L):1/0,G=Number.isFinite(d)?P(d):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(C??ko);V<1&&(_=Number.isFinite(_)?_*V:_,E="temperature");let N=Number.isFinite(_)?R(_,F,C):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*hp(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:h,currentCeiling:d,chargeCurrentCeiling:f,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 X0.set(e,k),k}function bp(e){return{name:e.name,chemistry:e.chemistry,capacityAh:e.capacityAh,curve:{kind:"analytic",vFull:e.vFull,vNom:e.vNom,vCut:e.vCut,r0:e.r0},iMaxA:e.iMaxA,...e.iMaxChargeA!==void 0?{iMaxChargeA:e.iMaxChargeA}:{},vMin:e.vCut,vMax:e.vFull,...e.massKg!==void 0?{massKg:e.massKg}:{}}}var q0={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},Q0={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},Z0={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 gp(){return{name:"Formula Student accumulator",cell:bp(q0),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 yp(){return{name:"LFP pack",cell:bp(Q0),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 xp(){return{name:"Road car pack",cell:bp(Z0),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 Rp(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 xc(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)=>yc(e.effRpm,e.effTorque,e.effGrid,n,o);return{model:e,maxTorque:t,efficiency:r}}function vp(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=p=>Math.max(0,e.terminalResistanceOhm*(1+.00393*(p-t))),l=p=>n>0&&o>0?n*Math.pow(Math.max(0,p)/o,a):0,u=(p,f,b)=>{let g=r>0?Math.abs(f)/r:0;return 1.5*c(b)*g*g+l(p)},m=(p,f)=>{let b=e.coolingWPerK*(f-e.coolantC)-l(p);return!(b>0)||r<=0?0:r*Math.sqrt(b/(1.5*c(f)))},h=e.coolingWPerK>0?e.heatCapacityJPerK/e.coolingWPerK:1/0,d=Number.isFinite(h)?.25*h:1/0;return{spec:e,startC:e.startC??e.coolantC,lossW:u,step(p,f,b){if(!(b>0)||!(e.heatCapacityJPerK>0))return p;let g=Number.isFinite(d)?Math.max(1,Math.ceil(b/d)):1,y=b/g,R=p;for(let M=0;M<g;M++)R+=(f-e.coolingWPerK*(R-e.coolantC))*y/e.heatCapacityJPerK;return R},continuousTorque:m,derate(p,f,b){if(s===void 0||i===void 0||!(i>s)||!(b>0)||f<=s)return 1;let g=Math.min(1,m(p,i)/b);return f>=i?g:1-(1-g)*(f-s)/(i-s)},equilibriumC(p){return e.coolingWPerK>0?e.coolantC+p/e.coolingWPerK:1/0}}}function Ue(e,t){return t==="rear"&&e.tireRateRear!==void 0?e.tireRateRear:e.tireRate}function kp(e,t){let r=e.tyreFreeRadiusRear;return(t==="rear"&&r!==void 0?r:e.tyreFreeRadius)??0}var Rc=9.81,J0=(e,t)=>e*(t*t)/2*(Math.PI/180)/1e3,Ga=(e,t)=>e+t>0?e*t/(e+t):0,ey=.5;function vc(e,t,r){if(!(r>0))return 1;let n=e*Rc*t*(Math.PI/180)/r;return 1/(1-Math.min(ey,n))}function Mp(e,t,r){return r>0?e*Rc*t/(r*r):0}function ty(e,t,r,n,o){if(!(n>0)||!(o>0))return 1;let a=Mp(e,t,r)*(1/n+1/o);return 1/(1-Math.min(ey,a))}function we(e){let t=4*e.unsprungPerCorner,r=Math.max(0,e.massTotal-t),n=r*e.frontMassFrac,o=r*(1-e.frontMassFrac),a=Ue(e,"front"),s=Ue(e,"rear"),i=e.wheelRateFront+(e.heaveSpringFront??0),c=e.wheelRateRear+(e.heaveSpringRear??0),l=Ga(i,a),u=Ga(c,s),m=(G,O)=>{let W=O/2;return W>0?1/(2*Math.PI)*Math.sqrt(G*1e3/W):0},h=m(l,n),d=m(u,o),p=Ga(e.wheelRateFront+e.arbFront,a),f=Ga(e.wheelRateRear+e.arbRear,s),b=J0(p,e.trackFront),g=J0(f,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*Rc*v,k=vc(r,v,y),F=y>0?x/y*k:0,C=e.massTotal*Rc*e.cgHeight/e.wheelbase,w=2*l,T=2*u,S=ty(r,e.cgHeight,e.wheelbase,w,T),P=(w>0&&T>0?(C/w+C/T)/e.wheelbase*S:0)*(180/Math.PI),L=e.wheelbase*e.wheelbase*Ga(w,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:h,rideFreqRear:d,rollRateFront:b,rollRateRear:g,rollRateTotal:y,rollWheelRateFront:p,rollWheelRateRear:f,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 Kr=["clFront","clRear","cd"],Mo=e=>e.frame?.kind==="pitch";function kc(e){return Mo(e)?{x:e.axes.h,y:e.axes.pitch}:{x:e.axes.hFront,y:e.axes.hRear}}var ry=e=>e.frame?.kind==="pitch";var Mc=45,Qe=e=>typeof e=="number"&&Number.isFinite(e);function Sc(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 ny(e,t){if(t===void 0)return null;for(let r of Kr){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 oy(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 Ka(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=Sc("front ride-height",e.axes?.hFront);if(i)return i;let c=Sc("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=Sc("ride-height",e.axes?.h);if(i)return i;let c=Sc("pitch",e.axes?.pitch,"\xB0","pitch");if(c)return c;let l=e.axes.pitch.find(u=>Math.abs(u)>=Mc);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 Kr){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 ny("yaw",e.attitude?.yaw)??ny("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 Kr){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])>=Mc||Math.abs(i[1])>=Mc))return`A pitch range reaching ${Math.abs(i[0])>=Mc?i[0]:i[1]}\xB0 is not a car's attitude. Pitch is in degrees.`}return oy("yaw",e.attitude?.yaw)??oy("roll",e.attitude?.roll)}return`Unknown aero model kind "${e.kind}".`}var ay=180/Math.PI;function Ac(e,t,r,n){let o=(n-r)/t;return{h:r+e.refX*o,pitch:Math.atan(o)*ay}}function So(e,t,r,n){let o=Math.tan(n/ay);return{hFront:r-e.refX*o,hRear:r+(t-e.refX)*o}}var JV=180/Math.PI,gC=["hFront","hRear"],yC=["h","pitch"],Fp=e=>e?.kind==="pitch"?yC:gC,vt=(e,t)=>e[t],Fc=(e,t)=>e[t],Sp=(e,t)=>({[e[0]]:t(e[0]),[e[1]]:t(e[1])});function xC(e){if(!(!e.yaw&&!e.roll))return{...e.yaw?{yaw:{...e.yaw}}:{},...e.roll?{roll:{...e.roll}}:{}}}function Cp(e){let t=Fp(e.frame),r=e.balanceFront,n=e.cl*r,o=e.cl*(1-r),a=Sp(t,c=>vt(e.dCl,c)*r+e.cl*vt(e.dBalance,c)),s=Sp(t,c=>vt(e.dCl,c)*(1-r)-e.cl*vt(e.dBalance,c)),i=xC(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:Sp(t,c=>vt(e.dCd,c))},range:{[t[0]]:[...Fc(e.range,t[0])],[t[1]]:[...Fc(e.range,t[1])]},provenance:{...e.provenance},...i?{attitude:i}:{}}}function Cc(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 Ap(e,t,r=11){let n=Array.from({length:r},(a,s)=>t.maxDeg*s/(r-1)),o=n.map(a=>Cc(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 sy(e){if(!(!e.attitude?.yaw&&!e.attitude?.roll))return{...e.attitude.yaw?{yaw:Ap(e.at,e.attitude.yaw)}:{},...e.attitude.roll?{roll:Ap(e.at,e.attitude.roll)}:{}}}function iy(e,t,r,n=0,o=0){let[a,s]=Fp(e.frame),i=t-vt(e.ref,a),c=r-vt(e.ref,s),l={clFront:e.at.clFront+vt(e.slope.clFront,a)*i+vt(e.slope.clFront,s)*c,clRear:e.at.clRear+vt(e.slope.clRear,a)*i+vt(e.slope.clRear,s)*c,cd:e.at.cd+vt(e.slope.cd,a)*i+vt(e.slope.cd,s)*c},u=e.attitude?.yaw?Cc(e.at,e.attitude.yaw,n):{clFront:1,clRear:1,cd:1},m=e.attitude?.roll?Cc(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 wp(e){let[t,r]=Fp(e.frame),n=[...Fc(e.range,t)],o=[...Fc(e.range,r)],a=i=>o.map(c=>n.map(l=>i(iy(e,l,c)))),s=sy(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 Tp=180/Math.PI,cy=new WeakMap,ly=new WeakMap,Pp=new WeakMap;function Hr(e,t){let r=ly.get(e);if(r)return r;let n=t?.wheelbase,o=n!==void 0?Pp.get(e)?.get(n):void 0;if(o)return o;let a=RC(e),s=a.map;if(!Mo(s)){let l=vC(e,a);return ly.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=kC(e,a,s.frame,n),c=Pp.get(e);return c||(c=new Map,Pp.set(e,c)),c.set(n,i),i}function RC(e){let t=cy.get(e);if(t)return t;let r=Ka(e);if(r)throw new Error(r);let n=e.kind==="map"?e:wp(e),{x:o,y:a}=kc(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},h=(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}},d=(y,R)=>{if(!u)return m;let M=c?h(c,y):m,v=l?h(l,R):m;return{clFront:M.clFront*v.clFront,clRear:M.clRear*v.clRear,cd:M.cd*v.cd,clamped:M.clamped||v.clamped}},p=(y,R,M=0,v=0)=>{let x=xn(o,y),k=xn(a,R),F=Math.min(x.i+1,s-1),C=Math.min(k.i+1,i-1),w=S=>{let A=S[k.i][x.i],P=S[k.i][F],L=S[C][x.i],D=S[C][F],I=A+x.t*(P-A),G=L+x.t*(D-L);return I+k.t*(G-I)},T=d(M,v);return{clFront:u?w(n.clFront)*T.clFront:w(n.clFront),clRear:u?w(n.clRear)*T.clRear:w(n.clRear),cd:u?w(n.cd)*T.cd:w(n.cd),clampedRide:x.clamped||k.clamped,clampedAttitude:T.clamped}},f={x:[o[0],o[s-1]],y:[a[0],a[i-1]]},b=(y,R,M=!1,v=0,x=0)=>{let k=d(v,x),F=xn(o,M?Math.min(Math.max(y,f.x[0]),f.x[1]):y),C=xn(a,M?Math.min(Math.max(R,f.y[0]),f.y[1]):R),w=Math.min(F.i+1,s-1),T=Math.min(C.i+1,i-1),S=w>F.i?o[w]-o[F.i]:0,A=T>C.i?a[T]-a[C.i]:0,P={};for(let L of Kr){let D=n[L],I=D[C.i][F.i],G=D[C.i][w],O=D[T][F.i],W=D[T][w],E=F.clamped||S===0?0:((G-I)*(1-C.t)+(W-O)*C.t)/S,_=C.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:f.x,y:f.y,hasAttitude:u,factors:d,at:p,slopes:b};return cy.set(e,g),g}function vC(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 Kr)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 kC(e,t,r,n){let o=r.refX,a=o/n,s=(l,u,m=0,h=0)=>{let d=(u-l)/n;return t.at(l+o*d,Math.atan(d)*Tp,m,h)},i=(l,u,m=!1,h=0,d=0)=>{let p=(u-l)/n,f=t.slopes(l+o*p,Math.atan(p)*Tp,m,h,d),b=Tp/(n*(1+p*p)),g={};for(let y of Kr)g[y]={hFront:f[y].x*(1-a)-f[y].y*b,hRear:f[y].x*a+f[y].y*b};return g},c={frame:r,x:t.x,y:t.y,at:t.at,toAxles:(l,u)=>So(r,n,l,u),fromAxles:(l,u)=>{let m=Ac(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 Lp(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,uy={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."},my={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."},py={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."},dy={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."},fy={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."},hy={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."},by={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."},gy={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 fr(e){return Cp({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 Dp=()=>fr(uy),Ep=()=>fr(my),Ip=()=>fr(py),_p=()=>fr(dy),Np=()=>fr(fy),Op=()=>fr(hy),Vp=()=>fr(by),Bp=()=>fr(gy);function Ao(e,t){let r=.5*e.rho*e.area*t*t,n=e.cl*r,o=e.cw*r,a=n*e.copLongFront;return{downforce:n,drag:o,downFront:a,downRear:n-a}}function wc(e,t){let r=e.massTotal;if(!(r>0))return{front:0,rear:0};let n=Math.max(0,Math.min(1,e.frontMassFrac)),o=2*e.unsprungPerCorner,a=(s,i)=>i>0?Math.min(1,s/i):0;return{front:(t.sprungMass*n+o*a(t.rideRateFront,Ue(e,"front")))/r,rear:(t.sprungMass*(1-n)+o*a(t.rideRateRear,Ue(e,"rear")))/r}}function Tc(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 $p(e,t){return e.wheelbase>0?e.massTotal*t*9.81/e.wheelbase:0}function Fo(e,t,r){let n=2*t.rideRateFront,o=2*t.rideRateRear;return!(n>0)||!(o>0)?0:Math.min(Mp(t.sprungMass,r,e.wheelbase),.5*n*o/(n+o))}function Pc(e,t,r,n,o){let a=e.cgHeight,s=$p(e,r);if(n===0&&o===0&&s===0)return{height:a,forward:0,noseLoad:0,dropFront:0,dropRear:0};let i=wc(e,t),c=2*t.rideRateFront,l=2*t.rideRateRear,u=a,m=0,h=0,d=0;for(let f=0;f<6;f++){d=Fo(e,t,u);let b=n-s*u,g=o+s*u;if(d>0){let M=c*l-d*(c+l);m=(b*(l-d)-d*g)/M,h=(g*(c-d)-d*b)/M}else m=c>0?b/c:0,h=l>0?g/l:0;let y=Tc(a,i,m,h),R=Math.abs(y-u);if(u=y,R<1e-9)break}let p=m-h;return{height:u,forward:e.wheelbase>0?u*p/e.wheelbase:0,noseLoad:d*p,dropFront:m,dropRear:h}}var Gp={yawDeg:0,rollDeg:0},yy=1e-4,MC=40,xy=50;function Co(e,t,r=0){let n=e.aero?.model;if(!(!n||!Hr(n,e).hasAttitude))return{yawDeg:r,rollDeg:we(e).rollGradient*t}}function Kp(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 So(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=ry(r)?n(r.frame,r.ref.h,r.ref.pitch):r.ref;else if(r){let{x:a,y:s}=kc(r),i=(a[0]+a[a.length-1])/2,c=(s[0]+s[s.length-1])/2;o=Mo(r)?n(r.frame,i,c):{hFront:i,hRear:c}}return{hFront:e.rideHeightFront??o.hFront,hRear:e.rideHeightRear??o.hRear}}var Ry=new WeakMap;function zr(e,t,r=0,n){let o=e.aero;if(!o?.model)return null;let a=Ry.get(e);a||(a=new Map,Ry.set(e,a));let s=n&&Hr(o.model,e).hasAttitude?n:Gp,i=s===Gp?`${t}|${r}`:`${t}|${r}|${s.yawDeg.toFixed(3)}|${s.rollDeg.toFixed(3)}`,c=a.get(i);if(c)return c;let l=SC(e,o,t,r,s);return a.size>4096&&a.clear(),a.set(i,l),l}function SC(e,t,r,n,o){let a=Hr(t.model,e),s=we(e),i=2*s.rideRateFront,c=2*s.rideRateRear,l=Kp(t,e.wheelbase),u=.5*t.rho*r*r,m=a.area,h=e.wheelbase>0?t.copHeight/e.wheelbase:0,d=wc(e,s),p=$p(e,n),f=(w,T)=>Tc(e.cgHeight,d,l.hFront-w,l.hRear-T),b=(w,T)=>l.hFront-w-(l.hRear-T),g=(w,T)=>{let S=a.at(w,T,o.yawDeg,o.rollDeg),A=u*m*S.clFront,P=u*m*S.clRear,L=u*m*S.cd,D=L*h,I=f(w,T),G=p*I,O=Fo(e,s,I)*b(w,T),W=A-G-D+O,E=P+G+D-O,_=w-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=(w,T,S=!1)=>{let A=a.slopes(w,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-h*A.cd.hFront),P*(A.clFront.hRear-h*A.cd.hRear)],[L*(A.clRear.hFront+h*A.cd.hFront),L*(A.clRear.hRear+h*A.cd.hRear)]]},R=l.hFront,M=l.hRear,v=g(R,M),x=0;for(;v.norm>=yy&&x<MC;){x++;let w=y(R,M),T=i>0?p/i:0,S=c>0?p/c:0,A=Fo(e,s,f(R,M)),P=i>0?A/i:0,L=c>0?A/c:0,D=1+w[0][0]-T*d.front-P,I=w[0][1]-T*d.rear+P,G=w[1][0]+S*d.front+L,O=1+w[1][1]+S*d.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)/xy,Math.abs(_)/xy);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],C=(1+k[0][0])*(1+k[1][1])-k[0][1]*k[1][0];return{v:r,axG:n,hFront:R,hRear:M,cgHeight:f(R,M),cgForward:e.wheelbase>0?f(R,M)*b(R,M)/e.wheelbase:0,cgNoseLoad:Fo(e,s,f(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:AC(k),stable:C>0&&F>0,converged:v.norm<yy,iterations:x,clampedRide:v.c.clampedRide,yawDeg:o.yawDeg,rollDeg:o.rollDeg,clampedAttitude:v.c.clampedAttitude}}function AC(e){let t=e[0][0]+e[1][1],r=e[0][0]*e[1][1]-e[0][1]*e[1][0],n=t*t-4*r;if(n>=0){let o=Math.sqrt(n);return Math.max(Math.abs((t+o)/2),Math.abs((t-o)/2))}return Math.sqrt(r)}function Ha(e,t,r=0,n){let o=zr(e,t,r,n);return o?{downforce:o.downforce,drag:o.drag,downFront:o.downFront,downRear:o.downRear}:e.aero?Ao(e.aero,t):{downforce:0,drag:0,downFront:0,downRear:0}}function Lc(e,t=0,r=0,n,o){if(e.aero&&t>0){if(e.aero.model){let i=zr(e,t,r,n);return{height:i.cgHeight,forward:i.cgForward,noseLoad:i.cgNoseLoad}}let a=Ao(e.aero,t),s=e.wheelbase>0?a.drag*e.aero.copHeight/e.wheelbase:0;return Pc(e,o??we(e),r,a.downFront-s,a.downRear+s)}return r===0?{height:e.cgHeight,forward:0,noseLoad:0}:Pc(e,o??we(e),r,0,0)}var vy=[0,1,0],Hp=[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],zp=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]],FC=e=>X(e,e),Yr=e=>Math.sqrt(X(e,e)),za=(e,t)=>FC(H(e,t)),ve=(e,t)=>Yr(H(e,t)),q=e=>{let t=Yr(e);return t<1e-12?[0,0,0]:[e[0]/t,e[1]/t,e[2]/t]};var Wr=(e,t,r)=>{let n=q(r),o=H(e,t);return ee(t,U(n,X(o,n)))},ky=(e,t,r)=>ve(e,Wr(e,t,r));var wC=1e-6;function TC(e){if(e<wC){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]=TC(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 Sy(n,o,r,new Array(r).fill(0))}function My(e,t,r){return Sy(e,t,t.length,r)}function Sy(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 h=s;h<r;h++)e[u][h]-=m*e[s][h];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 Ay=e=>{let t=0;for(let r of e)t=Math.max(t,Math.abs(r));return t},Fy=e=>{let t=0;for(let r of e)t+=r*r;return t},PC=Math.sqrt(Number.EPSILON);function Cy(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=Ay(c),u=Fy(c),m=.001,h=1,d=c.length,p=Array.from({length:d},()=>new Array(a).fill(0)),f=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:h};for(let w=0;w<a;w++){let T=PC*Math.max(Math.abs(i[w]),s[w]);for(let A=0;A<a;A++)M[A]=i[A];M[w]+=T;let S=e(M);for(let A=0;A<d;A++)p[A][w]=(S[A]-c[A])/T}let k=0;for(let w=0;w<a;w++){for(let S=0;S<a;S++){let A=0;for(let P=0;P<d;P++)A+=p[P][w]*p[P][S];f[w][S]=A}let T=0;for(let S=0;S<d;S++)T+=p[S][w]*c[S];g[w]=T,k=Math.max(k,f[w][w])}let F=Math.max(k,1e-9),C=!1;for(let w=0;w<18;w++){let T=m*F;for(let A=0;A<a;A++){let P=f[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=My(b,y,R);if(h=Math.max(h,S.condProxy),!S.singular){for(let L=0;L<a;L++)v[L]=i[L]+R[L];let A=e(v),P=Fy(A);if(P<u){for(let L=0;L<a;L++)i[L]=v[L];c=A,u=P,l=Ay(c),m=Math.max(m*.3,1e-12),C=!0;break}}m=Math.min(m*4,1e12)}if(!C)break}return{x:i,residualNorm:l,iterations:n,converged:l<o,condProxy:h}}function Ya(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 Yp(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 wy=e=>[e[0],-e[1],-e[2],-e[3]];function Ty(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 Py(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 Ly(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 Wp(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],h=n+i+m;if(h>=n&&h>=i&&h>=m){let f=Math.sqrt(1+h),b=.5/f;return[.5*f,(c-u)*b,(l-a)*b,(o-s)*b]}if(n>=i&&n>=m){let f=Math.sqrt(1+n-i-m),b=.5/f;return[(c-u)*b,.5*f,(s+o)*b,(l+a)*b]}if(i>=m){let f=Math.sqrt(1-n+i-m),b=.5/f;return[(l-a)*b,(s+o)*b,.5*f,(u+c)*b]}let d=Math.sqrt(1-n-i+m),p=.5/d;return[(o-s)*p,(l+a)*p,(u+c)*p,.5*d]}function Dy(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 Ey(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 LC(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 DC(e){let t=e.hardpoints,r=q(H(t.damperChassis,t.pushrodOuter)),[n,o]=LC(r);return{top:t.damperChassis,lower0:t.pushrodOuter,axis0:r,e1:n,e2:o}}function jp(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=za(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:DC(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 Up(e,t){return ee(e.lcaFront,Et(e.lbjRel0,e.lcaDir,t))}function wo(e,t){return e.steerMovesRack?ee(e.tieInner0,U(e.rackAxis,t)):e.tieInner0}function Xp(e,t,r,n){let o=It(e,t,e.lbj0),a=Up(e,r),s=o[0]-a[0],i=o[1]-a[1],c=o[2]-a[2],l,u;if(e.strut){let p=e.strut,f=[t[3],t[4],t[5]],b=H(p.top,It(e,t,p.lower0));l=X(b,nt(f,p.e1)),u=X(b,nt(f,p.e2))}else{let p=It(e,t,e.ubj0),f=H(p,e.ucaFront),b=X(f,e.ucaDir),g=H(f,U(e.ucaDir,b));l=b-e.ubjAxial0,u=(X(g,g)-e.ubjRadius2)/e.ubjRadiusRef}let m=It(e,t,e.tro0),h=wo(e,n),d=(za(m,h)-e.tieLen2)/e.tieLenRef;return[s,i,c,l,u,d]}var Wa=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]),Dc=e=>{let t=Wa(e);return[e[0]/t,e[1]/t,e[2]/t]},EC=(e,t)=>H(e,U(t,X(e,t))),qp=e=>Dc(ae(e,Math.abs(e[0])<.6?[1,0,0]:[0,1,0]));function IC(e,t){let r=e.ucaDir,n=ee(e.ucaFront,U(r,e.ubjAxial0)),o=Math.sqrt(e.ubjRadius2),a=EC(H(e.ubj0,e.ucaFront),r),s=Wa(a)>1e-9?Dc(a):qp(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),h=Ya(2*o*X(s,u),2*o*X(i,u),l-m-o*o,2*o*Math.sqrt(m));if(h.free)return"free";let d=Dc(c),p=(f,b)=>{let g=ee(n,ee(U(s,o*f),U(i,o*b))),y=Dc(H(g,t));return{q1:Py(d,y),k:y,margin:h.margin,ok:h.ok}};return h.margin>0?[p(h.c1,h.s1),p(h.c2,h.s2)]:[p(h.c1,h.s1)]}function _C(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=Wa(a),i=s>1e-9?U(a,1/s):qp(n),c=H(t.top,r),l=Wa(c);if(!(l>1e-9))return"free";let u=U(c,1/l),m=s/l,h=1-m,d=h>=0?Math.sqrt((1-m)*(1+m)):0,p=qp(u),f=b=>{let g=b*d,y=ee(U(u,g),U(p,Math.min(m,1))),R=H(U(u,Math.min(m,1)),U(p,g));return{q1:Yp(Wp(R,y,ae(R,y)),wy(Wp(i,n,ae(i,n)))),k:u,margin:h,ok:h>=0}};return h>0?[f(1),f(-1)]:[f(1)]}function NC(e,t,r,n){let{k:o}=n,a=Ty(n.q1,H(e.tro0,e.lbj0)),s=X(a,o),i=H(a,U(o,s)),c=Wa(i);if(!(c>1e-9))return"free";let l=U(i,1/c),u=ae(o,l),m=ee(t,U(o,s)),h=H(m,r),d=X(h,h),p=Ya(2*c*X(h,l),2*c*X(h,u),e.tieLen2-d-c*c,2*c*Math.sqrt(d));if(p.free)return"free";let f=(g,y)=>({q:Yp(Ly(o,g,y),n.q1)});return{roots:p.margin>0?[f(p.c1,p.s1),f(p.c2,p.s2)]:[f(p.c1,p.s1)],margin:p.margin,ok:p.ok}}function Iy(e,t,r,n=[0,0,0,0,0,0]){let o=Up(e,t),a=wo(e,r),s=Dy([n[3],n[4],n[5]]),i=f=>Math.abs(f[0]*s[0]+f[1]*s[1]+f[2]*s[2]+f[3]*s[3]),c=e.strut?_C(e,e.strut,o):IC(e,o);if(c==="free")return{x:n.slice(),converged:!1,margin:0,free:!0};let l=null,u=null;for(let f of c){let b=NC(e,o,a,f);if(b==="free")return{x:n.slice(),converged:!1,margin:0,free:!0};let g=Math.min(f.margin,b.margin),y=b.ok&&f.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:h}=l??u,d=Ey(m),p=H(H(o,e.c0),nt(d,H(e.lbj0,e.c0)));return{x:[p[0],p[1],p[2],d[0],d[1],d[2]],converged:l!==null,margin:h,free:!1}}function Ny(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:za(e.pushrodOuter,e.rockerToPushrod),damperLen0:ve(e.rockerToDamper,e.damperChassis)}}var OC=(e,t)=>ee(e.pivotA,Et(e.rprRel0,e.axis,t)),Qp=(e,t)=>ee(e.pivotA,Et(e.rdmRel0,e.axis,t));function ja(e,t){return{pushrod:OC(e,t),damper:Qp(e,t)}}function Oy(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=Ya(2*X(s,o),2*X(s,a),e.rodLen2-c-i,2*Math.sqrt(i*c));if(l.free){let d=Math.abs(e.rodLen2-c-i)<=1e-9*e.rodLen2;return{phi:r,damperLength:ve(Qp(e,r),e.damperChassis),converged:d,margin:0}}let u=_y(Math.atan2(l.s1,l.c1),r),m=_y(Math.atan2(l.s2,l.c2),r),h=Math.abs(m-r)<Math.abs(u-r)?m:u;return{phi:h,damperLength:ve(Qp(e,h),e.damperChassis),converged:l.ok,margin:l.margin}}function _y(e,t){let r=2*Math.PI;return e+r*Math.round((t-e)/r)}function Vy(e,t,r,n){return ee(t,nt(U(q(r),n),H(e,t)))}function By(e,t,r,n){let o=q(n),a=h=>{let d=H(h,r);return H(d,U(o,X(d,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 $y(e,t,r,n){return ee(t,nt(U(q(r),n),H(e,t)))}var Ec=180/Math.PI,VC=(e,t,r)=>Math.max(t,Math.min(r,e)),Gy=[NaN,NaN,NaN];function Ua(e){let t=q(e.spinAxis),r=q(H(e.uprightUpper,e.uprightLower)),n=-Math.asin(VC(t[2],-1,1))*Ec,o=Math.atan2(t[0],t[1])*Ec,a=Math.atan2(-r[0],r[2])*Ec,s=Math.atan2(-r[1],r[2])*Ec,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,h=C=>ee(u,U(r,(C-u[2])/r[2])),d=m?h(l[2]):Gy,p=m?h(e.wheelCenter[2]):Gy,f=l[1]-d[1],b=d[0]-l[0],g=q(ae(t,[0,0,1])),y=ae([0,0,1],g),R=H(l,d),M=X(R,y),v=-X(R,g),x=e.wheelCenter[1]-p[1],k=p[0]-e.wheelCenter[0],F=ky(e.tieOuter,u,r);return{camber:n,toe:o,caster:a,kpi:s,scrubRadius:f,mechanicalTrail:b,scrubAtWheel:M,trailAtWheel:v,kingpinOffset:x,casterOffset:k,steeringArm:F,contactPatch:l,kingpinGround:d,kingpinAtHub:p}}function et(e){return{corner:e,inv:jp(e),rocker:Ny(e.hardpoints)}}var BC=[20,20,20,.2,.2,.2];function Hy(e,t,r,n=[0,0,0,0,0,0]){let o=Iy(e,t,r,n);if(!o.free)return o;let a=$C(e,t,r,n);return{x:a.x,converged:a.converged,margin:0}}function $C(e,t,r,n=[0,0,0,0,0,0]){return Cy(o=>Xp(e,o,t,r),n,{scales:BC,tol:1e-10,maxIter:40})}var GC=.01,Ic=1.2,mt=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 Ky(s,t,!1);let c=(Ee(e,.02,r,Zp(s),o).travel-s.travel)/.02;(!Number.isFinite(c)||Math.abs(c)<1e-6)&&(c=1);let l=h=>Math.max(-Ic,Math.min(Ic,h)),u=l((t-s.travel)/c),m=Ee(e,u,r,Zp(s),o);for(let h=0;h<12&&!(Math.abs(m.travel-t)<1e-4);h++){let d=m.travel-s.travel,p=Math.abs(d)<1e-9?u:u-(m.travel-t)*((u-a)/d);a=u,s=m,u=l(p),m=Ee(e,u,r,Zp(s),o)}return Ky(m,t,Math.abs(u)===Ic)}function Ky(e,t,r){let n=e.travel-t,o=Math.abs(n)<=GC,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 Zp(e){return{q:[e.pose.t[0],e.pose.t[1],e.pose.t[2],e.pose.omega[0],e.pose.omega[1],e.pose.omega[2]],phi:e.points.rockerAngle}}function KC(e,t,r,n,o){switch(e){case"upright":return It(t,r,o.pushrodOuter);case"upperArm":{let a=It(t,r,t.ubj0),s=By(t.ubj0,a,t.ucaFront,t.ucaDir);return $y(o.pushrodOuter,t.ucaFront,t.ucaDir,s)}default:return Vy(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=Hy(a,t,r,i),l=c.x,u=[l[3],l[4],l[5]],m={t:[l[0],l[1],l[2]],omega:u},h=s.hardpoints,d=s.config,p=a.strut,f=p?p.top:It(a,l,h.uprightUpper),b=It(a,l,h.uprightLower),g=It(a,l,h.tieOuter),y=It(a,l,h.wheelCenter),R=q(nt(u,d.spinAxis)),M=KC(p?"upright":d.pushrodAttach,a,l,t,h),v=p?p.top:h.damperChassis,x=p||d.actuation==="direct"?{phi:0,damperLength:ve(M,v),converged:!0,margin:1}:Oy(e.rocker,M,n?.phi??0),k=Ua({uprightUpper:f,uprightLower:b,wheelCenter:y,spinAxis:R,tieOuter:g,loadedRadius:o?.loadedRadius??d.loadedRadius,patchShift:o?.patchShift});return{pose:m,beta:t,travel:l[2],steer:r,points:{uprightUpper:f,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 To=e=>e==="FL"||e==="FR"?"front":"rear",Yy=e=>e==="FL"||e==="RL"?"left":"right";function $e(e,t){return e.corners?.[t]??HC(e[To(t)],Yy(t))}function Wy(e){let t=e.config.springSplit;return e.config.actuation==="decoupled"||t===void 0||!Number.isFinite(t)||Math.abs(t)>=1?0:t}var zy=new WeakMap;function HC(e,t){let r=Wy(e);if(r===0)return e;let n=zy.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)},zy.set(e,n)}return n[t]}var Po=["FL","FR","RL","RR"],pt=e=>2*e.hardpoints.wheelCenter[1],jr=(e,t)=>t?pt($e(e,"FL"))/2+pt($e(e,"FR"))/2:pt($e(e,"RL"))/2+pt($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 Rn(e,t){return[e[0],t.sideSign*e[1],e[2]]}function Lo(e){return e.frontAxleX-e.wheelbase/2}function Jp(e,t,r){return t[2]+e.heave+(t[0]-r)*Math.sin(e.pitch)-t[1]*Math.sin(e.roll)}function Ur(e,t,r,n){let o=Ze(e,t),a=(n?jr(n,o.isFront):o.isFront?t.trackFront:t.trackRear)/2,s=o.sideSign*a,i=o.axleX-Lo(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 zC={travelMin:-40,travelMax:40,steps:41,steer:0};function Xa(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={...zC,...t},n=et(e);return Do(n,r)}function Do(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:Xa(m),converged:m.converged});let h=Xa(m);for(let R=1;R<=l;R++){let M=c*R/l,v=Ee(e,M,r,h);h=Xa(v),u.push({beta:M,travel:v.travel,warm:h,converged:v.converged})}h=Xa(m);for(let R=1;R<=l;R++){let M=-c*R/l,v=Ee(e,M,r,h);h=Xa(v),u.push({beta:M,travel:v.travel,warm:h,converged:v.converged})}u.sort((R,M)=>R.beta-M.beta);let d=u[u.length-1].travel>=u[0].travel,p=!1;for(let R=1;R<u.length;R++){let M=u[R].travel-u[R-1].travel;(d&&M<-1e-6||!d&&M>1e-6)&&(p=!0)}let f=u.filter(R=>R.converged).map(R=>R.travel),b=f.length?[Math.min(...f),Math.max(...f)]:[0,0],g=f.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=YC(u,M,d),x=WC(u,v);y.push(Ee(e,v,r,x))}return jC(y,e.corner.config.actuation==="decoupled"?0:e.corner.config.springRate),{samples:y,covered:g,reach:b,fold:p,unconverged:y.filter(R=>!R.converged).length}}function YC(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 WC(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 ed(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 jC(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=ed(n,r,s),c=ed(o,r,s),l=-ed(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 _c=e=>e!==void 0&&Number.isFinite(e)&&e>0;function UC(e){return e&&_c(e.helperRate)&&_c(e.helperTravel)?{rate:e.helperRate,travel:e.helperTravel}:null}function td(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=UC(n),a=-td(e,t,o),s=Eo(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 Eo(e,t){if(!Number.isFinite(e))return{droop:null,bump:null};let r=_c(t?.extended)&&t.extended>e?t.extended:null,n=r!==null&&_c(t?.stroke)?r-t.stroke:null;return{droop:r!==null?e-r:null,bump:n!==null&&n<e?e-n:null}}function rd(e,t){if(!(e>0)||!Number.isFinite(e))return null;let r=Eo(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 XC(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=td(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 qC(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=td(r,n,o)+t;return a<=0?0:a>=o.rate*o.travel/r+o.travel?r:r*o.rate/(r+o.rate)}function Io(e,t){let r=XC(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 nd(e,t){let r=qC(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 od(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 Nc={min:-60,max:60,steps:61},ad=e=>({travel:[e.min,e.max],force:[0,0],motionRatio:[0,0],spring:null}),jy=new WeakMap;function QC(e,t){let r=jy.get(e.corner);r||jy.set(e.corner,r=new Map);let n=`${t.min}|${t.max}|${t.steps}`,o=r.get(n);return o||r.set(n,o=Do(e,{travelMin:t.min,travelMax:t.max,steps:t.steps,steer:0})),o}function Qa(e,t,r=Nc,n=e.corner.config.coilover){let o=e.corner.config;if(o.actuation==="decoupled")return ad(r);let a=QC(e,r),s=JC(e,o.springRate,a.samples),i=[];for(let f of a.samples){let b=f.metrics.motionRatio;!f.converged||b===void 0||!Number.isFinite(b)||!Number.isFinite(f.metrics.damperLength)||i.length>0&&f.travel<=i[i.length-1].t+1e-6||i.push({t:f.travel,L:f.metrics.damperLength,mr:b})}if(i.length<2)return ad(r);let c=tw(i,0);if(!(Math.abs(c.mr)>1e-6))return ad(r);let l=t/c.mr,u=qa(s,l,c.L,n),m=u?ZC(i,od(u).map(f=>c.L-f)):i,h=m.map(f=>(u?Io(u,c.L-f.L):l+s*(c.L-f.L))*f.mr-t),d=f=>f===null?null:m.find(b=>b.L===c.L-f)?.t??null,p=u?od(u).map(d).filter(f=>f!==null):[];return{travel:m.map(f=>f.t),force:h,motionRatio:m.map(f=>f.mr),spring:{rate:s,preload:l,length0:c.L,law:u},...u?{stops:{droop:d(u.droop),bump:d(u.bump)}}:{},...p.length?{kinks:p}:{}}}function ZC(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 JC(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:ew(e,n,r);return!(o>0)||!Number.isFinite(o)?t:t*o/(t+o)}function ew(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=ja(e.rocker,n.points.rockerAngle),s=q(H(o.rockerPivotB,o.rockerPivotA)),i=(m,h)=>Math.abs(X(s,ae(H(m,o.rockerPivotA),q(H(h,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 sd(e,t){let r=e.travel.length;if(r===0)return 0;if(r===1)return e.motionRatio[0];let n=br(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 hr(e,t,r){if(!e.spring)return Kt(e,t);let{rate:n,preload:o,length0:a,law:s}=e.spring,i=sd(e,0),c=a-r;return(s?Io(s,c):o+n*c)*sd(e,t)-o*i}function tw(e,t){let r=br(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 br(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=br(e.travel,t),o=(t-e.travel[n])/(e.travel[n+1]-e.travel[n]);return e.force[n]+o*(e.force[n+1]-e.force[n])}function _o(e,t){let r=e.travel.length;if(r<3)return Za(e,t);let n=br(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 Za(e,t){if(e.travel.length<2)return 0;let n=br(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 Xr(e,t,r){return e.config.actuation==="decoupled"&&t.attach==="rocker"&&r==="coil"}function id(e,t,r){return Xr(e,t,r)?[t.inner[0],-t.inner[1],t.inner[2]]:t.inner}function No(e,t,r){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return cd(e,t,r.kind,qe(e,{travelMin:n,travelMax:o,steps:a}).samples)}function cd(e,t,r,n){let o=q(H(t.outer,id(e,t,r))),a=[],s=[],i=t.outer;for(let d of n)a.push(d.travel),s.push(X(H(Pe(e,t,d),i),o));let c=a.length,l=new Array(c).fill(0);for(let d=0;d<c;d++){let p=Math.max(0,d-1),f=Math.min(c-1,d+1),b=a[f]-a[p];l[d]=b!==0?(s[f]-s[p])/b:0}let u=l[0];for(let d=1;d<c;d++)if(a[d]>=0){let p=a[d]-a[d-1],f=p!==0?(0-a[d-1])/p:0;u=l[d-1]+f*(l[d]-l[d-1]);break}let m=l.filter(d=>Math.abs(d)>1e-9).map(Math.sign),h=m.length>0&&m.some(d=>d!==m[0]);return{travel:a,ratio:l,linkTravel:s,atDesign:u,reverses:h}}function ld(e,t){let{travel:r,ratio:n}=e,o=r.length;if(o===0)return 0;if(t<=r[0])return n[0];if(t>=r[o-1])return n[o-1];let a=0,s=o-1;for(;s-a>1;){let c=a+s>>1;r[c]<=t?a=c:s=c}let i=(t-r[a])/(r[s]-r[a]);return n[a]+i*(n[s]-n[a])}function ud(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 Ja=e=>e.mount??{kind:"rockerToRocker"},Qy=e=>[e[0],0,e[2]],rw=e=>2*Math.abs(e[1]),nw=(e,t)=>Math.hypot(e[0]-t[0],e[2]-t[2]);function Vc(e,t){return t.kind==="chassis"?nw(e,t.anchor):rw(e)}function es(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 vn(e,t,r={}){let n=r.travelMin??-40,o=r.travelMax??40,a=r.steps??21;return md(e,t,qe(e,{travelMin:n,travelMax:o,steps:a}).samples)}function md(e,t,r){let n=Ja(t),o=p=>Pe(e,{...t,inner:t.outer},r[p]),a=[],s=[],i=[];for(let p=0;p<r.length;p++)a.push(r[p].travel),i.push(Vc(o(p),n));let c=Xy(a,i,0);for(let p of i)s.push(c-p);let l=a.length,u=new Array(l).fill(0);for(let p=0;p<l;p++){let f=Math.max(0,p-1),b=Math.min(l-1,p+1),g=a[b]-a[f];u[p]=g!==0?(s[b]-s[f])/g:0}let m=Uy(a,20),h=Uy(a,-20),d=es(o(m),o(h),n);return{travel:a,ratio:u,springTravel:s,atDesign:Xy(a,u,0),installedLength:c,rollSensitivity:c-d}}function Uy(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 Xy(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 pd(e,t,r){let n={outer:t.outer,attach:t.attach},o=qe(e,{travelMin:-5,travelMax:5,steps:3}),a=p=>Qy(Pe(e,{...n,inner:n.outer},o.samples[p])),s=a(1),i=a(2),c=a(0),l=i[0]-c[0],u=i[2]-c[2],m=Math.hypot(l,u),h=m>1e-9?[l/m,u/m]:[0,1],d=r??Math.max(80,2*Math.abs(t.outer[1])*.5);return[s[0]+h[0]*d,0,s[2]+h[1]*d]}function dd(e,t){let r=e.hardpoints,n=r.rockerPivotA,o=qy(Oc(r.rockerPivotB,r.rockerPivotA)),a=Math.max(30,.6*Zy(Oc(r.rockerToDamper,n))),s=Oc(r.rockerToDamper,n),i=qy(Oc(s,ow(o,aw(s,o)))),c=sw(o,i),l=null,u=-1/0;for(let m=0;m<360;m+=10){let h=m*Math.PI/180,p={outer:[n[0]+a*(Math.cos(h)*i[0]+Math.sin(h)*c[0]),n[1]+a*(Math.cos(h)*i[1]+Math.sin(h)*c[1]),n[2]+a*(Math.cos(h)*i[2]+Math.sin(h)*c[2])],attach:"rocker"},f=t==="chassis"?{...p,mount:{kind:"chassis",anchor:pd(e,p)}}:p,b;try{b=vn(e,f,{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=f)}return l??{outer:r.rockerToDamper,attach:"rocker"}}var Oc=(e,t)=>[e[0]-t[0],e[1]-t[1],e[2]-t[2]],ow=(e,t)=>[e[0]*t,e[1]*t,e[2]*t],aw=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2],Zy=e=>Math.hypot(e[0],e[1],e[2]),qy=e=>{let t=Zy(e)||1;return[e[0]/t,e[1]/t,e[2]/t]},sw=(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 fd=.001,iw=e=>({outer:e.outer,inner:e.outer,attach:e.attach}),sx=(e,t,r)=>(Vc(e.at0,t)-Vc(r,t))/2,cw=(e,t)=>X(H(t,e.pickup.at0),e.axis);function hd(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 Jy(e,t){let r=[0,1,2].map(n=>hd(e,t.map(o=>o[n])));return t.map((n,o)=>[r[0][o],r[1][o],r[2][o]])}function bd(e){return{travel:e,heave:e.map(t=>t/2),heaveRatio:e.map(()=>.5),roll:[...e],rollRatio:e.map(()=>1)}}function ex(e,t,r,n){let o=e.corner;if(!t.heave&&!t.roll)return{side:bd([n.min,n.max]),pickups:{}};let a=ot(ge(e,0,0)),s={};if(t.heave&&r){let f=iw(t.heave);s.heave={corner:o,link:f,at0:Pe(o,f,a)}}if(t.roll){let f=t.roll;s.roll={pickup:{corner:o,link:f,at0:Pe(o,f,a)},axis:q(H(f.outer,id(o,f,t.rollKind??"coil")))}}let i=t.roll&&Xr(o,t.roll,t.rollKind??"coil")?{near:t.roll,far:{...t.roll,outer:t.roll.inner}}:null,c=Do(e,{travelMin:n.min,travelMax:n.max,steps:n.steps,steer:0}),l=[],u=[],m=[],h=[],d=[];for(let f of c.samples)!f.converged||l.length>0&&f.travel<=l[l.length-1]+1e-6||(l.push(f.travel),u.push(s.heave&&r?sx(s.heave,r,Pe(o,s.heave.link,f)):f.travel/2),m.push(s.roll?cw(s.roll,Pe(o,s.roll.pickup.link,f)):f.travel),i&&(h.push(Pe(o,i.near,f)),d.push(Pe(o,i.far,f))));if(l.length<2)return{side:bd([n.min,n.max]),pickups:{}};let p={travel:l,heave:u,heaveRatio:hd(l,u),roll:m,rollRatio:hd(l,m)};return i&&(p.eyes={near:h,nearRatio:Jy(l,h),far:d,farRatio:Jy(l,d)}),{side:p,pickups:s}}function Bc(e,t,r){let n=br(e,r);return t[n]+(r-e[n])/(e[n+1]-e[n])*(t[n+1]-t[n])}function tx(e,t,r){let n=br(e,r);return(t[n+1]-t[n])/(e[n+1]-e[n])}function He(e,t){return{h:Bc(e.travel,e.heave,t),dh:Bc(e.travel,e.heaveRatio,t),ddh:tx(e.travel,e.heaveRatio,t),r:Bc(e.travel,e.roll,t),dr:Bc(e.travel,e.rollRatio,t),ddr:tx(e.travel,e.rollRatio,t)}}function rx(e,t,r,n){let o=br(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 gd=(e,t)=>Math.hypot(e[0]-t[0],e[1]+t[1],e[2]-t[2]);function ix(e,t){let r=e.side[0].eyes,n=e.side[1].eyes;if(!r||!n)return null;let o=rx(e.side[0].travel,r.near,r.nearRatio,t[0]),a=rx(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]],h=X(c,l),d=X(c,u),p=(X(l,u)-h*d)/i;return{L:i,dL:[h,d],ddL:[[(X(l,l)-h*h)/i+X(c,o.dd),p],[p,(X(u,u)-d*d)/i+X(c,m)]]}}var cx=(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,lw=(e,t)=>e.bump!==null&&t>e.bump||e.droop!==null&&t<e.droop?e.rate:0;function ts(e,t,r,n,o=0){let a=e.rollStop;if(!a)return r;let s=ix(e,t);if(!s)return r;let i=cx(a,a.length0-(n??s.L+o));return i===0?r:[r[0]-i*s.dL[0],r[1]-i*s.dL[1]]}function $c(e,t){let r=bd(e.travel);return t==="heave"?{...e,heave:r.heave,heaveRatio:r.heaveRatio}:{...e,roll:r.roll,rollRatio:r.rollRatio}}var Gc=(e,t)=>e?e.law?Io(e.law,t):e.preload+e.rate*t:0,nx=(e,t)=>e?e.law?nd(e.law,t):e.rate:0;function rs(e,t,r,n,o){let a=Gc(e.heave,n),s=Gc(e.roll,o);return[a*t.dh+s*t.dr,a*r.dh-s*r.dr]}var ox=(e,t)=>He(e[0],t).h+He(e[1],t).h;function uw(e,t){let r=e.gap>0?ox(t,e.gap):0;return e.bothWays?{free:r,pull:e.gap>0?ox(t,-e.gap):0}:{free:r,pull:null}}function mw(e,t,r){let n={...t,outer:t.inner},o=(u,m)=>{let h=mt(ge(e[0],u,0)),d=mt(ge(e[1],m,0));if(!h||!d)return NaN;let p=Pe(e[0].corner,t,h),f=Pe(e[1].corner,n,d);return Math.hypot(p[0]-f[0],p[1]+f[1],p[2]-f[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)>fd?{length0:s,scale:l}:null}function lx(e,t,r,n=Nc){let o=r.heave?Ja(r.heave):void 0,a=ex(e[0],r,o,n),s=e[1].corner===e[0].corner?a:ex(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,h=(t[0].arbRate+t[1].arbRate)/2,d=i.map(A=>He(A,0));c&&!(Math.abs(d[0].dh+d[1].dh)>fd)&&(i=[$c(i[0],"heave"),$c(i[1],"heave")],c=!1),l&&!(Math.abs(d[0].dr+d[1].dr)>fd)&&(i=[$c(i[0],"roll"),$c(i[1],"roll")],l=!1),d=i.map(A=>He(A,0));let p=d[0].dh+d[1].dh,f=d[0].dr+d[1].dr,b=m>0?2*m/(p*p):0,g=h>0?2*h/(f*f):0,y=0,R=0;if(r.carriesLoad){let A=[t[0].springLoad,t[1].springLoad];if(b>0&&g>0){let P=-d[0].dh*d[1].dr-d[1].dh*d[0].dr;Math.abs(P)>1e-12&&(y=(-A[0]*d[1].dr-A[1]*d[0].dr)/P,R=(d[0].dh*A[1]-d[1].dh*A[0])/P)}else b>0?y=(A[0]+A[1])/p:g>0&&(R=(A[0]-A[1])/f)}let M={};if(c&&o){let A=[a.pickups.heave,s.pickups.heave];M.heave={pickups:A,mount:o,span0:es(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?rd(b,{...uw(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&&Xr(e[0].corner,r.roll,r.rollKind??"coil"))){let A=mw(e,r.roll,i);A&&(M.roll.unit=A)}let C=g>0?{rate:g,preload:R}:null,w={side:i,heave:F,roll:C,force0:[0,0],carriesLoad:r.carriesLoad,read:M},T=M.roll?.unit,S=T&&g>0&&i[0].eyes&&i[1].eyes?Eo(T.length0,r.rollCoilover):null;return T&&S&&(S.droop!==null||S.bump!==null)&&(w.rollStop={length0:T.length0,rate:1e3*g/(T.scale*T.scale),...S}),w.force0=ts(w,[0,0],rs(w,d[0],d[1],d[0].h+d[1].h,d[0].r-d[1].r)),w}function ns(e,t,r){let n=He(e.side[0],t[0]),o=He(e.side[1],t[1]),a=r?ts(e,t,rs(e,n,o,n.h+o.h+r.heave,n.r-o.r+r.roll),void 0,r.unit):ts(e,t,rs(e,n,o,n.h+o.h,n.r-o.r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function yd(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=nx(e.heave,a),c=nx(e.roll,s),l=Gc(e.heave,a),u=Gc(e.roll,s),m=i*n.dh*o.dh-c*n.dr*o.dr,h=[[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]],d=e.rollStop,p=d?ix(e,t):null;if(!d||!p)return h;let f=d.length0-(r?p.L+r.unit:p.L),b=lw(d,f);if(b===0)return h;let g=cx(d,f),y=(M,v)=>b*p.dL[M]*p.dL[v]-g*p.ddL[M][v],R=m+y(0,1);return[[h[0][0]+y(0,0),R],[R,h[1][1]+y(1,1)]]}function xd(e,t,r){let n=yd(e,t);return n[r][0]+n[r][1]}function pw(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-es(Pe(o.corner,o.link,r[0]),Pe(a.corner,a.link,r[1]),n.mount)}function dw(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 fw(e,t){let r=e.read.roll;if(!e.rollStop||!r)return;let[n,o]=r.pickups;return gd(Pe(n.corner,n.link,t[0]),Pe(o.corner,{...o.link,outer:o.link.inner},t[1]))}function os(e,t,r){let n=He(e.side[0],t[0]),o=He(e.side[1],t[1]),a=ts(e,t,rs(e,n,o,pw(e,t,r),dw(e,t,r)),fw(e,r));return[a[0]-e.force0[0],a[1]-e.force0[1]]}function Rd(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*sx(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?gd(Pe(l.corner,l.link,n),Pe(l.corner,{...l.link,outer:l.link.inner},n)):void 0;return ts(e,[r,r],rs(e,o,a,c,n?0:o.r-a.r),u)[t]-e.force0[t]}function vd(e,t,r,n){let o=_o(e,r[n]);return t?.carriesLoad?o+xd(t,r,n):o}var kd=e=>e==="FR"||e==="RR"?1:0,Kc=(e,t)=>e.elements?.[t==="FL"||t==="FR"?"front":"rear"]??null;var ux=e=>Number.isFinite(e)&&e>0?1/e:0;var mx=(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},hw=(e,t)=>[e[0][0]*t[0]+e[0][1]*t[1],e[1][0]*t[0]+e[1][1]*t[1]],px=1e-8,bw=40;function gw(e,t,r,n){return{force:(s,i)=>{if(r){let u=ns(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=Za)=>{if(r){let c=yd(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 Oo(e,t,r,n,o,a=[0,0],s=[0,0],i=null,c){let l=[ux(r[0].tyreRate),ux(r[1].tyreRate)],u=[r[0].staticLoad,r[1].staticLoad],m=gw(r,n,i,c),h=P=>m.force(P,a),d=m.stiffness([0,0]),p=[l[0]>0?l[0]:1/Math.max(1,Math.abs(d[0][0])),l[1]>0?l[1]:1/Math.max(1,Math.abs(d[1][1]))],f=(P,L)=>{let D=L===1?h(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=[p[0]*(u[0]+I[0]),p[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]?[p[0]*P[0][0],p[0]*P[0][1]]:[1+P[0][0]*l[0],P[0][1]*l[0]],L[1]?[p[1]*P[1][0],p[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=f(D,L),G=!1,O=0;for(;O<bw;O++){if(g(I.r)<px){G=!0;break}let W=mx(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=f(_,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=f(_,L);D=_,I=V}return!G&&g(I.r)<px&&(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,C=[F[0]?-u[0]:x.f[0],F[1]?-u[1]:x.f[1]],w=[F[0]?Math.max(0,x.on[0]):0,F[1]?Math.max(0,x.on[1]):0],T=m.stiffness(v,_o),S=b(T,F);return{t:v,dF:C,lifted:F,clearance:w,converged:k,iterations:M,respond:(P,L,D=[0,0])=>{let I=[F[0]?-p[0]*D[0]:P[0]-L[0]-D[0]*l[0],F[1]?-p[1]*D[1]:P[1]-L[1]-D[1]*l[1]],G=mx(S,I);if(!G)return[NaN,NaN];let O=hw(T,G);return[F[0]?0:O[0]+D[0],F[1]?0:O[1]+D[1]]}}}var kn=e=>!(Number.isFinite(e.tyreRate)&&e.tyreRate>0);function Qt(e,t,r){return t?.input.corners[r].staticLoadedRadius??e}var Md=["FL","FR","RL","RR"],hx={front:["FL","FR"],rear:["RL","RR"]},yw=512,xw=5e-4,Rw=8;function Hc(e,t){let r={},n={},o=new Map;for(let s of Md){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=`${Md.findIndex(d=>$e(e.vehicle,d)===$e(e.vehicle,s))}|${c.springLoad}|${u?`${u.extended}/${u.stroke}`:""}`,h=o.get(m);h?r[s]=h:(r[s]=u?Qa(i,c.springLoad,void 0,u):Qa(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=hx[s];a[s]=lx([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 bx(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 vw=e=>`${e.heave}|${e.pitch}|${e.roll}|${e.steer}`;function Sd(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 kw=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 dx(e,t,r,n){let o=hx[n],a=e.vehicle.config,s=o.map(C=>Ur(C,a,r,e.vehicle)),i=[t.input.corners[o[0]],t.input.corners[o[1]]],c=t.loadCase;if(!c&&i.every(kn))return{corners:[Sd(e,o[0],s[0]),Sd(e,o[1],s[1])],respond:null};let l=o.map(C=>t.curve[C]),u=t.elements?.[n]??null,m=o.map(C=>Qt($e(e.vehicle,C).config.loadedRadius,t,C)),h=[s[0].travel+(c?.ground[o[0]]??0),s[1].travel+(c?.ground[o[1]]??0)],d=[c?.linkLoad[o[0]]??0,c?.linkLoad[o[1]]??0],p=[c?.patchShift[o[0]],c?.patchShift[o[1]]],f=[0,0],b=[0,0],g,y=Oo(h,f,i,l,void 0,void 0,d,u),R=[void 0,void 0],M=[!0,!0],v=[0,0],x=!1;for(let C=0;C<Rw;C++){C>0&&(y=Oo(h,f,i,l,g,b,d,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 w=[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,kw(R[A]),{loadedRadius:m[A]-v[A],patchShift:p[A]}),L=ot(P);R[A]=L,M[A]=P.ok,w[A]=L.points.contactPatch[2]-t.ground0[o[A]]-y.t[A]-v[A],T[A]=hr(l[A],y.t[A],L.points.damperLength)-Kt(l[A],y.t[A])}if(u){let A=os(u,y.t,[R[0],R[1]]),P=ns(u,y.t);T[0]+=A[0]-P[0],T[1]+=A[1]-P[1]}let S=Math.max(Math.abs(w[0]-f[0]),Math.abs(w[1]-f[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(f=w,b=T,g=y.t,S<xw){x=!0;break}}let k=y.respond([1,1],[0,0]);return{corners:[0,1].map(C=>{let w=R[C];return{travel:y.t[C],steer:s[C].steer,ground:h[C],tyreDeflection:v[C],load:i[C].staticLoad+y.dF[C],loadedRadius:m[C]-v[C],lifted:y.lifted[C],clearance:y.clearance[C],contactLength:bx(m[C]-v[C],i[C].staticLoad+y.dF[C],i[C].tyreRate),converged:y.converged&&x&&M[C],rigid:!1,state:w,solved:M[C],rideRate:k[C],wheelRateAtLoad:vd(l[C],u,y.t,C)}}),respond:y.respond}}function gx(e,t){let r=e.kc,n=vw(t),o=r.memo.get(n);if(o)return o;let a=dx(e,r,t,"front"),s=dx(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>=yw&&r.memo.clear(),r.memo.set(n,i),i}function dt(e,t){if(!e.kc){let r={};for(let n of Md)r[n]=Sd(e,n,Ur(n,e.vehicle.config,t,e.vehicle));return r}return gx(e,t).corners}function zc(e,t,r){return e.kc?gx(e,t).respond[r]:null}function as(e,t,r,n=0){let o=e.kc;if(!o)return r;let a=o.input.corners[t];if(kn(a))return r;let s=Ur(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})),h=Kc(o,t),d=hr(o.curve[t],r,m.points.damperLength)+(h?Rd(h,kd(t),r,m):a.heaveRate*r),f=Math.max(d+l,-a.staticLoad)/a.tyreRate;return(f===0?m:ot(ge(e.ctx[t],r,s,void 0,{loadedRadius:i-f,patchShift:u}))).points.contactPatch[2]-o.ground0[t]-(c?.ground[t]??0)}var Mw=180/Math.PI,Sw=[0,0,1];function Aw(e,t){let r=Rn(e,t),n=U(ae(Sw,r),-t.sideSign);return-Math.atan2(n[1],n[0])*Mw}var yx=e=>1/Math.tan(e*Math.PI/180),xx=.05,Rx=.001;function vx(e,t,r){if(!Number.isFinite(e)||!Number.isFinite(t))return NaN;if(!(Math.abs(e)<Rx&&Math.abs(t)<Rx))return e>0&&t>0?100*(yx(t)-yx(e))/r:NaN}function Fw(e,t){let r=jr(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=[xx,-xx].map(l=>{let{inner:u,outer:m}=a(t("FL",l).deg-n,t("FR",l).deg-o);return vx(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:h,outer:d}=a(l.deg-n,u.deg-o),p=vx(h,d,r);return{steerL:l.deg,steerR:u.deg,inner:h,outer:d,toeDiff:h-d,ackermannPct:p??i(),inside:p===void 0?null:m?"left":"right",converged:l.ok&&u.ok}}}function Ad(e,t){let r=e.vehicle.config,n={FL:Ze("FL",r),FR:Ze("FR",r)},o=t.travel??0,a=Fw(e,(i,c)=>{let l=mt(ge(e.ctx[i],o,n[i].sideSign*c));return{deg:l?Aw(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 kx=35,Mx=55,Nt=e=>e.rackTravel&&e.rackTravel>0?e.rackTravel:kx,Fd=e=>e.rackRatio&&e.rackRatio>0?e.rackRatio:Mx;var Cd=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 Sx(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=d=>{let p=[l],f=Cd(s);for(let b=1;b<=r;b++){let g=d*(t*b)/r,y=Ee(e,s.beta,g,f,o),R=mt(ge(e,n,g,Cd(y),o));if(!R||!y.converged){i++,p.push({...p[p.length-1]});continue}p.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}),f=Cd(y)}return p},m=u(1),h=u(-1);return{travelMm:n,unsolved:i,centre:l,positive:m,negative:h}}function Cw(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 Ax(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:Cw(o,t)});return{travelMm:e.travelMm,inner:n(r?e.positive:e.negative),outer:n(r?e.negative:e.positive)}}function ww(e){return e.positive[1].steer-e.centre.steer<0}function Tw(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:Fd(e.config),innerJacobian:r.inner.jacobian,outerJacobian:r.outer.jacobian}}function wd(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=Sx(i,t,r,0,s),u=ww(l),m=Ax(l,c,u),h=Math.max(2,Math.floor(a)),d=Array.from({length:h},(b,g)=>n+(o-n)*g/(h-1));d.some(b=>Math.abs(b)<1e-9)||d.push(0),d.sort((b,g)=>b-g);let p=l.unsolved,f=d.map(b=>{if(Math.abs(b)<1e-9)return m;let g=Sx(i,t,r,b,s);return p+=g.unsolved,Ax(g,c,u)});return{...Tw(e,c,m),...Fx(l.unsolved),travelSurface:{rackMm:c,rows:f,...Fx(p)}}}var Fx=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 Yc(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 Cx(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 Mn=(e,t,r)=>e+r*(t-e);function Vo(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 Mn(a,s,n.t)}function wx(e,t,r,n){let o=Yc(e.rackMm,e.rows[r.lo][t].jacobian,n);if(r.lo===r.hi)return o;let a=Yc(e.rackMm,e.rows[r.hi][t].jacobian,n);return{longitudinal:Mn(o.longitudinal,a.longitudinal,r.t),lateral:Mn(o.lateral,a.lateral,r.t),vertical:Mn(o.vertical,a.vertical,r.t),yaw:Mn(o.yaw,a.yaw,r.t)}}function Bo(e,t,r,n){let o=e.travelSurface;if(!o||o.rackMm.length<2||o.rows.length===0)return $o(e,t);let a=Cx(o,r),s=Cx(o,n),i=(d,p,f)=>{let b=o.rows[p.lo][d].steerDeg[f];return p.lo===p.hi?b:Mn(b,o.rows[p.hi][d].steerDeg[f],p.t)},c=new Array(o.rackMm.length);for(let d=0;d<c.length;d++)c[d]=.5*(i("inner",a,d)+i("outer",s,d));let l=Math.max(0,t),u=c.length-1,m=o.rackMm[u],h=l>c[u];if(l<=c[0])m=o.rackMm[0],h=!1;else if(!h){let d=1;for(;d<c.length-1&&c[d]<l;)d++;let p=d-1,f=c[d]-c[p],b=Math.abs(f)>1e-12?(l-c[p])/f:0;m=Mn(o.rackMm[p],o.rackMm[d],b)}return{innerDeg:Vo(o,"inner","steerDeg",a,m),outerDeg:Vo(o,"outer","steerDeg",s,m),innerCamber:Vo(o,"inner","camberDeg",a,m),outerCamber:Vo(o,"outer","camberDeg",s,m),innerLift:Vo(o,"inner","liftMm",a,m),outerLift:Vo(o,"outer","liftMm",s,m),innerJacobian:wx(o,"inner",a,m),outerJacobian:wx(o,"outer",s,m),atLock:h}}function $o(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:Yc(e.meanDeg,e.innerJacobian,t),outerJacobian:Yc(e.meanDeg,e.outerJacobian,t)}:{},atLock:r>=0&&t>e.meanDeg[r]}}var Pw=()=>({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 Go(e,t,r=we(e),n){let o=e.steerFront;if(!o?.innerLift||!o.outerLift||o.meanDeg.length<2||Math.abs(t)<1e-12)return Pw();let a=Math.abs(t),s=t>0,i=n&&o.travelSurface?Bo(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,h=.5*(u+m),d=r.rollWheelRateFront,p=r.rollWheelRateRear,f=e.trackFront,b=e.trackRear,g=d*f*f+p*b*b,y=g>0?d*f*(m-u)/g:0,R={FL:u-h+.5*f*y,FR:m-h-.5*f*y,RL:.5*b*y,RR:-.5*b*y};return{lift:{FL:u,FR:m,RL:0,RR:0},travel:R,load:{FL:d*R.FL,FR:d*R.FR,RL:p*R.RL,RR:p*R.RR},rollDeg:y===0?0:-Math.atan(y)*180/Math.PI}}function Td(e,t,r){let n=t/r,o=a=>1/Math.tan(a*Math.PI/180);for(let a=0;a<e.meanDeg.length;a++)if(e.outerDeg[a]>.3&&e.innerDeg[a]>.3)return 100*(o(e.outerDeg[a])-o(e.innerDeg[a]))/n;return NaN}var ss=9.81;function Ko(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?zr(e,t,r,Co(e,n,o)):Ao(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 Pd(e,t,r=0,n=0,o=0){if(!e.aero?.model||t<=0)return!1;let a=zr(e,t,r,Co(e,n,o));return a!=null&&(a.clampedRide||a.clampedAttitude)}function Sn(e){let t=e.loadFactor===void 0?e.massTotal*ss:e.massTotal*ss*e.loadFactor,r=t*e.frontMassFrac,n=t*(1-e.frontMassFrac);return{FL:r/2,FR:r/2,RL:n/2,RR:n/2}}function Tx(e,t=we(e),r=e.cgHeight){let n=e.trackFront/1e3,o=e.trackRear/1e3,a=e.rcHeightFront/1e3,s=e.rcHeightRear/1e3,i=(e.rcHeightFront+(e.rcHeightRear-e.rcHeightFront)*(1-e.frontMassFrac))/1e3,c=r/1e3-i,l=2*e.unsprungPerCorner,u=e.unsprungCgHeight/1e3,m=t.sprungMass*c*vc(t.sprungMass,c,t.rollRateTotal),h=(m*t.frontRollStiffFrac+t.sprungFront*a+l*u)/n,d=(m*(1-t.frontRollStiffFrac)+t.sprungRear*s+l*u)/o;return{cf:h,cr:d}}function Ld(e){let{cf:t,cr:r}=Tx(e);return t+r>0?t/(t+r):.5}function Px(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 h=u>0?1:-1,d=(h*a-c)*t;h*u>=h*d?(c=h*a,u-=d):(c+=u/t,u=0);let p=(h*s-l)*r;u!==0&&(h*u>=h*p?(l=h*s,u-=p):(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 Wc(e,t,r,n,o,a,s,i).loads}function Wc(e,t,r,n=0,o=0,a=0,s,i){let c=Sn(e),l=we(e),u=Lc(e,n,r,Co(e,t,o),l),{cf:m,cr:h}=Tx(e,l,u.height),d=m*t*ss,p=h*t*ss,f=e.massTotal*(r*ss)*u.height/e.wheelbase-u.noseLoad,b=Ko(e,n,r,t,o),g=(i??Go(e,a,l,s)).load,y={FL:c.FL-d-f/2+b.FL+g.FL,FR:c.FR+d-f/2+b.FR+g.FR,RL:c.RL-p+f/2+b.RL+g.RL,RR:c.RR+p+f/2+b.RR+g.RR};return Px(y,e.trackFront,e.trackRear)}var Dd=Math.PI/180;function Uc(e,t){let r=8*Dd,n=0,o=0;for(let a=1;a<=90;a++){let s=a*.5,i=Math.abs(e.Fy(s*Dd,t,0));if(i>n&&(n=i,r=s*Dd,o=a),a>o+12&&i<.995*n)break}return{aPeak:r,fyPeak:n}}function Lx(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 cs=.999;function kt(e,t,r,n,o){if(t<=0)return 0;let{aPeak:a,fyPeak:s}=o??Uc(e,t),i=Math.min(Math.abs(r),cs*s),c=n?-1:1,l=(v,x)=>Math.abs(e.forces({Fz:t,kappa:c*v,alpha:x}).Fy),u=.3,m=u,h=l(u,a);if(h<i){let v=0,x=u,k=NaN,F=h;for(let C=0;C<9;C++){let w=.5*(v+x),T=l(w,a);T>=i?(v=w,k=T):(x=w,F=T)}Number.isNaN(k)&&(k=l(0,a)),m=k<i?0:Lx(v,k,x,F,i)}if(m<=0)return 0;let d=v=>{if(i===0)return c*e.forces({Fz:t,kappa:c*v,alpha:0}).Fx;let x=0,k=a,F=NaN,C=NaN;for(let w=0;w<5;w++){let T=.5*(x+k),S=l(v,T);S<i?(x=T,F=S):(k=T,C=S)}return Number.isNaN(F)&&(F=l(v,0)),Number.isNaN(C)&&(C=l(v,a)),c*e.forces({Fz:t,kappa:c*v,alpha:Lx(x,F,k,C,i)}).Fx},p=4,f=v=>m*v/p,b=[0],g=1;for(let v=1;v<=p;v++)b.push(d(f(v))),b[v]>b[g]&&(g=v);let[y,R]=g===p?[p-1,p-2]:b[g-1]>=b[g+1]?[g-1,g+1]:[g+1,g-1],M=Iw(d,f(g-1),f(Math.min(p,g+1)),f(g),b[g],f(y),b[y],f(R),b[R],Lw);return c*Math.max(0,M)}var Lw=.01,Dw=20,Ew=(3-Math.sqrt(5))/2;function Iw(e,t,r,n,o,a,s,i,c,l){o=-o,s=-s,c=-c;let u=r-t,m=0;for(let h=0;h<Dw;h++){let d=l*Math.abs(n)+1e-10,p=.5*(t+r);if(Math.abs(n-p)<=2*d-.5*(r-t))break;let f=!0;if(Math.abs(u)>d){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*d||r-x<2*d)&&(m=p>=n?d:-d),f=!1}}f&&(u=n>=p?t-n:r-n,m=Ew*u);let b=Math.abs(m)>=d?n+m:n+(m>=0?d:-d),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 _d(e,t){return e.model?.kind==="simple"?null:Ix(e,t)}var Dx=new WeakMap,Ed=100,Ex=1.35,Id=18,Jt=41,jc=41,is=65;function Ix(e,t){let r=Dx.get(e);if(r)return r;let n=Math.log(Ex),o=(d,p)=>{let f=k=>Math.abs(kt(e,d,k,p)),b=f(0),g=t.muY(d)*d,y=new Float64Array(Jt),R=b>0&&g>0?Math.max(1,t.muX(d)*d/b):1;if(!(b>0)||!(g>0))y.fill(1);else{let k=[],F=[];for(let w=0;w<jc;w++){let T=Math.sin(.5*Math.PI*w/(jc-1));k.push(T),F.push(w===0?1:w===jc-1?0:Math.min(F[w-1],f(T*g)/b))}let C=jc-1;for(let w=0;w<Jt;w++){let T=w/(Jt-1);for(;C>0&&F[C-1]<T;)C--;let S=C>0?F[C-1]-F[C]:0;y[w]=C===0?k[0]:k[C]+(S>0?(T-F[C])/S:0)*(k[C-1]-k[C])}y[0]=1,y[Jt-1]=0}let M=new Float64Array(is),v=k=>Math.atan2(y[k],k/(Jt-1)/R),x=Jt-2;for(let k=0;k<is;k++){let F=.5*Math.PI*k/(is-1),C=Math.cos(F),w=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=C*(P-S)-w*(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:Id},(d,p)=>Ed*Ex**p),s=a.map(d=>o(d,!1)),i=a.map(d=>o(d,!0)),c=(d,p)=>{let f=Math.min(1,Math.abs(p)*d.scale)*(Jt-1),b=Math.min(Jt-2,Math.floor(f));return d.room[b]+(f-b)*(d.room[b+1]-d.room[b])},l=d=>{let p=d>Ed?Math.log(d/Ed)/n:0;if(p>=Id-1)return[Id-2,1];let f=Math.floor(p);return[f,p-f]},u=(d,p,f)=>{if(f===0)return 1;let b=f<0?i:s,g=c(b[d],f);return p>0?g+p*(c(b[d+1],f)-g):g},m=(d,p,f)=>{let b=p<0?i:s,[g,y]=l(d),R=Math.atan2(Math.abs(f),Math.abs(p))/(.5*Math.PI)*(is-1),M=Math.min(is-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},h={keeps(d,p){if(p===0)return 1;let[f,b]=l(d);return u(f,b,p)},atLoad(d){let[p,f]=l(d);return b=>u(p,f,b)},use(d,p,f){let b=Math.hypot(p,f);return b>0?Math.min(1,b/m(d,p,f)):0},reach:m};return Dx.set(e,h),h}var _w=[["front","FL","FR"],["rear","RL","RR"]];function Ho(e,t,r,n){let o={...e},a=0,s=cs;for(let[i,c,l]of _w){let u=(M,v)=>n(i,Math.max(0,v[M])).fyPeak,m=Math.min(s,e[c]),h=Math.min(s,e[l]),d=m*u(c,r)+h*u(l,r);if(!(d>0))continue;let p=u(c,t),f=u(l,t),b=m*p+h*f,g=b>0?d/b:1/0,y=m*g,R=h*g;y<=s?R<=s||(R=s,y=p>0?(d-s*f)/p:1/0):(y=s,R=f>0?(d-s*p)/f:1/0),(!(y<=s)||!(R<=s))&&(a+=Math.max(0,d-s*(p+f)),y=Math.min(s,y),R=Math.min(s,R)),o[c]=y,o[l]=R}return{util:o,short:a}}var _x=.001,Nw=1e-5,Nx=100;function Ow(e,t,r,n){if(!(n>_x))return r;let o=t,a=Math.abs(r-t)<Nx?t+Math.sign(r-t)*Nx:r;for(let s=0;s<60&&Math.abs(a-o)>Nw;s++){let i=.5*(o+a);e(i)>_x?a=i:o=i}return o}function Xc(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=Ow(e,t,o,e(o));return a!==o&&(n=a),a},edge:()=>n}}function qc(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 Nd=40;function Qc(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 Ox=[0,0,0];function Vw(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 Zc(e,t,r){if(e.mcpherson)return Bw(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 h=q(H(n[m].c,n[m].r)),d=ae(H(n[m].r,o),h);a[0][m]=h[0],a[1][m]=h[1],a[2][m]=h[2],a[3][m]=d[0],a[4][m]=d[1],a[5][m]=d[2]}let s=ae(H(e.contactPatch,o),t),i=r??Ox,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]:Vw(e,u[5]),condProxy:l.condProxy,singular:l.singular}}function Bw(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??Ox,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,h=[m[3],m[4],m[5]],d=q(H(o,e.pushrodOuter)),p=X(h,d),f=Math.hypot(h[0]-p*d[0],h[1]-p*d[1],h[2]-p*d[2]);return{ucaFront:NaN,ucaRear:NaN,lcaFront:m[0],lcaRear:m[1],tieRod:m[2],pushRod:u.singular?NaN:p,damper:u.singular?NaN:p,condProxy:u.condProxy,singular:u.singular,strutSide:u.singular?NaN:f,topMount:h}}function Od(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 $w=[0,0,0];function ls(e,t,r,n){let o=e.direct?e.damperChassis:e.rockerToPushrod;if(e.mcpherson)return{...Zc(e,r,n),armResidual:0};if(t==="upright")return{...Zc(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)),h=[{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]}],d=[[],[],[],[],[],[]];for(let Q=0;Q<6;Q++){let ne=h[Q].dir,te=ae(H(h[Q].at,c),ne);d[0][Q]=ne[0],d[1][Q]=ne[1],d[2][Q]=ne[2],d[3][Q]=te[0],d[4][Q]=te[1],d[5][Q]=te[2]}let p=ae(H(e.contactPatch,c),r),f=n??$w,b=[-r[0],-r[1],-r[2],-(p[0]+f[0]),-(p[1]+f[1]),-(p[2]+f[2])],g=qt(d,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)),C=q(H(o,e.pushrodOuter)),w=U(k,-1),T=(Q,ne)=>X(F,ae(H(Q,i.front),ne)),S=T(e.pushrodOuter,C),A=Math.abs(S)>1e-9?-T(i.bj,w)/S:NaN,P=ee(w,U(C,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:Gw(e,A),condProxy:g.condProxy,singular:y,armResidual:K}}function Gw(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 F$=Math.PI/180;function us(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 Bx=["QSX3","QSX8","QSX13","QSX14"],Kw=["QSX1"],Jc=["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",...Bx];function Hw(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 zw(e){let t=new Set(Hw(e)),r=Jc.filter(n=>!Bx.includes(n));return[...r.filter(n=>!t.has(n)),...[...t].filter(n=>!r.includes(n)),...Kw]}function Yw(e,t){let r={...e};for(let n of t)r[n]!==void 0&&r[n]!==0&&(r[n]=-r[n]);return r}var gr=(e,t,r)=>Number.isFinite(e[t])?e[t]:r;function $x(e,t){return t!=="5.2"?gr(e,"PKY6",0)*gr(e,"LKYC",1):gr(e,"PKY1",-15)*Math.sin(gr(e,"PKY4",2)*Math.atan(1/gr(e,"PKY2",2)))*gr(e,"LKY",1)*gr(e,"PHY3",0)+gr(e,"PVY3",0)*gr(e,"LMUY",1)}var Vx=.1;function Gx(e){if(e.fitData)return"sae";let t=$x(e.coeffs,e.version);return t>Vx?"sae":t<-Vx?"iso":null}function ms(e){return e.axisSystem??Gx(e)??"sae"}function el(e){let t=new Set,r=n=>{for(let o of n)t.has(o)?t.delete(o):t.add(o)};return ms(e)==="iso"&&r(Jc),e.axisSystem&&e.side==="left"&&r(zw(e.version)),t.size?Yw(e.coeffs,t):e.coeffs}var w$=Math.PI/180;var B=(e,t)=>Number.isFinite(e)?e:t;function Hx(e){let t=el(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 Kx=new WeakMap;function ps(e){let t=Kx.get(e);return t===void 0&&(t=Hx(e),Kx.set(e,t)),t}var zx=e=>e>=0?1:-1;function tl(e,t,r=0,n){let o=ps(e),a=Math.max(1,t),s=r,i=o.LFZO*e.fnomin,c=(a-i)/i,l=e.nomPressure>0&&n?(n-e.nomPressure)/e.nomPressure:0,u=e.unloadedR0,m=(o.PDY1+o.PDY2*c)*(1+o.PPY3*l+o.PPY4*l*l)*(1-o.PDY3*s*s)*o.LMUY,h=o.PCY1*o.LCY,d=m*a,p=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,f=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(p)>1e-6?p:1e-6*(p<0?-1:1),R=f?(o.PHY1+o.PHY2*c)*o.LHY+(b*s-g)/y:(o.PHY1+o.PHY2*c)*o.LHY+o.PHY3*s,M=f?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=h*d!==0?p/(h*d):0;return{Fz:a,g:s,dfz:c,dpi:l,Fz0p:i,R0:u,Cy:h,Dy:d,By:v,SHy:R,SVy:M,Kya:p,muy:m,EyA:o.PEY1+o.PEY2*c,EyG:1+o.PEY5*s*s,EyS:o.PEY3+o.PEY4*s,LEY:o.LEY}}function rl(e,t,r=0,n){let o=tl(e,t,r,n),a=ps(e),{Fz:s,g:i,dfz:c,dpi:l,Fz0p:u,R0:m,muy:h,Kya:d,SVy:p,By:f,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,C=Math.abs(d)>1e-6?d:1e-6*(d<0?-1:1),w=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:f,SHy:y,SVy:p,Kya:d,muy:h,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:h*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:w?(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:w?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*f*b,Dr:w?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:d!==0?p/d:0,sixOne:w,kk:k/C*(k/C),sS0:m*(a.SSZ1+(a.SSZ3+a.SSZ4*c)*i)*a.LS,sS2:m*a.SSZ2*a.LS/u}}function ds(e,t){let r=t+e.SHy,n=e.EyA*(e.EyG-e.EyS*zx(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 nl(e,t){let r=t+e.SHx,n=e.ExA*(1-e.PEX4*zx(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 Yx(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 Ww(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=Yx(e,o,r),i=e.Bt*s;return e.Dt*Math.cos(e.Ct*Math.atan(i-a*(i-Math.atan(i))))*n}function jw(e,t,r,n){return e.Dr*Math.cos(Math.atan(e.Br*Yx(e,t+e.SHy+e.arOff,r)))*n}function Wx(e,t,r,n,o,a){let s=Math.cos(t),i=Ww(e,t,r,s),c=jw(e,t,r,s);return-i*(o-a)+c+(e.sS0+e.sS2*o)*n}function jx(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*nl(e,t)}function Vd(e,t){let r=e.sS0===0&&e.sS2===0?0:jx(e,0,t);return Wx(e,t,0,r,ds(e,t),0)}function ol(e,t,r){let n=ds(e,r),o=jx(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:Wx(e,r,t,o,m,u)}}var fs=(e,t)=>Math.max(.1,e.muY0+e.loadSensY*(t-e.nominalLoad)),hs=(e,t)=>Math.max(.1,e.muX0+e.loadSensX*(t-e.nominalLoad)),Ux=(e,t,r)=>fs(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cy*Math.atan(e.By*r)),Xx=(e,t,r)=>hs(e,Math.max(1,t))*Math.max(1,t)*Math.sin(e.Cx*Math.atan(e.Bx*r));function Bd(e,t){let r=Math.max(1,t.Fz),n=fs(e,r)*r,o=hs(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 al=Math.PI/180;function qr(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 qx(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?us(r,t):1,s=n?us(n,t):1,i=o?us(o,t):1;if(a===1&&s===1&&i===1)return e;if(e.kind==="simple")return{...e,muY0:e.muY0*a,muX0:e.muX0*s};let c={...e.coeffs},l=(u,m)=>{c[u]=(c[u]??1)*m};return l("LMUY",a),l("LMUX",s),l("LTR",i),l("LRES",i),{...e,coeffs:c}}function zo(e,t,r){let n=0,o=0;for(let s=r;s<=t;s+=r){let i=Math.abs(e(s));i>o&&(o=i,n=s)}let a=r/10;for(let s=Math.max(a,n-r);s<=n+r;s+=a)o=Math.max(o,Math.abs(e(s)));return o}function Ie(e){let t=qx(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=rl(r,v,x,k),a=v,s=x,i=k),o),l=null,u=NaN,m=NaN,h=NaN,d=(v,x,k)=>(l!==null&&v===u&&x===m&&k===h||(l=tl(r,v,x,k),u=v,m=x,h=k),l),p=v=>e.kind==="magic"?ol(c(v.Fz,v.gamma??0,v.p),v.kappa,v.alpha):Bd(n,v),f=(v,x,k=0,F)=>e.kind==="magic"?ds(d(x,k,F),v):Ux(n,x,v),b=(v,x,k=0,F)=>e.kind==="magic"?nl(c(x,k,F),v):Xx(n,x,v),g=(v,x,k=0,F)=>e.kind==="magic"?Vd(c(x,k,F),v):p({Fz:x,kappa:0,alpha:v,gamma:k,p:F}).Mz,y=v=>e.kind==="simple"?fs(n,v):zo(x=>f(x*al,v),45,1)/Math.max(1,v),R=v=>e.kind==="simple"?hs(n,v):zo(x=>b(x,v),.6,.02)/Math.max(1,v),M=v=>{let x=.1*al;return Math.abs((f(x,v)-f(-x,v))/(2*x))};return{model:e,forces:p,Fx:b,Fy:f,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 Yo(e){let t=Math.max(1,e.model.kind==="magic"?e.model.fnomin:e.model.nominalLoad);return e.Fy(2*al,t,0)-e.Fy(-2*al,t,0)>=0?1:-1}var Uw=Math.PI/180;function xe(e,t){return e.axle?e.axle(t):e}function il(e,t){if(e===t)return e;let r=Yo(e)*Yo(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,h)=>n(e.Fx(l,u,m,h),t.Fx(l,u,m,h)),i=(l,u,m=0,h)=>n(e.Fy(l,u,m,h),r*t.Fy(l,u,m,h)),c=(l,u,m=0,h)=>n(e.Mz(l,u,m,h),r*t.Mz(l,u,m,h));return{model:e.model,forces:a,Fx:s,Fy:i,Mz:c,muX:l=>zo(u=>s(u,l),.6,.02)/Math.max(1,l),muY:l=>zo(u=>i(u*Uw,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 it(e){if(Qx.has(e))return e;let t=Zx.get(e);if(t)return t;let r;if(e.axle){let n=e.axle("front"),o=e.axle("rear"),a=it(n),s=it(o);r=a===n&&s===o?e:il(a,s)}else Yo(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 Qx.add(r),r!==e&&Zx.set(e,r),r}var Qx=new WeakSet,Zx=new WeakMap;var cl=25*(Math.PI/180);function Xw(e){let t=.6180339887,r=0,n=cl,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 bs(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=cl;if(s(cl)<=a){let u=Xw(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(cl,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),h=s(m)-a;if(h<0?i=m:c=m,Math.abs(h)<=l)return m}return c}var $d={shaft:!1,trail:0,hub:[0,0,0]};function eR(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 Gd(e,t,r){let n=r.shaft?Od(e,t):[0,0,0];if(r.trail!==0){let a=eR(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 qw=(e,t)=>{let r=e!==void 0&&e>0?1/e:0,n=t!==void 0&&t>0?1/t:0;return r+n},ll={ucaFront:0,ucaRear:0,lcaFront:0,lcaRear:0,tieRod:0,pushRod:0,rack:0};function An(e){return!e.measured}function Fn(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 gs(e,t){let r=e.corner.hardpoints,n=ja(e.rocker,t.points.rockerAngle);return{ucaFront:r.ucaFront,ucaRear:r.ucaRear,lcaFront:r.lcaFront,lcaRear:r.lcaRear,tieInner:wo(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 Kd(e,t,r=0){let n=t.links??{},o=t.bushings??{},a=(l,u,m)=>{let h=qw(u,m);return h>0&&Number.isFinite(l)?l*h: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 tR(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 ys(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=tR(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=tR(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 Qw=8,Zw=1e-5,Jw=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 Hd(e,t,r){let n=Gd(e,r.force,r.extras??$d),o=r.alignMoment?ee(n.moment,[0,0,r.alignMoment]):n.moment;return ls(e,t,n.force,o)}function ml(e,t,r,n,o,a,s=0){let i=Ee(e,t,r,o,a),c=e.corner.compliance;if(!(Fn(c)&&An(e.corner)))return{state:i,forces:Hd(gs(e,i),e.corner.config.pushrodAttach,n),deflection:ll,rigid:i,iterations:0,converged:!0,bypassed:!0};let u=i,m=e,h=e.corner.config.pushrodAttach,d=Hd(gs(e,i),h,n),p=ll,f=!1,b=0;for(;b<Qw;b++){let g=gs(m,u);if(d=Hd(g,h,n),d.singular)break;p=Kd(d,c,s),m=ys(e,p);let y=Ee(m,t,r,Jw(u),a),R=ve(y.points.wheelCenter,u.points.wheelCenter);if(u=y,R<Zw){f=!0;break}}return{state:u,forces:d,deflection:p,rigid:i,iterations:b+1,converged:f&&u.converged,bypassed:!1}}var ul=1e3,rR=1e5;function nR(e,t,r,n,o){let a=ml(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 pl(e,t,r,n,o){let a={force:[0,0,n]},s=(b,g=0)=>nR(e,t,r,{force:b,alignMoment:g},o),i=nR(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,ul,n]),l=s([0,-ul,n]),u=s([ul,0,n]),m=s([-ul,0,n]),h=s([0,0,n],rR),d=s([0,0,n],-rR),p=(b,g)=>(b-g)/2,f=[i,c,l,u,m,h,d].every(b=>b.converged);return{toePerLateral:p(c.toe,l.toe),camberPerLateral:p(c.camber,l.camber),toePerLongitudinal:p(u.toe,m.toe),camberPerLongitudinal:p(u.camber,m.camber),toePerAligning:p(h.toe,d.toe),lateralPatch:p(c.patch[1],l.patch[1]),longitudinalPatch:p(u.patch[0],m.patch[0]),bypassed:!1,converged:f}}var eT=1e3;function zd(e,t=eT){if(!Fn(e.compliance)||!An(e))return;let r=et(e),n=Ee(r,0,0),o=pl(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 Wo(e,t=-Nd,r=Nd,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=zd(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 dl(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 Qr(e,t){return{motionRatio:dl(e.travel,e.motionRatio,t),camber:dl(e.travel,e.camber,t),toe:dl(e.travel,e.toe,t),damperLen:dl(e.travel,e.damperLen,t)}}var oR=Math.PI/180,tT=9.81;function jo(e,t,r,n=0){let o=we(e),a=e.wheelbase*(1-e.frontMassFrac),s=e.wheelbase*e.frontMassFrac,i=Ko(e,n),c=e.aero?.model?(M,v,x)=>Ko(e,n,v,M,x):()=>i,l=Qr(t,0),u=Qr(r,0),m=e.loadFactor,h=m!==void 0&&m!==1?(m-1)*e.massTotal*tT:0,d=h*e.frontMassFrac/2,p=h*(1-e.frontMassFrac)/2,f=(M,v)=>v>0&&Number.isFinite(v)&&M+v>0?v/(M+v):1,b=Ue(e,"front"),g=Ue(e,"rear"),y={F:f(e.wheelRateFront+(e.heaveSpringFront??0),b),R:f(e.wheelRateRear+(e.heaveSpringRear??0),g)},R={F:f(e.wheelRateFront+e.arbFront,b),R:f(e.wheelRateRear+e.arbRear,g)};return(M,v,x=0,k=0)=>{let F=c(M,v,x),C=o.rollGradient*M,w=C*oR,T=o.pitchGradient*v*oR,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(w),V=(O==="R"?s:-a)*Math.tan(T),N=`${O}${G}`,$=h?F[N]+(O==="F"?d:p):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=Go(e,k,o,{FL:P("FL"),FR:P("FR")}),D=C+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=Qr(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 Yd=(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,Yd(e?.roadFeedbackGain,1))),turnInFrictionNm:Math.max(0,Yd(e?.turnInFrictionNm,0)),columnStiffnessNmPerRad:Math.max(0,Yd(e?.columnStiffnessNmPerRad,0))}}function Wd(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 aR=()=>({totalNm:0,aligningNm:0,lateralNm:0,longitudinalNm:0,jackingNm:0});function wn(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 xs(e,t,r,n="model",o){let a=e.steerFront;if(!wn(e)||!a)return null;let s=t<0?-1:1,c=a.rackRatioMmPerRev/(2*Math.PI)/1e3,l=t>=0,u=o&&a.travelSurface?Bo(a,Math.abs(t),l?o.FL:o.FR,l?o.FR:o.FL):$o(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=aR();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}},h=m("FL",l?u.innerJacobian:u.outerJacobian),d=m("FR",l?u.outerJacobian:u.innerJacobian),p=aR();for(let b of[h.moment,d.moment])p.aligningNm+=b.aligningNm,p.lateralNm+=b.lateralNm,p.longitudinalNm+=b.longitudinalNm,p.jackingNm+=b.jackingNm,p.totalNm+=b.totalNm;let f=Wd(p.totalNm,t,e.steeringSystem);return p.totalNm=f.driverNm,{...p,roadNm:f.roadNm,assistanceNm:f.assistanceNm,frictionNm:f.frictionNm,columnTwistDeg:f.columnTwistDeg,rackForceN:h.rackN+d.rackN,aligningSource:n,perWheel:{FL:h.moment,FR:d.moment}}}var rT=e=>"front"in e&&"rear"in e;function Uo(e,t){return rT(e)?e[t]:e}function Ud(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)),h=(u-a[m])/o;return l[m]+h*(l[m+1]-l[m])};return{muX:l=>c(s,l),muY:l=>c(i,l)}}function jd(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 sR(e,t,r){let n=jd(e,t),o=jd(e,r);return{left:n,right:o,fyRes:n.fyRes+o.fyRes}}function yr(e,t,r){let n=sR(Uo(e,"front"),t.FL,t.FR),o=sR(Uo(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 fl=[{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"}],oT=fl.flatMap(e=>[e.min,e.max]);function lR(e){return Math.max(1,e.kind==="magic"?e.fnomin:e.nominalLoad)}function iR(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=cR.get(e);if(t!==void 0)return t;let r=10*lR(e.model),{turnover:n,collapse:o}=sT(e,r),a=n??o??r;return cR.set(e,a),a}var cR=new WeakMap;function sT(e,t){let r=lR(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 h=o(m*s);if(h<c){i=iR(o,(m-2)*s,m*s,20,(d,p)=>d>p);break}c=h}let l=null,u=n(s);for(let m=2;m<=a;m++){let h=n(m*s);if(h>u){let d=iR(n,(m-2)*s,m*s,40,(p,f)=>p<f);n(d)<.05*n(r)&&(l=d);break}u=h}return{turnover:i,collapse:l}}var uR=["FL","FR","RL","RR"],iT=e=>e==="FL"||e==="RL",cT=e=>e==="FL"||e==="FR"?"front":"rear";function hl(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 uR)a[l]={...t[l]};let s=l=>{let u=0;for(let h of uR)cT(h)===e.axle&&(a[h].Fx=e.sense*(h===e.strong?l-e.open/2:e.open/2),u-=(iT(h)?o:-o)*a[h].Fx);let m=yr(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 lT=[["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]],uT=[["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]],mT=[["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]],pT=[["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]],dT=[["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]],pR=[["lateral",lT],["longitudinal",uT],["aligning",mT],["combined",pT],["scaling",dT]].flatMap(([e,t])=>t.map(([r,n,o])=>({key:r,section:e,text:n,fallback:o}))),LG=new Map(pR.map(e=>[e.key,e]));var fT=/^\$\s*EDITED\s+([A-Z][A-Z0-9_]*)\s+was\s+(absent|[-+0-9.eE]+)\s*$/;function dR(e){let t={};for(let r of e.split(/\r?\n/)){let n=r.trim().match(fT);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 bT=/^\s*\$\s*UNLOADED_RADIUS_STAND_IN\s*=\s*([0-9.eE+-]+)/,gT=/^\$-+ written by (?:PaceDynamics|PaceLab)\b/m,yT=/^\$\s*AXIS_SYSTEM\s*=\s*(ISO-W|SAE)\b/m;function xT(e){let t=e.match(yT);return t?{axisSystem:t[1]==="SAE"?"sae":"iso",trustSide:!0}:gT.test(e)?{axisSystem:"sae",trustSide:!1}:{axisSystem:"iso",trustSide:!0}}function RT(e){return e>=62?"6.2":e>=61?"6.1":"5.2"}var fR=new Map([["pa",1],["pascal",1],["kpa",1e3],["kilopascal",1e3],["mpa",1e6],["megapascal",1e6],["bar",1e5],["psi",6894.757293168]]);function vT(e,t,r){let n=r.PRESSURE?.trim().toLowerCase(),o=n===void 0?1:fR.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 kT=new Map([["radians",1],["radian",1],["rad",1],["degrees",Math.PI/180],["degree",Math.PI/180],["deg",Math.PI/180]]);function MT(e,t){let r=(s,i)=>s===void 0?1:i.get(s.trim().toLowerCase()),n=r(t.ANGLE,kT),o={fz:1,kappa:1,alpha:n,gamma:n,p:r(t.PRESSURE,fR)},a={};for(let s of fl){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 Rs(e,t="imported",r={}){let n=xT(e),o=r.axisSystem??n.axisSystem,a={},s={},i={},c="",l;for(let g of e.split(/\r?\n/)){let y=g.match(bT);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=RT(a.FITTYP??62),m=dR(e),h=m?Object.fromEntries(Object.entries(m).filter(([g])=>a[g]!==void 0)):void 0,d=a.VERTICAL_STIFFNESS??a.KZ??0,p=vT(a,s,i),f=MT(a,i),b=[];return a.UNLOADED_RADIUS===void 0&&a.R0===void 0&&b.push("UNLOADED_RADIUS"),d<=0&&b.push("VERTICAL_STIFFNESS"),a.FNOMIN===void 0&&b.push("FNOMIN"),p===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:d>0?d/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:p??0,missing:b,...h&&Object.keys(h).length?{edited:h}:{},...f?{range:f}:{}}}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 BG=Math.PI/180;var zG=Math.PI/180,YG=180/Math.PI;function vs(){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 yR=`$ AXIS_SYSTEM = SAE (authored in the evaluation frame: y right)
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)
3
3
  [MODEL]
4
4
  FITTYP = 62
5
5
  [DIMENSION]
@@ -108,7 +108,7 @@ QHZ1 = 0
108
108
  QHZ2 = 0
109
109
  QHZ3 = 0
110
110
  QHZ4 = 0
111
- `;function Xd(){return Rs(yR,"Example MF6.2")}var FT=Math.PI/180,xR=2,RR=2;function vR(e){let t=Math.sin(RR*Math.atan(1/xR)),r=-e.corneringStiffness/(e.Fz0*t),n=e.camberStiffness/FT/e.Fz0,o=(a,s=5)=>Number(a.toFixed(s)).toString();return`$ AXIS_SYSTEM = SAE (authored in the evaluation frame: y right, +inclination gives +Fy)
111
+ `;function Zd(){return vs(AR,"Example MF6.2")}var GT=Math.PI/180,FR=2,wR=2;function CR(e){let t=Math.sin(wR*Math.atan(1/FR)),r=-e.corneringStiffness/(e.Fz0*t),n=e.camberStiffness/GT/e.Fz0,o=(a,s=5)=>Number(a.toFixed(s)).toString();return`$ AXIS_SYSTEM = SAE (authored in the evaluation frame: y right, +inclination gives +Fy)
112
112
  [MODEL]
113
113
  FITTYP = 62
114
114
  [DIMENSION]
@@ -170,9 +170,9 @@ PEY3 = 0.1
170
170
  PEY4 = -4
171
171
  PEY5 = 0
172
172
  PKY1 = ${o(r)}
173
- PKY2 = ${o(xR)}
173
+ PKY2 = ${o(FR)}
174
174
  PKY3 = 0.8
175
- PKY4 = ${o(RR)}
175
+ PKY4 = ${o(wR)}
176
176
  PKY5 = 0
177
177
  PKY6 = ${o(n)}
178
178
  PKY7 = 0
@@ -220,7 +220,7 @@ QHZ1 = 0
220
220
  QHZ2 = 0
221
221
  QHZ3 = 0
222
222
  QHZ4 = 0
223
- `}function xr(e){let t=Rs(vR(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 kR={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},MR={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},SR={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},AR={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},FR={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},CR={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},wR={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},TR={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},qd=()=>xr(kR),Qd=()=>xr(MR),Zd=()=>xr(SR),Jd=()=>xr(AR),ef=()=>xr(FR),tf=()=>xr(CR),rf=()=>xr(wR),nf=()=>xr(TR);var PR=e=>Number.isFinite(e)&&e>0;function bl(e,t){let r=PR(t.grip)?t.grip:1,n=PR(t.stiffness)?t.stiffness:1;if(r===1&&n===1)return e;if(e.kind==="simple"){let o=n/r;return{...e,muX0:e.muX0*r,muY0:e.muY0*r,loadSensX:e.loadSensX*r,loadSensY:e.loadSensY*r,Bx:e.Bx*o,By:e.By*o}}return{...e,coeffs:{...e.coeffs,LMUX:(e.coeffs.LMUX??1)*r,LMUY:(e.coeffs.LMUY??1)*r,LKX:(e.coeffs.LKX??1)*n,LKY:(e.coeffs.LKY??1)*n}}}var ks={ok:!0,violation:0},Tn=1e7;function Rr(e,t){let r;try{r=e.build(t)}catch(s){return{total:Tn*2,feasible:!1,terms:[],reason:`build failed: ${String(s)}`}}let n=e.feasible(r);if(!n.ok)return{total:Tn+Math.max(0,n.violation),feasible:!1,terms:[],reason:n.reason};let o;try{o=e.terms(r)}catch(s){return{total:Tn*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:Tn*2,feasible:!1,terms:o,reason:"objective was not finite"}}var Ms=(e,t)=>!t||(e.feasible!==t.feasible?e.feasible:e.total<t.total);function of(e,t){return t.map((r,n)=>Math.min(e[n].hi,Math.max(e[n].lo,r)))}var vr=e=>e.map(t=>t.start);function gl(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 CT(e){let t=0;for(;t===0;)t=e();return Math.sqrt(-2*Math.log(t))*Math.cos(2*Math.PI*e())}function af(e,t){let{budget:r}=t,n=Math.max(1,Math.floor(t.progressEvery??1)),o=e.variables,a=d=>of(o,d.map((p,f)=>o[f].lo+p*(o[f].hi-o[f].lo))),s=d=>d.map((p,f)=>(p-o[f].lo)/(o[f].hi-o[f].lo)),i=0,c=0,l=null,u=null,m=[];return{vars:o,denorm:a,norm:s,evaluate:d=>{if(i>=r)return l?.total??Number.POSITIVE_INFINITY;i++;let p=d.map(g=>Math.min(1,Math.max(0,g))),f=Rr(e,a(p));f.feasible||c++;let b=Ms(f,l)?f:l;return b===f&&(l=f,u=p),m.push(b.total),t.onProgress&&(i%n===0||i===r)&&t.onProgress({evaluations:i,budget:r,x:a(u),score:b,infeasible:c}),f.total},left:()=>r-i,result:d=>({method:d,x:u?a(u):vr(o),score:l??Rr(e,vr(o)),evaluations:i,history:m,infeasible:c})}}var sf=(e,t,r,n=0,o)=>{let a=t?r.norm(vr(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 LR(e,t){let r=af(e,t),n=gl(t.seed??1),o=e.variables.length;for(r.evaluate(sf(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 Xo(e,t){let r=af(e,t),n=e.variables.length,o=gl(t.seed??1),a=1,s=2,i=.5,c=.5,l=sf(e,t.warmStart!==!1,r,t.startJitter,o),u=.25;for(;r.left()>0;){let m=[{u:l,f:r.evaluate(l)}];for(let h=0;h<n&&r.left()>0;h++){let d=l.slice();d[h]+=d[h]+u>1?-u:u,m.push({u:d,f:r.evaluate(d)})}for(;r.left()>0;){m.sort((g,y)=>g.f-y.f);let h=m[n],d=new Array(n).fill(0);for(let g=0;g<n;g++)for(let y=0;y<n;y++)d[y]+=m[g].u[y]/n;let p=g=>d.map((y,R)=>y+g*(y-h.u[R])),f=p(a),b=r.evaluate(f);if(b<m[0].f){let g=p(s),y=r.evaluate(g);m[n]=y<b?{u:g,f:y}:{u:f,f:b}}else if(b<m[n-1].f)m[n]={u:f,f:b};else{let g=p(-i),y=r.evaluate(g);if(y<h.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((h,d)=>h.f-d.f),l=m[0].u.map(h=>Math.min(1,Math.max(0,h+.05*(o()-.5)))),u=Math.max(.02,u*.5)}return r.result("nelder-mead")}function DR(e,t){let r=af(e,t),n=e.variables.length,o=gl(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,h=(4+l/n)/(n+4+2*l/n),d=(n+2)/3,p=Math.min(1,d*2/((n+1.3)**2+l)),f=Math.min(1-p,d*2*(l-2+1/l)/((n+2)**2+l)),b=Math.sqrt(n)*(1-1/(4*n)+1/(21*n*n)),g=sf(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(CT(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(),C=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],C[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)*C[S];let w=Math.sqrt(M.reduce((S,A)=>S+A*A,0)),T=w/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-h)*v[S]+T*Math.sqrt(h*(2-h)*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-p-f)*P+p*(v[S]*v[S]+(1-T)*h*(2-h)*P)+f*A*P;R[S]=Math.sqrt(Math.max(1e-12,L))}if(y*=Math.exp(u/m*(w/b-1)),y<1e-6||y>10)break}return r.result("sep-cma-es")}var qo=[{name:"random",run:LR},{name:"nelder-mead",run:Xo},{name:"sep-cma-es",run:DR}];var c4=Math.PI/180;var yl=Math.PI/180;var p4={Fz:100,alpha:.25*yl,kappa:.005,gamma:.5*yl,p:6900},ER={Fz:100,alpha:1*yl,kappa:.02,gamma:.5*yl,p:6900};var IR=Math.PI/180,y4={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:IR},gamma:{rad:1,deg:IR},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 M4=Math.PI/180;var BT=Math.PI/180;var P4=3*BT;var _4=Math.PI/180;var j4=Math.PI/180;var jT={RCX1:1,RCY1:1,REX1:0,REY1:0,RBY3:0,RHX1:0,RHY1:0},OR={RBX1:15,RBX2:15,RBY1:18,RBY2:19,...jT};var oK=Math.PI/180;var JT=Math.PI/180,xl=[{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"}],xK=new Map(xl.map(e=>[e.id,e]));var RK=.01*JT;var ze=Math.PI/180;var $R=new Set(xl.filter(e=>e.group!=="inputs"&&(e.unit==="N"||e.unit==="N\xB7m"||e.unit==="N/rad")).map(e=>e.id)),GR={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}},pf={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 df={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,...GR[t],...o}],x:t,y:r,...n}),Rl=(e,[t,r],n,o,a={})=>({id:e,form:"carpet",sweep:[{input:t,...pf[t]},{input:r,...pf[r]}],x:n,y:[o],...a}),kr=(e,t)=>({id:e,fixed:t}),Ot={input:"Fz",values:"car"},mf={alpha:0,kappa:0},ft={kappa:0},VR={alpha:0},rP={input:"Fz",values:[500,1e3,1500]},nP=[{id:"overview",name:"Overview",cards:[kr("tyre","tyre"),ke("fy","alpha",["Fy"],{title:"Lateral force",hold:ft}),ke("mz","alpha",["Mz"],{title:"Aligning moment",hold:ft}),ke("fx","kappa",["Fx"],{title:"Longitudinal force",hold:VR}),Rl("combined-carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),kr("ellipse","ellipse")]},{id:"lateral",name:"Lateral",cards:[ke("fy-load","alpha",["Fy"],{title:"Lateral force per wheel load",series:Ot,hold:ft}),ke("muy-load","alpha",["muY"],{title:"Lateral force per unit load",series:Ot,hold:ft}),ke("fy-peak","alpha",["Fy"],{title:"Lateral force over its peak",series:Ot,hold:ft,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:ft}),ke("trail","alpha",["t"],{title:"Pneumatic trail",series:Ot,hold:ft},{from:0,to:12*ze,n:49}),ke("mzr","alpha",["Mzr"],{title:"Residual aligning moment",series:Ot,hold:ft},{from:0,to:12*ze,n:49}),Rl("gough",["alpha","Fz"],"Fy","Mz",{title:"Gough plot",hold:ft}),ke("steering-feel","alpha",["t"],{title:"Steering feel",x:"FyRel",series:Ot,hold:ft},{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:VR}),ke("mux-peak","Fz",["muXPeak"],{title:"Peak longitudinal \u03BC over load"}),ke("kx","Fz",["dFxdk"],{title:"Slip stiffness at zero slip over load",hold:mf}),ke("kappa-peak","Fz",["kappaPeak"],{title:"Slip ratio at the peak over load"})]},{id:"combined",name:"Combined",cards:[Rl("carpet",["kappa","alpha"],"Fy","Fx",{title:"Combined-slip carpet"}),Rl("envelope-load",["kappa","alpha"],"Fy","Fx",{title:"Friction envelope per load",scale:{per:"Fz"},facet:rP}),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]}}),kr("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:ft}),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",...df.gamma},{input:"Fz",...df.Fz,follow:!0}],x:"gamma",y:["Fz"],z:"muYPeak"},ke("camber-stiffness","alpha",["dFydg"],{title:"Camber stiffness at the point",series:Ot,hold:ft}),ke("mx","alpha",["Mx"],{title:"Overturning moment",series:Ot,hold:ft})]},{id:"rolling",name:"Rolling and radius",cards:[ke("my","V",["My"],{title:"Rolling-resistance moment",series:Ot,hold:mf}),ke("radius","Fz",["R0","Rl","Re"],{title:"Radius over load"},{from:0}),ke("p-roll","V",["Proll"],{title:"Rolling power",series:Ot,hold:mf})]},{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:ft,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:[kr("operating","operating"),kr("wheels","wheels")]},{id:"fit",name:"Fit check",cards:[kr("fitLateral","fitLateral"),kr("fitLongitudinal","fitLongitudinal"),kr("fitCoupling","fitCoupling"),kr("fitEnvelope","fitEnvelope")]}];var uP=5670374e-14,ff=273.15,zR=.95,YR=60,vl=10,mP=.55,Mt=25,hf=-20,bf=50,As={tempC:[20,100,200,550,650,750],factor:[.8,.92,1,1,.85,.65]},Fs={discMassKg:.5,discOuterMm:220,specificHeatJPerKgK:460,emissivity:.6,coolingWPerM2K:200,padCurve:{tempC:[...As.tempC],factor:[...As.factor]}},kl={...Fs,discMassKg:.4,discOuterMm:200,padCurve:{tempC:[...As.tempC],factor:[...As.factor]}};function gf(e,t){let r=t==="front"?Fs:kl,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 pP=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},Ss=(e,t,r,n)=>Math.min(r,Math.max(t,pP(e,n)));function dP(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 yf(e,t){return{discMassKg:Ss(e?.discMassKg,.05,20,t.discMassKg),discOuterMm:Ss(e?.discOuterMm,50,600,t.discOuterMm),specificHeatJPerKgK:Ss(e?.specificHeatJPerKgK,100,3e3,t.specificHeatJPerKgK),emissivity:Ss(e?.emissivity,.02,1,t.emissivity),coolingWPerM2K:Ss(e?.coolingWPerM2K,vl,5e3,t.coolingWPerM2K),padCurve:dP(e?.padCurve,t.padCurve)}}function Ml(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 xf(e,t=1){let r=e.discMassKg*e.specificHeatJPerKgK,n=e.discOuterMm*.001/2,o=2*Math.PI*n*n,a=YR/3.6,s=e.emissivity*uP*o,i=m=>vl+(e.coolingWPerM2K-vl)*Math.pow(Math.max(0,m)*t/a,mP),c=(m,h,d)=>{let p=m+ff,f=d+ff;return i(h)*o*(m-d)+s*(p**4-f**4)},l=(m,h)=>i(h)*o+4*s*Math.max(0,m+ff)**3,u=(m,h)=>r/l(h,m);return{heatCapacityJPerK:r,areaM2:o,convectionAt:i,coolingW:c,timeConstantS:u,step(m,h,d,p,f){if(!(p>0))return m+h/r;let b=u(d,m+Math.max(0,h)/r),g=Math.max(1,Math.ceil(p/(.25*b))),y=p/g,R=h/g;for(let M=0;M<g;M++)m+=(R-c(m,d,f)*y)/r;return m},padFactor:m=>Ml(e.padCurve,m),window:WR(e.padCurve)}}function Sl(e,t,r,n,o,a,s=Mt){let i=n.length,c=new Array(i),l=new Array(i),u=new Array(i),m=zR/Math.max(1,t),h=a,d=h,p=0,f=0,b=0;for(let g=0;g<i;g++){let y=Math.max(0,r[g]??0);c[g]=h,l[g]=y*n[g],u[g]=e.padFactor(h);let R=y*(o[g]??0);p+=R,h<e.window.fromC?f+=R:h>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;h=e.step(h,m*R,v,x,s),h>d&&(d=h)}return{tempC:c,heatW:l,padFactor:u,startC:a,endC:h,maxC:d,workJ:p,coldWorkJ:f,hotWorkJ:b}}function WR(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])&&Ml(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 Rf=1e5,qR=.001,Pn={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},kf={fullAtBar:10,maxPowerKw:0,fadeBelowKmh:0,distribution:"equal"};var Mf=ZR(Fl(Pn,"Formula Student brakes")),Sf=40,QR={ideal:!1,barFront:Pn.barFront,pedalForceMaxN:0,testSpeedKmh:Sf,regen:kf};function jR(e){let{heat:t,...r}=e;return t?{...r,heat:{...t,padCurve:{tempC:[...t.padCurve.tempC],factor:[...t.padCurve.factor]}}}:r}function ZR(e){let t=(r,n)=>r.heat?r:{...r,heat:gf(r,n)};return{...e,front:t(e.front,"front"),rear:t(e.rear,"rear")}}function Fl(e,t){return{name:t,pedalRatio:e.pedalRatio,masterFrontMm:e.masterFrontMm,masterRearMm:e.masterRearMm,valve:e.valve,valveKneeBar:e.valveKneeBar,valveSlope:e.valveSlope,front:jR(e.front),rear:jR(e.rear),adjusterPitchMm:e.adjusterPitchMm,barLengthMm:e.barLengthMm}}function Af(e,t){return JR({...e,barFront:t.barFront,pedalForceMaxN:t.pedalForceMaxN})}function Ff(e,t){let r=Sr(t),n=e?tr(e):void 0;return{mode:r.ideal?"tyre":n?"hydraulic":"balance",hydraulic:n?Af(n,r):Pn,regen:r.regen}}var fP=["none","proportioning","limiter"],Al=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t},Je=(e,t,r,n)=>Math.min(r,Math.max(t,Al(e,n))),hP=(e,t)=>{let r=Al(e,t);return r>0?r:t};function UR(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(Al(e?.discs,n==="inboard"?1:t.discs)))),pistonsPerSide:Math.max(1,Math.min(6,Math.round(Al(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:yf(e.heat,t.heat??r)}:{}}}function JR(e){let t=Pn;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:fP.includes(e?.valve)?e?.valve:t.valve,valveKneeBar:Je(e?.valveKneeBar,0,200,t.valveKneeBar),valveSlope:Je(e?.valveSlope,0,1,t.valveSlope),front:UR(e?.front,t.front,Fs),rear:UR(e?.rear,t.rear,kl),adjusterPitchMm:hP(e?.adjusterPitchMm,t.adjusterPitchMm),barLengthMm:Je(e?.barLengthMm,0,500,t.barLengthMm)}}function bP(e){let t=kf;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=JR(e??void 0),r=typeof e?.name=="string"&&e.name.trim()?e.name:gP;return Fl(t,r)}function Sr(e){return{ideal:e?.ideal===!0,barFront:Je(e?.barFront,.05,.95,Pn.barFront),pedalForceMaxN:Je(e?.pedalForceMaxN,0,5e3,0),testSpeedKmh:Je(e?.testSpeedKmh,5,150,Sf),regen:bP(e?.regen)}}var gP="Formula Student brakes";var vf=e=>Math.PI/4*(e*qR)**2;function Zr(e,t){let r=e.pistonsPerSide*vf(e.pistonDiaMm)*Rf;return e.discs*2*e.padMu*r*e.effRadiusMm*qR*e.ratio/Math.max(.05,t)}function ev(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/vf(e.masterFrontMm)/Rf,o=(1-e.barFront)*r/vf(e.masterRearMm)/Rf;return{front:n,rearIn:o,rear:ev(e,o)}}function yP(e,t){let r=Cs(e,1);return{front:Zr(e.front,t)*r.front,rear:Zr(e.rear,t)*r.rearIn}}function ws(e,t){let r=yP(e,t);return r.front/Math.max(1e-12,r.front+r.rear)}function Ts(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=tv(t,l),m=t.maxPowerKw>0&&l>0?t.maxPowerKw*1e3/l:1/0,h=Math.max(0,e.fFront[c]),d=Math.max(0,e.fRear[c]),p=h+d>0?Math.min(1,m/(h+d)):1;r.push(l),n.push(h*p*u),o.push(d*p*u)}}function tv(e,t){let r=e.fadeBelowKmh/3.6;return r>0?Math.max(0,Math.min(1,t/r)):1}function Mr(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 XR=new WeakMap;function Ln(e){let t=XR.get(e);return t||(t=e.mode==="hydraulic"&&e.hydraulic?RP(e,e.hydraulic):xP(e),XR.set(e,t)),t}function xP(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 RP(e,t){let r=Zr(t.front,e.tyreRadiusM),n=Zr(t.rear,e.tyreRadiusM),o=e.regen,a=(c,l)=>{let u=Cs(t,c),m=0,h=0;if(o&&u.front>0){let d=o.fullAtBar>0?Math.min(1,u.front/o.fullAtBar):1;m=d*Mr(o.v,o.front,l),h=d*Mr(o.v,o.rear,l)}return{front:r*u.front+m,rear:n*u.rear+h,regenFront:m,regenRear:h,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 h=0;h<60;h++){let d=.5*(m+u);i(d,l)<c?m=d:u=d}return u}}}function Cf(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 Cl=cs,vP=.1,Dn=(e,t)=>e.a*Math.sqrt(Math.max(0,1-(t/Math.max(1e-9,e.b))**2));function wl(e,t,r){if(!(r>t))return t;let n=(Math.sqrt(5)-1)/2,o=t,a=r,s=a-n*(a-o),i=o+n*(a-o),c=e(s),l=e(i);for(let h=0;h<48;h++)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 h of[t,r]){let d=e(h);d>m&&(u=h,m=d)}return u}function Pf(e,t,r){let n=Math.max(0,r-Cl*t.b),o=Math.min(r,Cl*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 Lf(e,t,r,n,o=0){let a=Math.max(0,r),s=Pf(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],h=u.Fz/Math.max(1e-9,u.Fz+m.Fz),d=Math.max(0,Math.min(1,1-h/vP)),p=d>0&&a<Cl*m.b?m.cap(a):0,f=p>l?l+d*(p-l):0,b=Math.max(0,Math.min(u.slide,u.a)),g={xNoLock:l,xLock:f,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=wl(T=>{let S=Dn(e,T),A=Dn(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)),C=(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=C(i,c,T);if(!(a>0))return S;let A=I=>Cl*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=wl(I=>Math.min(y,Dn(e,I)-T)+Math.min(y,Dn(t,a-I)-T),P,L);return Math.max(S,C(e.cap(D),t.cap(a-D),T))}}}var wf=e=>Math.max(e.xNoLock,e.xLock),Tf=e=>Math.max(e.mixedMax,2*e.xLock);function Qo(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 Zo(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 Ps(e,t,r,n){return e.shares?kP(e,e.shares,t,r,n):MP(e,t,r,n)}function rv(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 kP(e,t,r,n,o){let a=Tf(r),s=Tf(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=Zo(r,t.front*b),y=Zo(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,h=[{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&&h.push({u:b,by:"front"})}if(n.xLock>n.xNoLock){let b=t.rear>0?n.mixedMax/t.rear:1/0;b<i&&h.push({u:b,by:"rear"})}let{cand:d,force:p}=rv(h,l),f=e.demand(d.u,o);return{force:Math.max(0,Number.isFinite(p)?p:0),control:d.u,demand:f,limitedBy:d.by,lockFront:f.front/2>r.mixedMax/2*(1+1e-9),lockRear:f.rear/2>n.mixedMax/2*(1+1e-9)}}function MP(e,t,r,n){let o=wf(t),a=wf(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 C=0;C<60;C++){let w=.5*(k+F);v(e.demand(w,n))?k=w:F=w}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),h=Number.isFinite(e.uMax)&&m>=e.uMax,d=v=>{let x=e.demand(v,n),k=Qo(t,s(x),x.regenFront),F=Qo(r,i(x),x.regenRear);return Number.isFinite(k)&&Number.isFinite(F)?k+F:-1/0},p=e.demand(m,n),f=o>0?s(p)/o:1/0,b=a>0?i(p)/a:1/0,g=[{u:m,by:h?"pedal":f>=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}=rv(g,d),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 Ar={regen:!0,regenEfficiency:.6};function Fr(e,t){let r=e.energy??t??Ar;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 nv(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 St(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 Tl(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 p=o+a>>1;e[p]<=r?o=p:a=p}if(o===n-1)return t[n-1];let s=p=>e[p+1]-e[p],i=p=>(t[p+1]-t[p])/s(p),c=p=>{if(p===0||p===n-1){let[y,R]=p===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 f=i(p-1),b=i(p),g=(f*s(p)+b*s(p-1))/(s(p-1)+s(p));return(Math.sign(f)+Math.sign(b))*Math.min(Math.abs(f),Math.abs(b),.5*Math.abs(g))},l=s(o),u=i(o),m=c(o),h=c(o+1),d=r-e[o];return t[o]+d*(m+d*((3*u-2*m-h)/l+d*(m+h-2*u)/(l*l)))}function Ls(e,t,r){return r.map(n=>St(e,t,n))}var Ds=e=>e.reduce((t,r)=>r>t?r:t,-1/0),Jo=e=>e.reduce((t,r)=>r<t?r:t,1/0);var SP=[-.906179845938664,-.538469310105683,0,.538469310105683,.906179845938664],AP=[.236926885056189,.478628670499366,.568888888888889,.478628670499366,.236926885056189];function Df(e,t,r){let n=.5*(r-t),o=.5*(t+r),a=0;for(let s=0;s<5;s++)a+=AP[s]*e(n*SP[s]+o);return n*a}var FP=Math.PI*2,CP=.5/3.6;function Es(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 Ef(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*FP;c[g]=y*o/n,l[g]=s[g]*n/o}let u=Ds(c),m=Cr(Jo(c),u,u/CP),h=Ls(c,l,m),{front:d,rear:p}=Es(t,r),f=h.map(g=>g*d),b=h.map(g=>g*p);return{vVehicle:m,fFront:f,fRear:b,vMax:u}}var ov=60/(2*Math.PI),av=.1,sv=.08,iv=0;function If(e){let t=(r,n)=>r===void 0||!Number.isFinite(r)?n:Math.max(0,r);return{up:t(e.upshiftTime,av),down:t(e.downshiftTime,sv)}}function _f(e){let t=e.driveKept;return t===void 0||!Number.isFinite(t)?iv:Math.max(0,Math.min(1,t))}function Nf(e,t,r){let{primary:n,ratios:o,efficiency:a}=e.gearbox,s=t>0&&r>0&&n>0,i=(b,g)=>b/ov*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)),h=(b,g)=>{let y=c[g];return y?b*y.ratio/r*ov:0},d=(b,g)=>g===0&&c.length>0&&b<c[0].vIdle,p=(b,g)=>{let y=c[g];return y?d(b,g)?m(e.idleRpm)*y.ratio*l/r:b<y.vIdle||b>y.vLimit?0:m(h(b,g))*y.ratio*l/r:0},f=(b,g)=>{let y=c[g];return!y||d(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:h,torque:m,force:p,inertiaMass:f,slipping:d}}function ea(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 Of(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 cv=9.81,lv=Math.PI*2;function At(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]*(lv/60),a[v]=t[v]/60*lv,s[v]=a[v]*u/l,i[v]=r[v]*l,c[v]=i[v]/u;let m=Ds(s),h=m,d=.5/3.6,p=Cr(Jo(s),m,m/d),f=Ls(s,c,p),b=Cr(Jo(t),Ds(t),250),g=Ls(t,o,b).map(v=>v*e.power_scale.value),y,R=h,M;if(e.motorModel?.kind==="ice"){M=Nf(e.motorModel,l,u);let v=Cr(0,M.vMax,Math.max(2,Math.ceil(M.vMax/d)+1)),x=v.map(C=>Of(M,C)),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=Ef(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:cv,FG:e.m.value*cv,vMax:R,vVehicle:p,fRad:f,uMotor:b,pMotor:g,vRad:s,fAxle:y,...M?{engine:M}:{}}}var Jr=e=>e.motorModel?.kind==="ice"?Es(1,e.motorPlacement==="front"?"front":"rear"):Es(Math.max(1,Math.round(e.motorCount??e.driven_wheels?.value??2)),e.motorPlacement??"rear");function uv(e){let t=Jr(e);return t.front>=2||t.rear>=2}function mv(e){return uv(e)?e.motorMount??"hub":"chassis"}function Vf(e){if(!e.motorModel)return{front:!1,rear:!0};let t=Jr(e);return{front:t.front>0,rear:t.rear>0}}function Bf(e){let t=Jr(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=mv(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 ct(e){return Ff(e.brakeModel,e.brakeSetup)}function Pl(e){return Sr(e.brakeSetup).ideal?"tyre":e.brakeModel||e.brakeModelId?"hydraulic":"balance"}function pv(e,t){if(!(ut(e.motorModel)||!Fr(e).regen))return Ts(Ll(At(e)),t??ct(e).regen)}function Ll(e){return e.fAxle??{vVehicle:e.vVehicle,fFront:e.vVehicle.map(()=>0),fRear:e.fRad.map(t=>t*e.params.driven_wheels.value)}}function $f(e,t=ct(e)){if(t.mode==="hydraulic")return ws(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 Gf(e,t=ct(e)){return{front:t.hydraulic.front.location==="inboard",rear:t.hydraulic.rear.location==="inboard"}}function Kf(e){let t=ct(e);return{brakeBalanceFront:$f(e,t),brakeInboard:Gf(e,t)}}function dv(e,t=ct(e)){if(t.mode==="tyre"||t.regen.distribution!=="wheel"||ut(e.motorModel))return;let r=Jr(e),n={front:r.front>=2,rear:r.rear>=2};return n.front||n.rear?n:void 0}function Is(e){let t=ct(e),r=e.r_dyn.value,n=Gf(e,t),o=$f(e,t),a=dv(e,t),s=t.mode==="hydraulic"||a?pv(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 TP=9.81;function Hf(e,t){if(ut(e.motorModel))return()=>0;let r=ct(e),n=Ts(t,r.regen);if(r.mode==="hydraulic"){let a=Ln({mode:"hydraulic",balanceFront:ws(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"?PP(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,Mr(n.v,n.front,s))+Math.min((1-c)*a,Mr(n.v,n.rear,s))}}function PP(e){let t=e.m.value*TP,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 fv(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 zf={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"},...fv("front"),...fv("rear")},Yf={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 Wf(e){let t=zf[e];return`${t.label}, ${t.section}`.toLowerCase()}function jf(e){let t=Yf[e];return t.section?`${t.section} ${t.label.charAt(0).toLowerCase()}${t.label.slice(1)}`:t.label}var hv=new WeakMap;function rr(e){if(e.brakes)return e.brakes;let t=hv.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},hv.set(e,t)}return t}var wr=e=>Ln(rr(e));var IP=Math.PI/180,ta=Object.freeze({tbr:1,preloadN:0}),Dl=Object.freeze({tbr:1/0,preloadN:0}),Xf=e=>e.faces*e.muClutch*e.rFrictionMm/e.rRampMm;function qf(e,t){if(!(e>0)||Number.isNaN(t))return 0;let r=Math.tan(Math.min(90,t)*IP);return r>0?Math.min(1,e/r):1}function gv(e){if(e>=1)return 1/0;let t=e>0?e:0;return(1+t)/(1-t)}function El(e){return e===1/0?1:e>1?(e-1)/(e+1):0}function ra(e,t){return e.tbr===1/0?1/0:(e.preloadN>0?e.preloadN:0)+El(e.tbr)*Math.abs(t)}function Ns(e,t,r){let n=o=>o!==void 0&&o>0&&r>0?o/r:0;switch(e.kind){case"open":return ta;case"spool":return Dl;case"independent":return t==="hubs"?ta:Dl;case"clutch":{let o=n(e.preloadNm);return t==="hubs"?{tbr:1,preloadN:o}:{tbr:gv(qf(Xf(e),t==="drive"?e.rampDriveDeg:e.rampCoastDeg)),preloadN:o}}case"torsen":{let o=n(e.preloadNm);if(t==="hubs")return{tbr:1,preloadN:o};let a=t==="drive"?e.tbrDrive:e.tbrCoast;return{tbr:a>1?a:1,preloadN:o}}}}function _s(e,t,r){let n=Math.max(0,Math.min(e,t)),o=Math.max(0,Math.max(e,t)),a=r.tbr>1?r.tbr:1,s=r.preloadN>0?r.preloadN:0;return a===1/0||s===1/0?n+o:n+Math.min(o,a*n+s*(1+a)/2)}var bv=4;function Uf(e,t){let r=0;for(let a of e)r=Math.max(r,_s(a.m1,a.m2,t));let n=t.tbr>1?t.tbr:1,o=(t.preloadN>0?t.preloadN:0)*(1+n)/2;if(n===1/0||o===1/0)return r;for(let a=0;a+1<e.length;a++){let s=e[a],i=e[a+1].m1-s.m1,c=e[a+1].m2-s.m2,l=h=>{h>0&&h<1&&(r=Math.max(r,_s(s.m1+h*i,s.m2+h*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 Os(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=Pf(e,t,c),u=l?2*Math.min(l.c1,l.c2):0;if(!l||s===1&&i===0||!(a>u))return Math.min(u,a);let m=wl(b=>Dn(e,b)+Dn(t,c-b),l.lo,l.hi),h=[{m1:l.c1,m2:l.c2}];for(let b=1;b<=bv&&m!==l.y1;b++){let g=l.y1+(m-l.y1)*b/bv;h.push({m1:e.cap(g),m2:t.cap(c-g)})}let d=Uf(h,ta),p=Uf(h,Dl);if(!(p>d))return u;let f=(Uf(h,{tbr:s,preloadN:i})-d)/(p-d);return Math.min(a,u+(a-u)*Math.min(1,Math.max(0,f)))}function yv(e,t,r,n,o,a){return Qf(e,o,Os(t,r,n,o,a))}function Qf(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 Zf(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,h=l-s,d=h!==0?i-l*(i-o)/h:NaN;m?d>Math.min(o,i)&&d<Math.max(o,i)||(d=.5*(o+i)):Number.isFinite(d)?Math.abs(d-i)>10*Math.abs(l)&&(d=i+Math.sign(d-i)*10*Math.abs(l)):d=c;let p=e(d),f=p-d;if(u++,m&&f<0==l<0?s*=.5:(o=i,s=l),i=d,c=p,l=f,s<0!=l<0&&Math.abs(i-o)<=r)break}return{x:i,fx:c,evals:u}}function xv(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),h=0;for(let d=o;l<a;d*=2){if(h=Math.min(h+d,m),h>m-n)return null;let p=t+u*h,f=e(p),b=f-p;if(l++,!(Math.abs(b)>n))return{x:p,fx:f,evals:l};if(c<0!=b<0)return vv(e,s,c,p,f,b,n,l,a);s=p,c=b}return null}function Rv(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 vv(e,o,s,c,u,m,r,l,n);if(l>=n)return{x:c,fx:u,evals:l};let h=Math.abs(c-o),d=s!==m?m*(c-o)/(s-m):NaN,p=d*i>0?Math.min(Math.abs(d),10*Math.abs(m),2*h):2*h;o=c,s=m,c+=i*p}}function vv(e,t,r,n,o,a,s,i,c){let l=t,u=r,m=n,h=a,d=n,p=o,f=0;for(;i<c&&Math.abs(m-l)>s;){d=(l*h-m*u)/(h-u),p=e(d);let b=p-d;if(i++,!(Math.abs(b)>s))break;b<0==u<0?(l=d,u=b,f===-1&&(h*=.5),f=-1):(m=d,h=b,f===1&&(u*=.5),f=1)}return{x:d,fx:p,evals:i}}function Il(e,t){return Math.abs(e.fx-e.x)>t?e.x:e.fx}var _P=(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:_P(e,t)?n.coast:n.hubs}var kv=e=>e.tbr>1||e.preloadN>0;var NP=9.81,Mv=["FL","FR","RL","RR"],Jf=e=>e==="FL"||e==="FR",_l=e=>Jf(e)?"front":"rear",Sv={front:["FL","FR"],rear:["RL","RR"]},$s=()=>({peak:new Map,freeBrake:new Map}),Bs=25;function Vs(e,t){let r=Math.max(0,e)/Bs,n=Math.floor(r),o=r-n,a=t(n);return o>0?a+o*(t(n+1)-a):a}var en=1e-4,OP=.05;function Tr(e,t,r,n=$s(),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=Uc(xe(t,S),Math.max(1,A*Bs)),i.set(P,L)),L},l=(S,A)=>({aPeak:Vs(A,P=>c(S,P).aPeak),fyPeak:Vs(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*Bs);L=kt(xe(t,S),D,0,!0,c(S,A)),u.set(P,L)}return L},h=(S,A)=>A>0?Vs(A,P=>m(S,P)):0,d=wr(e),p=rr(e),f=S=>p.regen&&p.regenPerWheel?.[S]?Mr(p.regen.v,p.regen[S],a)/2:0,b=f("front"),g=f("rear"),y=(S,A,P)=>{let L=Math.max(0,A[S]),D=l(_l(S),L);return kt(xe(t,_l(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(h(S,fe)),b:J.fyPeak,slide:fe>0?Math.abs(Y.forces({Fz:fe,kappa:-1,alpha:0}).Fx):0,cap:re=>Math.abs(kt(Y,fe,re,!0,J))}},G=te=>Math.abs(P[te])*l(_l(te),Math.max(0,A[te])).fyPeak,[O,W]=Sv[S],E=I(O),_=I(W),V=G(O)+G(W),N=Lf(E,_,V,L,S==="front"?b:g),$=D?N:{...N,xLock:0},K=Vt(e,S,-1),z=K&&kv(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=yv($,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=d.shares?Zo(A,L.front):Qo(A,(L.front-L.regenFront)/2,L.regenFront),I=d.shares?Zo(P,L.rear):Qo(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(h(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},C={front:e.trackFront/2e3,rear:e.trackRear/2e3},w=(S,A,P,L,D)=>{let I=L.cap,G=D.cap,O=Ps(d,I,G,a),W={arms:F,halfTrack:C,ayDir:Math.sign(S)};for(let E=0;E<2;E++){let _=v(O,I,G),V={};for(let $ of Mv){let K=Math.max(0,A[$]);V[$]={Fz:K,Fy:Math.abs(P[$])*l(_l($),K).fyPeak,Fx:-(Jf($)?_.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 Qf($.eq,$.law,hl(K,V,k,W))};I=N(L),G=N(D),O=Ps(d,I,G,a)}return{limit:O,front:I,rear:G}};return{peakAt:l,axle:M,ceiling:(S,A,P)=>{let[L,D]=Sv[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)/NP,a,0,A)}),G.loads),W=Xc(fe=>Ho(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=Ho(P,D,I,l).util;let re=0,pe=0,de=0;for(let ie of Mv){let oe=y(ie,D,E);re+=oe,Jf(ie)?pe+=oe:de+=oe}if(_={front:Math.abs(pe),rear:Math.abs(de)},d.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=w(S,D,E,ie,oe);V=ue.limit,N={front:ue.front,rear:ue.rear}}else V=Ps(d,ie.cap,oe.cap,a),N={front:ie.cap,rear:oe.cap};re=-V.force}return re/s},K=Zf($,0,en),z=Il(K,en),j=z;if(V?.lockFront||V?.lockRear){let fe=Zf(J=>$(J,!1),0,en);j=Il(fe,en);let Y=xv($,fe.x,K.x,en,OP);Y||$(K.x),z=Il(Y??K,en)}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 Ol=9.81;function VP(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 Cv=(e,t)=>t.mode==="hydraulic"&&!!rr(e).regen;function na(e,t,r=0,n,o=0){if(!e.brakes&&e.brakeBalanceFront==null)return e.frontMassFrac;let a=wr(e);if(a.shares&&a.mode!=="tyre")return a.shares.front;let s=n&&Cv(e,a)?wv(e,n):void 0,i=s?.shares??Av.get(e);i||Av.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=Tv(c,l,u),h=i.get(m);if(h===void 0){let d=-c*.005,p=l*.25,f=e.massTotal*Math.abs(d)*Ol;if(s){let b=Lv(a,Pv(e,s,c,l,u),f,p);h=b.front+b.rear>0?b.front/(b.front+b.rear):.5}else h=a.mode==="tyre"?VP(e,d,p):Cf(a,f,p);i.size>5e4&&i.clear(),i.set(m,h)}return h}var Av=new WeakMap;function Vl(e,t,r,n,o=0){let a=wr(e);if(!Cv(e,a))return;let s=Math.round(Math.max(0,r)/(e.massTotal*Ol)/.005),i=Math.round(Math.max(0,n)/.25);return Lv(a,Pv(e,wv(e,t),s,i,Math.round(o/.01)),Math.max(0,r),n)}var Fv=new WeakMap;function wv(e,t){let r=Fv.get(e);r||Fv.set(e,r=new WeakMap);let n=r.get(t);return n||r.set(t,n={ev:t,tyres:$s(),shares:new Map,rooms:new Map,speeds:new Map}),n}var Tv=(e,t,r)=>(r*1001+e)*100003+t;function Pv(e,t,r,n,o){let a=Tv(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:Tr(e,t.ev,i,t.tyres),dragG:-Math.max(0,Ha(e,i).drag)/(e.massTotal*Ol)},t.speeds.set(n,l));let{cap:u}=l,m=Le(e,c,-r*.005+l.dragG,i),h=Math.abs(c)*e.massTotal*Ol,d=b=>{let[g,y]=b==="front"?["FL","FR"]:["RL","RR"],R=h*(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)},p,f;s=(b,g)=>(b==="front"?p??=d("front"):f??=d("rear")).regenRoom(g),t.rooms.size>5e4&&t.rooms.clear(),t.rooms.set(a,s)}return s}function Nl(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 Lv(e,t,r,n){if(!(r>0))return Nl(e,t,1,n);let o=c=>c.front+c.rear,a=e.controlFor(r,n),s=Nl(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=Nl(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=Nl(e,t,l,n);o(u)<r?a=l:(i=l,s=u)}return s}var oa={rel:.003,abs:2,kappa:1e-5,iters:12},eh={rel:1e-6,abs:.001,kappa:1e-12,iters:40};function En(e,t,r,n=oa){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)),h=e(o*m),d=Math.abs(h.Fx)-a,p=null;for(;d<0&&m<.3;){let g=Math.min(.3,m*1.9),y=e(o*g),R=Math.abs(y.Fx);if(R<Math.abs(h.Fx)){p={kappa:g,forces:y};break}c=m,l=h,u=d,m=g,h=y,d=R-a}if(d<0){let g=GP(e,o,c,l,m,h,p),y=Math.abs(g.forces.Fx);if(y<a)return{kappa:o*g.kappa,forces:g.forces};m=g.kappa,h=g.forces,d=y-a}let f=h,b=o*m;for(let g=0;g<n.iters&&m-c>n.kappa;g++){let y=d-u,R=Math.abs(y)>1e-12?(c*d-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(f=M,b=o*R,Math.abs(v)<s)break;v<0?(c=R,u=v,d*=.5):(m=R,d=v,u*=.5)}return{kappa:b,forces:f}}var Dv=1e-6,BP=40,$P=(3-Math.sqrt(5))/2;function GP(e,t,r,n,o,a,s){let i=a,c,l,u,m=-Math.abs(a.Fx),h,d,p=-Math.abs(n.Fx);if(s){c=s.kappa;let g=-Math.abs(s.forces.Fx);[l,h,u,d]=g<=p?[c,g,r,p]:[r,p,c,g]}else{c=.3;let g=.3*(1-Dv),y=e(t*g),R=-Math.abs(y.Fx);if(R>=m)return{kappa:o,forces:a};[l,h,u,d]=[o,m,r,p],o=g,m=R,i=y}p<m&&([l,h]=[o,m],o=r,m=p,i=n);let f=c-r,b=0;for(let g=0;g<BP;g++){let y=Dv*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(f)>y){let F=(o-l)*(m-d),C=(o-u)*(m-h),w=(o-u)*C-(o-l)*F;C=2*(C-F),C>0&&(w=-w),C=Math.abs(C);let T=f;if(f=b,Math.abs(w)<Math.abs(.5*C*T)&&w>C*(r-o)&&w<C*(c-o)){b=w/C;let S=o+b;(S-r<2*y||c-S<2*y)&&(b=R>=o?y:-y),M=!1}}M&&(f=o>=R?r-o:c-o,b=$P*f);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,d=h,l=o,h=m,o=v,m=k,i=x):(v<o?r=v:c=v,k<=h||l===o?(u=l,d=h,l=v,h=k):(k<=d||u===o||u===l)&&(u=v,d=k))}return{kappa:o,forces:i}}var Bl=e=>Math.max(2,.003*Math.abs(e)),KP=(e,t)=>Math.max(t.abs,t.rel*Math.abs(e)),th=.5,HP=.03;function zP(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),C=t.at(k);return{kappaM:v,kl:x,kr:k,fl:F,fr:C,g:F.Fx+C.Fx-r}},i=KP(r,o),c=Math.max(-th,Math.min(th,n)),l=s(c);if(Math.abs(c)>HP){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,h=l,d=.004,p=l;for(let v=0;v<12;v++){let x=m.kappaM+u*d;if(Math.abs(x)>th)break;let k=s(x);if(Math.abs(k.g)<i)return k;if(Math.abs(k.g)<Math.abs(p.g)&&(p=k),Math.sign(k.g)!==Math.sign(m.g)){h=k;break}if(u*(k.g-m.g)<=0)return p;m=k,d*=1.9}if(h===l)return p;let f=m,b=h,g=f.g,y=b.g,R=Math.abs(g)<Math.abs(y)?f:b,M=Math.min(1e-7,o.kappa);for(let v=0;v<30&&Math.abs(b.kappaM-f.kappaM)>M;v++){let x=y-g,k=Math.abs(x)>1e-12?(f.kappaM*y-b.kappaM*g)/x:.5*(f.kappaM+b.kappaM),F=Math.min(f.kappaM,b.kappaM),C=Math.max(f.kappaM,b.kappaM);k>F&&k<C||(k=.5*(F+C));let w=s(k);if(R=w,Math.abs(w.g)<i)break;Math.sign(w.g)===Math.sign(g)?(f=w,g=w.g,y*=.5):(b=w,y=w.g,g*=.5)}return R}function Ev(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 rh(e,t,r,n,o,a=oa){let s=zP(e,t,r,o,a),i=s.fr.Fx-s.fl.Fx,c=ra(n,r);if(Math.abs(i)<=c){let R=r-(s.fl.Fx+s.fr.Fx),M=Math.max(0,Math.abs(R)-Bl(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,h=En(e.at,u,e.seed||s.kl,a),d=En(t.at,m,t.seed||s.kr,a),p=Math.abs(u-h.forces.Fx)>Bl(u),f=Math.abs(m-d.forces.Fx)>Bl(m),b=Math.max(0,n.preloadN),g=El(n.tbr);p&&!f?d=En(t.at,Ev(h.forces.Fx,l,b,g),d.kappa,a):f&&!p&&(h=En(e.at,Ev(d.forces.Fx,-l,b,g),h.kappa,a));let y=(R,M)=>({kappa:R.kappa,forces:R.forces,want:M,short:Math.max(0,Math.abs(M-R.forces.Fx)-Bl(M))});return{left:y(h,u),right:y(d,m),locked:!1,spoolKappa:s.kappaM}}var YP={front:["FL","FR"],rear:["RL","RR"]},WP=Object.freeze({Fx:0,Fy:0,Mz:0});function $l(e,t,r,n){let o=r;for(let a of["front","rear"]){let[s,i]=YP[a],c=r[s]+r[i],l=Vt(e,a,c);if(!l||!(ra(l,c)>0))continue;let u=xe(t,a),m=n.alpha[a],h=(a==="front"?e.trackFront:e.trackRear)/2e3,d=(f,b)=>{let g=Math.max(0,n.Fz[f]);return{at:g>0?y=>u.forces({Fz:g,kappa:y,alpha:m,gamma:0}):()=>WP,vx:Math.max(.05,1-b*n.curvature),seed:0}},p=rh(d(s,h),d(i,-h),c,l,n.seed?.[a]??0);n.seed&&(n.seed[a]=p.spoolKappa),o===r&&(o={...r}),o[s]=p.left.want,o[i]=p.right.want}return o}var Me=9.81,se=Math.PI/180,jP=8,UP=1e-6,rn=["FL","FR","RL","RR"],zt=e=>e==="FL"||e==="FR",tn=e=>zt(e)?"front":"rear";function Ks(e,t){let r=xe(e,"front"),n=xe(e,"rear");return r===n?_n(r,t):{front:_n(r,t),rear:_n(n,t)}}function _n(e,t){return Ud(e,Math.min(t,Ht(e)))}var Kl=e=>e==="FL"||e==="RL";function sa(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,na(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 lh(e,t,r,n){return Math.abs(Nn(e,t,r,n!==void 0?{steerMaxDeg:n}:{}).peak.steerDeg)}function uh(e,t,r,n){let o=e.tv;if(!o?.enabled)return 0;let a=e1(o)(t,Math.abs(r),n);return r<0?-a:a}function mh(e,t,r=0,n,o=0,a=0,s){let i=sa(e,{axG:t,driveFrontFrac:a},r,n,o),c=i?i.fx:{FL:0,FR:0,RL:0,RR:0};return i&&s&&n?$l(e,n,c,s):c}var Hs=e=>Kl(e)?-1:1,ph=(e,t,r,n,o)=>t*e.Fy(t*r,n,t*o);function ih(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 XP(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?Bo(o,n/se,u?r.FL:r.FR,u?r.FR:r.FL):$o(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)),h=Math.atan(s/(u+a/2));c=n+i*(m-n),l=n+i*(h-n)}return{innerMag:c,outerMag:l,innerCamber:0,outerCamber:0,atLock:!1}}function zs(e,t,r){let n=(e.toeFrontDeg??0)*se,o=(e.toeRearDeg??0)*se,a=XP(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 dh(e,t,r){if(r.Fz<=0)return 0;let n=it(xe(e,tn(t))),o=Hs(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 Iv(e,t,r,n){if(!wn(e))return null;let o=it(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:dh(o,s,i)}}return xs(e,r/se,a,qr(o.model),{FL:n.FL.travelMm,FR:n.FR.travelMm})}var _v=()=>({totalNm:[],aligningNm:[],lateralNm:[],longitudinalNm:[],jackingNm:[]});function Nv(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 qP=Object.freeze({Fx:0,Fy:0,Mz:0});function Ov(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&&ra(o,n)>0?{F:n,law:o}:null}function Ft(e,t,r,n,o,a,s,i,c){let l=s?.fx,u=s?.axG??0,{wb:m,lf:h,lr:d,m:p}=ih(e),f=Ov(e,"front",l),b=Ov(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=it(xe(t,"front")),v=it(xe(t,"rear")),x=e.trackFront/2e3,k=e.trackRear/2e3,F=!!(e.kinFront&&e.kinRear),C=F&&y===null?jo(e,e.kinFront,e.kinRear,r):null,w=NaN,T=null,S=Y=>{if(!F)return null;if(y===null)return C;let J=R(Y);return J!==w&&(w=J,T=jo(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+h*J/r:n+h/y,pe=y===null?n-d*J/r:n-d/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=Wc(e,Y/Me,u,ie,n/se,o/se,ue,oe?.steeringJacking),Ae=Ve.loads;E=Ve.overturned;let le=zs(e,o,ue),Re=le.steer,Ce=0,Ge=be=>{let Fe=Math.max(0,Ae[be]),ye=Hs(be),me=zt(be)?M:v,Te=O(be),Se=0,Ke=0;if(Te){let yn=W[be];Se=Te.toePerFy*yn.fy+Te.toePerFx*yn.fx+Te.toePerMz*yn.mz,Ke=Te.camberPerFy*yn.fy+Te.camberPerFx*yn.fx}let je=Re[be]+(oe?ye*oe[be].bumpToe*se:0)+ye*Se*se,Gt=je-(zt(be)?re:pe),gn=(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:gn}},We=(be,Fe)=>{let ye=y===null?J/r:1/y,me=zt(be)?h:-d,Te=(Kl(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}):()=>qP,vx:Math.max(.05,Se),seed:P[be]}};for(let be=0;be<(I?jP:1);be++){Ce=0;let Fe=0,ye={};for(let me of rn){let Te=zt(me)?f:b;if(Te&&!ye[me]){let[Ro,Dt]=zt(me)?["FL","FR"]:["RL","RR"],hc=Ge(Ro),$0=Ge(Dt),G0=tn(me),mp=rh(We(Ro,hc),We(Dt,$0),Te.F,Te.law,g[G0],eh);g[G0]=mp.spoolKappa,ye[Ro]={w:hc,share:mp.left},ye[Dt]={w:$0,share:mp.right}}let Se=ye[me]?.w??Ge(me),{Fz:Ke,mir:je,t:Gt,gains:gn,complianceToe:yn,steerK:ip,slip:cp,camberRad:lp}=Se,$a=l?.[me]??0,go,yo=0,up=0,fc=0,xo=ye[me]?.share;if(xo)P[me]=xo.kappa,up=xo.kappa,yo=xo.forces.Fx,fc=xo.short,go=je*xo.forces.Fy;else if($a===0||Ke<=0)go=ph(Gt,je,cp,Ke,lp),fc=Ke<=0?Math.abs($a):0;else{let Dt=En(hc=>Gt.forces({Fz:Ke,kappa:hc,alpha:je*cp,gamma:je*lp}),$a,P[me],eh);P[me]=Dt.kappa,up=Dt.kappa,yo=Dt.forces.Fx,fc=Math.max(0,Math.abs($a-yo)-Math.max(oa.abs,oa.rel*Math.abs($a))),go=je*Dt.forces.Fy}if(A[me]={Fz:Ke,travelMm:oe?.[me].travel??0,steerRad:ip,slipRad:cp,camberRad:lp,Fy:go,Fx:yo,kappa:up,fxShort:fc,lifted:Ve.lifted[me]},gn){let Ro=G&&gn.toePerMz?dh(Gt,me,A[me]):0;W[me]={fy:-je*go,fx:yo,mz:-je*Ro*1e3};let Dt=W[me];Fe=Math.max(Fe,Math.abs(gn.toePerFy*Dt.fy+gn.toePerFx*Dt.fx+gn.toePerMz*Dt.mz-yn))}Ce+=go*Math.cos(ip)+yo*Math.sin(ip)}if(Fe<UP)break}return Ce/p},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)/p);if(y!==null){N=4*Me;for(let Y=0;Y<8;Y++){let J=Math.min(40*Me,3.5*V(R(N))/p);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),Ce=Math.min(de,ie),Ge=Math.max(de,ie);Re>Ce&&Re<Ge||(Re=.5*(de+ie));let We=$(Re);if(Ve=Re,Math.abs(We)<1e-4||Ge-Ce<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/d),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=h*(A.FL.Fy*Math.cos(A.FL.steerRad)+A.FR.Fy*Math.cos(A.FR.steerRad))-d*(A.RL.Fy+A.RR.Fy);if(s||f||b){let Y=J=>(Kl(J)?1:-1)*(zt(J)?x:k);for(let J of rn){let re=A[J],pe=zt(J)?h:-d;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/(p*Me*m),wheels:A,overturned:E,res:te-Q}}function QP(e,t,r,n,o,a,s,i=0){let c=20*se,l=.001,u=(f,b)=>{let g=Ft(e,t,r,f,n,b,s);return{cn:g.cn-i,ay:g.ay*Me}},m=f=>n===0||i!==0||Math.abs(f)<.05||Math.sign(f)===Math.sign(n),h=(f,b,g,y)=>{let R=u(f,y);if(Math.abs(R.cn)<1e-5)return{beta:f,trimmed:!0};let M=y===void 0?void 0:R.ay,v={pos:{b:f,cn:R.cn,ay:M},neg:{b:f,cn:R.cn,ay:M}},x=null,k=f,F=Math.abs(R.cn);for(let C=0;C<b.length&&!x;C++)for(let w of[v.pos,v.neg]){let T=w===v.pos?1:-1,S=f+T*b[C];if(Math.abs(S)>c)continue;let A=u(S,w.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!=w.cn<0){let P={lo:w.b,hi:S,ayLo:w.ay},L=Vv(u,P),D=u(L,w.ay);if(Math.abs(D.cn)<l&&m(D.ay))return x=P,{beta:L,trimmed:!0}}w.b=S,w.cn=A.cn,y!==void 0&&(w.ay=A.ay)}return x?{beta:Vv(u,x),trimmed:!0}:g?{beta:k,trimmed:!1}:null},d=[.25,.75,2,5].map(f=>f*se);if(o!==void 0&&Number.isFinite(o)&&Math.abs(o)<=c){let f=h(o,d,!1,a);if(f)return f;if(!s&&i===0&&a!==void 0&&Number.isFinite(a)){let b=ZP(e,t,r,n,o,a,c);if(b&&m(b.ay))return{beta:b.beta,trimmed:!0,ay:b.ay}}}let p=[1,3,7,15,20].map(f=>f*se).filter(f=>f<=c);return h(0,p,!0)??{beta:0,trimmed:!1}}function Vv(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),h=m.cn;if(o!==void 0&&(o=m.ay),i=u,Math.abs(h)<1e-5||Math.abs(n-r)<1e-5)break;h<0==a<0?(r=u,a=h,s*=.5):(n=u,s=h,a*=.5)}return i}function ZP(e,t,r,n,o,a,s){let i=(h,d)=>{let p=Ft(e,t,r,h,n,void 0,null,void 0,d);return{r:p.res,c:p.cn}},c=o,l=a,u=i(c,l),m=0;for(let h=0;h<JP;h++){let d=i(c+nh,l),p=i(c,l+oh),f=(d.r-u.r)/nh,b=(p.r-u.r)/oh,g=(d.c-u.c)/nh,y=(p.c-u.c)/oh,R=f*y-b*g;if(!Number.isFinite(R)||R===0||Math.abs(R)<nL*(Math.abs(f*y)+Math.abs(b*g)))return null;if(h===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*f)/R,x=Math.min(1,eL/Math.max(Math.abs(M),1e-300),tL/Math.max(Math.abs(v),1e-300));if(c+=x*M,l+=x*v,Math.abs(c-o)>rL||Math.abs(c)>s||l*a<0)return null;u=i(c,l)}return null}var JP=8,nh=1e-5,oh=.001,eL=1*se,tL=2,rL=5*se,nL=.5;function Yv(e,t,r,n,o,a,s,i){let c=Ft(e,t,r,n,o,a,s,void 0,i),l=c.ay*Me/r,u={},m=0;for(let p of rn){let f=c.wheels[p],b=xe(t,tn(p)),g=Ht(b),y=b.muY(Math.min(f.Fz,g)),R=b.muX(Math.min(f.Fz,g));m+=f.fxShort,u[p]={Fz:f.Fz,steerDeg:f.steerRad/se,slipDeg:f.slipRad/se,camberDeg:f.camberRad/se,Fy:f.Fy,Fx:f.Fx,Mz:dh(b,p,f),gripUtil:y*f.Fz>0?Math.hypot(f.Fy/(y*f.Fz),R*f.Fz>0?f.Fx/(R*f.Fz):0):0,...f.Fz>g?{pastTurnover:!0}:{},lifted:f.lifted}}let h=xs(e,o/se,u,qr(xe(t,"front").model),{FL:c.wheels.FL.travelMm,FR:c.wheels.FR.travelMm}),d=zs(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,...d.atLock?{lockDeg:(d.steer.FL+d.steer.FR)/2/se}:{},converged:!0,trimmed:!c.overturned,overturned:c.overturned,driving:!1,fxShortfall:m,...h?{steering:h}:{}}}function Lr(e,t,r,n,o,a,s=0){let i=Math.max(8,r),c=In(e,t,i,n,o,a,s);return n!==0&&o?.driving===void 0&&(c.driving=yL(e,t,i,c,a,s)),c}function In(e,t,r,n,o,a,s){let i=n*se,c=sa(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:h,ay:d}=QP(e,t,r,i,u,l,c,s),p=Yv(e,t,r,m,i,l,c,d),f={...p,trimmed:h&&!p.overturned};return f.driving=n===0?f.trimmed:o?.driving!==void 0&&o.driving&&f.trimmed&&Math.abs(f.beta-o.beta)<=oL,f}var oL=3;function Nn(e,t,r,n={}){let o=Math.max(8,r),a=n.direction??1,s=n.yawDemandCn??0,i=n.steerMaxDeg??aL,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=ah.get(e)?.get(t)?.get(l);if(x)return x}let u=(x,k)=>k.trimmed&&Math.abs(k.beta-x.beta)<=Hl&&Math.abs(k.ay-x.ay)*Me<=zl,m=!1,h=(x,k)=>{let F=In(e,t,o,a*x,k,c(a*x),s);return u(k,F)?(F.driving=!0,F):(m=F.overturned,null)},d=[In(e,t,o,0,void 0,c(0),s)],p=null,f=!1,b,g=x=>{let k=d.length-1;for(;k>1&&x.sb*(d[k].beta-d[k-1].beta)>=0;)k--;let F=a*(x.state.ay-d[k].ay)>0,C=w=>x.sb*(w.beta-x.state.beta)>0||a*w.steerDeg>=a*x.state.steerDeg||F&&a*w.ay>=a*x.state.ay;for(;d.length>Math.max(2,k)&&C(d[d.length-1]);)d.pop();b={state:x.state,stall:d[d.length-1]},d.push(x.state),p=Math.abs(x.state.steerDeg)},y=(x,k=!1)=>k||hL(d[d.length-1],x)?bL(e,t,o,a,d,x,c,s):null,R=d[0].trimmed?d[0]:null;if(!R){let x=0;for(let k=Bv;k<=i&&!R;k+=Bv){let F=In(e,t,o,a*k,void 0,c(a*k),s);if(F.trimmed){let C=k;R=F;for(let w=0;w<6;w++){let T=.5*(x+C),S=In(e,t,o,a*T,void 0,c(a*T),s);S.trimmed?(C=T,R=S):x=T}}else x=k}R&&(R.driving=!0,d.push(R))}if(R){let x=Math.abs(R.steerDeg),k=Math.min(sh,100/(o*o)),F=R;for(;x<i;){let C=Math.min(i,x+k),w=h(C,F);if(w){let L=y(w);if(L){g(L);break}if(d.push(w),C>=i||Jv(e,a*C))break;Math.abs(w.beta-F.beta)<.5*Hl&&Math.abs(w.ay-F.ay)*Me<.5*zl&&(k=Math.min(sh,1.5*k)),x=C,F=w;continue}if(k>sL){k*=.5;continue}let T=m,S=!1,A=null;for(let L of iL){let D=Math.min(i,x+L);if(D<=x)continue;let I=h(D,F);if(I){if(A=y(I,!0),A)break;d.push(I),x=D,F=I,k=Math.min(sh,100/(o*o)),S=!0;break}}if(S)continue;if(A){g(A);break}p=x,f=T;let P=T?null:fL(e,t,o,a,d,c,s);P&&g(P);break}}else p=0;let M=d[0];for(let x of d)a*x.ay>a*M.ay&&(M=x);let v={states:d,foldDeg:p,rollover:f,peak:M,...b?{fold:b}:{}};if(l!==null){let x=ah.get(e);x||(x=new WeakMap,ah.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 ah=new WeakMap,aL=90,Hl=1.5,zl=2.5,sh=5,sL=.002,iL=[.5,1],Bv=2.5,Wv=.01,Pr=.001,cL=.05,lL=.25,uL=5,mL=2,$v=1e-8,pL=1e-7,dL=1e-6;function jv(e,t,r,n,o,a,s){let i=n*se,c=o.ay*Me,l=b=>{let g=Ft(e,t,r,i,b*se,c,sa(e,a(b),r,t));return{g:g.cn-s,ay:g.ay}},u=o.steerDeg,m=l(u),h=u+(u<0?-.001:.001),d=l(h),p=()=>d.g===0||Math.abs(h-u)<$v;for(let b=0;b<40&&Math.sign(m.g)===Math.sign(d.g)&&!p();b++){let g=(d.g-m.g)/(h-u),y=g!==0?h-d.g/g:h+2*(h-u);if(!Number.isFinite(y))return null;let R=2*Math.abs(h-u)+.001;if(y=h+Math.max(-R,Math.min(R,y-h)),u=h,m=d,h=y,d=l(h),Math.abs(h-o.steerDeg)>mL)return null}let f={x:h,ay:d.ay};if(Math.sign(m.g)!==Math.sign(d.g)){let b=u,g=m.g,y=h,R=d.g;for(let M=0;M<60&&R!==0&&Math.abs(y-b)>$v;M++){let v=(b*R-y*g)/(R-g),x=l(v);if(f={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(!p())return null;return Math.abs(f.ay-o.ay)*Me>zl?null:{steerDeg:f.x,ay:f.ay}}function Gs(e,t,r,n,o){let a=Yv(e,t,r,n.beta*se,n.steerDeg*se,n.ay*Me,sa(e,o(n.steerDeg),r,t));return{...a,trimmed:!a.overturned,driving:!a.overturned}}function fL(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 h=Uv(e,t,r,a,s),d=h(u.beta,u),p=h(c.beta,c);if(!d||!p)return null;let f=n*p.steerDeg>=n*d.steerDeg,b=f?d:p,g=f?p:d,y=f?m:-m,R=null;for(let x=Wv;Math.abs(g.beta-c.beta)<=Hl;x*=1.5){let k=h(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=Xv(h,n,b,g,R);if(!M)return null;let v=Gs(e,t,r,M,a);return!v.trimmed||Math.abs(v.beta-c.beta)>Hl||Math.abs(v.ay-c.ay)*Me>zl?null:{state:v,sb:m}}function Uv(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=jv(e,t,r,s,i,n,o);if(!c)return null;let l={beta:s,...c};return a.push(l),l}}function hL(e,t){let r=Math.abs(t.beta-e.beta);return r>lL&&r>uL*Math.abs(t.steerDeg-e.steerDeg)}function bL(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],h=Math.sign(a.beta-l.beta);if(h===0||Math.sign(l.beta-m.beta)!==h||!m.driving)return null;let d=Uv(e,t,r,s,i),p=d(m.beta,m),f=d(l.beta,l);if(!p||!f||n*f.steerDeg<n*p.steerDeg)return null;let b=p,g=f,y=null;for(let R=Wv;h*(a.beta-g.beta)>0;R=Math.min(cL,1.5*R)){let M=d(h*(a.beta-g.beta)>R?g.beta+h*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=Xv(d,n,...y);if(!x)return null;let k=Gs(e,t,r,x,s);return k.trimmed?{state:k,sb:h}:null}b=g,g=M}return null}function Xv(e,t,r,n,o){let a=d=>-t*d.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,h=0;for(let d=0;d<100;d++){let p=.5*(s+i);if(Math.abs(c.beta-p)<=2*Pr-.5*(i-s))break;let f=!0;if(Math.abs(m)>Pr){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=h,Math.abs(R)<Math.abs(.5*y*M)&&R>y*(s-c.beta)&&R<y*(i-c.beta)){h=R/y;let v=c.beta+h;(v-s<2*Pr||i-v<2*Pr)&&(h=p>=c.beta?Pr:-Pr),f=!1}}f&&(m=c.beta>=p?s-c.beta:i-c.beta,h=Qv*m);let b=e(Math.abs(h)>=Pr?c.beta+h:c.beta+(h>=0?Pr:-Pr));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 fh(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],h=u[u.length-1],d=l(m),p=l(h);if(d>0||p<0)return null;if(p===0)return Gs(e,t,r,h,i);let f=m;for(let b=0;b<60&&Math.abs(h.beta-m.beta)>1e-9;b++){let g=(m.beta*p-h.beta*d)/(p-d),y=u[0];for(let x of u)Math.abs(x.beta-g)<Math.abs(y.beta-g)&&(y=x);let R=jv(e,t,r,g,y,i,c);if(!R)return null;let M={beta:g,...R};u.push(M),f=M;let v=l(M);if(Math.abs(v)<("steerDeg"in a?pL:dL))break;v<0?(m=M,d=v,p*=.5):(h=M,p=v,d*=.5)}return Gs(e,t,r,f,i)}function gL(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 fh(e,t,r,n.fold,a,{steerDeg:o});let u=typeof a.op=="function"?a.op(o):a.op,m=In(e,t,r,o,l,u,a.yawDemandCn??0);return m.driving?m:null}function yL(e,t,r,n,o,a){if(!n.trimmed)return!1;let s=n.steerDeg<0?-1:1,{states:i}=Nn(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)],h=Math.abs(m.steerDeg)-Math.abs(u.steerDeg),d=h>0?Math.min(1,Math.max(0,(c-Math.abs(u.steerDeg))/h)):0,p=u.beta+d*(m.beta-u.beta),f=u.ay+d*(m.ay-u.ay);return Math.abs(n.beta-p)<=1&&Math.abs(n.ay-f)<=.05}function nn(e,t,r,n,o){let a=Math.max(8,r),s=n>=0?1:-1,i=Math.abs(n),c=(b,g)=>Lr(e,t,a,s*b,g,o),l=Nn(e,t,a,{direction:s,op:o}),{fold:u}=l;if(u&&Math.abs(u.state.steerDeg)<=aa){if(i>Math.abs(u.state.ay))return Kv(e,t,a,s,i,o);if(i>Math.abs(u.stall.ay)){let b=fh(e,t,a,u,{direction:s,op:o},{ayG:i});if(b)return b}}let m=l.states.filter(b=>Math.abs(b.steerDeg)<=aa),h=m[m.length-1],d=l.states.length>m.length;d&&Math.abs(h.steerDeg)<aa&&m.push(c(aa,h));let p=m.findIndex(b=>Math.abs(b.ay)>=i);if(p===0)return Lr(e,t,a,0,void 0,o);if(p>0)return Gv(m[p-1],m[p],i,c);let f=qv(m,c,void 0,d||l.foldDeg===null);return f.ay>=i?Gv(f.below,f.state,i,c):l.foldDeg!==null&&l.foldDeg<aa?Kv(e,t,a,s,i,o):f.state}var aa=20;function Gv(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 h=a.f===o.f?.5*(o.steer+a.steer):o.steer-o.f*(a.steer-o.steer)/(a.f-o.f),d=n(h,i),p=Math.abs(d.ay)-r;if(Math.abs(p)<u&&(l=d,u=Math.abs(p)),Math.abs(p)<=xL||a.steer-o.steer<=RL)break;p<0?(o={steer:h,f:p},c===-1&&(a.f*=.5),c=-1):(a={steer:h,f:p},c===1&&(o.f*=.5),c=1)}return l}var xL=1e-9,RL=1e-7;function qv(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=vL/4,c,l,u,m,h,d,p,f,b=null,g;if(o>0&&o<e.length-1){let x=e[o+1];g=C=>{if(C<s)return t(C,a);let w=t(C,e[o]);return w.ay===e[o].ay?t(C,a):w},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];h=Math.abs(k.steerDeg),d=-Math.abs(k.ay),p=Math.abs(F.steerDeg),f=-Math.abs(F.ay)}else{let x=Math.abs(e[o].lockDeg??e[o].steerDeg),k=x-kL,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 C=t(s,a);return{state:C,below:a,ay:Math.abs(C.ay)}}g=C=>t(C,a),c=Math.abs(a.steerDeg),l=x,u=k,m=-Math.abs(F.ay),b=F,h=x,d=-Math.abs(e[o].ay),p=c,f=-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-h)*(m-f),A=(u-p)*(m-d),P=(u-p)*A-(u-h)*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=Qv*y);let C=Math.abs(R)>=i?u+R:u+(R>=0?i:-i),w=g(C),T=-Math.abs(w.ay);T<=m?(C>=u?c=u:l=u,p=h,f=d,h=u,d=m,u=C,m=T,b=w):(C<u?c=C:l=C,T<=d||h===u?(p=h,f=d,h=C,d=T):(T<=f||p===u||p===h)&&(p=C,f=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 vL=.001,kL=.01,Qv=(3-Math.sqrt(5))/2;function Kv(e,t,r,n,o,a){let s=l=>Math.abs(Lr(e,t,r,n*l,void 0,a).ay),i=0,c=aa;if(s(c)<o)return Lr(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 Lr(e,t,r,n*.5*(i+c),void 0,a)}function hh(e,t,r,n,o){let a=nn(e,t,r,n,o);return a.steering?Math.abs(a.steering.totalNm):NaN}function bh(e,t,r,n,o){if(!wn(e))return NaN;let a=n<0?-1:1,s=Math.abs(n),i=nn(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,h=Lr(e,t,r,a*u,void 0,o),d=Lr(e,t,r,a*m,void 0,o),p=h.steering?Math.abs(h.steering.totalNm):NaN,f=d.steering?Math.abs(d.steering.totalNm):NaN,b=Math.abs(d.ay)-Math.abs(h.ay);if(Number.isFinite(p)&&Number.isFinite(f)&&b>=.01||l===.4&&Number.isFinite(p)&&Number.isFinite(f)&&b>.001)return(f-p)/b}return NaN}function ch(e,t,r,n,o,a){let s=Math.max(8,r),i=Ft(e,t,s,n*se,o*se,void 0,sa(e,a,s,t));return{ay:i.ay,cn:i.cn}}function gh(e,t,r,n,o){let a=Math.max(8,r),s=nn(e,t,a,n,o),i=.5,c=ch(e,t,a,s.beta+i,s.steerDeg,o).cn,l=ch(e,t,a,s.beta-i,s.steerDeg,o).cn;return(c-l)/(2*i*se)*e.massTotal*Me*(e.wheelbase/1e3)}function yh(e,t,r,n){let o=Math.max(8,r),{branch:a,opts:s}=ML(e,t,o,n);return Zv(e,t,o,a,s)}function ML(e,t,r,n){if(!e.tv?.enabled){let s=n?{op:n}:{};return{branch:Nn(e,t,r,s),opts:s}}let o=lh(e,t,r),a={op:s=>{let i=uh(e,r,s,o);return i===0?n:{axG:n?.axG??0,driveFrontFrac:n?.driveFrontFrac,tvRearDiffN:i}}};return{branch:Nn(e,t,r,a),opts:a}}function Zv(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 Gs(e,t,r,n.peak,a);let i=(l,u)=>In(e,t,r,l,u,a(l),s),c=n.states[0].driving||!n.peak.driving?n.states:n.states.slice(1);return qv(c,i,c.indexOf(n.peak),n.foldDeg===null).state}function xh(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:h,lr:d}=ih(e),p=o===void 0?0:d/o,f=o===void 0?0:(h+d)/o,b=n.nLines??9,g=n.nPts??21,y=n.steering!==!1&&wn(e),R=y?qr(xe(t,"front").model):void 0,M=(E,_,V,N)=>V===1?E:E+(_-E)*N/(V-1),v=e.tv?.enabled?lh(e,t,a):0,x=E=>{let _=uh(e,a,E/se,v);return!n.axG&&_===0?null:sa(e,{axG:n.axG??0,driveFrontFrac:n.driveFrontFrac,tvRearDiffN:_},a,t)},{lf:k,lr:F}=ih(e),C=n.reserves?Ks(t,e.massTotal*Me*1.2):null,w=E=>C?yr(C,{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=C?{stabil:[],agil:[]}:void 0,Q=y?_v():void 0,ne;for(let Y=0;Y<g;Y++){let J=M(c,l,g,Y),re=Ft(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=w(re.wheels);j.stabil.push(pe.stabil),j.agil.push(pe.agil)}Q&&Nv(Q,Iv(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])-p/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=C?{stabil:[],agil:[]}:void 0,j=y?_v():void 0,Q;for(let ne=0;ne<g;ne++){let te=M(u,m,g,ne),fe=Ft(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=w(fe.wheels);z.stabil.push(Y.stabil),z.agil.push(Y.agil)}j&&Nv(j,Iv(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(f),I,G;if(o===void 0)I=(Ft(e,t,a,p+L,f,void 0,D,o).cn-Ft(e,t,a,p-L,f,void 0,D,o).cn)/(2*L),G=(Ft(e,t,a,p,f+L,void 0,x(f+L),o).cn-Ft(e,t,a,p,f-L,void 0,x(f-L),o).cn)/(2*L);else{let E=(N,$)=>Ft(e,t,a,N,$,void 0,x($),o).cn,_=(N,$,K)=>Number.isFinite(N)?(-3*N+4*$-K)/(2*L):(K-$)/L,V=E(p,f);I=-_(V,E(p-L,f),E(p-2*L,f)),G=_(V,E(p,f+L),E(p,f+2*L))}let O=0;if(D&&D.axG){let E=Ft(e,t,a,p,f,void 0,D,o),_=0;for(let V of rn)_+=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 Jv(e,t){return zs(e,t*se).atLock}function SL(e,t,r,n,o=Tr(e,t,r)){let a=r,s=e.massTotal,i=rn.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*Bs);M=kt(xe(t,g),v,0,!1,c(g,v)),u.set(R,M)}return M},h=(g,y)=>y>0?Vs(y,R=>m(g,R)):0,d=(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:h(g,I),b:G.fyPeak,slide:0,cap:O=>I>0?kt(v,I,O,!1,G):0}},[k,F]=g==="front"?["FL","FR"]:["RL","RR"],C=x(k),w=x(F),T=M[k]*C.b,S=M[F]*w.b,A=C.cap(T)+w.cap(S),P=Os(C,w,T+S,y,A);return{l:k,r:F,full:P,asHeld:()=>({axle:g,strong:C.cap(T)>=w.cap(S)?k:F,full:P,open:Os(C,w,T+S,ta,A),sense:1})}},p=g=>({muX:y=>y>0?h(g,y)/y:0,muY:y=>y>0?c(g,y).fyPeak/y:0}),f={front:p("front"),rear:p("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),C=Xc(P=>Ho(R,F(P),x,c).short,-M,1),w=R,T=P=>{let L=C.at(P);v=F(L),w=Ho(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[tn(G)];if(O){if(Kl(G)){let V=d(tn(G),O,v,w);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(tn(G),W),_=kt(xe(t,tn(G)),W,w[G]*E.fyPeak,!1,E);D+=_,I&&(I.fx[G]=_)}if(I){let G={};for(let O of rn){let W=Math.max(0,v[O]);G[O]={Fz:W,Fy:w[O]*c(tn(O),W).fyPeak,Fx:I.fx[O]}}for(let O of I.axles)D+=hl(O,G,f,b(g))-O.full}return D/s},S=Rv(T,-M,en).fx,A=C.edge();return A!==void 0&&S>A&&(S=A,T(S)),{ax:S,loads:v}}}}var Gl=.05,Hv=.001,zv=16,Yl=8;function Rh(e,t,r,n){let o=Math.max(Yl,r),a=n.nSteer??7,s=e.tv?.enabled?lh(e,t,o,n.steerMaxDeg):0,i=E=>{let _=uh(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=Nn(e,t,o,l),m=E=>{let _={},V={};for(let N of rn)_[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?AL(E,e.massTotal):0}},h=null,d=E=>{if(h&&E===h.steerDeg)return m(h);let _=gL(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)},p=u.peak.driving&&u.peak.ay>0?Zv(e,t,o,u,l):null,f=p?Math.max(0,p.ay*Me):0,b=p?[...u.states.filter(E=>E.steerDeg<p.steerDeg),p]:u.states,g=p?b.findIndex(E=>E.ay*Me>=.995*f):0,y=b[g].steerDeg,{fold:R}=u;if(p&&R&&u.peak===R.state){let E=.995*f/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&&(h=fh(e,t,o,R,l,{ayG:E},u.states.slice($,_+1)))}if(h)y=h.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+_);d(N).ayMs>=.995*f?_=N:E=N}y=_}let M=[];for(let E=0;E<(f>0?a:1);E++){let _=E/(a-1);M.push(d(y*(_+Math.sin(Math.PI/2*_))/2))}M[0].ayMs=0;let v=[],x=[],k=[],F=[],C=Tr(e,t,o,void 0,n.diffYaw===!0),w=SL(e,t,o,n,C),T=n.axDrag??0,S=E=>{let _=C.limitAt(E.ayMs/Me,E.steerDeg,E.util,T+E.scrub);return{axD:_.edge!==void 0&&_.edge>0?_.edge:_.ax,locked:_.axUnlocked-_.ax>Gl}},A=E=>w.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+Gl&&N.push({read:$=>({axA:A($)}),past:$=>($.axA??-1/0)>_.axA}),-V.axD>-_.axD+Gl&&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<zv&&Q-j>Hv&&!(z&&Math.abs(fe-te)<=Gl);Y++){let J=.5*(j+Q),re=d(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<zv&&$-N>Hv;Q++){let ne=.5*(N+$),te=d(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:p!==null&&Jv(e,p.steerDeg)}}function AL(e,t){let r=e.beta*se,n=0;for(let o of rn){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 V8=Math.PI/180,B8={speeds:Array.from({length:23},(e,t)=>8+t),steerMaxDeg:14,steerSteps:29};function t1(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 ia={enabled:!1,kp:3e3,ffLow:150,ffHigh:300,vLow:18,vHigh:25},e1=e=>t1(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"}},FL=["k_yaw","k_roll","k_pitch"];function Ys(e){for(let t of FL)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 Wl(e){let t=(r,n)=>e[r]?.value??n;return{enabled:t("tv_enabled",0)>=.5,kp:t("tv_kp",ia.kp),ffLow:t("tv_ff_low",ia.ffLow),ffHigh:t("tv_ff_high",ia.ffHigh),vLow:t("tv_v_low",ia.vLow),vHigh:t("tv_v_high",ia.vHigh)}}var r1=[10,25,50,100,200,300];function vh(e,t,r,n,o){let s=r1.map(i=>Math.round(i<=25?r*i:r*25+n*(i-25)));return{id:e,label:t,speedMmS:[...r1],reboundN:s,bumpN:s.map(i=>Math.round(i*o))}}var jl={name:"Generic FS damper",curves:[vh("c1","Soft",1.6,1,.65),vh("c2","Medium",3,1.6,.65),vh("c3","Firm",8,2.4,.65)]};function Ul(e){let t=e.curves.length;return t>0?e.curves[Math.floor((t-1)/2)].id:""}var on=25;function ca(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 n1(e,t){return t>=0?ca(e.rebound,t):-ca(e.bump,-t)}function o1(e,t,r){return t*n1(e,t*r)}var kh=(e,t)=>e.curves.find(r=>r.id===t);function Ws(e,t){let r=kh(e,Ul(e)),n=(t&&kh(e,t.bump))??r,o=(t&&kh(e,t.rebound))??r;return{bump:{speedMmS:n?.speedMmS??[],forceN:n?.bumpN??[]},rebound:{speedMmS:o?.speedMmS??[],forceN:o?.reboundN??[]}}}var Xl=5e3;function js(e,t){let r=t>0?t:1,n=[],o=[],a=e.bump.speedMmS.map(c=>c/r).filter(c=>c<Xl),s=e.rebound.speedMmS.map(c=>c/r).filter(c=>c<Xl),i=c=>{n.push(c),o.push(o1(e,r,c))};i(-Xl);for(let c=a.length-1;c>=0;c--)i(-a[c]);i(0);for(let c of s)i(c);return i(Xl),{kind:"map",input:"velocity",x:n,y:o}}var Mh=64;function Us(e,t,r){let n=t>0?t:1,o=Math.max(r,1e-6),a=0;for(let s=0;s<Mh;s++){let i=Math.sin((s+.5)*Math.PI/Mh),c=n*o*i;a+=n*(ca(e.rebound,c)+ca(e.bump,c))*i}return a*(Math.PI/Mh)/(Math.PI*o)}function On(e,t,r,n,o=e){let a=(c,l,u)=>{if(!c||c.curves.length===0)return;let m=Ws(c,l);return{law:m,curve:js(m,u),rate:Us(m,u,on)}},s=a(e,t?.front,r),i=a(o??e,t?.rear,n);return!s&&!i?null:{...s?{front:s}:{},...i?{rear:i}:{}}}var a1=(e,t)=>({...e,y:e.y.map(r=>r*t)}),CL=e=>({...e,x:e.x.map(t=>-t).reverse(),y:e.y.map(t=>-t).reverse()});function Sh(e,t,r){let n=Math.abs(r)>0?Math.abs(r):1,o=Ws(e,t);return{law:o,curve:a1(js(o,n),.5),rate:Us(o,n,on)/2,mr:n,ratio:n,share:.5}}function Ah(e,t,r,n,o){let a=n*(Math.abs(r)>0?Math.abs(r):1),s=Ws(e,t),i=a1(js(s,a),1/n);return{law:s,curve:o?CL(i):i,rate:Us(s,a,on)/n,mr:a/n,ratio:a,share:1/n}}function Xs(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 Dr(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 Zs(e){return e.kind==="coil"?2:1}function Qs(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 i1(e){return Qs(e)/2}function c1(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 s1(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 wL(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 Js(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*Qs(e.section)/e.barLength,a=2*o/(n*n),s=i1(e.armSection??e.section),i=3*e.E*s/n**3,c=e.dropLinkRate??1/0;return{rateAtLink:s1([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*Qs(e.section)/e.barLength,a=2*o/(n*n),s=3*e.E*c1(e.blade)/n**3,i=e.dropLinkRate??1/0;return{rateAtLink:s1([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*Qs(e.section)/e.length,a=2*o/(n*n);return{rateAtLink:a,contributions:{barTwist:a},torsional:o}}case"coil":{let n=Dr(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=wL(e.linkTravel,e.force,t);return{rateAtLink:Math.max(0,n),contributions:{},torsional:0}}}}function ql(e,t,r=0){if(e.kind==="none")return{wheelRate:0,motionRatio:0,rateAtLink:0};if(e.kind==="direct")return{wheelRate:Math.max(0,e.wheelRate),motionRatio:1,rateAtLink:0};let n=t?ld(t,r):1,o=t?ud(t,r):0,a=Js(e,o).rateAtLink;return{wheelRate:Math.max(0,a*n*n),motionRatio:n,rateAtLink:a}}function ei(e,t){let r=e.damper??0;return!r||e.design.kind==="none"?0:Zs(e.design)*r*t*t}var TL=150;function PL(e){return X(e,[0,-.5,1])<-1e-9?U(e,-1):e}function l1(e){let t=e.hardpoints,r=H(t.rockerPivotB,t.rockerPivotA),n=ee(t.rockerPivotA,U(H(t.rockerToDamper,t.rockerPivotA),.6)),o=PL(q(ae(r,H(t.rockerToDamper,t.rockerPivotA))));return{outer:n,inner:ee(n,U(o,TL)),attach:"rocker"}}function Ct(e,t){let r={};for(let o of Po)r[o]=et($e(e,o));let n={vehicle:e,ctx:r};return t&&(n.kc=Hc(n,t)),n}var Ql=.5;function LL(e,t){let r=([i,c,l])=>{let u=q(H(c,i)),m=H(l,i),h=q(H(m,U(u,X(m,u))));return[u,h,ae(u,h)]},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 u1=e=>[(e[2][1]-e[1][2])/2,(e[0][2]-e[2][0])/2,(e[1][0]-e[0][1])/2];function Zl(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+Ql,r.steer,void 0,a),l=ge(o,r.travel-Ql,r.steer,void 0,a),u=(s?s.ok:r.converged)&&c.ok&&l.ok,m=ot(c),h=ot(l),d=(w,T)=>_t(w.points[T],n),p=o.inv.strut?"pushrodOuter":"uprightUpper",f=d(i,p),b=d(i,"uprightLower"),g=w=>{let T=H(b,f);return Math.hypot(...ae(T,H(d(i,w),f)))/Math.hypot(...T)},y=g("tieOuter")>=g("wheelCenter")?"tieOuter":"wheelCenter",R=[f,b,d(i,y)],M=w=>LL(R,[d(w,p),d(w,"uprightLower"),d(w,y)]),v=M(m),x=M(h),k=u1(v.rot),F=u1(x.rot),C=[NaN,NaN,NaN];return{solved:u,state:i,at:w=>d(i,w),velocity:w=>u?U(H(v.move(w),x.move(w)),1/(2*Ql)):C,omega:u?U(H(k,F),1/(2*Ql)):C}}function Fh(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 m1(e,t,r){let n=Zl(e,t,dt(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 p1(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 d1(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 DL(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 EL=.1*Math.PI/180;function f1(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]))*EL<=o*n}function Jl(e,t){return!e.valid||!e.cpLeft||!e.cpRight?!1:f1([e.lateral,e.height],e.cpLeft,e.cpRight,e.sinAngle,t)}function ti(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 IL=1;function h1(e){let t=ti(e);if(!t||!e.cpLeft||!e.cpRight||Math.abs(t.left-t.right)>IL)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 la(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=m1(e,n,t),s=m1(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=p1(a),c=p1(s),l=d1(a,i),u=d1(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 h=i?[i[0]-a.cp[0],i[1]-a.cp[1]]:l,d=c?[c[0]-s.cp[0],c[1]-s.cp[1]]:u,p=Math.hypot(h[0],h[1]),f=Math.hypot(d[0],d[1]),b=p>0&&f>0?Math.abs(h[0]*d[1]-h[1]*d[0])/(p*f):0,g=Fh(a.cp,h,s.cp,d)??DL(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,C=(g[0]-a.cp[0])*-x+(g[1]-a.cp[1])*v,w=(g[0]-k)*v+(g[1]-F)*x;return{lateral:g[0],height:g[1],heightAboveGround:C,lateralAlongGround:w,valid:!0,icLeft:i,icRight:c,lineLeft:l,lineRight:u,sinAngle:b,cpLeft:a.cp,cpRight:s.cp}}function Er(e,t){return{front:or(e,t,"front"),rear:or(e,t,"rear")}}function eu(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 _L(e,t){return{camber:eu(e.travel,e.camber,t),toe:eu(e.travel,e.toe,t),motionRatio:eu(e.travel,e.motionRatio,t),damperLen:e.damperLen?eu(e.travel,e.damperLen,t):0}}var b1=e=>_L(e,0).motionRatio;function Ch(e,t){if(e.kind!=="coil")return null;let r=t??e.motionRatio,n=Dr(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 tu(e,t){if(e.kind==="none")return 0;if(e.kind==="tabulated"){let n=a=>NL(e,a);return(n(.5)-n(-.5))/(2*.5)/2}if((e.gap??0)>0)return 0;let r=t??e.motionRatio;return Dr(e.rate,0)*r*r/2}function ri(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 NL(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 wh={kind:"coil",rate:120,motionRatio:.7,gap:5,bothWays:!1};var g1=new WeakMap;function nu(e,t){let r=g1.get(e);r||(r=new Map,g1.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=vn(e,t);return r.set(n,a),a}var OL=32,ni=new Map,y1=new WeakMap,VL=1;function BL(e){let t=y1.get(e);return t===void 0&&(t=VL++,y1.set(e,t)),t}function Th(e,t){if(!t.linkage)return null;let r=Xr(e,t.linkage,t.design.kind),n=`${BL(e)}|${r?"unit":"bar"}|${JSON.stringify(t.linkage)}`,o=ni.get(n);if(o)return o;let a=No(e,t.linkage,{kind:t.design.kind});return ni.size>=OL&&ni.delete(ni.keys().next().value),ni.set(n,a),a}function Bn(e,t,r=0){let n=(o,a)=>{if(!(!o||o.design.kind==="none"))return ql(o.design,Th(a,o),r).wheelRate};return{front:n(t.arbFrontDesign,e.front),rear:n(t.arbRearDesign,e.rear)}}function ua(e,t){let r=(n,o)=>{if(!n||n.design.kind==="none")return;let a=n.linkage?nu(o,n.linkage).atDesign:void 0;return tu(n.design,a)};return{front:r(t.heaveFrontDesign,e.front),rear:r(t.heaveRearDesign,e.rear)}}function M1(e,t){let r=(a,s)=>{if(!a||a.design.kind!=="coil")return;let i=a.linkage?nu(s,a.linkage).atDesign:void 0;return Ch(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 ou(e,t){let r=(o,a)=>o?ri(o,Ph(o,a)):0,n=(o,a)=>o?ei(o,Lh(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 Ph=(e,t)=>e.linkage?nu(t,e.linkage).atDesign:void 0,Lh=(e,t)=>ql(e.design,Th(t,e),0).motionRatio;function S1(e,t){let r=t.damperSetup,n=t.heaveDamperModel??t.damperModel,o=t.rollDamperModel??t.damperModel,a=(h,d,p)=>{if(!h||!n?.curves.length)return;let f=Ph(h,d);if(ri(h,f)>0)return Sh(n,r?.[p],f??(h.design.kind==="coil"?h.design.motionRatio:1))},s=(h,d,p)=>{if(!h||!o?.curves.length)return;let f=Lh(h,d);if(!(ei(h,f)>0))return;let b=Th(d,h)!==null;return Ah(o,r?.[p],f,Zs(h.design),b&&f>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 A1(e,t){let r=t.heaveDamperModel??t.damperModel,n=t.rollDamperModel??t.damperModel,o=(i,c)=>Vn(i)?{source:"none"}:qs(i.config.coilover,c),a=(i,c)=>{if(!i)return{source:"none"};let l=ri(i,Ph(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=ei(i,Lh(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 F1(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 Vn=e=>e.config.actuation==="decoupled",$n="a decoupled axle damps in its heave and roll elements, set below";function C1(e,t,r={}){let n={...t},o=(m,h)=>{let d=n[m];d&&typeof d=="object"&&"value"in d&&(n[m]={...d,value:h})},{front:a,rear:s}=Bn(e,t);a!==void 0&&o("arb_front",a),s!==void 0&&o("arb_rear",s);for(let[m,h,d]of[[t.heaveFrontDesign,e.front,"heave_spring_front"],[t.heaveRearDesign,e.rear,"heave_spring_rear"]]){if(!m||m.design.kind==="none")continue;let p=m.linkage?nu(h,m.linkage).atDesign:void 0;o(d,tu(m.design,p))}let i=GL(e,t,r),c=$L(e,i);n.kinFront=c.kinFront,n.kinRear=c.kinRear;let l=zL(e,i);n.steerFront=c.steerFront,Number.isFinite(l.ackermannPct)&&o("ackermann_pct",l.ackermannPct);let u=m=>Vn(m)?0:m.measured?.springRate??m.config.springRate;o("spring_front",u(e.front)),o("spring_rear",u(e.rear));for(let[m,h]of[[e.front,"spring_front"],[e.rear,"spring_rear"]])Vn(m)&&(n.readouts={...n.readouts,[h]:"a decoupled axle has no corner spring; its heave and roll elements carry the car"});for(let[m,h]of[[e.front,"damper_front"],[e.rear,"damper_rear"]])Vn(m)&&(o(h,0),n.readouts={...n.readouts,[h]:$n});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 $L(e,t){return{kinFront:R1(e.front),kinRear:R1(e.rear),steerFront:e.front.measured?void 0:au(e.front,t)}}var x1=new WeakMap;function R1(e){let t=x1.get(e);return t||x1.set(e,t=Wo(e)),t}function GL(e,t,r={}){return KL(e,t,r.front,r.rear)}function KL(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 su(a,r,n).front??o}var v1=new WeakMap;function au(e,t=e.config.loadedRadius){let r=v1.get(e);r||(r=new Map,v1.set(e,r));let n=r.get(t);if(n)return n;let o=t===e.config.loadedRadius?void 0:{loadedRadius:t},a=wd(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 k1=new WeakMap;function HL(e){return qe(e,{travelMin:-1,travelMax:1,steps:3}).samples[1].metrics.motionRatio??1}var ru=e=>e.measured?b1(e.measured):HL(e);function zL(e,t=e.front.config.loadedRadius){let r=()=>e.front.measured?void 0:au(e.front,t);return{...YL(e),get steerFront(){return r()},get ackermannPct(){let n=r();return n?Td(n,pt(e.front),e.config.wheelbase):Number.NaN}}}function YL(e){let t=k1.get(e);if(t)return t;let r=e.front.measured,n=e.rear.measured,a=!r||!n?Er(Ct(e),{heave:0,pitch:0,roll:0,steer:0}):null,s={wheelbase:e.config.wheelbase,trackFront:r?r.track:pt(e.front),trackRear:n?n.track:pt(e.rear),mrFront:ru(e.front),mrRear:ru(e.rear),rcFront:r?r.rollCentreHeight:a&&a.front.valid?a.front.heightAboveGround:0,rcRear:n?n.rollCentreHeight:a&&a.rear.valid?a.rear.heightAboveGround:0,rcGainFront:r||!a?0:la(a.front),rcGainRear:n||!a?0:la(a.rear),rcFrontValid:r?!0:!!a?.front.valid,rcRearValid:n?!0:!!a?.rear.valid};return k1.set(e,s),s}var ht={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}},P1=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 Gn(e){if(P1(e))switch(e.kind){case"open":case"spool":return{kind:e.kind};case"clutch":{let t=ht.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=ht.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 iu(e){if(!P1(e))return;let t=Gn(e.front),r=Gn(e.rear);return t||r?{...t?{front:t}:{},...r?{rear:r}:{}}:void 0}function oi(e){let t=Jr(e),r=n=>n>=2?"independent":n===1?"diff":"none";return{front:r(t.front),rear:r(t.rear)}}function ai(e){if(!e.driveline)return;let t=oi(e),r=e.r_dyn.value,n=s=>{if(t[s]!=="diff")return;let i=Gn(e.driveline?.[s]);if(!(!i||i.kind==="independent"))return{kind:i.kind,drive:Ns(i,"drive",r),coast:Ns(i,"coast",r),hubs:Ns(i,"hubs",r)}},o=n("front"),a=n("rear");return o||a?{...o?{front:o}:{},...a?{rear:a}:{}}:void 0}var WL={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"}},w1=e=>{let t=e==="front"?"Front":"Rear";return Object.fromEntries(Object.entries(WL).map(([r,n])=>[`${e}.${r}`,{section:t,...n}]))},cu={...w1("front"),...w1("rear")},T1=e=>e.motorModel?.kind==="ice"?e.motorPlacement==="front"?"front":"rear":null;function L1(e,t){let r=T1(t);if(!(!r||T1(e)===r||t.driveline?.[r]))return{...t.driveline,[r]:{...ht.clutch}}}function Bt(e,t,r,n){return e>0?!(r>0)||!Number.isFinite(r)?e:Math.max(1,e-t/r):n}function lu(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 ma(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 Ir(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 si(e,t){if(!e)return UL(t);let r=t-Qr(e,0).camber;return r?{...e,camber:e.camber.map(n=>n+r)}:e}function jL(e){return{kinFront:si(e.kinFront,Z(e,"camber_front_deg")),kinRear:si(e.kinRear,Z(e,"camber_rear_deg"))}}function UL(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 D1=9.81,E1=e=>e>1?e/100:e;function pa(e,t,r){let n=t??e.tireModel??vs(),o=r??e.tireModelRear??n,a={grip:Z(e,"grip_scale"),stiffness:Z(e,"stiffness_scale")},s=bl(n,a);return{front:s,rear:o===n?s:bl(o,a)}}function sr(e,t,r){let n=pa(e,t,r),o=Ie(n.front);return it(n.rear===n.front?o:il(o,Ie(n.rear)))}function Dh(e,t,r){let n=E1(e.front_mass_diss.value),o=pa(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*D1*n/2,u=e.m.value*D1*(1-n)/2,m=(i?a.verticalStiffness():0)||Z(e,"tire_vertical_rate"),h=(c?s.verticalStiffness():0)||Z(e,"tire_vertical_rate"),d=er(i)??0,p=er(c)??0,f=e.surveyedRadiusFront&&e.surveyedRadiusRear?lu({freeRadius:d,staticLoad:l,tyreRate:m,surveyed:e.surveyedRadiusFront},{freeRadius:p,staticLoad:u,tyreRate:h,surveyed:e.surveyedRadiusRear},n):void 0,b=e.surveyedRadiusFront?Bt(d,l,m,e.surveyedRadiusFront):void 0,g=e.surveyedRadiusRear?Bt(p,u,h,e.surveyedRadiusRear):void 0;return{ev:a,evR:s,Wf:l,Wr:u,tireRate:m,tireRateRear:h,tyreFreeRadius:d,tyreFreeRadiusRear:p,cgStandingRadius:f,standingFront:b,standingRear:g}}function su(e,t,r){let n=Dh(e,t,r);return{front:n.standingFront,rear:n.standingRear}}function I1(e,t,r){return Dh(e,t,r).cgStandingRadius}function lt(e,t,r){let n=E1(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:h,tyreFreeRadiusRear:d,cgStandingRadius:p,standingFront:f,standingRear:b}=Dh(e,t,r),g=Is(e),y=ai(e),R=On(e.damperModel,e.damperSetup,o,a,e.damperModelRear??e.damperModel),M=e.readouts?.damper_front===$n,v=e.readouts?.damper_rear===$n,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:Wl(e),cgHeight:ma(Z(e,"cg_height"),e.cgReference?.standingRadius,p),...p!==void 0?{cgStandingRadius:p}:{},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:XL(e,{Wf:c,Wr:l,tireRate:u,tireRateRear:m,tyreFreeRadius:h,tyreFreeRadiusRear:d,standingFront:f,standingRear:b}),tyreFreeRadius:h,...d!==h?{tyreFreeRadiusRear:d}:{},rcHeightFront:Ir(Z(e,"rc_front"),e.rcRoad?.gainFront,e.rcRoad?.radiusFront,f),rcHeightRear:Ir(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,...jL(e)}}function XL(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 uu={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 _1(e,t=e.batteryModel){if(!t)return e;let r=dr(t),n=(o,a)=>({...o,value:a});return{...e,capacity:n(e.capacity,r.capacityAh),ocv:n(e.ocv,r.voltageAtFull)}}var O1={damper_front:`the damper part sets it: its front curve at ${on} mm/s`,damper_rear:`the damper part sets it (the rear's own, where the car names one): its rear curve at ${on} mm/s`};function mu(e){let t=!!(e.damperModelId||e.damperModel),r=t||!!(e.damperModelIdRear||e.damperModelRear);return{...t?{damper_front:O1.damper_front}:{},...r?{damper_rear:O1.damper_rear}:{}}}function V1(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=On(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!==$n&&(i.damper_front=s(e.damper_front,"damper front",a.front.rate/(n*n))),a.rear&&e.readouts?.damper_rear!==$n&&(i.damper_rear=s(e.damper_rear,"damper rear",a.rear.rate/(o*o))),i}var B1={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 _r(e){return!!e&&typeof e=="object"&&"value"in e&&"label"in e}var eD={Batteriekapazit\u00E4t:"pack capacity",Rollwiderstandsbeiwert:"rolling-resistance coefficient"},G1=e=>eD[e]??e;function pu(e){let t=[];for(let r of Object.keys(e)){if(r==="motor"||r==="name")continue;let n=e[r];_r(n)&&t.push({key:r,label:G1(n.label),value:n.value,unit:n.unit})}return t}var tD=[{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"]}],rD=.5,$1=e=>e==="infinite"?1/0:typeof e=="number"?e:null,nD=e=>/front/.test(e)?e.replace("front","rear"):/rear/.test(e)?e.replace("rear","front"):null,bU=(()=>{let e=B1.rows,t=o=>{let a=nD(o),s=$1(e[o]?.score),i=a&&e[a]?$1(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>=rD&&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 Eh={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 K1(e){let t=new Map;for(let a of pu(e))t.set(a.key,a);let r=new Set,n=[];for(let a of tD){let s=[];for(let i of a.keys){let c=t.get(i);c&&(s.push(c),r.add(i))}s.length&&n.push({title:a.title,rows:s})}let o=pu(e).filter(a=>!r.has(a.key));return o.length&&n.push({title:"Other",rows:o}),n}var Ih={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"},_h={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"},H1=e=>!!(e.aeroModelId||e.aeroModel);function oD(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 aD=e=>!!(e.batteryModelId||e.batteryModel);function sD(e,t){let r={};return t.geometry&&Object.assign(r,Eh,oD(e)),H1(e)&&Object.assign(r,Ih),aD(e)&&Object.assign(r,uu),Object.assign(r,mu(e)),e.readouts&&Object.assign(r,e.readouts),r}function z1(e,t){let r=sD(e,t);return H1(e)||Object.assign(r,_h),r}function Nh(e){let t=e.cop_long;return _r(t)?1-t.value:.5}function iD(e,t){let r=e.front_aero_diss,n=e.cop_long;!_r(r)||!_r(n)||(t===r.label?n.value=1-r.value:t===n.label&&(r.value=1-n.value))}function cD(e,t){iD(e,t);let r=e.c_l,n=e.c_w,o=e.l_to_d_ratio;!_r(r)||!_r(n)||(t===r.label||t===n.label?_r(o)&&n.value!==0&&(o.value=r.value/n.value):_r(o)&&t===o.label&&o.value!==0&&(n.value=r.value/o.value))}function du(e,t,r){let n=!1;for(let o of Object.keys(e)){if(o==="motor"||o==="name")continue;let a=e[o];if(_r(a)&&G1(a.label)===t){a.value=r,n=!0;break}}return n&&cD(e,t),n}function fu(e,t,r=0,n,o){let a=()=>({cl:e.c_l.value,cw:e.c_w.value,frontShare:Nh(e),A:e.A.value,platform:null});if(!e.aeroModel)return a();let s=zr(n??lt(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:Nh(e),A:s.area,platform:s}}var Y1=e=>typeof e=="object"&&e!==null&&typeof e.value=="number"&&typeof e.label=="string";function W1(e,t=e.aeroModel){if(!t)return e;let r=Hr(t,{wheelbase:Z(e,"wheelbase")}).at(Z(e,"ride_height_front"),Z(e,"ride_height_rear")),{cl:n,balanceFront:o}=Lp(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(Y1(e.cop_long)?e.cop_long:void 0,nr.cop_long,1-o)};return Y1(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 ii={dsTarget:.25,accelStep:.25,vTol:.002,scanSteps:24,seamIters:8,fitSpacing:1},lD=32;function j1(e,t,r){let n=Math.round(e/t);return Math.max(1,Math.min(Number.isFinite(n)?n:1,Math.floor(r/lD)||1))}function at(e){let t=ii,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 U1=Math.PI/180,hu=.02,X1=new WeakMap;function ci(e){let t=X1.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)*U1,l=(e.bank?.[i]??0)*U1,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 X1.set(e,s),s}function bu(e,t,r){return e.n0[t]+e.k[t]*r*r}function q1(e,t){return e.k[t]<0?Math.sqrt(Math.max(0,e.n0[t])/-e.k[t]):1/0}function Q1(e,t){if(!e)return null;let r=1/0,n=-1/0;for(let o=0;o<e.n0.length;o++){let a=bu(e,o,t[o]??0);a<r&&(r=a),a>n&&(n=a)}return r>=1-hu&&n<=1+hu?null:{lo:r,hi:n}}var da=[.1,.25,.5,.75,1,1.25,1.5,2,2.5];function Z1(e){let t=e.lo>=1-hu?1:1-1.25*(1-e.lo)-.05,r=e.hi<=1+hu?1:1+1.25*(e.hi-1)+.05,n=[...da].reverse().find(a=>a<=t)??da[0],o=da.find(a=>a>=r)??da[da.length-1];return da.filter(a=>a>=n&&a<=o)}function Oh(e,t,r){return r<1?Math.max(e,t):Math.min(e,t)}function J1(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,h,d=1,p=1)=>s.axAccel(m,h,d,p)+t.axAccel(u(m),m,h,d,p)-r.axAccel(m,h,d,p),axDecel:(m,h,d=1,p=1)=>{let f=b=>s.axDecel(m,h,d,b)+t.axDecel(u(m),m,h,d,b)-r.axDecel(m,h,d,b);return p===1?f(1):Oh(f(p),f(1),p)},ay:(m,h,d=1)=>Math.max(0,s.ay(m,h,d)+t.ay(u(m),m,h,d)-r.ay(m,h,d)),scrub:(m,h,d=1)=>(s.scrub?.(m,h,d)??0)+t.scrub(u(m),m,h,d)-(r.scrub?.(m,h,d)??0)}:{vMax:s.vMax,axAccel:(m,h,d=1,p=1)=>t.axAccel(u(m),m,h,d,p),axDecel:(m,h,d=1,p=1)=>t.axDecel(u(m),m,h,d,p),ay:(m,h,d=1)=>t.ay(u(m),m,h,d),scrub:(m,h,d=1)=>t.scrub(u(m),m,h,d)}}}function gu(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}=uD(e,t,r),u=new Array(a),m=new Array(a),h=new Array(a),d=new Array(a).fill(0),p=0,f=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:C,gear:w,tau:T,target:S}=F;p=0,f=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=w;if(C<L-1e-9?n.best(C)>w&&(n.rpm(C,w)>=n.limitRpm||c[A]>=C*M)?O=w+1:w>0&&C<n.vIdle(w)&&(O=w-1):L<C-1e-9&&w>0&&n.best(l[A])<w&&n.rpm(C,w-1)<=n.limitRpm&&(O=w-1),O===w)break;S=O,O>w?p++:f++,T=O>w?y:R,T<=0&&(w=S)}u[A]=C,m[A]=w+1,h[A]=n.rpm(C,w);let D=T>0;d[A]=D?1:0;let I=L;if(!D)C<L&&(I=Math.min(L,Math.sqrt(Math.max(0,C*C+2*o(A,C,n.share(C,w))*t[A]))));else if(C<L){let G=o(A,C,g>0?g*n.share(C,w):0),O=Math.min(L,Math.sqrt(Math.max(0,C*C+2*G*t[A]))),W=C+O>0?2*t[A]/(C+O):1/0;if(W<=T)I=O,b+=W,T-=W;else{let E=Math.min(L,Math.max(0,C+G*T)),_=Math.max(0,t[A]-(C+E)*.5*T);b+=T,T=0,w=S,I=Math.min(L,Math.sqrt(Math.max(0,E*E+2*o(A,E,n.share(E,w))*_)))}}else{let G=C+I>0?2*t[A]/(C+I):0;b+=Math.min(G,T),T-=G,T<=0&&(w=S)}C=I}return{v:C,gear:w,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 C=v(k),w=Math.abs(C.v-k.v)<=1e-9&&C.gear===k.gear&&C.target===k.target&&Math.abs(C.tau-k.tau)<=1e-12;if(k=C,w)break}else{let F=v(k);u[a-1]=F.v,m[a-1]=F.gear+1,h[a-1]=n.rpm(F.v,F.gear),d[a-1]=F.tau>0?1:0}return{v:u,gear:m,rpm:h,shifting:d,upshifts:p,downshifts:f,gapTime:b}}function uD(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,h=e[m]<e[u]-1e-9;s=h?0:s+t[u],i=h?Math.min(i,e[m]):e[u],l<n&&(o[u]=s,a[u]=i)}return{brakeAhead:o,apexAhead:a}}var Vh=.001,Bh=9.81,li=(e,t)=>$h(e?.gradient?.[t]??0);function $h(e){return e===0?0:-Bh*Math.sin(e*Math.PI/180)}function sn(e,t){let r=new Array(t);for(let n=0;n<t;n++)r[n]=$h(e?.[n]??0);return r}var an=(e,t)=>{let r=e?.mu?.[t];return r!=null&&r>0?r:1},Kn=(e,t)=>e?.bank?.[t]??0;function mD(e,t,r,n,o,a){let s=e.ay(t,r,an(o,a)),i=Kn(o,a);if(!i)return s;let c=i*Math.PI/180,l=n===0?0:-Math.sign(n)*Bh*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)+Bh*Math.sin(r)}function Gh(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 Hn=(e,t,r)=>t?t(r):e,pD=1e-4;function fa(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),h=Hn(e,o,l),d=a!==void 0&&a>0?Math.min(h.vMax,a):h.vMax,p=s?Math.min(d,s(l)):d,f=m<=0?p:Gh(b=>b*b*m-mD(h,b,0,u,n,l),Vh,p,i.scanSteps,Math.min(i.vTol,pD));c.push({v:f,ax:0,ay:f*f*u})}return c}function dD(e,t,r,n,o,a,s=1,i=0,c=0,l){if(r.v<=t.v)return 0;let u=d=>{let p=Ye(d*d*n,c),f=(l?e.axDecel(d,Math.abs(p),s,l(d)):e.axDecel(d,Math.abs(p),s))+i;return Math.sqrt(Math.max(0,d*d+2*f*o))},m=r.v;r.v=Gh(d=>u(d)-t.v,Vh,r.v,a.scanSteps,a.vTol),r.ay=r.v*r.v*n;let h=Math.abs(Ye(r.ay,c));return r.ax=(l?e.axDecel(r.v,h,s,l(r.v)):e.axDecel(r.v,h,s))+i,m-r.v}function fD(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 ek(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 h=(m+1)%i;u=Math.max(u,dD(Hn(e,o,m),t[h],t[m],r.curvature[m],r.ds[m],s,an(r,m),li(r,m),Kn(r,m),a?d=>a(m,d):void 0))}if(u<=s.vTol)break}return c}function tk(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 h=(m+1)%i;u=Math.max(u,fD(Hn(e,o,m),t[h],t[m],r.curvature[m],r.ds[m],an(r,m),li(r,m),Kn(r,m),a?a[m]:1))}if(u<=s.vTol)break}return c}function hD(e,t,r){let n=r.load?ci(t):null;if(!n||!r.load)return{pick:r.envelope};let o=t.npts;return{pick:J1(n,r.load,e,r.envelope),cap:a=>q1(n,a%o),n:(a,s)=>bu(n,a,s)}}function rk(e,t,r,n,o,a,s){return gu(n,r.ds,o,a,(i,c,l)=>{let u=c*c*r.curvature[i];return Hn(e,t,i).axAccel(c,Math.abs(Ye(u,Kn(r,i))),an(r,i),s?l*s[i]:l)+li(r,i)})}function nk(e,t){return{gear:e.gear.slice(0,t),engineRpm:e.rpm.slice(0,t),shifting:e.shifting.slice(0,t)}}function ok(e,t,r,n){if(!e.scrub)return{};let o=!1,a=n.map((s,i)=>{let c=Hn(e,t,i),l=Ye(s*s*r.curvature[i],Kn(r,i)),u=c.scrub?c.scrub(s,Math.abs(l),an(r,i)):0;return u!==0&&(o=!0),u});return o?{axScrub:a}:{}}function bt(e,t,r,n={}){let o=at(r),a=t.npts,s=t.closed&&!n.standingStart,{pick:i,cap:c,n:l}=hD(e,t,n),u=n.driveDerate,m=n.brakeFade;if(!s)return bD(e,t,o,n.standingStart===!0,i,u,n.vCeiling,m,c,l,n.shifts);let h=fa(e,t.curvature,o,t,i,n.vCeiling,c),d=ek(e,h,t,o,i,m),p=tk(e,h,t,o,i,u),f=n.shifts?rk(e,i,t,h.map(M=>M.v),!0,n.shifts,u):void 0;if(f)for(let M=0;M<a;M++)h[M].v=f.v[M];for(let M=0;M<a;M++){let v=h[M];v.ay=v.v*v.v*t.curvature[M];let x=h[(M+1)%a].v;v.ax=(x*x-v.v*v.v)/(2*t.ds[M])}let b=h.map(M=>M.v),g=h.map(M=>M.ax),y=h.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:h,v:b,ax:g,ay:y,laptime:R,sweeps:{backward:d,forward:p},...l?{loadFactor:b.map((M,v)=>l(v,M))}:{},...ok(e,i,t,b),...f?nk(f,a):{}}}function bD(e,t,r,n,o,a,s,i,c,l,u){let m=t.npts,h=t.closed?m:m-1,d=h+1,p=new Array(d);for(let R=0;R<d;R++)p[R]=t.curvature[R%m];let f=fa(e,p,r,t,o,s,c);n&&(f[0].v=0);for(let R=h-1;R>=0;R--){let M=f[R],v=f[R+1];if(M.v<=v.v)continue;let x=Hn(e,o,R),k=C=>{let w=Ye(C*C*t.curvature[R],Kn(t,R)),T=(i?x.axDecel(C,Math.abs(w),an(t,R),i(R,C)):x.axDecel(C,Math.abs(w),an(t,R)))+li(t,R);return Math.sqrt(Math.max(0,C*C+2*T*t.ds[R]))},F=n&&R===0?M.v:Vh;M.v=Gh(C=>k(C)-v.v,F,M.v,r.scanSteps,r.vTol)}for(let R=0;R<h;R++){let M=f[R],v=f[R+1];M.ay=M.v*M.v*t.curvature[R];let x=Ye(M.ay,Kn(t,R));M.ax=Hn(e,o,R).axAccel(M.v,Math.abs(x),an(t,R),a?a[R]:1)+li(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?rk(e,o,t,f.map(R=>R.v),!1,u,a):void 0;if(b)for(let R=0;R<d;R++)f[R].v=b.v[R];let g=0;for(let R=0;R<h;R++){let M=f[R].v+f[R+1].v;M>0&&(g+=2*t.ds[R]/M)}let y=f.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<h?f[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))}:{},...ok(e,o,t,y.map(R=>R.v)),...b?nk(b,m):{}}}var ak=(e,t)=>{let r=e[t]?.value;return Number.isFinite(r)&&r>0?r:0};function zn(e,t,r){let n=e.m.value,o=e.r_dyn?.value??0,a=ak(e,"I_wheel"),s=e.motorModel?.kind==="ice"?0:ak(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,h=u*a/c,d=n+m+h;return{mass:n,driven:m,undriven:h,effective:d,powerFactor:n/d,tractionFactor:n/(n+h)}}function Yn(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 ui=36e5,lk=Math.PI*2,Kh=e=>Math.max(0,Math.min(1,e));function Hh(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=xc(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/lk),l=Math.max(0,i*o/(n*a)),u=r.efficiency(c,l);return u>.01?u:.5}}var sk=new WeakMap;function ha(e){if(e.batteryModel)return e.batteryModel;let t=e.capacity.value,r=e.ocv.value,n=sk.get(e);if(n&&n.capacityAh===t&&n.ocv===r)return n.model;let o=Rp(t,r);return sk.set(e,{capacityAh:t,ocv:r,model:o}),o}function zh(e){let t=e.params,r=Hf(t,Ll(e));if(ut(t.motorModel)||ct(t).mode!=="hydraulic")return r;let n;return(o,a,s,i=0)=>{if(!(o>0))return 0;n??=gD(e);let c=Vl(n.inp,n.ev,o,a,i);return c?Math.min(o,c.regenFront+c.regenRear):r(o,a,s)}}var ik=new WeakMap;function gD(e){let t=e.params,r=ik.get(t);if(!r){let n=Fr(t);r={inp:lt(n.regen?t:{...t,energy:{...n,regen:!0}}),ev:sr(t)},ik.set(t,r)}return r}var mi=e=>e.airTempC??Mt;function yu(e,t){return e.thermal?e.thermal.startC??t:ko}function ck(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 uk=()=>({windingC:[],derate:[],lossW:[],torqueNm:[],ampsRms:[]});function yD(e){let t=e.motorModel;if(!t?.thermal)return;let r=vp(t.thermal),n=xc(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/lk),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 xD(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),h=u?c/l:1,d=r*h;return{dq:m*d,lossJ:m*m*e.resistance(n,o)*d,energyJ:l*d,short:c>i,cutoff:u,seconds:d}}function RD(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 vD(e){let{drivenFront:t,drivenRear:r}=Yn(e);return zn(e.params,t,r)}function ba(e,t,r,n,o=Ar,a,s,i,c,l,u){let m=e.params,h=m.rho.value,d=m.fr_0.value,p=m.m.value,f=e.FG,b=m.aeroModel?lt(m):void 0,g=Hh(m),y=dr(ha(m)),R=y.chargeC,M=Kh(a??m.soc.value),v=mi(m),x=s??yu(y,v),k=x,F=0,C=0,w=0,T=0,S=-1,A=-1,P=-1,L=yD(m),D=L?L.th.startC:0,I=D,G=0,O=1,W=-1,E=0,_=0,V=zh(e),N=m.motorModel?.kind==="ice",$=u?.scrub,K=$?p/vD(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}=fu(m,Q,te/9.81,b),re=.5*h*fe*J*ne,pe=.5*h*Y*J*ne,de=(f+re)*-d,ie=$?-K*($[j]??0):0,oe=de+pe+ie+p*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,Ce=M,Ge=x,We=0,be=0,Fe=le;if(N){oe>0&&(be=ue/g(Q,oe),F+=be/ui),l?.netKwh.push(F-C),l?.powerKw?.push(le>0?be/le/1e3:0);continue}if(oe>0){let ye=ue/g(Q,oe),me=xD(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/ui,be=me.energyJ*Ke,Fe=me.seconds,w+=me.lossJ*Ke,T+=Se,le>0&&(We=Se/me.seconds),M=Kh(M-Se/R),x=ck(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=RD(y,Te,le,M,x),Ke=(1-M)*R,je=Math.min(Se.dq,Ke),Gt=Se.dq>0?je/Se.dq:1;C+=Se.energyJ*Gt/ui,be=-Se.energyJ*Gt,w+=Se.lossJ*Gt,T-=je,le>0&&(We=-je/le),M=Kh(M+je/R),x=ck(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-C),l?.powerKw?.push(le>0?be/Fe/1e3:0),l?.pack){let ye=l.pack;ye.soc.push(Ce),ye.amps.push(We),ye.volts.push(y.ocv(Ce)-We*y.resistance(Ce,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:C,net:F-C,chargeAh:T/3600,loss:w/ui,socEnd:M,shortAt:S,cutoffAt:A,emptyAt:P,tempEndC:x,tempMaxC:k,...L?{motorTempEndC:D,motorTempMaxC:I,motorLossKwh:G/ui,motorDerateMin:O,motorDerateAt:W,motorDerateTimeFrac:_>0?E/_:0}:{}}}var kD=.5,MD=.02,SD=6;function mk(e,t,r,n,o,a,s,i){let c=n(),l=1,u=p=>{let f=uk(),b=ba(e,t,p.v,p.ax,r,o,a,f,s,void 0,{ay:p.ay,bank:i,...p.axScrub?{scrub:p.axScrub}:{}});return{trace:f,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 h=m.trace.derate.slice(),d=!1;for(let p=0;p<SD;p++){let f=n(h);l++;let b=Math.abs(f.laptime-c.laptime);if(c=f,m=u(c),b<MD){d=!0;break}let g=m.trace.derate,y=new Array(h.length);for(let R=0;R<h.length;R++)y[R]=h[R]+kD*((g[R]??1)-h[R]);h=y}return{lap:c,derate:h,solves:l,converged:d,peakWindingC:m.peak,derateTimeFrac:m.frac}}var AD=.1;function pk(e){let t=e.power_limit_kw?.value??0;return t>0?t*1e3:0}function Yh(e,t,r){return e.motorModel?.kind==="ice"?1/0:dr(ha(e)).maxPower(t??e.soc.value,r,pk(e)).watts}function xu(e,t,r,n){let o=Yh(e,r,n);if(!Number.isFinite(o))return 1/0;if(o<=0)return 0;let a=Math.max(AD,t),s=Hh(e),i=o*(e.effi_pgb?.value??.9)/a;return o*s(t,i)/a}var FD=180/Math.PI;function Ru(e,t,r,n){let o=e*t,a=e*(1-t);return o/r-a/n}var vu=e=>e*9.81*FD;var t9=Math.PI/180;function ku(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?Ru(e.massTotal,e.frontMassFrac,2*i,2*c):0,u=vu(l),m=u>.15?"understeer":u<-.15?"oversteer":"neutral";return{gradient:u,balance:m,cAlphaFront:i,cAlphaRear:c}}var l9=Math.PI/180,u9=180/Math.PI;var dk=2220446049250313e-31;function TD(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 h=0;h<t;h++)e[a][h]*=m;for(let h=0;h<t;h++)e[h][a]*=l}}}}}function PD(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 LD(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])<=dk*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 h=.5*(u-l),d=h*h+m,p=Math.sqrt(Math.abs(d));l+=s,d>=0?(p=h+(h>=0?Math.abs(p):-Math.abs(p)),r[a-1]=r[a]=l+p,p!==0&&(r[a]=l-m/p),n[a-1]=n[a]=0):(r[a-1]=r[a]=l+h,n[a]=p,n[a-1]=-p),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 h=a-2,d=0,p=0,f=0;for(;h>=c;h--){let b=e[h][h],g=l-b,y=u-b;d=(g*y-m)/e[h+1][h]+e[h][h+1],p=e[h+1][h+1]-b-g-y,f=e[h+2][h+1];let R=Math.abs(d)+Math.abs(p)+Math.abs(f);if(d/=R,p/=R,f/=R,h===c)break;let M=Math.abs(e[h][h-1])*(Math.abs(p)+Math.abs(f)),v=Math.abs(d)*(Math.abs(e[h-1][h-1])+Math.abs(b)+Math.abs(e[h+1][h+1]));if(M<=dk*v)break}for(let b=h+2;b<=a;b++)e[b][b-2]=0,b!==h+2&&(e[b][b-3]=0);for(let b=h;b<=a-1;b++){b!==h&&(d=e[b][b-1],p=e[b+1][b-1],f=b!==a-1?e[b+2][b-1]:0,l=Math.abs(d)+Math.abs(p)+Math.abs(f),l!==0&&(d/=l,p/=l,f/=l));let g=Math.sqrt(d*d+p*p+f*f),y=d>=0?g:-g;if(y!==0){b===h?c!==h&&(e[b][b-1]=-e[b][b-1]):e[b][b-1]=-y*l,d+=y,l=d/y,u=p/y;let R=f/y;p/=d,f/=d;for(let v=b;v<=a;v++){let x=e[b][v]+p*e[b+1][v];b!==a-1&&(x+=f*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*f),e[v][b+1]-=x*p,e[v][b]-=x}}}}}}while(c<a-1&&a>=0)}return r.map((i,c)=>({re:i,im:n[c]}))}function fk(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 TD(r),PD(r),LD(r)}function hk(e){let t=[],r=new Array(e.length).fill(!1),n=fk(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 Wh(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 f=c;f<r;f++)for(let b=c;b<r;b++){let g=e[f][b]*e[f][b]+t[f][b]*t[f][b];g>m&&(m=g,l=f,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 f=0;f<r;f++)[e[f][c],e[f][u]]=[e[f][u],e[f][c]],[t[f][c],t[f][u]]=[t[f][u],t[f][c]];[n[c],n[u]]=[n[u],n[c]]}let h=e[c][c],d=t[c][c],p=h*h+d*d;for(let f=c+1;f<r;f++){let b=(e[f][c]*h+t[f][c]*d)/p,g=(t[f][c]*h-e[f][c]*d)/p;if(!(b===0&&g===0))for(let y=c;y<r;y++)e[f][y]-=b*e[c][y]-g*t[c][y],t[f][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 h=0,d=0;for(let p=c+1;p<r;p++)h+=e[c][p]*o[p]-t[c][p]*a[p],d+=e[c][p]*a[p]+t[c][p]*o[p];o[c]=-(h*l+d*u)/m,a[c]=-(d*l-h*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 DD(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 Wh(r,n)}function Mu(e,t=r=>DD(e,r)){return hk(e).map(r=>({...r,vector:t(r.eigenvalue)}))}function ga(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 bk(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 ga(Mu(i),c,0)}function gk(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=bk({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 Su(e,t,r){let n=we(e);return{front:gk(e,n,"front",t??n.rideDampingFront),rear:gk(e,n,"rear",r??n.rideDampingRear)}}var M9=180/Math.PI;var jh=["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},ya=20,yk=[ce.zFL,ce.zFR,ce.zRL,ce.zRR],xk=[ce.vzFL,ce.vzFR,ce.vzRL,ce.vzRR],Nr={fzFL:0,fzFR:1,fzRL:2,fzRR:3,fzBody:4,myBody:5,mxBody:6,fx:7,fy:8,mz:9},Uh=10;function Au(e){let t=Array.from({length:ya},()=>new Array(ya).fill(0)),r=Array.from({length:ya},()=>new Array(Uh).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[yk[i]]-=c,s[xk[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),h=e.damperRate[s]+c(e.rollDamper),d=(l+u)/2,p=(l-u)/2,f=(m+h)/2,b=(m-h)/2,g=new Array(ya).fill(0);a(g,s,d,f),(p!==0||b!==0)&&a(g,o[s],p,b);let y=e.wheelMass[s],R=e.leverX[s],M=e.leverY[s],v=yk[s],x=xk[s];for(let k=0;k<ya;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][Nr.fzFL+s]=1/y}return r[ce.vzBody][Nr.fzBody]=1/e.bodyMass,r[ce.pitchRate][Nr.myBody]=1/n.yy,r[ce.rollRate][Nr.mxBody]=1/n.xx,r[ce.vx][Nr.fx]=1/e.totalMass,r[ce.vy][Nr.fy]=1/e.totalMass,r[ce.yawRate][Nr.mz]=1/n.zz,{A:t,B:r,params:e}}function Xh(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,h=Ue(e,"front")*1e3,d=Ue(e,"rear")*1e3,p=(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:[h,h,d,d],tyreDamping:[p,p,p,p],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 Rk=ce.rollRate+1;function vk(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,Rk).map(i=>i.slice(0,Rk));if(!n.every(i=>i.every(Number.isFinite)))return{};let a=Mu(n,i=>{let c=i.re*i.re-i.im*i.im,l=2*i.re*i.im,u=r.map((h,d)=>r.map((p,f)=>(d===f?c:0)-i.re*n[2*d+1][2*f+1]-n[2*d+1][2*f])),m=r.map((h,d)=>r.map((p,f)=>(d===f?l:0)-i.im*n[2*d+1][2*f+1]));return Wh(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:ga(a,s,1),pitch:ga(a,s,2),roll:ga(a,s,3)}}function kk(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 Fu(e){let t=we(e),r=e.wheelbase/1e3,n=r*(1-e.frontMassFrac),o=r*e.frontMassFrac,a=t.rollRateTotal*(180/Math.PI),s=e.rollInertia??t.sprungMass*.6*.6,i=2*t.rideRateFront*1e3,c=2*t.rideRateRear*1e3,l=i*n*n+c*o*o,u=e.pitchInertia??t.sprungMass*1.2*1.2,m=vk(Au(Xh(e)));return{roll:kk(m.roll,a,s),pitch:kk(m.pitch,l,u)}}var Cu=9.81,Or=Math.PI/180;function Mk(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 xa(e,t,r,n,o){let{wb:a,lf:s,lr:i,m:c}=Mk(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/Cu,0,r),F=Math.max(0,k.FL+k.FR),C=Math.max(0,k.RL+k.RR),w=t(v,F),T=t(x,C),S=(w*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,h=-n+i*u/r,d=Le(e,l/Cu,0,r),p=Math.max(0,d.FL+d.FR),f=Math.max(0,d.RL+d.RR),b=t(m,p),g=t(h,f),y=s*b*Math.cos(o)-i*g;return{ay:l/Cu,cn:y/(c*Cu*a)}}function qh(e,t,r,n={}){let o=Math.max(8,r),a=(n.betaMaxDeg??10)*Or,s=(n.deltaMaxDeg??10)*Or,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:[]},h=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),C=xa(e,t,o,F,y);R.push(C.ay),M.push(C.cn),v.push(F/Or),x.push(y/Or),Math.abs(C.ay)>h&&(h=Math.abs(C.ay))}u.push({label:`\u03B4 ${(y/Or).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 d=[];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),C=xa(e,t,o,y,F);R.push(C.ay),M.push(C.cn),v.push(y/Or),x.push(F/Or)}d.push({label:`\u03B2 ${(y/Or).toFixed(0)}\xB0`,ay:R,cn:M,betaDeg:v,deltaDeg:x})}let p=.5*Or,f=(xa(e,t,o,p,0).cn-xa(e,t,o,-p,0).cn)/(2*p),b=(xa(e,t,o,0,p).cn-xa(e,t,o,0,-p).cn)/(2*p);return{isoBeta:d,isoDelta:u,trim:m,maxAy:h,stability:f,control:b,speed:o}}function ED(e){return!e.corneringStiffnessFront||!e.corneringStiffnessRear?null:{Cf:2*e.corneringStiffnessFront,Cr:2*e.corneringStiffnessRear}}function pi(e,t){let r=ED(e);if(!r)return null;let{Cf:n,Cr:o}=r,{wb:a,lf:s,lr:i,m:c}=Mk(e),l=e.yawInertia??c*1*1,u=Math.max(3,t),m=-(n+o)/(c*u),h=(-s*n+i*o)/(c*u)-u,d=(-s*n+i*o)/(l*u),p=-(s*s*n+i*i*o)/(l*u),f=m+p,b=m*p-h*d,g=f*f-4*b,y,R,M;if(g<0)y=f/2,R=Math.sqrt(Math.max(0,b)),M=R>0?-f/(2*R):1;else{let P=Math.sqrt(g);y=Math.max((f+P)/2,(f-P)/2),R=Math.sqrt(Math.abs(b)),M=R>0?-f/(2*R):1}let v=f<0&&b>0,x=Ru(c,e.frontMassFrac,n,o),k=vu(x),F=k>.15?"understeer":k<-.15?"oversteer":"neutral",C=s*n-i*o,w=P=>P*3.6,T=null,S=null;C>1e-6?S=w(Math.sqrt(n*o*a*a/(c*C))):C<-1e-6&&(T=w(Math.sqrt(n*o*a*a/(c*-C))));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 Sk=Math.PI/180;function Ck(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 Ak(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 wk(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,h]of[[s,1-c],[Math.min(o-1,s+1),c]])if(!(h<=0))for(let[d,p]of[[i,1-l],[Math.min(a-1,i+1),l]])p<=0||(u+=h*p*n(e.isoDelta[m],d,m));return u}function Tk(e,t,r){let n=e.isoDelta[0],o=(n.betaDeg[1]-n.betaDeg[0])*Sk||1,a=e.isoDelta.length>1?(e.isoDelta[1].deltaDeg[0]-e.isoDelta[0].deltaDeg[0])*Sk:1,s=x=>wk(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)=>Ak(x.cn,k,o)),h=s((x,k,F)=>Ak(e.isoDelta.map(C=>C.cn[k]),F,a||1)),d=Math.max(1e-6,e.maxAy),p=Math.abs(i)/d,f=Math.max(1e-6,...e.isoDelta.flatMap(x=>x.cn.filter(Number.isFinite).map(Math.abs))),b=Math.abs(c)/f,g=i===0?c:c*Math.sign(i),y=[];y.push(`${Ck(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(h)/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.`),p>.97?y.push(`At the edge of the diagram: ${Math.abs(i).toFixed(2)} g is essentially all this car has at this speed.`):p<.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:h,gripUsed:p,notes:y}}var Fk=1e-4;function Qh(e){let t=null,r=h=>{if(!t)return!0;let d=Math.abs(h),p=Math.abs(t.ay);return d>p*(1+Fk)?!0:d<p*(1-Fk)?!1:h>0&&t.ay<0};for(let h=0;h<e.isoDelta.length;h++){let d=e.isoDelta[h];for(let p=1;p<d.cn.length;p++){if(!(d.cn[p-1]===0||d.cn[p-1]<0!=d.cn[p]<0))continue;let b=d.cn[p-1]===d.cn[p]?0:d.cn[p-1]/(d.cn[p-1]-d.cn[p]),g=d.ay[p-1]+b*(d.ay[p]-d.ay[p-1]);r(g)&&(t={ay:g,d:h,b:b<.5?p-1:p})}}if(!t)return null;let n=Tk(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 ID=["tv_kp"];function Pk(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"},...ID.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 _D=Pk(0);function Lk(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 ND=Lk(0);var OD=9.81;function VD(e){let t=e.wheelbase/1e3;return{lf:t*(1-e.frontMassFrac),lr:t*e.frontMassFrac}}function di(e,t,r,n){let o=t.tire;if(!o)return null;let s=(r==="limit"?yh(e,o,t.speed):nn(e,o,t.speed,t.ayG)).wheels;return yr(n??_n(o,e.massTotal*OD*1.2),{FL:s.FL,FR:s.FR,RL:s.RL,RR:s.RR},VD(e))}function BD(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 Dk=[{key:"understeer",label:"Understeer gradient",unit:"\xB0/g",compute:(e,t)=>ku(e,t.ayG,BD(t),t.speed).gradient},{key:"rollGradient",label:"Roll gradient",unit:"\xB0/g",compute:e=>we(e).rollGradient},{key:"pitchGradient",label:"Pitch gradient",unit:"\xB0/g",compute:e=>we(e).pitchGradient},{key:"tlltdFront",label:"TLLTD front",unit:"%",compute:e=>100*Ld(e)},{key:"rollStiffFront",label:"Front roll-stiffness",unit:"%",compute:e=>100*we(e).frontRollStiffFrac},{key:"rideFreqFront",label:"Ride freq front",unit:"Hz",compute:e=>we(e).rideFreqFront},{key:"rideFreqRear",label:"Ride freq rear",unit:"Hz",compute:e=>we(e).rideFreqRear},{key:"rollFreq",label:"Roll-mode freq",unit:"Hz",compute:e=>Fu(e).roll.freq},{key:"pitchFreq",label:"Pitch-mode freq",unit:"Hz",compute:e=>Fu(e).pitch.freq},{key:"zetaFront",label:"Damping \u03B6 front",unit:"-",compute:e=>Su(e).front.dampingRatio},{key:"zetaRear",label:"Damping \u03B6 rear",unit:"-",compute:e=>Su(e).rear.dampingRatio},{key:"yawFreq",label:"Yaw natural freq",unit:"Hz",compute:(e,t)=>pi(e,t.speed)?.yawFreq??NaN},{key:"yawZeta",label:"Yaw damping \u03B6",unit:"-",compute:(e,t)=>pi(e,t.speed)?.dampingRatio??NaN},{key:"stabilitySpeed",label:"Char./critical speed",unit:"km/h",compute:(e,t)=>{let r=pi(e,t.speed);return r?r.criticalSpeed??r.characteristicSpeed??NaN:NaN}},{key:"maxAy",label:"Max lateral accel",unit:"g",compute:(e,t)=>t.fyAxle?qh(e,t.fyAxle,t.speed,{betaMaxDeg:12,deltaMaxDeg:12}).maxAy:NaN},{key:"yawReserveRear",label:"Yaw stability reserve",unit:"N\xB7m",compute:(e,t)=>di(e,t,"operating")?.stabil??NaN},{key:"yawReserveFront",label:"Yaw agility reserve",unit:"N\xB7m",compute:(e,t)=>di(e,t,"operating")?.agil??NaN},{key:"limitBalance",label:"Limit balance (+US / \u2212OS)",unit:"-",compute:(e,t)=>di(e,t,"limit")?.rel??NaN},{key:"yawStiffness",label:"Yaw stiffness N_\u03B2",unit:"N\xB7m/rad",compute:(e,t)=>t.tire?gh(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorque",label:"Steering holding torque",unit:"N\xB7m",compute:(e,t)=>t.tire?hh(e,t.tire,t.speed,t.ayG):NaN},{key:"steeringTorqueGradient",label:"Steering feedback gradient",unit:"N\xB7m/g",compute:(e,t)=>t.tire?bh(e,t.tire,t.speed,t.ayG):NaN}],Zh=Object.fromEntries(Dk.map(e=>[e.key,e]));var Vr=9.81;function $D(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 GD={front:!1,rear:!0};function Ra(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 Ek(e,t,r,n,o,a){let s=e[t]+e[r];if(!(s>0))return;let i=Ra(n,o[t],a[t]),c=Ra(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 Ik(e,t,r,n,o,a={},s="open"){if(!e.rear)return 1;if(!e.front)return 0;let i=(h,d,p)=>p?_s(h,d,p):s==="own"?h+d:2*Math.min(h,d),c=i(Ra(n,t.FL,r.FL),Ra(n,t.FR,r.FR),a.front),l=i(Ra(o,t.RL,r.RL),Ra(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 Jh(e,t,r,n){return{car:t?Ok(t,r.loadFactor[n]):e,ayTyre:Ye(r.ay[n],r.bank?.[n]??0),axCar:r.ax[n]-(r.axGrade?.[n]??0)}}function _k(e,t){if(!e.aero?.model)return 0;let r=Math.min(t.v.length,t.ax.length,t.ay.length),n=t.loadFactor?Tu(e):void 0,o=0,a=0;for(let s=0;s<r;s++){let i=t.ds?.[s]??1,c=Jh(e,n,t,s);o+=i,Pd(c.car,t.v[s],c.axCar/Vr,c.ayTyre/Vr)&&(a+=i)}return o>0?a/o:0}function Nk(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?Tu(e):void 0,i=0,c=0;for(let l=0;l<a;l++){let u=r.ds?.[l]??1,m=Jh(e,s,r,l);i+=u;let h=Le(m.car,m.ayTyre/Vr,m.axCar/Vr,r.v[l]);(h.FL>n||h.FR>n||h.RL>o||h.RR>o)&&(c+=u)}return i>0?c/i:0}function wu(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=Ks(t,e.massTotal*Vr*1.2),l=Uo(c,"front"),u=Uo(c,"rear"),m=it(xe(t,"front")),h=it(xe(t,"rear")),d=n.perWheel?_d(m,l):null,p=n.perWheel?h===m?d:_d(h,u):null,f=n.driven??GD,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),C=Ht(h),w=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?Tu(e):void 0;for(let O=0;O<o;O++){let W=Jh(e,G,r,O),{ayTyre:E,axCar:_}=W,V=E/Vr,N=Le(W.car,V,_/Vr,r.v[O]),$=e.massTotal*E,K=$*i/a,z=$*s/a,j=bs(m,K,N.FL,N.FR,P),Q=bs(h,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(h.Fy(Q,N.RL,0)),RR:Math.abs(h.Fy(Q,N.RR,0))},te=(_-(r.axDrag?.[O]??0)-(r.axScrub?.[O]??0))/Vr,fe=te>0&&f.front?Ik(f,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={...mh(e,te,r.v[O],t,V,fe,J)};te>0&&(b.front||Ek(re,"FL","FR",l,N,ne),b.rear||Ek(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:C)&&(de=!0)}de&&(k+=r.ds?.[O]??1);let ie=yr(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 Ce=N[Re],Ge=Re==="FL"||Re==="FR",We=Ge?l:u,be=We.muY(Ce)*Ce,Fe=We.muX(Ce)*Ce,ye=I[Re],me=Ge?j:Q;ye.Fz[O]=Ce,ye.alpha[O]=me,ye.Fy[O]=ne[Re],ye.Fx[O]=re[Re],ye.Mz[O]=Ce>0?(Ge?m:h).Mz(me,Ce,0):0,ye.FxCap[O]=Fe,ye.FyCap[O]=be;let Te=be>0?Math.min(1,Math.abs(ne[Re])/be):0,Se=$D(re[Re],Fe,Ge?Ae:le),Ke=Ge?d:p,je=Ke&&Ce>0?Ke.reach(Ce,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&&(w+=oe),pe&&(T+=oe),Pd(W.car,r.v[O],_/Vr,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?w/A:0,beyondFrac:A>0?T/A:0,aeroOutsideFrac:A>0?S/A:0,wheels:I}}function Tu(e){return Object.create(e,{loadFactor:{value:1,writable:!0,enumerable:!0}})}function Ok(e,t){return e.loadFactor=t,e}var eb=9.81;function tb(e,t,r,n={}){let o=r.v.length,a=e.massTotal,s=wr(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),h=m-(r.axDrag?.[l]??0)-(r.axScrub?.[l]??0),d=-a*h;if(!(d>0))continue;let p=Ye(r.ay[l],r.bank?.[l]??0)/eb,f=Math.min(.99,Math.max(.01,na(e,h/eb,u,t,p)));c.front[l]=d*f,c.rear[l]=d*(1-f);let b=i?Vl(e,t,d,u,p):void 0;if(c.regen&&n.regen&&(c.regen[l]=b?Math.min(d,b.regenFront+b.regenRear):n.regen(d,u,m/eb)),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(d,u),u);c.pFront[l]=g.pFront,c.pRear[l]=g.pRear,c.pedalN[l]=g.pedalN}}return c}var EX=Math.PI/180;var IX=jh.map(Hs);var _X=[ce.zFL,ce.zFR,ce.zRL,ce.zRR];var NX=Array.from({length:ce.rollRate+1},(e,t)=>t);var eE=9.81,tE=.001,rE=.6,nE=2,Gk=4;function Kk(e,t,r,n=Gk){let o=Math.min(e.v.length,t.npts),{ds:a,closed:s}=t,i=r.massTotal*eE*r.wheelbase,c=oE(e.ay.slice(0,o).map((m,h)=>m/Math.max(tE,e.v[h])),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 h=m===0?s?o-1:-1:m-1,d=m===o-1?s?0:-1:m+1;if(h<0||d<0)continue;let p=a[h]+a[m];if(!(p>0))continue;u[m]=e.v[m]*(c[d]-c[h])/p;let f=Math.sign(c[m]);l[m]=f===0?0:f*r.yawInertia*u[m]/i}return{demand:l,rdot:u}}function oE(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,h=0;for(let d=1;d<=s&&!(!r&&c+d>=o||(h+=t[(c+d-1)%o],!(h<l)));d++){let p=1-h/l;u+=p*e[(c+d)%o],m+=p}h=0;for(let d=1;d<=s&&!(!r&&c-d<0);d++){let p=(c-d+o)%o;if(h+=t[p],!(h<l))break;let f=1-h/l;u+=f*e[p],m+=f}i[c]=u/m}return i}function Hk(e,t,r,n,o={}){let a=o.maxIter??20,s=o.tol??.001,i=Math.min(1,Math.max(.001,o.relax??rE)),c=o.smoothM??Gk,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=bt(e.steady,t,n,l),m=[u.laptime],h=new Array(t.npts).fill(0),d=h.slice(),p=u,f=0,b=!1,g=0;for(let M=0;M<a;M++){f=M+1;let v=Kk(p,t,r,c);h=v.demand.map((F,C)=>h[C]+i*(F-h[C])),d=v.rdot;let x=bt(e.steady,t,n,{...l,envelope:F=>e.at(h[F]??0)});m.push(x.laptime);let k=Math.abs(x.laptime-p.laptime);if(p=x,g=k<=s?g+1:0,g>=nE){b=!0;break}}let y=0,R=0;for(let M=0;M<t.npts;M++)R+=t.ds[M],e.clamps(h[M]??0)&&(y+=t.ds[M]);return{...p,steady:u,demand:h,rdot:d,history:m,iterations:f,converged:b,clampedFrac:R>0?y/R:0}}var YX=Math.PI/180;var M7=180/Math.PI;function va(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=h=>{let d=e[h];return i*(r-s)*(r-d)/((a-s)*(a-d))+c*(r-a)*(r-d)/((s-a)*(s-d))+t[h]*(r-a)*(r-s)/((d-a)*(d-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 Yk(e,t){let r=e.filter(d=>d.atLock),n=e.filter(d=>!d.atLock),o=r.length>0&&n.length>0&&r[r.length-1].v<n[0].v,a=d=>({vs:d.map(f=>f.v),ayMax:d.map(f=>f.ayMax),radius:d.map(f=>Math.max(f.v,t)**2/f.ayMax),accel:d[0].axAccelN.map((f,b)=>d.map(g=>g.axAccelN[b])),decel:d[0].axDecelN.map((f,b)=>d.map(g=>g.axDecelN[b])),scrub:d[0].axScrubN.map((f,b)=>d.map(g=>g.axScrubN[b]))}),s=(d,p)=>({axAccelN:d.accel.map(f=>va(d.vs,f,p)),axDecelN:d.decel.map(f=>va(d.vs,f,p)),axScrubN:d.scrub.map(f=>va(d.vs,f,p))});if(!o){let d=a(e);return p=>({ayMax:va(d.vs,d.ayMax,p),...s(d,p)})}let i=a(r),c=a(n),l=i.vs[i.vs.length-1],u=c.vs[0],m=d=>Math.max(d,t)**2/va(i.vs,i.radius,d),h=d=>d>=u||c.vs.length<2?va(c.vs,c.ayMax,d):c.ayMax[0]+(c.ayMax[1]-c.ayMax[0])/(c.vs[1]-c.vs[0])*(d-u);return d=>{if(d<=l)return{ayMax:m(d),...s(i,d)};if(d>=u)return{ayMax:h(d),...s(c,d)};let p=m(d),f=h(d);return p<f?{ayMax:p,...s(i,d)}:{ayMax:f,...s(c,d)}}}function vE(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 Wk(e,t,r,n,o){let a=r>t?Math.max(2,Math.min(5,Math.floor(n))):1,s=[];for(let h=0;h<a;h++)s.push(e(a===1?t:t+(r-t)*h/(a-1)));let i=Yk(s,t),c=[],l=a,u=(h,d)=>{let p=.5*(h+d),f=e(p);l++;let b=vE(i(p),f);s.splice(s.findIndex(g=>g.v>p),0,f),i=Yk(s,t),b>o&&c.push({lo:h,hi:p,misfit:b},{lo:p,hi:d,misfit:b})},m=s.map(h=>h.v);for(let h=0;h+1<m.length&&l<n;h++)m[h+1]-m[h]>=1&&u(m[h],m[h+1]);if(m.length>1){let h=.5*(m[0]+m[1]);if(s.some(d=>d.v===h))for(let[d,p]of[[m[0],h],[h,m[1]]]){if(l>=n||p-d<1)break;let f=c.findIndex(b=>b.lo===d&&b.hi===p);f>=0&&c.splice(f,1),u(d,p)}}for(;l<n&&c.length>0;){let h=0;for(let b=1;b<c.length;b++)c[b].misfit>c[h].misfit&&(h=b);let{lo:d,hi:p,misfit:f}=c.splice(h,1)[0];if(f<=o)break;p-d<1||u(d,p)}return{anchors:s,at:i}}var kE=2,ME=.5,fi=Math.PI/180,jk=21,SE={nCoarse:11,nSteer:13,nNorm:41,nAngle:45},AE={nCoarse:11,nSteer:13,nNorm:41,nAngle:61},FE=.005,CE=.05,rb=e=>e<0?0:e>1?1:e;function wE(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*fi,u=0,m=(b,g,y)=>{for(let R=b;R<=g;R+=y){let M=Math.abs(t.Fy(R*fi,c,0));M>u&&(u=M,l=R*fi)}};m(1,45,1),m(Math.max(.1,l/fi-1),l/fi+1,.1);let h=[],d=[],p=[],f=[];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));h.push(4*R/o),d.push(s*kt(t,c,R,!1)/o),p.push(4*kt(t,c,R,!0)/o),f.push(-4*R*Math.sin(y)/o)}return h[0]=0,{ayMax:4*u/o,ay:h,axAccel:d,axDecel:p,axScrub:f,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?AE:SE),{nCoarse:c,nSteer:l,nAngle:u}=i,m=Cr(0,1,i.nNorm).map(V=>Math.sin(Math.PI/2*V)),h=e.params,d=h.m.value,p=h.rho.value,f=h.fr_0.value,b=h.driven_wheels.value,g=h.power_scale.value,y=e.FG,R=lt(h);s!==1&&(R.loadFactor=s);let M=sr(h),v=nv(0,n?.vRes??(e.engine?ME:kE),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:C}=Yn(e),w=zn(h,F,C),T=(V,N)=>{let $=k?St(k.vVehicle,V,N):NaN;return Number.isFinite($)?$:1/0},S=V=>{let N=V*V,{cl:$,cw:K,A:z}=fu(h,V,0,R),j=.5*p*-K*z*N,Q=.5*p*-$*z*N,ne=f*(-Q+y);return j+ne},A=V=>{let N=S(V)/d*w.powerFactor,$=S(V)/d*w.tractionFactor,K;if(e.engine){let j=S(V);K=ea(e.engine,V,w.effective,j,g).accel-N}else if(k){let j=0;F&&(j+=T(k.fFront,V)),C&&(j+=T(k.fRear,V)),K=g*j/d*w.powerFactor}else{let j=St(e.vVehicle,x,V),Q=g*j/d*w.powerFactor;K=Number.isFinite(Q)?Q:1/0}let z=xu(h,V,o)/d*w.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+CE)*L),I=r==="fast"?wE:Rh,G=V=>{let N=I(R,M,V,{drivenFront:F,drivenRear:C,nSteer:l,yawDemandCn:a,axDrag:S(V)/d,...h.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=>Tl(N.ay,N.axAccel,z(te))*w.tractionFactor),Q=m.map(te=>Tl(N.ay,N.axDecel,z(te))),ne=m.map(te=>Tl(N.ay,N.axScrub,z(te))*w.tractionFactor);return{v:V,ayMax:N.ayMax,axAccelN:j,axDecelN:Q,axScrubN:ne,atLock:N.atLock===!0}},O=r==="fast"?0:Math.min(Yl,D),W=Wk(G,O,D,c,i.anchorTol??FE),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=rb(Math.abs(Math.cos(ie)));J.push({ax:Math.min(St(m,te,ue)+K,Q+$)+St(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=rb(Math.abs(Math.cos(ie)));re.push({ax:St(m,fe,ue)+$+St(m,Y,ue),ay:oe,v:N})}let pe=(de,ie,oe)=>Array.from({length:jk},(ue,Ve)=>({ax:ie+(oe-ie)*(Ve+1)/(jk+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{...Xk(E,m),rows:E,norm:m,surf:_}}function ka(e,t){return e?.length?t.map(r=>Lu(e,r)):t.map(()=>0)}function Lu(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 Xk(e,t){let r=e[e.length-1].v,n=p=>{if(p<=e[0].v)return{i0:0,i1:0,t:0};if(p>=r)return{i0:e.length-1,i1:e.length-1,t:0};let f=0,b=e.length-1;for(;b-f>1;){let g=f+b>>1;e[g].v<=p?f=g:b=g}return{i0:f,i1:b,t:(p-e[f].v)/(e[b].v-e[f].v)}},o=p=>{let{i0:f,i1:b,t:g}=n(p);return{a:e[f],b:e[b],t:f===b?0:g}},a=(p,f,b)=>p===0||f===b?f:f+p*(b-f),s=(p,f,b,g)=>p===0?St(t,f,g):a(p,St(t,f,g),St(t,b,g)),i=(p,f)=>f>=1?p.axPower:Math.min(f*p.axDrive,p.axPackCap),c=({a:p,b:f,t:b},g,y)=>p.axScrubN?y*s(b,p.axScrubN,f.axScrubN,g):0,l=p=>p.axDragTyre??p.axDrag,u=({a:p,b:f,t:b},g,y)=>{let R=y*a(b,p.ayMax,f.ayMax);return R>0?rb(g/R):1},m=(p,f,b=1,g=1)=>{let{a:y,b:R,t:M}=p,v=u(p,f,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(p,v,b)},h=(p,f,b=1,g=1)=>{let{a:y,b:R,t:M}=p,v=u(p,f,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(p,v,b)},d=({a:p,b:f,t:b},g,y=1)=>{let R=t.length-1,M=p.axAccelN,v=f.axAccelN,x=p.axDecelN,k=f.axDecelN,F=p.axScrubN,C=f.axScrubN,w=I=>M[I]+b*(v[I]-M[I]),T=I=>x[I]+b*(k[I]-x[I]),S=I=>F?y*(F[I]+b*(C[I]-F[I])):0,A=a(b,p.ayMax,f.ayMax),P=a(b,p.axDrag,f.axDrag),L=a(b,l(p),l(f)),D=a(b,p.axPower,f.axPower);for(let I=R;I>=0;I--){let G=Math.min(y*w(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*w(I)+L+S(I),y*w(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:(p,f,b=1,g=1)=>m(o(p),f,b,g),axDecel:(p,f,b=1,g=1)=>h(o(p),f,b,g),ay:(p,f,b=1)=>d(o(p),f,b),scrub:(p,f,b=1)=>{let g=o(p);return c(g,u(g,f,b),b)}}}function TE(e,t,r){let n=e.params,o=n.m.value,{drivenFront:a,drivenRear:s}=Yn(e),i=zn(n,a,s);return c=>xu(n,c,t,r)/o*i.powerFactor}function hi(e,t,r,n){let o=TE(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{...Xk(a,e.norm),rows:a,norm:e.norm}}var PE=[-.2,-.08,0,.06,.12,.2,.3];function qk(e,t=!1,r="twoTrack",n,o,a=PE){let s=[...new Set([...a,0])].sort((p,f)=>p-f),i=s.map(p=>ir(e,t,r,n,o,p)),c=i[s.indexOf(0)],l=s[0],u=s[s.length-1],m=p=>{if(p<=l)return{i:0,t:0};if(p>=u)return{i:s.length-1,t:0};let f=0;for(;f<s.length-2&&s[f+1]<=p;)f++;return{i:f,t:(p-s[f])/(s[f+1]-s[f])}},h=p=>{let f=b=>{let{i:g,t:y}=m(b);return{a:p[g],b:p[Math.min(p.length-1,g+1)],t:y}};return b=>{let{a:g,b:y,t:R}=f(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)}}},d=p=>p<l||p>u;return{anchors:s,steady:c,clamps:d,at:h(i),atSoc(p,f,b){let g=i.map(y=>hi(y,p,f,b));return{anchors:s,steady:g[s.indexOf(0)],clamps:d,at:h(g)}}}}function Qk(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{...Uk(a,s),atSoc:(i,c,l)=>Uk(a,s.map(u=>hi(u,i,c,l)))}}function Uk(e,t){let r=e.length-1,n=1,o=0,a=0,s=0,i=1,c=0,l=0,u=d=>{if(n=1,!(d>e[0]))return void(o=0);if(d>=e[r])return void(o=r);let p=0;for(;p<r-1&&e[p+1]<=d;)p++;if(o=p,d===e[p])return;a=p+1;let f=e[p],b=e[p+1];if(r<2){n=2,c=(d-f)/(b-f),i=1-c;return}s=p===0?2:p+1===r||d-e[p-1]<e[p+2]-d?p-1:p+2;let g=e[s];n=3,i=(d-b)*(d-g)/((f-b)*(f-g)),c=(d-f)*(d-g)/((b-f)*(b-g)),l=(d-f)*(d-b)/((g-f)*(g-b))},m=d=>{let p=d(t[o]);if(n===1)return p;let f=d(t[a]);if(n===2)return i*p+c*f;let b=i*p+c*f+l*d(t[s]);return Math.min(Math.max(p,f),Math.max(Math.min(p,f),b))},h=(d,p,f,b,g)=>{if(u(d),n===1||f===0)return m(M=>g(M,f));let y=m(M=>M.ay(p,0,b));if(!(y>0))return m(M=>g(M,f));let R=f/y;return m(M=>g(M,R*M.ay(p,0,b)))};return{anchors:e,axAccel:(d,p,f,b=1,g=1)=>h(d,p,f,b,(y,R)=>y.axAccel(p,R,b,g)),axDecel:(d,p,f,b=1,g=1)=>{let y=R=>h(d,p,f,b,(M,v)=>M.axDecel(p,v,b,R));return g===1?y(1):Oh(y(g),y(1),g)},scrub:(d,p,f,b=1)=>h(d,p,f,b,(g,y)=>g.scrub?.(p,y,b)??0),ay:(d,p,f,b=1)=>{if(u(d),n===1||f===0)return m(M=>M.ay(p,f,b));let g=M=>f>0?M.axAccel(p,0,b):-M.axDecel(p,0,b),y=m(g);if(!(y>0))return m(M=>M.ay(p,f,b));let R=f/y;return m(M=>M.ay(p,R*g(M),b))}}}var Zk=new WeakMap;function nb(e,t){let r=Zk.get(e);if(!r){let n=Fr(e).regen?zh(t??At(e)):void 0;r={inp:lt(e),ev:sr(e),...n?{regen:n}:{}},Zk.set(e,r)}return r}function ob(e,t,r){let n=nb(e,r);return tb(n.inp,n.ev,t,n.regen?{regen:n.regen}:{})}function ab(e){let t=ct(e);if(t.mode!=="hydraulic")return null;let r=a=>a.heat?{heat:xf(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 LE(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 sb(e,t,r,n,o,a=Mt){if(!e)return null;let s=LE(t);return{...e.front?{front:Sl(e.front.heat,e.front.discs,s.front,r,n,o.front,a)}:{},...e.rear?{rear:Sl(e.rear.heat,e.rear.discs,s.rear,r,n,o.rear,a)}:{}}}var DE=.5,EE=.02,IE=6,Du=9,Jk=1e-9,_E={FL:0,FR:0,RL:0,RR:0};function ib(e){return e?[...new Set([...e.padCurve.factor,1])].sort((t,r)=>t-r):[1]}function NE(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 eM(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 tM(e,t,r,n,o=()=>0){let a=Array.from({length:Du},(m,h)=>r*h/(Du-1)),s=$s(),{front:i,rear:c}=n,l=a.map(m=>{let h=o(m),d=f=>Tr(f,t,m,s).limitAt(0,0,_E,h).ax,p=d(e);return i.map(f=>c.map(b=>{if(f===1&&b===1)return 1;let g=p<0?d(NE(e,f,b))/p:1;return Math.abs(g-1)<Jk?1:g}))}),u=a[1]-a[0];return{share(m,h,d){if(h===1&&d===1)return 1;let p=u>0?Math.min(Du-2,Math.max(0,Math.floor(m/u))):0,f=u>0?Math.min(1,Math.max(0,(m-a[p])/u)):0,b=eM(i,h),g=eM(c,d),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]),C=v[x][g.i]+g.t*(v[x][k]-v[x][g.i]);return F+b.t*(C-F)},R=y(p)+f*(y(Math.min(Du-1,p+1))-y(p));return Math.abs(R-1)<Jk?1:R}}}function OE(e,t){let{front:r,rear:n}=t;return(o,a)=>e.share(a,r?.[o]??1,n?.[o]??1)}var VE=e=>(e.front??[]).every(t=>t===1)&&(e.rear??[]).every(t=>t===1);function rM(e,t,r){let n=e(),o=1,a=t(n);if(VE(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<IE;c++){let l=e(OE(r,s));o++;let u=Math.abs(l.laptime-n.laptime);if(n=l,u<EE){i=!0;break}a=t(n);let m=(p,f)=>p&&f?p.map((b,g)=>b+DE*((f[g]??1)-b)):p,h=m(s.front,a.front),d=m(s.rear,a.rear);s={...h?{front:h}:{},...d?{rear:d}:{}}}return{lap:n,pads:s,solves:o,converged:i}}function cn(e,t){let r=e.engine;if(!r||r.gears.length===0||t.length===0)return;let n=e.params,{drivenFront:o,drivenRear:a}=Yn(e),s=zn(n,o,a).effective,i=n.power_scale.value,{up:c,down:l}=If(r.engine.gearbox),u=r.engine.idleRpm,m=(h,d,p)=>(i*r.force(h,d)+p)/(s+r.inertiaMass(h,d));return{count:r.gears.length,up:c,down:l,kept:_f(r.engine.gearbox),limitRpm:r.engine.limitRpm,best:h=>ea(r,h,s,Lu(t,h)*s,i).gear,share:(h,d)=>{let p=Lu(t,h),f=p*s,b=ea(r,h,s,f,i);if(d===b.gear)return 1;let g=b.accel-p;return g>0?Math.min(1,Math.max(0,(m(h,d,f)-p)/g)):0},rpm:(h,d)=>r.slipping(h,d)?u:r.rpm(h,d),vIdle:h=>r.gears[h]?.vIdle??0}}var nM=new WeakMap;function lb(e){let t=nM.get(e.ggv);return t===void 0&&(t=cn(e.vehicle,e.ggv.rows)??null,nM.set(e.ggv,t)),t??void 0}function BE(e){return e.gear&&e.engineRpm&&e.shifting?{gear:e.gear,rpm:e.engineRpm,shifting:e.shifting}:{}}var Iu=class extends Error{constructor(t){super(t),this.name="EventError"}};function $E(e,t){let{ggv:r}=t,n=at(t.numerics),o=n.accelStep,a=Math.max(1,Math.round(e.distance/o)),s=fa(r,new Array(a+1).fill(0),n);s[0].v=e.vStart??0;for(let p=0;p<s.length-1;p++){let f=s[p],b=s[p+1];f.v>=b.v||(f.ax=r.axAccel(f.v,0),b.v=Math.min(r.vMax,Math.sqrt(Math.max(0,f.v*f.v+2*f.ax*o))))}let i=lb(t),c=i?gu(s.map(p=>p.v),new Array(a).fill(o),!1,i,(p,f,b)=>r.axAccel(f,0,1,b)):void 0;if(c){for(let p=0;p<=a;p++)s[p].v=c.v[p];for(let p=0;p<a;p++)s[p].ax=(s[p+1].v*s[p+1].v-s[p].v*s[p].v)/(2*o)}let l=0;for(let p=0;p<a;p++){let f=s[p].v+s[p+1].v;f>0&&(l+=2*o/f)}let u=s.slice(0,a).map(p=>p.v),m=s.slice(0,a).map(p=>p.ax),h=new Array(a).fill(o),d=h.map((p,f)=>f*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:d,x:d,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:pM(t,h,[...u,s[a].v],m,1)}}function GE(e,t){let r=Math.max(1,Math.round(e.laps??1)),[n]=fa(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=pM(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 _u(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 KE(e,t){let r=e.distance!=null?t.v_limit_endurance?.value??0:0;return r>0?r/3.6:void 0}function HE(e,t){if(e.distance==null||ut(t.motorModel))return 0;let r=t.endurance_reserve?.value??0;return r>0?Math.min(r,95)/100:0}var oM=1;function lM(e,t,r,n){return{v:r.v,ax:r.ax,ay:r.ay,ds:t.ds,axDrag:ka(e.ggv.rows,r.v),...r.axScrub?{axScrub:r.axScrub}:{},axGrade:n,...t.bank?{bank:t.bank}:{}}}var aM=new WeakMap;function uM(e){let t=e.vehicle.params;if(!t.brakeFade)return null;let r=aM.get(t);if(r===void 0){let n=ab(t),o=n?ct(t):null;if(!n||!o||o.mode!=="hydraulic")r=null;else{let a=nb(t,e.vehicle),s=e.ggv.rows,i=tM(a.inp,a.ev,e.vehicle.vMax,{front:ib(o.hydraulic.front.heat),rear:ib(o.hydraulic.rear.heat)},c=>ka(s,[c])[0]);r={discs:n,table:i}}aM.set(t,r)}return r}function zE(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=lb(e),u=(g,y)=>e.yaw?Hk(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}:{}}):bt(hi(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=sn(t.gradient,t.npts),h=g=>n.motorThermal?mk(e.vehicle,t.ds,e.energyOpts??Ar,y=>u(y,g),o,a,m,t.bank).lap:u(void 0,g),d=uM(e);if(!d)return h();let p=mi(n),f=r.discC??{front:p,rear:p};return rM(h,g=>{let y=sb(d.discs,ob(n,lM(e,t,g,m),e.vehicle),g.v,t.ds,f,p);return{...y?.front?{front:y.front.padFactor}:{},...y?.rear?{rear:y.rear.padFactor}:{}}},d.table).lap}function YE(e,t){let r=KE(e,t.vehicle.params),n=HE(e,t.vehicle.params);return n>0?UE(e,t,n,r):bi(e,t,r)}function Eu(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 sM=5,WE=.1,jE=.005,iM=12;function UE(e,t,r,n){let o=bi(e,t,n),a=1,s=(p,f,b)=>({...p,energyTarget:{reserve:r,capKmh:f===void 0?null:f*3.6,met:b,solves:a}}),i=Eu(o,r);if(i>=0)return s(o,n,!0);let c=Math.min(n??1/0,t.ggv.vMax),l=c/2,u=bi(e,t,l);a++;let m=Eu(u,r);for(;m<0&&l>sM&&a<iM;)c=l,i=m,l=Math.max(sM,l/2),u=bi(e,t,l),a++,m=Eu(u,r);if(m<0)return s(u,l,!1);let h=l,d=0;for(;a<iM&&c-l>WE&&m>jE;){let p=c-l,f=Math.min(c-.05*p,Math.max(l+.05*p,l+m*p/(m-i))),b=bi(e,t,f);a++;let g=Eu(b,r);g>=0?(l=f,m=g,u=b,h=f,d===1&&(i/=2),d=1):(c=f,i=g,d===-1&&(m/=2),d=-1)}return s(u,h,!0)}function mM(e,t,r){return r===0?e:e&&!t}function bi(e,t,r){let n=t.track;if(!n)throw new Iu(`Event "${e.id}" needs a track.`);let o=_u(e,n),a=e.standingStart??t.standingStart??!1,s=K=>mM(a,n.closed,K),i=t.vehicle.params,c=dr(ha(i)),l=c.capacityAh,u=i.soc.value,m=mi(i),h=yu(c,m),d=0,p=0,f=0,b=0,g=[],y=!1,R=-1/0,M=0,v=0,x=!1,k=-1/0,F=0,C=0,w=-1/0,T=(K,z,j=1)=>{K.tempMaxC>w&&(w=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,C+=(K.motorLossKwh??0)/j)},S=null,A,P=ab(i),L={front:m,rear:m},D=null,I=uM(t)!==null,G=(K,z)=>I&&(Math.abs(K.front-z.front)>oM||Math.abs(K.rear-z.rear)>oM),O=(K,z,j)=>{let Q=Yh(i,K,z);if(D&&D.launch===j&&!QE(Q,D.pw)&&!G(L,D.discC))return D.lap;let ne=zE(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=sn(n.gradient,n.npts),E=(K,z,j)=>ba(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=ob(i,lM(t,n,K,W),t.vehicle),_.set(K,j)),sb(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=h;x=!1,k=-1/0,F=0,C=0,w=-1/0;let ne=O(u,h,z),te=E(ne,u,h);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=h,oe=-1,ue=null,Ve=1;if(Y<=cb)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(XE,Math.max(2,Math.ceil(Y/(2*cb))));Ve=le;let Re=u,Ce=h;J=0,re=0,pe=0,de=0;for(let Ge=0;Ge<le;Ge++){let We=O(Re,Ce,z),be=E(We,Re,Ce),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,Ce+=(be.tempEndC-Ce)/le,Re<=0){oe=Math.round(n.npts*(Ge+1)/le),ue=be;break}}if(ie=Ce,oe>=0&&ue){A=N(K,ue,oe);break}u=Re}d+=J,p+=re,f+=pe,b+=de,Y<=cb&&(u=te.socEnd),h=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:d,entryTime:ne.laptime,socStart:j,socEnd:u,packTempStartC:Q,packTempEndC:h,packTempMaxC:Number.isFinite(w)?w: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:C}}:{},...Ae?{brakes:{...Ae.front?{front:cM(Ae.front)}:{},...Ae.rear?{rear:cM(Ae.rear)}:{}}}:{}}),S=ne}if(!S){let K=lb(t);S=bt(hi(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:d,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}:{},...BE(S)},energy:{consumed:p,loss:f,...ut(i.motorModel)?{}:{native:{value:b,unit:"Ah"}},remainingFraction:ut(i.motorModel)?1:u,...y?{motor:{peakWindingC:R,derateTimeFrac:d>0?M/d:0,lossKwh:v}}:{}},lapLog:g,...A?{incomplete:A}:{}}}var cb=.05;function cM(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 XE=4,qE=.001;function QE(e,t){return e===t?!1:!Number.isFinite(e)||!Number.isFinite(t)?!0:Math.abs(e-t)>qE*Math.max(1,Math.abs(t))}function pM(e,t,r,n,o,a){return ZE(e,t,o,()=>({v:r,ax:n,...a?{lateral:a}:{}}))}function ZE(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=ba(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 ut(e.vehicle.params.motorModel)?{consumed:s,loss:i,remainingFraction:1}:{consumed:s,loss:i,native:{value:c,unit:"Ah"},remainingFraction:a}}function dM(e,t){switch(e.kind){case"straightLineAccel":return $E(e,t);case"constantRadius":return GE(e,t);case"trackLap":return YE(e,t)}}function ub(e,t){let r={};for(let n of e)r[n.id]=dM(n,t);return r}function fM(e,t){if(e.kind!=="trackLap")return e;let{distance:r,...n}=e;return{...n,laps:Math.max(1,Math.round(t))}}function Wn(e,t,r,n,o="twoTrack",a){let s=1/0,i=-1/0;for(let h of r){let d=ci(h);if(!d)continue;let p=Q1(d,bt(t,h,n).v);p&&(s=Math.min(s,p.lo),i=Math.max(i,p.hi))}if(!(i>=s))return;let c=Z1({lo:s,hi:i}),l=c.join(","),u=a?.get(l);if(u)return u;let m=Qk(e,c,t,o);return a?.set(l,m),m}var Nu=e=>e.distance/Math.max(1,e.laps);function Ou(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 JE=e=>e.v.map(t=>t*3.6),eI=e=>e.ax.map(t=>t/9.81),tI=e=>e.ay.map(t=>t/9.81),rI=e=>e.ay.map((t,r)=>e.v[r]>1e-6?t/(e.v[r]*e.v[r]):0),Vu=(e,t,r)=>e?.slice()??new Array(t.s.length).fill(r),nI=e=>Vu(e.z,e,0),oI=e=>e.gradient?e.gradient.map(t=>100*Math.tan(t*Math.PI/180)):Vu(void 0,e,0),aI=e=>Vu(e.bank,e,0),sI=e=>Vu(e.mu,e,1);function iI(e){let t=e.s.length,r=Ou(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 mb=[{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 hM(e){let t=Ou(e);return{ds:t,vars:{s:e.s,ds:t,t:iI(e),v:e.v,speed:JE(e),ax:e.ax,ay:e.ay,axg:eI(e),ayg:tI(e),curv:rI(e),z:nI(e),grade:oI(e),bank:aI(e),grip:sI(e)}}}function bM(e,t){return{v:e.v,ax:e.ax,ay:e.ay,ds:Ou({s:e.s,length:t}),axGrade:sn(e.gradient,e.v.length),...e.bank?{bank:e.bank}:{},...e.loadFactor?{loadFactor:e.loadFactor}:{}}}function gM(e,t){let r=lt(e);return{pastTurnover:Nk(r,sr(e),t),...e.aeroModel?{aeroOutside:_k(r,t)}:{}}}var Bu="Flying lap";function pb(e,t){return e.kind!=="trackLap"||e.label!==Bu?e.label:e.standingStart??t?"Run":e.label}function cI(e){let t=lt(e);return{yawInertia:t.yawInertia??0,massTotal:t.massTotal,wheelbase:t.wheelbase/1e3}}function lI(e,t,r){let n=e.params,o=n.ggvMode??"twoTrack",a=n.quasiTransient?qk(e,!1,o):null,s=a?a.steady:ir(e,!1,o),i=t?Wn(e,s,[t],r,o):void 0;return{ggv:s,...a?{yaw:{family:a,car:cI(n)}}:{},...i?{load:i}:{}}}function uI(e,t){let r=t.lapCounts,n=t.standingStart??!1,o=!1,a=e.events.map(s=>{let i=r?.[s.id]!=null?fM(s,r[s.id]):s,c=pb(i,n),l=c===i.label?i:{...i,label:c};return l!==s&&(o=!0),l});return o?a:e.events}function mI(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=_u(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 pI(e,t){for(let[r,n]of Object.entries(e))n.trace&&(e[r]={...n,...gM(t,bM(n.trace,Nu(n)))})}function gi(e,t,r={}){let n=At(e),o=lI(n,r.track,r.numerics),{ggv:a}=o,s=ub(uI(t,r),{vehicle:n,...o,track:r.track,energyOpts:Fr(e,r.energyOpts),numerics:r.numerics,standingStart:r.standingStart});return mI(s,t,r),pI(s,n.params),{name:e.name,rulesetId:t.id,events:s,ggv:a}}function db(e){return{...e,ggv:{rows:e.ggv.rows,vMax:e.ggv.vMax,surf:e.ggv.surf}}}var fb=["<","<=",">",">=","==","!="],_e=class extends Error{at;constructor(t,r){super(t),this.name="ExprError",this.at=r}},yi=e=>e>="0"&&e<="9",yM=e=>/[A-Za-z_]/.test(e),dI=e=>/[A-Za-z0-9_]/.test(e);function fI(e){let t=[],r=0;for(;r<e.length;){let n=e[r];if(n===" "||n===" "||n===`
224
- `||n==="\r"){r++;continue}if(yi(n)||n==="."&&yi(e[r+1]??"")){let o=r;for(;r<e.length&&(yi(e[r])||e[r]===".");)r++;if(e[r]==="e"||e[r]==="E"){let i=r;if(r++,(e[r]==="+"||e[r]==="-")&&r++,yi(e[r]??""))for(;r<e.length&&yi(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(yM(n)){let o=r;for(;;){for(;r<e.length&&dI(e[r]);)r++;if(e[r]==="."&&yM(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(fb.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 hb(e){let t=fI(e),r=0,n=()=>t[r],o=f=>{let b=n();return b.t==="op"&&b.value===f},a=f=>o(f)?(r++,!0):!1,s=(f,b)=>{if(!a(f))throw new _e(`Expected ${b} here`,n().at)};function i(){let f=c(),b=n();if(b.t!=="op"||!fb.includes(b.value))return f;r++;let g={kind:"binary",op:b.value,left:f,right:c(),at:b.at},y=n();if(y.t==="op"&&fb.includes(y.value))throw new _e("Comparisons do not chain \u2014 write and(a < b, b < c)",y.at);return g}function c(){let f=l();for(;;){let b=n().at;if(a("+"))f={kind:"binary",op:"+",left:f,right:l(),at:b};else if(a("-"))f={kind:"binary",op:"-",left:f,right:l(),at:b};else return f}}function l(){let f=u();for(;;){let b=n().at;if(a("*"))f={kind:"binary",op:"*",left:f,right:u(),at:b};else if(a("/"))f={kind:"binary",op:"/",left:f,right:u(),at:b};else return f}}function u(){return a("-")?{kind:"unary",op:"-",arg:u()}:a("+")?u():m()}function m(){let f=h(),b=n().at;return a("^")?{kind:"binary",op:"^",left:f,right:u(),at:b}:f}function h(){let f=n();if(f.t==="num")return r++,{kind:"num",value:f.value};if(f.t==="name"){if(r++,a("(")){let b=[];if(!o(")"))do b.push(i());while(a(","));return s(")","a closing bracket"),{kind:"call",name:f.value,args:b,at:f.at}}return{kind:"var",name:f.value,at:f.at}}if(a("(")){let b=i();return s(")","a closing bracket"),b}throw f.t==="end"?new _e("The expression ends before it is finished",f.at):new _e(`"${f.value}" cannot start a value`,f.at)}let d=i(),p=n();if(p.t!=="end")throw new _e(`"${p.value}" is left over \u2014 check for a missing operator`,p.at);return d}function bb(e){let t=new Set,r=n=>{n.kind==="var"?t.add(n.name):n.kind==="call"?n.args.forEach(r):n.kind==="unary"?r(n.arg):n.kind==="binary"&&(r(n.left),r(n.right))};return r(e),t}var xi=(e,t)=>typeof e=="number"?new Array(t).fill(e):e;function hI(e){let t=1;for(let r of e)Array.isArray(r)&&(t=Math.max(t,r.length));return t}function wt(e,t){if(e.every(a=>typeof a=="number"))return t(...e);let r=hI(e),n=e.map(a=>xi(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=>wt(r,t)}),jn=e=>e!==0&&!Number.isNaN(e),cr=e=>e?1:0;function xM(e,t,r){let n=RM(t,r,"integrate"),o=n.length,a=xi(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 RM(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 $u={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)=>jn(e)?t:r),and:Ne(2,(e,t)=>cr(jn(e)&&jn(t))),or:Ne(2,(e,t)=>cr(jn(e)||jn(t))),not:Ne(1,e=>cr(!jn(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=xM(e,t,0),n=t.ds,o=xi(e,n.length),a=n.length-1;return r[a]+(o[a]+o[0])/2*n[a]}},integrate:{arity:1,call:([e],t)=>xM(e,t,0)},cum:{arity:1,call:([e],t)=>{let r=t.ds?.length??(Array.isArray(e)?e.length:1),n=xi(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=RM(t,0,"deriv"),n=r.length,o=xi(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}}},Ma={g:9.81,pi:Math.PI,e:Math.E,nan:NaN,inf:1/0},Ri={fleetmin:"min",fleetmax:"max"};function Un(e){switch(e.kind){case"call":return Object.hasOwn(Ri,e.name)||e.args.some(Un);case"unary":return Un(e.arg);case"binary":return Un(e.left)||Un(e.right);default:return!1}}var bI=e=>typeof e=="number"?`${e}`:`between ${e[0]} and ${e[1]}`;function gI(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 yI(e,t){let r=t.map(c=>({k:c,d:gI(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(Ma,e.name))return Ma[e.name];let r=[...Object.keys(t.vars),...Object.keys(Ma)].sort();throw new _e(yI(e.name,r),e.at)}case"unary":return wt([lr(e.arg,t)],r=>-r);case"binary":{let r=lr(e.left,t),n=lr(e.right,t);switch(e.op){case"+":return wt([r,n],(o,a)=>o+a);case"-":return wt([r,n],(o,a)=>o-a);case"*":return wt([r,n],(o,a)=>o*a);case"/":return wt([r,n],(o,a)=>a===0?0:o/a);case"^":return wt([r,n],(o,a)=>o**a);case"<":return wt([r,n],(o,a)=>cr(o<a));case"<=":return wt([r,n],(o,a)=>cr(o<=a));case">":return wt([r,n],(o,a)=>cr(o>a));case">=":return wt([r,n],(o,a)=>cr(o>=a));case"==":return wt([r,n],(o,a)=>cr(o===a));case"!=":return wt([r,n],(o,a)=>cr(o!==a))}break}case"call":{let r=Object.hasOwn(Ri,e.name)?Ri[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($u,e.name)?$u[e.name]:void 0;if(!n){let s=[...Object.keys($u),...t.fleet?Object.keys(Ri):[]];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 ${bI(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 Sa=e=>Number.isFinite(e)?e:NaN,gb=[{name:"time",unit:"s",what:"the whole event, every lap",read:e=>Sa(e?.time)},{name:"lapTime",unit:"s",what:"one lap \u2014 the last one completed",read:e=>Sa(e?.lapTime)},{name:"distance",unit:"m",what:"distance covered",read:e=>Sa(e?.distance)},{name:"laps",unit:"-",what:"laps completed",read:e=>Sa(e?.laps)},{name:"energy",unit:"kWh",what:"energy drawn over the event",read:e=>Sa(e?.energy?.consumed)},{name:"remaining",unit:"-",what:"share of the pack or tank left afterwards",read:e=>Sa(e?.energy?.remainingFraction)},{name:"finished",unit:"-",what:"1 when the car ran the whole event, else 0",read:e=>e&&!e.incomplete?1:0}],vM=/^[A-Za-z_][A-Za-z0-9_]*$/,xI=new Set([...Object.keys(Ma),...mb.map(e=>e.name)]);function Gu(e,t,r=[]){let n=[],o=new Set(r),a=t.map(b=>b.id),s=new Set;for(let b of a)vM.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(!vM.test(b.key)){n.push({key:b.key,message:`"${b.key}" must be one word \u2014 letters, digits and _`});continue}if(xI.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,hb(b.expr))}catch(g){let y=g;n.push({key:b.key,message:y.message,at:y.at})}}let l=new Map;for(let[b,g]of c)l.set(b,[...bb(g)].filter(y=>i.has(y)));let u=new Set,m=[];for(;;){let b=[...c.keys()].find(g=>!u.has(g)&&l.get(g).every(y=>u.has(y)||!c.has(y)));if(!b)break;u.add(b),m.push(b)}for(let b of c.keys()){if(u.has(b))continue;let g=RI(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 h=(b,g,y)=>{throw new _e("fleetmin() and fleetmax() cannot sit inside one another",y)},d=new Set,p={};for(let b of a)for(let g of gb)p[`${b}.${g.name}`]=1;for(let b of o)p[b]=1;for(let b of i.keys())p[b]=1;let f={};for(let b of mb)f[b.name]=[1,1];for(let b of m){let g=i.get(b),y=c.get(b);(Un(y)||l.get(b).some(x=>d.has(x)))&&d.add(b);let R=g.over!=null?{...p,...f}:p,M=g.over!=null?[1,1]:void 0,v=(x,k,F)=>{let C=lr(x,{vars:R,ds:M,fleet:h});if(Array.isArray(C))throw new _e("fleetmin() and fleetmax() compare one number per car \u2014 reduce the channel first, e.g. peak(v)",F);return C};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:d,eventIds:a},problems:n}}function RI(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 vI(e,t,r={}){let n={...r};for(let o of e.eventIds){let a=t.events[o];for(let s of gb)n[`${o}.${s.name}`]=s.read(a)}return{vars:n,laps:new Map,events:t.events}}function kM(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?hM({...n.trace,length:Nu(n)}):null,e.laps.set(t.over,r)}return r?{vars:{...e.vars,...r.vars},ds:r.ds}:null}var MM=e=>Array.isArray(e)?NaN:e;function SM(e,t,r,n={}){let o=Object.keys(t),a=o.map(i=>vI(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 h of a)h.vars[i.key]=NaN;continue}let u=new Map,m=(h,d)=>{let p=u.get(h);if(p!==void 0)return p;let f=NaN;for(let b of a){let g=kM(b,i);if(!g)continue;let y=MM(lr(h,g));Number.isFinite(y)&&(Number.isNaN(f)||(d==="min"?y<f:y>f))&&(f=y)}return u.set(h,f),f};for(let h of a){let d=kM(h,i);h.vars[i.key]=d?MM(lr(c,l?{...d,fleet:m}:d)):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 vi(e,t,r){return SM(e,t,!0,r)}function yb(e,t,r){return SM(e,{car:t},!1,r?{car:r}:void 0).car}var Ku=class extends Error{problems;constructor(t,r){super(`Ruleset "${t}" does not compile:
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===`
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}},Mi=e=>typeof e=="number"&&Number.isFinite(e),ki=e=>Mi(e)&&e>0,Tt=(e,t)=>e===void 0||t(e);function kI(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":ki(a.distance)||r(`${s} needs a distance above zero, in metres`),Tt(a.vStart,i=>Mi(i)&&i>=0)||r(`${s}'s entry speed must be zero or more`);break;case"constantRadius":ki(a.radius)||r(`${s} needs a radius above zero, in metres`),Tt(a.laps,i=>Mi(i)&&i>=1)||r(`${s} runs at least one lap`);break;case"trackLap":Tt(a.laps,i=>Mi(i)&&i>=1)||r(`${s} runs at least one lap`),Tt(a.distance,ki)||r(`${s}'s distance must be above zero, in metres`),Tt(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),Tt(a.unit,i=>typeof i=="string")||r("Its unit is text",s),Tt(a.over,i=>typeof i=="string")||r("Names its event by id",s),Tt(a.format,i=>i==="time"||i==="points")||r("Is shown as a time, as points, or as a number",s),Tt(a.max,Mi)||r("Its maximum is a number",s),Tt(a.lowerBetter,i=>typeof i=="boolean")||r("Lower is better, or it is not",s),Tt(a.hidden,i=>typeof i=="boolean")||r("Is hidden, or it is not",s)}Tt(e.track?.minTurnRadius,ki)||r("The tightest turn the rules allow is a radius above zero");let n=e.battery;for(let o of["packVoltageMax","segmentVoltageMax","powerLimitKw"])Tt(n?.[o],ki)||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 AM(e){let t=kI(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}=Gu(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 Hu(e){return AM(e).problems}var xb=e=>Number.isFinite(e)?e:NaN;function MI(e){return e.unit&&e.format!=="time"?`${e.label} (${e.unit})`:e.label}function ln(e){let t=structuredClone(e),{plan:r,problems:n}=AM(t);if(!r)throw new Ku(t.id,n);let o=new WeakMap,a=d=>{let p=o.get(d);return p||(p=yb(r,d),o.set(d,p)),p},s=new Map(t.kpis.map(d=>[d.key,d])),i=new Map;for(let[d,p]of Object.entries(t.score?.parts??{}))i.has(p)||i.set(p,d);let c=d=>(p,f)=>{if(!f)return NaN;let b=f.kpis?.[d];if(b!==void 0)return xb(b);let g=f,y=i.get(d);return y!==void 0?xb(g.parts?.[y]):d===t.score?.total?xb(g.total):NaN},l=t.kpis.filter(d=>!d.hidden).map(d=>{let p=r.field.has(d.key);return{key:d.key,label:MI(d),lowerBetter:d.lowerBetter??!1,...d.format?{format:d.format}:{},...p?{field:!0}:{},value:p?c(d.key):f=>a(f)[d.key]}}),u=t.score,m=u?d=>{let p=vi(r,d),f={};for(let[b,g]of Object.entries(p)){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)}f[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 f}:void 0,h=m||(r.field.size>0?d=>{let p=vi(r,d),f={};for(let[b,g]of Object.entries(p))f[b]={kpis:Object.fromEntries(t.kpis.map(y=>[y.key,g[y.key]]))};return f}: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}:{},...h?{field:h}:{},definition:t}}var Yt={accel:"accel",skidpad:"skidpad",autocross:"autocross",endurance:"endurance"},FM=[{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}],CM=[{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"}],wM={total:"overall",parts:{[Yt.accel]:"accelPts",[Yt.skidpad]:"skidpadPts",[Yt.autocross]:"autocrossPts",[Yt.endurance]:"endurancePts",efficiency:"efficiencyPts"}},TM={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:FM,kpis:CM,score:wM,track:{minTurnRadius:4.5},battery:K0,traceEventId:Yt.autocross},PM={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:FM,kpis:CM,score:wM,track:{minTurnRadius:4.5},traceEventId:Yt.autocross},Si=ln(TM),Rb=ln(PM);var vb="lap",SI=[{kind:"trackLap",id:vb,label:Bu,laps:1}],LM={id:"trackday",label:"Track day",description:"One flying lap of the selected track. Times and traces only \u2014 no scoring.",events:SI,kpis:[{key:"lap",label:"Lap time",format:"time",lowerBetter:!0,expr:"lap.time"},{key:"topSpeed",label:"Top speed",unit:"km/h",over:vb,expr:"peak(speed)"},{key:"energy",label:"Energy / lap",unit:"kWh",lowerBetter:!0,expr:"lap.energy"}],traceEventId:vb},kb=ln(LM);function un(e){if(e===null||typeof e!="object")return JSON.stringify(e)??"null";if(Array.isArray(e))return`[${e.map(un).join(",")}]`;let t=e,r=Object.keys(t).sort(),n=[];for(let o of r)t[o]!==void 0&&n.push(`${JSON.stringify(o)}:${un(t[o])}`);return`{${n.join(",")}}`}function Xn(e){let t=un(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 Aa=[Si,Rb,kb],qn=Si.id,Fa=e=>Aa.some(t=>t.id===e),DM=new WeakMap,Ai=new Map,AI=64;function zu(e){let t=DM.get(e);if(t!==void 0)return t;let r=un(e),n=Ai.get(r);return n===void 0&&(n=Hu(e).length?null:ln(e),Ai.size>=AI&&Ai.delete(Ai.keys().next().value),Ai.set(r,n)),DM.set(e,n),n}function Yu(e,t=[]){if(e==null)return;if(typeof e!="string")return zu(e)??void 0;let r=Aa.find(o=>o.id===e);if(r)return r;let n=t.find(o=>o.id===e);return n?zu(n)??void 0:void 0}function Qn(e,t=[]){return Yu(e,t)??Si}function Mb(e=[]){let t=e.filter(r=>!Fa(r.id)).map(r=>zu(r)).filter(r=>r!==null);return[...Aa,...t]}var Fi=e=>e.definition??e.id;function Wu(e,t,r){let n=e.length,o=new Array(n);for(let p=0;p<n;p++){let f=p+1<n?e[p+1]:r;o[p]=f-e[p]}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 p=0;p<n;p++){let f=o[(p-1+n)%n],b=o[p];a[p]=f,s[p]=2*(f+b),i[p]=b;let g=t[(p+1)%n],y=t[(p-1+n)%n];c[p]=6*((g-t[p])/b-(t[p]-y)/f)}let l=FI(a,s,i,c),u=new Array(n),m=new Array(n),h=new Array(n),d=new Array(n);for(let p=0;p<n;p++){let f=o[p],b=l[p],g=l[(p+1)%n],y=t[p],R=t[(p+1)%n];u[p]=y,h[p]=b/2,d[p]=(g-b)/(6*f),m[p]=(R-y)/f-f*(2*b+g)/6}return{n,eval:(p,f)=>u[p]+f*(m[p]+f*(h[p]+f*d[p])),d1:(p,f)=>m[p]+f*(2*h[p]+f*3*d[p]),d2:(p,f)=>2*h[p]+f*6*d[p]}}function Ab(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),h=new Array(u).fill(0),d=new Array(u).fill(0),p=new Array(u).fill(0);for(let g=0;g<u;g++){let y=g+1;m[g]=o[y-1],h[g]=2*(o[y-1]+o[y]),d[g]=o[y],p[g]=6*((t[y+1]-t[y])/o[y]-(t[y]-t[y-1])/o[y-1])}let f=n>=3;if(f){let g=o[0]/o[1];h[0]+=o[0]*(1+g),d[0]-=o[0]*g;let y=o[n-1]/o[n-2];h[u-1]+=o[n-1]*(1+y),m[u-1]-=o[n-1]*y}let b=Sb(m,h,d,p);for(let g=0;g<u;g++)a[g+1]=b[g];f&&(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 FI(e,t,r,n){let o=t.length;if(o===1)return[n[0]/(t[0]+e[0]+r[0])];if(o===2){let p=t[0],f=r[0]+e[0],b=e[1]+r[1],g=t[1],y=p*g-f*b;return[(n[0]*g-f*n[1])/y,(p*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=Sb(e,c,r,n),u=new Array(o).fill(0);u[0]=i,u[o-1]=s;let m=Sb(e,c,r,u),h=(l[0]+a*l[o-1]/i)/(1+m[0]+a*m[o-1]/i),d=new Array(o);for(let p=0;p<o;p++)d[p]=l[p]-h*m[p];return d}function Sb(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 EM(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 IM(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 h=r*i-o*o,d=n*o-r*s,p=r*a-n*n;return[(c*t[0]+l*t[1]+u*t[2])/m,(l*t[0]+h*t[1]+d*t[2])/m,(u*t[0]+d*t[1]+p*t[2])/m]}function _M(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(f=>e.closed?(f+t)%t:f);if(s.some(f=>f<0||f>=t))continue;let i=s.map(f=>EM(e,a,f)),c=Math.max(...i.map(Math.abs));if(!(c>0))continue;let l=i.map(f=>f/c),u=[0,0,0,0,0];for(let f of l)for(let b=0;b<5;b++)u[b]+=f**b;let m=IM([u[0],u[1],u[2],u[2],u[3],u[4]],[1,0,0]);if(!m)continue;let h=l.map(f=>m[0]+m[1]*f+m[2]*f*f),d=0,p=1;h.forEach((f,b)=>{d+=f*e.z[s[b]],p+=f*f}),r.push(Math.abs(e.z[a]-d)/Math.sqrt(p))}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 CI(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=EM(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 wI(e,t,r){let{j:n,t:o}=CI(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 h=0;h<5;h++)i[h]+=m,m*=l});let c=IM([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 Fb(e,t){return t>0?e.z.map((r,n)=>{let o=wI(e,n,t/2);return o?o.value.reduce((a,s,i)=>a+s*e.z[o.j[i]],0):r}):[...e.z]}function TI(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 ju(e){let t=Ci(e);if(!t)return 0;let r=_M(t);return r>1e-6?Math.max(10,TI(r,PI(t))):0}function PI(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 Xu(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 NM(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 Uu(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 LI(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 Cb(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=NM(r,(y,R)=>ur(e,y,R));if(!b)return null;let g=Uu(b,t);return g.every(Number.isFinite)?g:null}let n=r-2,a=NM(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=Uu(a,t.slice(0,n)),l=Uu(a,s),u=Uu(a,i),m=(b,g)=>{let y=0;for(let R=0;R<b.length;R++)y+=b[R]*g[R];return y},h=[[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)]],d=[t[r-2]-m(s,c),t[r-1]-m(i,c)],p=LI(h,d);if(!p)return null;let f=new Array(r).fill(0);for(let b=0;b<n;b++)f[b]=c[b]-l[b]*p[0]-u[b]*p[1];return f[r-2]=p[0],f[r-1]=p[1],f.every(Number.isFinite)?f:null}function OM(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=Cb(i,t);if(c){let l=Xu(i,c).map((m,h)=>m-t[h]);if(Math.sqrt(l.reduce((m,h)=>m+h*h,0))<=1e-6*Math.max(a,1e-12))return c}o=o===0?n*1e-12:o*10}return null}var VM=4,DI=8,wb=.001;function EI(e,t,r){let n=[];for(let c=1;c<e.length;c++){let l=e[c]-e[c-1];l>=wb&&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/j1(r,s,i)))}function II(e,t){let r=e.closed!==!1,n=[],o=[],a=(F,C)=>{let w=n.length-1;w>=0&&Math.hypot(F-n[w],C-o[w])<wb||(n.push(F),o.push(C))},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 C=(F+1)%s;c[F+1]=c[F]+Math.hypot(e.x[C]-e.x[F],e.y[C]-e.y[F])}let l=c[i],u=e.fit==="interpolate",m=u?s:EI(c,r,t),h=r?m:m-1,d=0;for(let F=0;F<=h&&!(r&&F===h);F++){if(u){a(e.x[F],e.y[F]);continue}let C=F*l/h;for(;d<i-1&&c[d+1]<C;)d++;let w=c[d+1]-c[d],T=w>0?(C-c[d])/w:0,S=(d+1)%s;a(e.x[d]+T*(e.x[S]-e.x[d]),e.y[d]+T*(e.y[S]-e.y[d]))}if(r)for(;n.length>2&&Math.hypot(n[n.length-1]-n[0],o[o.length-1]-o[0])<wb;)n.pop(),o.pop();let p=n.length,f=r?p:p-1,b=new Array(f+1);b[0]=0;for(let F=1;F<=f;F++){let C=F%p,w=n[C]-n[F-1],T=o[C]-o[F-1],S=Math.sqrt(Math.hypot(w,T))||1e-9;b[F]=b[F-1]+S}let g=r?Wu(b.slice(0,p),n,b[p]):Ab(b,n),y=r?Wu(b.slice(0,p),o,b[p]):Ab(b,o),R=new Array(f);for(let F=0;F<f;F++)R[F]=b[F+1]-b[F];let M=[0],v=[0],x=[0],k=0;for(let F=0;F<f;F++){let C=R[F]/VM;for(let w=0;w<VM;w++){let T=w*C;k+=Df(S=>Math.hypot(g.d1(F,S),y.d1(F,S)),T,T+C),M.push(k),v.push(F),x.push(T+C)}}return{closed:r,sx:g,sy:y,h:R,sTable:M,segTable:v,uTable:x,length:k,rawCum:c,rawLength:l}}function wi(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 h=i*n.rawLength,d=0,p=a;for(;d<p;){let b=d+p+1>>1;n.rawCum[b]<=h?d=b:p=b-1}let f=d<a?n.rawCum[d+1]-n.rawCum[d]:0;c=d+(f>0?(h-n.rawCum[d])/f: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 _I=.01,NI=3,BM=10;function OI(e,t,r,n=BM){let o={step:0,uncertainty:1/0},a=e.length;if(a<8||!(r>0))return o;let s=Math.max(BM,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=[],h=[],d=(R,M,v)=>{let x=R/s;m.push([1,x,x*x,x*x*x,M]),h.push(v)};for(let R=0;R<u;R++)d(t[R]+i,1,e[R]);for(let R=0;R<u;R++)d(t[a-1-R]-r+i,0,e[a-1-R]);let p=Array.from({length:5},()=>new Array(5).fill(0)),f=new Array(5).fill(0);m.forEach((R,M)=>{for(let v=0;v<5;v++){f[v]+=R[v]*h[M];for(let x=0;x<5;x++)p[v][x]+=R[v]*R[x]}});let b=qt(p,f),g=qt(p,[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+=(h[M]-v)**2}),{step:b.x[4],uncertainty:Math.sqrt(y/(m.length-5)*g.x[4])}}function VI(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 BI(e,t,r){let{pos:n,loop:o}=VI(e.length,t),{step:a,uncertainty:s}=OI(e,n,o,r);return Math.abs(a)>Math.max(_I,NI*s)?{z:e.map((i,c)=>i+a*n[c]/o),drift:-a}:{z:e,drift:0}}function $I(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],h=r[u+1],d=n[u+1],p=o[u+1],f=n[u]===d?o[u]:0,b=h-m,g=b>0?f+(t-m)/b*(p-f):f;for(let y=0;y<2;y++){let R=m+Df(v=>Math.hypot(s.d1(d,v),i.d1(d,v)),f,g),M=Math.hypot(s.d1(d,g),i.d1(d,g));if(M<1e-12)break;g-=(R-t)/M}return{seg:d,du:Math.min(Math.max(g,0),a[d])}}var GI=3,Tb=5;function KI(e,t,r,n=Tb){return Qu(e,t,r,n)}function Qu(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 h of[0,a-1])i[h]+=m,u[h]*=1+m}return Cb({n:a,diag:i,off1:c,off2:l,closed:r},u)??[...e]}function gt(e,t){let r=at(t),n=II(e,r.fitSpacing),o=n.length,a=Math.max(DI,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 h=new Array(s),d=new Array(s),p=new Array(s);for(let w=0;w<s;w++){let T=w*i,{seg:S,du:A}=$I(n,T);c[w]=n.sx.eval(S,A),l[w]=n.sy.eval(S,A),u[w]=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);h[w]=O>0?(P*I-L*D)/O:0,d[w]=G>0?-L/G:0,p[w]=G>0?P/G:0}let f=u.map(w=>o>0?Math.min(1,w/o):0),b=Array.isArray(e.z)&&e.z.length>1,g=b&&(e.zSmoothing??0)>0?e.zSmoothing:0,y=b&&n.closed?BI(e.z,n.rawCum,g):null,R=y?y.z:e.z,M=g>0?Ci(e):null,v=M?Fb({...M,z:R},g):R,x=wi(v,0,f,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 w=0;for(let T=0;T<s;T++)u[T]=w,w+=m[T]}let F=b?m.reduce((w,T)=>w+T,0):o,C;if(b){C=new Array(s).fill(0);let w=Math.max(GI,e.zReach??ju(e)),T=Math.max(2,Math.round(w/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;C[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?KI(h,i,n.closed,e.turnReach):h,npts:s,length:F,nx:d,ny:p,z:x,gradient:k,...C?{verticalCurvature:C}:{},widthLeft:wi(e.widthLeft,1.5,f,n),widthRight:wi(e.widthRight,1.5,f,n),bank:wi(e.bank,0,f,n),mu:wi(e.mu,1,f,n),...y?.drift?{elevationDrift:y.drift}:{}}}function $M(e,t,r){let n=Xu(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 HI(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 h=s(l,m);h!=null&&(i[h]-=ur(e,h,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 OM(c,i)}var zI=1e-4;function GM(e,t,r,n,o={}){let a=e.n,s=o.maxIter??60,i=o.tol??1e-9,c=o.bounds,l=(p,f)=>Math.min(n[f],Math.max(r[f],p)),u=r.map((p,f)=>c?.[f]==="hi"?n[f]:c?.[f]==="lo"?r[f]:l(0,f)),m=$M(e,t,u),h=new Array(a).fill("free"),d=!1;for(let p=0;p<s;p++){let f=Xu(e,u).map((R,M)=>R-t[M]),b=!1;for(let R=0;R<a;R++){let M=u[R]<=r[R]+i&&f[R]>=-i?"lo":u[R]>=n[R]-i&&f[R]<=i?"hi":"free";M!==h[R]&&(h[R]=M,b=!0)}if(d&&!b)return{x:u,iterations:p+1,converged:!0,bounds:h};let g=HI(e,t,h,R=>u[R]);if(!g)return{x:u,iterations:p+1,converged:!1,bounds:h};let y=!1;for(let R=1;R>1e-12;R*=.5){let M=!1,v=u.map((F,C)=>{if(h[C]!=="free")return F;let w=F+R*(g[C]-F),T=l(w,C);return T!==w&&(M=!0),T}),x=$M(e,t,v),k=0;for(let F=0;F<a;F++)k+=f[F]*(v[F]-u[F]);if(R===1&&!M||x<m&&x<=m+zI*k){u=v,m=x,d=R===1&&!M,y=!0;break}}if(!y)return{x:u,iterations:p+1,converged:!1,bounds:h}}return{x:u,iterations:s,converged:!1,bounds:h}}var Pb={lineStep:2,carHalfWidth:.75,margin:.1,foldMargin:.25,referenceReach:5,passes:40,iterations:400},YI=[1,.5,.25,.125,.0625,.03125,.015625,.0078125,.00390625,.001953125,.0009765625],WI=e=>Math.sqrt(e.reduce((t,r)=>t+r*r,0)/(e.length||1));function Ti(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],h=e[i]-e[s],d=t[i]-t[s],p=Math.hypot(c,l),f=Math.hypot(u,m),b=Math.hypot(h,d),g=p*f*b;o[a]=g>1e-12?2*(c*m-l*u)/g:0}return o}var jI=Math.PI/180,KM=20;function UI(e,t){let r=e.npts,n=e.closed,o=e.x.map((d,p)=>d+t[p]*e.nx[p]),a=e.y.map((d,p)=>d+t[p]*e.ny[p]),s=[0];for(let d=1;d<r;d++)s.push(s[d-1]+Math.hypot(o[d]-o[d-1],a[d]-a[d-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 d of c)for(let p=0;p<r;p++)l.push(s[p]+d*i),u.push(p+d*r);n&&(l.push(2*i),u.push(2*r));let m=[0];for(let d=1;d<l.length;d++)m.push(m[d-1]+.5*(u[d]+u[d-1])*(l[d]-l[d-1]));let h=d=>{let p=0,f=l.length-1;for(;f-p>1;){let g=p+f>>1;l[g]<=d?p=g:f=g}let b=l[f]>l[p]?(d-l[p])/(l[f]-l[p]):0;return m[p]+(l[f]-l[p])*b*(u[p]+.5*b*(u[f]-u[p]))};return s.map((d,p)=>{let f=n?KM:Math.min(KM,d,i-d);if(!(f>0))return e.z[p];let b=(h(d+f)-h(d-f))/(2*f),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 XI(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?UI(t,r):t.z;return{...n||o?{z:s.map((i,c)=>i+r[c]*Math.tan(t.bank[c]*jI))}:{},...n?{zReach:e.zReach??ju(e)}:{},...o?{bank:[...t.bank]}:{},...a?{mu:[...t.mu]}:{}}}function HM(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 qI(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,h)=>l*h-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,h=e[l]-e[u],d=t[l]-t[u],p=e[m]-e[l],f=t[m]-t[l],b=e[m]-e[u],g=t[m]-t[u],y=Math.hypot(h,d),R=Math.hypot(p,f),M=Math.hypot(b,g),v=y*R*M;if(!(v>1e-12))continue;let x=2*c(h,d,p,f)/v,k=Math.sqrt(.5*(y+R)),F=x/(2*k),C=(h*r[u]+d*n[u])/y,w=(b*r[u]+g*n[u])/M,T=(h*r[l]+d*n[l])/y,S=(p*r[l]+f*n[l])/R,A=(p*r[m]+f*n[m])/R,P=(b*r[m]+g*n[m])/M,L=-2*c(r[u],n[u],p,f)/v+x*(C/y+w/M),D=2*c(r[l],n[l],b,g)/v-x*(T/y-S/R),I=2*c(h,d,r[m],n[m])/v-x*(A/R+P/M);s[l]=x*k,i.l[l]=k*L-F*.5*C,i.d[l]=k*D+F*.5*(T-S),i.r[l]=k*I+F*.5*A}return{res:s,jac:i}}function QI(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=(f,b)=>o?f[(b+a)%a]:b>=0&&b<a?f[b]:0,m=new Array(a),h=new Array(a),d=new Array(a),p=new Array(a);for(let f=0;f<a;f++){let b=u(c,f-1),g=u(s,f+1);m[f]=b*b+i[f]*i[f]+g*g,h[f]=i[f]*c[f]+g*u(i,f+1),d[f]=g*u(c,f+1),p[f]=-(b*u(l,f-1)+i[f]*l[f]+g*u(l,f+1))}return{M:{n:a,closed:o,diag:m,off1:h,off2:d},b:p}}function ZI(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 h=0;h<o;h++){let d=(h+1)%r;a+=Math.hypot(e.x[d]-e.x[h],e.y[d]-e.y[h])}let s=a/o,i=Qu(e.x,s,n,t,!0),c=Qu(e.y,s,n,t,!0),l=new Array(r),u=new Array(r);for(let h=0;h<r;h++){let d=n?(h-1+r)%r:Math.max(h-1,0),p=n?(h+1)%r:Math.min(h+1,r-1),f=i[p]-i[d],b=c[p]-c[d],g=Math.hypot(f,b)||1;l[h]=-b/g,u[h]=f/g}let m=Ti(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 JI=6;function e2(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]),h=Math.hypot(e.x[u]-e.x[l],e.y[u]-e.y[l]);s[l]=h>1e-9?m/h:0}let i=Math.max(0,Math.round(JI/(e.ds[0]||1))),c=1-n;for(let l=0;l<o;l++){let u=0,m=0;for(let h=-i-1;h<=i;h++){let d=e.closed?((l+h)%o+o)%o:l+h;d<0||d>=a||(u=Math.max(u,s[d]),m=Math.max(m,-s[d]))}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 Lb(e,t={}){let r={...Pb,...t},n=gt(e,{dsTarget:r.lineStep}),o=ZI(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=Ti(T.x,T.y,o.closed),A=HM(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=WI(n.curvature),l=HM(n.x,n.y,n.closed).reduce((T,S)=>T+S,0),u=new Array(a).fill(0),m=r.carHalfWidth+r.margin,h=new Array(a),d=new Array(a),p=0;for(let T=0;T<a;T++){let S=o.widthLeft[T]-m,A=-(o.widthRight[T]-m);if(S<A){p++;let P=(o.widthLeft[T]-o.widthRight[T])/2;h[T]=P,d[T]=P}else h[T]=S,d[T]=A}let f=[...h],b=[...d];e2(o,h,d,r.foldMargin);let g=T=>{let S=s(T),A=XI(e,o,T),P={name:`${e.name} \u2014 racing line`,x:S.x,y:S.y,closed:o.closed,widthLeft:f.map((E,_)=>Math.max(0,E-T[_])),widthRight:b.map((E,_)=>Math.max(0,T[_]-E)),...A,fit:"interpolate",turnReach:Tb},L=1e-6,D=T.filter((E,_)=>E>=h[_]-L||E<=d[_]+L).length,I=Ti(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:p,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]=d[y+T],x[T]=h[y+T];if(!o.closed&&M>0){let T=(S,A)=>{if(v[S]=Math.max(v[S],d[A]),x[S]=Math.min(x[S],h[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=[...Ti(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],C=k(u),w;for(let T=0;T<r.passes;T++){let S=s(F),{res:A,jac:P}=qI(S.x,S.y,o.nx,o.ny,o.closed),{M:L,b:D}=QI(P,A,y,R,o.closed),I=GM(L,D,v.map((W,E)=>W-F[y+E]),x.map((W,E)=>W-F[y+E]),{maxIter:r.iterations,bounds:w});w=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 YI){let E=F.map((V,N)=>V+W*G[N]),_=k(E);if(_.integral<C.integral*(1-1e-6)){F=E,C=_,O=!0;break}}if(!O)break}return g(F)}function Db(e){let t=Math.max(Z(e,"track_front"),Z(e,"track_rear"));return(t>0?t/2e3:.6)+.1}function Zu(e,t,r={}){if(!r.racingLine)return{asset:e,numerics:t,line:null};let n=r.params?Db(r.params):void 0,o=Lb(e,{...r.line,...n?{carHalfWidth:n}:{}});return{asset:o.asset,numerics:{...t,fitSpacing:0},line:o}}function Pi(e,t,r={}){let n=Zu(e,t,r);return{track:gt(n.asset,n.numerics),line:n.line}}function Eb(e=4,t=Pi){let r=new WeakMap;return(n,o,a={})=>{let s=a.racingLine===!0,i=s?[a.params?Db(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 zM={racingLine:!1,standingStart:!1},Ju=256;function Li(e,t,r,n,o=zM,a=Pi){let s=Qn(n),{racingLine:i,standingStart:c,lapCounts:l}=o;return e.map(u=>{let{track:m}=a(t,r,{racingLine:i,params:u});return db(gi(u,s,{track:m,numerics:r,standingStart:c,lapCounts:l}))})}function Ib(e,t){let r=Qn(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 _b(e,t,r){let n={};for(let o of Qn(e).metrics)n[o.key]=o.value(t,r);return n}var em=36;var Vb=287.05287,r2=461.495,tm=9.80665/(Vb*.0065),n2=101325/(Vb*288.15),o2=273.15,a2=-500,s2=6e3,i2=400,c2=1100,rm={source:"car",altitudeM:0,pressure:{kind:"standard"},humidityPct:0};function l2(e){return 101325*Math.pow(1-.0065*e/288.15,tm)}function u2(e){return 288.15/.0065*(1-Math.pow(e/n2,1/(tm-1)))}function m2(e){return 288.15/.0065*(1-Math.pow(e/101325,1/tm))}function p2(e,t){return e*Math.pow(1-.0065*t/288.15,tm)}function d2(e){return 611.21*Math.exp((18.678-e/234.5)*(e/(257.14+e)))}function f2(e,t){switch(e.kind){case"standard":return l2(t);case"qnh":return p2(e.hPa*100,t);case"station":return e.hPa*100}}function Di(e,t,r=0,n=m2(e)){let o=t+o2,a=Math.min(.5*e,Math.max(0,Math.min(100,r))/100*d2(t)),s=e-a,i=s/(Vb*o)+a/(r2*o);return{altitudeM:n,p:e,pDry:s,T:o,rho:i,densityAltitudeM:u2(i)}}function YM(e,t){return Di(f2(e.pressure,e.altitudeM),t,e.humidityPct,e.altitudeM)}var Nb=(e,t,r)=>Math.min(r,Math.max(t,e)),Ob=(e,t)=>{let r=Number(e);return Number.isFinite(r)?r:t};function nm(e){if(!e||typeof e!="object")return structuredClone(rm);let t=e,r=t.pressure??{},n=Nb(Ob(r.hPa,1013.25),i2,c2),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:Nb(Ob(t.altitudeM,0),a2,s2),pressure:o,humidityPct:Nb(Ob(t.humidityPct,0),0,100)}}var Ei=e=>e?.source==="venue";var h2=Math.PI/180;function b2(){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 g2(){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 Bb(e){let t=-e*h2;return q([0,Math.cos(t),Math.sin(t)])}function om(){let e={rodType:"push",pushrodAttach:"lowerArm",steerMode:"rack",spinAxis:Bb(-1),loadedRadius:230,springRate:35,rackAxis:[0,1,0]};return{hardpoints:b2(),config:e}}function Ii(){let e={rodType:"pull",pushrodAttach:"lowerArm",steerMode:"fixed",spinAxis:Bb(-1.5),loadedRadius:232,springRate:40,rackAxis:[0,1,0]};return{hardpoints:g2(),config:e}}function am(){let e=[-25,635,460],t=[-40,600,710],r={layout:"mcpherson",actuation:"direct",rodType:"push",pushrodAttach:"upright",steerMode:"rack",spinAxis:Bb(-.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 $b(){return{front:om(),rear:Ii(),config:{wheelbase:1600,trackFront:1200,trackRear:1220,frontAxleX:800}}}var y2=Math.PI/180;function WM(e){let t=-e*y2;return q([0,Math.cos(t),Math.sin(t)])}function Gb(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:WM(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]=x2(o[l]);return{hardpoints:o,config:c}}function x2(e){return e.map(t=>Math.round(t*10)/10+0)}function Jn(e){return{name:e.name,front:Gb(om(),e.front),rear:Gb(Ii(),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 wa=600,eo=610,Ta=230,to=232;function ro(){let e=$b();return{...e,name:"Formula Student",front:{...e.front,config:{...e.front.config,actuation:"rocker"}},rear:{...e.rear,config:{...e.rear.config,actuation:"rocker"}}}}function Kb(){return Jn({name:"Formula 1",wheelbase:3600,trackFront:1600,trackRear:1600,front:{kx:1.3,ky:800/wa,kz:355/Ta,lowerInnerDz:-5,upperInnerDz:0,camberDeg:-3,loadedRadius:355,springRate:200},rear:{kx:1.3,ky:800/eo,kz:355/to,lowerInnerDz:35,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:220}})}function _i(){return Ca(Jn({name:"GT car",wheelbase:2700,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/wa,kz:325/Ta,lowerInnerDz:18,upperInnerDz:5,camberDeg:-3.5,loadedRadius:325,springRate:110,actuation:"direct"},rear:{kx:1.2,ky:825/eo,kz:325/to,lowerInnerDz:36,upperInnerDz:15,camberDeg:-2,loadedRadius:325,springRate:120,actuation:"direct"}}),318.6,318.6)}function Ni(){return Ca(Jn({name:"Sports car",wheelbase:2750,trackFront:1550,trackRear:1550,front:{kx:1.15,ky:775/wa,kz:320/Ta,lowerInnerDz:36,upperInnerDz:15,camberDeg:-.5,loadedRadius:320,springRate:55,actuation:"direct"},rear:{kx:1.15,ky:775/eo,kz:320/to,lowerInnerDz:57,upperInnerDz:25,camberDeg:-1,loadedRadius:320,springRate:60,actuation:"direct"}}),305.4,309)}function R2(e,t,r,n,o,a){let s=am(),i=Object.fromEntries(Object.entries(s.hardpoints).map(([l,[u,m,h]])=>[l,[u,m+e,h]])),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:WM(n),springRate:o,rackTravel:a}}}function jM(){return Ca({name:"Cup car",front:R2(55,-25,-23,-3.5,150,55),rear:Gb(Ii(),{kx:1.15,ky:820/eo,kz:320/to,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 UM(){return{...Ca(Jn({name:"Stock car",wheelbase:2794,trackFront:1650,trackRear:1650,front:{kx:1.2,ky:825/wa,kz:355/Ta,lowerInnerDz:20,upperInnerDz:5,camberDeg:-2.5,loadedRadius:355,springRate:175,actuation:"direct"},rear:{kx:1.2,ky:825/eo,kz:355/to,lowerInnerDz:40,upperInnerDz:15,camberDeg:-1.5,loadedRadius:355,springRate:150,actuation:"direct"}}),343.8,345.3),chassis:{boxes:[],body:"nascar"}}}function XM(){let e=Ca(Jn({name:"Hill-climb prototype",wheelbase:2550,trackFront:1580,trackRear:1540,front:{kx:1.1,ky:790/wa,kz:300/Ta,lowerInnerDz:10,upperInnerDz:5,camberDeg:-2.5,loadedRadius:300,springRate:90},rear:{kx:1.1,ky:770/eo,kz:300/to,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 qM(){let e=Ca(Jn({name:"Race truck",wheelbase:3700,trackFront:2050,trackRear:1950,front:{kx:1.5,ky:1025/wa,kz:506/Ta,lowerInnerDz:40,upperInnerDz:10,camberDeg:-.5,loadedRadius:506,springRate:200,actuation:"direct"},rear:{kx:1.5,ky:975/eo,kz:506/to,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}),QM=(e,t)=>({...nr[e],value:t});function ZM(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 no(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 Br(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:QM("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]=QM(r,n);return t}var Pa={name:"Formula Student",m:300,A:1,cl:3,cw:1.3,frontMass:.47,frontAero:.45,rDyn:.222,drivenWheels:2,gearRatio:11.5,motor:ZM(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}},zb={name:"Formula 1",m:798,A:1.5,cl:3,cw:.9,frontMass:.46,frontAero:.44,rDyn:.35,drivenWheels:2,gearRatio:4.9,motor:no(735,2e3,12500,2500,2),motorCount:1,driveline:{rear:ht.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}},sm={name:"GT car",m:1300,A:2,cl:1.4,cw:.42,frontMass:.5,frontAero:.42,rDyn:.33,drivenWheels:2,gearRatio:3.43,motor:no(410,2e3,8e3,2e3,2),motorCount:1,driveline:{rear:ht.clutch},capacityAh:200,ocv:800,drivetrainEfficiency:.9,powerLimitKw:0,tireModelId:"t5",dynamics:{grip_scale:1,stiffness_scale:1,cg_height:450,tire_vertical_rate:280,unsprung_mass:45,brake_balance:.6,arb_front:40,arb_rear:25,damper_front:4.5,damper_rear:4.5,spring_front:110,spring_rear:120,mr_front:.79,mr_rear:.77,cop_long:.58,cop_height:500,ride_height_front:55,ride_height_rear:75,I_yaw:1800,I_roll:450,I_pitch:1800,camber_front_deg:-3.5,camber_rear_deg:-2,track_front:1650,track_rear:1650,wheelbase:2700,rc_front:48,rc_rear:80}},im={name:"Sports car",m:1600,A:2.2,cl:-.1,cw:.3,frontMass:.55,frontAero:.5,rDyn:.32,drivenWheels:2,gearRatio:3.14,motor:no(220,1500,6500,1400,2),motorCount:1,driveline:{rear:ht.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}},Yb={name:"Cup car",m:1265,A:2.1,cl:.45,cw:.4,frontMass:.62,frontAero:.45,rDyn:.31,drivenWheels:2,gearRatio:3.5,motor:no(250,2e3,7e3,1190,2),motorCount:1,motorPlacement:"front",driveline:{front:ht.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}},Wb={name:"Stock car",m:1620,A:2.2,cl:.6,cw:.45,frontMass:.53,frontAero:.45,rDyn:.35,drivenWheels:2,gearRatio:4.1,motor:no(500,2500,9e3,1680,2),motorCount:1,driveline:{rear:ht.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}},jb={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:no(330,3e3,8500,1240,2),motorCount:1,driveline:{rear:ht.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}},Ub={name:"Race truck",m:5300,A:6.2,cl:-.1,cw:.65,frontMass:.6,frontAero:.6,rDyn:.502,drivenWheels:2,gearRatio:3.55,motor:no(880,100,3e3,88e3,2),motorCount:1,driveline:{rear:ht.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 Hb(e,t,r){return Br(r({...structuredClone(e),name:t}))}var cm={[Pa.name]:Br(Pa),"Formula Student +15% downforce":Hb(Pa,"Formula Student +15% downforce",e=>({...e,cl:e.cl*1.15,cw:e.cw*1.08})),"Formula Student -15 kg":Hb(Pa,"Formula Student -15 kg",e=>({...e,m:e.m-15})),"Formula Student +15% power":Hb(Pa,"Formula Student +15% power",e=>({...e,motor:ZM(25*1.15,15e3,2e4),powerLimitKw:80*1.15})),[zb.name]:Br(zb),[sm.name]:Br(sm),[im.name]:Br(im),[Yb.name]:Br(Yb),[Wb.name]:Br(Wb),[jb.name]:Br(jb),[Ub.name]:Br(Ub)},JM=Object.keys(cm),Xb=JM.slice(0,4),qb=[Pa.name,zb.name,sm.name,im.name,Yb.name,Wb.name,jb.name,Ub.name];var yee={"Touring car":sm.name,"Street car":im.name};var v2={bg:"#0e1116",panel:"#161b22",panel2:"#1c232d",border:"#2a323d",borderBright:"#39424e",sunken:"#11161c",ink:"#06090d"},k2={normal:"#d6dde6",dim:"#8b96a3",bright:"#e7ecf3",white:"#ffffff"},M2={label:"#c8d2dc",grid:"#39424e",gridFaint:"#232b35",empty:"#1a2028"},S2={accent:"#4aa3ff",accentInk:"#04121f",warn:"#ffb454",good:"#4ec9a0",bad:"#ff6b6b",badSoft:"#ff8f8f"},A2=["#f0e442","#7b68ee","#f7a8b8","#d55e00","#d8b4fe","#b5e48c"],lm={front:"#a6e22e",rear:"#00b4d8"},eS=["#5b4bd6","#4aa3ff","#4ec9a0","#f0e442"],Qb={power:"#ffb454",traction:"#f0845c",front:lm.front,rear:lm.rear,grip:"#73c9b3",braking:"#b48aff",crest:"#e88fd0",below:"rgba(214, 221, 230, 0.32)"},F2={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"},C2={x:"#ff6b6b",y:"#57c75a",z:"#4aa3ff"},w2={line:"#b4bfcb"},T2={compression:"#b48aff",tension:"#ff6b6b"},P2={fz:"#e7ecf3",fx:"#7ad7f0",fy:"#ff54c8"},L2={drivenLine:"#4d7cff",axis:"#eef3fa",slip:"#ffe81a",drive:Qb.power,brake:Qb.braking},D2={ground:"#101920",grid:"#1a2630",gridMajor:"#26343f",horizon:"#1d2833",bridge:"#6f7a86",coneLeft:"#2f63c9",coneRight:"#d9b51f",coneStart:"#ee7a2c"},E2={chassis:"#435160",volume:"#303b47",tyre:"#435160",tyreLine:"#39424e",tyreFace:"#1c232d"},I2={centreLine:"#4aa3ff",corridorFill:"rgba(74,163,255,0.10)",boundary:"#3d4956",racingLine:"#ffb454",start:"#e7ecf3",finish:"#ff6b6b",direction:"#8b96a3"},_2={SURFACE:v2,TEXT:k2,CHART:M2,ROLE:S2,SERIES:A2,AXLE:lm,LAP_SPEED:eS,LIMITER:Qb,RIG:F2,AXIS:C2,CONSTRUCTION:w2,FORCE:T2,TYRE_FORCE:P2,REPLAY:L2,SCENERY:D2,BODY:E2,TRACK:I2},tS=e=>Object.fromEntries(Object.entries(e).map(([t,r])=>[t,Array.isArray(r)?Object.freeze([...r]):Object.freeze({...r})])),um=tS(_2),yt=um.SERIES,rS=(()=>{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 tS({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 nS=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},Ree=(()=>{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=um[r],o=rS[r];for(let a of Object.keys(n)){let s=nS(n[a]);s&&!e.has(s)&&e.set(s,o[a])}}return e})();var oS=(e,t)=>new Set(t.flatMap(r=>{let n=e[r];return Array.isArray(n)?[...n]:Object.values(n)}).map(nS).filter(r=>r!==null)),vee=oS(rS,["SERIES","AXLE","LAP_SPEED","LIMITER","ROLE","RIG","FORCE","TYRE_FORCE","REPLAY","AXIS","TRACK","CONSTRUCTION"]),kee=oS(um,Object.keys(um).filter(e=>e!=="SURFACE"));function Zb(){return{kind:"simple",name:"Simple motor",rpm:[0,16e3,2e4],torque:[21,21,14],efficiency:.95}}function Jb(){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 eg(){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 tg(){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 rg(){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 aS(){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 sS(){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 iS(){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 cS(){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 lS(){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 uS(){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 mS(e){return Xn(N2(e))}function N2(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 Oi(e,t){return{...t,fingerprint:mS(e)}}var pS="CC-BY-4.0",O2={title:"PaceDynamics built-in library",url:"https://pacedyn.dev/",licence:pS},dS={fidelity:"generic",licence:pS,sources:[O2]};var mm=e=>Oi(e,dS);var fS=["raw.githubusercontent.com"],hS=["tum-csv"],B2=/^[0-9a-f]{64}$/;function Bi(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"||!B2.test(r)||!hS.includes(n))return!1;try{let o=new URL(t);return o.protocol==="https:"&&fS.includes(o.hostname)&&!o.username&&!o.password&&!o.port}catch{return!1}}var pm=e=>new URL(e.url).hostname;async function bS(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 $2(e){let t=new URL(e).pathname.split("/").pop()??"";return decodeURIComponent(t).replace(/\.[^.]*$/,"")||"Linked track"}function G2(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 K2={"tum-csv":G2};function gS(e,t){return K2[t.format](e,$2(t.url))}async function ng(e,t,r){let n=await bS(e);if(n!==t.sha256)throw new Error(`${pm(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=gS(new TextDecoder().decode(e),t),a=await dm(o);if(a!==r)throw new Error(`Linked track ${r} does not convert to its name (it is ${a}).`);return o}var og=20,z2=new RegExp(`^[0-9a-f]{${og}}$`),$i=e=>typeof e=="string"&&z2.test(e);async function dm(e){let t=new TextEncoder().encode(un(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,og)}var ag=e=>`tracks/${e}.json`;var Y2=e=>typeof e=="object"&&e!==null&&!Array.isArray(e);function sg(e){return{model:{name:e.name,source:e.source},...e.provenance?{provenance:e.provenance}:{}}}async function ig(e,t){if(!Y2(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 dm(e);if(r!==t)throw new Error(`Catalogue track ${t} does not match its name (it is ${r}).`);return e}var oo=(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}),mn=[oo("suspensions","suspensionId","suspension"),oo("tires","tireModelId","tyre",[{key:"tiresRear",ref:"tireModelIdRear",label:"rear tyre"}]),oo("motors","motorModelId","motor"),oo("aeros","aeroModelId","aero map"),oo("batteries","batteryModelId","battery"),oo("brakes","brakeModelId","brakes"),oo("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 fm(e){let t={...e};for(let r of mn)for(let n of r.refs)delete t[n];return t}var hm=yt,Gi=hm,cg=hm,pn=[...yt.slice(3),...yt.slice(0,3)],mg=[...yt.slice(1),yt[0]],lg=[...yt.slice(2),...yt.slice(0,2)],ug=[...yt.slice(4),...yt.slice(0,4)],pg=[...yt.slice(5),...yt.slice(0,5)],Ki=[...yt.slice(2),...yt.slice(0,2)];function dg(){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 fg(e,t,r){let n=cm[e];if(!n)throw new Error(`no preset vehicle named "${e}"`);return{id:t,params:{...Ys(structuredClone(n)),energy:{...Ar},suspensionId:"sus1"},visible:!0,color:Gi[r%Gi.length]}}function U2(){return Xb.map((e,t)=>fg(e,`v${t+1}`,t))}function X2(){return[vs(),Xd(),qd(),Qd(),Zd(),Jd(),ef(),tf(),rf(),nf()].map((t,r)=>({id:`t${r+1}`,color:cg[r%cg.length],model:t}))}function q2(){return[Dp(),Ep(),Ip(),_p(),Np(),Op(),Vp(),Bp()].map((t,r)=>({id:`a${r+1}`,color:lg[r%lg.length],model:t}))}function Q2(){return[gp(),yp(),xp()].map((t,r)=>({id:`b${r+1}`,color:ug[r%ug.length],model:t}))}function Z2(){return[{id:"brk1",color:pg[0],model:structuredClone(Mf)}]}function J2(){return[{id:"dmp1",color:Ki[0],model:structuredClone(jl)}]}function e_(){return[Zb(),Jb()].map((t,r)=>({id:`m${r+1}`,color:pn[r%pn.length],model:t}))}function hg(e){let t=r=>({...r,provenance:mm(r.model)});return{...e,suspensions:e.suspensions.map(t),vehicles:e.vehicles.map(r=>({...r,provenance:mm(fm(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 Hi(e="Untitled project"){let t=new Date().toISOString(),r=U2();return hg({schemaVersion:em,meta:{id:dg(),name:e,domain:"racecar",rulesetId:qn,createdAt:t,updatedAt:t},suspensions:[{id:"sus1",color:mg[0],model:ro()}],activeSuspensionId:"sus1",vehicles:r,activeVehicleId:r[0]?.id??null,tires:X2(),motors:e_(),aeros:q2(),batteries:Q2(),brakes:Z2(),dampers:J2(),tracks:[],activeTrackId:null,mathChannels:[],rulesets:[],studies:[],activeStudyId:null,loadCases:[],reportLayouts:[],tyreSheets:[],kinSheets:[],plans:[],results:[],settings:{numerics:{...ii},ggvMode:"twoTrack",quasiTransient:!1,motorThermal:!1,brakeFade:!1,airTempC:Mt,air:structuredClone(rm),diffYaw:!1,lapCounts:{},pathPlanId:null,useRacingLine:!0,standingStart:!1}})}var t_=9.81,zi={speed:20,ayG:1.2};function bg(e,t={}){let r=t.operating??zi,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}),h=()=>{if(o!==void 0)return o;if(!n)return o=null;try{o=n(e)}catch{o=null}return o},d=()=>{if(a!==void 0)return a;try{a=sr(e.params)}catch{a=null}return a},p=g=>{let y=m(g),R=`${y.speed}|${y.ayG}`,M=i.get(R);if(M!==void 0)return M;let v=d();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},f=()=>{if(s!==void 0)return s;let g=h(),y=d();if(!g||!y)return s=null;try{s=_n(y,g.massTotal*t_*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=h(),x=d(),k=null;if(v&&x)try{k=xh(v,x,y,{steering:!1})}catch{k=null}return c.set(R,k),k};return{operating:r,dynAvailable:!!n,operatingAt:m,dynInput:h,tyre:d,dynCtx:p,grip:f,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?Qh(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=h(),k=p(y),F=null;if(x&&k)try{F=di(x,k,g,f()??void 0)}catch{F=null}return u.set(M,F),F}}}var yS=["widthLeft","widthRight","bank","mu"];function Yi(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 gg(e){let t=Yi(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 gm(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 h of yS){let d=l[h];if(d===void 0)continue;let p=s[h],f=r[h];for(let b=0;b<o&&t[b]<l.from;b++)f=p[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;p[b]=u>0&&y<u?f+(d-f)*(y/u):d}}}return s}function ym(e,t,r){if(!t.length)return e;let n=Yi(e),o=n.length,a={widthLeft:bm(e.widthLeft,r.widthLeft),widthRight:bm(e.widthRight,r.widthRight),bank:bm(e.bank,r.bank),mu:bm(e.mu,r.mu)},s={};for(let c of yS){let l=e[c];Array.isArray(l)&&l.length===o&&(s[c]=l)}let i=gm(t,n,a,s);return{...e,...i}}function bm(e,t){return typeof e=="number"?e:t}var vS=1,xS=4,Rm=Math.PI/180,yg=e=>e===null||!Number.isFinite(e)||e===0?0:1/e;function xg(e){return e.kind==="arc"?Math.abs(e.radius)*Math.abs(e.angle)*Rm:e.length}function xm(e,t){return e.kind==="straight"?0:e.kind==="arc"?yg(e.radius):t}function RS(e){return e.kind==="straight"?0:e.kind==="arc"?yg(e.radius):yg(e.endRadius)}var Wi=(e,t,r,n,o)=>e+t*o+(n>0?(r-t)*o*o/(2*n):0);function ji(e,t={}){let r=Math.max(.05,t.spacing??vS),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+xg(A),0),m=Math.max(n?3:2,Math.round(u/r)),h=u>0?u/m:r,d=o.x,p=o.y,f=o.heading*Rm,b=e.length?xm(e[0],0):0,g=0,y=h,R=(S,A,P)=>{s.push(S),i.push(A),c.push(P)};R(d,p,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=Wi(f,S,S,P,L);if(Math.abs(S)<1e-12)d+=I*Math.cos(O),p+=I*Math.sin(O);else{let W=O+S*I;d+=(Math.sin(W)-Math.sin(O))/S,p+=-(Math.cos(W)-Math.cos(O))/S}return}let G=I/xS;for(let O=0;O<xS;O++){let W=L+O*G,E=Wi(f,S,A,P,W),_=Wi(f,S,A,P,W+G/2),V=Wi(f,S,A,P,W+G);d+=G/6*(Math.cos(E)+4*Math.cos(_)+Math.cos(V)),p+=G/6*(Math.sin(E)+4*Math.sin(_)+Math.sin(V))}};for(let S of e){let A=xg(S),P=xm(S,b),L=RS(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(d,p,g+I),y+=h}M(P,L,A,D,A),f=Wi(f,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?xm(e[0],b):0,F={gap:v,headingError:r_((f-o.heading*Rm)/Rm),curvatureError:b-k},C=[];for(let S=0;S<e.length;S++){let A=RS(e[S]),P=S+1<e.length?e[S+1]:n?e[0]:null;if(!P)continue;let L=xm(P,A);C.push({index:S,before:A,after:L,jump:Math.abs(L-A)})}let w=gm(l,c,a);return{asset:{name:t.name??"Track",x:s,y:i,fit:"interpolate",...n?{}:{closed:!1},...w},sections:l,joints:C,closure:F,length:x}}function r_(e){let t=e%360;return t>180&&(t-=360),t<-180&&(t+=360),t}var n_={halfWidthM:1.5,spacingM:.5};function Ui(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 ${MS(e).toFixed(0)} m`}}}function MS(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 SS=e=>e.kind==="skidpad"||e.kind==="curves"&&e.closed===!0,AS=e=>e.kind==="acceleration",FS=1.5,CS=3;function o_(e,t){let r=e.offsetM,n=e.pitchM,o=Math.max(1,e.gates)*n,a=Math.max(0,e.leadInM),s=FS*n,i=f=>{let b=Math.min(1,Math.max(0,f));return b*b*b*(b*(b*6-15)+10)},c=f=>Math.min(i(f/s),i((o-f)/s)),l=r*(Math.PI/n)**2,u=l>0?Math.max(.05,Math.min(t.spacingM,1/l*(CS*Math.PI/180))):t.spacingM,m=[],h=[],d=Math.max(1,Math.round(a/u));for(let f=0;f<d;f++)m.push(-a+a*f/d),h.push(0);let p=Math.max(8,Math.round(o/u));for(let f=0;f<=p;f++){let b=o*f/p;m.push(b),h.push(r*c(b)*Math.sin(Math.PI*b/n))}return{name:Ui(e),x:m,y:h,closed:!1,widthLeft:t.halfWidthM,widthRight:t.halfWidthM,fit:"interpolate"}}function a_(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 Rg(e,t={}){let r={...n_,...t},n=AS(e),o=a_(e);if(!o){let u=o_(e,r);return{asset:u,peakCurvature:kS(u),worstJoint:0,standingStart:n}}let a=SS(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*(CS*Math.PI/180))):r.spacingM,c=ji(o,{name:Ui(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:kS(c.asset),worstJoint:l.reduce((u,m)=>Math.max(u,m.jump),0),standingStart:n}}function kS(e){try{return Math.max(...gt(e).curvature.map(Math.abs))}catch{return NaN}}var km={courses:[{id:"c1",course:{kind:"manoeuvre",spec:{kind:"skidpad",radiusM:8.375}}}],ggvMode:"twoTrack"};function vg(e){return e.course.kind==="project"?"the project\u2019s track":e.course.kind==="track"?e.course.name:Ui(e.course.spec)}var wS=new WeakMap,vm=new Map;function TS(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=vm.get(n);if(o)return{...o,numerics:r};let a=Rg(e.spec),s={asset:a.asset,standingStart:a.standingStart};return vm.size>64&&vm.clear(),vm.set(n,s),{...s,numerics:r}}function kg(e,t,r={}){let n=r.lap??km,o=r.simParams,a=r.numerics??{},s=n.courses.length?n.courses:km.courses,i,c,l,u=new Map,m=new Map,h=new Map,d=new Map,p=M=>(M?.courseId?s.find(v=>v.id===M.courseId):void 0)??s[0],f=()=>{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=p(M);if(!v)return null;let x=m.get(v.id);if(x!==void 0)return x;let k=TS(v.course,r,a),F=null;if(k)try{let C=JSON.stringify(k.numerics),w=wS.get(k.asset);w||(w=new Map,wS.set(k.asset,w));let T=w.get(C);T||(T=gt(k.asset,k.numerics),w.set(C,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=f();if(!M)return c=null;try{l=At(M),c=ir(l,!1,n.ggvMode)}catch{c=null}return c},y=M=>{let v=b(M);if(!v)return null;let x=h.get(v.id);if(x!==void 0)return x;let k=g(),F=null;if(k)try{let C=l?Wn(l,k,[v.track],v.numerics,n.ggvMode,u):void 0,w=l?cn(l,k.rows):void 0;F=bt(k,v.track,v.numerics,{standingStart:v.standingStart,...C?{load:C}:{},...w?{shifts:w}:{}})}catch{F=null}return h.set(v.id,F),F};return{lapSettings:n,get lapAvailable(){return!!o&&s.some(M=>!!TS(M.course,r,a))},lapParams:f,courses:()=>s,course:b,ggv:g,lap:y,lapReserve:M=>{let v=b(M);if(!v)return null;let x=d.get(v.id);if(x!==void 0)return x;let k=y(M),F=t.dynInput(),C=t.tyre(),w=null;if(k&&F&&C)try{let T=f();w=wu(F,C,{v:k.v,ax:k.ax,ay:k.ay,ds:v.track.ds,axDrag:ka(g()?.rows,k.v),...k.axScrub?{axScrub:k.axScrub}:{},axGrade:sn(v.track.gradient,k.v.length),bank:v.track.bank,...k.loadFactor?{loadFactor:k.loadFactor}:{}},T?{driven:Vf(T)}:{})}catch{w=null}return d.set(v.id,w),w}}}var PS=180/Math.PI,Mg={rise:0,sinPitch:0,sinRoll:0};function LS(e){let t=e.kc;return t?DS(e.vehicle,r=>t.ground0[r]):Mg}function DS(e,t){let r=e.config,n=Lo(r),o=0,a=0,s=0,i=0,c=0,l=0,u=0,m=0,h=0;for(let g of Po){let y=Ze(g,r),R=y.axleX-n,M=y.sideSign*jr(e,y.isFront)/2,v=t(g);if(!Number.isFinite(v))return Mg;o++,a+=R,s+=M,i+=v,c+=R*R,l+=M*M,u+=R*M,m+=R*v,h+=M*v}let d=o*(c*l-u*u)-a*(a*l-u*s)+s*(a*u-c*s);if(!(Math.abs(d)>1e-9))return{rise:i/o,sinPitch:0,sinRoll:0};let p=(i*(c*l-u*u)-a*(m*l-u*h)+s*(m*u-c*h))/d,f=(o*(m*l-u*h)-i*(a*l-u*s)+s*(a*h-m*s))/d,b=(o*(c*h-m*u)-a*(a*h-m*s)+i*(a*u-c*s))/d;return{rise:p,sinPitch:f,sinRoll:-b}}function Xi(e,t){let r=e.kc,n=DS(e.vehicle,o=>(r?r.ground0[o]:0)+t[o]);return q([-n.sinPitch,n.sinRoll,1])}function Sg(e,t,r,n){let o=q(Rn(e,Ze(t,r)));return-Math.asin(Math.max(-1,Math.min(1,X(o,n))))*PS}function Mm(e,t,r,n,o){let a=q(Rn(n,Ze(t,r))),s=q([1-a[0]*a[0],-a[0]*a[1],-a[0]*a[2]]),i=ae(a,s),c=d=>[X(d,s),X(d,i),X(d,a)],l=d=>ee(ee(U(s,d[0]),U(i,d[1])),U(a,d[2])),u=e.points,m=c(u.spinAxis),h=Ua({uprightUpper:c(u.uprightUpper),uprightLower:c(u.uprightLower),wheelCenter:c(u.wheelCenter),spinAxis:m,tieOuter:c(u.tieOuter),loadedRadius:o.loadedRadius,patchShift:o.patchShift&&s_(o.patchShift,e.metrics.toe/PS,Math.atan2(m[0],m[1]))});return{caster:h.caster,kpi:h.kpi,scrubRadius:h.scrubRadius,mechanicalTrail:h.mechanicalTrail,scrubAtWheel:h.scrubAtWheel,trailAtWheel:h.trailAtWheel,kingpinOffset:h.kingpinOffset,casterOffset:h.casterOffset,kingpinGround:l(h.kingpinGround),contactPatch:l(h.contactPatch),elbow:l([h.contactPatch[0],h.kingpinGround[1],h.kingpinGround[2]]),kingpinAtHub:l(h.kingpinAtHub)}}function s_(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 ES(e,t){let r=LS(t);if(r===Mg)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 Ag(e,t,r){let n=ES({heave:0,pitch:0,roll:0,steer:0},r);return e-Jp(n,[t,0,0],Lo(r.vehicle.config))}var i_=180/Math.PI;function Fg(e,t){return!e.valid||!e.ic?!1:Math.hypot(e.ic[0]-e.cp[0],e.ic[1]-e.cp[1])<=t}function Sm(e,t,r){let n=Ze(t,e.vehicle.config),o=dt(e,r),a=Zl(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),h=u(l),d=[c[0],c[2]],p=[l[0],l[2]];if(!a.solved)return{ic:null,line:null,cp:d,wc:p,road:[1,0],swingArmAngleDeg:NaN,tanTheta:NaN,tanThetaHub:NaN,valid:!1,unsolved:!0,sinAngle:0};let f=Xi(e,{FL:o.FL.ground,FR:o.FR.ground,RL:o.RL.ground,RR:o.RR.ground}),b=Math.hypot(f[0],f[2]),g=[f[0]/b,f[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?[d[0]+m[1]/M,d[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:d,wc:p,road:y,swingArmAngleDeg:0,tanTheta:0,tanThetaHub:0,valid:!1,sinAngle:F};let C=[m[1]/v,-m[0]/v],w=x?[x[0]-d[0],x[1]-d[1]]:[n.isFront?-1:1,0],T=C[0]*w[0]+C[1]*w[1]<0?[-C[0],-C[1]]:C,S=R(m);return{ic:x,line:T,cp:d,wc:p,road:y,swingArmAngleDeg:Math.atan(S)*i_,tanTheta:S,tanThetaHub:R(h),valid:!0,sinAngle:F}}function IS(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 l_=180/Math.PI,u_=Math.PI/180,Cg=.5,Am=2,wg=.25,m_={heave:0,pitch:0,roll:0,steer:0},p_={FL:"FR",FR:"FL",RL:"RR",RR:"RL"},Fm=e=>e.ok?e.state:{...e.nearest,converged:!1};function Tg(e,t,r){return t.state?t.solved===!1?{...t.state,converged:!1}:t.state:Fm(ge(e,t.travel,t.steer,void 0,r))}var _S=new WeakMap;function NS(e,t){let r=e.ctx[t],n=$e(e.vehicle,t).config.loadedRadius,o=Qt(n,e.kc,t),a=_S.get(r);a||(a=new Map,_S.set(r,a));let s=a.get(o);if(!s){let i=Ur(t,e.vehicle.config,m_,e.vehicle);s=Fm(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),OS=(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 BS(e,t,r,n,o){let a=e.vehicle.config,s=To(r),i=$e(e.vehicle,r),c=Ze(r,a),l=e.ctx[r],u=dt(e,t),m=u[r],h={travel:m.travel,steer:m.steer},d=m.rigid?void 0:{loadedRadius:m.loadedRadius},p=Tg(l,m,d),f=NS(e,r),b={lo:Fm(ge(l,h.travel-Cg,h.steer,void 0,d)),hi:Fm(ge(l,h.travel+Cg,h.steer,void 0,d)),step:Cg},g=c.isFront?{lo:Ee(l,p.beta,h.steer-Am,void 0,d),hi:Ee(l,p.beta,h.steer+Am,void 0,d),step:Am}:null,y=z=>{let j=dt(e,{...t,roll:t.roll+z*u_})[r];return Tg(l,j,j.rigid?void 0:{loadedRadius:j.loadedRadius})},R={lo:y(-wg),hi:y(wg),step:wg},M=f_(e,t,r,c.isFront,u,g),v=_t(p.points.contactPatch,c),x=_t(f.points.contactPatch,c),k=Math.abs(v[1])-Math.abs(x[1]),F=p_[r],C=u[F],w=Tg(e.ctx[F],C,C.rigid?void 0:{loadedRadius:C.loadedRadius}),T=w.converged?k+Math.abs(w.points.contactPatch[1])-Math.abs(NS(e,F).points.contactPatch[1]):NaN,S=o??or(e,t,s),A=Jl(S,pt(i)),P=A?null:h1(S),L=c.sideSign>0?S.icRight:S.icLeft,D=L?Math.hypot(L[0]-v[1],L[1]-v[2]):1/0,I=Sm(e,r,t),G=I.ic?Math.hypot(I.ic[0]-I.cp[0],I.ic[1]-I.cp[1]):1/0,O=IS(I,s,a.wheelbase,n),W=-mr(b,z=>z.points.damperLength),E=i.config.springRate,_=mr(R,z=>z.metrics.camber),V=Xi(e,{FL:u.FL.ground,FR:u.FR.ground,RL:u.RL.ground,RR:u.RR.ground}),N=e.kc?.loadCase,$=z=>N?Mm(z,r,a,V,{loadedRadius:m.loadedRadius,patchShift:N.patchShift[r]}):z.metrics,K=$(p);return{id:r,converged:p.converged,travel:p.travel,camber:p.metrics.camber,camberRoad:Sg(p.points.spinAxis,r,a,V),toe:p.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:p.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:OS(g,z=>z.metrics.camber,z=>z.metrics.toe),steerJacking:-OS(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)-Ag(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:Fg(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:p.points.damperLength,damperTravel:f.points.damperLength-p.points.damperLength,...d_(i,f.points.damperLength,p.points.damperLength,e.kc?.curve[r].spring?.law),rockerAngle:i.config.actuation==="direct"?0:(p.points.rockerAngle-f.points.rockerAngle)*l_,groundDisplacement:m.rigid?p.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 d_(e,t,r,n){if(e.config.actuation==="decoupled")return{};let o=n?{droop:n.droopStated?n.droop:null,bump:n.bump}:Eo(t,e.config.coilover),a=t-r;return{...o.droop!==null?{damperToExtended:a-o.droop}:{},...o.bump!==null?{damperToClosed:o.bump-a}:{}}}function f_(e,t,r,n,o,a){if(!a||!n)return;let s=zc(e,t,"front"),i=e.kc;if(!s||!i)return;let c=["FL","FR"],l=[0,0],u=[0,0],m={lo:[],hi:[]},h=0;for(let f=0;f<2;f++){let b=c[f],g=o[b],y=e.ctx[b],R=g.rigid?void 0:{loadedRadius:g.loadedRadius},x=(b==="FR"?1:-1)*(r==="FR"?1:-1)*Am,k=g.state?{q:[...g.state.pose.t,...g.state.pose.omega],phi:g.state.points.rockerAngle}:void 0,F=mt(ge(y,g.travel,g.steer-x,k,R)),C=mt(ge(y,g.travel,g.steer+x,k,R));if(!F||!C)return NaN;l[f]=C.points.contactPatch[2]-F.points.contactPatch[2],u[f]=hr(i.curve[b],g.travel,C.points.damperLength)-hr(i.curve[b],g.travel,F.points.damperLength),m.lo.push(F),m.hi.push(C),b===r&&(h=C.metrics.toe-F.metrics.toe)}let d=i.elements?.front;if(d){let f=[o.FL.travel,o.FR.travel],b=os(d,f,[m.hi[0],m.hi[1]]),g=os(d,f,[m.lo[0],m.lo[1]]);u[0]+=b[0]-g[0],u[1]+=b[1]-g[1]}return Math.abs(h)>1e-9?s([0,0],l,u)[r==="FL"?0:1]/h:NaN}function qi(e,t,r,n,o){return BS(e,t,r==="front"?"FL":"RL",n,o)}function Pg(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 Lg=Math.PI/180,Cm={travelSteps:9,heaveSteps:5,rollSteps:4,rackSteps:6},wm={travelMin:-25,travelMax:25,rollMaxDeg:3,rollAtLimitDeg:2.5};function h_(e){let t=e.params;return{cgHeight:t.cg_height?lt({...t,surveyedRadiusFront:e.vehicle.front.config.loadedRadius,surveyedRadiusRear:e.vehicle.rear.config.loadedRadius}).cgHeight:300,...Kf(t),drive:Bf(t)}}function Dg(e,t=Cm,r=wm,n){let o=null,a=(S,A)=>(o||(o={violation:S,reason:A}),null),s=e.vehicle,i=S=>S==="front"?s.front:s.rear,c=null,l=null,u=()=>{if(c)return c;if(n)try{let S=n();if(S)return c=Ct(s,S.kc),l=S.cgHeight,c}catch{a(500,"the car could not be stood on its tyre: its rates did not assemble")}return c=Ct(s)},m=S=>S==="front"?"FL":"RL",h=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}},d=(S,A)=>-as(u(),m(S),A),p=new Map,f=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=h_(e);return v=l!==null&&Number.isFinite(l)?{...S,cgHeight:l}:S},k,F,C=()=>{if(F!==void 0)return F;let S=qc(u().ctx.FL,Nt(s.front.config));return F=S?Qc(S):null,F},w=(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=>w(f,S,()=>zd(i(S))??null),sweep:S=>w(p,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=C();if(L)return a(L.violation,L.reason)}return A}),rcHeave:S=>w(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:d(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=>w(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*Lg,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=Ad(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=C();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)=>w(y,`${S}:${A}:${P}`,()=>{try{let L=ge(u().ctx[m(S)],A,P,void 0,h(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=>w(R,`${S.heave}:${S.pitch}:${S.roll}:${S.steer}`,()=>{try{return Pg(u(),S,x())}catch{return a(500,"the derived readout threw")}}),readoutAtTravel:(S,A)=>w(M,`${S}:${A}`,()=>{try{return qi(u(),{heave:d(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*Lg),L=u();if(!L.kc)return P;try{let D=dt(L,{heave:0,pitch:0,roll:A*Lg,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 b_=Eb();function Eg(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=Yu(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?Li([c],a.track,a.numerics,Fi(s),a.settings,b_)[0]:gi(c,s,{numerics:a.numerics,standingStart:l,lapCounts:u});o={};for(let h of s.metrics)bc(h)&&(o[h.key]=h.value(m,void 0))}}catch{o=null}return r.set(n,o),o}}}var Tm=Math.PI/180,Pm=1e-6;function GS(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 Qi(e){let t=e.measured;if(t)return GS(t.travel,t.camber);let r=q(e.config.spinAxis);return-Math.asin(Math.max(-1,Math.min(1,r[2])))/Tm}function Zi(e){let t=e.measured;if(t)return GS(t.travel,t.toe);let[r,n]=e.config.spinAxis;return Math.atan2(r,n)/Tm}function Ig(e,t){let r=Math.abs(t.camber)>=Pm,n=Math.abs(t.toe)>=Pm;if(!r&&!n)return e;let o=e.measured;if(o)return{...e,measured:{...o,...r?{camber:o.camber.map(d=>d+t.camber)}:{},...n?{toe:o.toe.map(d=>d+t.toe)}:{}}};let[a,s]=e.config.spinAxis,i=Math.hypot(a,s);if(!(i>0))return e;let c=(Qi(e)+t.camber)*Tm,l=(Zi(e)+t.toe)*Tm,[u,m]=n?[Math.sin(l),Math.cos(l)]:[a/i,s/i],h=[u*Math.cos(c),m*Math.cos(c),-Math.sin(c)];return{...e,config:{...e.config,spinAxis:h}}}function Lm(e){let t=e&&typeof e=="object"?e.value:void 0;return typeof t=="number"&&Number.isFinite(t)?t:void 0}function g_(e,t){let r=t;return{front:Lm(r.camber_front_deg)??Qi(e.front),rear:Lm(r.camber_rear_deg)??Qi(e.rear)}}function y_(e,t){let r=t;return{front:Lm(r.toe_front_deg)??Zi(e.front),rear:Lm(r.toe_rear_deg)??Zi(e.rear)}}function x_(e){return{camber:{front:Qi(e.front),rear:Qi(e.rear)},toe:{front:Zi(e.front),rear:Zi(e.rear)}}}var $S=new WeakMap;function R_(e,t){let r=x_(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)<Pm&&Math.abs(u.toe)<Pm;if(o(n.front)&&o(n.rear))return e;let a=`${t.camber.front}|${t.camber.rear}|${t.toe.front}|${t.toe.rear}`,s=$S.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&&Ig(m,n[To(u)])])):void 0,l={...e,front:Ig(e.front,n.front),rear:Ig(e.rear,n.rear),...c?{corners:c}:{}};return s||$S.set(e,s=new Map),s.size>=16&&s.clear(),s.set(a,l),l}function Dm(e,t){return t?R_(e,{camber:g_(e,t),toe:y_(e,t)}):e}var v_=9.81;function La(e){let t=Sn(e),r=Math.max(0,e.unsprungPerCorner)*v_,n=a=>{let s=a==="FL"||a==="FR",i=s?"front":"rear",c=Ue(e,i),l=c>0?c:1/0,u=kp(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 KS=new WeakMap;function k_(e){let t=Dm(e.vehicle,e.params);if(t===e.vehicle)return e;let r=KS.get(e);return(!r||r.vehicle!==t)&&KS.set(e,r={...e,vehicle:t}),r}function Da(e,t={}){let r=k_(e),n=bg(r,t),o=t.assemble?()=>{let c=n.dynInput();if(!c)throw new Error("the car did not assemble");return{kc:La(c),cgHeight:c.cgHeight}}:void 0,a=Dg(r,t.density,t.envelope,o),s=kg(r,n,t),i=Eg(r,t);return{...a,...n,...s,...i,get failure(){return a.failure},values:new Map}}function _g(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 Ng=e=>e?.reads==="speed"||e?.reads==="operating",Og=e=>e?.reads==="lateral"||e?.reads==="operating";function ao(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}@${ao(r)}`,o=e.values.get(n);if(o!==void 0)return o;let a;try{a=r?.courseId==="*"&&t.reads==="course"?M_(e,t,r):t.read(e,r)}catch{a=NaN}return e.values.set(n,a),a}function M_(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 xt(e){return`${e.quantity??e.groupShort??e.group} \xB7 ${e.label}`}var S_={front:"Front",rear:"Rear"},Ji={heave:0,pitch:0,roll:0,steer:0};function HS(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 A_(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 ec=e=>e.length?Math.max(...e)-Math.min(...e):NaN;function zS(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 YS(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 WS(e){let t=S_[e],r=x=>`kin.${e}.${x}`,n=(x,k)=>{let F=x.sweep(e);return F?{x:F.samples.map(C=>C.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 h(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 d=x=>{if(u(x.car))return null;let k=x.sweep(e);return k?md(o(x.car),a(x.car).linkage,k.samples):null},p=x=>{if(h(x.car))return null;let k=x.sweep(e);if(!k)return null;let F=s(x.car),C=cd(o(x.car),F.linkage,F.design.kind,k.samples),w=C.atDesign<0?-1:1;return{travel:C.travel,ratio:C.ratio.map(T=>T*w),atDesign:C.atDesign*w}},f=x=>x.readout(Ji)?.[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?A_(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?ec(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?ec(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(C=>C.sinAngle),...F.rc.map(C=>C.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=>f(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=>f(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=>f(x)?.rollCamber??NaN},{id:r("rollCamberRecovery"),group:`${t} camber & toe`,label:"camber recovery in roll",unit:"%",scale:20,scope:e,cost:"readout",read:x=>f(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=>f(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=>f(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?HS(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?HS(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=>ec(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=>ec(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=>f(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=>f(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=>f(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=>f(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?YS(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(w=>w.metrics.motionRatio??NaN).filter(Number.isFinite);if(!F.length)return NaN;let C=F.reduce((w,T)=>w+T,0)/F.length;return C>0?(Math.max(...F)-Math.min(...F))/C: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?YS(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=>d(x)?.atDesign??NaN,curve:x=>{let k=d(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=>zS(d(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:ua(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:h,read:x=>p(x)?.atDesign??NaN,curve:x=>{let k=p(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:h,read:x=>zS(p(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:Bn(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(Ji)?.[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:ec(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=>f(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=>f(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(Ji)?.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(Ji)?.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(Ji)?.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 jS(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 F_=[{id:"kin.front.ackermannCentre",group:"Steering",label:"Ackermann near centre",unit:"%",scale:25,scope:"front",cost:"cheap",read:e=>jS(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=>jS(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}}],C_=[{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}}],Vg=[...WS("front"),...WS("rear"),...F_,...C_];var US={understeer:"operating",yawFreq:"speed",yawZeta:"speed",yawStiffness:"operating",steeringTorque:"operating",steeringTorqueGradient:"operating"};function rt(e,t,r,n="cheap"){let o=Zh[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,...US[e]?{reads:US[e]}:{},read:(a,s)=>{let i=a.dynInput(),c=a.dynCtx(s);return i&&c?o.compute(i,c):NaN}}}var w_=[rt("understeer","Handling \u2014 balance",.1),rt("tlltdFront","Handling \u2014 balance",5),rt("rollStiffFront","Handling \u2014 balance",5)],T_=[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")],P_=[rt("steeringTorque","Steering feel",1,"trim"),rt("steeringTorqueGradient","Steering feel",2,"trim")],L_=[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)],D_=[{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}],E_=[{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}],Bg=[...w_,...T_,...P_,...L_,...D_,...E_];function I_(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 $g=[{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)=>I_(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 __(e,t){let r=/^(.*?)\s*\(([^)]+)\)\s*$/.exec(e);return r?{label:r[1],unit:r[2]}:{label:e,unit:t?"s":""}}function N_(e){return e==="s"||e==="kWh"?.1:e==="km/h"?2:1}var XS=new WeakMap;function Em(e){let t=XS.get(e);return t||(t=e.metrics.filter(bc).map(r=>{let{label:n,unit:o}=__(r.label,r.format==="time");return{id:`event.${e.id}.${r.key}`,group:`Events \xB7 ${e.label}`,groupShort:"Events",label:n,unit:o,scale:N_(o),scope:"car",cost:"session",read:a=>a.session(e.id)?.[r.key]??NaN}}),XS.set(e,t),t)}var Gg=Aa.flatMap(Em);var Im=[...Vg,...Bg,...$g,...Gg],Ea=Object.fromEntries(Im.map(e=>[e.id,e]));var qS={all:Im,byId:Ea},QS=new WeakMap;function $r(e=[]){if(e.length===0)return qS;let t=QS.get(e);if(t)return t;let r=Mb(e).filter(n=>!Fa(n.id)).flatMap(Em);return t=r.length?{all:[...Im,...r],byId:{...Ea,...Object.fromEntries(r.map(n=>[n.id,n]))}}:qS,QS.set(e,t),t}var tc=180/Math.PI,Ia=Math.PI/180,V_=.2;function _m(e,t){let r=H(t,e);return q(r[0]<0?zp(r):r)}var Nm=e=>({side:Math.atan2(e[2],e[0])*tc,plan:Math.atan2(e[1],e[0])*tc}),Om=(e,t)=>q([1,Math.tan(t*Ia),Math.tan(e*Ia)]),rc=e=>Math.abs(e[0])>=V_,Vm=(e,t)=>Math.atan(t/Math.max(e,1))*tc,Bm=(e,t)=>Math.tan(t*Ia)*Math.max(e,1);var dn=["side","plan","clock","len"],jt={uca:{fore:"ucaFront",aft:"ucaRear",ball:"uprightUpper"},lca:{fore:"lcaFront",aft:"lcaRear",ball:"uprightLower"}},nc={uca:"upper arm",lca:"lower arm"},B_=1,ZS=(e,t)=>_m(e[jt[t].fore],e[jt[t].aft]);function JS(e){let t=q(H(Hp,U(e,X(Hp,e))));return{e1:t,e2:ae(e,t)}}function Kg(e,t){let r=ZS(e,t);if(!rc(r))return`the ${nc[t]}'s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it`;let n=jt[t],o=Wr(e[n.ball],e[n.fore],r);return Math.hypot(...H(o,e[n.ball]))>=B_?null:`the ${nc[t]}'s ball joint sits on its own pivot axis, so the arm has no length to swing on`}function Gr(e,t){let r=jt[t],n=e[r.ball],o=ZS(e,t),a=Wr(n,e[r.fore],o),s=H(a,n),i=Math.hypot(s[0],s[1],s[2]),{e1:c,e2:l}=JS(o),u=i>0?U(s,1/i):c;return{...Nm(o),clock:Math.atan2(X(u,l),X(u,c))*tc,len:i,sFront:X(H(e[r.fore],a),o),sRear:X(H(e[r.aft],a),o)}}function Hg(e,t){let r=Om(e.side,e.plan),{e1:n,e2:o}=JS(r),a=ee(U(n,Math.cos(e.clock*Ia)),U(o,Math.sin(e.clock*Ia))),s=ee(t,U(a,e.len));return{fore:ee(s,U(r,e.sFront)),aft:ee(s,U(r,e.sRear))}}function eA(e,t,r,n){let o=jt[t],a={...Gr(e,t),[r]:n},{fore:s,aft:i}=Hg(a,e[o.ball]);return{...e,[o.fore]:s,[o.aft]:i}}function tA(e,t){return t==="clock"?e.len:Math.abs(e.sFront-e.sRear)/2}function $m(e,t,r){return t==="len"?r:Vm(tA(e,t),r)}function zg(e,t,r){return t==="len"?r:Bm(tA(e,t),r)}var so=["side","plan","atY","atZ"],io={fore:"rockerPivotA",aft:"rockerPivotB"},$_=5,rA=e=>_m(e.rockerPivotA,e.rockerPivotB);function _a(e){return Math.hypot(...H(e.rockerPivotB,e.rockerPivotA))<$_?"the rocker\u2019s two pivots are the same point, so there is no axis to describe":rc(rA(e))?null:"the rocker\u2019s pivot axis is nearly across the car, where its side- and plan-view angles stop describing it"}function fn(e){let t=rA(e),r=rc(t)?t:[1,0,0],n=e.rockerPivotA,o=ee(n,U(r,-n[0]/r[0]));return{...Nm(r),atY:o[1],atZ:o[2],sA:X(H(n,o),r),sB:X(H(e.rockerPivotB,o),r)}}function Yg(e){let t=Om(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 nA(e,t,r){if(_a(e))return e;let{a:n,b:o}=Yg({...fn(e),[t]:r});return{...e,rockerPivotA:n,rockerPivotB:o}}var oA=e=>Math.abs(e.sA-e.sB)/2;function Wg(e,t,r){return t==="side"||t==="plan"?Vm(oA(e),r):r}function jg(e,t,r){return t==="side"||t==="plan"?Bm(oA(e),r):r}var Xt={front:"Front",rear:"Rear"},Ut=["x","y","z"],Oe=(e,t)=>t==="front"?e.front:e.rear,oc=(e,t,r)=>t==="front"?{...e,front:r}:{...e,rear:r},aA=[{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"}]}],sA={damperChassis:"strut top mount",pushrodOuter:"strut lower mount"},co=30;function G_(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).config.layout==="mcpherson";for(let o of aA)for(let{key:a,label:s}of o.keys){let i=n&&sA[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:co,read:l=>Oe(l.vehicle,r).hardpoints[a][c],write:(l,u)=>{let m=Oe(l.vehicle,r),h=[...m.hardpoints[a]];h[c]=u;let d={...m.hardpoints,[a]:h};return{...l,vehicle:oc(l.vehicle,r,{...m,hardpoints:d})}}})}}return t}var K_={side:"axis side-view angle",plan:"axis plan-view angle",clock:"arm clock angle",len:"effective arm length"},H_={side:"\xB0",plan:"\xB0",clock:"\xB0",len:"mm"};function z_(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=Kg(a,o)?null:Gr(a,o);for(let i of dn)t.push({id:`arm.${r}.${o}.${i}`,group:`${Xt[r]} ${n?"arm axes":"wishbone axes"}`,label:`${nc[o]} \u2014 ${K_[i]}`,scope:Xt[r],unit:H_[i],defaultSpan:s?$m(s,i,co):co,read:c=>Gr(Oe(c.vehicle,r).hardpoints,o)[i],write:(c,l)=>{let u=Oe(c.vehicle,r),m=eA(u.hardpoints,o,i,l);return{...c,vehicle:oc(c.vehicle,r,{...u,hardpoints:m})}}})}}return t}var Y_={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"},W_={side:"\xB0",plan:"\xB0",atY:"mm",atZ:"mm"};function j_(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r).hardpoints,o=_a(n)?null:fn(n);for(let a of so)t.push({id:`rocker.${r}.${a}`,group:`${Xt[r]} rocker axis`,label:`rocker \u2014 ${Y_[a]}`,scope:Xt[r],unit:W_[a],defaultSpan:o?Wg(o,a,co):co,read:s=>fn(Oe(s.vehicle,r).hardpoints)[a],write:(s,i)=>{let c=Oe(s.vehicle,r),l=nA(c.hardpoints,a,i);return{...s,vehicle:oc(s.vehicle,r,{...c,hardpoints:l})}}})}return t}var Gm={front:"heaveFrontDesign",rear:"heaveRearDesign"},Ug={front:"arbFrontDesign",rear:"arbRearDesign"};function U_(e,t){return{heave:e.config.actuation==="decoupled"?"heave element":"third spring",roll:t?.design.kind==="coil"?"roll shock":"anti-roll bar"}}var Km=e=>/^(heave|roll)\.(front|rear)\.(outer|inner|anchor)\.[xyz]$/.test(e);function X_(e){let t=[];for(let r of["front","rear"]){let n=Oe(e.vehicle,r),o=e.params[Gm[r]],a=e.params[Ug[r]],s=U_(n,a),i=p=>p.params[Gm[r]],c=p=>p.params[Ug[r]],l=(p,f)=>({...p,params:{...p.params,[Gm[r]]:f}}),u=(p,f)=>({...p,params:{...p.params,[Ug[r]]:f}}),m={group:`${Xt[r]} heave & roll elements`,scope:Xt[r]},h=(p,f,b,g,y)=>{for(let R of b)t.push({...m,id:`${p}.${Ut[R]}`,label:`${f} ${Ut[R]}`,unit:"mm",defaultSpan:co,read:M=>g(M)[R],write:(M,v)=>{let x=[...g(M)];return x[R]=v,y(M,x)}})},d=(p,f,b,g,y)=>{t.push({...m,id:p,label:f,unit:"N/mm",defaultSpan:Math.max(5,b*.4),read:g,write:y})};if(o?.design.kind==="coil"){if(o.linkage){let p=b=>i(b).linkage;h(`heave.${r}.outer`,`${s.heave} eye`,[0,1,2],b=>p(b).outer,(b,g)=>l(b,{...i(b),linkage:{...p(b),outer:g}})),o.linkage.mount?.kind==="chassis"&&h(`heave.${r}.anchor`,`${s.heave} chassis anchor`,[0,2],b=>p(b).mount.anchor,(b,g)=>l(b,{...i(b),linkage:{...p(b),mount:{kind:"chassis",anchor:g}}}))}if(typeof o.design.rate=="number"){let p=f=>i(f).design;d(`heave.${r}.rate`,`${s.heave} spring rate (@element)`,o.design.rate,f=>p(f).rate,(f,b)=>l(f,{...i(f),design:{...p(f),rate:b}}))}}if(a&&a.design.kind!=="none"){if(a.linkage&&a.design.kind!=="direct"){let f=R=>c(R).linkage,b=Xr(n,a.linkage,a.design.kind),[g,y]=b?["left arm eye","right arm eye"]:["drop-link pickup","arm tip"];h(`roll.${r}.outer`,`${s.roll} ${g}`,[0,1,2],R=>f(R).outer,(R,M)=>u(R,{...c(R),linkage:{...f(R),outer:M}})),h(`roll.${r}.inner`,`${s.roll} ${y}`,[0,1,2],R=>f(R).inner,(R,M)=>u(R,{...c(R),linkage:{...f(R),inner:M}}))}let p=a.design;if(p.kind==="coil"&&typeof p.rate=="number"){let f=b=>c(b).design;d(`roll.${r}.rate`,`${s.roll} spring rate (@element)`,p.rate,b=>f(b).rate,(b,g)=>u(b,{...c(b),design:{kind:"coil",rate:g}}))}else p.kind==="direct"&&d(`roll.${r}.wheelRate`,`${s.roll} rate (@wheel)`,p.wheelRate,f=>c(f).design.wheelRate,(f,b)=>u(f,{...c(f),design:{kind:"direct",wheelRate:b}}))}}return t}var q_=[{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 Q_(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 h=Oe(u.vehicle,r),d={...h,compliance:c(h.compliance??{},Math.max(1,m))};return{...u,vehicle:oc(u.vehicle,r,d)}}})};for(let a of["ucaFront","ucaRear","lcaFront","lcaRear","tieRod","pushRod"])o(`link.${a}`,`${Z_[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}`,`${J_[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 Z_={ucaFront:"UCA front leg",ucaRear:"UCA rear leg",lcaFront:"LCA front leg",lcaRear:"LCA rear leg",tieRod:"tie rod",pushRod:"push/pull rod"},J_={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 eN(){return q_.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:oc(t.vehicle,e.axle,o)}}}))}function tN(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 rN(e){let t=oi(e.params),r=[];for(let n of["front","rear"]){if(t[n]!=="diff")continue;let o=Gn(e.params.driveline?.[n]);if(o?.kind!=="clutch"&&o?.kind!=="torsen")continue;let a=(s,i)=>{let c=cu[`${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=>Gn(l.params.driveline?.[n])?.[s],write:(l,u)=>({...l,params:{...l.params,driveline:iu({...l.params.driveline,[n]:{...l.params.driveline?.[n],[s]:u}})}})}};o.kind==="clutch"?r.push(a("preloadNm",Math.max(5,.2*o.preloadNm)),a("rampDriveDeg",5),a("rampCoastDeg",5)):r.push(a("tbrDrive",Math.max(.25,.2*o.tbrDrive)),a("tbrCoast",Math.max(.25,.2*o.tbrCoast)))}return r}function nN(e){if(Pl(e.params)!=="hydraulic")return[];let t=[{id:"brakeSetup.barFront",group:"Brakes",label:`${jf("barFront").toLowerCase()}, front share`,unit:"-",defaultSpan:.05,read:a=>Sr(a.params.brakeSetup).barFront,write:(a,s)=>({...a,params:{...a.params,brakeSetup:Sr({...Sr(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:Wf(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 iA=e=>!!e&&typeof e=="object"&&"value"in e&&"label"in e;function cA(e){let t={...e};for(let r of Object.keys(t)){let n=t[r];iA(n)&&(t[r]={...n})}return t}function oN(e){let t=[];for(let r of K1(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 iA(s)?s.value:NaN},write:(a,s)=>{let i=cA(a.params);return du(i,n.label,s),{...a,params:i}}})}return t}function lA(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 aA)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 dn)t[`arm.${s}.${l}.${u}`]={why:c};for(let l of so)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 h of Ut)t[`${u}.${s}.${m}.${h}`]={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 so)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[Gm[s]]?.linkage;if(i.measured||!c||c.attach!=="rocker"||c.mount?.kind==="chassis")continue;let l=i.hardpoints,u=[0,1,2].map(h=>l.rockerPivotB[h]-l.rockerPivotA[h]),m=Math.hypot(u[0],u[1],u[2]);if(m>0)for(let h=0;h<3;h++)Math.abs(u[h]/m)<1-1e-12||(t[`heave.${s}.outer.${Ut[h]}`]={why:`the rocker shaft runs along ${Ut[h]} \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 dn)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=Kg(i.hardpoints,l);if(u)for(let m of dn)t[`arm.${s}.${l}.${m}`]={why:u,useInstead:`hp.${s}.${jt[l].fore}.z`}}let c=_a(i.hardpoints);if(c&&i.config.actuation!=="direct")for(let l of so)t[`rocker.${s}.${l}`]={why:c,useInstead:`hp.${s}.${io.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 h=m.design.kind==="direct"?`${u}.${l}.wheelRate`:`${u}.${l}.rate`;t[i]={why:`computed from ${c}`,useInstead:h}}let o=e.params.aeroModelId||e.params.aeroModel?Ih:_h;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(uu))t[`param.${s}`]={why:i};for(let[s,i]of Object.entries(mu(e.params)))t[`param.${s}`]={why:i};let a=Pl(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 uA(e){let t={...sN,...lA(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[...G_(e),...z_(e),...j_(e),...X_(e),...eN(),...tN(e),...nN(e),...rN(e),...Q_(e),...oN(e.params)].map(r)}var aN={spring_front:"cfg.front.springRate",spring_rear:"cfg.rear.springRate"},sN=Object.fromEntries(Object.entries(Eh).map(([e,t])=>[`param.${e}`,{why:t,useInstead:aN[e]}])),Pt=e=>e.scope?`${e.scope} \xB7 ${e.label}`:e.label;function $t(e){let t={};for(let r of uA(e))t[r.id]=r;return t}var Xg=e=>e.step!==void 0&&Number.isFinite(e.step)&&e.step>0?e.step:0,qg=e=>Xg(e)>0||(e.values?.length??0)>0,Qg=e=>e.some(qg),mA=e=>1e-9*Math.max(1,Math.abs(e.lo),Math.abs(e.hi));function pA(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=Xg(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 dA=(e,t)=>t.map((r,n)=>e[n]&&qg(e[n])?pA(e[n],r):r);function Zg(e,t=1e3){if(e.values?.length)return e.values.length;let r=Xg(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 Jg(e,t,r){let n=dA(e.variables,t),o=n.every((a,s)=>a===t[s]);return{x:n,score:o?r:Rr(e,n)}}function n0(e,t){if(!e.variables.some(n=>n.fixed||n.around||e0(n)))return e;let r=e.variables.filter(n=>!n.fixed).map(n=>{if(e0(n))return{...n,lo:Math.min(...n.values),hi:Math.max(...n.values)};if(!n.around)return n;let{around:o,fixed:a,...s}=n,i=t(n.id);return Number.isFinite(i)?{...s,lo:i-o.minus,hi:i+o.plus}:s});return{...e,variables:r}}var e0=e=>!!e.values?.length&&(e.lo!==Math.min(...e.values)||e.hi!==Math.max(...e.values));function Lt(e,t){if(!t.variables.some(n=>n.fixed||n.around||e0(n)))return t;let r=$t(e);return n0(t,n=>{let o=r[n];if(!o)return NaN;try{return o.read(e)}catch{return NaN}})}function lo(e){return[...e.objectives,...e.constraints,...e.watches??[]]}var o0=e=>(e.metrics??$r()).byId;function a0(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:Pt(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 Hm(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]))}),o}function ac(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 hA=(e,t="")=>t&&t!=="-"?`${e} ${t}`:`${e}`;function bA(e,t,r){let n=t??Ea[e.metricId],o=(n?xt(n):e.metricId)+sc(e.at,n,r),a=s=>hA(s,n?.unit);return e.op==="max"?`${o} \u2264 ${a(e.limit)}`:e.op==="min"?`${o} \u2265 ${a(e.limit)}`:`${o} between ${e.limit} and ${a(e.limit2??e.limit)}`}function sc(e,t,r){if(!e)return"";let n=[];if(e.speed!==void 0&&Ng(t)&&n.push(`${(e.speed*3.6).toFixed(0)} km/h`),e.ayG!==void 0&&Og(t)&&n.push(`${e.ayG.toFixed(2)} g`),e.courseId==="*"&&t?.reads==="course")n.push(_g(t));else if(e.courseId&&t?.reads==="course"){let o=r?.lap.courses.find(a=>a.id===e.courseId);o&&n.push(vg(o))}return n.length?` @ ${n.join(", ")}`:""}function gA(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 yA=5e-4;function xA(e,t){return e.cost!=="lap"&&e.cost!=="session"?0:Number.isFinite(t)?yA*Math.abs(t):0}function zm(e,t,r={}){t=Lt(e,t);let n=a0(e,t),o=$t(e),a=o0(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,h)=>{let d=0,p=[];for(let{spec:f,metric:b}of m){let g=Wt(h,b,f.at);if(!Number.isFinite(g))return{ok:!1,violation:h.failure?.violation??400,reason:h.failure?.reason??`${xt(b)} could not be computed`};let y=ac(f,g);y>0&&(d+=y/b.scale,p.push(`${bA(f,b,t)} (${hA(g.toFixed(3),b.unit)})`))}return p.length===0?ks:{ok:!1,violation:d,reason:p.join("; ")}};return{name:"study",variables:n,build:m=>{let h=e;return t.variables.forEach((d,p)=>{let f=o[d.id];f&&(h=f.write(h,m[p]))}),{car:h,ev:Da(h,{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 h=u(i,m);if(!h.ok)return h;for(let{spec:d,metric:p}of c)Wt(m,p,d.at);for(let{spec:d,metric:p}of l)Wt(m,p,d.at);return m.failure?{ok:!1,violation:m.failure.violation,reason:m.failure.reason}:u(c,m)},terms:({ev:m})=>l.map(({spec:h,metric:d})=>{let p=Wt(m,d,h.at);return{name:xt(d)+sc(h.at,d,t),raw:p,unit:d.unit,weight:h.weight,contribution:gA(h,d,p),resolution:Math.abs(h.weight)*xA(d,p)/d.scale}})}}function s0(e,t,r={}){let n=t.variables.length>0&&t.variables.every(p=>p.fixed);t=Lt(e,t);let o=$t(e),a=[],s=o0(r),i=lo(t).map(p=>p.metricId),c=i.some(p=>p.startsWith("dyn.")),l=i.some(p=>p.startsWith("lap."));if(i.some(p=>p.startsWith("kin."))){let p=t.envelope;p.travelMin<0&&p.travelMax>0||a.push("The travel the linkage is read over must reach both ways from the design ride: droop below zero, bump above."),(!(p.rollMaxDeg>0)||!(p.rollAtLimitDeg>=0))&&a.push("The roll the linkage is read over must be above zero.")}if(c&&!r.assemble&&a.push("This study reads whole-car metrics, and nothing here can assemble the car to read them from."),l&&!r.simParams&&a.push("This study reads lap metrics, and nothing here can prepare the car for a lap."),l&&!t.lap.courses.length&&a.push("This study reads lap metrics and has no course to drive. Add one under \u201CWhat the car drives\u201D."),l&&t.lap.courses.some(p=>p.course.kind==="project")&&!r.projectTrack?.()&&a.push("This study laps the project\u2019s track, and the project has none. Pick a manoeuvre, or load a track."),l)for(let p of t.lap.courses)p.course.kind==="track"&&!r.libraryTrack?.(p.course.trackId)&&a.push(`This study drives ${p.course.name}, which is not in the project\u2019s tracks, or has not loaded yet.`);let u=new Set([...t.lap.courses.map(p=>p.id),"*"]);for(let p of lo(t))if(p.at?.courseId&&!u.has(p.at.courseId)){let f=s[p.metricId];a.push(`${f?xt(f):p.metricId} names a course this study no longer has. Point it at one of the courses below.`)}l&&t.lap.ggvMode==="fast"&&t.variables.some(f=>/arb_|spring|heave_|front_mass_diss|cg_height|^hp\./.test(f.id.replace("param.","")))&&a.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?a.push("Every variable is fixed \u2014 there is nothing to search."):t.variables.length===0&&a.push("No variables selected \u2014 there is nothing to search."),t.objectives.length===0&&a.push("No objective selected. Constraints alone say which designs are legal, not which is better.");for(let p of t.variables){let f=o[p.id];if(!f){a.push(`\u201C${p.id}\u201D is not a variable this car has.`);continue}if(p.values&&p.values.length<2?a.push(`${Pt(f)}: list two values or more, or fix it where it is.`):p.hi>p.lo?p.step!==void 0&&Zg({...p,start:f.read(e)})<2&&a.push(`${Pt(f)}: a step of ${p.step} ${f.unit} leaves no other place to land in its box. Make the step finer or the box wider, or fix it.`):a.push(`${Pt(f)}: the upper bound must be above the lower one (${p.lo} to ${p.hi}).`),f.supersededBy){let g=f.supersededBy.useInstead?o[f.supersededBy.useInstead]:void 0,y=g?Pt(g):void 0;a.push(`${Pt(f)} cannot be searched: ${f.supersededBy.why}.`+(y?` Use ${y} instead.`:""))}let b=f.read(e);Number.isFinite(b)&&(b<p.lo||b>p.hi)&&a.push(`${Pt(f)} starts at ${b.toFixed(1)} ${f.unit}, outside its own bounds.`)}let m=p=>{let f=/^arm\.(front|rear)\.(uca|lca)\./.exec(p);if(f)return`${f[1]}.${f[2]}`;let b=/^rocker\.(front|rear)\./.exec(p);if(b)return`${b[1]}.rocker`;let g=/^hp\.(front|rear)\.(ucaFront|ucaRear|lcaFront|lcaRear|rockerPivotA|rockerPivotB)\./.exec(p);return g?g[2].startsWith("rocker")?`${g[1]}.rocker`:`${g[1]}.${g[2].startsWith("uca")?"uca":"lca"}`:null},h=new Map;for(let p of t.variables){let f=m(p.id);if(!f)continue;let b=h.get(f);b||h.set(f,b={arms:[],coords:[]}),(/^(arm|rocker)\./.test(p.id)?b.arms:b.coords).push(p.id)}for(let[p,f]of h){if(f.arms.length===0||f.coords.length===0)continue;let b=y=>o[y]?Pt(o[y]):y,g=p.endsWith("rocker")?"rocker":`${p.endsWith("uca")?"upper":"lower"} arm`;a.push(`${p.startsWith("front")?"The front":"The rear"} ${g} is being moved two ways at once \u2014 as an axis (${f.arms.map(b).join(", ")}) and as pivot coordinates (${f.coords.map(b).join(", ")}). They describe the same ${g}, so whichever is applied second overwrites the other. Keep one.`)}for(let p of t.constraints){let f=s[p.metricId];if(!f){a.push(`\u201C${p.metricId}\u201D is not a metric.`);continue}p.op==="band"&&!((p.limit2??p.limit)>p.limit)&&a.push(`${xt(f)}: the band's upper limit must be above its lower one.`)}c&&!(t.operating.speed>0)&&a.push("Whole-car metrics need a speed to be read at; a yaw-moment diagram at rest is degenerate.");for(let p of lo(t))if(p.at?.speed!==void 0&&!(p.at.speed>0)){let f=s[p.metricId];a.push(`${f?xt(f):p.metricId} is asked for at rest, where a yaw-moment diagram is degenerate.`)}for(let p of t.watches??[])s[p.metricId]||a.push(`\u201C${p.metricId}\u201D is not a metric.`);let d=new Set;for(let p of lo(t)){let f=s[p.metricId],b=f?.unavailable?.(e);!f||!b||d.has(f.id)||(d.add(f.id),a.push(`${xt(f)} cannot be read on this car: ${b}.`))}for(let p of t.objectives)s[p.metricId]?p.weight>0?p.goal==="target"&&!Number.isFinite(p.target)?a.push(`${xt(s[p.metricId])}: \u201Chit a value\u201D needs a value.`):p.goal==="target"&&p.tolerance!==void 0&&!(p.tolerance>=0)&&a.push(`${xt(s[p.metricId])}: the tolerance must be zero or more.`):a.push(`${xt(s[p.metricId])}: weight must be positive.`):a.push(`\u201C${p.metricId}\u201D is not a metric.`);return a}var RA=.1,vA=2e3,t0=3;function i0(e,t,r={},n=vA){t=Lt(e,t);let o=zm(e,t,r),a=o0(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],h=(S,A=m)=>{let P={};for(let L of A){let D=a[L.metricId];D&&(P[`${L.metricId}@${ao(L.at)}`]=Wt(S.ev,D,L.at))}return P},d=S=>m.map(A=>S[`${A.metricId}@${ao(A.at)}`]).map(A=>Number.isFinite(A)?A.toFixed(9):"x").join("|"),p=h(l,lo(t)),f=d(p),b=[],g=[],y={},R=[],M=0;t.variables.forEach((S,A)=>{let P=s[S.id];if(!P)return;if(R.length>=t0&&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=h(I);y[P.id]=O,d(O)===f&&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<t0;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,C=[],w=lo(t).map(S=>S.metricId);if(w.some(S=>S.startsWith("dyn.trim")||S==="dyn.ymdMaxAy")){let S=l.ev.ymdLimit();S?.onGridEdge&&C.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&&C.push("The yaw-moment diagram found no trim point, so anything read off the limit is unavailable.")}if(w.some(S=>S==="dyn.steeringTorque"||S==="dyn.steeringTorqueGradient")){let S=l.ev.tyre()?.model,A=S?qr(S):null;A==="assumed"?C.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"&&C.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(w.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>=RA?C.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&&C.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:p,samples:R.length,times:R,dead:b,moves:y,unprobed:g,warnings:C,beyondFrac:w.some(S=>T.includes(S))?l.ev.lapReserve()?.beyondFrac:void 0,startFeasible:u.ok,startReason:u.reason}}var cN=[{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:lN.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 lN=["setup:m","characteristics:peak_power","characteristics:power_to_weight","characteristics:cla","characteristics:cda","characteristics:pack_energy","characteristics:maxAy","characteristics:top_speed"];var moe=new Set(cN.map(e=>e.kind));var kA={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 c0=["FL","FR","RL","RR"],Rt=(e,t,r)=>({input:e,from:r?r[0]:kA[e].from,to:r?r[1]:kA[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:Rt("roll",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"toe-rack",form:"curves",title:"Wheel angle against the rack",sweep:Rt("steer",25),wheels:["FL","FR"],y:["toe"]},{id:"camber-rack",form:"curves",title:"Camber to the road through the steer",sweep:Rt("steer",25),wheels:["FL","FR"],y:["camberRoad"]},{id:"load-roll",form:"curves",title:"Wheel loads through roll",sweep:Rt("roll",25),wheels:c0,y:["wheelLoad"]},{id:"travel-roll",form:"curves",title:"Wheel travel through roll",sweep:Rt("roll",25),wheels:c0,y:["travel"]},{id:"toe-roll",form:"curves",title:"Roll steer, all four",sweep:Rt("roll",25),wheels:c0,y:["toe"]}]},{id:"maps",name:"Travel and steer together",cards:[{id:"camber-map",form:"surface",title:"Camber over travel and rack",sweep:Rt("travel",17),second:Rt("steer",13),wheels:["FL"],y:["camber"]},{id:"bump-steer-map",form:"map",title:"Bump steer over travel and rack",sweep:Rt("travel",17),second:Rt("steer",13),wheels:["FL"],y:["bumpSteer"]},{id:"bump-steer-family",form:"curves",title:"Bump steer through travel, at five rack positions",sweep:Rt("travel",25),second:Rt("steer",5,[-20,20]),wheels:["FL"],y:["bumpSteer"]},{id:"scrub-map",form:"surface",title:"Scrub radius over travel and rack",sweep:Rt("travel",17),second:Rt("steer",13),wheels:["FL"],y:["scrubRadius"]}]}];function l0(e){let t=Number(e);return Number.isFinite(t)?Math.min(bf,Math.max(hf,t)):Mt}var SA=6e4;var cae=[{within:60*6e4,every:SA},{within:1440*6e4,every:60*6e4},{within:720*60*6e4,every:1440*6e4},{within:1/0,every:10080*6e4}];var RN=new Set(["color","visible","source","origin"]),xae=["id",...RN];var CA=.18/1.18,wA={induction:{kind:"natural"}},TA=e=>e.breathing??wA;function Ym(e){switch(e?.kind){case"sae-j1349":return Di(99e3,25);case"measured":return Di(e.hPa*100,e.tempC);default:return Di(101325,20)}}var kN=Ym(void 0);function PA(e,t){let r=Ym(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 LA(e,t){let r=e.induction;if(r.kind==="table"){let o=s=>Be(r.densityAltitudeM,r.powerPct,s),a=o(Ym(e.rated).densityAltitudeM);return a>0?Math.max(0,o(t.densityAltitudeM)/a):0}let n=e.frictionShare??CA;return Math.max(0,(PA(e,t)-n)/(1-n))}var FA=new WeakMap;function m0(e,t){let r=e.asRated??e,n=`${t.p}|${t.pDry}|${t.T}`,o=FA.get(r);o||FA.set(r,o=new Map);let a=o.get(n);if(a)return a;let s=LA(TA(r),t),i={...r,torque:r.torque.map(c=>c*s),asRated:r};return o.set(n,i),i}function FN(e){return JSON.parse(p0(d0(e,"public/laptime/index.json"),"utf8")).tracks}var CN=async e=>{let t=await fetch(e.url);if(!t.ok)throw new Error(`The track could not be read from ${pm(e)} (${t.status}).`);return new Uint8Array(await t.arrayBuffer())};function DA(e,t=new Map,r=CN){let n=FN(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(!$i(o.address))throw new Error(`"${o.address}" is not a catalogue address`);if(!Bi(o.link))throw new Error("This track is linked to a source this version does not read from.");i=await ng(await r(o.link),o.link,o.address)}else if(o.kind==="catalogue"){if(!$i(o.address))throw new Error(`"${o.address}" is not a catalogue address`);let c=JSON.parse(p0(d0(e,"public/catalogue",ag(o.address)),"utf8"));i=await ig(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(p0(d0(e,"public/laptime",c),"utf8"))}return t.set(a,i),structuredClone(i)}}var wN=9.81;function EA(e,t=e.tireModel,r=e.tireModelRear){if(!t)return e;let n=e.m.value*wN/4,o=pa(e,t,r),a=Ie(o.front).rollingRadius(n),s=o.rear===o.front?a:Ie(o.rear).rollingRadius(n),i=TN(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 TN(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 PN=1e-6;function IA(e,t,r){let n=e.cgReference;if(!n||!e.cg_height)return e;let o=I1(e,t,r);if(o===void 0||Math.abs(o-n.standingRadius)<PN)return e;let a=n.typed??e.cg_height.value;return{...e,cg_height:{...e.cg_height,value:ma(e.cg_height.value,n.standingRadius,o)},cgReference:{...n,standingRadius:o,typed:a}}}function _A(e,t,r){let n=e.rcRoad,o=e.rc_front,a=e.rc_rear;if(!n||!o||!a)return e;let s=su(e,t,r),i=Ir(o.value,n.gainFront,n.radiusFront,s.front),c=Ir(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 NA=e=>({brakeFade:e.brakeFade,airTempC:e.airTempC,diffYaw:e.diffYaw,...Ei(e.air)?{air:e.air}:{}});var uo=(e,t)=>t?e.find(r=>r.id===t)?.model:void 0;function mo(e){return{tire:t=>uo(e.tires,t),motor:t=>uo(e.motors,t),aero:t=>uo(e.aeros,t),battery:t=>uo(e.batteries,t),brake:t=>uo(e.brakes??[],t),damper:t=>uo(e.dampers??[],t),suspensionOf:t=>Dm(f0(e,t),t)}}function f0(e,t){let r=uo(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 po(e,t,r){let n={front:t.tire(e.tireModelId),rear:t.tire(e.tireModelIdRear)};return h0(C1(t.suspensionOf(e),e,n),t,r)}function LN(e){return Ei(e.air)?YM(e.air,e.airTempC??Mt):void 0}var DN="the air the session states, at its venue";function EN(e,t){return t?{...e,rho:{...e.rho,value:t.rho},readouts:{...e.readouts,rho:DN}}:e}function IN(e,t,r){if(!r)return{rho:e.rho,motorModel:t,readouts:e.readouts};let{rho:n,readouts:o}=EN(e,r);return{rho:n,motorModel:t&&ut(t)?m0(t,r):t,air:r,readouts:o}}function h0(e,t,r){let n=t.tire(e.tireModelId),o=t.tire(e.tireModelIdRear),a=_A(IA(EA(V1(_1(W1(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}=IN(a,t.motor(e.motorModelId),LN(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),...Xs(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 VN=e=>e!==!1,BN=(e,t,r)=>r&&t>0?(e%t+t)%t:Math.min(Math.max(e,0),t);function $N(e,t,r){let n=e.points.filter(o=>Number.isFinite(o.at)&&Number.isFinite(o.z)).map(o=>({...o,at:BN(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 GN(e,t,r){let n=$N(e,t,r),o=n.length;if(o===0)return[];let a=d=>d<o-1?n[d+1].at-n[d].at:r?n[0].at+t-n[d].at:1/0,s=d=>d<o-1?(n[d+1].z-n[d].z)/a(d):r&&o>1?(n[0].z-n[d].z)/a(d):0,i=n.map(d=>Math.max(0,Number.isFinite(d.curve)?d.curve:0)/2),c=(d,p,f)=>i[d]+i[p]>f?f*i[d]/(i[d]+i[p]):i[d],l=d=>d<o-1||r?c(d,d<o-1?d+1:0,a(d)):Math.max(0,t-n[d].at),u=d=>d>0?c(d,d-1,a(d-1)):r?c(d,o-1,a(o-1)):n[d].at,m=d=>d>0?s(d-1):r&&o>1?s(o-1):n[d].at<=1e-9?s(d):0,h=d=>!r&&d===o-1&&o>1&&n[d].at>=t-1e-9?s(d-1):s(d);return n.map((d,p)=>{let f=l(p),b=u(p),g=Math.min(i[p],f,b),y=!r&&g<i[p]&&(p===o-1&&g===f||p===0&&g===b);return{at:d.at,z:d.z,gIn:m(p),gOut:h(p),half:g,asked:i[p],atEnd:y}})}function KN(e,t,r,n){let o=t-e.at;return n&&r>0?o-r*Math.round(o/r):o}function HN(e,t,r,n){for(let s of e){let i=KN(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 OA(e,t,r,n){let o=VN(n),a=GN(e,r,o);return a.length?t.map(s=>HN(a,s,r,o)):t.map(()=>0)}function ic(e,t){if(!t?.points.length)return e;let r=Yi(e),{zSmoothing:n,...o}=e;return{...o,z:OA(t,r,gg(e),e.closed)}}var Wm={widthLeft:1.5,widthRight:1.5,bank:0,mu:1};function VA(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 cc(e,t){let r=VA(e.source);return BA(e,r?await t(r):void 0)}function BA(e,t){let{source:r}=e;if(r.kind==="segments"){let{segments:i,closed:c,spacing:l}=r,{asset:u}=ji(i,{name:e.name,closed:c,spacing:l,base:Wm});return ic(u,r.profile)}let n=r.sections??[];if(r.kind==="inline")return ic(ym(r.asset,n,Wm),r.profile);if(!t)throw new Error(`Track "${e.name}" has to be loaded before it can be resolved.`);let{widthLeft:o,widthRight:a,closed:s}=r;return ic(ym({...t,...o!==void 0?{widthLeft:o}:{},...a!==void 0?{widthRight:a}:{},...s!==void 0?{closed:s}:{}},n,Wm),r.profile)}var Uie=1/500;var Xie=5*Math.PI/180;var oce=1/3;var jN=[4,2,1,.5,.25,.125];function $A(e,t,r={}){let n=[...r.steps??jN].sort((g,y)=>y-g),o=at(r.numerics),a=r.tolPct??.5,s=At(e),i=e.ggvMode??"twoTrack",c=ir(s,!1,i),l={...o,dsTarget:n[0]??o.dsTarget},u=n.length?Wn(s,c,[gt(t,l)],l,i):void 0,m=cn(s,c.rows),h=n.map((g,y)=>{let R={...o,dsTarget:g},M=Date.now(),v=gt(t,R),x=bt(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}}),d=h[h.length-1]?.lapTime??NaN,p=h.map(g=>{let y=g.lapTime-d;return{...g,delta:y,deltaPct:d?100*y/d:NaN}}),f=p.filter(g=>Math.abs(g.deltaPct)<=a),b=f.length?Math.max(...f.map(g=>g.dsTarget)):null;return{points:p,reference:d,recommended:b,tolPct:a}}function Na(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:l0(t.airTempC??r.airTempC),...Ei(nm(t.air??r.air))?{air:nm(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 jm(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 cc(r,t)}}function qN(e,t){let r=structuredClone(e);for(let[n,o]of Object.entries(t))if(!du(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 b0=(e,t)=>{let r=e?.name;return typeof r=="string"&&r?r:t};function QN(e,t){let r={};for(let n of mn){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:b0(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:b0(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:b0(i.model,i.id),byFallback:!0}:null;continue}r[n.doc]=null}return r}function ZN(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 GA(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 KA=e=>e.length<2?e[0]??"":`${e.slice(0,-1).join(", ")} and ${e[e.length-1]}`;async function Um(e,t,r={}){let n=Na(e,r.settings),{entry:o,asset:a}=await jm(e,t),s=mo(e),i=r.vehicleIds?.length?r.vehicleIds.map(p=>{let f=e.vehicles.find(b=>b.id===p);if(!f)throw new Error(`this project holds no vehicle "${p}"`);return f}):e.vehicles.filter(p=>p.visible);if(!i.length)throw new Error("no vehicle is visible in this project \u2014 name some in vehicleIds");let c=i.map(p=>{let f=r.overrides?.[p.id]?qN(p.params,r.overrides[p.id]):p.params;return po(structuredClone(f),s,n)}),l=Fi(Qn(e.meta.rulesetId,e.rulesets)),u=Li(c,a,n.numerics,l,{racingLine:n.racingLine,standingStart:n.standingStart,lapCounts:n.lapCounts}),m={};i.forEach((p,f)=>{m[p.id]=u[f]});let{scores:h,field:d}=Ib(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:h!==null,vehicles:i.map((p,f)=>({id:p.id,name:u[f].name||String(p.params.name??p.id),events:ZN(u[f]),metrics:_b(l,u[f],d?.[p.id]),fitted:QN(e,p.params),...h?.[p.id]?{score:{total:h[p.id].total,parts:{...h[p.id].parts}}}:{}})),raw:{results:m,scores:h,field:d}}}async function HA(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=Na(e),{asset:a}=await jm(e,t),s=po(structuredClone(n.params),mo(e),o);return $A(s,a,{...r.steps?{steps:r.steps}:{},numerics:o.numerics,...r.tolPct!==void 0?{tolPct:r.tolPct}:{},...r.onStep?{onStep:r.onStep}:{}})}var JN=(e,t)=>e[t]??[],eO=(e,t,r)=>r<=1?[e]:Array.from({length:r},(n,o)=>e+(t-e)*o/(r-1));function Xm(e){return e.kind==="param"?eO(e.start,e.end,Math.max(1,Math.round(e.steps))):e.kind==="part"?[...e.partIds]:[...e.values]}var zA=e=>e.kind==="param"?e.label:e.kind==="part"?`${e.part} model`:e.setting;function tO(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=po(structuredClone(r.params),mo(e),Na(e)),o=z1(n,{geometry:!0}),a=pu(n);for(let i of t.axes){if(i.kind==="param"){let c=a.find(u=>u.label===i.label);if(!c)throw new Error(`no parameter is labelled "${i.label}" on this car \u2014 read vehicle_get for the labels it has`);let l=o[c.key];if(l)throw new Error(`"${i.label}" is a readout on this car, not an input: ${l}. Sweeping it would report exactly zero. Sweep what produces it instead.`)}if(i.kind==="part"){let c=mn.find(l=>l.doc===i.part);if(!c)throw new Error(`"${i.part}" is not a library \u2014 it is one of ${mn.map(l=>l.doc).join(", ")}`);for(let l of i.partIds)if(!JN(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*Xm(c).length,1);if(s>Ju)throw new Error(`that grid is ${s} runs, over the ${Ju} cap \u2014 a run is a whole session. Drop an axis or use fewer steps.`)}var rO=e=>e.map(t=>String(typeof t=="number"?Number(t.toPrecision(4)):t)).join(" \xD7 ");function nO(e,t){let r=[...new Set(e.flatMap(o=>(o.didNotFinish??[]).map(a=>a.label)))],n=e.map(o=>({name:rO(o.at),events:r.map(a=>({label:a,incomplete:o.didNotFinish?.find(s=>s.label===a)}))}));return GA(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`:KA(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 oO(e){let t=[[]];for(let r of e){let n=Xm(r),o=[];for(let a of n)for(let s of t)o.push([...s,a]);t=o}return t}async function YA(e,t,r,n){tO(e,r);let o=oO(r.axes),a=[],s=!1;for(let[u,m]of o.entries()){let h=structuredClone(e),d=h.vehicles.find(M=>M.id===r.vehicleId),p={...r.settings},f={};r.axes.forEach((M,v)=>{let x=m[v];if(M.kind==="param")f[M.label]=x;else if(M.kind==="part"){let k=mn.find(F=>F.doc===M.part);d.params[k.ref]=x}else p[M.setting]=x});let b=r.fleet?h.vehicles.filter(M=>M.visible||M.id===r.vehicleId).map(M=>M.id):[r.vehicleId],g=await Um(h,t,{vehicleIds:b,settings:p,...Object.keys(f).length?{overrides:{[r.vehicleId]:f}}:{}});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(Xm(u).length<2)return;i.some(d=>{if(new Set(a.map(b=>`${b.at[m]}`)).size<2)return!1;let f=a.map(b=>b.metrics[d]).filter(Number.isFinite);return Math.max(...f)-Math.min(...f)>1e-9})||c.push(zA(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(...nO(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:zA(u),values:Xm(u)})),runs:a,metricKeys:i,fleetScored:s,flat:c,caveats:l}}var uue=Math.PI/180;function g0(e){if(!e.chassis)return e;let{chassis:t,...r}=e;return r}var Ide=180/Math.PI;var jO={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 she=jO.id;var lc=.02;function oF(e){let t=Math.max(lc,Math.abs(e.heaveMotionRatio)),r=Math.max(lc,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 XO=(e,t)=>({od:t,id:Math.min(e.id,t-.5)}),qO=(e,t)=>e/(2*t*t);function nF(e,t){switch(e.kind){case"ubar":case"blade":case"torsionTube":return{...e,section:XO(e.section,t)};default:return e}}function aF(e,t,r){let n=Math.max(lc,Math.abs(r));if(e?.kind==="coil"){let l=qO(t,n),u=e.rate;if(typeof u=="number")return{...e,rate:l};let m=Dr(u,0);if(!(m>0))return{...e,rate:l};let h=l/m;return{...e,rate:{...u,y:u.y.map(d=>d*h)}}}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=>Js(nF(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 nF(a,c)}function sF(e,t,r,n){let o=e?.design,a=aF(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 QO=Math.PI/180,qm=1e-6;function ZO(e){return!(ve(e.rockerPivotA,e.rockerPivotB)<qm||ve(e.rockerToPushrod,e.rockerPivotA)<qm||ve(e.rockerToDamper,e.rockerPivotA)<qm||ve(e.rockerToDamper,e.damperChassis)<qm)}function uF(e){if(!ZO(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 mF(e){if(e.config.actuation!=="direct"||uF(e))return;let{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}=e5(e);return{rockerPivotA:t,rockerPivotB:r,rockerToPushrod:n,rockerToDamper:o}}var iF=40;function Qm(e,t={}){let r=e.hardpoints,n=r.pushrodOuter,o=r.damperChassis,a=ve(n,o),s=ee(n,U(H(o,n),JO)),i=t.armRod??Math.max(25,.15*a),c=t.armDamper??i,l=[s[0]-iF,s[1],s[2]],u=[s[0]+iF,s[1],s[2]],m=q(H(u,l)),h=H(n,s),d=q(H(h,U(m,cF(h,m)))),p=Et(d,m,(t.armAngleDeg??60)*QO),f=ee(s,U(p,i)),b=H(o,s),g=q(H(b,U(m,cF(b,m)))),y=U(q(ae(m,g)),t.damperSide??1),R=ee(s,U(y,c));return{...r,rockerPivotA:l,rockerPivotB:u,rockerToPushrod:f,rockerToDamper:R}}var JO=.72,cF=(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2];function lF(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 e5(e,t={}){let r=t.target??lF(e),n=t.armAngleDeg,o=Qm(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 d of[1,-1]){let p=Qm(e,{armRod:s,armAngleDeg:n,damperSide:d}),f={...e,config:{...e.config,actuation:"rocker"},hardpoints:p};try{let b=et(f),g=ge(b,15,0),y=ge(b,-15,0);if(g.ok&&y.ok&&g.state.metrics.damperLength<y.state.metrics.damperLength)return d}catch{}}return 1})(),c=(d,p)=>{try{return lF({...e,config:{...e.config,actuation:"rocker"},hardpoints:Qm(e,{armRod:d,armAngleDeg:n,armDamper:p,damperSide:i})})}catch{return Number.NaN}},l=[1,.6,.35,.2,1.7,2.6].map(d=>Math.max(12,s*d)),u=s,m=s,h=1/0;for(let d of l){let p=.25*d,f=6*d,b=d;for(let y=0;y<24;y++){let R=(p+f)/2,M=c(d,R);if(!Number.isFinite(M))break;b=R,M<r?p=R:f=R}let g=Math.abs(c(d,b)-r);if(Number.isFinite(g)&&g<h&&(h=g,u=d,m=b),h<1e-4*Math.max(1,r))break}return Qm(e,{armRod:u,armAngleDeg:n,armDamper:m,damperSide:i})}var Rhe=Array.from({length:19},(e,t)=>-45+5*t);var vhe=Math.PI/180;function t5(e){let t=e.hardpoints,r=q(H(t.rockerPivotB,t.rockerPivotA)),n=Wr(t.rockerToDamper,t.rockerPivotA,r),o=.6*Yr(H(t.rockerToDamper,n)),a=ae(r,vy),s=Yr(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 r5=(e,t)=>({...e,config:{...e.config,actuation:t}});function R0(e,t,r,n){let o=r==="front"?e.front:e.rear,a=ru(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=Bn(e,t)[r]??Z(t,r==="front"?"arb_front":"arb_rear"),u=ua(e,t)[r]??Z(t,r==="front"?"heave_spring_front":"heave_spring_rear"),m=mF(o),h=r5(m?{...o,hardpoints:{...o.hardpoints,...m}}:o,"decoupled"),d=r==="front"?t.heaveFrontDesign:t.heaveRearDesign,p=n?.heave??pF(d?.linkage,C=>vn(h,C).atDesign)??dd(h,"rockerToRocker"),f=!c||c.design.kind==="none"||c.design.kind==="coil",b=f?"coil":"ubar",g=c?.linkage&&(c.design.kind==="none"||c.linkage.attach!=="rocker")?c.linkage:void 0,y=n?.roll??pF(f?g:c?.linkage,C=>No(h,C,{kind:b}).atDesign)??(f?t5(h):l1(h)),R=vn(h,p).atDesign,M=No(h,y,{kind:b}).atDesign,v=ou(e,t),x=oF({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=sF({design:d?.design??{kind:"none"},linkage:p,damper:d?.damper},k,x,M);return m?{...F,crank:m}:F}function pF(e,t){return e&&Math.abs(t(e))>=lc?e:void 0}var Zm=[{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"]}],v0=()=>({arbFront:void 0,arbRear:void 0,heaveFront:void 0,heaveRear:void 0}),n5={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]}},o5={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]}},a5=()=>({outer:[0,189,486],attach:"rocker",mount:{kind:"chassis",anchor:[-225,0,486]}}),s5={rate:60,motionRatio:1},i5={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]}},c5=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]}},l5={kind:"coil",rate:1560,motionRatio:1,gap:0,bothWays:!0},u5=40,m5={rockerPivotA:[50,130,440],rockerPivotB:[-50,130,440],rockerToPushrod:[10,170,460],rockerToDamper:[-20,64,440],damperChassis:[-20,64,215]},dF=()=>({outer:[-50,130,480],attach:"rocker",shaftStation:-50}),fF=()=>({outer:[50,130,400],inner:[50,130,480],attach:"rocker",shaftStationOuter:50,shaftStationInner:50}),p5=e=>[e[0],e[1],e[2]];function d5(e){let t=r=>({...r,hardpoints:{...r.hardpoints,...bF(m5)},config:{...r.config,actuation:"decoupled"}});return{...e,front:t(e.front),rear:t(e.rear)}}function bF(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,p5(r)]))}function gF(e,t=ro(),r=e==="pull"?o5:n5){let n=(o,a)=>({...o,hardpoints:{...o.hardpoints,...bF(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 Jm(e,t){let r=k0(e),n=Oa(e);if(e==="heave")return{meta:r,vehicle:n,components:{...v0(),heaveFront:{design:{...wh,...s5},linkage:a5()}}};if(e!=="decoupled")return{meta:r,vehicle:n,components:v0()};let o=R0(n,t,"front",{heave:dF(),roll:fF()}),a=R0(n,t,"rear",{heave:dF(),roll:fF()});return{meta:r,vehicle:n,components:{arbFront:o.arb,arbRear:a.arb,heaveFront:o.heave,heaveRear:a.heave}}}function Oa(e){let{name:t}=k0(e);if(e==="direct")return{..._i(),name:t};if(e==="mcpherson"){let n=Ni(),o=am();return{...n,front:{...o,config:{...o.config,loadedRadius:n.front.config.loadedRadius}},name:t}}let r=f5(gF(e==="pullrod"?"pull":"push"));return{...e==="decoupled"?d5(r):r,name:t}}var hF={front:221.7,rear:220.9};function f5(e){return{...e,front:{...e.front,config:{...e.front.config,loadedRadius:hF.front}},rear:{...e.rear,config:{...e.rear.config,loadedRadius:hF.rear}}}}function k0(e){let t=Zm.find(r=>r.id===e);if(!t)throw new Error(`Unknown suspension template: ${e}`);return t}function ep(){let e=t=>({design:{...l5},linkage:c5(t),damper:u5});return{meta:k0("heave"),vehicle:gF("push",Kb(),i5),components:{...v0(),heaveFront:e("front"),heaveRear:e("rear")}}}var yF=[10,25,50,100,200,300],h5=[{id:"c1",label:"Soft",scale:.7},{id:"c2",label:"Medium",scale:1},{id:"c3",label:"Firm",scale:1.4}],xF=e=>Math.round(e*100)/100;function b5(e,t,r){let n=yF.map(o=>xF(r*o));return{id:e,label:t,speedMmS:[...yF],bumpN:n,reboundN:[...n]}}function g5(e){return{name:e.name,body:{...e.body},curves:h5.map(t=>b5(t.id,t.label,xF(e.coefficient*t.scale)))}}function uc(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 pr(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:Ki[e.dampers.length%Ki.length],model:g5(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 st=e=>`${e} (typical)`,M0={car:{name:st("Formula Student damper"),coefficient:2.5,body:{extended:249,stroke:55}}},tp={car:M0.car,heave:{name:st("Formula Student heave damper"),coefficient:3.4,body:{extended:270,stroke:47}},roll:{name:st("Formula Student roll damper"),coefficient:3.7,body:{extended:322,stroke:100}}},rp={car:{name:st("Formula 1 damper"),coefficient:6,body:{extended:240,stroke:40}},heave:{name:st("Formula 1 heave damper"),coefficient:40,body:{extended:240,stroke:40}}},RF={car:{name:st("GT damper"),coefficient:4.5,body:{extended:510,stroke:80}}},S0={car:{name:st("Sports car damper"),coefficient:2.4,body:{extended:515,stroke:110}}},vF={car:{name:st("Sports car strut"),coefficient:2.4,body:{extended:310,stroke:120}},rear:S0.car},kF={car:{name:st("Cup car strut"),coefficient:4,body:{extended:285,stroke:75}},rear:{name:st("Cup car rear damper"),coefficient:3.5,body:{extended:505,stroke:80}}},MF={car:{name:st("Stock car front damper"),coefficient:7.5,body:{extended:555,stroke:110}},rear:{name:st("Stock car rear damper"),coefficient:6.75,body:{extended:555,stroke:110}}},SF={car:{name:st("Hill-climb front damper"),coefficient:3,body:{extended:285,stroke:65}},rear:{name:st("Hill-climb rear damper"),coefficient:3.5,body:{extended:285,stroke:65}}},AF={car:{name:st("Race truck front damper"),coefficient:12,body:{extended:780,stroke:160}},rear:{name:st("Race truck rear damper"),coefficient:8.5,body:{extended:780,stroke:160}}};function Ba(e){return e.vehicles=e.vehicles.slice(0,1),e.activeVehicleId=e.vehicles[0]?.id??null,e}function hn(e,t){let r=Hi(e);return r.meta.rulesetId=t,r}function fo(e,t,r,n){let o=hn(e,t);return o.suspensions=[{...o.suspensions[0],model:n()}],o.vehicles=[fg(r,"v1",0)],o.activeVehicleId="v1",o}var[,y5,x5,R5,v5,k5,M5,S5]=qb;function A0(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 FF(){return{...Oa("decoupled"),name:ro().name}}var A5=[{label:"Formula Student (decoupled)",vehicle:FF,components:e=>uc(Jm("decoupled",e).components,tp)},{label:"Formula 1 (third springs)",vehicle:()=>ep().vehicle,components:()=>uc(ep().components,rp)}],F0={"direct-coilover":"direct",pushrod:"pushrod",pullrod:"pullrod","third-spring":"heave","mcpherson-strut":"mcpherson"},F5=[...A5.map(e=>e.vehicle),...Object.values(F0).map(e=>()=>Oa(e))];function Va(e){let t=uc(Jm("decoupled",e.vehicles[0].params).components,tp);e.suspensions=[{...e.suspensions[0],model:FF()}];for(let r of e.vehicles)A0(r.params,t);return pr(e,tp),e}var ho={title:"OpenStreetMap",url:"https://www.openstreetmap.org/copyright",licence:"ODbL-1.0",credit:"\xA9 OpenStreetMap contributors"},np={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"},CF={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]"},wF={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"},C5={id:"cota",name:"Circuit of the Americas, Austin",address:"e0c6ea889d708cf15f9c",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ho,np,wF]}},w5={id:"laguna-seca",name:"Laguna Seca, Monterey",address:"185b5811b9c423ef44ef",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ho,np,wF]}},T5={id:"nordschleife",name:"Nordschleife, N\xFCrburg",address:"74c49603c7b2f15985c6",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ho,CF]}},P5={id:"brands-hatch",name:"Brands Hatch, Kent",address:"c4953e3c25eaba4a5b7e",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ho,{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."}]}},L5={id:"bristol",name:"Bristol, Tennessee",address:"f0e23953669a414ad600",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ho,np]}},D5={id:"pikes-peak",name:"Pikes Peak, Colorado",address:"3de137fe33b5c2875036",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ho,np]},standingStart:!0},E5={source:"venue",altitudeM:3580,pressure:{kind:"standard"},humidityPct:0},I5=10,_5={id:"nurburg-sprint",name:"Sprintstrecke, N\xFCrburg",address:"1875636cdbb615aa2756",provenance:{fidelity:"derived",licence:"ODbL-1.0",sources:[ho,CF]}};function bo(e,t){let{id:r,name:n,address:o,provenance:a,standingStart:s}=t,i={kind:"catalogue",id:r,address:o},c=Oi(sg({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 bn(e,t,r){let n=e.vehicles[0].params,o=`m${e.motors.length+1}`;e.motors=[...e.motors,{id:o,color:pn[e.motors.length%pn.length],model:t}];let a=L1({},{...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,op={hubPlanetary:14.5,inboardChain:4,engineChain:3.4},O5="Hub motor, 35 kW (example)";function C0(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 TF(e){let t=e.motors.find(r=>r.id==="m1");return t.model={...t.model,name:O5},t.id}function ap(e,t,r){let n=Ba(Va(hn(e,r)));return n.vehicles[0].params.name=t,n}function V5(){let e=ap("Formula Student combustion car","Formula Student combustion","fs-cv");bn(e,tg(),op.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 B5(){let e=ap("Formula Student AWD car","Formula Student AWD","fs-ev");return C0(e,TF(e),4,"awd",op.hubPlanetary,"hub"),e}function $5(){let e=ap("Formula Student RWD hub-motor car","Formula Student RWD hub motors","fs-ev");return C0(e,TF(e),2,"rear",op.hubPlanetary,"hub"),e}function G5(){let e=ap("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:pn[e.motors.length%pn.length],model:eg()}],C0(e,t,1,"rear",op.inboardChain),e.vehicles[0].params.driveline={rear:structuredClone(ht.clutch)},e}function K5(){let e=Ba(Va(hn("Formula Student endurance energy","fs-ev"))),t=e.vehicles[0],r=structuredClone(t);if(r.id="v2",r.color=Gi[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 H5(){let e=ep(),t=fo("Formula 1 car","trackday",y5,()=>e.vehicle);return A0(t.vehicles[0].params,uc(e.components,rp)),pr(t,rp),bn(t,rg(),N5),bo(t,C5)}function PF(e="GT car",t=_i){let r=fo(e,"trackday",x5,t);return pr(r,RF),bn(r,aS(),r.vehicles[0].params.gear_ratio.value),bo(r,w5)}function LF(e="Sports car",t=Ni,r=S0){let n=fo(e,"trackday",R5,t);return pr(n,r),bn(n,sS(),n.vehicles[0].params.gear_ratio.value),bo(n,T5)}function z5(){let e=fo("Cup car","trackday",v5,jM);return pr(e,kF),bn(e,iS(),e.vehicles[0].params.gear_ratio.value),bo(e,P5)}function Y5(){let e=fo("Stock car","trackday",k5,UM);return pr(e,MF),bn(e,cS(),e.vehicles[0].params.gear_ratio.value),bo(e,L5)}function W5(){let e=fo("Hill-climb prototype","trackday",M5,XM);return pr(e,SF),bn(e,lS(),e.vehicles[0].params.gear_ratio.value),e.settings.air=structuredClone(E5),e.settings.airTempC=I5,bo(e,D5)}function j5(){let e=fo("Race truck","trackday",S5,qM);return pr(e,AF),bn(e,uS(),e.vehicles[0].params.gear_ratio.value),bo(e,_5)}function U5(e){let t=Zm.find(o=>o.id===e);if(e==="direct")return PF(t.name,()=>Oa(e));if(e==="mcpherson")return LF(t.name,()=>Oa(e),vF);let r=Ba(hn(t.name,"trackday")),n=Jm(e,r.vehicles[0].params);return r.suspensions=[{...r.suspensions[0],model:n.vehicle}],A0(r.vehicles[0].params,n.components),pr(r,M0),r}function mc(e,t,r){let n=F0[e],o=Zm.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:()=>U5(n)}}var X5=[{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:()=>Va(hn("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:K5},{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:()=>Ba(Va(hn("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:V5},{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:B5},{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:$5},{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:G5},{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:H5},{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:PF},{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:LF},{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:z5},{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:Y5},{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:W5},{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:j5},{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:()=>Ba(Va(hn("Suspension study","trackday")))},mc("direct-coilover","The GT car\u2019s wishbones driving coilovers straight into the towers, at Laguna Seca.","On the GT car, at Laguna Seca."),mc("pushrod","The FS car on pushrods: a rod from each lower wishbone works a rocker.","On the Formula Student car, at FSG."),mc("pullrod","The FS car on pullrods: a rod from each upper wishbone pulls a low rocker.","On the Formula Student car, at FSG."),mc("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."),mc("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:()=>Ba(Va(hn("Tyre study","fs-ev")))}],DF=X5.map(e=>({...e,load:()=>hg(e.load())}));var EF={width:320,height:200},abe=[.6*EF.width-9,.6*EF.height-9];var IF=new WeakMap,_F=new WeakMap,w0=e=>JSON.stringify(e,(t,r)=>r===1/0?"Infinity":r);function NF(e,t){if(!t){let a=IF.get(e);return a||(a=Ct(e),IF.set(e,a)),a}let r=_F.get(e);r||(r=new Map,_F.set(e,r));let n=w0(t),o=r.get(n);return o||(r.size>=4&&r.clear(),o=Ct(e,t),r.set(n,o)),o}var Z5=Math.PI/180,J5=e=>e>1?e/100:e;function pc(e){let t=null;return()=>(t??={v:e()}).v}function OF(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 VF=new WeakMap,T0={heave:0,pitch:0,roll:0,steer:0},BF=[0,1,2,3,4],$F=[-20,-10,0,10,20];function KF(e,t){let r=Er(e,T0),n=["front","rear"],o=c=>{let l=ti(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 BF){let l=c===0?null:Er(e,{...T0,roll:c*Z5});n.forEach((u,m)=>{let h=l?ti(l[u]):null,d=h&&Number.isFinite(a[m]);s[m].rc.push(d?t[m]+(h.left+h.right)/2-a[m]:t[m]),s[m].split.push(d?(h.left-h.right)/2:0)})}let i=n.map(()=>[]);for(let c of $F){let l=c===0?null:Er(e,{...T0,heave:-c});n.forEach((u,m)=>{let h=l&&l[u].valid&&r[u].valid;i[m].push(h?t[m]+l[u].height-r[u].height:t[m])})}return{roll:{rollDeg:BF,rcFront:s[0].rc,rcRear:s[1].rc,rcSplitFront:s[0].split,rcSplitRear:s[1].split},heave:{drop:$F,rcFront:i[0],rcRear:i[1]}}}var GF=new WeakMap;function eV(e,t,r,n){let o=GF.get(e);o||(o=new Map,GF.set(e,o));let a=`${w0(r)}|${n[0]}|${n[1]}`,s=o.get(a);if(!s){o.size>=4&&o.clear();try{s=KF(NF(e,r),n)}catch{s=t.rigidMigration(n)}o.set(a,s)}return s}function tV(e){let t=VF.get(e);if(t)return t;let r=Ct(e),n=Er(r,{heave:0,pitch:0,roll:0,steer:0}),o=OF(e.front),a=OF(e.rear),s={wheelbase:e.config.wheelbase,trackFront:pt(e.front),trackRear:pt(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:la(n.front),rcGainRear:la(n.rear),rigidMigration:i=>KF(r,i),kinFront:pc(()=>Wo(e.front)),kinRear:pc(()=>Wo(e.rear))};return VF.set(e,s),s}function HF(e,t,r,n){let o=tV(e),a=Bn(e,t),s=ua(e,t),i=M1(e,t),c=ou(e,t),l=S1(e,t),u=F1(t),m=A1(e,t),h=Vn(e.front),d=Vn(e.rear),p=On(t.damperModel,t.damperSetup,o.mrFront,o.mrRear,t.damperModelRear??t.damperModel),f={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=J5(t.front_mass_diss.value),y=pa(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),C=M.corneringStiffness(k),w=(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=lu({freeRadius:S,staticLoad:x,tyreRate:w,surveyed:e.front.config.loadedRadius},{freeRadius:A,staticLoad:k,tyreRate:T,surveyed:e.rear.config.loadedRadius},g),L=Bt(S,x,w,e.front.config.loadedRadius),D=Bt(A,k,T,e.rear.config.loadedRadius),I=[Ir(o.rcHeightFront,o.rcGainFront,e.front.config.loadedRadius,L),Ir(o.rcHeightRear,o.rcGainRear,e.rear.config.loadedRadius,D)],G=pc(()=>si(o.kinFront(),Z(t,"camber_front_deg"))),O=pc(()=>si(o.kinRear(),Z(t,"camber_rear_deg"))),W=pc(()=>eV(e,o,La(V),I)),E=Is({...t,wheelbase:{...t.wheelbase,value:o.wheelbase}}),_=ai(t),V={massTotal:t.m.value,frontMassFrac:g,steeringSystem:t.steeringSystem,tv:Wl(t),cgHeight:ma(Z(t,"cg_height"),t.cgReference?.standingRadius,P),cgStandingRadius:P,wheelbase:o.wheelbase,trackFront:o.trackFront,trackRear:o.trackRear,wheelRateFront:h?0:o.wheelRateFront,wheelRateRear:d?0:o.wheelRateRear,decoupledFront:h,decoupledRear:d,...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&&!h?{heaveSeatFront:i.front}:{},...i.rear&&!d?{heaveSeatRear:i.rear}:{},...m.rollFront.coilover?{rollCoiloverFront:m.rollFront.coilover}:{},...m.rollRear.coilover?{rollCoiloverRear:m.rollRear.coilover}:{},tireRate:w,...T!==w?{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,w,o.unsprungCgHeight),tyreFreeRadius:S,...A!==S?{tyreFreeRadiusRear:A}:{},rcHeightFront:I[0],rcHeightRear:I[1],corneringStiffnessFront:F,corneringStiffnessRear:C,get kinFront(){return G()},get kinRear(){return O()},damperFront:h?0:p?.front?.rate??Z(t,"damper_front")*o.mrFront*o.mrFront,damperRear:d?0:p?.rear?.rate??Z(t,"damper_rear")*o.mrRear*o.mrRear,...p?.front&&!h?{damperCurveFront:p.front.curve}:{},...p?.rear&&!d?{damperCurveRear:p.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:f,yawInertia:Z(t,"I_yaw"),rollInertia:Z(t,"I_roll"),pitchInertia:Z(t,"I_pitch"),get steerFront(){return au(e.front,L)},ackermannPct:Z(t,"ackermann_pct"),toeFrontDeg:Z(t,"toe_front_deg"),toeRearDeg:Z(t,"toe_rear_deg")};return V}var YF=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}),L0={ggvMode:"twoTrack"},zF=new WeakMap;function D0(e,t=L0){let r=zF.get(e.vehicle);r||zF.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={...YF(e.params),suspensionOf:()=>e.vehicle};n.set(o,a=po(e.params,s,t))}return a}var WF=(e=L0)=>t=>D0(t,e),jF=(e=L0)=>t=>HF(t.vehicle,h0(t.params,YF(t.params),e),t.params.tireModel,t.params.tireModelRear);function rV(e,t){return D0(e,t.switches)}var E0=e=>$r(e?.rulesets);function UF(e,t,r,n,o={},a=()=>r.standingStart){let s=D0(n,r.switches),i=(l,u)=>{let m=Zu(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 XF=e=>[...new Set(e.lap.courses.flatMap(t=>t.course.kind==="track"?[t.course.trackId]:[]))],qF=e=>{let t=e?.session;return t?{sessionParams:r=>rV(r,t),session:()=>t}:{}},sp=e=>({metrics:E0(e),assemble:jF(e?.switches),simParams:WF(e?.switches),projectTrack:()=>e?.course??null,libraryTrack:t=>e?.tracks?.[t]??null,numerics:e?.numerics,...qF(e)}),nV=(e,t)=>({density:e.density,envelope:e.envelope,operating:e.operating,lap:e.lap,assemble:jF(t?.switches),simParams:WF(t?.switches),projectTrack:()=>t?.course??null,libraryTrack:r=>t?.tracks?.[r]??null,numerics:t?.numerics,...qF(t)}),QF="nelder-mead",ZF=600,dc=[0,.15,.15];function JF(e,t,r,n=dc.length){let o=N0(t);return dc.slice(0,Math.max(1,n)).map((a,s)=>({...e,seed:s+1,startJitter:a,car:o,...r?{lap:r}:{}}))}function eC(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 tC(e,t,r,n,o=.01){let a=E0(n).byId;return oV(e,t,r,n).filter(s=>s.excess>-o*(a[s.metricId]?.scale??1))}function oV(e,t,r,n){let o;try{o=Da(Hm(e,t,r),nV(t,n))}catch{return[]}return aV(o,t,E0(n))}function aV(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=`${xt(a)}${sc(o.at,a)}`;n.push({key:o.key,metricId:o.metricId,label:i,unit:a.unit==="-"?"":a.unit,value:s,excess:ac(o,s)})}return n}var sV=.05;function iV(e,t){if(t.id.startsWith("hp.")||Km(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(fn(a.hardpoints),r[2],1)}let n=/^arm\.(front|rear)\.(uca|lca)\.(\w+)$/.exec(t.id);if(!n)return null;let o=n[1]==="front"?e.vehicle.front:e.vehicle.rear;return zg(Gr(o.hardpoints,n[2]),n[3],1)}function rC(e,t,r){let n=r.filter(h=>h.score.feasible);if(n.length<2)return null;let o=t.map(h=>iV(e,h)),a=o.every(h=>h!==null)?"mm":null,s=0,i="",c=0,l=n.reduce((h,d)=>d.score.total<h.score.total?d:h);for(let h of n)if(h!==l)for(let d=0;d<t.length;d++){let p=Math.abs(h.x[d]-l.x[d])*(o[d]??1);c+=p*p,p>s&&(s=p,i=t[d].name)}let u=n.map(h=>h.score.total),m=l.score.terms.reduce((h,d)=>h+(d.resolution??0),0);return{distance:Math.sqrt(c),worst:s,worstName:i,scoreSpread:Math.max(...u)-Math.min(...u),tolerance:Math.max(sV,m),unit:a}}var cV={steeringSystem:!0,brakeSetup:!0,driveline:!0,heaveFrontDesign:!0,heaveRearDesign:!0,arbFrontDesign:!0,arbRearDesign:!0},nC=e=>Object.hasOwn(cV,e);function P0(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 lV(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":nC(t)||P0(e)?"block":null}function I0(e,t){t=Lt(e,t);let r=$t(e);return t.variables.filter(n=>r[n.id]&&!r[n.id].supersededBy&&!lV(n.id)).map(n=>Pt(r[n.id]))}function oC(e,t,r){t=Lt(e,t);let n=$t(e),o=Hm(e,t,r),a=[],s=new Set,i=new Set;for(let c of t.variables){let l=n[c.id];if(!l||l.supersededBy)continue;let u=l.read(o),[m,h,d,p]=c.id.split(".");if(m==="rocker"){let f=`${h}.rocker`;if(i.has(f))continue;i.add(f);let b=h==="front"?o.vehicle.front:o.vehicle.rear;for(let g of[io.fore,io.aft]){let y=b.hardpoints[g];for(let R=0;R<3;R++)a.push({kind:"hardpoint",axle:h,key:g,axis:R,value:y[R]})}}else if(m==="arm"){let f=`${h}.${d}`;if(i.has(f))continue;i.add(f);let b=h==="front"?o.vehicle.front:o.vehicle.rear,g=jt[d];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:h,key:y,axis:M,value:R[M]})}}else if(m==="hp")a.push({kind:"hardpoint",axle:h,key:d,axis:"xyz".indexOf(p),value:u});else if(m==="cfg")a.push({kind:"config",axle:h,field:d,value:u});else if(m==="kc"){if(s.has(`kc.${h}`))continue;s.add(`kc.${h}`);let f=h==="front"?o.vehicle.front:o.vehicle.rear;a.push({kind:"compliance",axle:h,value:f.compliance})}else if(m==="param")a.push({kind:"param",label:Pt(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(nC(m)||P0(c.id)){let f=P0(c.id)??m;if(s.has(f))continue;s.add(f);let b=o.params[f];if(!b)throw new Error(`optimiser: "${c.id}" left the car with no ${f} to adopt`);a.push({kind:"block",key:f,value:b})}else throw new Error(`optimiser: Adopt has no way to write "${c.id}" back into the project`)}return a}function _0(e){let t=performance.now(),{dead:r,unprobed:n,...o}=i0(e.car,e.spec,sp(e.lap));return{...o,deadIds:r.map(a=>a.id),unprobedIds:n.map(a=>a.id),elapsedMs:performance.now()-t}}var N0=e=>e.vehicle.chassis?{...e,vehicle:g0(e.vehicle)}:e;function aC(e,t){try{let r=O0(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:vr(r.variables),score:Rr(r,vr(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&&Qg(r.variables)?Jg(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 O0=(e,t,r)=>zm(e,t,sp(r));function sC(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),...Xs(e,t.damper)}}function iC(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 cC=e=>({ggvMode:e.ggvMode,quasiTransient:e.quasiTransient===!0&&e.ggvMode!=="fast",motorThermal:e.motorThermal===!0,...NA({brakeFade:e.brakeFade===!0,airTempC:e.airTempC,diffYaw:e.diffYaw===!0,...e.air?{air:e.air}:{}})});function uV(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 lC(e,t){let r=t.plannedPath!==void 0,n=uV(t);return{...UF(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 V0(e,t){let r=e.vehicles.find(o=>o.id===t);if(!r)throw new Error(`this project holds no vehicle "${t}"`);let n=mo(e);return iC(structuredClone(f0(e,r.params)),structuredClone(r.params),sC(r.params,n))}var mV="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 B0(e,t,r,n){if(e.settings.pathPlanId)throw new Error(mV);let o=Na(e),a=e.tracks.length?(await jm(e,t)).asset:null,s={};for(let i of n?XF(n):[]){let c=e.tracks.find(l=>l.id===i);c&&(s[i]=await cc(c,t))}return lC(r,{track:a,numerics:o.numerics,racingLine:o.racingLine,standingStart:o.standingStart,lapCounts:o.lapCounts??{},switches:cC(o),rulesets:e.rulesets??[],library:s,standingOf:i=>e.tracks.find(c=>c.id===i)?.standingStart===!0})}async function uC(e,t,r,n){let o=V0(e,r),a=Lt(o,n),s=await B0(e,t,o,a);return _0({id:0,car:o,spec:a,lap:s})}async function mC(e,t,r,n){let o=V0(e,r),a=Lt(o,n),s=I0(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 B0(e,t,o,a)}catch(l){return{problems:[l instanceof Error?l.message:String(l)]}}let c=s0(o,a,{...sp(i),metrics:$r(e.rulesets)});return c.length?{problems:c}:{problems:[],msPerEval:_0({id:0,car:o,spec:a,lap:i}).msPerEval,carFingerprint:Xn(N0(o))}}async function pV(e,t,r,n,o,a=[]){let s=JF(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 h=[],d=null,p=null;if(aC(m,y=>{y.kind==="progress"?(h.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"?d={result:y.result,elapsedMs:y.elapsedMs}:p=y.message}),p)throw new Error(p);if(!d)throw new Error("the search stopped without a result");let{result:f,elapsedMs:b}=d,g={seed:m.seed,startJitter:m.startJitter,x:f.x,score:f.score,evaluations:f.evaluations,infeasible:f.infeasible,history:f.history,trace:h,elapsedMs:b,...f.snapped?{snapped:f.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 pC(e,t,r,n){let o=V0(e,r.vehicleId),a=Lt(o,r.spec),s=I0(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 B0(e,t,o,a),c=r.method??QF;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??ZF,u=Math.max(1,Math.min(r.seeds??dc.length,dc.length)),m=await pV(o,{spec:a,method:c,budget:l},i,u,n),h=O0(o,a,i),d=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:eC(h.variables,b.x),constraints:tC(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}}:{}})),p=m.runs.reduce((b,g)=>Ms(g.score,b.score)?g:b),f=p.snapped?.score.feasible?p.snapped:null;return{method:c,budget:l,seeds:d,spread:m.runs.length>1?rC(o,h.variables,m.runs.map(b=>({x:b.x,score:b.score}))):null,writes:oC(o,a,f?f.x:p.x),...p.snapped?{adopts:f?"on its steps":`as found: on its steps it breaks a hold (${p.snapped.score.reason??"not legal"})`}:{}}}function fC(){if(typeof process.threadCpuUsage!="function")return performance.now();let e=process.threadCpuUsage();return(e.user+e.system)/1e3}async function fV(e,t){let r=DA(e.root);switch(e.kind){case"sweep":return YA(e.doc,r,e.req,t);case"convergence":return HA(e.doc,r,{vehicleId:e.vehicleId,...e.steps?{steps:e.steps}:{},...e.tolPct!==void 0?{tolPct:e.tolPct}:{},onStep:t});case"study":return pC(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 Um(e.doc,r,{...e.vehicleIds?{vehicleIds:e.vehicleIds}:{},...e.settings?{settings:e.settings}:{},...e.overrides?{overrides:e.overrides}:{}});case"probe":return uC(e.doc,r,e.vehicleId,e.spec);case"quote":return mC(e.doc,r,e.vehicleId,e.spec)}}if(dC){let e=dC,t=r=>e.postMessage(r);(async()=>{try{let r=await fV(dV,(n,o)=>t({type:"progress",done:n,total:o}));t({type:"done",result:r,cpuMs:fC()})}catch(r){t({type:"failed",message:r instanceof Error?r.message:String(r),cpuMs:fC()})}})()}export{fV as runJob,fC 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 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};