mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 16:34:06 +01:00
Moves the standalone React 19 + Vite 8 + TypeScript 6 game from ~/Downloads/reverse/reverse-survivors into reverse_survivors/, so it is version-controlled, indexed, and covered by CI instead of sitting untracked outside any repository. - Relocates the project's nested .github/workflows/ci.yml to the repository root as .github/workflows/reverse-survivors-ci.yml. GitHub only reads workflows from the root, so the nested copy would have been inert — same treatment billsplit received. The workflow is path-scoped to reverse_survivors/** and runs npm ci / check / build on Node 22. - Sets cache-dependency-path on actions/setup-node, since defaults.run.working-directory applies only to run: steps and not to actions; without it the npm cache looks for a lockfile at the root. - Keeps npm and the existing package-lock.json. TypeScript stays pinned at 6.0.3 deliberately: typescript-eslint 8.65 caps its peer range at <6.1.0 and TS 7 drops the JS compiler API that typed linting needs. - Adds a reverse_survivors/ row to the Repository Layout table in README.md and CLAUDE.md. Verified in place: npm ci, npm run check (95 tests, 100% statements / branches / functions / lines), npm run build, and a dev-server smoke check serving /src/main.tsx. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
74 lines
2.1 KiB
TypeScript
74 lines
2.1 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { createRng, nextFloat, nextInt, pick } from './rng'
|
|
import { clamp, dist, toward } from './vec'
|
|
|
|
describe('vec', () => {
|
|
it('measures distance', () => {
|
|
expect(dist({ x: 0, y: 0 }, { x: 3, y: 4 })).toBe(5)
|
|
})
|
|
|
|
it('builds a velocity toward a target with the requested speed', () => {
|
|
const v = toward({ x: 0, y: 0 }, { x: 10, y: 0 }, 50)
|
|
expect(v).toEqual({ x: 50, y: 0 })
|
|
})
|
|
|
|
it('returns zero velocity for coincident points', () => {
|
|
expect(toward({ x: 5, y: 5 }, { x: 5, y: 5 }, 99)).toEqual({ x: 0, y: 0 })
|
|
})
|
|
|
|
it('clamps below, inside, and above the range', () => {
|
|
expect(clamp(-1, 0, 10)).toBe(0)
|
|
expect(clamp(4, 0, 10)).toBe(4)
|
|
expect(clamp(11, 0, 10)).toBe(10)
|
|
})
|
|
})
|
|
|
|
describe('rng', () => {
|
|
it('is deterministic for a given seed', () => {
|
|
const a = createRng(123)
|
|
const b = createRng(123)
|
|
expect([nextFloat(a), nextFloat(a), nextFloat(a)])
|
|
.toEqual([nextFloat(b), nextFloat(b), nextFloat(b)])
|
|
})
|
|
|
|
it('produces different sequences for different seeds', () => {
|
|
expect(nextFloat(createRng(1))).not.toBe(nextFloat(createRng(2)))
|
|
})
|
|
|
|
it('stays within [0, 1)', () => {
|
|
const rng = createRng(77)
|
|
for (let i = 0; i < 200; i += 1) {
|
|
const v = nextFloat(rng)
|
|
expect(v).toBeGreaterThanOrEqual(0)
|
|
expect(v).toBeLessThan(1)
|
|
}
|
|
})
|
|
|
|
it('wraps negative seeds into unsigned space', () => {
|
|
expect(createRng(-1).s).toBe(0xffffffff)
|
|
})
|
|
|
|
it('nextInt stays within [0, max)', () => {
|
|
const rng = createRng(9)
|
|
for (let i = 0; i < 100; i += 1) {
|
|
const v = nextInt(rng, 4)
|
|
expect(v).toBeGreaterThanOrEqual(0)
|
|
expect(v).toBeLessThan(4)
|
|
}
|
|
})
|
|
|
|
it('pick eventually returns every element of a tuple', () => {
|
|
const rng = createRng(5)
|
|
const seen = new Set<string>()
|
|
for (let i = 0; i < 64; i += 1) {
|
|
seen.add(pick(rng, ['a', 'b', 'c'] as const))
|
|
}
|
|
expect(seen).toEqual(new Set(['a', 'b', 'c']))
|
|
})
|
|
|
|
it('pick is deterministic', () => {
|
|
expect(pick(createRng(42), [10, 20, 30] as const))
|
|
.toBe(pick(createRng(42), [10, 20, 30] as const))
|
|
})
|
|
})
|