{"version":3,"sources":["component/Snake/SnakesAlive.tsx","component/ElasticCollisions/Histogram.tsx","vectors.ts","component/ElasticCollisions/elasticCollisionsSimulator.ts","component/ElasticCollisions/SpriteCtrl.tsx","component/ElasticCollisions/SpriteSimulatorCtrl.tsx","component/ElasticCollisions/model.ts","component/ElasticCollisions/BouncingSprites.tsx","component/ElasticCollisions/GasSimulation.tsx","component/Snake/snake.ts","component/PlanetSimulation/planets.ts","component/PlanetSimulation/PlanetOrbit.tsx","component/Rope/ropeSimulation.ts","component/Rope/Rope.tsx","App.tsx","serviceWorker.js","index.js"],"names":["lastUpdate","getMagnitude","vector","Math","sqrt","x","y","addVectors","vector1","vector2","subtractVectors","dotProduct","scaleVector","scale","createRandonVector","magnitude","random","convertToUnitVector","simulationSpeeds","speed","timeInterval","updatePosition","sprite","environment","deltaVelocity","gravity","position","velocity","performCollisions","sprites","collisions","i","length","sprite1","j","sprite2","deltaX","deltaY","size","push","getCollisions","collision","v1Final","getNewVelocityVectory","v2Final","deltaVelecity","deltaPosition","lengthV1","lengthV2","temp","acos","getAngle","distance","dotProd","numerator","mass","denominator","tempVector","getEnergy","map","v","BallSpriteRenderCtrl","key","name","width","height","cx","cy","r","style","fill","color","stroke","strokeWidth","opacity","CatSpriteRenderCtrl","center","stroke-width","transform","rotation","viewBox","d","ManSpriteRenderCtrl","id","y2","x2","y1","x1","find","s","SpriteSimulatorCtrl","spriteGenerator","useState","setCounter","spriteCount","setSpriteCount","running","setRunning","spriteType","setSpriteType","simulationSpeed","setSimulationSpeed","doSimulationTimeStepCB","useCallback","forEach","abs","doBoundaries","rotationSpeed","updateRotation","useEffect","interval","setInterval","count","clearInterval","areaHeight","areaWidth","window","innerWidth","innerHeight","className","onClick","val","prev","onChange","e","countStr","Number","parseInt","onCountOfBallsChanged","currentTarget","value","speedType","onSimulationSpeedChanged","type","sType","onSpriteTypeChanged","index","SpriteRenderCtrl","getSpriteRenderCtrl","colors","generateSprites","ceil","xPos","YPos","BouncingSprites","Histogram","ref","useRef","svg","select","current","diff","Date","now","data","xScale","scaleLinear","domain","range","remove","append","attr","call","axisBottom","bins","histogram","thresholds","ticks","getHist","numBins","yScale","max","selectAll","enter","x0","tempLength","getHeight","createSprites","spacing","rowCount","colCount","row","col","doContainerBoundaries","heatType","doHeatingCooling","GasSimulation","setHeatType","totalEnergy","setTotalEnergy","energy","reduce","acc","SpritesCtrl","scaleHeight","SpriteCtrl","getRandom","min","nextColorComp","comp","inc","c","createSnake","minX","maxX","minY","maxY","direction","PI","directionVector","cos","sin","body","bodyColor","g","b","turnSnake","snake","turn","splice","headPos","posX","posY","margin","snakes","masterSnake","SnakesAlive","changeRandomDirection","handleKeyPress","event","addEventListener","removeEventListener","idx","RenderSnake","seg","RenderMasterSnake","getScenario","scenarioType","getScenario1","getScenario2","getScenario3","Error","planets","centre","planet","deltaV","planet1","diffVect","unitVect","forceOfGravity","gravityDeltaV","getGravityDeltaV","deltaPos1","deltaPos2","scenario","PlanetOrbit","setScenarioType","scaleFactor","newScenarioType","PlanetCtrl","updatePoint","pointIndex","rope","simulation","point","points","pointLS","undefined","pointRS","forceLS","calculateForceVector","tempV","forceRS","point2","separation","deltaPosUnitVector","ES","RopeCtrl","updateAllPoints","PointCtrl","App","path","to","href","Boolean","location","hostname","match","ReactDOM","render","StrictMode","document","getElementById","navigator","serviceWorker","ready","then","registration","unregister","catch","error","console","message"],"mappings":"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","file":"static/js/main.a66538c8.chunk.js","sourcesContent":["import React, { useCallback, useEffect, useState } from \"react\";\r\nimport {\r\n Snake,\r\n createSnake,\r\n updatePosition,\r\n changeRandomDirection,\r\n turnSnake,\r\n nextColorComp,\r\n} from \"./snake\";\r\n\r\nconst margin = 50;\r\nconst numberOfSnakes = 10;\r\nconst minX = margin / 2;\r\nconst minY = margin / 2;\r\nconst maxX = window.innerWidth - margin / 2;\r\nconst maxY = window.innerHeight - margin / 2;\r\nconst snakes: Snake[] = [];\r\nconst masterSnake = createSnake(minX, maxX, minY, maxY);\r\n\r\nfor (let i = 0; i < numberOfSnakes; i++)\r\n snakes.push(createSnake(minX, maxX, minY, maxY));\r\n\r\nexport const SnakesAlive = () => {\r\n const [, setCounter] = useState(0);\r\n\r\n const doSimulationTimeStepCB = useCallback(() => {\r\n snakes.forEach((snake) => {\r\n updatePosition(snake, minX, maxX, minY, maxY);\r\n changeRandomDirection(snake);\r\n });\r\n updatePosition(masterSnake, minX, maxX, minY, maxY);\r\n updatePosition(masterSnake, minX, maxX, minY, maxY);\r\n setCounter((count) => count + 1);\r\n }, []);\r\n\r\n useEffect(() => {\r\n const interval = setInterval(() => {\r\n doSimulationTimeStepCB();\r\n }, 50);\r\n return () => clearInterval(interval);\r\n }, [doSimulationTimeStepCB]);\r\n\r\n const handleKeyPress = (event: any) => {\r\n const snake = snakes[0];\r\n\r\n if (event.key === \",\") {\r\n turnSnake(masterSnake, -0.3);\r\n } else if (event.key === \".\") {\r\n turnSnake(masterSnake, 0.3);\r\n }\r\n\r\n snake.directionVector = {\r\n deltaX: Math.cos(snake.direction),\r\n deltaY: Math.sin(snake.direction),\r\n };\r\n };\r\n\r\n useEffect(() => {\r\n window.addEventListener(\"keydown\", handleKeyPress);\r\n return () => {\r\n window.removeEventListener(\"keydown\", handleKeyPress);\r\n };\r\n }, []);\r\n\r\n return (\r\n
\r\n \r\n \r\n\r\n {}\r\n {snakes.map((s, idx) => (\r\n \r\n ))}\r\n \r\n
\r\n );\r\n};\r\n\r\nconst RenderSnake = ({ snake }: { snake: Snake }) => {\r\n let r = snake.bodyColor.r;\r\n let g = snake.bodyColor.g;\r\n let b = snake.bodyColor.b;\r\n return (\r\n <>\r\n {snake.body.map((seg, idx) => (\r\n \r\n ))}\r\n \r\n );\r\n};\r\n\r\nconst RenderMasterSnake = ({ snake }: { snake: Snake }) => {\r\n return (\r\n <>\r\n {snake.body.map((seg, idx) => (\r\n \r\n ))}\r\n \r\n );\r\n};\r\n","import React, { useRef } from \"react\";\r\n\r\nimport d3, { max, select, scaleLinear, histogram, axisBottom } from \"d3\";\r\nimport { getEnergy } from \"./elasticCollisionsSimulator\";\r\nimport { Sprite, Environment } from \"./model\";\r\n\r\nlet lastUpdate: number;\r\n\r\nexport const Histogram = ({\r\n sprites,\r\n environment,\r\n}: {\r\n sprites: Sprite[];\r\n environment: Environment;\r\n}) => {\r\n const ref = useRef(null);\r\n const svg = select(ref.current);\r\n\r\n var margin = { top: 10, right: 30, bottom: 30, left: 40 };\r\n const width = 400 - margin.left - margin.right;\r\n const height = 300 - margin.top - margin.bottom;\r\n\r\n let diff = 0;\r\n if (lastUpdate) diff = Date.now() - lastUpdate;\r\n\r\n if (diff > 1000 || !lastUpdate) {\r\n lastUpdate = Date.now();\r\n\r\n const data = getEnergy(sprites, environment);\r\n\r\n //const maxVal = (max(data) || 100) + 50;\r\n const maxVal = 20000;\r\n const minVal = 0;\r\n //const minVal = min(data) || 0;\r\n //const minVal = 0;\r\n //const maxVal = 100;\r\n const xScale = scaleLinear()\r\n .domain([minVal, maxVal])\r\n .range([0, 600]);\r\n\r\n svg.select(\"g\").remove();\r\n\r\n svg\r\n .append(\"g\")\r\n .attr(\"transform\", \"translate(0,\" + height + \")\")\r\n .call(axisBottom(xScale));\r\n\r\n var getHist = histogram()\r\n .domain([minVal, maxVal]) // then the domain of the graphic\r\n .thresholds(xScale.ticks(70)); // then the numbers of bins\r\n\r\n var bins = getHist(data);\r\n\r\n const numBins = bins.length;\r\n const yScale = scaleLinear()\r\n .domain([0, max(bins, (d: any) => d.length)])\r\n .range([height, 0]);\r\n\r\n //svg.append(\"g\").attr(\"transform\", \"translate(0,0)\").call(axisLeft(yScale));\r\n\r\n const getHeight = (d: d3.Bin) => {\r\n const tempLength = yScale(d.length);\r\n return height - (tempLength || 0);\r\n };\r\n\r\n const getWidth = (d: d3.Bin) => {\r\n return width / numBins - 2;\r\n };\r\n\r\n svg.selectAll(\"rect\").remove();\r\n\r\n svg\r\n .selectAll(\"rect\")\r\n .data(bins)\r\n .enter()\r\n .append(\"rect\")\r\n .attr(\"x\", 1)\r\n .attr(\"transform\", (d) => {\r\n return \"translate(\" + xScale(d.x0 || 0) + \",\" + yScale(d.length) + \")\";\r\n })\r\n .attr(\"width\", width / numBins)\r\n .attr(\"height\", (d) => getHeight(d))\r\n .style(\"fill\", \"#69b3a2\");\r\n }\r\n\r\n return (\r\n
\r\n \r\n \r\n \r\n
\r\n );\r\n};\r\n","import { Vector } from \"./component/ElasticCollisions/model\";\r\n\r\nexport const getAngle = (vector1: Vector, vector2: Vector) => {\r\n const lengthV1 = getMagnitude(vector1);\r\n const lengthV2 = getMagnitude(vector2);\r\n const temp = dotProduct(vector1, vector2) / (lengthV1 * lengthV2);\r\n return Math.acos(temp);\r\n};\r\n\r\nexport const getMagnitude = (vector: Vector) => {\r\n return Math.sqrt(vector.x * vector.x + vector.y * vector.y);\r\n};\r\n\r\nexport const addVectors = (vector1: Vector, vector2: Vector): Vector => {\r\n return { x: vector1.x + vector2.x, y: vector1.y + vector2.y };\r\n};\r\n\r\nexport const subtractVectors = (vector1: Vector, vector2: Vector): Vector => {\r\n return { x: vector1.x - vector2.x, y: vector1.y - vector2.y };\r\n};\r\n\r\nexport const dotProduct = (vector1: Vector, vector2: Vector): number => {\r\n return vector1.x * vector2.x + vector1.y * vector2.y;\r\n};\r\n\r\nexport const scaleVector = (vector1: Vector, scale: number): Vector => {\r\n return { x: vector1.x * scale, y: vector1.y * scale };\r\n};\r\n\r\nexport const createRandonVector = (magnitude: number) => {\r\n return {\r\n x: (Math.random() - 0.5) * magnitude,\r\n y: (Math.random() - 0.5) * magnitude,\r\n };\r\n};\r\n\r\nexport const convertToUnitVector = (vector: Vector): Vector => {\r\n const magnitude = getMagnitude(vector);\r\n if (magnitude === 0) return { x: 0, y: 0 };\r\n return { x: vector.x / magnitude, y: vector.y / magnitude };\r\n};\r\n","import {\r\n subtractVectors,\r\n getAngle,\r\n dotProduct,\r\n scaleVector,\r\n getMagnitude,\r\n} from \"../../vectors\";\r\nimport { Sprite, Environment, Collision, Vector } from \"./model\";\r\n\r\nexport type SpeedType =\r\n | \"Very Slow\"\r\n | \"Slow\"\r\n | \"Normal\"\r\n | \"Fast\"\r\n | \"Very Fast\"\r\n | \"Flat Out\";\r\n\r\nexport interface SpeedMapType {\r\n speed: SpeedType;\r\n timeInterval: number;\r\n}\r\n\r\nexport const simulationSpeeds: SpeedMapType[] = [\r\n {\r\n speed: \"Very Slow\",\r\n timeInterval: 0.01,\r\n },\r\n {\r\n speed: \"Slow\",\r\n timeInterval: 0.02,\r\n },\r\n {\r\n speed: \"Normal\",\r\n timeInterval: 0.03,\r\n },\r\n {\r\n speed: \"Fast\",\r\n timeInterval: 0.04,\r\n },\r\n {\r\n speed: \"Very Fast\",\r\n timeInterval: 0.05,\r\n },\r\n {\r\n speed: \"Flat Out\",\r\n timeInterval: 0.07,\r\n },\r\n];\r\n\r\nexport const doBoundaries = (sprite: Sprite, environment: Environment) => {\r\n if (sprite.position.x - sprite.size < 0 && sprite.velocity.x < 0) {\r\n sprite.velocity.x = -1 * sprite.velocity.x;\r\n }\r\n\r\n if (\r\n sprite.position.x + sprite.size > environment.width &&\r\n sprite.velocity.x > 0\r\n ) {\r\n sprite.velocity.x = -1 * sprite.velocity.x;\r\n }\r\n\r\n if (sprite.position.y + sprite.size > environment.height) {\r\n sprite.velocity.y = -1 * Math.abs(sprite.velocity.y);\r\n }\r\n\r\n if (sprite.position.y - sprite.size < 0) {\r\n sprite.velocity.y = Math.abs(sprite.velocity.y);\r\n }\r\n};\r\n\r\nexport const updatePosition = (\r\n sprite: Sprite,\r\n environment: Environment,\r\n timeInterval: number\r\n) => {\r\n const deltaVelocity = -1 * environment.gravity * timeInterval;\r\n sprite.position.x += sprite.velocity.x * timeInterval;\r\n sprite.position.y += (sprite.velocity.y + 0.5 * deltaVelocity) * timeInterval;\r\n sprite.velocity.y += deltaVelocity;\r\n};\r\n\r\nexport const updateRotation = (sprite: Sprite, timeInterval: number) => {\r\n sprite.rotation += sprite.rotationSpeed * timeInterval;\r\n};\r\n\r\nconst getCollisions = (sprites: Sprite[]): Collision[] => {\r\n const collisions: Collision[] = [];\r\n for (let i = 0; i < sprites.length; i++) {\r\n const sprite1 = sprites[i];\r\n\r\n for (let j = i + 1; j < sprites.length; j++) {\r\n //if (i === j) continue;\r\n\r\n const sprite2 = sprites[j];\r\n\r\n const deltaX = sprite1.position.x - sprite2.position.x;\r\n const deltaY = sprite1.position.y - sprite2.position.y;\r\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\r\n if (distance <= sprite1.size + sprite2.size)\r\n collisions.push({ sprite1: sprite1, sprite2: sprite2 });\r\n }\r\n }\r\n return collisions;\r\n};\r\n\r\nexport const performCollisions = (sprites: Sprite[]) => {\r\n const collisions = getCollisions(sprites);\r\n\r\n if (collisions.length === 0) return;\r\n\r\n //const collisionSprites: Sprite[] = [];\r\n for (const collision of collisions) {\r\n const sprite1 = collision.sprite1;\r\n const sprite2 = collision.sprite2;\r\n\r\n // Ensure that we only process a single collision for a sprite\r\n //if (collisionSprites.indexOf(sprite1) > -1) continue;\r\n //if (collisionSprites.indexOf(sprite2) > -1) continue;\r\n //collisionSprites.push(sprite1);\r\n //collisionSprites.push(sprite2);\r\n\r\n const v1Final = getNewVelocityVectory(sprite1, sprite2);\r\n const v2Final = getNewVelocityVectory(sprite2, sprite1);\r\n if (v1Final) sprite1.velocity = v1Final;\r\n if (v2Final) sprite2.velocity = v2Final;\r\n\r\n /*\r\n const forceAngle = getAngle(sprite1.position, sprite2.position);\r\n const reverseForceAngle = 3.14159 + forceAngle;\r\n\r\n sprite2.velocity.x = Math.cos(forceAngle) * 80;\r\n sprite2.velocity.y = Math.sin(forceAngle) * 80;\r\n\r\n sprite1.velocity.x = Math.cos(reverseForceAngle) * 80;\r\n sprite1.velocity.y = Math.sin(reverseForceAngle) * 80;\r\n */\r\n }\r\n};\r\n\r\nconst getNewVelocityVectory = (\r\n sprite1: Sprite,\r\n sprite2: Sprite\r\n): Vector | null => {\r\n const deltaVelecity = subtractVectors(sprite1.velocity, sprite2.velocity);\r\n const deltaPosition = subtractVectors(sprite1.position, sprite2.position);\r\n\r\n const angle = getAngle(deltaPosition, deltaVelecity);\r\n\r\n if (angle < 1.5708) {\r\n // quirk of discreet step simulation. This is a collision where the sprites are moving away from each other\r\n return null;\r\n }\r\n const distance = getMagnitude(deltaPosition);\r\n const dotProd = dotProduct(deltaVelecity, deltaPosition);\r\n\r\n const numerator = 2 * sprite2.mass * dotProd;\r\n const denominator = (sprite1.mass + sprite2.mass) * (distance * distance);\r\n\r\n const tempVector = scaleVector(deltaPosition, numerator / denominator);\r\n const result = subtractVectors(sprite1.velocity, tempVector);\r\n return result;\r\n};\r\n\r\nconst getStats = (sprites: Sprite[]): { average: number; medium: number } => {\r\n const data = sprites.map((b) => getMagnitude(b.velocity));\r\n\r\n let average = data.reduce((acc, val) => acc + val, 0);\r\n average = average / data.length;\r\n\r\n const dataSort = data.sort();\r\n const mid = Math.ceil(data.length / 2);\r\n const medium =\r\n data.length % 2 === 0\r\n ? (dataSort[mid] + dataSort[mid - 1]) / 2\r\n : dataSort[mid - 1];\r\n\r\n return { average, medium };\r\n};\r\n\r\nexport const getTotalEnergy = (sprites: Sprite[], environment: Environment) => {\r\n return getEnergy(sprites, environment).reduce(\r\n (acc, energy) => acc + energy,\r\n 0\r\n );\r\n};\r\n\r\nexport const getEnergy = (sprites: Sprite[], environment: Environment) => {\r\n return sprites.map((sprite) => {\r\n const v = getMagnitude(sprite.velocity);\r\n const ke = 0.5 * sprite.mass * v * v;\r\n const pe = sprite.mass * environment.gravity * sprite.position.y;\r\n return ke + pe;\r\n });\r\n};\r\n","import React from \"react\";\r\nimport { SpriteCtrlProps } from \"./model\";\r\n\r\nexport const BallSpriteRenderCtrl = ({\r\n sprite,\r\n environment,\r\n}: SpriteCtrlProps) => {\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport const CatSpriteRenderCtrl = ({\r\n sprite,\r\n environment,\r\n}: SpriteCtrlProps) => {\r\n const center = sprite.size;\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n );\r\n};\r\nexport const ManSpriteRenderCtrl = ({\r\n sprite,\r\n environment,\r\n}: SpriteCtrlProps) => {\r\n const center = sprite.size;\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n );\r\n};\r\n","import React, { useCallback, useEffect, useState } from \"react\";\r\nimport {\r\n doBoundaries,\r\n performCollisions,\r\n simulationSpeeds,\r\n SpeedType,\r\n updatePosition,\r\n updateRotation,\r\n} from \"./elasticCollisionsSimulator\";\r\nimport {\r\n getSpriteRenderCtrl,\r\n Sprite,\r\n SpriteSimulatorCtrlProps,\r\n SpriteType,\r\n} from \"./model\";\r\n\r\nconst environment = {\r\n gravity: 10,\r\n height: 1000,\r\n width: 1000,\r\n};\r\n\r\nconst defaultspriteCount = 10;\r\nconst defaultSpeed = \"Fast\";\r\nlet timeInterval: number =\r\n simulationSpeeds.find((s) => s.speed === defaultSpeed)?.timeInterval || 0;\r\n\r\nlet sprites: Sprite[] = [];\r\n\r\nexport const SpriteSimulatorCtrl = ({\r\n spriteGenerator,\r\n}: SpriteSimulatorCtrlProps) => {\r\n const [, setCounter] = useState(0);\r\n const [spriteCount, setSpriteCount] = useState(defaultspriteCount);\r\n const [running, setRunning] = useState(true);\r\n const [spriteType, setSpriteType] = useState(\"Man\");\r\n const [simulationSpeed, setSimulationSpeed] = useState(\r\n defaultSpeed\r\n );\r\n\r\n const doSimulationTimeStepCB = useCallback(() => {\r\n performCollisions(sprites);\r\n sprites.forEach((sprite) => {\r\n doBoundaries(sprite, environment);\r\n updatePosition(sprite, environment, timeInterval);\r\n updateRotation(sprite, timeInterval);\r\n });\r\n }, []);\r\n\r\n useEffect(() => {\r\n const interval = setInterval(() => {\r\n if (running) {\r\n doSimulationTimeStepCB();\r\n setCounter((count) => count + 1);\r\n }\r\n }, 10);\r\n return () => clearInterval(interval);\r\n }, [running, spriteCount, doSimulationTimeStepCB]);\r\n\r\n useEffect(() => {\r\n sprites = spriteGenerator(spriteType, spriteCount, environment);\r\n }, [spriteCount, spriteType, spriteGenerator]);\r\n\r\n const onCountOfBallsChanged = (countStr: string) => {\r\n const count = Number.parseInt(countStr);\r\n setSpriteCount(count);\r\n };\r\n\r\n const onSimulationSpeedChanged = (speedType: SpeedType) => {\r\n setSimulationSpeed(speedType);\r\n timeInterval =\r\n simulationSpeeds.find((s) => s.speed === speedType)?.timeInterval || 0;\r\n setCounter((count) => count + 1);\r\n };\r\n\r\n const onSpriteTypeChanged = (type: string) => {\r\n const sType = type as SpriteType;\r\n setSpriteType(sType);\r\n sprites = spriteGenerator(sType, spriteCount, environment);\r\n };\r\n\r\n const toggleStartStop = () => {\r\n setRunning((val) => !val);\r\n setCounter((prev) => prev + 1);\r\n };\r\n\r\n const resetSimulation = () => {\r\n sprites = spriteGenerator(spriteType, spriteCount, environment);\r\n setCounter((count) => count + 1);\r\n };\r\n\r\n let areaHeight = 0,\r\n areaWidth = 0;\r\n if (window.innerWidth > 800) {\r\n // Horizontal layout\r\n areaHeight = window.innerHeight - 50;\r\n areaWidth = window.innerWidth - 300;\r\n } else {\r\n // vartical layout\r\n areaWidth = window.innerWidth - 50;\r\n areaHeight = areaWidth;\r\n }\r\n\r\n return (\r\n
\r\n
\r\n
\r\n \r\n {running ? \"Stop\" : \"Run\"}\r\n \r\n
\r\n
\r\n \r\n Reset\r\n \r\n
\r\n
\r\n
Sprite Count
\r\n onCountOfBallsChanged(e.currentTarget.value)}\r\n value={spriteCount}\r\n >\r\n {[1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60].map((i) => (\r\n \r\n ))}\r\n \r\n
\r\n
\r\n
Simulation speed
\r\n \r\n onSimulationSpeedChanged(e.currentTarget.value as SpeedType)\r\n }\r\n value={simulationSpeed}\r\n >\r\n {simulationSpeeds.map((s) => (\r\n \r\n ))}\r\n \r\n
\r\n
\r\n
Sprite Type
\r\n onSpriteTypeChanged(e.currentTarget.value)}\r\n value={spriteType}\r\n >\r\n \r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n \r\n \r\n\r\n {sprites.map((sprite, index) => {\r\n const SpriteRenderCtrl = getSpriteRenderCtrl(sprite);\r\n return (\r\n \r\n );\r\n })}\r\n \r\n
\r\n
\r\n );\r\n};\r\n","import {\r\n ManSpriteRenderCtrl,\r\n CatSpriteRenderCtrl,\r\n BallSpriteRenderCtrl,\r\n} from \"./SpriteCtrl\";\r\n\r\nexport interface Vector {\r\n x: number;\r\n y: number;\r\n}\r\n\r\nexport type SpriteType = \"Man\" | \"Ball\" | \"Cat\";\r\n\r\nexport interface Sprite {\r\n color: string;\r\n size: number;\r\n mass: number;\r\n name: string;\r\n position: { x: number; y: number };\r\n velocity: Vector;\r\n rotation: number;\r\n rotationSpeed: number;\r\n type: SpriteType;\r\n}\r\n\r\nexport interface Environment {\r\n gravity: number;\r\n width: number;\r\n height: number;\r\n}\r\n\r\nexport interface Collision {\r\n sprite1: Sprite;\r\n sprite2: Sprite;\r\n}\r\n\r\nexport type SpriteCtrlProps = {\r\n sprite: Sprite;\r\n environment: Environment;\r\n};\r\n\r\nexport type SpriteRenderCtrl = (props: SpriteCtrlProps) => JSX.Element;\r\n\r\nexport type SpriteGenerator = (\r\n spriteType: SpriteType,\r\n count: number,\r\n environment: Environment\r\n) => Sprite[];\r\n\r\nexport type SpriteSimulatorCtrlProps = {\r\n spriteGenerator: SpriteGenerator;\r\n};\r\n\r\nexport const getSpriteRenderCtrl = (sprite: Sprite) => {\r\n switch (sprite.type) {\r\n case \"Man\":\r\n return ManSpriteRenderCtrl;\r\n case \"Cat\":\r\n return CatSpriteRenderCtrl;\r\n default:\r\n return BallSpriteRenderCtrl;\r\n }\r\n};\r\n","import React from \"react\";\r\nimport { createRandonVector } from \"../../vectors\";\r\nimport { Environment, Sprite, SpriteType } from \"./model\";\r\nimport { SpriteSimulatorCtrl } from \"./SpriteSimulatorCtrl\";\r\n\r\nconst colors = [\r\n \"purple\",\r\n \"red\",\r\n \"white\",\r\n \"blue\",\r\n \"black\",\r\n \"cyan\",\r\n \"orange\",\r\n \"green\",\r\n \"grey\",\r\n \"yellow\",\r\n \"MAROON\",\r\n \"Olive\",\r\n \"Teal\",\r\n];\r\n\r\nconst generateSprites = (\r\n spriteType: SpriteType,\r\n count: number,\r\n environment: Environment\r\n) => {\r\n const sprites: Sprite[] = [];\r\n for (let i = 0; i < count; i++) {\r\n const size = Math.ceil(Math.random() * 40) + 20;\r\n const xPos =\r\n Math.ceil(Math.random() * (environment.width - 2 * size)) + size;\r\n const YPos =\r\n Math.ceil(Math.random() * (environment.height - 2 * size)) + size;\r\n sprites.push({\r\n type: spriteType,\r\n color: colors[i % colors.length],\r\n name: `sprite ${i}`,\r\n position: { x: xPos, y: YPos },\r\n velocity: createRandonVector(120),\r\n size: size,\r\n mass: 10,\r\n rotation: 0,\r\n rotationSpeed: Math.ceil(Math.random() * 80) - 40,\r\n });\r\n }\r\n return sprites;\r\n};\r\n\r\nexport const BouncingSprites = () => {\r\n return ;\r\n};\r\n","import React, { useCallback, useEffect, useState } from \"react\";\r\nimport { createRandonVector, scaleVector } from \"../../vectors\";\r\nimport { Environment, Sprite } from \"./model\";\r\nimport {\r\n performCollisions,\r\n getTotalEnergy,\r\n updatePosition,\r\n simulationSpeeds,\r\n SpeedType,\r\n} from \"./elasticCollisionsSimulator\";\r\n\r\nimport { Histogram } from \"./Histogram\";\r\n\r\nconst environment = {\r\n gravity: 10,\r\n height: 800,\r\n width: 800,\r\n};\r\n\r\nconst createSprites = (environment: Environment, size: number) => {\r\n const gap = 20;\r\n const spacing = 2 * size + gap;\r\n const rowCount = (environment.height - spacing) / spacing;\r\n const colCount = (environment.width - spacing) / spacing;\r\n\r\n const sprites: Sprite[] = [];\r\n for (let row = 0; row < rowCount; row++) {\r\n for (let col = 0; col < colCount; col++) {\r\n sprites.push({\r\n color: \"white\",\r\n size,\r\n mass: 0.2,\r\n name: `sprite ${row} ${col}`,\r\n position: {\r\n x: col * spacing + gap + size,\r\n y: row * spacing + gap + size,\r\n },\r\n velocity: createRandonVector(25),\r\n rotation: 0,\r\n rotationSpeed: 10,\r\n type: \"Ball\",\r\n });\r\n }\r\n }\r\n return sprites;\r\n};\r\n\r\n// simulate heating/cooling from below\r\nconst doHeatingCooling = (sprite: Sprite, heatType: HeatType) => {\r\n if (heatType === \"Heat\") {\r\n sprite.velocity = scaleVector(sprite.velocity, 1.3);\r\n } else if (heatType === \"Cool\") {\r\n sprite.velocity = scaleVector(sprite.velocity, 0.8);\r\n }\r\n};\r\n\r\nconst doContainerBoundaries = (\r\n sprite: Sprite,\r\n environment: Environment,\r\n heatType: HeatType\r\n) => {\r\n // lower boundary\r\n if (sprite.position.x - sprite.size < 0 && sprite.velocity.x < 0) {\r\n sprite.velocity.x = -1 * sprite.velocity.x;\r\n doHeatingCooling(sprite, heatType);\r\n }\r\n\r\n if (\r\n sprite.position.x + sprite.size > environment.width &&\r\n sprite.velocity.x > 0\r\n ) {\r\n sprite.velocity.x = -1 * sprite.velocity.x;\r\n }\r\n\r\n if (sprite.position.y + sprite.size > environment.height) {\r\n sprite.velocity.y = -1 * Math.abs(sprite.velocity.y);\r\n }\r\n\r\n if (sprite.position.y - sprite.size < 0) {\r\n sprite.velocity.y = Math.abs(sprite.velocity.y);\r\n }\r\n};\r\n\r\nconst defaulktSize = 10;\r\nconst defaultSpeed = \"Normal\";\r\nlet timeInterval: number =\r\n simulationSpeeds.find((s) => s.speed === defaultSpeed)?.timeInterval || 0;\r\n\r\nlet sprites = createSprites(environment, defaulktSize);\r\n\r\ntype HeatType = \"Heat\" | \"Cool\" | \"None\";\r\n\r\nexport const GasSimulation = () => {\r\n const [, setCounter] = useState(0);\r\n const [heatType, setHeatType] = useState(\"None\");\r\n const [totalEnergy, setTotalEnergy] = useState();\r\n const [running, setRunning] = useState(false);\r\n const [simulationSpeed, setSimulationSpeed] = useState(\r\n defaultSpeed\r\n );\r\n\r\n const doSimulationTimeStepCB = useCallback(() => {\r\n performCollisions(sprites);\r\n sprites.forEach((sprite) => {\r\n doContainerBoundaries(sprite, environment, heatType);\r\n updatePosition(sprite, environment, timeInterval);\r\n });\r\n }, [heatType]);\r\n\r\n const onHeatingChange = (type: string) => {\r\n setHeatType(type as HeatType);\r\n };\r\n\r\n useEffect(() => {\r\n const interval = setInterval(() => {\r\n if (running) {\r\n doSimulationTimeStepCB();\r\n setCounter((count) => count + 1);\r\n }\r\n }, 10);\r\n return () => clearInterval(interval);\r\n }, [running, doSimulationTimeStepCB]);\r\n\r\n useEffect(() => {\r\n const interval = setInterval(() => {\r\n if (running) {\r\n const energy = getTotalEnergy(sprites, environment);\r\n setTotalEnergy(Math.ceil(energy));\r\n }\r\n }, 1000);\r\n return () => clearInterval(interval);\r\n }, [running]);\r\n\r\n const toggleStartStop = () => {\r\n setRunning((val) => !val);\r\n setCounter((prev) => prev + 1);\r\n };\r\n\r\n const resetSimulation = () => {\r\n sprites = createSprites(environment, 10);\r\n setCounter((count) => count + 1);\r\n };\r\n\r\n const onSimulationSpeedChanged = (speedType: SpeedType) => {\r\n setSimulationSpeed(speedType);\r\n timeInterval =\r\n simulationSpeeds.find((s) => s.speed === speedType)?.timeInterval || 0;\r\n setCounter((count) => count + 1);\r\n };\r\n\r\n //console.log(\"total energy\", Math.ceil(energy));\r\n\r\n return (\r\n
\r\n
\r\n
\r\n \r\n {running ? \"Stop\" : \"Run\"}\r\n \r\n
\r\n
\r\n \r\n Reset\r\n \r\n
\r\n
\r\n
Scenario
\r\n onHeatingChange(e.currentTarget.value)}\r\n >\r\n \r\n \r\n \r\n \r\n
\r\n
\r\n
Simulation speed
\r\n \r\n onSimulationSpeedChanged(e.currentTarget.value as SpeedType)\r\n }\r\n value={simulationSpeed}\r\n >\r\n {simulationSpeeds.map((s) => (\r\n \r\n ))}\r\n \r\n
\r\n\r\n
\r\n
Total Energy : {totalEnergy}
\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
Energy Histogram
\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nconst SpritesCtrl = ({\r\n sprites,\r\n heatType,\r\n}: {\r\n sprites: Sprite[];\r\n heatType: HeatType;\r\n}) => {\r\n const margin = 50;\r\n const scaleHeight = (window.innerHeight - 2 * margin) / environment.height;\r\n\r\n return (\r\n \r\n \r\n \r\n\r\n {heatType !== \"None\" && (\r\n \r\n )}\r\n\r\n {sprites.map((sprite, index) => {\r\n return ;\r\n })}\r\n \r\n \r\n );\r\n};\r\n\r\nconst SpriteCtrl = ({ sprite, index }: { sprite: Sprite; index: number }) => {\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n","\r\nexport type Pos = {\r\n x: number;\r\n y: number;\r\n};\r\n\r\nexport type Vect = {\r\n deltaX: number;\r\n deltaY: number;\r\n};\r\n\r\nexport type Snake = {\r\n body: Pos[];\r\n direction: number;\r\n directionVector: Vect;\r\n size: number;\r\n length: number;\r\n bodyColor: {\r\n r: number;\r\n g: number;\r\n b: number;\r\n };\r\n};\r\n\r\nexport const getRandom = (min: number, max: number) => {\r\n const diff = Math.abs(max - min);\r\n return Math.random() * diff + min;\r\n};\r\n\r\nexport const nextColorComp = (comp: number, inc: number) => {\r\n let c = comp + inc;\r\n if (c > 255) c = c - 255;\r\n if (c < 0) c = c + 255;\r\n return c;\r\n};\r\n\r\nexport const createSnake = (\r\n minX: number,\r\n maxX: number,\r\n minY: number,\r\n maxY: number\r\n) => {\r\n const size = getRandom(5, 20);\r\n const direction = Math.random() * 2 * Math.PI;\r\n const directionVector = {\r\n deltaX: Math.cos(direction),\r\n deltaY: Math.sin(direction),\r\n };\r\n\r\n const snake: Snake = {\r\n body: [{ x: getRandom(minX, maxX), y: getRandom(minY, maxY) }],\r\n direction,\r\n directionVector,\r\n size: size,\r\n length: getRandom(50, 100),\r\n bodyColor: {\r\n r: Math.random() * 255,\r\n g: Math.random() * 255,\r\n b: Math.random() * 255,\r\n },\r\n };\r\n\r\n return snake;\r\n};\r\n\r\nexport const changeRandomDirection = (snake: Snake) => {\r\n turnSnake(snake, getRandom(-0.3, 0.3));\r\n};\r\n\r\nexport const turnSnake = (snake: Snake, turn: number) => {\r\n snake.direction += turn;\r\n snake.directionVector = {\r\n deltaX: Math.cos(snake.direction),\r\n deltaY: Math.sin(snake.direction),\r\n };\r\n};\r\nexport const updatePosition = (\r\n snake: Snake,\r\n minX: number,\r\n maxX: number,\r\n minY: number,\r\n maxY: number\r\n) => {\r\n if (snake.body.length >= snake.length) snake.body = snake.body.splice(1);\r\n\r\n const headPos = snake.body[snake.body.length - 1];\r\n let posX = headPos.x;\r\n let posY = headPos.y;\r\n\r\n posX += (snake.directionVector.deltaX * snake.size) / 2;\r\n posY += (snake.directionVector.deltaY * snake.size) / 2;\r\n\r\n if (posX >= maxX - snake.size) posX = minX + snake.size;\r\n else if (posX <= minX + snake.size) posX = maxX - snake.size;\r\n else if (posY >= maxY - snake.size) posY = minY + snake.size;\r\n else if (posY <= minY + snake.size) posY = maxY - snake.size;\r\n\r\n snake.body.push({ x: posX, y: posY });\r\n};\r\n\r\n","import {\r\n scaleVector,\r\n addVectors,\r\n convertToUnitVector,\r\n getMagnitude,\r\n subtractVectors,\r\n} from \"../../vectors\";\r\nimport { Vector } from \"../ElasticCollisions/model\";\r\n\r\nexport interface Planet {\r\n color: string;\r\n size: number;\r\n mass: number;\r\n name: string;\r\n position: { x: number; y: number };\r\n velocity: { x: number; y: number };\r\n}\r\n\r\nexport interface Scenario {\r\n planets: Planet[];\r\n name: string;\r\n size: number;\r\n}\r\n\r\nexport type ScenarioType = \"Scenario1\" | \"Scenario2\" | \"Scenario3\";\r\n\r\nexport const getScenario = (scenarioType: ScenarioType): Scenario => {\r\n if (scenarioType === \"Scenario1\") return getScenario1();\r\n if (scenarioType === \"Scenario2\") return getScenario2();\r\n if (scenarioType === \"Scenario3\") return getScenario3();\r\n throw Error(\"Unknown scenario\");\r\n};\r\n\r\nconst getScenario1 = (): Scenario => {\r\n return {\r\n planets: [\r\n {\r\n color: \"yellow\",\r\n size: 50,\r\n mass: 1000000,\r\n name: \"Sun\",\r\n position: { x: 500, y: 500 },\r\n velocity: { x: 0, y: 0 },\r\n },\r\n {\r\n color: \"red\",\r\n size: 30,\r\n mass: 30,\r\n name: \"Planet 1\",\r\n position: { x: 500, y: 1000 },\r\n velocity: { x: 40, y: 0 },\r\n },\r\n {\r\n color: \"blue\",\r\n size: 10,\r\n mass: 10,\r\n name: \"Planet 2\",\r\n position: { x: 500, y: 100 },\r\n velocity: { x: -40, y: 0 },\r\n },\r\n ],\r\n name: \"Scenario1\",\r\n size: 1000,\r\n };\r\n};\r\n\r\nconst getScenario2 = (): Scenario => {\r\n return {\r\n planets: [\r\n {\r\n color: \"yellow\",\r\n size: 50,\r\n mass: 1000000,\r\n name: \"Sun\",\r\n position: { x: 500, y: 500 },\r\n velocity: { x: 0, y: 0 },\r\n },\r\n {\r\n color: \"red\",\r\n size: 10,\r\n mass: 10000,\r\n name: \"Planet 1\",\r\n position: { x: 500, y: 120 },\r\n velocity: { x: 60, y: 0 },\r\n },\r\n {\r\n color: \"blue\",\r\n size: 10,\r\n mass: 10000,\r\n name: \"Planet 2\",\r\n position: { x: 500, y: 60 },\r\n velocity: { x: 40, y: 0 },\r\n },\r\n ],\r\n name: \"Scenario2\",\r\n size: 1000,\r\n };\r\n};\r\n\r\nconst getScenario3 = (): Scenario => {\r\n const centre: Vector = { x: 1000, y: 1000 };\r\n return {\r\n planets: [\r\n {\r\n color: \"yellow\",\r\n size: 50,\r\n mass: 1000000,\r\n name: \"Sun\",\r\n position: centre,\r\n velocity: { x: 0, y: 0 },\r\n },\r\n {\r\n color: \"grey\",\r\n size: 5,\r\n mass: 5,\r\n name: \"Mercury\",\r\n position: { x: centre.x, y: centre.y + 100 },\r\n velocity: { x: 95, y: 0 },\r\n },\r\n {\r\n color: \"silver\",\r\n size: 15,\r\n mass: 5,\r\n name: \"Venus\",\r\n position: { x: centre.x, y: centre.y + 150 },\r\n velocity: { x: 85, y: 0 },\r\n },\r\n {\r\n color: \"blue\",\r\n size: 15,\r\n mass: 5,\r\n name: \"Earth\",\r\n position: { x: centre.x, y: centre.y + 200 },\r\n velocity: { x: 75, y: 0 },\r\n },\r\n {\r\n color: \"red\",\r\n size: 12,\r\n mass: 5,\r\n name: \"Mars\",\r\n position: { x: centre.x, y: centre.y + 250 },\r\n velocity: { x: 65, y: 0 },\r\n },\r\n {\r\n color: \"orange\",\r\n size: 40,\r\n mass: 5,\r\n name: \"Jupiter\",\r\n position: { x: centre.x, y: centre.y + 350 },\r\n velocity: { x: 55, y: 0 },\r\n },\r\n {\r\n color: \"OLIVE\",\r\n size: 35,\r\n mass: 5,\r\n name: \"Saturn\",\r\n position: { x: centre.x, y: centre.y + 450 },\r\n velocity: { x: 50, y: 0 },\r\n },\r\n {\r\n color: \"TEAL\",\r\n size: 25,\r\n mass: 5,\r\n name: \"Neptune\",\r\n position: { x: centre.x, y: centre.y + 550 },\r\n velocity: { x: 45, y: 0 },\r\n },\r\n {\r\n color: \"green\",\r\n size: 25,\r\n mass: 5,\r\n name: \"Uranus\",\r\n position: { x: centre.x, y: centre.y + 650 },\r\n velocity: { x: 40, y: 0 },\r\n },\r\n ],\r\n name: \"Scenario3\",\r\n size: 1700,\r\n };\r\n};\r\n\r\nexport const getGravityDeltaV = (\r\n planet: Planet,\r\n planets: Planet[],\r\n timeInterval: number\r\n): Vector => {\r\n let deltaV: Vector = { x: 0, y: 0 };\r\n for (let i = 0; i < planets.length; i++) {\r\n const planet1 = planets[i];\r\n if (planet1 === planet) continue;\r\n\r\n const diffVect = subtractVectors(planet1.position, planet.position);\r\n\r\n const distance = getMagnitude(diffVect);\r\n if (distance === 0) continue;\r\n const unitVect = convertToUnitVector(diffVect);\r\n const forceOfGravity = (planet.mass * planet1.mass) / (distance * distance);\r\n const gravityDeltaV = scaleVector(\r\n unitVect,\r\n (forceOfGravity * timeInterval) / planet.mass\r\n );\r\n deltaV = addVectors(deltaV, gravityDeltaV);\r\n }\r\n return deltaV;\r\n};\r\n\r\nexport const updatePosition = (\r\n planet: Planet,\r\n planets: Planet[],\r\n timeInterval: number\r\n) => {\r\n // Calculate the delta velocity due to gravity of other planets\r\n const deltaVelocity = getGravityDeltaV(planet, planets, timeInterval);\r\n\r\n // Calculate change in position due to planets velocity\r\n const deltaPos1 = scaleVector(planet.velocity, timeInterval);\r\n planet.position = addVectors(planet.position, deltaPos1);\r\n\r\n // calculate change in position due to gravity\r\n const deltaPos2 = scaleVector(deltaVelocity, timeInterval);\r\n planet.position = addVectors(planet.position, deltaPos2);\r\n\r\n // update planet's velocity due to gravity\r\n planet.velocity = addVectors(planet.velocity, deltaVelocity);\r\n};\r\n","import React, { useCallback, useEffect, useState } from \"react\";\r\nimport {\r\n simulationSpeeds,\r\n SpeedType,\r\n} from \"../ElasticCollisions/elasticCollisionsSimulator\";\r\nimport { getScenario, Planet, ScenarioType, updatePosition } from \"./planets\";\r\n\r\nconst defaultScenario = \"Scenario3\";\r\nconst defaultSpeed = \"Normal\";\r\nlet timeInterval: number =\r\n simulationSpeeds.find((s) => s.speed === defaultSpeed)?.timeInterval || 0;\r\nlet scenario = getScenario(defaultScenario);\r\n\r\nexport const PlanetOrbit = () => {\r\n const [, setCounter] = useState(0);\r\n const [running, setRunning] = useState(false);\r\n const [scenarioType, setScenarioType] = useState(\r\n defaultScenario\r\n );\r\n const [simulationSpeed, setSimulationSpeed] = useState(\r\n defaultSpeed\r\n );\r\n\r\n const size = Math.min(window.innerHeight - 50, window.innerWidth - 200);\r\n const scaleFactor = size / scenario.size;\r\n\r\n const doSimulationTimeStepCB = useCallback(() => {\r\n scenario.planets.forEach((planet) => {\r\n updatePosition(planet, scenario.planets, timeInterval);\r\n });\r\n }, []);\r\n\r\n useEffect(() => {\r\n const interval = setInterval(() => {\r\n if (running) {\r\n doSimulationTimeStepCB();\r\n\r\n setCounter((count) => count + 1);\r\n }\r\n }, 10);\r\n return () => clearInterval(interval);\r\n }, [running, doSimulationTimeStepCB]);\r\n\r\n const onScenarioTypeChanged = (newScenarioType: ScenarioType) => {\r\n scenario = getScenario(newScenarioType);\r\n setScenarioType(newScenarioType);\r\n };\r\n\r\n const onSimulationSpeedChanged = (speedType: SpeedType) => {\r\n setSimulationSpeed(speedType);\r\n timeInterval =\r\n simulationSpeeds.find((s) => s.speed === speedType)?.timeInterval || 0;\r\n };\r\n\r\n const toggleStartStop = () => {\r\n setRunning((val) => !val);\r\n };\r\n\r\n const resetSimulation = () => {\r\n scenario = getScenario(scenarioType);\r\n setCounter((count) => count + 1);\r\n };\r\n\r\n return (\r\n
\r\n
\r\n
\r\n \r\n {running ? \"Stop\" : \"Run\"}\r\n \r\n
\r\n
\r\n \r\n Reset\r\n \r\n
\r\n
\r\n
Scenario
\r\n \r\n onScenarioTypeChanged(e.currentTarget.value as ScenarioType)\r\n }\r\n >\r\n \r\n \r\n \r\n \r\n
\r\n\r\n
\r\n
Simulation speed
\r\n \r\n onSimulationSpeedChanged(e.currentTarget.value as SpeedType)\r\n }\r\n value={simulationSpeed}\r\n >\r\n {simulationSpeeds.map((s) => (\r\n \r\n ))}\r\n \r\n
\r\n
\r\n
\r\n \r\n \r\n {scenario.planets.map((planet, index) => {\r\n return ;\r\n })}\r\n \r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nconst PlanetCtrl = ({ planet }: { planet: Planet }) => {\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n","import {\r\n addVectors,\r\n convertToUnitVector,\r\n dotProduct,\r\n getMagnitude,\r\n scaleVector,\r\n subtractVectors,\r\n} from \"../../vectors\";\r\nimport { Vector } from \"../ElasticCollisions/model\";\r\n\r\nconst neutralSeparation = 10;\r\n\r\nexport interface Point {\r\n position: Vector;\r\n velocity: Vector;\r\n mass: number;\r\n size: number;\r\n}\r\n\r\nexport interface Rope {\r\n points: Point[];\r\n}\r\n\r\nexport interface Simulation {\r\n gravity: number;\r\n timeInterval: number;\r\n ES: number;\r\n size: number;\r\n}\r\n\r\nexport const updateAllPoints = (\r\n rope: Rope,\r\n simulation: Simulation,\r\n timeInterval: number\r\n) => {\r\n for (let i = 0; i < rope.points.length; i++) {\r\n updatePoint(i, rope, simulation, timeInterval);\r\n }\r\n};\r\n\r\nexport const updatePoint = (\r\n pointIndex: number,\r\n rope: Rope,\r\n simulation: Simulation,\r\n timeInterval: number\r\n) => {\r\n if (pointIndex === 0) return; // start of rope is anchored\r\n //if (pointIndex === rope.points.length - 1) return; // end of rope is anchored\r\n\r\n let deltaV = { x: 0, y: 0 };\r\n const point = rope.points[pointIndex];\r\n\r\n const pointLS = pointIndex > 0 ? rope.points[pointIndex - 1] : undefined;\r\n const pointRS =\r\n pointIndex < rope.points.length - 1\r\n ? rope.points[pointIndex + 1]\r\n : undefined;\r\n\r\n // Calculate the velocity change due to point to left\r\n if (pointLS) {\r\n const forceLS = calculateForceVector(point, pointLS, simulation);\r\n const tempV = scaleVector(forceLS, (0.5 * timeInterval) / point.mass);\r\n deltaV = addVectors(deltaV, tempV);\r\n }\r\n\r\n // Add the velocity change due to point to right\r\n if (pointRS) {\r\n const forceRS = calculateForceVector(point, pointRS, simulation);\r\n const tempV = scaleVector(forceRS, (0.5 * timeInterval) / point.mass);\r\n deltaV = addVectors(deltaV, tempV);\r\n }\r\n\r\n // velocity change due to gravity\r\n if (simulation.gravity > 0) {\r\n const gravityDeltaV = {\r\n x: 0,\r\n y: -1 * simulation.gravity * timeInterval,\r\n };\r\n\r\n const tempV = scaleVector(gravityDeltaV, 0.5 * timeInterval);\r\n deltaV = addVectors(deltaV, tempV);\r\n }\r\n\r\n point.velocity = addVectors(point.velocity, deltaV);\r\n\r\n point.position = addVectors(point.position, point.velocity);\r\n\r\n // update the points velocity with the delta V\r\n\r\n //if (pointLS) point.velocity = getPerpVector(point, pointLS, point.velocity);\r\n};\r\n\r\nconst fixupDistance = (point: Point, point2: Point) => {\r\n const deltaPosition = subtractVectors(point2.position, point.position);\r\n const separation = getMagnitude(deltaPosition);\r\n const diff = separation - neutralSeparation;\r\n console.log(diff);\r\n\r\n const unitVector = convertToUnitVector(deltaPosition);\r\n point.position = addVectors(point.position, scaleVector(unitVector, diff));\r\n};\r\n\r\nconst fixupVelcoity = (point: Point, point2: Point) => {\r\n const deltaPosition = subtractVectors(point2.position, point.position);\r\n const positionVector = convertToUnitVector(deltaPosition);\r\n const dotProd = dotProduct(positionVector, point.velocity);\r\n\r\n // const diff = separation - neutralSeparation;\r\n // console.log(diff);\r\n\r\n //const unitVector = convertToUnitVector(deltaPosition);\r\n //point.position = addVectors(point.position, scaleVector(unitVector, diff));\r\n};\r\n\r\n//\r\nconst getPerpVector = (point: Point, point2: Point, vector: Vector): Vector => {\r\n const deltaPosition = subtractVectors(point2.position, point.position);\r\n const unitVector = convertToUnitVector(deltaPosition);\r\n //console.log(\"unitVector\", unitVector.x, unitVector.y);\r\n\r\n const perpVector = { x: -1 * unitVector.y, y: unitVector.x };\r\n //console.log(\"perpVector\", perpVector.x, perpVector.y);\r\n\r\n const dotProd = dotProduct(vector, perpVector);\r\n return scaleVector(perpVector, dotProd);\r\n};\r\n\r\n// Returns the force on point as a result of point2\r\nconst calculateForceVector = (\r\n point: Point,\r\n point2: Point,\r\n simulation: Simulation\r\n): Vector => {\r\n const deltaPosition = subtractVectors(point2.position, point.position);\r\n const separation = getMagnitude(deltaPosition);\r\n const deltaPosUnitVector = convertToUnitVector(deltaPosition);\r\n\r\n return scaleVector(\r\n deltaPosUnitVector,\r\n (separation - neutralSeparation) * simulation.ES\r\n );\r\n};\r\n","import React, { useCallback, useEffect, useState } from \"react\";\r\nimport {\r\n simulationSpeeds,\r\n SpeedType,\r\n} from \"../ElasticCollisions/elasticCollisionsSimulator\";\r\nimport { Simulation, Rope, Point, updateAllPoints } from \"./ropeSimulation\";\r\n\r\nconst simulation: Simulation = {\r\n ES: 0.1,\r\n gravity: 1,\r\n timeInterval: 0.01,\r\n size: 200,\r\n};\r\n\r\nconst getRope = () => {\r\n return {\r\n points: [\r\n {\r\n mass: 0.1,\r\n position: { x: 100, y: 100 },\r\n velocity: { x: 0, y: 0 },\r\n size: 5,\r\n },\r\n {\r\n mass: 0.1,\r\n position: { x: 110, y: 100 },\r\n velocity: { x: 0, y: 0 },\r\n size: 5,\r\n },\r\n {\r\n mass: 0.1,\r\n position: { x: 120, y: 100 },\r\n velocity: { x: 0, y: 0 },\r\n size: 5,\r\n },\r\n {\r\n mass: 0.1,\r\n position: { x: 130, y: 100 },\r\n velocity: { x: 0, y: 0 },\r\n size: 5,\r\n },\r\n {\r\n mass: 0.1,\r\n position: { x: 140, y: 100 },\r\n velocity: { x: 0, y: 0 },\r\n size: 5,\r\n },\r\n {\r\n mass: 0.1,\r\n position: { x: 150, y: 100 },\r\n velocity: { x: 0, y: 0 },\r\n size: 5,\r\n },\r\n {\r\n mass: 0.1,\r\n position: { x: 160, y: 100 },\r\n velocity: { x: 0, y: 0 },\r\n size: 5,\r\n },\r\n {\r\n mass: 0.1,\r\n position: { x: 170, y: 100 },\r\n velocity: { x: 0, y: 0 },\r\n size: 5,\r\n },\r\n ],\r\n };\r\n};\r\n\r\nlet rope = getRope();\r\nconst defaultSpeed = \"Normal\";\r\nlet timeInterval: number =\r\n simulationSpeeds.find((s) => s.speed === defaultSpeed)?.timeInterval || 0;\r\n\r\nexport const RopeCtrl = () => {\r\n const [, setCounter] = useState(0);\r\n const [running, setRunning] = useState(false);\r\n const [simulationSpeed, setSimulationSpeed] = useState(\r\n defaultSpeed\r\n );\r\n\r\n const size = Math.min(window.innerHeight - 50, window.innerWidth - 200);\r\n const scaleFactor = size / simulation.size;\r\n\r\n const doSimulationTimeStepCB = useCallback(() => {\r\n updateAllPoints(rope, simulation, timeInterval);\r\n }, []);\r\n\r\n useEffect(() => {\r\n const interval = setInterval(() => {\r\n if (running) {\r\n doSimulationTimeStepCB();\r\n setCounter((count) => count + 1);\r\n }\r\n }, 10);\r\n return () => clearInterval(interval);\r\n }, [running, doSimulationTimeStepCB]);\r\n\r\n const onSimulationSpeedChanged = (speedType: SpeedType) => {\r\n setSimulationSpeed(speedType);\r\n timeInterval =\r\n simulationSpeeds.find((s) => s.speed === speedType)?.timeInterval || 0;\r\n rope = getRope();\r\n setCounter((count) => count + 1);\r\n };\r\n\r\n const toggleStartStop = () => {\r\n setRunning((val) => !val);\r\n setCounter((prev) => prev + 1);\r\n };\r\n\r\n const resetSimulation = () => {\r\n rope = getRope();\r\n setCounter((count) => count + 1);\r\n };\r\n\r\n return (\r\n
\r\n
\r\n
\r\n \r\n {running ? \"Stop\" : \"Run\"}\r\n \r\n
\r\n
\r\n \r\n Reset\r\n \r\n
\r\n
\r\n
Simulation speed
\r\n \r\n onSimulationSpeedChanged(e.currentTarget.value as SpeedType)\r\n }\r\n value={simulationSpeed}\r\n >\r\n {simulationSpeeds.map((s) => (\r\n \r\n ))}\r\n \r\n
\r\n
\r\n
\r\n \r\n \r\n {rope.points.map((point, index) => {\r\n return ;\r\n })}\r\n \r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nconst PointCtrl = ({ point }: { point: Point }) => {\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n","import React from \"react\";\r\nimport { HashRouter, Link, Route, Switch } from \"react-router-dom\";\r\nimport \"./App.css\";\r\nimport { BouncingSprites } from \"./component/ElasticCollisions/BouncingSprites\";\r\nimport { GasSimulation } from \"./component/ElasticCollisions/GasSimulation\";\r\nimport { SnakesAlive } from \"./component/Snake/SnakesAlive\";\r\nimport { PlanetOrbit } from \"./component/PlanetSimulation/PlanetOrbit\";\r\nimport { RopeCtrl } from \"./component/Rope/Rope\";\r\n\r\nfunction App() {\r\n return (\r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n
Yallambee NET
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n );\r\n}\r\n\r\nexport default App;\r\n","// This optional code is used to register a service worker.\r\n// register() is not called by default.\r\n\r\n// This lets the app load faster on subsequent visits in production, and gives\r\n// it offline capabilities. However, it also means that developers (and users)\r\n// will only see deployed updates on subsequent visits to a page, after all the\r\n// existing tabs open on the page have been closed, since previously cached\r\n// resources are updated in the background.\r\n\r\n// To learn more about the benefits of this model and instructions on how to\r\n// opt-in, read https://bit.ly/CRA-PWA\r\n\r\nconst isLocalhost = Boolean(\r\n window.location.hostname === 'localhost' ||\r\n // [::1] is the IPv6 localhost address.\r\n window.location.hostname === '[::1]' ||\r\n // 127.0.0.0/8 are considered localhost for IPv4.\r\n window.location.hostname.match(\r\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\r\n )\r\n);\r\n\r\nexport function register(config) {\r\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\r\n // The URL constructor is available in all browsers that support SW.\r\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\r\n if (publicUrl.origin !== window.location.origin) {\r\n // Our service worker won't work if PUBLIC_URL is on a different origin\r\n // from what our page is served on. This might happen if a CDN is used to\r\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\r\n return;\r\n }\r\n\r\n window.addEventListener('load', () => {\r\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\r\n\r\n if (isLocalhost) {\r\n // This is running on localhost. Let's check if a service worker still exists or not.\r\n checkValidServiceWorker(swUrl, config);\r\n\r\n // Add some additional logging to localhost, pointing developers to the\r\n // service worker/PWA documentation.\r\n navigator.serviceWorker.ready.then(() => {\r\n console.log(\r\n 'This web app is being served cache-first by a service ' +\r\n 'worker. To learn more, visit https://bit.ly/CRA-PWA'\r\n );\r\n });\r\n } else {\r\n // Is not localhost. Just register service worker\r\n registerValidSW(swUrl, config);\r\n }\r\n });\r\n }\r\n}\r\n\r\nfunction registerValidSW(swUrl, config) {\r\n navigator.serviceWorker\r\n .register(swUrl)\r\n .then(registration => {\r\n registration.onupdatefound = () => {\r\n const installingWorker = registration.installing;\r\n if (installingWorker == null) {\r\n return;\r\n }\r\n installingWorker.onstatechange = () => {\r\n if (installingWorker.state === 'installed') {\r\n if (navigator.serviceWorker.controller) {\r\n // At this point, the updated precached content has been fetched,\r\n // but the previous service worker will still serve the older\r\n // content until all client tabs are closed.\r\n console.log(\r\n 'New content is available and will be used when all ' +\r\n 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'\r\n );\r\n\r\n // Execute callback\r\n if (config && config.onUpdate) {\r\n config.onUpdate(registration);\r\n }\r\n } else {\r\n // At this point, everything has been precached.\r\n // It's the perfect time to display a\r\n // \"Content is cached for offline use.\" message.\r\n console.log('Content is cached for offline use.');\r\n\r\n // Execute callback\r\n if (config && config.onSuccess) {\r\n config.onSuccess(registration);\r\n }\r\n }\r\n }\r\n };\r\n };\r\n })\r\n .catch(error => {\r\n console.error('Error during service worker registration:', error);\r\n });\r\n}\r\n\r\nfunction checkValidServiceWorker(swUrl, config) {\r\n // Check if the service worker can be found. If it can't reload the page.\r\n fetch(swUrl, {\r\n headers: { 'Service-Worker': 'script' },\r\n })\r\n .then(response => {\r\n // Ensure service worker exists, and that we really are getting a JS file.\r\n const contentType = response.headers.get('content-type');\r\n if (\r\n response.status === 404 ||\r\n (contentType != null && contentType.indexOf('javascript') === -1)\r\n ) {\r\n // No service worker found. Probably a different app. Reload the page.\r\n navigator.serviceWorker.ready.then(registration => {\r\n registration.unregister().then(() => {\r\n window.location.reload();\r\n });\r\n });\r\n } else {\r\n // Service worker found. Proceed as normal.\r\n registerValidSW(swUrl, config);\r\n }\r\n })\r\n .catch(() => {\r\n console.log(\r\n 'No internet connection found. App is running in offline mode.'\r\n );\r\n });\r\n}\r\n\r\nexport function unregister() {\r\n if ('serviceWorker' in navigator) {\r\n navigator.serviceWorker.ready\r\n .then(registration => {\r\n registration.unregister();\r\n })\r\n .catch(error => {\r\n console.error(error.message);\r\n });\r\n }\r\n}\r\n","import React from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport './index.css';\r\nimport App from './App';\r\nimport * as serviceWorker from './serviceWorker';\r\n\r\nReactDOM.render(\r\n \r\n \r\n ,\r\n document.getElementById('root')\r\n);\r\n\r\n// If you want your app to work offline and load faster, you can change\r\n// unregister() to register() below. Note this comes with some pitfalls.\r\n// Learn more about service workers: https://bit.ly/CRA-PWA\r\nserviceWorker.unregister();\r\n"],"sourceRoot":""}