mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-25 11:04:00 +00:00
Start sketching out new resize algo
This commit is contained in:
parent
8a13222aa0
commit
797aeffa17
3 changed files with 374 additions and 0 deletions
199
experiments/resizeAlgorithm/resizeUtils.test.js
Normal file
199
experiments/resizeAlgorithm/resizeUtils.test.js
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
import fs from "fs";
|
||||
|
||||
import { double } from "./resizeUtils";
|
||||
|
||||
function compositeContains(composite, value) {
|
||||
return !!(composite & value);
|
||||
}
|
||||
|
||||
const decomposeValues = composite =>
|
||||
[1, 2, 4].filter(value => compositeContains(composite, value));
|
||||
|
||||
function matrixFromMap(map) {
|
||||
return map
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map(row => row.trim().split(""));
|
||||
}
|
||||
|
||||
function walkMatrix(matrix, cb) {
|
||||
matrix.forEach((row, y) => {
|
||||
row.forEach((value, x) => {
|
||||
cb(x, y, value);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function boxesFromMatrix(matrix) {
|
||||
const boxes = new Map();
|
||||
walkMatrix(matrix, (x, y, composite) => {
|
||||
const values = decomposeValues(composite);
|
||||
values.forEach(value => {
|
||||
if (!boxes.has(value)) {
|
||||
// Initialize the box
|
||||
boxes.set(value, { top: y, left: x, width: 1, height: 1 });
|
||||
} else {
|
||||
const box = boxes.get(value);
|
||||
if (box.top === y && x - box.left === box.width) {
|
||||
// The top side is still growing.
|
||||
box.width++;
|
||||
} else if (box.left === x && y - box.top === box.height) {
|
||||
// The left side is still growing.
|
||||
box.height++;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return boxes;
|
||||
}
|
||||
|
||||
function parseBoxes(map) {
|
||||
return boxesFromMatrix(matrixFromMap(map));
|
||||
}
|
||||
|
||||
function boxContains(box, pos) {
|
||||
if (
|
||||
pos.x >= box.left &&
|
||||
pos.x < box.left + box.width &&
|
||||
pos.y >= box.top &&
|
||||
pos.y < box.top + box.height
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function matrixFromBoxes(boxes) {
|
||||
let width = 0;
|
||||
let height = 0;
|
||||
boxes.forEach(box => {
|
||||
width = Math.max(width, box.left + box.width);
|
||||
height = Math.max(height, box.top + box.height);
|
||||
});
|
||||
const matrix = [];
|
||||
for (let y = 0; y < height; y++) {
|
||||
if (!matrix[y]) {
|
||||
matrix[y] = [];
|
||||
}
|
||||
for (let x = 0; x < width; x++) {
|
||||
let cellNumber = 0;
|
||||
boxes.forEach((box, boxNumber) => {
|
||||
if (boxContains(box, { x, y })) {
|
||||
cellNumber += Number(boxNumber);
|
||||
}
|
||||
});
|
||||
matrix[y].push(String(cellNumber || " "));
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
function mapFromMatrix(matrix) {
|
||||
return matrix.map(row => row.join("")).join("\n");
|
||||
}
|
||||
|
||||
function assertionsFromTxt(txtPath) {
|
||||
return fs
|
||||
.readFileSync(txtPath, "utf8")
|
||||
.split(/\=\=\= /)
|
||||
.filter(Boolean)
|
||||
.map(assertionText => {
|
||||
const lines = assertionText.split("\n");
|
||||
const [message, ...bodyLines] = lines;
|
||||
let [input, output] = bodyLines.join("\n").split("---\n");
|
||||
input = input.trim();
|
||||
output = output.trim();
|
||||
return { message, input, output };
|
||||
});
|
||||
}
|
||||
|
||||
xdescribe("integration", () => {
|
||||
assertionsFromTxt(
|
||||
"./js/__fixtures__/resizeDoubleTestCases.txt"
|
||||
).forEach(({ input, output, message }) => {
|
||||
it(message, () => {
|
||||
const matrix = matrixFromMap(input);
|
||||
const boxes = boxesFromMatrix(matrix);
|
||||
const doubledBoxes = double(boxes);
|
||||
const derivedMatrix = matrixFromBoxes(doubledBoxes);
|
||||
const derivedMap = mapFromMatrix(derivedMatrix);
|
||||
expect(derivedMap).toEqual(output);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("matrixFromBoxes", () => {
|
||||
it("can make a matrix from a box", () => {
|
||||
const boxes = new Map([["1", { top: 0, left: 0, width: 4, height: 4 }]]);
|
||||
expect(matrixFromBoxes(boxes)).toEqual(
|
||||
matrixFromMap(`
|
||||
1111
|
||||
1111
|
||||
1111
|
||||
1111
|
||||
`)
|
||||
);
|
||||
});
|
||||
it("can make a matrix from two boxes", () => {
|
||||
const boxes = new Map([
|
||||
["1", { top: 0, left: 0, width: 4, height: 4 }],
|
||||
["2", { top: 1, left: 1, width: 2, height: 2 }]
|
||||
]);
|
||||
expect(matrixFromBoxes(boxes)).toEqual(
|
||||
matrixFromMap(`
|
||||
1111
|
||||
1331
|
||||
1331
|
||||
1111
|
||||
`)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseBoxes", () => {
|
||||
it("parses a box", () => {
|
||||
const boxes = parseBoxes(`
|
||||
1111
|
||||
1111
|
||||
1111
|
||||
1111
|
||||
`);
|
||||
expect(boxes.get(1)).toEqual({ top: 0, left: 0, width: 4, height: 4 });
|
||||
});
|
||||
it("parses a smaller box", () => {
|
||||
const boxes = parseBoxes(`
|
||||
11
|
||||
11
|
||||
`);
|
||||
expect(boxes.get(1)).toEqual({ top: 0, left: 0, width: 2, height: 2 });
|
||||
});
|
||||
it("parses nested boxes", () => {
|
||||
const boxes = parseBoxes(`
|
||||
1111
|
||||
1331
|
||||
1331
|
||||
1111
|
||||
`);
|
||||
expect(boxes.get(1)).toEqual({ top: 0, left: 0, width: 4, height: 4 });
|
||||
expect(boxes.get(2)).toEqual({ top: 1, left: 1, width: 2, height: 2 });
|
||||
});
|
||||
it("parses overlapping boxes", () => {
|
||||
const boxes = parseBoxes(`
|
||||
110
|
||||
132
|
||||
022
|
||||
`);
|
||||
expect(boxes.get(1)).toEqual({ top: 0, left: 0, width: 2, height: 2 });
|
||||
expect(boxes.get(2)).toEqual({ top: 1, left: 1, width: 2, height: 2 });
|
||||
});
|
||||
it("parses three overlapping boxes", () => {
|
||||
const boxes = parseBoxes(`
|
||||
1154
|
||||
1374
|
||||
0220
|
||||
`);
|
||||
expect(boxes.get(1)).toEqual({ top: 0, left: 0, width: 3, height: 2 });
|
||||
expect(boxes.get(2)).toEqual({ top: 1, left: 1, width: 2, height: 2 });
|
||||
expect(boxes.get(4)).toEqual({ top: 0, left: 2, width: 2, height: 2 });
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue