import { describe, expect, it } from 'vitest';
import { remapSlots } from '../paletteMap';
import { decodeModel } from '../format';
import type { VoxelPalette } from '../../voxel/grid';
import type { VoxelModel } from '../format';
const SCENE: VoxelPalette = {
colors: {
1: '#4a5340', 6: '#5b5b66', 7: '#94949e',
},
};
/** Модель 2×1×1: воксель слота 9 с «каменным» hex и слот 2 с «луговым». */
function makeModel(hexA: string, hexB: string): VoxelModel {
return {
size: [2, 1, 1],
palette: { 9: hexA, 2: hexB },
data: btoa(String.fromCharCode(9, 2)),
};
}
describe('remapSlots (палитра модели → палитра сцены)', () => {
it('точное совпадение hex перекладывает слоты 1:1', () => {
const m = remapSlots(makeModel('#5b5b66', '#4a5340'), SCENE);
const g = decodeModel(m);
expect(g.get(0, 0, 0)).toBe(6);
expect(g.get(1, 0, 0)).toBe(1);
expect(m.palette).toEqual({ 6: '#5b5b66', 1: '#4a5340' });
});
it('нет совпадения — ближайший по RGB', () => {
// #5d5d68 чуть светлее камня #5b5b66 → слот 6; #ffffff ближе всего к свету #94949e
const m = remapSlots(makeModel('#5d5d68', '#ffffff'), SCENE);
const g = decodeModel(m);
expect(g.get(0, 0, 0)).toBe(6);
expect(g.get(1, 0, 0)).toBe(7);
});
it('детерминирован и не трогает пустоту', () => {
const a = remapSlots(makeModel('#5d5d68', '#ffffff'), SCENE);
const b = remapSlots(makeModel('#5d5d68', '#ffffff'), SCENE);
expect(JSON.stringify(a)).toBe(JSON.stringify(b));
const g = decodeModel(a);
expect(g.get(0, 0, 1)).toBe(0); // вне размера не появилось
expect(g.count()).toBe(2);
});
});