diff --git a/.vscode/settings.json b/.vscode/settings.json index 2ba7ff8c..98958d46 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -25,7 +25,7 @@ "editor.suggest.snippetsPreventQuickSuggestions": false, "editor.suggestSelection": "first", "editor.tabCompletion": "onlySnippets", - "editor.wordBasedSuggestions": false + "editor.wordBasedSuggestions": "off" }, "[markdown]": { "editor.wordWrap": "on", diff --git a/modules/code-builder/src/collision/spec/Brute.spec.ts b/modules/code-builder/src/collision/spec/Brute.spec.ts new file mode 100644 index 00000000..37fce429 --- /dev/null +++ b/modules/code-builder/src/collision/spec/Brute.spec.ts @@ -0,0 +1,55 @@ +import CollisionSpaceBrute from '../Brute'; +import type { TCollisionObject } from '@/@types/collision'; + +describe('CollisionSpaceBrute', () => { + let collisionSpace: CollisionSpaceBrute; + + beforeEach(() => { + collisionSpace = new CollisionSpaceBrute(100, 100); + }); + + it('should add objects correctly', () => { + const objects: TCollisionObject[] = [ + { id: 'A', x: 10, y: 10, width: 10, height: 10 }, + { id: 'B', x: 20, y: 20, width: 10, height: 10 }, + ]; + collisionSpace.addObjects(objects); + expect(collisionSpace['_objects'].length).toBe(2); + }); + + it('should delete objects correctly', () => { + const objects: TCollisionObject[] = [ + { id: 'A', x: 10, y: 10, width: 10, height: 10 }, + { id: 'B', x: 20, y: 20, width: 10, height: 10 }, + ]; + collisionSpace.addObjects(objects); + collisionSpace.delObjects([{ id: 'A', x: 0, y: 0, width: 0, height: 0 }]); + expect(collisionSpace['_objects'].length).toBe(1); + expect(collisionSpace['_objects'][0].id).toBe('B'); + }); + + it('should check collisions correctly', () => { + const objects: TCollisionObject[] = [ + { id: 'A', x: 10, y: 10, width: 10, height: 10 }, + { id: 'B', x: 15, y: 15, width: 10, height: 10 }, + { id: 'C', x: 50, y: 50, width: 10, height: 10 }, + ]; + collisionSpace.addObjects(objects); + collisionSpace.setOptions({ objType: 'rect', colThres: 0 }); + + const collisions = collisionSpace.checkCollision({ id: 'Test', x: 12, y: 12, width: 10, height: 10 }); + expect(collisions).toContain('A'); + expect(collisions).toContain('B'); + expect(collisions).not.toContain('C'); + }); + + it('should reset correctly', () => { + const objects: TCollisionObject[] = [ + { id: 'A', x: 10, y: 10, width: 10, height: 10 }, + { id: 'B', x: 20, y: 20, width: 10, height: 10 }, + ]; + collisionSpace.addObjects(objects); + collisionSpace.reset(); + expect(collisionSpace['_objects'].length).toBe(0); + }); +}); \ No newline at end of file diff --git a/modules/code-builder/src/collision/spec/QuadTree.spec.ts b/modules/code-builder/src/collision/spec/QuadTree.spec.ts new file mode 100644 index 00000000..dec9cc7d --- /dev/null +++ b/modules/code-builder/src/collision/spec/QuadTree.spec.ts @@ -0,0 +1,64 @@ +import CollisionSpaceQuadTree from '../QuadTree'; +import type { TCollisionObject } from '@/@types/collision'; + +describe('CollisionSpaceQuadTree', () => { + let collisionSpace: CollisionSpaceQuadTree; + + beforeEach(() => { + collisionSpace = new CollisionSpaceQuadTree(100, 100); + }); + + it('should add objects correctly', () => { + const objects: TCollisionObject[] = [ + { id: 'A', x: 10, y: 10, width: 10, height: 10 }, + { id: 'B', x: 20, y: 20, width: 10, height: 10 }, + ]; + collisionSpace.addObjects(objects); + expect(collisionSpace['_objMap'].size).toBe(2); + }); + + it('should delete objects correctly', () => { + const objects: TCollisionObject[] = [ + { id: 'A', x: 10, y: 10, width: 10, height: 10 }, + { id: 'B', x: 20, y: 20, width: 10, height: 10 }, + ]; + collisionSpace.addObjects(objects); + collisionSpace.delObjects([{ id: 'A', x: 0, y: 0, width: 0, height: 0 }]); + expect(collisionSpace['_objMap'].size).toBe(1); + expect(collisionSpace['_objMap'].has('B')).toBe(true); + }); + + it('should check collisions correctly', () => { + const objects: TCollisionObject[] = [ + { id: 'A', x: 10, y: 10, width: 10, height: 10 }, + { id: 'B', x: 15, y: 15, width: 10, height: 10 }, + { id: 'C', x: 50, y: 50, width: 10, height: 10 }, + ]; + collisionSpace.addObjects(objects); + collisionSpace.setOptions({ objType: 'rect', colThres: 0 }); + + const collisions = collisionSpace.checkCollision({ id: 'Test', x: 12, y: 12, width: 10, height: 10 }); + expect(collisions).toContain('A'); + expect(collisions).toContain('B'); + expect(collisions).not.toContain('C'); + }); + + it('should reset correctly', () => { + const objects: TCollisionObject[] = [ + { id: 'A', x: 10, y: 10, width: 10, height: 10 }, + { id: 'B', x: 20, y: 20, width: 10, height: 10 }, + ]; + collisionSpace.addObjects(objects); + collisionSpace.reset(); + expect(collisionSpace['_objMap'].size).toBe(0); + }); + + it('should not add objects outside the collision space', () => { + const objects: TCollisionObject[] = [ + { id: 'A', x: -10, y: -10, width: 10, height: 10 }, + { id: 'B', x: 110, y: 110, width: 10, height: 10 }, + ]; + collisionSpace.addObjects(objects); + expect(collisionSpace['_objMap'].size).toBe(0); + }); +}); \ No newline at end of file diff --git a/modules/code-builder/src/collision/spec/utils.spec.ts b/modules/code-builder/src/collision/spec/utils.spec.ts new file mode 100644 index 00000000..6d301c51 --- /dev/null +++ b/modules/code-builder/src/collision/spec/utils.spec.ts @@ -0,0 +1,34 @@ +import { checkCollision } from '../utils'; +import type { TCollisionObject } from '@/@types/collision'; + +describe('Collision Utils', () => { + describe('checkCollision', () => { + const objA: TCollisionObject = { id: 'A', x: 0, y: 0, width: 10, height: 10 }; + const objB: TCollisionObject = { id: 'B', x: 5, y: 5, width: 10, height: 10 }; + const objC: TCollisionObject = { id: 'C', x: 20, y: 20, width: 10, height: 10 }; + + it('should detect collision between overlapping circles', () => { + expect(checkCollision(objA, objB, { objType: 'circle', colThres: 0 })).toBe(true); + }); + + it('should not detect collision between non-overlapping circles', () => { + expect(checkCollision(objA, objC, { objType: 'circle', colThres: 0 })).toBe(false); + }); + + it('should detect collision between overlapping rectangles', () => { + expect(checkCollision(objA, objB, { objType: 'rect', colThres: 0 })).toBe(true); + }); + + it('should not detect collision between non-overlapping rectangles', () => { + expect(checkCollision(objA, objC, { objType: 'rect', colThres: 0 })).toBe(false); + }); + + it('should respect collision threshold for circles', () => { + expect(checkCollision(objA, objB, { objType: 'circle', colThres: 0.9 })).toBe(false); + }); + + it('should respect collision threshold for rectangles', () => { + expect(checkCollision(objA, objB, { objType: 'rect', colThres: 0.9 })).toBe(false); + }); + }); +}); \ No newline at end of file