From a6dc577ee576833e44e69f0176e8922b0fb31b6b Mon Sep 17 00:00:00 2001 From: David Lounsbrough Date: Thu, 22 Aug 2024 14:26:08 -0500 Subject: [PATCH] start testing Simulation --- eslint.config.mjs | 3 ++- jest.config.js | 4 ++-- rollup.config.mjs | 1 - src/Body.spec.ts | 4 ++-- src/Simulation.spec.ts | 52 ++++++++++++++++++++++++++++++++++++++++++ src/Simulation.ts | 25 +++++++++++++++----- src/StableUniverses.ts | 6 ++--- src/Vector.spec.ts | 2 +- 8 files changed, 81 insertions(+), 16 deletions(-) create mode 100644 src/Simulation.spec.ts diff --git a/eslint.config.mjs b/eslint.config.mjs index dcb3fad..8e7491c 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -18,7 +18,8 @@ export default tseslint.config( }, { rules: { - 'semi': ['error', 'never'] + semi: ['error', 'never'], + quotes: ['error', 'single'] } } ) diff --git a/jest.config.js b/jest.config.js index ad6c371..90edef0 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,8 +1,8 @@ /** @type {import('ts-jest').JestConfigWithTsJest} **/ // eslint-disable-next-line no-undef module.exports = { - testEnvironment: "node", + testEnvironment: 'node', transform: { - "^.+.tsx?$": ["ts-jest", {}], + '^.+.tsx?$': ['ts-jest', {}], }, } diff --git a/rollup.config.mjs b/rollup.config.mjs index c57f5aa..2272324 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -17,7 +17,6 @@ export default { sourcemap: true } ], - external: ['node:events'], plugins: [ typescript() ] diff --git a/src/Body.spec.ts b/src/Body.spec.ts index e699336..837071f 100644 --- a/src/Body.spec.ts +++ b/src/Body.spec.ts @@ -1,5 +1,5 @@ -import Body from "./Body" -import Vector from "./Vector" +import Body from './Body' +import Vector from './Vector' describe('Body', () => { describe('setExternalForces', () => { diff --git a/src/Simulation.spec.ts b/src/Simulation.spec.ts new file mode 100644 index 0000000..7f28129 --- /dev/null +++ b/src/Simulation.spec.ts @@ -0,0 +1,52 @@ +import Body from './Body' +import Simulation from './Simulation' +import Vector from './Vector' + +describe('Simulation', () => { + it('should call changeCallback', async () => { + let resolver: (value?: unknown) => void + const promise = new Promise((resolve) => { resolver = resolve }) + + const simulation = new Simulation({ + bodies: [], + renderInterval: 0, + changeCallback: () => { resolver() } + }) + + await promise + simulation.stop() + }) + + it('should move bodies through universe', async () => { + let resolver: (value?: unknown) => void + const promise = new Promise((resolve) => { resolver = resolve }) + + const startingPositions = [ + new Vector(1, 1, 1), + new Vector(-1, -1, -1) + ] + + const simulation = new Simulation({ + bodies: [ + new Body({ + position: startingPositions[0], + velocity: new Vector(0, 0, 0) + }), + new Body({ + position: startingPositions[1], + velocity: new Vector(0, 0, 0) + }) + ], + renderInterval: 0, + changeCallback: () => { resolver() } + }) + + expect(simulation.bodies).toBe(simulation.universe.bodies) + + await promise + simulation.stop() + + expect(simulation.bodies[0].position).not.toEqual(startingPositions[0]) + expect(simulation.bodies[1].position).not.toEqual(startingPositions[1]) + }) +}) diff --git a/src/Simulation.ts b/src/Simulation.ts index dc8f810..8f1caec 100644 --- a/src/Simulation.ts +++ b/src/Simulation.ts @@ -1,4 +1,3 @@ -import EventEmitter from 'node:events' import Universe from './Universe' import Body from './Body' @@ -10,8 +9,8 @@ export default class Simulation { renderInterval: number universe: Universe - eventEmitter: EventEmitter simulationInterval: NodeJS.Timeout + changeCallback: () => void constructor({ /** orbital bodies in the simulation */ @@ -23,19 +22,23 @@ export default class Simulation { /** simulation time elapsed between iterations */ deltaTime, /** computer time between iterations */ - renderInterval + renderInterval, + /** callback fired when simulation state changes */ + changeCallback }: { bodies: Body[] gravity?: number collisions?: boolean deltaTime?: number renderInterval?: number + changeCallback: () => void }) { this.bodies = bodies this.gravity = gravity ?? 6.674e-11 this.collisions = collisions ?? false this.deltaTime = deltaTime ?? 0.5 this.renderInterval = renderInterval ?? 10 + this.changeCallback = changeCallback this.universe = new Universe({ bodies: this.bodies, @@ -44,10 +47,20 @@ export default class Simulation { deltaTime: this.deltaTime }) - this.eventEmitter = new EventEmitter() + this.start() + } + + /** start simulation */ + start() { + clearInterval(this.simulationInterval) this.simulationInterval = setInterval(() => { this.universe.moveBodiesThroughTime() - this.eventEmitter.emit('deltaTime') - }, renderInterval) + this.changeCallback() + }, this.renderInterval) + } + + /** stop simulation */ + stop() { + clearInterval(this.simulationInterval) } } diff --git a/src/StableUniverses.ts b/src/StableUniverses.ts index 4266690..28db6cb 100644 --- a/src/StableUniverses.ts +++ b/src/StableUniverses.ts @@ -84,19 +84,19 @@ export const FigureEight = new Universe({ mass: 1, position: new Vector(0.97000436, -0.24308753, 0), velocity: new Vector(0.466203685, 0.43236573, 0), - color: "#3d9900" + color: '#3d9900' }), new Body({ mass: 1, position: new Vector(-0.97000436, 0.24308753, 0), velocity: new Vector(0.466203685, 0.43236573, 0), - color: "#00314e" + color: '#00314e' }), new Body({ mass: 1, position: new Vector(0, 0, 0), velocity: new Vector(-0.93240737, -0.86473146, 0), - color: "#008ebd" + color: '#008ebd' }) ], gravity: 1, collisions: false, deltaTime: 0.005 diff --git a/src/Vector.spec.ts b/src/Vector.spec.ts index 9552012..fcbc51a 100644 --- a/src/Vector.spec.ts +++ b/src/Vector.spec.ts @@ -1,4 +1,4 @@ -import Vector from "./Vector" +import Vector from './Vector' describe('Vector', () => { describe('constructor', () => {