mirror of
https://github.com/TextPlace/CoreTextPlace.git
synced 2025-07-06 19:55:34 +00:00
feat: on-demand section creation & 0.3.0.
This commit is contained in:
parent
dbfeb13c47
commit
5077995eb3
3 changed files with 87 additions and 28 deletions
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@textplace/core",
|
"name": "@textplace/core",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"exports": "./mod.ts",
|
"exports": "./mod.ts",
|
||||||
"imports": {
|
"imports": {
|
||||||
"@deno/dnt": "jsr:@deno/dnt@^0.41.3"
|
"@deno/dnt": "jsr:@deno/dnt@^0.41.3"
|
||||||
|
|
|
@ -9,15 +9,7 @@ import { applyChange, createSection } from "./section.ts";
|
||||||
import type { BoardChange } from "../types/change.ts";
|
import type { BoardChange } from "../types/change.ts";
|
||||||
|
|
||||||
export function createBoard(config: BoardConfig): BoardData {
|
export function createBoard(config: BoardConfig): BoardData {
|
||||||
const sections: SectionData[][] = Array(config.ySections)
|
return { config, sections: [] };
|
||||||
.fill(0)
|
|
||||||
.map((_, sy) =>
|
|
||||||
Array(config.xSections)
|
|
||||||
.fill(0)
|
|
||||||
.map((_, sx) => createSection({ sx, sy }, config))
|
|
||||||
);
|
|
||||||
|
|
||||||
return { config, sections };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function locateSection(
|
export function locateSection(
|
||||||
|
@ -30,9 +22,38 @@ export function locateSection(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a section from board.
|
||||||
|
*
|
||||||
|
* If the section does not exist yet, it will be created and (optionally) added to `board`.
|
||||||
|
*/
|
||||||
|
export function getSectionOnBoard(
|
||||||
|
{ sx, sy }: SectionPosition,
|
||||||
|
board: BoardData,
|
||||||
|
options: {
|
||||||
|
/**
|
||||||
|
* Whether the section data is only used for reading.
|
||||||
|
*
|
||||||
|
* If `true`, this function will return an empty section configured with default values, but will not add it to the board data to save storage.
|
||||||
|
*/
|
||||||
|
readOnly: boolean;
|
||||||
|
} = { readOnly: false },
|
||||||
|
): SectionData {
|
||||||
|
let section: SectionData;
|
||||||
|
if (!board.sections[sy] && !options.readOnly) board.sections[sy] = [];
|
||||||
|
|
||||||
|
if (!board.sections[sy]?.[sx]) {
|
||||||
|
section = createSection({ sx, sy }, board.config);
|
||||||
|
if (!options.readOnly) board.sections[sy][sx] = section;
|
||||||
|
} else {
|
||||||
|
section = board.sections[sy][sx];
|
||||||
|
}
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
export function applyChangeOnBoard(change: BoardChange, board: BoardData) {
|
export function applyChangeOnBoard(change: BoardChange, board: BoardData) {
|
||||||
const { sx, sy } = locateSection(change, board.config);
|
const sPos = locateSection(change, board.config);
|
||||||
const section = board.sections[sy][sx];
|
const section = getSectionOnBoard(sPos, board);
|
||||||
applyChange(change, section);
|
applyChange(change, section);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +80,8 @@ export function renderFullBoard(data: BoardData): FullBoard {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { sx, sy } = locateSection({ x, y }, data.config);
|
const sPos = locateSection({ x, y }, data.config);
|
||||||
const section = data.sections[sy][sx];
|
const section = getSectionOnBoard(sPos, data, { readOnly: true });
|
||||||
const xInSection = x % data.config.sectionWidth;
|
const xInSection = x % data.config.sectionWidth;
|
||||||
const yInSection = y % data.config.sectionHeight;
|
const yInSection = y % data.config.sectionHeight;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,11 @@ import {
|
||||||
assertEquals,
|
assertEquals,
|
||||||
} from "https://deno.land/std@0.224.0/assert/mod.ts";
|
} from "https://deno.land/std@0.224.0/assert/mod.ts";
|
||||||
|
|
||||||
import { createBoard, renderFullBoard } from "../logic/board.ts";
|
import {
|
||||||
|
createBoard,
|
||||||
|
getSectionOnBoard,
|
||||||
|
renderFullBoard,
|
||||||
|
} from "../logic/board.ts";
|
||||||
import type { BoardData } from "../types/board.ts";
|
import type { BoardData } from "../types/board.ts";
|
||||||
import { checkFullBoard } from "./checkFullBoard.ts";
|
import { checkFullBoard } from "./checkFullBoard.ts";
|
||||||
import { locateSection } from "../logic/board.ts";
|
import { locateSection } from "../logic/board.ts";
|
||||||
|
@ -14,8 +18,8 @@ Deno.test("board", async (t) => {
|
||||||
|
|
||||||
await t.step("createBoard", () => {
|
await t.step("createBoard", () => {
|
||||||
board = createBoard({
|
board = createBoard({
|
||||||
xSections: 2,
|
xSections: 3,
|
||||||
ySections: 2,
|
ySections: 3,
|
||||||
sectionWidth: 4,
|
sectionWidth: 4,
|
||||||
sectionHeight: 3,
|
sectionHeight: 3,
|
||||||
defaultCh: " ",
|
defaultCh: " ",
|
||||||
|
@ -24,17 +28,8 @@ Deno.test("board", async (t) => {
|
||||||
defaultWidth: 1,
|
defaultWidth: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
assertEquals(board.sections.length, 2);
|
// Sections are created on demand.
|
||||||
assertEquals(board.sections[0].length, 2);
|
assertEquals(board.sections.length, 0);
|
||||||
assertEquals(board.sections[0][0].offsetX, 0);
|
|
||||||
assertEquals(board.sections[0][0].offsetY, 0);
|
|
||||||
assertEquals(board.sections[0][1].offsetX, 4);
|
|
||||||
assertEquals(board.sections[0][1].offsetY, 0);
|
|
||||||
assertEquals(board.sections[1].length, 2);
|
|
||||||
assertEquals(board.sections[1][0].offsetX, 0);
|
|
||||||
assertEquals(board.sections[1][0].offsetY, 3);
|
|
||||||
assertEquals(board.sections[1][1].offsetX, 4);
|
|
||||||
assertEquals(board.sections[1][1].offsetY, 3);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await t.step("locateSection", () => {
|
await t.step("locateSection", () => {
|
||||||
|
@ -73,10 +68,53 @@ Deno.test("board", async (t) => {
|
||||||
assertEquals(board.sections[1][1].ch[2][0], "嘛");
|
assertEquals(board.sections[1][1].ch[2][0], "嘛");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await t.step("getSectionOnBoard: existing section", () => {
|
||||||
|
assert(board);
|
||||||
|
|
||||||
|
const section = getSectionOnBoard({ sx: 1, sy: 1 }, board, {
|
||||||
|
readOnly: true,
|
||||||
|
});
|
||||||
|
assertEquals(section.ch[0][0], "嘛");
|
||||||
|
assertEquals(section.color[0][0], "F");
|
||||||
|
assertEquals(section.bgColor[0][0], "0");
|
||||||
|
assertEquals(section.width[0][0], 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
await t.step("getSectionOnBoard: non-existing row", () => {
|
||||||
|
assert(board);
|
||||||
|
|
||||||
|
const section = getSectionOnBoard({ sx: 1, sy: 2 }, board, {
|
||||||
|
readOnly: true,
|
||||||
|
});
|
||||||
|
assertEquals(section.ch[0][0], " ");
|
||||||
|
assertEquals(section.color[0][0], "F");
|
||||||
|
assertEquals(section.bgColor[0][0], "0");
|
||||||
|
assertEquals(section.width[0][0], 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
await t.step("getSectionOnBoard: non-existing section", () => {
|
||||||
|
assert(board);
|
||||||
|
|
||||||
|
const section = getSectionOnBoard({ sx: 2, sy: 1 }, board, {
|
||||||
|
readOnly: true,
|
||||||
|
});
|
||||||
|
assertEquals(section.ch[0][0], " ");
|
||||||
|
assertEquals(section.color[0][0], "F");
|
||||||
|
assertEquals(section.bgColor[0][0], "0");
|
||||||
|
assertEquals(section.width[0][0], 1);
|
||||||
|
});
|
||||||
|
|
||||||
await t.step("renderFullBoard", () => {
|
await t.step("renderFullBoard", () => {
|
||||||
assert(board);
|
assert(board);
|
||||||
|
|
||||||
const rendered = renderFullBoard(board);
|
const rendered = renderFullBoard(board);
|
||||||
checkFullBoard(rendered);
|
checkFullBoard(rendered);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await t.step("on-demand creation: only changed sections are saved", () => {
|
||||||
|
assert(board);
|
||||||
|
|
||||||
|
assertEquals(board.sections.length, 2);
|
||||||
|
assertEquals(board.sections[0].length, 2);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue