+
setIsExpanded(!isExpanded)}
+ >
+
Configuration
+ {isExpanded ? '▼' : '◀'}
+
+
+ {isExpanded && (
+ <>
+
+
Car Physics
+
+
+ Max Speed
+ {carConfig.maxSpeed.toFixed(1)}
+
+
updateCar('maxSpeed', parseFloat(e.target.value))}
+ style={sliderStyle}
+ />
+
+
+ Turn Speed
+ {carConfig.turnSpeed.toFixed(2)}
+
+
updateCar('turnSpeed', parseFloat(e.target.value))}
+ style={sliderStyle}
+ />
+
+
+ Tire Grip (Lateral)
+ {(carConfig.lateralFriction * 100).toFixed(0)}%
+
+
updateCar('lateralFriction', parseFloat(e.target.value))}
+ style={sliderStyle}
+ />
+
+
+ Air Resistance
+ {(carConfig.frictionAir * 1000).toFixed(0)}
+
+
updateCar('frictionAir', parseFloat(e.target.value))}
+ style={sliderStyle}
+ />
+
+
+
+
Track Gen
+
+
+ Complexity (Wiggle)
+ {(simConfig.trackComplexity * 100).toFixed(0)}%
+
+
updateSim('trackComplexity', parseFloat(e.target.value))}
+ style={sliderStyle}
+ />
+
+
+ Length (Nodes)
+ {simConfig.trackLength}
+
+
updateSim('trackLength', parseInt(e.target.value))}
+ style={sliderStyle}
+ />
+
+
+
+
+
+ Physics apply immediately.
+ Track settings apply on generate.
+
+ >
+ )}
+
+ );
+}
diff --git a/src/apps/SelfDrivingCar/FitnessGraph.tsx b/src/apps/SelfDrivingCar/FitnessGraph.tsx
new file mode 100644
index 0000000..408d832
--- /dev/null
+++ b/src/apps/SelfDrivingCar/FitnessGraph.tsx
@@ -0,0 +1,140 @@
+interface FitnessGraphProps {
+ history: Array<{ generation: number; best: number; average: number }>;
+ width?: number | string;
+ height?: number | string;
+ className?: string;
+}
+
+export default function FitnessGraph({ history, width = "100%", height = 150, className = "" }: FitnessGraphProps) {
+ if (history.length < 2) {
+ return (
+