import { Num, Optional } from '@ephox/katamari';
export interface MatrixNavigationOutcome {
readonly rowIndex: number;
readonly columnIndex: number;
readonly cell: A;
}
export type MatrixNavigationFunc = (matrix: A[][], startRow: number, startCol: number) => Optional>;
const toCell = (matrix: A[][], rowIndex: number, columnIndex: number): Optional> => Optional.from(matrix[rowIndex]).bind((row) => Optional.from(row[columnIndex]).map((cell) => ({
rowIndex,
columnIndex,
cell
})));
const cycleHorizontal = (matrix: A[][], rowIndex: number, startCol: number, deltaCol: number) => {
const row = matrix[rowIndex];
const colsInRow = row.length;
const newColIndex = Num.cycleBy(startCol, deltaCol, 0, colsInRow - 1);
return toCell(matrix, rowIndex, newColIndex);
};
const cycleVertical = (matrix: A[][], colIndex: number, startRow: number, deltaRow: number) => {
const nextRowIndex = Num.cycleBy(startRow, deltaRow, 0, matrix.length - 1);
const colsInNextRow = matrix[nextRowIndex].length;
const nextColIndex = Num.clamp(colIndex, 0, colsInNextRow - 1);
return toCell(matrix, nextRowIndex, nextColIndex);
};
const moveHorizontal = (matrix: A[][], rowIndex: number, startCol: number, deltaCol: number) => {
const row = matrix[rowIndex];
const colsInRow = row.length;
const newColIndex = Num.clamp(startCol + deltaCol, 0, colsInRow - 1);
return toCell(matrix, rowIndex, newColIndex);
};
const moveVertical = (matrix: A[][], colIndex: number, startRow: number, deltaRow: number) => {
const nextRowIndex = Num.clamp(startRow + deltaRow, 0, matrix.length - 1);
const colsInNextRow = matrix[nextRowIndex].length;
const nextColIndex = Num.clamp(colIndex, 0, colsInNextRow - 1);
return toCell(matrix, nextRowIndex, nextColIndex);
};
// return address(Math.floor(index / columns), index % columns);
const cycleRight = (matrix: A[][], startRow: number, startCol: number): Optional> =>
cycleHorizontal(matrix, startRow, startCol, +1);
const cycleLeft = (matrix: A[][], startRow: number, startCol: number): Optional> =>
cycleHorizontal(matrix, startRow, startCol, -1);
const cycleUp = (matrix: A[][], startRow: number, startCol: number): Optional> =>
cycleVertical(matrix, startCol, startRow, -1);
const cycleDown = (matrix: A[][], startRow: number, startCol: number): Optional> =>
cycleVertical(matrix, startCol, startRow, +1);
const moveLeft = (matrix: A[][], startRow: number, startCol: number): Optional> =>
moveHorizontal(matrix, startRow, startCol, -1);
const moveRight = (matrix: A[][], startRow: number, startCol: number): Optional> =>
moveHorizontal(matrix, startRow, startCol, +1);
const moveUp = (matrix: A[][], startRow: number, startCol: number): Optional> =>
moveVertical(matrix, startCol, startRow, -1);
const moveDown = (matrix: A[][], startRow: number, startCol: number): Optional> =>
moveVertical(matrix, startCol, startRow, +1);
export {
cycleRight,
cycleLeft,
cycleUp,
cycleDown,
moveLeft,
moveRight,
moveUp,
moveDown
};