A world-class math input for the web
1import { TokenFlow } from "../flow";
2
3export class GridFlow extends TokenFlow {
4 rows: number;
5 columns: number;
6
7 constructor(rows: number, columns: number) {
8 super();
9 this.rows = rows;
10 this.columns = columns;
11 }
12
13 get requiredLength(): number | null {
14 return this.rows * this.columns;
15 }
16
17 isWithin(
18 anchorIndex: number,
19 headIndex: number,
20 otherIndex: number
21 ): boolean {
22 const anchorRow = Math.floor(anchorIndex / this.columns);
23 const anchorCol = anchorIndex % this.columns;
24 const headRow = Math.floor(headIndex / this.columns);
25 const headCol = headIndex % this.columns;
26 const otherRow = Math.floor(otherIndex / this.columns);
27 const otherCol = otherIndex % this.columns;
28
29 const minRow = Math.min(anchorRow, headRow);
30 const maxRow = Math.max(anchorRow, headRow);
31 const minCol = Math.min(anchorCol, headCol);
32 const maxCol = Math.max(anchorCol, headCol);
33
34 return (
35 otherRow >= minRow &&
36 otherRow <= maxRow &&
37 otherCol >= minCol &&
38 otherCol <= maxCol
39 );
40 }
41
42 verticalCandidates(
43 direction: "up" | "down",
44 fromIndex: number,
45 length: number
46 ): number[] {
47 const row = Math.floor(fromIndex / this.columns);
48 const col = fromIndex % this.columns;
49 const candidates: number[] = [];
50
51 if (direction === "up" && row > 0) {
52 candidates.push((row - 1) * this.columns + col);
53 } else if (direction === "down" && row < this.rows - 1) {
54 candidates.push((row + 1) * this.columns + col);
55 }
56
57 return candidates.filter((index) => index < length);
58 }
59}