Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,5 @@ Thumbs.db

# PyInstaller
/build/
/dist/
/dist/BrowserExtension/node_modules
BrowserExtension/node_modules/
8 changes: 8 additions & 0 deletions BrowserExtension/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
export class GridPuzzleCanvasProvider {
static getCanvasData(html: string): { pqqList: string[], size: number } {
const sizeMatch = html.match(/(?:gpl\.)?([Ss]ize)\s*=\s*(\d+);/);
if (!sizeMatch) {
throw new Error("Could not find grid size.");
}
const size = parseInt(sizeMatch[2], 10);

const pqqMatch = html.match(/(?:gpl\.)?pq{1,2}\s*=\s*"(.*?)";/);
if (!pqqMatch) {
throw new Error("Could not find grid data (pq/pqq).");
}
const pqqRaw = pqqMatch[1];
const pqqString = this.decodeIfCustomBase64(pqqRaw);
const pqqList = this.splitToList(pqqString, size);

return { pqqList, size };
}

static getCanvasDataExtended(html: string): { pqqList: string[], arList: string[], abList: string[], size: number } {
const { pqqList, size } = this.getCanvasData(html);

const arMatch = html.match(/ar_data\s*=\s*"(.*?)";/);
if (!arMatch) throw new Error("Could not find ar_data.");
const arString = this.decodeIfCustomBase64(arMatch[1]);
const arList = this.splitToList(arString, size);

const abMatch = html.match(/ab_data\s*=\s*"(.*?)";/);
if (!abMatch) throw new Error("Could not find ab_data.");
const abString = this.decodeIfCustomBase64(abMatch[1]);
const abList = this.splitToList(abString, size);

return { pqqList, arList, abList, size };
}

static decodeIfCustomBase64(str: string): string {
if (str.length < 4 || !this.isValidBase64(str.slice(3))) {
return str;
}
try {
return atob(str.slice(3));
} catch (e) {
console.warn("Base64 decode failed, returning original string", e);
return str;
}
}

static isValidBase64(str: string): boolean {
return str.length % 4 === 0 && /^[A-Za-z0-9+/]*={0,2}$/.test(str);
}

static splitToList(str: string, size: number): string[] {
const splitPipe = str.split('|');
if (splitPipe.length === size || splitPipe.length === size * size) {
return splitPipe;
}
return str.split('');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Grid } from "../../../Domain/Base/grid";

export class GridPuzzleProvider {
static makeOpenedGrid(rowCount: number, columnCount: number, matrixCells: Element[]): Grid<Set<string>> {
const bordersDict: { [key: string]: string } = {
'br': 'right',
'bl': 'left',
'bt': 'up',
'bb': 'down'
};

const allBorders = new Set(['up', 'down', 'left', 'right']);
const gridData: Set<string>[][] = [];

for (let r = 0; r < rowCount; r++) {
gridData[r] = [];
for (let c = 0; c < columnCount; c++) {
gridData[r][c] = new Set();
}
}

for (let i = 0; i < matrixCells.length; i++) {
const r = Math.floor(i / columnCount);
const c = i % columnCount;
const cell = matrixCells[i];

if (r >= rowCount) break;

const closedBorders = new Set<string>();

// Check for explicit border classes
cell.classList.forEach(cls => {
if (bordersDict[cls]) {
closedBorders.add(bordersDict[cls]);
}
});

// Add implicit boundary borders
if (r === 0) closedBorders.add('up');
if (r === rowCount - 1) closedBorders.add('down');
if (c === 0) closedBorders.add('left');
if (c === columnCount - 1) closedBorders.add('right');

// Calculate open borders: All - Closed
const openBorders = new Set<string>();
allBorders.forEach(b => {
if (!closedBorders.has(b)) {
openBorders.add(b);
}
});

gridData[r][c] = openBorders;
}

return new Grid(gridData);
}
}
Loading