import { describe, expect, it } from 'vitest';
import { blobPlacement, sunShadow } from '../shadowSim';
describe('sunShadow', () => {
it('ночью тени нет', () => {
expect(sunShadow(2)).toBeNull();
expect(sunShadow(23)).toBeNull();
expect(sunShadow(5.5)).toBeNull();
});
it('на границах дня альфа нулевая, в разгар дня максимальная', () => {
expect(sunShadow(6)!.alpha).toBeCloseTo(0);
expect(sunShadow(19.9)!.alpha).toBeCloseTo(0); // к закату гаснет (в 20 — null)
const noon = sunShadow(13)!.alpha;
expect(noon).toBeGreaterThan(0.3);
const morning = sunShadow(7)!.alpha; // ещё в разгоне (dawn..day = 6..8)
expect(morning).toBeGreaterThan(0);
expect(morning).toBeLessThan(noon);
});
it('тень утром на запад экрана, вечером на восток', () => {
expect(sunShadow(7)!.dirX).toBeLessThan(-0.5);
expect(sunShadow(19)!.dirX).toBeGreaterThan(0.5);
expect(sunShadow(13)!.dirX).toBeCloseTo(0); // полдень — почти под объектом
});
it('длина максимальна утром/вечером, минимальна в полдень', () => {
const noon = sunShadow(13)!.len;
const morning = sunShadow(7)!.len;
const evening = sunShadow(19)!.len;
expect(noon).toBeLessThan(morning);
expect(noon).toBeLessThan(evening);
expect(morning).toBeCloseTo(evening, 1); // симметричный день
});
it('вектор направления единичный', () => {
for (let h = 6; h < 20; h += 0.5) {
const s = sunShadow(h)!;
expect(Math.hypot(s.dirX, s.dirY)).toBeCloseTo(1);
}
});
});
describe('blobPlacement', () => {
it('эллипс тянется от базы вдоль направления тени', () => {
const sun = { dirX: 1, dirY: 0, len: 1, alpha: 0.3 };
const b = blobPlacement(10, 40, sun);
expect(b.x).toBeCloseTo((40 + 8) / 2); // reach = height·len
expect(b.y).toBe(0);
expect(b.scaleX).toBeCloseTo(24);
expect(b.scaleY).toBeCloseTo(10); // 0.7 + 0.3·len = 1.0 при len=1
expect(b.alpha).toBeCloseTo(0.3);
expect(b.rotation).toBeCloseTo(0);
});
it('длинная утренняя тень дальше, чем короткая полуденная', () => {
const morning = blobPlacement(10, 40, { dirX: -1, dirY: 0, len: 1.5, alpha: 0.3 });
const noon = blobPlacement(10, 40, { dirX: 0, dirY: 1, len: 0.6, alpha: 0.3 });
expect(Math.hypot(morning.x, morning.y)).toBeGreaterThan(Math.hypot(noon.x, noon.y));
});
it('поворот соответствует направлению тени', () => {
const b = blobPlacement(10, 40, { dirX: 0, dirY: 1, len: 1, alpha: 0.3 });
expect(b.rotation).toBeCloseTo(Math.PI / 2);
});
});