diff --git a/src/Universe.spec.ts b/src/Universe.spec.ts index df93e1c..8e74297 100644 --- a/src/Universe.spec.ts +++ b/src/Universe.spec.ts @@ -3,13 +3,49 @@ import Universe from './Universe' import Vector from './Vector' describe('Universe', () => { + describe('parameter validation', () => { + it('should throw error if deltaTimeSegments is not a positive integer', () => { + expect(() => new Universe({ + bodies: [], + deltaTimeSegments: 0, + changeCallback: () => {} + })).toThrow('deltaTimeSegments must be a positive integer') + + expect(() => new Universe({ + bodies: [], + deltaTimeSegments: -1, + changeCallback: () => {} + })).toThrow('deltaTimeSegments must be a positive integer') + + expect(() => new Universe({ + bodies: [], + deltaTimeSegments: 1.1, + changeCallback: () => {} + })).toThrow('deltaTimeSegments must be a positive integer') + }) + + it('should throw error if simulationInterval is not positive', () => { + expect(() => new Universe({ + bodies: [], + simulationInterval: 0, + changeCallback: () => {} + })).toThrow('simulationInterval must be positive') + + expect(() => new Universe({ + bodies: [], + simulationInterval: -1, + changeCallback: () => {} + })).toThrow('simulationInterval must be positive') + }) + }) + it('should call changeCallback', async () => { let resolver: (value?: unknown) => void const promise = new Promise((resolve) => { resolver = resolve }) const universe = new Universe({ bodies: [], - simulationInterval: 0, + simulationInterval: 1, changeCallback: () => { resolver() } }) @@ -37,7 +73,7 @@ describe('Universe', () => { velocity: new Vector(0, 0, 0) }) ], - simulationInterval: 0, + simulationInterval: 1, changeCallback: () => { resolver() } }) diff --git a/src/Universe.ts b/src/Universe.ts index 48461e2..5d33e61 100644 --- a/src/Universe.ts +++ b/src/Universe.ts @@ -11,20 +11,23 @@ export default class Universe { changeCallback: () => void private internalInterval: NodeJS.Timeout + /** + * @param universe definition of the universe + * @param universe.bodies orbital bodies in the simulation + * @param universe.gravity gravitational strength + * @param universe.collisions should bodies collide? (elastically) + * @param universe.deltaTime simulation time elapsed between iterations + * @param universe.deltaTimeSegments number of segments in which to split the simlation time delta for more precise calculations + * @param universe.simulationInterval computer time between iterations + * @param universe.changeCallback callback fired when simulation state changes + */ constructor({ - /** orbital bodies in the simulation */ bodies, - /** gravitational strength */ gravity, - /** should bodies collide? (elastically) */ collisions, - /** simulation time elapsed between iterations */ deltaTime, - /** number of segments in which to split the simlation time delta for more precise calculations */ deltaTimeSegments, - /** computer time between iterations */ simulationInterval, - /** callback fired when simulation state changes */ changeCallback }: { bodies: Body[] @@ -36,13 +39,21 @@ export default class Universe { changeCallback: () => void }) { this.bodies = bodies - this.deltaTime = deltaTime ?? 0.5 this.gravity = gravity ?? 6.674e-11 this.collisions = collisions ?? false + this.deltaTime = deltaTime ?? 0.5 this.deltaTimeSegments = deltaTimeSegments ?? 1 this.simulationInterval = simulationInterval ?? 10 this.changeCallback = changeCallback + if (this.deltaTimeSegments % 1 || this.deltaTimeSegments < 1) { + throw new Error('deltaTimeSegments must be a positive integer') + } + + if (this.simulationInterval <= 0) { + throw new Error('simulationInterval must be positive') + } + this.start() } @@ -60,7 +71,7 @@ export default class Universe { clearInterval(this.internalInterval) } - calculateGravitationalForces = () => { + private calculateGravitationalForces = () => { const bodyForces: Vector[][] = Array.from({ length: this.bodies.length }, () => []) this.bodies.forEach((body1, index1) => { this.bodies.slice(index1 + 1).forEach((body2, index2) => { @@ -77,7 +88,7 @@ export default class Universe { }) } - bounceCollisions = (body1: Body, index1: number) => { + private bounceCollisions = (body1: Body, index1: number) => { this.bodies.forEach((body2, index2) => { if (index1 !== index2) { const distanceBetweenBodies = body2.position.distance(body1.position) @@ -104,7 +115,7 @@ export default class Universe { }) } - moveBodiesThroughTime = () => { + private moveBodiesThroughTime = () => { this.calculateGravitationalForces() this.bodies.forEach((body, index) => { const deltaTimePerSegment = this.deltaTime / this.deltaTimeSegments diff --git a/src/Vector.spec.ts b/src/Vector.spec.ts index fcbc51a..d17665d 100644 --- a/src/Vector.spec.ts +++ b/src/Vector.spec.ts @@ -84,7 +84,7 @@ describe('Vector', () => { it('should scale vector to factor', () => { expect(new Vector(1, 2, 3).scaleTo(3)) .toEqual(new Vector(expect.closeTo(0.8), expect.closeTo(1.6), expect.closeTo(2.41))) - expect(() => new Vector(1, -2, 3).scaleTo(-1)).toThrow(new Error('magnitude must be positive')) + expect(() => new Vector(1, -2, 3).scaleTo(-1)).toThrow('magnitude must be positive') }) }) })