@inventure71/paddockjs 4.1.0 → 4.3.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/CHANGELOG.md +76 -0
- package/INSTALL_AND_UPDATE.md +31 -5
- package/README.md +34 -3
- package/docs/advanced_ai_pace.md +131 -0
- package/docs/advanced_physics_rebuild.md +166 -0
- package/docs/architecture.md +111 -30
- package/docs/cleanup_coverage.md +284 -0
- package/docs/component_inventory.md +32 -16
- package/docs/composable-layouts.md +2 -0
- package/docs/concepts.md +12 -1
- package/docs/custom_model_controller.md +1 -1
- package/docs/data_contract.md +33 -10
- package/docs/data_model.md +4 -2
- package/docs/efficiency_cleanup_2026-10-13.md +80 -0
- package/docs/getting-started.md +3 -0
- package/docs/grid_walk.md +80 -0
- package/docs/index.md +5 -2
- package/docs/keyboard_driving_fix.md +118 -0
- package/docs/limit_driving_2026-10-14.md +88 -0
- package/docs/loading.md +141 -0
- package/docs/maintainability_audit_2026-09-08.md +146 -0
- package/docs/racing_ai_improvements.md +145 -0
- package/docs/rules.md +43 -13
- package/docs/sense_contract.md +4 -1
- package/docs/system_specs.md +40 -12
- package/docs/testing-reliability-guide.md +67 -0
- package/docs/v11_improvements.md +108 -0
- package/package.json +23 -15
- package/src/api/MountedSimulatorComponents.js +101 -0
- package/src/api/PaddockSimulatorController.js +56 -81
- package/src/app/BrowserExpertAdapter.js +0 -6
- package/src/app/BrowserExpertExternalRenderer.js +72 -50
- package/src/app/ExternalTrackSnapshot.js +50 -0
- package/src/app/F1SimulatorApp.js +242 -297
- package/src/app/HostLifecycleEmitter.js +93 -0
- package/src/app/banners/raceDataBannerController.js +9 -4
- package/src/app/camera/cameraConstants.js +1 -1
- package/src/app/camera/cameraController.js +10 -13
- package/src/app/camera/cameraGeometry.js +1 -1
- package/src/app/controls/SimulatorViewControls.js +45 -0
- package/src/app/controls/workbenchBindings.js +64 -0
- package/src/app/controls/workbenchDisclosure.js +41 -0
- package/src/app/domBindings.js +21 -13
- package/src/app/gridWalk/GridWalkController.js +180 -0
- package/src/app/gridWalk/gridWalkCamera.js +88 -0
- package/src/app/gridWalk/gridWalkControls.js +24 -0
- package/src/app/gridWalk/gridWalkCrew.js +246 -0
- package/src/app/gridWalk/gridWalkLabels.js +104 -0
- package/src/app/gridWalk/gridWalkLayout.js +46 -0
- package/src/app/gridWalk/gridWalkNavigation.js +99 -0
- package/src/app/gridWalk/gridWalkProjectBanner.js +43 -0
- package/src/app/gridWalk/gridWalkSession.js +50 -0
- package/src/app/layoutSupport.js +2 -0
- package/src/app/raceOverlayClearanceSupport.js +21 -7
- package/src/app/readouts/carOverviewRenderer.js +9 -4
- package/src/app/readouts/readoutFormatters.js +1 -8
- package/src/app/readouts/telemetryRenderer.js +1 -3
- package/src/app/readouts/timingTowerRenderer.js +48 -50
- package/src/app/rendering/appAssets.js +8 -10
- package/src/app/rendering/carRenderer.js +27 -79
- package/src/app/rendering/displayUtils.js +0 -6
- package/src/app/rendering/expertSensorRenderer.js +1 -1
- package/src/app/rendering/replayGhostRenderer.js +4 -1
- package/src/app/rendering/trackRenderer.js +2 -2
- package/src/app/runtime/frameLoop.js +18 -17
- package/src/app/runtime/pixiStartupLifecycle.js +94 -0
- package/src/app/runtime/runtimeTiming.js +4 -1
- package/src/app/runtime/runtimeVisibility.js +7 -2
- package/src/config/cssValues.js +1 -1
- package/src/config/defaultOptions.js +12 -173
- package/src/config/restartOptions.js +1 -0
- package/src/config/runtimeSeed.js +10 -0
- package/src/config/simulatorDefaults.js +106 -0
- package/src/config/telemetryModules.js +20 -0
- package/src/config/theme/cssTokens.js +85 -0
- package/src/config/theme/themeCss.js +72 -0
- package/src/config/theme/themeInputs.js +155 -0
- package/src/config/theme/themeResolver.js +172 -0
- package/src/config/theme/themeSelectors.js +69 -0
- package/src/config/theme/themeTokens.js +257 -0
- package/src/config/theme/themeUtils.js +15 -0
- package/src/config/themeOptions.js +14 -830
- package/src/config/timingGapMode.js +0 -2
- package/src/config/uiOptions.js +53 -0
- package/src/data/championship.js +16 -158
- package/src/data/championshipDefaults.js +87 -0
- package/src/data/driverData.js +10 -20
- package/src/data/entryIdentity.js +67 -0
- package/src/data/entryPresentation.js +23 -0
- package/src/data/entryTypes.d.ts +160 -0
- package/src/data/index.d.ts +12 -195
- package/src/data/ratingScale.js +14 -0
- package/src/data/teamTypes.d.ts +23 -0
- package/src/data/trackTypes.d.ts +101 -0
- package/src/data/vehicleData.js +12 -23
- package/src/environment/actions.js +3 -2
- package/src/environment/controllerLoop.js +57 -44
- package/src/environment/controllerScheduler.js +30 -0
- package/src/environment/driverObservations.js +260 -0
- package/src/environment/driverReset.js +51 -0
- package/src/environment/episode.js +0 -1
- package/src/environment/evaluation.js +6 -90
- package/src/environment/evaluationTracker.js +100 -0
- package/src/environment/events.js +23 -0
- package/src/environment/index.d.ts +35 -91
- package/src/environment/metrics.js +3 -17
- package/src/environment/observationSchema.js +104 -0
- package/src/environment/observationVector.js +16 -115
- package/src/environment/observations.js +16 -316
- package/src/environment/options.js +5 -24
- package/src/environment/renderFrames.js +21 -0
- package/src/environment/resetOptions.js +41 -0
- package/src/environment/results.js +125 -0
- package/src/environment/rewards.js +10 -16
- package/src/environment/runtime.js +17 -300
- package/src/environment/scenarioOptions.js +90 -0
- package/src/environment/scenarioPlacements.js +70 -0
- package/src/environment/scenarioPresets.js +78 -0
- package/src/environment/scenarios.js +5 -236
- package/src/environment/scratch.js +18 -0
- package/src/environment/sensorOptions.js +20 -0
- package/src/environment/sensors/index.js +2 -556
- package/src/environment/sensors/indexedRayBands.js +0 -18
- package/src/environment/sensors/nearbyCars.js +18 -15
- package/src/environment/sensors/opponentRadar.js +3 -2
- package/src/environment/sensors/pitConnectorProximity.js +20 -0
- package/src/environment/sensors/rayBandTrace.js +1 -37
- package/src/environment/sensors/rayBatch.js +81 -0
- package/src/environment/sensors/rayConfig.js +26 -0
- package/src/environment/sensors/rayGeometry.js +0 -8
- package/src/environment/sensors/rayGuards.js +0 -6
- package/src/environment/sensors/rayOutputs.js +75 -0
- package/src/environment/sensors/rayQuery.js +110 -0
- package/src/environment/sensors/rayScratch.js +146 -0
- package/src/environment/sensors/sensorTargets.js +12 -4
- package/src/environment/sensors/surfaceRays.js +6 -61
- package/src/environment/sensors/trackRays.js +7 -80
- package/src/environment/simulationSetup.js +30 -0
- package/src/environment/specs.js +15 -109
- package/src/index.d.ts +43 -202
- package/src/index.js +28 -6
- package/src/placeholder/index.js +1 -8
- package/src/rendering/displayLifecycle.js +6 -0
- package/src/rendering/proceduralTrackAsset.js +1 -1
- package/src/rendering/renderSnapshot.js +3 -0
- package/src/rendering/track/finishLineRenderer.js +1 -1
- package/src/rendering/track/gridRenderer.js +1 -1
- package/src/rendering/track/offsetStrokeSafety.js +2 -2
- package/src/rendering/track/pitLaneRenderer.js +1 -1
- package/src/rendering/track/trackMaterialRenderer.js +4 -4
- package/src/rendering/track/trackRenderConstants.js +0 -1
- package/src/rendering/track/trackRenderGeometry.js +1 -7
- package/src/simulation/collisionGeometry.js +12 -20
- package/src/simulation/driver/advancedPathControls.js +53 -0
- package/src/simulation/driver/advancedRacePace.js +112 -0
- package/src/simulation/driver/advancedRacingControls.js +61 -0
- package/src/simulation/driver/advancedRacingEnvelope.js +255 -0
- package/src/simulation/driver/advancedRacingSteering.js +76 -0
- package/src/simulation/driver/advancedRacingTiming.js +16 -0
- package/src/simulation/driver/arcadeRacePace.js +83 -0
- package/src/simulation/driver/arcadeRacingControls.js +111 -0
- package/src/simulation/driver/arcadeRacingEnvelope.js +63 -0
- package/src/simulation/driver/driverControlConstants.js +0 -2
- package/src/simulation/driver/driverController.js +16 -5
- package/src/simulation/driver/edgeRecovery.js +2 -3
- package/src/simulation/driver/racingControls.js +10 -396
- package/src/simulation/driver/racingDriverProfile.js +48 -0
- package/src/simulation/driver/racingLinePlan.js +54 -20
- package/src/simulation/driver/rejoinControls.js +59 -112
- package/src/simulation/driver/safetyCarControls.js +12 -0
- package/src/simulation/driver/trafficScan.js +136 -27
- package/src/simulation/participants/participantInteractions.js +24 -15
- package/src/simulation/pit/pitCarPlacement.js +29 -0
- package/src/simulation/pit/pitFlow.js +8 -30
- package/src/simulation/pit/pitIntent.js +4 -3
- package/src/simulation/pit/pitOccupancy.js +2 -2
- package/src/simulation/pit/pitQueue.js +2 -18
- package/src/simulation/pit/pitRouteMovement.js +1 -36
- package/src/simulation/pit/pitRouting.js +5 -81
- package/src/simulation/pit/pitService.js +3 -32
- package/src/simulation/pit/pitServiceConstants.js +1 -0
- package/src/simulation/pit/pitServiceProgress.js +34 -0
- package/src/simulation/pit/pitSnapshots.js +8 -4
- package/src/simulation/pit/pitState.js +1 -5
- package/src/simulation/race/classification.js +1 -8
- package/src/simulation/race/raceFinish.js +3 -8
- package/src/simulation/race/raceOrder.js +2 -13
- package/src/simulation/race/raceProgress.js +6 -20
- package/src/simulation/race/raceSetup.js +1 -1
- package/src/simulation/race/raceStep.js +20 -11
- package/src/simulation/race/redFlag.js +2 -4
- package/src/simulation/race/safetyCar.js +5 -9
- package/src/simulation/race/stalledDnf.js +2 -4
- package/src/simulation/raceSimulation.js +6 -38
- package/src/simulation/replay/replayGhosts.js +44 -32
- package/src/simulation/rules/collisionSteward.js +0 -14
- package/src/simulation/rules/penaltyActions.js +37 -0
- package/src/simulation/rules/penaltyLedger.js +8 -1
- package/src/simulation/rules/pitLaneSpeedingSteward.js +1 -1
- package/src/simulation/rules/rulesReview.js +20 -16
- package/src/simulation/rules/trackLimitsSteward.js +2 -2
- package/src/simulation/simMath.js +4 -0
- package/src/simulation/snapshots/raceSnapshots.js +30 -11
- package/src/simulation/timing/drsState.js +8 -0
- package/src/simulation/timing/drsTiming.js +2 -4
- package/src/simulation/timing/lapTelemetry.js +7 -4
- package/src/simulation/timing/sectorPerformance.js +14 -6
- package/src/simulation/timing/timingLines.js +12 -6
- package/src/simulation/track/pitLaneAccess.js +2 -2
- package/src/simulation/track/pitLaneLayout.js +4 -135
- package/src/simulation/track/pitLaneModel.js +70 -0
- package/src/simulation/track/pitLaneState.js +0 -1
- package/src/simulation/track/pitServiceLayout.js +121 -0
- package/src/simulation/track/proceduralTrack.js +77 -0
- package/src/simulation/track/spatialQueries.js +76 -31
- package/src/simulation/track/trackBuilder.js +54 -0
- package/src/simulation/track/trackConstants.js +0 -22
- package/src/simulation/track/trackMath.js +4 -29
- package/src/simulation/track/trackModel.js +12 -240
- package/src/simulation/track/trackModelCache.js +105 -0
- package/src/simulation/track/trackNearestQueries.js +1218 -0
- package/src/simulation/track/trackQueryConstants.js +3 -0
- package/src/simulation/track/trackQueryConstruction.js +368 -0
- package/src/simulation/track/trackQueryIndex.js +12 -1933
- package/src/simulation/track/trackQuerySegments.js +174 -0
- package/src/simulation/track/trackQueryStats.js +12 -0
- package/src/simulation/track/trackRayQueries.js +165 -0
- package/src/simulation/vehicle/advancedContactResponse.js +89 -0
- package/src/simulation/vehicle/advancedTireForces.js +92 -0
- package/src/simulation/vehicle/advancedVehicleModel.js +65 -0
- package/src/simulation/vehicle/advancedVehiclePhysics.js +127 -0
- package/src/simulation/vehicle/contactResolution.js +23 -9
- package/src/simulation/vehicle/mainTrackWheelSurface.js +2 -13
- package/src/simulation/vehicle/pitWheelSurface.js +0 -12
- package/src/simulation/vehicle/runoffResponse.js +2 -4
- package/src/simulation/vehicle/sampledWheelSurface.js +266 -0
- package/src/simulation/vehicle/vehicleGeometry.js +85 -103
- package/src/simulation/vehicle/vehicleKinematics.js +10 -0
- package/src/simulation/vehicle/vehiclePhysics.js +42 -196
- package/src/simulation/vehicle/vehicleSnapshots.js +18 -6
- package/src/simulation/vehicle/vehicleState.js +5 -3
- package/src/simulation/vehicle/wheelSurface.js +13 -432
- package/src/simulation/vehicle/wheelSurfaceCache.js +55 -0
- package/src/simulation/vehicle/wheelSurfaceSummary.js +101 -0
- package/src/styles.css +173 -19
- package/src/ui/bannerTemplates.js +4 -2
- package/src/ui/cameraControlsTemplate.js +4 -2
- package/src/ui/gridWalkTemplate.js +29 -0
- package/src/ui/htmlEscaping.js +8 -0
- package/src/ui/raceCanvasTemplate.js +3 -2
- package/src/ui/shellTemplate.js +3 -0
- package/src/ui/telemetryDrawerTemplate.js +4 -2
- package/src/ui/telemetryTemplates.js +3 -22
- package/src/ui/templateUtils.js +2 -8
- package/src/ui/viewControlsTemplate.js +21 -0
- package/examples/train-basic-policy.mjs +0 -276
- package/examples/trainingData.mjs +0 -133
package/src/data/index.d.ts
CHANGED
|
@@ -1,199 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
export type PaddockProceduralTrackProfile = 'race' | 'training-short' | 'training-medium' | 'training-technical';
|
|
1
|
+
import type { TeamData } from './teamTypes.js';
|
|
3
2
|
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
includePitLane?: boolean;
|
|
10
|
-
length?: {
|
|
11
|
-
minMeters?: number;
|
|
12
|
-
maxMeters?: number;
|
|
13
|
-
};
|
|
14
|
-
startStraight?: {
|
|
15
|
-
gridMeters?: number;
|
|
16
|
-
exitMeters?: number;
|
|
17
|
-
blendMeters?: number;
|
|
18
|
-
lockExtraMeters?: number;
|
|
19
|
-
};
|
|
20
|
-
pitLane?: {
|
|
21
|
-
enabled?: boolean;
|
|
22
|
-
};
|
|
23
|
-
shape?: {
|
|
24
|
-
scale?: number;
|
|
25
|
-
cornerDensity?: number;
|
|
26
|
-
variation?: number;
|
|
27
|
-
};
|
|
28
|
-
validation?: {
|
|
29
|
-
minClearanceMultiplier?: number;
|
|
30
|
-
minShapeVariation?: number;
|
|
31
|
-
minNonAdjacentArcMeters?: number;
|
|
32
|
-
maxLocalTurnRadians?: number;
|
|
33
|
-
maxSampleHeadingDeltaRadians?: number;
|
|
34
|
-
};
|
|
35
|
-
attempts?: {
|
|
36
|
-
primary?: number;
|
|
37
|
-
fallback?: number;
|
|
38
|
-
};
|
|
39
|
-
}
|
|
3
|
+
export type {
|
|
4
|
+
PaddockPitCrewStats,
|
|
5
|
+
PaddockThemeSelector,
|
|
6
|
+
TeamData,
|
|
7
|
+
} from './teamTypes.js';
|
|
40
8
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export type CustomFieldInput = CustomField[] | Record<string, string>;
|
|
47
|
-
export type PaddockThemeSelector = 'default' | 'active' | 'selectedTeam' | 'team' | `team:${string}` | string;
|
|
48
|
-
|
|
49
|
-
export interface PaddockPitCrewStats {
|
|
50
|
-
speed?: number;
|
|
51
|
-
consistency?: number;
|
|
52
|
-
reliability?: number;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export interface TeamData {
|
|
56
|
-
id?: string;
|
|
57
|
-
name?: string;
|
|
58
|
-
color?: string;
|
|
59
|
-
icon?: string;
|
|
60
|
-
theme?: PaddockThemeSelector;
|
|
61
|
-
pitCrew?: PaddockPitCrewStats;
|
|
62
|
-
pitCrewStats?: PaddockPitCrewStats;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface SimulatorDriver {
|
|
66
|
-
id: string;
|
|
67
|
-
name: string;
|
|
68
|
-
color: string;
|
|
69
|
-
link?: string;
|
|
70
|
-
icon?: string;
|
|
71
|
-
code?: string;
|
|
72
|
-
timingName?: string;
|
|
73
|
-
tire?: TireCompound;
|
|
74
|
-
raceData?: string[];
|
|
75
|
-
customFields?: CustomFieldInput;
|
|
76
|
-
team?: TeamData | null;
|
|
77
|
-
driverNumber?: number;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export interface DriverRatings {
|
|
81
|
-
pace: number;
|
|
82
|
-
racecraft: number;
|
|
83
|
-
aggression: number;
|
|
84
|
-
riskTolerance: number;
|
|
85
|
-
patience: number;
|
|
86
|
-
consistency: number;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export interface VehicleRatings {
|
|
90
|
-
power: number;
|
|
91
|
-
braking: number;
|
|
92
|
-
aero: number;
|
|
93
|
-
dragEfficiency: number;
|
|
94
|
-
mechanicalGrip: number;
|
|
95
|
-
weightControl: number;
|
|
96
|
-
tireCare: number;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export interface DriverBlueprint extends Partial<DriverRatings> {
|
|
100
|
-
customFields?: CustomFieldInput;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export interface VehicleBlueprint extends Partial<VehicleRatings> {
|
|
104
|
-
id?: string | null;
|
|
105
|
-
name?: string | null;
|
|
106
|
-
customFields?: CustomFieldInput;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export interface DriverConstructorArgs {
|
|
110
|
-
ratings: DriverRatings;
|
|
111
|
-
customFields: CustomField[];
|
|
112
|
-
pace: number;
|
|
113
|
-
racecraft: number;
|
|
114
|
-
consistency: number;
|
|
115
|
-
personality: {
|
|
116
|
-
aggression: number;
|
|
117
|
-
riskTolerance: number;
|
|
118
|
-
patience: number;
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export interface VehicleConstructorArgs {
|
|
123
|
-
id: string | null;
|
|
124
|
-
name: string | null;
|
|
125
|
-
ratings: VehicleRatings;
|
|
126
|
-
customFields: CustomField[];
|
|
127
|
-
powerNewtons: number;
|
|
128
|
-
brakeNewtons: number;
|
|
129
|
-
downforceCoefficient: number;
|
|
130
|
-
dragCoefficient: number;
|
|
131
|
-
tireGrip: number;
|
|
132
|
-
mass: number;
|
|
133
|
-
tireCare: number;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export class DriverData {
|
|
137
|
-
constructor(input?: DriverBlueprint);
|
|
138
|
-
readonly pace: number;
|
|
139
|
-
readonly racecraft: number;
|
|
140
|
-
readonly aggression: number;
|
|
141
|
-
readonly riskTolerance: number;
|
|
142
|
-
readonly patience: number;
|
|
143
|
-
readonly consistency: number;
|
|
144
|
-
readonly customFields: CustomField[];
|
|
145
|
-
ratings(): DriverRatings;
|
|
146
|
-
toConstructorArgs(): DriverConstructorArgs;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export class VehicleData {
|
|
150
|
-
constructor(input?: VehicleBlueprint);
|
|
151
|
-
readonly id: string | null;
|
|
152
|
-
readonly name: string | null;
|
|
153
|
-
readonly power: number;
|
|
154
|
-
readonly braking: number;
|
|
155
|
-
readonly aero: number;
|
|
156
|
-
readonly dragEfficiency: number;
|
|
157
|
-
readonly mechanicalGrip: number;
|
|
158
|
-
readonly weightControl: number;
|
|
159
|
-
readonly tireCare: number;
|
|
160
|
-
readonly customFields: CustomField[];
|
|
161
|
-
ratings(): VehicleRatings;
|
|
162
|
-
toConstructorArgs(): VehicleConstructorArgs;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export interface ChampionshipEntryBlueprint {
|
|
166
|
-
driverId: string;
|
|
167
|
-
driverNumber?: number;
|
|
168
|
-
timingName?: string;
|
|
169
|
-
driver?: DriverData | DriverBlueprint;
|
|
170
|
-
vehicle?: VehicleData | VehicleBlueprint;
|
|
171
|
-
team?: TeamData;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export interface NormalizedSimulatorDriver extends SimulatorDriver {
|
|
175
|
-
code: string;
|
|
176
|
-
timingCode: string;
|
|
177
|
-
raceName: string;
|
|
178
|
-
driverNumber: number;
|
|
179
|
-
team: TeamData | null;
|
|
180
|
-
pace: number;
|
|
181
|
-
racecraft: number;
|
|
182
|
-
consistency: number;
|
|
183
|
-
personality: DriverConstructorArgs['personality'];
|
|
184
|
-
vehicle: VehicleConstructorArgs;
|
|
185
|
-
constructorArgs: {
|
|
186
|
-
driver: DriverConstructorArgs;
|
|
187
|
-
vehicle: VehicleConstructorArgs;
|
|
188
|
-
};
|
|
189
|
-
championship: {
|
|
190
|
-
id: string;
|
|
191
|
-
name: string;
|
|
192
|
-
season: number;
|
|
193
|
-
entryIndex: number;
|
|
194
|
-
vehicleId: string | null;
|
|
195
|
-
};
|
|
196
|
-
}
|
|
9
|
+
import type { PaddockProceduralTrackProfile, PaddockProceduralTrackOptions, PaddockTrackPoint, PaddockDrsZone, PaddockResolvedProceduralTrackOptions, PaddockProceduralTrack } from './trackTypes.js';
|
|
10
|
+
import type { TireCompound, CustomField, CustomFieldInput, EntryPresentation, SimulatorDriver, DriverRatings, VehicleRatings, DriverBlueprint, VehicleBlueprint, DriverConstructorArgs, VehicleConstructorArgs, DriverData, VehicleData, ChampionshipEntryBlueprint, NormalizedSimulatorDriver } from './entryTypes.js';
|
|
11
|
+
export type { PaddockProceduralTrackProfile, PaddockProceduralTrackOptions, PaddockTrackPoint, PaddockDrsZone, PaddockResolvedProceduralTrackOptions, PaddockProceduralTrack } from './trackTypes.js';
|
|
12
|
+
export type { TireCompound, CustomField, CustomFieldInput, EntryPresentation, SimulatorDriver, DriverRatings, VehicleRatings, DriverBlueprint, VehicleBlueprint, DriverConstructorArgs, VehicleConstructorArgs, ChampionshipEntryBlueprint, NormalizedSimulatorDriver } from './entryTypes.js';
|
|
13
|
+
export { DriverData, VehicleData } from './entryTypes.js';
|
|
197
14
|
|
|
198
15
|
export const CHAMPIONSHIP_ENTRY_BLUEPRINTS: ChampionshipEntryBlueprint[];
|
|
199
16
|
export const DEMO_PROJECT_DRIVERS: SimulatorDriver[];
|
|
@@ -207,6 +24,6 @@ export function normalizeSimulatorDrivers(
|
|
|
207
24
|
drivers: SimulatorDriver[],
|
|
208
25
|
options?: { entries?: ChampionshipEntryBlueprint[]; caller?: string },
|
|
209
26
|
): NormalizedSimulatorDriver[];
|
|
210
|
-
export function createProceduralTrack(seed?: number | string, options?: PaddockProceduralTrackOptions):
|
|
27
|
+
export function createProceduralTrack(seed?: number | string, options?: PaddockProceduralTrackOptions): PaddockProceduralTrack;
|
|
211
28
|
export function kphToSimSpeed(kph: number): number;
|
|
212
29
|
export function simSpeedToKph(simSpeed: number): number;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const RATING_MINIMUM = 0;
|
|
2
|
+
export const RATING_NEUTRAL = 50;
|
|
3
|
+
export const RATING_MAXIMUM = 100;
|
|
4
|
+
|
|
5
|
+
export function clampRating(value, label, domain) {
|
|
6
|
+
const rating = Number(value);
|
|
7
|
+
if (!Number.isFinite(rating)) throw new Error(`Invalid ${domain} rating for ${label}: ${value}`);
|
|
8
|
+
return Math.min(Math.max(rating, RATING_MINIMUM), RATING_MAXIMUM);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function applyRating(definition, value, direction = 1) {
|
|
12
|
+
const normalized = (value - definition.neutral) / (definition.maximum - definition.neutral);
|
|
13
|
+
return definition.base + normalized * definition.variance * direction;
|
|
14
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type PaddockThemeSelector =
|
|
2
|
+
| 'default'
|
|
3
|
+
| 'active'
|
|
4
|
+
| 'selectedTeam'
|
|
5
|
+
| 'team'
|
|
6
|
+
| `team:${string}`
|
|
7
|
+
| string;
|
|
8
|
+
|
|
9
|
+
export interface PaddockPitCrewStats {
|
|
10
|
+
speed?: number;
|
|
11
|
+
consistency?: number;
|
|
12
|
+
reliability?: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface TeamData {
|
|
16
|
+
id?: string;
|
|
17
|
+
name?: string;
|
|
18
|
+
color?: string;
|
|
19
|
+
icon?: string;
|
|
20
|
+
theme?: PaddockThemeSelector;
|
|
21
|
+
pitCrew?: PaddockPitCrewStats;
|
|
22
|
+
pitCrewStats?: PaddockPitCrewStats;
|
|
23
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export type PaddockProceduralTrackProfile = 'race' | 'training-short' | 'training-medium' | 'training-technical';
|
|
2
|
+
|
|
3
|
+
export interface PaddockProceduralTrackOptions {
|
|
4
|
+
profile?: PaddockProceduralTrackProfile;
|
|
5
|
+
minLengthMeters?: number;
|
|
6
|
+
maxLengthMeters?: number;
|
|
7
|
+
startStraightMeters?: number;
|
|
8
|
+
includePitLane?: boolean;
|
|
9
|
+
length?: {
|
|
10
|
+
minMeters?: number;
|
|
11
|
+
maxMeters?: number;
|
|
12
|
+
};
|
|
13
|
+
startStraight?: {
|
|
14
|
+
gridMeters?: number;
|
|
15
|
+
exitMeters?: number;
|
|
16
|
+
blendMeters?: number;
|
|
17
|
+
lockExtraMeters?: number;
|
|
18
|
+
};
|
|
19
|
+
pitLane?: {
|
|
20
|
+
enabled?: boolean;
|
|
21
|
+
};
|
|
22
|
+
shape?: {
|
|
23
|
+
scale?: number;
|
|
24
|
+
cornerDensity?: number;
|
|
25
|
+
variation?: number;
|
|
26
|
+
};
|
|
27
|
+
validation?: {
|
|
28
|
+
minClearanceMultiplier?: number;
|
|
29
|
+
minShapeVariation?: number;
|
|
30
|
+
minNonAdjacentArcMeters?: number;
|
|
31
|
+
maxLocalTurnRadians?: number;
|
|
32
|
+
maxSampleHeadingDeltaRadians?: number;
|
|
33
|
+
};
|
|
34
|
+
attempts?: {
|
|
35
|
+
primary?: number;
|
|
36
|
+
fallback?: number;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface PaddockTrackPoint {
|
|
41
|
+
x: number;
|
|
42
|
+
y: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface PaddockDrsZone {
|
|
46
|
+
id: string;
|
|
47
|
+
startRatio: number;
|
|
48
|
+
endRatio: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface PaddockResolvedProceduralTrackOptions {
|
|
52
|
+
profile: PaddockProceduralTrackProfile;
|
|
53
|
+
length: {
|
|
54
|
+
min: number;
|
|
55
|
+
max: number;
|
|
56
|
+
};
|
|
57
|
+
startStraight: {
|
|
58
|
+
grid: number;
|
|
59
|
+
exit: number;
|
|
60
|
+
blend: number;
|
|
61
|
+
lockExtra: number;
|
|
62
|
+
};
|
|
63
|
+
pitLane: {
|
|
64
|
+
enabled: boolean;
|
|
65
|
+
};
|
|
66
|
+
shape: {
|
|
67
|
+
scale: number;
|
|
68
|
+
cornerDensity: number;
|
|
69
|
+
variation: number;
|
|
70
|
+
};
|
|
71
|
+
validation: {
|
|
72
|
+
minClearanceMultiplier: number;
|
|
73
|
+
minShapeVariation: number;
|
|
74
|
+
minNonAdjacentArcDistance: number;
|
|
75
|
+
maxLocalTurnRadians: number;
|
|
76
|
+
maxSampleHeadingDeltaRadians: number;
|
|
77
|
+
};
|
|
78
|
+
attempts: {
|
|
79
|
+
primary: number;
|
|
80
|
+
fallback: number;
|
|
81
|
+
};
|
|
82
|
+
cacheKey: string;
|
|
83
|
+
[key: string]: unknown;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface PaddockProceduralTrack {
|
|
87
|
+
name: string;
|
|
88
|
+
width: number;
|
|
89
|
+
kerbWidth: number;
|
|
90
|
+
gravelWidth: number;
|
|
91
|
+
runoffWidth: number;
|
|
92
|
+
barrierWidth: number;
|
|
93
|
+
sampleCount: number;
|
|
94
|
+
seed?: number;
|
|
95
|
+
curveInterpolation?: string;
|
|
96
|
+
centerlineControls?: readonly PaddockTrackPoint[];
|
|
97
|
+
drsZones?: readonly PaddockDrsZone[] | null;
|
|
98
|
+
pitLane?: { enabled?: boolean } | null;
|
|
99
|
+
generationOptions?: PaddockResolvedProceduralTrackOptions;
|
|
100
|
+
[key: string]: unknown;
|
|
101
|
+
}
|
package/src/data/vehicleData.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { normalizeCustomFields } from './customFields.js';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const RATING_NEUTRAL = 50;
|
|
5
|
-
const RATING_MAXIMUM = 100;
|
|
3
|
+
import { RATING_MINIMUM, RATING_NEUTRAL, RATING_MAXIMUM, clampRating, applyRating } from './ratingScale.js';
|
|
6
4
|
|
|
7
5
|
export const VEHICLE_STAT_DEFINITIONS = {
|
|
8
6
|
power: { minimum: RATING_MINIMUM, neutral: RATING_NEUTRAL, maximum: RATING_MAXIMUM, base: 43000, variance: 3200, output: 'powerNewtons' },
|
|
@@ -14,18 +12,6 @@ export const VEHICLE_STAT_DEFINITIONS = {
|
|
|
14
12
|
tireCare: { minimum: RATING_MINIMUM, neutral: RATING_NEUTRAL, maximum: RATING_MAXIMUM, base: 1, variance: 0.12, output: 'tireCare' },
|
|
15
13
|
};
|
|
16
14
|
|
|
17
|
-
function clampRating(value, label) {
|
|
18
|
-
const rating = Number(value);
|
|
19
|
-
if (!Number.isFinite(rating)) throw new Error(`Invalid vehicle rating for ${label}: ${value}`);
|
|
20
|
-
return Math.min(Math.max(rating, RATING_MINIMUM), RATING_MAXIMUM);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function applyRating(definition, value) {
|
|
24
|
-
const normalized = (value - definition.neutral) / (definition.maximum - definition.neutral);
|
|
25
|
-
const direction = definition.direction ?? 1;
|
|
26
|
-
return definition.base + normalized * definition.variance * direction;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
15
|
export class VehicleData {
|
|
30
16
|
constructor({
|
|
31
17
|
id = null,
|
|
@@ -38,17 +24,19 @@ export class VehicleData {
|
|
|
38
24
|
weightControl = RATING_NEUTRAL,
|
|
39
25
|
tireCare = RATING_NEUTRAL,
|
|
40
26
|
customFields = [],
|
|
27
|
+
driverModel = null,
|
|
41
28
|
} = {}) {
|
|
42
29
|
this.id = id;
|
|
43
30
|
this.name = name;
|
|
44
|
-
this.power = clampRating(power, 'power');
|
|
45
|
-
this.braking = clampRating(braking, 'braking');
|
|
46
|
-
this.aero = clampRating(aero, 'aero');
|
|
47
|
-
this.dragEfficiency = clampRating(dragEfficiency, 'dragEfficiency');
|
|
48
|
-
this.mechanicalGrip = clampRating(mechanicalGrip, 'mechanicalGrip');
|
|
49
|
-
this.weightControl = clampRating(weightControl, 'weightControl');
|
|
50
|
-
this.tireCare = clampRating(tireCare, 'tireCare');
|
|
31
|
+
this.power = clampRating(power, 'power', 'vehicle');
|
|
32
|
+
this.braking = clampRating(braking, 'braking', 'vehicle');
|
|
33
|
+
this.aero = clampRating(aero, 'aero', 'vehicle');
|
|
34
|
+
this.dragEfficiency = clampRating(dragEfficiency, 'dragEfficiency', 'vehicle');
|
|
35
|
+
this.mechanicalGrip = clampRating(mechanicalGrip, 'mechanicalGrip', 'vehicle');
|
|
36
|
+
this.weightControl = clampRating(weightControl, 'weightControl', 'vehicle');
|
|
37
|
+
this.tireCare = clampRating(tireCare, 'tireCare', 'vehicle');
|
|
51
38
|
this.customFields = normalizeCustomFields(customFields);
|
|
39
|
+
this.driverModel = driverModel;
|
|
52
40
|
}
|
|
53
41
|
|
|
54
42
|
ratings() {
|
|
@@ -67,7 +55,7 @@ export class VehicleData {
|
|
|
67
55
|
const ratings = this.ratings();
|
|
68
56
|
const values = Object.fromEntries(Object.entries(VEHICLE_STAT_DEFINITIONS).map(([key, definition]) => [
|
|
69
57
|
definition.output,
|
|
70
|
-
applyRating(definition, ratings[key]),
|
|
58
|
+
applyRating(definition, ratings[key], definition.direction ?? 1),
|
|
71
59
|
]));
|
|
72
60
|
|
|
73
61
|
return {
|
|
@@ -75,6 +63,7 @@ export class VehicleData {
|
|
|
75
63
|
name: this.name,
|
|
76
64
|
ratings,
|
|
77
65
|
customFields: this.customFields,
|
|
66
|
+
driverModel: this.driverModel,
|
|
78
67
|
...values,
|
|
79
68
|
};
|
|
80
69
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { clamp } from '../simulation/simMath.js';
|
|
2
2
|
import { VEHICLE_LIMITS } from '../simulation/vehicle/vehiclePhysics.js';
|
|
3
|
+
import { normalizePitIntent } from '../simulation/pit/pitIntent.js';
|
|
3
4
|
|
|
4
5
|
export function resolveActionMap(actions = {}, controlledDrivers = [], { policy = 'strict' } = {}) {
|
|
5
6
|
const errors = [];
|
|
@@ -52,8 +53,8 @@ function finiteActionValue(value, message, policy, errors) {
|
|
|
52
53
|
|
|
53
54
|
function normalizePitIntentAction(action, driverId, policy, errors) {
|
|
54
55
|
if (!Object.hasOwn(action, 'pitIntent')) return null;
|
|
55
|
-
const number =
|
|
56
|
-
if (
|
|
56
|
+
const number = normalizePitIntent(action.pitIntent);
|
|
57
|
+
if (number != null) {
|
|
57
58
|
const pitCompound = normalizePitCompoundAction(action, driverId, policy, errors);
|
|
58
59
|
if (pitCompound === false) return null;
|
|
59
60
|
return pitCompound == null ? number : { intent: number, targetCompound: pitCompound };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { cancelScheduled, defaultScheduler, now } from './controllerScheduler.js';
|
|
2
|
+
|
|
1
3
|
export function createPaddockDriverControllerLoop({
|
|
2
4
|
runtime,
|
|
3
5
|
controller,
|
|
@@ -28,6 +30,8 @@ export function createPaddockDriverControllerLoop({
|
|
|
28
30
|
let previousActions = {};
|
|
29
31
|
let lastDecisionMs = 0;
|
|
30
32
|
let lastError = null;
|
|
33
|
+
let generation = 0;
|
|
34
|
+
let generationController = new AbortController();
|
|
31
35
|
|
|
32
36
|
async function ensureSpecs() {
|
|
33
37
|
if (!actionSpec) actionSpec = runtime.getActionSpec();
|
|
@@ -39,14 +43,24 @@ export function createPaddockDriverControllerLoop({
|
|
|
39
43
|
observationSpec = runtime.getObservationSpec();
|
|
40
44
|
}
|
|
41
45
|
|
|
46
|
+
async function runControllerHook(name, context) {
|
|
47
|
+
try {
|
|
48
|
+
return await controller[name]?.(context);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (context.signal.aborted) return;
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
42
55
|
async function ensureInitialized(context) {
|
|
43
56
|
if (initialized) return;
|
|
44
|
-
await
|
|
45
|
-
initialized = true;
|
|
57
|
+
await runControllerHook('init', context);
|
|
58
|
+
if (!context.signal.aborted) initialized = true;
|
|
46
59
|
}
|
|
47
60
|
|
|
48
61
|
async function resetRuntime(options = {}, { stopPlayback = true } = {}) {
|
|
49
62
|
if (stopPlayback) stop();
|
|
63
|
+
const resetGeneration = generation;
|
|
50
64
|
result = runtime.reset(options);
|
|
51
65
|
previousResult = null;
|
|
52
66
|
heldActions = null;
|
|
@@ -57,9 +71,11 @@ export function createPaddockDriverControllerLoop({
|
|
|
57
71
|
previousActions = {};
|
|
58
72
|
lastError = null;
|
|
59
73
|
await refreshSpecs();
|
|
74
|
+
if (generation !== resetGeneration) return result;
|
|
60
75
|
const context = buildContext({ resetDriverIds: controlledDrivers() });
|
|
61
76
|
await ensureInitialized(context);
|
|
62
|
-
|
|
77
|
+
if (generation !== resetGeneration) return result;
|
|
78
|
+
await runControllerHook('reset', context);
|
|
63
79
|
return result;
|
|
64
80
|
}
|
|
65
81
|
|
|
@@ -75,6 +91,9 @@ export function createPaddockDriverControllerLoop({
|
|
|
75
91
|
if (typeof runtime.resetDrivers !== 'function') {
|
|
76
92
|
throw new Error('The supplied Paddock runtime does not support resetDrivers().');
|
|
77
93
|
}
|
|
94
|
+
const resumePlayback = running;
|
|
95
|
+
stop();
|
|
96
|
+
const resetGeneration = generation;
|
|
78
97
|
const resetDriverIds = Object.keys(placements);
|
|
79
98
|
previousResult = result;
|
|
80
99
|
result = runtime.resetDrivers(placements, resultOptions);
|
|
@@ -89,29 +108,39 @@ export function createPaddockDriverControllerLoop({
|
|
|
89
108
|
delete previousActions[driverId];
|
|
90
109
|
});
|
|
91
110
|
await ensureSpecs();
|
|
111
|
+
if (generation !== resetGeneration) return result;
|
|
92
112
|
const context = buildContext({ resetDriverIds });
|
|
93
113
|
await ensureInitialized(context);
|
|
94
|
-
|
|
114
|
+
if (generation !== resetGeneration) return result;
|
|
115
|
+
await runControllerHook('reset', context);
|
|
116
|
+
if (resumePlayback && generation === resetGeneration) start();
|
|
95
117
|
return result;
|
|
96
118
|
}
|
|
97
119
|
|
|
98
|
-
async function beginDecision() {
|
|
120
|
+
async function beginDecision(expectedGeneration) {
|
|
99
121
|
await ensureResult();
|
|
122
|
+
if (generation !== expectedGeneration) return false;
|
|
100
123
|
const context = buildContext();
|
|
101
124
|
await ensureInitialized(context);
|
|
125
|
+
if (generation !== expectedGeneration) return false;
|
|
102
126
|
const startedAt = now();
|
|
103
|
-
const actions = await
|
|
127
|
+
const actions = await runControllerHook('decideBatch', context);
|
|
128
|
+
if (generation !== expectedGeneration) return false;
|
|
104
129
|
lastDecisionMs = now() - startedAt;
|
|
105
130
|
heldActions = actions && typeof actions === 'object' ? actions : {};
|
|
106
131
|
heldFramesRemaining = repeat;
|
|
107
132
|
policyStep += 1;
|
|
133
|
+
return true;
|
|
108
134
|
}
|
|
109
135
|
|
|
110
|
-
async function stepFrame() {
|
|
136
|
+
async function stepFrame(expectedGeneration = generation) {
|
|
111
137
|
await ensureResult();
|
|
138
|
+
if (generation !== expectedGeneration) return result;
|
|
112
139
|
if (!heldActions || heldFramesRemaining <= 0) {
|
|
113
|
-
await beginDecision();
|
|
140
|
+
const decisionReady = await beginDecision(expectedGeneration);
|
|
141
|
+
if (!decisionReady) return result;
|
|
114
142
|
}
|
|
143
|
+
if (generation !== expectedGeneration) return result;
|
|
115
144
|
const actionIndex = repeat - heldFramesRemaining;
|
|
116
145
|
const actions = heldActions;
|
|
117
146
|
const previousActionsForStep = previousActions;
|
|
@@ -121,7 +150,8 @@ export function createPaddockDriverControllerLoop({
|
|
|
121
150
|
heldFramesRemaining -= 1;
|
|
122
151
|
runtimeStep = Number(result?.info?.step ?? runtimeStep + 1);
|
|
123
152
|
previousActions = actions;
|
|
124
|
-
|
|
153
|
+
if (generation !== expectedGeneration) return result;
|
|
154
|
+
await runControllerHook('onStep', buildContext({
|
|
125
155
|
actionIndex,
|
|
126
156
|
actions,
|
|
127
157
|
previousActions: previousActionsForStep,
|
|
@@ -133,8 +163,10 @@ export function createPaddockDriverControllerLoop({
|
|
|
133
163
|
async function step() {
|
|
134
164
|
let latest = result;
|
|
135
165
|
const targetPolicyStep = policyStep + 1;
|
|
166
|
+
const expectedGeneration = generation;
|
|
136
167
|
while (policyStep < targetPolicyStep || heldFramesRemaining > 0) {
|
|
137
|
-
latest = await stepFrame();
|
|
168
|
+
latest = await stepFrame(expectedGeneration);
|
|
169
|
+
if (generation !== expectedGeneration) break;
|
|
138
170
|
if (latest?.done) break;
|
|
139
171
|
if (policyStep >= targetPolicyStep && heldFramesRemaining <= 0) break;
|
|
140
172
|
}
|
|
@@ -145,18 +177,21 @@ export function createPaddockDriverControllerLoop({
|
|
|
145
177
|
if (running) return;
|
|
146
178
|
lastError = null;
|
|
147
179
|
running = true;
|
|
180
|
+
const expectedGeneration = generation;
|
|
148
181
|
const schedule = scheduler ?? defaultScheduler();
|
|
149
182
|
const tick = async () => {
|
|
150
|
-
if (!running) return;
|
|
183
|
+
if (!running || generation !== expectedGeneration) return;
|
|
151
184
|
scheduled = null;
|
|
152
185
|
try {
|
|
153
|
-
await stepFrame();
|
|
186
|
+
await stepFrame(expectedGeneration);
|
|
154
187
|
} catch (error) {
|
|
188
|
+
if (generation !== expectedGeneration) return;
|
|
155
189
|
lastError = error;
|
|
156
190
|
running = false;
|
|
157
191
|
scheduled = null;
|
|
158
192
|
return;
|
|
159
193
|
}
|
|
194
|
+
if (generation !== expectedGeneration) return;
|
|
160
195
|
if (!running || result?.done) {
|
|
161
196
|
running = false;
|
|
162
197
|
return;
|
|
@@ -167,9 +202,17 @@ export function createPaddockDriverControllerLoop({
|
|
|
167
202
|
}
|
|
168
203
|
|
|
169
204
|
function stop() {
|
|
205
|
+
const previousController = generationController;
|
|
206
|
+
const previousSchedule = scheduled;
|
|
170
207
|
running = false;
|
|
171
|
-
|
|
208
|
+
generation += 1;
|
|
209
|
+
generationController = new AbortController();
|
|
172
210
|
scheduled = null;
|
|
211
|
+
try {
|
|
212
|
+
cancelScheduled(previousSchedule);
|
|
213
|
+
} finally {
|
|
214
|
+
previousController.abort();
|
|
215
|
+
}
|
|
173
216
|
}
|
|
174
217
|
|
|
175
218
|
function controlledDrivers() {
|
|
@@ -184,6 +227,7 @@ export function createPaddockDriverControllerLoop({
|
|
|
184
227
|
};
|
|
185
228
|
return {
|
|
186
229
|
runtime,
|
|
230
|
+
signal: generationController.signal,
|
|
187
231
|
mode,
|
|
188
232
|
actionRepeat: repeat,
|
|
189
233
|
controlledDrivers: drivers,
|
|
@@ -242,34 +286,3 @@ export function createPaddockDriverControllerLoop({
|
|
|
242
286
|
},
|
|
243
287
|
};
|
|
244
288
|
}
|
|
245
|
-
|
|
246
|
-
function now() {
|
|
247
|
-
return typeof performance !== 'undefined' && typeof performance.now === 'function'
|
|
248
|
-
? performance.now()
|
|
249
|
-
: Date.now();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
function cancelScheduled(handle) {
|
|
253
|
-
if (handle == null) return;
|
|
254
|
-
if (typeof handle.cancel === 'function') {
|
|
255
|
-
handle.cancel();
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
258
|
-
if (typeof handle === 'number') {
|
|
259
|
-
if (typeof cancelAnimationFrame === 'function') cancelAnimationFrame(handle);
|
|
260
|
-
if (typeof clearTimeout === 'function') clearTimeout(handle);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
function defaultScheduler() {
|
|
265
|
-
if (typeof requestAnimationFrame === 'function') {
|
|
266
|
-
return (callback) => {
|
|
267
|
-
const id = requestAnimationFrame(callback);
|
|
268
|
-
return { cancel: () => cancelAnimationFrame(id) };
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
return (callback) => {
|
|
272
|
-
const id = setTimeout(callback, 0);
|
|
273
|
-
return { cancel: () => clearTimeout(id) };
|
|
274
|
-
};
|
|
275
|
-
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export function now() {
|
|
2
|
+
return typeof performance !== 'undefined' && typeof performance.now === 'function'
|
|
3
|
+
? performance.now()
|
|
4
|
+
: Date.now();
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function cancelScheduled(handle) {
|
|
8
|
+
if (handle == null) return;
|
|
9
|
+
if (typeof handle.cancel === 'function') {
|
|
10
|
+
handle.cancel();
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (typeof handle === 'number') {
|
|
14
|
+
if (typeof cancelAnimationFrame === 'function') cancelAnimationFrame(handle);
|
|
15
|
+
if (typeof clearTimeout === 'function') clearTimeout(handle);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function defaultScheduler() {
|
|
20
|
+
if (typeof requestAnimationFrame === 'function') {
|
|
21
|
+
return (callback) => {
|
|
22
|
+
const id = requestAnimationFrame(callback);
|
|
23
|
+
return { cancel: () => cancelAnimationFrame(id) };
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return (callback) => {
|
|
27
|
+
const id = setTimeout(callback, 0);
|
|
28
|
+
return { cancel: () => clearTimeout(id) };
|
|
29
|
+
};
|
|
30
|
+
}
|