import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { describe, expect, it } from 'vitest';
import { encodeMap, parseMap } from '@rpg/engine';
import {
buildMeadowsMap,
buildPondsMap,
buildZvenetsMap,
buildHouseElderMap,
buildShopMap
} from '../../src/data/map';
/**
* Карты-файлы: fresh-тест (диск == генератор) и round-trip RLE — read-only
* и идут в каждом `npm test`. Запись файлов — только при RUN_MAPS_GEN=1
* (`npm run maps`): обычный прогон тестов не трогает рабочее дерево.
*/
const here = dirname(fileURLToPath(import.meta.url));
const outDir = resolve(here, '../../assets/maps');
const gen = !!process.env.RUN_MAPS_GEN;
const d = gen ? describe : describe.skip;
const MAPS: Record<string, ReturnType<typeof buildMeadowsMap>> = {
meadows: buildMeadowsMap(),
ponds: buildPondsMap(),
zvenets: buildZvenetsMap(),
house_elder: buildHouseElderMap(),
shop: buildShopMap()
};
describe('карты-файлы на диске равны генераторам (fresh)', () => {
for (const [id, data] of Object.entries(MAPS)) {
it(`${id}.map не разъехался с генератором (npm run maps лечит)`, () => {
const path = resolve(outDir, `${id}.map`);
const onDisk = JSON.parse(readFileSync(path, 'utf8'));
expect(onDisk).toEqual(encodeMap(data));
});
}
});
describe('rpg-map, RLE (round-trip, read-only)', () => {
for (const [id, data] of Object.entries(MAPS)) {
it(`${id}: encode -> parse восстанавливает карту`, () => {
const back = parseMap(JSON.parse(JSON.stringify(encodeMap(data))));
expect(back.width).toBe(data.width);
expect(back.height).toBe(data.height);
expect(back.blocked).toEqual(data.blocked);
expect(back.tiles).toEqual(data.tiles);
expect(back.tall).toEqual(data.tall);
});
}
it('RLE реально сжимает карты', () => {
for (const [id, data] of Object.entries(MAPS)) {
const file = encodeMap(data);
const pairs = file.tiles as [number, number][];
// Серий меньше, чем тайлов: RLE что-то ужал, несмотря на пятнистость
expect(pairs.length).toBeLessThan(data.tiles.length);
expect(file.encoding).toBe('rle');
expect(id.length).toBeGreaterThan(0);
}
});
});
d('запись карт-файлов (RUN_MAPS_GEN=1 / npm run maps)', () => {
for (const [id, data] of Object.entries(MAPS)) {
it(`${id}: пишет assets/maps/${id}.map`, () => {
const file = encodeMap(data);
mkdirSync(outDir, { recursive: true });
writeFileSync(resolve(outDir, `${id}.map`), JSON.stringify(file));
expect(true).toBe(true);
});
}
});