Files
2026-09-24 17:57:54 +02:00

89 lines
2.9 KiB
JavaScript

import { describe, expect, it } from 'vitest';
import {
angleTo,
clamp,
clampLength,
directionFromKeys,
distance,
inCircle,
length,
normalize,
rotate,
} from '../../app/static/js/logic/math.js';
import { createRng, pick, randFloat, randInt } from '../../app/static/js/logic/rng.js';
describe('math', () => {
it('clamp begrenzt Werte', () => {
expect(clamp(5, 0, 3)).toBe(3);
expect(clamp(-1, 0, 3)).toBe(0);
expect(clamp(2, 0, 3)).toBe(2);
});
it('normalize lässt den Nullvektor unverändert', () => {
expect(normalize({ x: 0, y: 0 })).toEqual({ x: 0, y: 0 });
expect(length(normalize({ x: 3, y: 4 }))).toBeCloseTo(1);
});
it('clampLength kürzt nur zu lange Vektoren', () => {
expect(length(clampLength({ x: 30, y: 40 }, 10))).toBeCloseTo(10);
expect(clampLength({ x: 1, y: 1 }, 10)).toEqual({ x: 1, y: 1 });
});
it('rotate und angleTo passen zusammen', () => {
const r = rotate({ x: 1, y: 0 }, Math.PI / 2);
expect(r.x).toBeCloseTo(0);
expect(r.y).toBeCloseTo(1);
expect(angleTo({ x: 0, y: 0 }, { x: 0, y: 5 })).toBeCloseTo(Math.PI / 2);
});
it('inCircle berücksichtigt die Ausdehnung des Objekts', () => {
expect(inCircle({ x: 110, y: 0 }, { x: 0, y: 0 }, 100)).toBe(false);
expect(inCircle({ x: 110, y: 0 }, { x: 0, y: 0 }, 100, 12)).toBe(true);
expect(distance({ x: 0, y: 0 }, { x: 3, y: 4 })).toBe(5);
});
it('directionFromKeys normalisiert Diagonalen (8-Wege-Bewegung)', () => {
expect(directionFromKeys({ up: true, down: false, left: false, right: false })).toEqual({ x: 0, y: -1 });
const diag = directionFromKeys({ up: true, down: false, left: false, right: true });
expect(length(diag)).toBeCloseTo(1);
expect(diag.x).toBeGreaterThan(0);
expect(diag.y).toBeLessThan(0);
expect(directionFromKeys({ up: true, down: true, left: true, right: true })).toEqual({ x: 0, y: 0 });
});
});
describe('rng', () => {
it('ist mit gleichem Seed deterministisch und liegt in [0, 1)', () => {
const a = createRng(123);
const b = createRng(123);
for (let i = 0; i < 1000; i += 1) {
const value = a();
expect(value).toBe(b());
expect(value).toBeGreaterThanOrEqual(0);
expect(value).toBeLessThan(1);
}
});
it('randInt deckt die Grenzen ab und bleibt im Intervall', () => {
const rng = createRng(7);
const seen = new Set();
for (let i = 0; i < 500; i += 1) {
const n = randInt(rng, 1, 3);
expect(n).toBeGreaterThanOrEqual(1);
expect(n).toBeLessThanOrEqual(3);
seen.add(n);
}
expect(seen).toEqual(new Set([1, 2, 3]));
});
it('randFloat und pick verhalten sich korrekt', () => {
const rng = createRng(9);
const f = randFloat(rng, 5, 6);
expect(f).toBeGreaterThanOrEqual(5);
expect(f).toBeLessThan(6);
expect(['a', 'b']).toContain(pick(rng, ['a', 'b']));
expect(() => pick(rng, [])).toThrow();
});
});