Initial commit: RHINE LAB · ANALYSIS OS:三维界面与动效实验(本仓库不含个人归档索引数据)
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { columnFiles, fileLocation } from "../src/data.ts";
|
||||
import {
|
||||
fileAtCell,
|
||||
selectionCell,
|
||||
visibleCell,
|
||||
poolCell,
|
||||
cellKey,
|
||||
LOOP_COLUMNS,
|
||||
LOOP_ROWS,
|
||||
wrap,
|
||||
} from "../src/archive-loop.ts";
|
||||
|
||||
// 每列的档案在零点两侧循环复用。列内条数不再固定为八条,
|
||||
// 所以用该列自己的 files.length 取模,而不是写死的 8。
|
||||
for (let lane = -23; lane <= 23; lane++) {
|
||||
const files = columnFiles(wrap(lane, 5));
|
||||
for (let row = -35; row <= 35; row++) {
|
||||
assert.equal(fileAtCell({ lane, row }), files[wrap(row - 12, files.length)]);
|
||||
}
|
||||
}
|
||||
let checks = 0;
|
||||
for (const direction of [-1, 1]) {
|
||||
let cell = { lane: 2, row: 12 };
|
||||
let index = fileAtCell(cell);
|
||||
const memory = Array.from({ length: 5 }, (_, lane) => columnFiles(lane)[0]);
|
||||
for (let step = 0; step < 10000; step++) {
|
||||
const axis = step % 17 < 10 ? "row" : "lane";
|
||||
const lane = fileLocation(index).lane;
|
||||
if (axis === "row") {
|
||||
const files = columnFiles(lane);
|
||||
index = files[wrap(files.indexOf(index) + direction, files.length)];
|
||||
} else index = memory[wrap(lane + direction, 5)];
|
||||
const next = selectionCell(index, cell, { axis, direction });
|
||||
assert.equal(
|
||||
next[axis] - cell[axis],
|
||||
direction,
|
||||
"Crossing a seam must move exactly one cell in the requested direction",
|
||||
);
|
||||
assert.equal(
|
||||
fileAtCell(next),
|
||||
index,
|
||||
"Selected physical cell must contain the requested document",
|
||||
);
|
||||
memory[fileLocation(index).lane] = index;
|
||||
cell = next;
|
||||
checks++;
|
||||
}
|
||||
}
|
||||
for (const center of [
|
||||
{ lane: 2, row: 12 },
|
||||
{ lane: -8.3, row: -19.2 },
|
||||
{ lane: 10002.49, row: -32001.49 },
|
||||
]) {
|
||||
const cells = Array.from({ length: LOOP_COLUMNS * LOOP_ROWS }, (_, i) =>
|
||||
visibleCell(i, center),
|
||||
);
|
||||
assert.equal(new Set(cells.map(cellKey)).size, LOOP_COLUMNS * LOOP_ROWS);
|
||||
const lanes = [...new Set(cells.map((c) => c.lane))].sort((a, b) => a - b);
|
||||
const rows = [...new Set(cells.map((c) => c.row))].sort((a, b) => a - b);
|
||||
assert.equal(lanes.length, LOOP_COLUMNS);
|
||||
assert.equal(rows.length, LOOP_ROWS);
|
||||
assert.equal(lanes.at(-1) - lanes[0], LOOP_COLUMNS - 1);
|
||||
assert.equal(rows.at(-1) - rows[0], LOOP_ROWS - 1);
|
||||
assert.ok(lanes[0] < center.lane - 3 && lanes.at(-1) > center.lane + 3);
|
||||
assert.ok(rows[0] < center.row - 14 && rows.at(-1) > center.row + 14);
|
||||
}
|
||||
for (let i = 0; i < 160; i++) {
|
||||
assert.deepEqual(
|
||||
poolCell(i),
|
||||
{ lane: Math.floor(i / 32), row: i % 32 },
|
||||
"Reference-animation instance order is preserved",
|
||||
);
|
||||
}
|
||||
console.log(
|
||||
JSON.stringify(
|
||||
{
|
||||
directionalMoves: checks,
|
||||
poolSize: LOOP_COLUMNS * LOOP_ROWS,
|
||||
referenceInstances: 160,
|
||||
checks: "passed",
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
Reference in New Issue
Block a user