Skip to content

Commit

Permalink
add descript to the algo solve
Browse files Browse the repository at this point in the history
  • Loading branch information
Viet281101 committed Jun 5, 2024
1 parent e0c3d92 commit 29bfec3
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 8 deletions.
3 changes: 2 additions & 1 deletion 2D/js/polyomino.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ export function getRandomColor() {
export const SHAPES = {
MONOMINO: [[1]],
DOMINO: [[1, 1]],
TROMINO: [[1, 1, 1]],
TROMINO_I: [[1, 1, 1]],
TROMINO_L: [[1, 0], [1, 1]],
TETROMINO_I: [[1, 1, 1, 1]],
TETROMINO_O: [[1, 1], [1, 1]],
TETROMINO_S: [[0, 1, 1], [1, 1, 0]],
Expand Down
2 changes: 1 addition & 1 deletion 2D/js/popup/polyomino.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export function showPolyominoPopup(toolbar) {
ctx.strokeRect(10, y - shapeSize / 2, 180, shapeSize + 20);

ctx.font = '20px Pixellari';
ctx.fillStyle = '#0000c4';
ctx.fillStyle = '#000';
ctx.fillText(shape.replace(/_/g, ' '), 15, y + 7);

const polyomino = new Polyomino(SHAPES[shape].map(row => [...row]), 200, y - shapeSize / 2, getRandomColor(), toolbar.mainApp, shape.replace(/_/g, ' '));
Expand Down
89 changes: 83 additions & 6 deletions 2D/js/popup/solve.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,23 @@ export function showSolvePopup(toolbar) {

const rows = [
{ label: 'Auto tiling the Polyominoes blocks', title: true },
{ label: '1) Backtracking method :', icon: '../assets/ic_solution.png' },
{ label: '2) Brute force method :', icon: '../assets/ic_solution.png' },
{ label: '3) Random method :', icon: '../assets/ic_solution.png' },
{ label: '4) Random backtracking :', icon: '../assets/ic_solution.png' }
{ label: '1) Backtracking method :', icon: '../assets/ic_solution.png', description: 'Backtracking places polyominoes on a grid, checking validity, and backtracks when stuck, ensuring no overlaps and full coverage. Usually runs in order of placing the larger blocks first, then the smaller.' },
{ label: '2) Brute force method :', icon: '../assets/ic_solution.png', description: 'Brute force tries all possible combinations of polyominoes on the grid to find a solution. It is guaranteed to find a solution if one exists but is computationally expensive and slow for large grids.' },
{ label: '3) Random method :', icon: '../assets/ic_solution.png', description: 'The random method places polyominoes randomly on the grid. It is fast but does not guarantee a solution or full coverage. It is useful for generating quick and varied patterns.' },
{ label: '4) Random backtracking :', icon: '../assets/ic_solution.png', description: 'Random backtracking combines random placement with backtracking to find a solution. It is more efficient than brute force but less predictable than pure backtracking.' }
];

const startY = 60;
const rowHeight = 60;
const colX = 30;
const maxWidth = 300;

const dropdowns = {};

rows.forEach((row, index) => {
const y = startY + index * rowHeight;
ctx.font = '20px Pixellari';
ctx.fillStyle = '#15159f';
ctx.fillStyle = '#000';
ctx.fillText(row.label, colX, y + 20);

if (row.icon) {
Expand All @@ -32,6 +35,10 @@ export function showSolvePopup(toolbar) {
};
attachSolveClickEvent(toolbar, popup, row, y);
}

if (row.description) {
dropdowns[index] = { description: row.description, expanded: false, y: y + 40 };
}
});

popup.addEventListener('mousemove', (e) => {
Expand All @@ -42,12 +49,82 @@ export function showSolvePopup(toolbar) {

rows.forEach((row, index) => {
const y = startY + index * rowHeight;
if (row.icon && toolbar.isInside(mouseX, mouseY, { x: popup.width - 94, y: y - 14, width: 50, height: 50 })) {
if (toolbar.isInside(mouseX, mouseY, { x: colX, y: y, width: popup.width - colX - 100, height: rowHeight })) {
cursor = 'pointer';
}
});
popup.style.cursor = cursor;
});

popup.addEventListener('click', (e) => {
const rect = popup.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;

rows.forEach((row, index) => {
const y = startY + index * rowHeight;
if (toolbar.isInside(mouseX, mouseY, { x: colX, y: y, width: popup.width - colX - 100, height: rowHeight })) {
if (dropdowns[index]) {
dropdowns[index].expanded = !dropdowns[index].expanded;
redrawPopup();
}
}
});
});

function wrapText(ctx, text, x, y, maxWidth, lineHeight) {
const words = text.split(' ');
let line = '';
const lines = [];

for (let n = 0; n < words.length; n++) {
let testLine = line + words[n] + ' ';
let metrics = ctx.measureText(testLine);
let testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
lines.push(line);
line = words[n] + ' ';
} else {
line = testLine;
}
}
lines.push(line);
lines.forEach((line, index) => {
ctx.fillText(line, x, y + index * lineHeight);
});
return lines.length;
}

function redrawPopup() {
ctx.clearRect(0, 0, popup.width, popup.height);
ctx.fillStyle = '#a0a0a0';
ctx.fillRect(0, 0, popup.width, popup.height);

let yOffset = 0;
rows.forEach((row, index) => {
const y = startY + index * rowHeight + yOffset;
ctx.font = '20px Pixellari';
ctx.fillStyle = '#000';
ctx.fillText(row.label, colX, y + 20);

if (row.icon) {
const icon = new Image();
icon.src = row.icon;
icon.onload = () => {
ctx.drawImage(icon, popup.width - 94, y - 14, 50, 50);
};
}

if (dropdowns[index] && dropdowns[index].expanded) {
ctx.font = '16px Pixellari';
ctx.fillStyle = '#000';
const linesCount = wrapText(ctx, dropdowns[index].description, colX + 20, y + 50, maxWidth, 20);
yOffset += linesCount * 20;
}
});
}

redrawPopup();
};

function attachSolveClickEvent(toolbar, popup, row, y) {
Expand Down

0 comments on commit 29bfec3

Please sign in to comment.