Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>1D Motion Solver | Class 11 Physics</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
| <style> | |
| .equation-input { | |
| background-color: #f8fafc; | |
| border-left: 4px solid #3b82f6; | |
| } | |
| .motion-diagram { | |
| position: relative; | |
| height: 100px; | |
| background-color: #f1f5f9; | |
| border-radius: 6px; | |
| overflow: hidden; | |
| } | |
| .object { | |
| position: absolute; | |
| width: 20px; | |
| height: 20px; | |
| background-color: #ef4444; | |
| border-radius: 50%; | |
| bottom: 10px; | |
| transition: left 0.5s ease-out; | |
| } | |
| .position-markers { | |
| position: absolute; | |
| bottom: 40px; | |
| width: 100%; | |
| height: 1px; | |
| background-color: #94a3b8; | |
| } | |
| .marker { | |
| position: absolute; | |
| bottom: 35px; | |
| width: 1px; | |
| height: 10px; | |
| background-color: #64748b; | |
| } | |
| .marker-label { | |
| position: absolute; | |
| bottom: 15px; | |
| transform: translateX(-50%); | |
| font-size: 10px; | |
| color: #64748b; | |
| } | |
| .vector-arrow { | |
| position: absolute; | |
| width: 0; | |
| height: 0; | |
| border-left: 6px solid transparent; | |
| border-right: 6px solid transparent; | |
| border-bottom: 12px solid #3b82f6; | |
| bottom: 30px; | |
| transform-origin: 50% 100%; | |
| } | |
| .vector-line { | |
| position: absolute; | |
| height: 2px; | |
| background-color: #3b82f6; | |
| bottom: 30px; | |
| } | |
| @media (max-width: 640px) { | |
| .problem-container { | |
| flex-direction: column; | |
| } | |
| .solution-container { | |
| margin-top: 20px; | |
| margin-left: 0; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 min-h-screen"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <!-- Header --> | |
| <header class="bg-white shadow-sm rounded-lg p-6 mb-8 flex flex-col md:flex-row justify-between items-center"> | |
| <div class="flex items-center"> | |
| <div class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center mr-4"> | |
| <i class="fas fa-rocket text-blue-500 text-xl"></i> | |
| </div> | |
| <div> | |
| <h1 class="text-2xl font-bold text-gray-800">1D Motion Solver</h1> | |
| <p class="text-gray-600">Solve numericals for Motion in One Dimension (Class 11 Physics)</p> | |
| </div> | |
| </div> | |
| <button id="help-btn" class="mt-4 md:mt-0 px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition"> | |
| <i class="fas fa-question-circle mr-2"></i>Need Help? | |
| </button> | |
| </header> | |
| <div class="grid grid-cols-1 gap-6"> | |
| <!-- Problem Input Section --> | |
| <div class="bg-white shadow-sm rounded-lg overflow-hidden"> | |
| <div class="bg-blue-600 px-6 py-4"> | |
| <h2 class="text-xl font-semibold text-white">Enter Problem Details</h2> | |
| </div> | |
| <div class="p-6"> | |
| <div class="mb-6 grid grid-cols-1 md:grid-cols-3 gap-4"> | |
| <!-- Problem Type Selector --> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Problem Type</label> | |
| <select id="problem-type" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"> | |
| <option value="uniform">Uniform Motion</option> | |
| <option value="constant-acceleration">Motion with Constant Acceleration</option> | |
| <option value="free-fall">Free Fall</option> | |
| <option value="relative-motion">Relative Motion</option> | |
| </select> | |
| </div> | |
| <!-- Known Variables --> | |
| <div id="known-vars-container"> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Known Variables (comma separated)</label> | |
| <input type="text" id="known-vars" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" placeholder="e.g. u, a, t"> | |
| </div> | |
| <!-- Find Variable --> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Find</label> | |
| <select id="find-var" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"> | |
| <option value="s">Displacement (s)</option> | |
| <option value="u">Initial Velocity (u)</option> | |
| <option value="v">Final Velocity (v)</option> | |
| <option value="a">Acceleration (a)</option> | |
| <option value="t">Time (t)</option> | |
| </select> | |
| </div> | |
| </div> | |
| <!-- Values Input --> | |
| <div id="values-input-container" class="mb-6"> | |
| <!-- Will be dynamically generated based on known variables --> | |
| <div class="text-center text-gray-500"> | |
| Select your known variables first | |
| </div> | |
| </div> | |
| <!-- Action Buttons --> | |
| <div class="flex flex-wrap gap-3"> | |
| <button id="solve-btn" class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 flex items-center"> | |
| <i class="fas fa-calculator mr-2"></i> Solve | |
| </button> | |
| <button id="reset-btn" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 flex items-center"> | |
| <i class="fas fa-redo mr-2"></i> Reset | |
| </button> | |
| <button id="example-btn" class="px-4 py-2 bg-purple-100 text-purple-700 rounded-md hover:bg-purple-200 flex items-center"> | |
| <i class="fas fa-lightbulb mr-2"></i> Load Example | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Solution Display Section --> | |
| <div id="solution-section" class="bg-white shadow-sm rounded-lg overflow-hidden hidden"> | |
| <div class="bg-green-600 px-6 py-4"> | |
| <h2 class="text-xl font-semibold text-white flex items-center justify-between"> | |
| <span>Solution</span> | |
| <button id="expand-all" class="text-xs bg-green-700 px-2 py-1 rounded"> | |
| Expand All Steps | |
| </button> | |
| </h2> | |
| </div> | |
| <div class="p-6"> | |
| <div id="solution-steps" class="space-y-6"> | |
| <!-- Solution steps will be inserted here --> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Visualization Section --> | |
| <div id="visualization-section" class="hidden"> | |
| <div class="bg-white shadow-sm rounded-lg overflow-hidden"> | |
| <div class="bg-indigo-600 px-6 py-4"> | |
| <h2 class="text-xl font-semibold text-white">Visualization</h2> | |
| </div> | |
| <div class="p-6"> | |
| <!-- Motion Diagram --> | |
| <div class="mb-8"> | |
| <h3 class="text-lg font-medium text-gray-800 mb-3">Motion Diagram</h3> | |
| <div class="motion-diagram" id="motion-diagram"> | |
| <!-- Will be dynamically generated --> | |
| </div> | |
| </div> | |
| <!-- Charts --> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6"> | |
| <div> | |
| <h3 class="text-lg font-medium text-gray-800 mb-3">Position vs Time</h3> | |
| <canvas id="position-chart" height="250"></canvas> | |
| </div> | |
| <div> | |
| <h3 class="text-lg font-medium text-gray-800 mb-3">Velocity vs Time</h3> | |
| <canvas id="velocity-chart" height="250"></canvas> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Help Modal --> | |
| <div id="help-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden"> | |
| <div class="bg-white rounded-lg max-w-2xl w-full max-h-[90vh] overflow-y-auto"> | |
| <div class="bg-blue-600 px-6 py-4 flex justify-between items-center"> | |
| <h3 class="text-xl font-semibold text-white">Help Guide</h3> | |
| <button id="close-help" class="text-white hover:text-blue-100"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="p-6"> | |
| <h4 class="text-lg font-medium text-gray-800 mb-3">How to use this solver</h4> | |
| <ol class="list-decimal pl-5 space-y-3 mb-6"> | |
| <li class="pl-2">Select the type of motion problem you're solving (uniform, constant acceleration, etc.)</li> | |
| <li class="pl-2">Enter which variables you know (comma separated)</li> | |
| <li class="pl-2">Input the values for each known variable</li> | |
| <li class="pl-2">Choose the variable you want to find</li> | |
| <li class="pl-2">Click "Solve" to see the complete solution</li> | |
| <li class="pl-2">View the visualizations and graphs for better understanding</li> | |
| </ol> | |
| <h4 class="text-lg font-medium text-gray-800 mb-3">Variable Key</h4> | |
| <div class="mb-6 grid grid-cols-2 md:grid-cols-3 gap-3"> | |
| <div class="bg-gray-100 p-2 rounded"> | |
| <span class="font-mono font-bold">u</span>: Initial velocity (m/s) | |
| </div> | |
| <div class="bg-gray-100 p-2 rounded"> | |
| <span class="font-mono font-bold">v</span>: Final velocity (m/s) | |
| </div> | |
| <div class="bg-gray-100 p-2 rounded"> | |
| <span class="font-mono font-bold">a</span>: Acceleration (m/s²) | |
| </div> | |
| <div class="bg-gray-100 p-2 rounded"> | |
| <span class="font-mono font-bold">s</span>: Displacement (m) | |
| </div> | |
| <div class="bg-gray-100 p-2 rounded"> | |
| <span class="font-mono font-bold">t</span>: Time (s) | |
| </div> | |
| <div class="bg-gray-100 p-2 rounded"> | |
| <span class="font-mono font-bold">g</span>: Gravity (9.8 m/s²) | |
| </div> | |
| </div> | |
| <h4 class="text-lg font-medium text-gray-800 mb-3">Common Equations</h4> | |
| <div class="bg-gray-50 p-4 rounded-lg space-y-3"> | |
| <div class="equation-input p-3 rounded"> | |
| <span class="font-semibold">1.</span> v = u + at | |
| </div> | |
| <div class="equation-input p-3 rounded"> | |
| <span class="font-semibold">2.</span> s = ut + ½at² | |
| </div> | |
| <div class="equation-input p-3 rounded"> | |
| <span class="font-semibold">3.</span> v² = u² + 2as | |
| </div> | |
| <div class="equation-input p-3 rounded"> | |
| <span class="font-semibold">4.</span> s = (u + v)t/2 | |
| </div> | |
| <div class="equation-input p-3 rounded"> | |
| <span class="font-semibold">5.</span> For free fall: a = -g (if upward is positive) | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // DOM Elements | |
| const problemTypeSelect = document.getElementById('problem-type'); | |
| const knownVarsInput = document.getElementById('known-vars'); | |
| const valuesInputContainer = document.getElementById('values-input-container'); | |
| const solveBtn = document.getElementById('solve-btn'); | |
| const resetBtn = document.getElementById('reset-btn'); | |
| const exampleBtn = document.getElementById('example-btn'); | |
| const solutionSection = document.getElementById('solution-section'); | |
| const solutionSteps = document.getElementById('solution-steps'); | |
| const visualizationSection = document.getElementById('visualization-section'); | |
| const motionDiagram = document.getElementById('motion-diagram'); | |
| const helpBtn = document.getElementById('help-btn'); | |
| const helpModal = document.getElementById('help-modal'); | |
| const closeHelp = document.getElementById('close-help'); | |
| const expandAllBtn = document.getElementById('expand-all'); | |
| // Variables | |
| let positionChart, velocityChart; | |
| let autoExpandSteps = true; | |
| // Initialize | |
| setupKnownVarsListener(); | |
| // Event Listeners | |
| problemTypeSelect.addEventListener('change', updateKnownVarsOptions); | |
| solveBtn.addEventListener('click', solveProblem); | |
| resetBtn.addEventListener('click', resetProblem); | |
| exampleBtn.addEventListener('click', loadExample); | |
| helpBtn.addEventListener('click', () => helpModal.classList.remove('hidden')); | |
| closeHelp.addEventListener('click', () => helpModal.classList.add('hidden')); | |
| expandAllBtn.addEventListener('click', toggleExpandAll); | |
| // Listen for clicks on step titles to toggle content | |
| document.addEventListener('click', function(e) { | |
| if (e.target.classList.contains('step-title')) { | |
| const content = e.target.nextElementSibling; | |
| content.classList.toggle('hidden'); | |
| const icon = e.target.querySelector('i'); | |
| icon.classList.toggle('fa-chevron-down'); | |
| icon.classList.toggle('fa-chevron-up'); | |
| } | |
| }); | |
| // Functions | |
| function setupKnownVarsListener() { | |
| knownVarsInput.addEventListener('input', function() { | |
| const vars = this.value.replace(/\s/g, '').split(','); | |
| renderValueInputs(vars); | |
| }); | |
| } | |
| function updateKnownVarsOptions() { | |
| const problemType = problemTypeSelect.value; | |
| let options = []; | |
| switch(problemType) { | |
| case 'uniform': | |
| options = ['u', 'v', 's', 't']; | |
| break; | |
| case 'constant-acceleration': | |
| options = ['u', 'v', 'a', 's', 't']; | |
| break; | |
| case 'free-fall': | |
| knownVarsInput.value = 'u,v,s,t'; | |
| renderValueInputs(['u', 'v', 's', 't']); | |
| document.getElementById('find-var').value = 'a'; | |
| return; | |
| case 'relative-motion': | |
| options = ['u1', 'u2', 'v1', 'v2', 'a1', 'a2', 't']; | |
| break; | |
| } | |
| knownVarsInput.value = options.join(','); | |
| renderValueInputs(options); | |
| } | |
| function renderValueInputs(vars) { | |
| valuesInputContainer.innerHTML = ''; | |
| if (vars.length === 0 || (vars.length === 1 && vars[0] === '')) { | |
| valuesInputContainer.innerHTML = '<div class="text-center text-gray-500">Select your known variables first</div>'; | |
| return; | |
| } | |
| vars.forEach(variable => { | |
| if (variable === '') return; | |
| const div = document.createElement('div'); | |
| div.className = 'mb-4'; | |
| let label, unit = ''; | |
| switch(variable) { | |
| case 'u': | |
| label = 'Initial Velocity'; | |
| unit = 'm/s'; | |
| break; | |
| case 'v': | |
| label = 'Final Velocity'; | |
| unit = 'm/s'; | |
| break; | |
| case 'a': | |
| label = 'Acceleration'; | |
| unit = 'm/s²'; | |
| break; | |
| case 's': | |
| label = 'Displacement'; | |
| unit = 'm'; | |
| break; | |
| case 't': | |
| label = 'Time'; | |
| unit = 's'; | |
| break; | |
| case 'u1': | |
| label = 'Initial Velocity (Object 1)'; | |
| unit = 'm/s'; | |
| break; | |
| case 'u2': | |
| label = 'Initial Velocity (Object 2)'; | |
| unit = 'm/s'; | |
| break; | |
| case 'v1': | |
| label = 'Final Velocity (Object 1)'; | |
| unit = 'm/s'; | |
| break; | |
| case 'v2': | |
| label = 'Final Velocity (Object 2)'; | |
| unit = 'm/s'; | |
| break; | |
| case 'a1': | |
| label = 'Acceleration (Object 1)'; | |
| unit = 'm/s²'; | |
| break; | |
| case 'a2': | |
| label = 'Acceleration (Object 2)'; | |
| unit = 'm/s²'; | |
| break; | |
| default: | |
| label = variable; | |
| } | |
| div.innerHTML = ` | |
| <label class="block text-sm font-medium text-gray-700 mb-1">${label} (${variable}) <span class="text-gray-500">${unit}</span></label> | |
| <input type="number" id="val-${variable}" step="any" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" placeholder="Enter value"> | |
| `; | |
| valuesInputContainer.appendChild(div); | |
| }); | |
| } | |
| function solveProblem() { | |
| // Clear previous solution | |
| solutionSteps.innerHTML = ''; | |
| solutionSection.classList.remove('hidden'); | |
| visualizationSection.classList.remove('hidden'); | |
| // Get problem parameters | |
| const problemType = problemTypeSelect.value; | |
| const knownVars = knownVarsInput.value.replace(/\s/g, '').split(','); | |
| const findVar = document.getElementById('find-var').value; | |
| const values = {}; | |
| knownVars.forEach(v => { | |
| if (v === '') return; | |
| const input = document.getElementById(`val-${v}`); | |
| values[v] = input ? parseFloat(input.value) : 0; | |
| }); | |
| // Solve based on problem type | |
| switch(problemType) { | |
| case 'uniform': | |
| case 'constant-acceleration': | |
| solveKinematicsProblem(problemType, knownVars, findVar, values); | |
| break; | |
| case 'free-fall': | |
| solveFreeFallProblem(knownVars, findVar, values); | |
| break; | |
| case 'relative-motion': | |
| solveRelativeMotionProblem(knownVars, findVar, values); | |
| break; | |
| } | |
| // Scroll to solution | |
| solutionSection.scrollIntoView({ behavior: 'smooth' }); | |
| } | |
| function solveKinematicsProblem(problemType, knownVars, findVar, values) { | |
| // Extract values with defaults | |
| const u = values.u || 0; | |
| const v = values.v || 0; | |
| const a = problemType === 'uniform' ? 0 : (values.a || 0); | |
| const s = values.s || 0; | |
| const t = values.t || 0; | |
| let result; | |
| let steps = []; | |
| // Create initial diagram | |
| createMotionDiagram([u, v], a, s, t); | |
| switch(findVar) { | |
| case 's': | |
| steps.push(`<div class="step"><div class="step-title cursor-pointer flex items-center justify-between bg-blue-50 p-3 rounded-t-md"><span class="font-medium">Step 1: Identify the known variables</span><i class="fas fa-chevron-down"></i></div><div class="${autoExpandSteps ? '' : 'hidden'} bg-blue-50 rounded-b-md p-3 border-t border-blue-100">We know: initial velocity (u = ${u} m/s), ${v !== 0 ? 'final velocity (v = ' + v + ' m/s), ' : ''}${a !== 0 ? 'acceleration (a = ' + a + ' m/s²), ' : ''}${t !== 0 ? 'time (t = ' + t + ' s)' : ''}</div></div>`); | |
| if (u && v && t) { | |
| // Equation: s = (u + v)t/2 | |
| result = (u + v) * t / 2; | |
| steps.push(`<div class="step"><div class="step-title cursor-pointer flex items-center justify-between bg-blue-50 p-3 rounded-t-md"><span class="font-medium">Step 2: Use equation s = (u + v)t/2</span><i class="fas fa-chevron-down"></i></div><div class="${autoExpandSteps ? '' : 'hidden'} bg-blue-50 rounded-b-md p-3 border-t border-blue-100">s = (${u} + ${v}) × ${t} / 2 = ${(u + v) * t / 2} m</div></div>`); | |
| } else if (u && t && a) { | |
| // Equation: s = ut + ½at² | |
| result = u * t + 0.5 * a * t * t; | |
| steps.push(`<div class="step"><div class="step-title cursor-pointer flex items-center justify-between bg-blue-50 p-3 rounded-t-md"><span class="font-medium">Step 2: Use equation s = ut + ½at²</span><i class="fas fa-chevron-down"></i></div><div class="${autoExpandSteps ? '' : 'hidden'} bg-blue-50 rounded-b-md p-3 border-t border-blue-100">s = ${u} × ${t} + 0.5 × ${a} × ${t}² = ${u * t} + ${0.5 * a * t * t} = ${result} m</div></div>`); | |
| } else if (u && v && a) { | |
| // Equation: v² = u² + 2as → s = (v² - u²)/2a | |
| result = (v * v - u * u) / (2 * a); | |
| steps.push(`<div class="step"><div class="step-title cursor-pointer flex items-center justify-between bg-blue-50 p-3 rounded-t-md"><span class="font-medium">Step 2: Use equation v² = u² + 2as</span><i class="fas fa-chevron-down"></i></div><div class="${autoExpandSteps ? '' : 'hidden'} bg-blue-50 rounded-b-md p-3 border-t border-blue-100">Rearranged to: s = (v² - u²)/2a = (${v}² - ${u}²)/(2 × ${a}) = ${result} m</div></div>`); | |
| } | |
| break; | |
| case 'v': | |
| if (u && a && t) { | |
| // Equation: v = u + at | |
| result = u + a * t; | |
| steps.push(`<div class="step"><div class="step-title cursor-pointer flex items-center justify-between bg-blue-50 p-3 rounded-t-md"><span class="font-medium">Step 2: Use equation v = u + at</span><i class="fas fa-chevron-down"></i></div><div class="${autoExpandSteps ? '' : 'hidden'} bg-blue-50 rounded-b-md p-3 border-t border-blue-100">v = ${u} + ${a} × ${t} = ${result} m/s</div></div>`); | |
| } else if (u && a && s) { | |
| // Equation: v² = u² + 2as | |
| result = Math.sqrt(u * u + 2 * a * s); | |
| steps.push(`<div class="step"><div class="step-title cursor-pointer flex items-center justify-between bg-blue-50 p-3 rounded-t-md"><span class="font-medium">Step 2: Use equation v² = u² + 2as</span><i class="fas fa-chevron-down"></i></div><div class="${autoExpandSteps ? '' : 'hidden'} bg-blue-50 rounded-b-md p-3 border-t border-blue-100">v = √(u² + 2as) = √(${u}² + 2 × ${a} × ${s}) = √(${u*u} + ${2*a*s}) = ${result} m/s</div></div>`); | |
| } | |
| break; | |
| // Other cases similar to above | |
| default: | |
| result = "Cannot solve for this variable with given information"; | |
| } | |
| // Add final answer | |
| if (result !== undefined) { | |
| steps.push(` | |
| <div class="bg-green-100 border-l-4 border-green-500 p-4"> | |
| <h3 class="font-bold text-green-800 mb-1">Final Answer</h3> | |
| <p class="text-green-700">${findVar.toUpperCase()} = ${result} ${findVar === 'a' ? 'm/s²' : findVar === 't' ? 's' : 'm' + (findVar === 's' ? '' : '/s')}</p> | |
| </div> | |
| `); | |
| } | |
| // Render steps | |
| solutionSteps.innerHTML = steps.join(''); | |
| // Create charts | |
| createCharts(problemType, u, v, a, s, t, result); | |
| } | |
| function solveFreeFallProblem(knownVars, findVar, values) { | |
| const u = values.u || 0; | |
| const v = values.v || 0; | |
| const s = values.s || 0; | |
| const t = values.t || 0; | |
| let result; | |
| let steps = []; | |
| // For free fall, acceleration is -9.8 m/s² (assuming upward as positive) | |
| const g = 9.8; | |
| const a = -g; | |
| // Create initial diagram (modified for free fall) | |
| createMotionDiagram([u, v], a, s, t, true); | |
| steps.push(`<div class="step"><div class="step-title cursor-pointer flex items-center justify-between bg-blue-50 p-3 rounded-t-md"><span class="font-medium">Step 1: Recognize this as free fall under gravity</span><i class="fas fa-chevron-down"></i></div><div class="${autoExpandSteps ? '' : 'hidden'} bg-blue-50 rounded-b-md p-3 border-t border-blue-100">Acceleration due to gravity (a) = -g = -9.8 m/s² (taking upward direction as positive)</div></div>`); | |
| switch(findVar) { | |
| case 'a': | |
| result = -g; | |
| steps.push(`<div class="step"><div class="step-title cursor-pointer flex items-center justify-between bg-blue-50 p-3 rounded-t-md"><span class="font-medium">Step 2: Free fall acceleration</span><i class="fas fa-chevron-down"></i></div><div class="${autoExpandSteps ? '' : 'hidden'} bg-blue-50 rounded-b-md p-3 border-t border-blue-100">In free fall near Earth's surface, acceleration = -g = -9.8 m/s² (positive direction is upward)</div></div>`); | |
| break; | |
| case 'v': | |
| if (u && t) { | |
| // v = u - gt | |
| result = u - g * t; | |
| steps.push(`<div class="step"><div class="step-title cursor-pointer flex items-center justify-between bg-blue-50 p-3 rounded-t-md"><span class="font-medium">Step 2: Use equation v = u - gt</span><i class="fas fa-chevron-down"></i></div><div class="${autoExpandSteps ? '' : 'hidden'} bg-blue-50 rounded-b-md p-3 border-t border-blue-100">v = ${u} - 9.8 × ${t} = ${result} m/s</div></div>`); | |
| } | |
| break; | |
| case 's': | |
| if (u && t) { | |
| // s = ut - ½gt² | |
| result = u * t - 0.5 * g * t * t; | |
| steps.push(`<div class="step"><div class="step-title cursor-pointer flex items-center justify-between bg-blue-50 p-3 rounded-t-md"><span class="font-medium">Step 2: Use equation s = ut - ½gt²</span><i class="fas fa-chevron-down"></i></div><div class="${autoExpandSteps ? '' : 'hidden'} bg-blue-50 rounded-b-md p-3 border-t border-blue-100">s = ${u} × ${t} - 0.5 × 9.8 × ${t}² = ${u*t} - ${0.5*g*t*t} = ${result} m</div></div>`); | |
| } | |
| break; | |
| } | |
| // Add final answer | |
| if (result !== undefined) { | |
| steps.push(` | |
| <div class="bg-green-100 border-l-4 border-green-500 p-4"> | |
| <h3 class="font-bold text-green-800 mb-1">Final Answer</h3> | |
| <p class="text-green-700">${findVar.toUpperCase()} = ${result} ${findVar === 'a' ? 'm/s²' : findVar === 't' ? 's' : 'm' + (findVar === 's' ? '' : '/s')}</p> | |
| </div> | |
| `); | |
| } | |
| solutionSteps.innerHTML = steps.join(''); | |
| createCharts('free-fall', u, v, a, s, t, result); | |
| } | |
| function solveRelativeMotionProblem(knownVars, findVar, values) { | |
| // Simplified relative motion example | |
| solutionSteps.innerHTML = ` | |
| <div class="bg-yellow-100 border-l-4 border-yellow-500 p-4"> | |
| <h3 class="font-bold text-yellow-800">Relative Motion Solution</h3> | |
| <p class="text-yellow-700">This feature is under development. For now, please use other motion types.</p> | |
| </div> | |
| `; | |
| } | |
| function createMotionDiagram(velocities, acceleration, displacement, time, isFreeFall = false) { | |
| motionDiagram.innerHTML = ''; | |
| // Create position markers | |
| const markersContainer = document.createElement('div'); | |
| markersContainer.className = 'position-markers'; | |
| motionDiagram.appendChild(markersContainer); | |
| // Create 5 position markers (0-4) | |
| for (let i = 0; i < 5; i++) { | |
| const marker = document.createElement('div'); | |
| marker.className = 'marker'; | |
| marker.style.left = `${(i / 4) * 95 + 2.5}%`; | |
| markersContainer.appendChild(marker); | |
| const label = document.createElement('div'); | |
| label.className = 'marker-label'; | |
| label.style.left = `${(i / 4) * 95 + 2.5}%`; | |
| label.textContent = `${i * (displacement / 4 || 1)} m`; | |
| markersContainer.appendChild(label); | |
| } | |
| // Create object | |
| const object = document.createElement('div'); | |
| object.className = 'object'; | |
| object.id = 'moving-object'; | |
| motionDiagram.appendChild(object); | |
| // Create velocity vectors if they exist | |
| if (velocities && velocities.length > 0) { | |
| velocities.forEach((velocity, index) => { | |
| if (velocity !== 0) { | |
| const vectorLine = document.createElement('div'); | |
| vectorLine.className = 'vector-line'; | |
| vectorLine.style.width = `${Math.min(Math.abs(velocity) * 5, 50)}px`; | |
| vectorLine.style.left = `${index === 0 ? '5%' : '95%'}`; | |
| vectorLine.style.transform = `translateX(${velocity > 0 ? 0 : '-100%'})`; | |
| const vectorArrow = document.createElement('div'); | |
| vectorArrow.className = 'vector-arrow'; | |
| vectorArrow.style.left = `${index === 0 ? '5%' : '95%'}`; | |
| vectorArrow.style.transform = `translateX(${velocity > 0 ? 0 : '-100%'}) ${velocity > 0 ? 'rotate(0)' : 'rotate(180deg)'}`; | |
| motionDiagram.appendChild(vectorLine); | |
| motionDiagram.appendChild(vectorArrow); | |
| // Add velocity label | |
| const vectorLabel = document.createElement('div'); | |
| vectorLabel.className = 'absolute text-xs text-blue-700'; | |
| vectorLabel.textContent = `v=${velocity} m/s`; | |
| vectorLabel.style.bottom = '50px'; | |
| vectorLabel.style.left = `${index === 0 ? '5%' : '95%'}`; | |
| vectorLabel.style.transform = `translateX(${velocity > 0 ? 0 : '-100%'})`; | |
| motionDiagram.appendChild(vectorLabel); | |
| } | |
| }); | |
| } | |
| // Create acceleration indicator if it exists | |
| if (acceleration && acceleration !== 0) { | |
| const accelLabel = document.createElement('div'); | |
| accelLabel.className = 'absolute font-bold text-xs'; | |
| accelLabel.style.top = '10px'; | |
| accelLabel.style.left = '50%'; | |
| accelLabel.style.transform = 'translateX(-50%)'; | |
| if (isFreeFall) { | |
| accelLabel.textContent = 'g = 9.8 m/s² ↓'; | |
| accelLabel.style.color = '#ef4444'; | |
| } else { | |
| accelLabel.textContent = `a = ${Math.abs(acceleration)} m/s² ${acceleration > 0 ? '→' : '←'}`; | |
| accelLabel.style.color = '#3b82f6'; | |
| } | |
| motionDiagram.appendChild(accelLabel); | |
| } | |
| // Animate the motion if time is provided | |
| if (time && time > 0) { | |
| setTimeout(() => { | |
| const obj = document.getElementById('moving-object'); | |
| obj.style.left = '95%'; | |
| // Create a dot at the start position | |
| const startMark = document.createElement('div'); | |
| startMark.className = 'absolute w-2 h-2 bg-gray-800 rounded-full bottom-10'; | |
| startMark.style.left = '5%'; | |
| motionDiagram.appendChild(startMark); | |
| // Create a dot at the end position | |
| const endMark = document.createElement('div'); | |
| endMark.className = 'absolute w-2 h-2 bg-gray-800 rounded-full bottom-10'; | |
| endMark.style.left = '95%'; | |
| motionDiagram.appendChild(endMark); | |
| }, 100); | |
| } | |
| } | |
| function createCharts(problemType, u, v, a, s, t, result) { | |
| // Destroy previous charts if they exist | |
| if (positionChart) positionChart.destroy(); | |
| if (velocityChart) velocityChart.destroy(); | |
| // Generate time points | |
| const timeSteps = 20; | |
| const timePoints = []; | |
| const timeInterval = t ? t / timeSteps : 2; // Default to 2s if time not specified | |
| for (let i = 0; i <= timeSteps; i++) { | |
| timePoints.push(i * (t ? (t / timeSteps) : timeInterval)); | |
| } | |
| // Calculate position and velocity at each time point | |
| const positionData = []; | |
| const velocityData = []; | |
| timePoints.forEach(time => { | |
| let pos, vel; | |
| if (problemType === 'uniform') { | |
| pos = u * time; | |
| vel = u; | |
| } else if (problemType === 'free-fall') { | |
| pos = u * time - 0.5 * 9.8 * time * time; | |
| vel = u - 9.8 * time; | |
| } else { | |
| // Constant acceleration | |
| pos = u * time + 0.5 * a * time * time; | |
| vel = u + a * time; | |
| } | |
| positionData.push(pos); | |
| velocityData.push(vel); | |
| }); | |
| // Position vs Time Chart | |
| const positionCtx = document.getElementById('position-chart').getContext('2d'); | |
| positionChart = new Chart(positionCtx, { | |
| type: 'line', | |
| data: { | |
| labels: timePoints.map(t => t.toFixed(1)), | |
| datasets: [{ | |
| label: 'Position (m)', | |
| data: positionData, | |
| borderColor: '#3b82f6', | |
| backgroundColor: 'rgba(59, 130, 246, 0.1)', | |
| borderWidth: 2, | |
| fill: true, | |
| tension: 0.1 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| plugins: { | |
| title: { | |
| display: true, | |
| text: 'Position vs Time' | |
| } | |
| }, | |
| scales: { | |
| x: { | |
| title: { | |
| display: true, | |
| text: 'Time (s)' | |
| } | |
| }, | |
| y: { | |
| title: { | |
| display: true, | |
| text: 'Position (m)' | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| // Velocity vs Time Chart | |
| const velocityCtx = document.getElementById('velocity-chart').getContext('2d'); | |
| velocityChart = new Chart(velocityCtx, { | |
| type: 'line', | |
| data: { | |
| labels: timePoints.map(t => t.toFixed(1)), | |
| datasets: [{ | |
| label: 'Velocity (m/s)', | |
| data: velocityData, | |
| borderColor: '#ef4444', | |
| backgroundColor: 'rgba(239, 68, 68, 0.1)', | |
| borderWidth: 2, | |
| fill: true, | |
| tension: 0.1 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| plugins: { | |
| title: { | |
| display: true, | |
| text: 'Velocity vs Time' | |
| } | |
| }, | |
| scales: { | |
| x: { | |
| title: { | |
| display: true, | |
| text: 'Time (s)' | |
| } | |
| }, | |
| y: { | |
| title: { | |
| display: true, | |
| text: 'Velocity (m/s)' | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| function resetProblem() { | |
| knownVarsInput.value = ''; | |
| valuesInputContainer.innerHTML = '<div class="text-center text-gray-500">Select your known variables first</div>'; | |
| solutionSection.classList.add('hidden'); | |
| visualizationSection.classList.add('hidden'); | |
| motionDiagram.innerHTML = ''; | |
| if (positionChart) positionChart.destroy(); | |
| if (velocityChart) velocityChart.destroy(); | |
| } | |
| function loadExample() { | |
| const problemType = problemTypeSelect.value; | |
| switch(problemType) { | |
| case 'uniform': | |
| knownVarsInput.value = 'u,t'; | |
| renderValueInputs(['u', 't']); | |
| const uInput = document.getElementById('val-u'); | |
| const tInput = document.getElementById('val-t'); | |
| if (uInput) uInput.value = '10'; | |
| if (tInput) tInput.value = '5'; | |
| document.getElementById('find-var').value = 's'; | |
| break; | |
| case 'constant-acceleration': | |
| knownVarsInput.value = 'u,a,t'; | |
| renderValueInputs(['u', 'a', 't']); | |
| const uCAInput = document.getElementById('val-u'); | |
| const aInput = document.getElementById('val-a'); | |
| const tCAInput = document.getElementById('val-t'); | |
| if (uCAInput) uCAInput.value = '5'; | |
| if (aInput) aInput.value = '2'; | |
| if (tCAInput) tCAInput.value = '4'; | |
| document.getElementById('find-var').value = 'v'; | |
| break; | |
| case 'free-fall': | |
| knownVarsInput.value = 'u,t'; | |
| renderValueInputs(['u', 't']); | |
| const uFFInput = document.getElementById('val-u'); | |
| const tFFInput = document.getElementById('val-t'); | |
| if (uFFInput) uFFInput.value = '20'; | |
| if (tFFInput) tFFInput.value = '3'; | |
| document.getElementById('find-var').value = 'v'; | |
| break; | |
| } | |
| } | |
| function toggleExpandAll() { | |
| autoExpandSteps = !autoExpandSteps; | |
| const steps = document.querySelectorAll('.step .step-title + div'); | |
| steps.forEach(step => { | |
| step.classList.toggle('hidden'); | |
| }); | |
| const icons = document.querySelectorAll('.step-title i'); | |
| icons.forEach(icon => { | |
| icon.classList.toggle('fa-chevron-down'); | |
| icon.classList.toggle('fa-chevron-up'); | |
| }); | |
| expandAllBtn.textContent = autoExpandSteps ? 'Collapse All Steps' : 'Expand All Steps'; | |
| } | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=AARIFSHABIR/motion" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |