edtechdev commited on
Commit
feed137
·
verified ·
1 Parent(s): 0782320

Create an interactive physics simulation. Two cars move along a horizontal path at different initial speeds. Each car can be dragged by the user along the path to new positions or new velocities. As both cars move, 3 graphs are simultaneiously updated over time: a graph of the cars' position over time, a graph of velocity over time, and a graph of acceleration over time.

Browse files
Files changed (2) hide show
  1. README.md +6 -3
  2. index.html +613 -18
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
  title: Physics Playground
3
- emoji: 🌍
4
- colorFrom: green
5
  colorTo: red
 
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
  title: Physics Playground
3
+ colorFrom: pink
 
4
  colorTo: red
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://deepsite.hf.co).
index.html CHANGED
@@ -1,19 +1,614 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Physics Playground</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
9
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js"></script>
10
+ <style>
11
+ .car-container {
12
+ transition: transform 0.2s ease;
13
+ }
14
+ .car-dragging {
15
+ cursor: grabbing !important;
16
+ z-index: 10;
17
+ }
18
+ .track-line {
19
+ stroke: #4b5563;
20
+ stroke-width: 2;
21
+ stroke-dasharray: 5,5;
22
+ }
23
+ .car-shadow {
24
+ filter: drop-shadow(0 4px 3px rgba(0,0,0,0.07)) drop-shadow(0 2px 2px rgba(0,0,0,0.06));
25
+ }
26
+ </style>
27
+ </head>
28
+ <body class="bg-gradient-to-br from-indigo-50 to-purple-100 min-h-screen">
29
+ <div class="container mx-auto px-4 py-8">
30
+ <header class="text-center mb-12">
31
+ <h1 class="text-4xl md:text-5xl font-bold text-gray-800 mb-3">Physics Playground 🚗</h1>
32
+ <p class="text-lg text-gray-600 max-w-2xl mx-auto">Drag the cars to change their positions or velocities. Watch as real-time graphs update to show position, velocity, and acceleration over time.</p>
33
+ </header>
34
+
35
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8 mb-12">
36
+ <!-- Simulation Canvas -->
37
+ <div class="lg:col-span-2 bg-white rounded-2xl shadow-xl p-6">
38
+ <div class="flex justify-between items-center mb-4">
39
+ <h2 class="text-xl font-bold text-gray-800">Simulation</h2>
40
+ <div class="flex space-x-2">
41
+ <button id="resetBtn" class="px-4 py-2 bg-indigo-100 text-indigo-700 rounded-lg hover:bg-indigo-200 transition flex items-center">
42
+ <i data-feather="refresh-ccw" class="mr-2"></i> Reset
43
+ </button>
44
+ <button id="playPauseBtn" class="px-4 py-2 bg-green-100 text-green-700 rounded-lg hover:bg-green-200 transition flex items-center">
45
+ <i data-feather="pause" class="mr-2"></i> Pause
46
+ </button>
47
+ </div>
48
+ </div>
49
+
50
+ <div id="simulationCanvas" class="relative h-64 bg-gradient-to-r from-blue-50 to-indigo-50 rounded-xl border-2 border-dashed border-gray-200 overflow-hidden">
51
+ <!-- Track -->
52
+ <div class="absolute top-1/2 left-0 right-0 h-1 bg-gray-300 transform -translate-y-1/2"></div>
53
+
54
+ <!-- Distance markers -->
55
+ <div class="absolute top-1/2 left-0 transform -translate-y-1/2 -translate-x-1/2">
56
+ <div class="text-xs text-gray-500">0m</div>
57
+ </div>
58
+ <div class="absolute top-1/2 left-1/4 transform -translate-y-1/2 -translate-x-1/2">
59
+ <div class="text-xs text-gray-500">25m</div>
60
+ </div>
61
+ <div class="absolute top-1/2 left-1/2 transform -translate-y-1/2 -translate-x-1/2">
62
+ <div class="text-xs text-gray-500">50m</div>
63
+ </div>
64
+ <div class="absolute top-1/2 left-3/4 transform -translate-y-1/2 -translate-x-1/2">
65
+ <div class="text-xs text-gray-500">75m</div>
66
+ </div>
67
+ <div class="absolute top-1/2 right-0 transform -translate-y-1/2 translate-x-1/2">
68
+ <div class="text-xs text-gray-500">100m</div>
69
+ </div>
70
+
71
+ <!-- Cars -->
72
+ <div id="car1" class="car-container absolute top-1/2 cursor-grab active:cursor-grabbing transform -translate-y-1/2" style="left: 20%;">
73
+ <div class="car-shadow">
74
+ <svg width="60" height="30" viewBox="0 0 60 30">
75
+ <rect x="5" y="8" width="50" height="14" rx="7" fill="#3b82f6"/>
76
+ <circle cx="15" cy="24" r="5" fill="#1e40af"/>
77
+ <circle cx="45" cy="24" r="5" fill="#1e40af"/>
78
+ <rect x="0" y="10" width="10" height="10" rx="2" fill="#3b82f6"/>
79
+ <rect x="50" y="10" width="10" height="10" rx="2" fill="#3b82f6"/>
80
+ </svg>
81
+ </div>
82
+ <div class="text-center mt-2 text-sm font-medium text-blue-600">Car 1</div>
83
+ </div>
84
+
85
+ <div id="car2" class="car-container absolute top-1/2 cursor-grab active:cursor-grabbing transform -translate-y-1/2" style="left: 40%;">
86
+ <div class="car-shadow">
87
+ <svg width="60" height="30" viewBox="0 0 60 30">
88
+ <rect x="5" y="8" width="50" height="14" rx="7" fill="#ef4444"/>
89
+ <circle cx="15" cy="24" r="5" fill="#b91c1c"/>
90
+ <circle cx="45" cy="24" r="5" fill="#b91c1c"/>
91
+ <rect x="0" y="10" width="10" height="10" rx="2" fill="#ef4444"/>
92
+ <rect x="50" y="10" width="10" height="10" rx="2" fill="#ef4444"/>
93
+ </svg>
94
+ </div>
95
+ <div class="text-center mt-2 text-sm font-medium text-red-600">Car 2</div>
96
+ </div>
97
+ </div>
98
+
99
+ <div class="mt-6 grid grid-cols-1 md:grid-cols-2 gap-4">
100
+ <div class="bg-blue-50 p-4 rounded-lg">
101
+ <h3 class="font-bold text-blue-800 mb-2">Car 1 Controls</h3>
102
+ <div class="flex items-center space-x-4">
103
+ <div>
104
+ <label class="text-sm text-gray-600">Position (m)</label>
105
+ <input type="range" id="position1" min="0" max="100" value="20" class="w-full">
106
+ <div class="text-center text-blue-700 font-mono" id="position1Value">20m</div>
107
+ </div>
108
+ <div>
109
+ <label class="text-sm text-gray-600">Velocity (m/s)</label>
110
+ <input type="range" id="velocity1" min="-10" max="10" value="3" class="w-full">
111
+ <div class="text-center text-blue-700 font-mono" id="velocity1Value">3m/s</div>
112
+ </div>
113
+ </div>
114
+ </div>
115
+
116
+ <div class="bg-red-50 p-4 rounded-lg">
117
+ <h3 class="font-bold text-red-800 mb-2">Car 2 Controls</h3>
118
+ <div class="flex items-center space-x-4">
119
+ <div>
120
+ <label class="text-sm text-gray-600">Position (m)</label>
121
+ <input type="range" id="position2" min="0" max="100" value="40" class="w-full">
122
+ <div class="text-center text-red-700 font-mono" id="position2Value">40m</div>
123
+ </div>
124
+ <div>
125
+ <label class="text-sm text-gray-600">Velocity (m/s)</label>
126
+ <input type="range" id="velocity2" min="-10" max="10" value="-2" class="w-full">
127
+ <div class="text-center text-red-700 font-mono" id="velocity2Value">-2m/s</div>
128
+ </div>
129
+ </div>
130
+ </div>
131
+ </div>
132
+ </div>
133
+
134
+ <!-- Data Panel -->
135
+ <div class="bg-white rounded-2xl shadow-xl p-6">
136
+ <h2 class="text-xl font-bold text-gray-800 mb-4">Current Data</h2>
137
+
138
+ <div class="space-y-4">
139
+ <div class="bg-blue-50 p-4 rounded-lg">
140
+ <div class="flex justify-between items-center">
141
+ <h3 class="font-bold text-blue-800">Car 1</h3>
142
+ <div class="flex space-x-2">
143
+ <span class="px-2 py-1 bg-blue-100 text-blue-800 rounded text-xs">v = <span id="car1Velocity">3</span> m/s</span>
144
+ <span class="px-2 py-1 bg-blue-100 text-blue-800 rounded text-xs">a = <span id="car1Acceleration">0</span> m/s²</span>
145
+ </div>
146
+ </div>
147
+ <div class="mt-2">
148
+ <div class="text-sm text-gray-600">Position: <span id="car1Position" class="font-mono">20</span> m</div>
149
+ <div class="w-full bg-gray-200 rounded-full h-2 mt-1">
150
+ <div id="car1Progress" class="bg-blue-600 h-2 rounded-full" style="width: 20%"></div>
151
+ </div>
152
+ </div>
153
+ </div>
154
+
155
+ <div class="bg-red-50 p-4 rounded-lg">
156
+ <div class="flex justify-between items-center">
157
+ <h3 class="font-bold text-red-800">Car 2</h3>
158
+ <div class="flex space-x-2">
159
+ <span class="px-2 py-1 bg-red-100 text-red-800 rounded text-xs">v = <span id="car2Velocity">-2</span> m/s</span>
160
+ <span class="px-2 py-1 bg-red-100 text-red-800 rounded text-xs">a = <span id="car2Acceleration">0</span> m/s²</span>
161
+ </div>
162
+ </div>
163
+ <div class="mt-2">
164
+ <div class="text-sm text-gray-600">Position: <span id="car2Position" class="font-mono">40</span> m</div>
165
+ <div class="w-full bg-gray-200 rounded-full h-2 mt-1">
166
+ <div id="car2Progress" class="bg-red-600 h-2 rounded-full" style="width: 40%"></div>
167
+ </div>
168
+ </div>
169
+ </div>
170
+ </div>
171
+
172
+ <div class="mt-6 bg-gray-50 p-4 rounded-lg">
173
+ <h3 class="font-bold text-gray-800 mb-2">Simulation Controls</h3>
174
+ <div class="grid grid-cols-2 gap-3">
175
+ <button id="accelerate1" class="px-3 py-2 bg-blue-100 text-blue-700 rounded hover:bg-blue-200 transition text-sm">Accelerate Car 1</button>
176
+ <button id="decelerate1" class="px-3 py-2 bg-blue-100 text-blue-700 rounded hover:bg-blue-200 transition text-sm">Decelerate Car 1</button>
177
+ <button id="accelerate2" class="px-3 py-2 bg-red-100 text-red-700 rounded hover:bg-red-200 transition text-sm">Accelerate Car 2</button>
178
+ <button id="decelerate2" class="px-3 py-2 bg-red-100 text-red-700 rounded hover:bg-red-200 transition text-sm">Decelerate Car 2</button>
179
+ </div>
180
+ </div>
181
+
182
+ <div class="mt-6">
183
+ <h3 class="font-bold text-gray-800 mb-2">Physics Concepts</h3>
184
+ <ul class="text-sm text-gray-600 space-y-1">
185
+ <li class="flex items-start">
186
+ <span class="text-green-500 mr-2">•</span>
187
+ <span>Position changes with velocity over time</span>
188
+ </li>
189
+ <li class="flex items-start">
190
+ <span class="text-green-500 mr-2">•</span>
191
+ <span>Velocity changes with acceleration</span>
192
+ </li>
193
+ <li class="flex items-start">
194
+ <span class="text-green-500 mr-2">•</span>
195
+ <span>Negative velocity means moving left</span>
196
+ </li>
197
+ </ul>
198
+ </div>
199
+ </div>
200
+ </div>
201
+
202
+ <!-- Graphs Section -->
203
+ <div class="bg-white rounded-2xl shadow-xl p-6 mb-12">
204
+ <h2 class="text-xl font-bold text-gray-800 mb-6">Real-time Physics Graphs</h2>
205
+
206
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
207
+ <div class="bg-gray-50 p-4 rounded-lg">
208
+ <h3 class="font-bold text-gray-800 mb-4 text-center">Position vs Time</h3>
209
+ <canvas id="positionChart"></canvas>
210
+ </div>
211
+
212
+ <div class="bg-gray-50 p-4 rounded-lg">
213
+ <h3 class="font-bold text-gray-800 mb-4 text-center">Velocity vs Time</h3>
214
+ <canvas id="velocityChart"></canvas>
215
+ </div>
216
+
217
+ <div class="bg-gray-50 p-4 rounded-lg">
218
+ <h3 class="font-bold text-gray-800 mb-4 text-center">Acceleration vs Time</h3>
219
+ <canvas id="accelerationChart"></canvas>
220
+ </div>
221
+ </div>
222
+ </div>
223
+
224
+ <footer class="text-center text-gray-600 text-sm py-6">
225
+ <p>Drag cars to change their positions or use controls to adjust velocities. Watch how physics laws govern motion!</p>
226
+ </footer>
227
+ </div>
228
+
229
+ <script>
230
+ // Initialize Feather Icons
231
+ feather.replace();
232
+
233
+ // Simulation state
234
+ const state = {
235
+ cars: [
236
+ { id: 'car1', position: 20, velocity: 3, acceleration: 0, color: '#3b82f6' },
237
+ { id: 'car2', position: 40, velocity: -2, acceleration: 0, color: '#ef4444' }
238
+ ],
239
+ isRunning: true,
240
+ lastTime: 0,
241
+ dataPoints: {
242
+ position: [[0, 20], [0, 40]],
243
+ velocity: [[0, 3], [0, -2]],
244
+ acceleration: [[0, 0], [0, 0]]
245
+ }
246
+ };
247
+
248
+ // DOM Elements
249
+ const elements = {
250
+ car1: document.getElementById('car1'),
251
+ car2: document.getElementById('car2'),
252
+ playPauseBtn: document.getElementById('playPauseBtn'),
253
+ resetBtn: document.getElementById('resetBtn'),
254
+ position1: document.getElementById('position1'),
255
+ position2: document.getElementById('position2'),
256
+ velocity1: document.getElementById('velocity1'),
257
+ velocity2: document.getElementById('velocity2'),
258
+ accelerate1: document.getElementById('accelerate1'),
259
+ decelerate1: document.getElementById('decelerate1'),
260
+ accelerate2: document.getElementById('accelerate2'),
261
+ decelerate2: document.getElementById('decelerate2')
262
+ };
263
+
264
+ // Initialize Charts
265
+ const positionCtx = document.getElementById('positionChart').getContext('2d');
266
+ const velocityCtx = document.getElementById('velocityChart').getContext('2d');
267
+ const accelerationCtx = document.getElementById('accelerationChart').getContext('2d');
268
+
269
+ const positionChart = new Chart(positionCtx, {
270
+ type: 'line',
271
+ data: {
272
+ labels: [0],
273
+ datasets: [{
274
+ label: 'Car 1',
275
+ data: [20],
276
+ borderColor: '#3b82f6',
277
+ backgroundColor: 'rgba(59, 130, 246, 0.1)',
278
+ tension: 0.4,
279
+ fill: false
280
+ }, {
281
+ label: 'Car 2',
282
+ data: [40],
283
+ borderColor: '#ef4444',
284
+ backgroundColor: 'rgba(239, 68, 68, 0.1)',
285
+ tension: 0.4,
286
+ fill: false
287
+ }]
288
+ },
289
+ options: {
290
+ responsive: true,
291
+ maintainAspectRatio: true,
292
+ plugins: {
293
+ legend: { position: 'top' }
294
+ },
295
+ scales: {
296
+ x: { title: { display: true, text: 'Time (s)' } },
297
+ y: { title: { display: true, text: 'Position (m)' } }
298
+ }
299
+ }
300
+ });
301
+
302
+ const velocityChart = new Chart(velocityCtx, {
303
+ type: 'line',
304
+ data: {
305
+ labels: [0],
306
+ datasets: [{
307
+ label: 'Car 1',
308
+ data: [3],
309
+ borderColor: '#3b82f6',
310
+ backgroundColor: 'rgba(59, 130, 246, 0.1)',
311
+ tension: 0.4,
312
+ fill: false
313
+ }, {
314
+ label: 'Car 2',
315
+ data: [-2],
316
+ borderColor: '#ef4444',
317
+ backgroundColor: 'rgba(239, 68, 68, 0.1)',
318
+ tension: 0.4,
319
+ fill: false
320
+ }]
321
+ },
322
+ options: {
323
+ responsive: true,
324
+ maintainAspectRatio: true,
325
+ plugins: {
326
+ legend: { position: 'top' }
327
+ },
328
+ scales: {
329
+ x: { title: { display: true, text: 'Time (s)' } },
330
+ y: { title: { display: true, text: 'Velocity (m/s)' } }
331
+ }
332
+ }
333
+ });
334
+
335
+ const accelerationChart = new Chart(accelerationCtx, {
336
+ type: 'line',
337
+ data: {
338
+ labels: [0],
339
+ datasets: [{
340
+ label: 'Car 1',
341
+ data: [0],
342
+ borderColor: '#3b82f6',
343
+ backgroundColor: 'rgba(59, 130, 246, 0.1)',
344
+ tension: 0.4,
345
+ fill: false
346
+ }, {
347
+ label: 'Car 2',
348
+ data: [0],
349
+ borderColor: '#ef4444',
350
+ backgroundColor: 'rgba(239, 68, 68, 0.1)',
351
+ tension: 0.4,
352
+ fill: false
353
+ }]
354
+ },
355
+ options: {
356
+ responsive: true,
357
+ maintainAspectRatio: true,
358
+ plugins: {
359
+ legend: { position: 'top' }
360
+ },
361
+ scales: {
362
+ x: { title: { display: true, text: 'Time (s)' } },
363
+ y: { title: { display: true, text: 'Acceleration (m/s²)' } }
364
+ }
365
+ }
366
+ });
367
+
368
+ // Drag functionality for cars
369
+ function initDrag(carElement, carIndex) {
370
+ let isDragging = false;
371
+ let offsetX, offsetY;
372
+
373
+ carElement.addEventListener('mousedown', (e) => {
374
+ isDragging = true;
375
+ carElement.classList.add('car-dragging');
376
+ offsetX = e.clientX - carElement.getBoundingClientRect().left;
377
+ offsetY = e.clientY - carElement.getBoundingClientRect().top;
378
+ e.preventDefault();
379
+ });
380
+
381
+ document.addEventListener('mousemove', (e) => {
382
+ if (!isDragging) return;
383
+
384
+ const canvasRect = document.getElementById('simulationCanvas').getBoundingClientRect();
385
+ const x = e.clientX - canvasRect.left - offsetX;
386
+ const position = Math.max(0, Math.min(100, (x / canvasRect.width) * 100));
387
+
388
+ state.cars[carIndex].position = position;
389
+ updateCarPosition(carIndex);
390
+ updateUI();
391
+ });
392
+
393
+ document.addEventListener('mouseup', () => {
394
+ if (isDragging) {
395
+ isDragging = false;
396
+ carElement.classList.remove('car-dragging');
397
+ }
398
+ });
399
+ }
400
+
401
+ // Update car position on canvas
402
+ function updateCarPosition(carIndex) {
403
+ const car = state.cars[carIndex];
404
+ const carElement = document.getElementById(car.id);
405
+ carElement.style.left = `${car.position}%`;
406
+ }
407
+
408
+ // Update UI elements
409
+ function updateUI() {
410
+ // Update car data displays
411
+ document.getElementById('car1Position').textContent = Math.round(state.cars[0].position);
412
+ document.getElementById('car1Velocity').textContent = state.cars[0].velocity.toFixed(1);
413
+ document.getElementById('car1Acceleration').textContent = state.cars[0].acceleration.toFixed(1);
414
+ document.getElementById('car1Progress').style.width = `${state.cars[0].position}%`;
415
+
416
+ document.getElementById('car2Position').textContent = Math.round(state.cars[1].position);
417
+ document.getElementById('car2Velocity').textContent = state.cars[1].velocity.toFixed(1);
418
+ document.getElementById('car2Acceleration').textContent = state.cars[1].acceleration.toFixed(1);
419
+ document.getElementById('car2Progress').style.width = `${state.cars[1].position}%`;
420
+
421
+ // Update sliders
422
+ elements.position1.value = state.cars[0].position;
423
+ elements.velocity1.value = state.cars[0].velocity;
424
+ elements.position2.value = state.cars[1].position;
425
+ elements.velocity2.value = state.cars[1].velocity;
426
+
427
+ // Update slider value displays
428
+ document.getElementById('position1Value').textContent = `${Math.round(state.cars[0].position)}m`;
429
+ document.getElementById('velocity1Value').textContent = `${state.cars[0].velocity}m/s`;
430
+ document.getElementById('position2Value').textContent = `${Math.round(state.cars[1].position)}m`;
431
+ document.getElementById('velocity2Value').textContent = `${state.cars[1].velocity}m/s`;
432
+ }
433
+
434
+ // Update charts with new data
435
+ function updateCharts(time) {
436
+ // Add new data points
437
+ positionChart.data.labels.push(time.toFixed(1));
438
+ velocityChart.data.labels.push(time.toFixed(1));
439
+ accelerationChart.data.labels.push(time.toFixed(1));
440
+
441
+ positionChart.data.datasets[0].data.push(state.cars[0].position);
442
+ positionChart.data.datasets[1].data.push(state.cars[1].position);
443
+
444
+ velocityChart.data.datasets[0].data.push(state.cars[0].velocity);
445
+ velocityChart.data.datasets[1].data.push(state.cars[1].velocity);
446
+
447
+ accelerationChart.data.datasets[0].data.push(state.cars[0].acceleration);
448
+ accelerationChart.data.datasets[1].data.push(state.cars[1].acceleration);
449
+
450
+ // Limit data points to last 20
451
+ if (positionChart.data.labels.length > 20) {
452
+ positionChart.data.labels.shift();
453
+ velocityChart.data.labels.shift();
454
+ accelerationChart.data.labels.shift();
455
+
456
+ positionChart.data.datasets[0].data.shift();
457
+ positionChart.data.datasets[1].data.shift();
458
+ velocityChart.data.datasets[0].data.shift();
459
+ velocityChart.data.datasets[1].data.shift();
460
+ accelerationChart.data.datasets[0].data.shift();
461
+ accelerationChart.data.datasets[1].data.shift();
462
+ }
463
+
464
+ // Update charts
465
+ positionChart.update();
466
+ velocityChart.update();
467
+ accelerationChart.update();
468
+ }
469
+
470
+ // Physics simulation
471
+ function simulatePhysics(deltaTime) {
472
+ if (!state.isRunning) return;
473
+
474
+ // Update positions based on velocity
475
+ state.cars.forEach(car => {
476
+ car.position += car.velocity * deltaTime;
477
+
478
+ // Boundary checks
479
+ if (car.position < 0) {
480
+ car.position = 0;
481
+ car.velocity = Math.abs(car.velocity) * 0.5; // Bounce with energy loss
482
+ } else if (car.position > 100) {
483
+ car.position = 100;
484
+ car.velocity = -Math.abs(car.velocity) * 0.5; // Bounce with energy loss
485
+ }
486
+ });
487
+
488
+ // Update UI
489
+ updateCarPosition(0);
490
+ updateCarPosition(1);
491
+ updateUI();
492
+ }
493
+
494
+ // Animation loop
495
+ function animationLoop(timestamp) {
496
+ if (!state.lastTime) state.lastTime = timestamp;
497
+ const deltaTime = (timestamp - state.lastTime) / 1000; // Convert to seconds
498
+ state.lastTime = timestamp;
499
+
500
+ simulatePhysics(deltaTime);
501
+
502
+ // Update charts every 0.5 seconds
503
+ if (timestamp % 500 < 20) { // Roughly every 0.5 seconds
504
+ const time = timestamp / 1000;
505
+ updateCharts(time);
506
+ }
507
+
508
+ requestAnimationFrame(animationLoop);
509
+ }
510
+
511
+ // Event Listeners
512
+ elements.playPauseBtn.addEventListener('click', () => {
513
+ state.isRunning = !state.isRunning;
514
+ const icon = elements.playPauseBtn.querySelector('i');
515
+ icon.setAttribute('data-feather', state.isRunning ? 'pause' : 'play');
516
+ feather.replace();
517
+ elements.playPauseBtn.innerHTML = elements.playPauseBtn.innerHTML.replace(
518
+ state.isRunning ? 'Play' : 'Pause',
519
+ state.isRunning ? 'Pause' : 'Play'
520
+ );
521
+ });
522
+
523
+ elements.resetBtn.addEventListener('click', () => {
524
+ state.cars[0].position = 20;
525
+ state.cars[0].velocity = 3;
526
+ state.cars[0].acceleration = 0;
527
+
528
+ state.cars[1].position = 40;
529
+ state.cars[1].velocity = -2;
530
+ state.cars[1].acceleration = 0;
531
+
532
+ state.lastTime = 0;
533
+
534
+ updateCarPosition(0);
535
+ updateCarPosition(1);
536
+ updateUI();
537
+
538
+ // Reset charts
539
+ positionChart.data.labels = [0];
540
+ velocityChart.data.labels = [0];
541
+ accelerationChart.data.labels = [0];
542
+
543
+ positionChart.data.datasets[0].data = [20];
544
+ positionChart.data.datasets[1].data = [40];
545
+ velocityChart.data.datasets[0].data = [3];
546
+ velocityChart.data.datasets[1].data = [-2];
547
+ accelerationChart.data.datasets[0].data = [0];
548
+ accelerationChart.data.datasets[1].data = [0];
549
+
550
+ positionChart.update();
551
+ velocityChart.update();
552
+ accelerationChart.update();
553
+ });
554
+
555
+ // Slider event listeners
556
+ elements.position1.addEventListener('input', () => {
557
+ state.cars[0].position = parseFloat(elements.position1.value);
558
+ updateCarPosition(0);
559
+ updateUI();
560
+ });
561
+
562
+ elements.velocity1.addEventListener('input', () => {
563
+ state.cars[0].velocity = parseFloat(elements.velocity1.value);
564
+ updateUI();
565
+ });
566
+
567
+ elements.position2.addEventListener('input', () => {
568
+ state.cars[1].position = parseFloat(elements.position2.value);
569
+ updateCarPosition(1);
570
+ updateUI();
571
+ });
572
+
573
+ elements.velocity2.addEventListener('input', () => {
574
+ state.cars[1].velocity = parseFloat(elements.velocity2.value);
575
+ updateUI();
576
+ });
577
+
578
+ // Acceleration controls
579
+ elements.accelerate1.addEventListener('click', () => {
580
+ state.cars[0].acceleration = 1;
581
+ state.cars[0].velocity += 0.5;
582
+ updateUI();
583
+ });
584
+
585
+ elements.decelerate1.addEventListener('click', () => {
586
+ state.cars[0].acceleration = -1;
587
+ state.cars[0].velocity -= 0.5;
588
+ updateUI();
589
+ });
590
+
591
+ elements.accelerate2.addEventListener('click', () => {
592
+ state.cars[1].acceleration = 1;
593
+ state.cars[1].velocity += 0.5;
594
+ updateUI();
595
+ });
596
+
597
+ elements.decelerate2.addEventListener('click', () => {
598
+ state.cars[1].acceleration = -1;
599
+ state.cars[1].velocity -= 0.5;
600
+ updateUI();
601
+ });
602
+
603
+ // Initialize drag functionality
604
+ initDrag(elements.car1, 0);
605
+ initDrag(elements.car2, 1);
606
+
607
+ // Start animation loop
608
+ requestAnimationFrame(animationLoop);
609
+
610
+ // Initial UI update
611
+ updateUI();
612
+ </script>
613
+ </body>
614
  </html>