2021-06-17 16:02:50 +02:00
|
|
|
import { html, css, LitElement, unsafeCSS } from 'https://unpkg.com/lit-element/lit-element.js?module';
|
|
|
|
import './infoBox.js'
|
2021-06-25 09:48:06 +02:00
|
|
|
import { GridElement, GridLetter, GridBox, gridType } from './gridBoxes.js'
|
2021-06-24 12:10:59 +02:00
|
|
|
import './solutionBox.js'
|
2021-06-17 16:02:50 +02:00
|
|
|
|
|
|
|
export class CrosswordGrid extends LitElement {
|
|
|
|
static get styles() {
|
|
|
|
return css`
|
|
|
|
body {
|
|
|
|
background-color: black;
|
2021-06-24 12:10:59 +02:00
|
|
|
text-align: center;
|
|
|
|
|
2021-06-17 16:02:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
table {
|
|
|
|
position: relative;
|
2021-06-24 12:10:59 +02:00
|
|
|
top: 7em;
|
2021-06-17 16:02:50 +02:00
|
|
|
border-spacing: 0px;
|
|
|
|
border-style: solid;
|
|
|
|
border-color: black;
|
|
|
|
border-width: 1em;
|
2021-06-24 12:10:59 +02:00
|
|
|
text-align: center;
|
|
|
|
margin-left: auto;
|
|
|
|
margin-right: auto;
|
2021-06-17 16:02:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
td {
|
|
|
|
padding: 0px;
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
}
|
|
|
|
|
|
|
|
static get properties() {
|
|
|
|
return {
|
|
|
|
id: { type: String },
|
|
|
|
width: { type: Number },
|
|
|
|
height: { type: Number },
|
2021-06-23 19:11:34 +02:00
|
|
|
infobox_id: { type: String }
|
2021-06-24 12:10:59 +02:00
|
|
|
};
|
2021-06-17 16:02:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
this.width = 10;
|
|
|
|
this.height = 10;
|
|
|
|
this.grid = [];
|
|
|
|
|
|
|
|
this.json_grid = null;
|
|
|
|
|
|
|
|
this.num_hints = 0;
|
|
|
|
|
|
|
|
this.lastMoveVertical = false;
|
|
|
|
|
|
|
|
this.infobox = null;
|
|
|
|
|
|
|
|
this.serverConnection = null;
|
2021-06-23 19:11:34 +02:00
|
|
|
|
2021-06-24 12:10:59 +02:00
|
|
|
this.solution_locations = [];
|
|
|
|
|
|
|
|
this.solutionBox = null;
|
|
|
|
|
|
|
|
this.gridCount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
setSolutionBox(solBox) {
|
|
|
|
this.solutionBox = solBox;
|
|
|
|
if (self.solution_locations)
|
|
|
|
solBox.length = self.solution_locations.length;
|
2021-06-23 19:11:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
getSolutionIndex(x, y) {
|
|
|
|
var i = 0;
|
|
|
|
for (i = 0; i < this.solution_locations.length; i++) {
|
|
|
|
if (this.solution_locations[i][0] == y && this.solution_locations[i][1] == x) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
2021-06-17 16:02:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
createGridByJson(json_grid) {
|
|
|
|
this.num_hints = 0;
|
|
|
|
this.json_grid = json_grid;
|
|
|
|
this.grid = [];
|
|
|
|
const width = json_grid.w;
|
|
|
|
const height = json_grid.h;
|
2021-06-24 12:10:59 +02:00
|
|
|
this.gridCount += 1;
|
2021-06-17 16:02:50 +02:00
|
|
|
|
2021-06-23 19:11:34 +02:00
|
|
|
this.solution_locations = json_grid.solution
|
|
|
|
|
2021-06-25 09:48:06 +02:00
|
|
|
if (this.solutionBox) {
|
2021-06-24 12:10:59 +02:00
|
|
|
this.solutionBox.length = this.solution_locations.length;
|
|
|
|
this.solutionBox.requestUpdate();
|
|
|
|
console.log("update box");
|
2021-06-25 09:48:06 +02:00
|
|
|
}
|
2021-06-24 12:10:59 +02:00
|
|
|
|
2021-06-17 16:02:50 +02:00
|
|
|
var y;
|
|
|
|
var x;
|
|
|
|
|
|
|
|
for (y = 0; y < height; y++) {
|
|
|
|
var row = [];
|
|
|
|
for (x = 0; x < width; x++) {
|
|
|
|
const json_cell = json_grid.grid[y][x];
|
|
|
|
const cell_type = json_cell.cell_type;
|
|
|
|
|
|
|
|
switch (cell_type) {
|
|
|
|
case "empty": {
|
|
|
|
row.push(new GridElement(x, y, this, gridType.EMPTY));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case "hint": {
|
|
|
|
row.push(new GridElement(x, y, this, gridType.HINT));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case "letter": {
|
|
|
|
row.push(new GridElement(x, y, this, gridType.LETTER));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
}
|
|
|
|
this.grid.push(row);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.width = width;
|
|
|
|
this.height = height;
|
2021-06-24 12:10:59 +02:00
|
|
|
|
|
|
|
this.requestUpdate();
|
|
|
|
|
2021-06-25 09:48:06 +02:00
|
|
|
|
2021-06-17 16:02:50 +02:00
|
|
|
}
|
|
|
|
|
2021-06-25 09:48:06 +02:00
|
|
|
focusNextCellHorizontal(x, y, skip_revealed = false) {
|
2021-06-17 16:02:50 +02:00
|
|
|
if (x + 1 < this.width && this.grid[y][x + 1].getGridType() === gridType.LETTER) {
|
|
|
|
if (this.grid[y][x].getGridType() === gridType.LETTER) {
|
2021-06-25 09:48:06 +02:00
|
|
|
//this.grid[y][x].getGridLetter().blur();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (skip_revealed && this.grid[y][x + 1].getGridLetter().revealed) {
|
|
|
|
return this.focusNextCellHorizontal(x + 1, y, true);
|
2021-06-17 16:02:50 +02:00
|
|
|
}
|
2021-06-25 09:48:06 +02:00
|
|
|
|
2021-06-23 19:11:34 +02:00
|
|
|
this.grid[y][x + 1].getGridLetter().focus(x, y);
|
2021-06-17 16:02:50 +02:00
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-06-25 09:48:06 +02:00
|
|
|
focusPrevCellHorizontal(x, y, skip_revealed = false) {
|
2021-06-17 16:02:50 +02:00
|
|
|
if (x - 1 >= 0 && this.grid[y][x - 1].getGridType() === gridType.LETTER) {
|
|
|
|
if (this.grid[y][x].getGridType() === gridType.LETTER) {
|
2021-06-25 09:48:06 +02:00
|
|
|
//this.grid[y][x].getGridLetter().blur();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (skip_revealed && this.grid[y][x - 1].getGridLetter().revealed) {
|
|
|
|
return this.focusPrevCellHorizontal(x - 1, y, true);
|
2021-06-17 16:02:50 +02:00
|
|
|
}
|
2021-06-25 09:48:06 +02:00
|
|
|
|
2021-06-17 16:02:50 +02:00
|
|
|
this.grid[y][x - 1].getGridLetter().focus();
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-06-25 09:48:06 +02:00
|
|
|
focusNextCellVertical(x, y, skip_revealed = false) {
|
2021-06-17 16:02:50 +02:00
|
|
|
if (y + 1 < this.height && this.grid[y + 1][x].getGridType() === gridType.LETTER) {
|
|
|
|
if (this.grid[y][x].getGridType() === gridType.LETTER) {
|
2021-06-25 09:48:06 +02:00
|
|
|
//this.grid[y][x].getGridLetter().blur();
|
|
|
|
}
|
|
|
|
if (skip_revealed && this.grid[y + 1][x].getGridLetter().revealed) {
|
|
|
|
return this.focusNextCellVertical(x, y + 1, true);
|
2021-06-17 16:02:50 +02:00
|
|
|
}
|
2021-06-23 19:11:34 +02:00
|
|
|
this.grid[y + 1][x].getGridLetter().focus(x, y);
|
2021-06-17 16:02:50 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-06-25 09:48:06 +02:00
|
|
|
focusPrevCellVertical(x, y, skip_revealed = false) {
|
2021-06-17 16:02:50 +02:00
|
|
|
if (y - 1 >= 0 && this.grid[y - 1][x].getGridType() === gridType.LETTER) {
|
|
|
|
if (this.grid[y][x].getGridType() === gridType.LETTER) {
|
2021-06-25 09:48:06 +02:00
|
|
|
//this.grid[y][x].getGridLetter().blur();
|
|
|
|
}
|
|
|
|
if (skip_revealed && this.grid[y - 1][x].getGridLetter().revealed) {
|
|
|
|
return this.focusPrevCellVertical(x, y - 1, true);
|
2021-06-17 16:02:50 +02:00
|
|
|
}
|
|
|
|
this.grid[y - 1][x].getGridLetter().focus();
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
focusNextCell(x, y) {
|
|
|
|
if (this.lastMoveVertical) {
|
2021-06-25 09:48:06 +02:00
|
|
|
if (this.focusNextCellVertical(x, y, true)) {
|
2021-06-17 16:02:50 +02:00
|
|
|
return;
|
|
|
|
}
|
2021-06-25 09:48:06 +02:00
|
|
|
if (this.focusNextCellHorizontal(x, y, true)) {
|
2021-06-17 16:02:50 +02:00
|
|
|
this.lastMoveVertical = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2021-06-25 09:48:06 +02:00
|
|
|
if (this.focusNextCellHorizontal(x, y, true)) {
|
2021-06-17 16:02:50 +02:00
|
|
|
return;
|
|
|
|
}
|
2021-06-25 09:48:06 +02:00
|
|
|
if (this.focusNextCellVertical(x, y, true)) {
|
2021-06-17 16:02:50 +02:00
|
|
|
this.lastMoveVertical = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-23 19:11:34 +02:00
|
|
|
focusPrevCell(x, y, lastX = -1, lastY = -1) {
|
|
|
|
if (lastX > 0 && lastY > 0) {
|
|
|
|
this.grid[lastY][lastX].getGridLetter().focus();
|
|
|
|
return;
|
|
|
|
}
|
2021-06-17 16:02:50 +02:00
|
|
|
if (this.lastMoveVertical) {
|
2021-06-25 09:48:06 +02:00
|
|
|
if (this.focusPrevCellVertical(x, y, true)) {
|
2021-06-17 16:02:50 +02:00
|
|
|
return;
|
|
|
|
}
|
2021-06-25 09:48:06 +02:00
|
|
|
if (this.focusPrevCellHorizontal(x, y, true)) {
|
2021-06-17 16:02:50 +02:00
|
|
|
this.lastMoveVertical = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2021-06-25 09:48:06 +02:00
|
|
|
if (this.focusPrevCellHorizontal(x, y, true)) {
|
2021-06-17 16:02:50 +02:00
|
|
|
return;
|
|
|
|
}
|
2021-06-25 09:48:06 +02:00
|
|
|
if (this.focusPrevCellVertical(x, y, true)) {
|
2021-06-17 16:02:50 +02:00
|
|
|
this.lastMoveVertical = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
getGridElement(x, y) {
|
|
|
|
return this.grid[y][x];
|
|
|
|
}
|
|
|
|
|
|
|
|
update(props) {
|
|
|
|
if (props.has("width") || props.has("height")) {
|
|
|
|
//
|
|
|
|
}
|
|
|
|
if (props.has("infobox_id")) {
|
|
|
|
this.infobox = document.getElementById(this.infobox_id);
|
|
|
|
}
|
|
|
|
super.update()
|
|
|
|
}
|
|
|
|
|
2021-06-23 19:11:34 +02:00
|
|
|
updateHints(x, y) {
|
2021-06-17 16:02:50 +02:00
|
|
|
var cell = this.grid[y][x];
|
2021-06-23 19:11:34 +02:00
|
|
|
if (cell.getGridType() != gridType.LETTER) {
|
2021-06-17 16:02:50 +02:00
|
|
|
console.error("cannot get hints for non letter cell");
|
|
|
|
}
|
|
|
|
|
|
|
|
//get horizontal hint:
|
|
|
|
var upper_end = cell;
|
|
|
|
while (upper_end.getGridType() === gridType.LETTER) {
|
|
|
|
upper_end = this.grid[upper_end.y - 1][x]
|
|
|
|
}
|
|
|
|
|
|
|
|
var left_end = cell;
|
|
|
|
while (left_end.getGridType() === gridType.LETTER) {
|
|
|
|
left_end = this.grid[y][left_end.x - 1]
|
|
|
|
}
|
|
|
|
|
|
|
|
var hHint = "";
|
|
|
|
var vHint = "";
|
|
|
|
|
|
|
|
if (left_end.getGridType() === gridType.HINT) {
|
|
|
|
var box = left_end.getHintBox();
|
2021-06-23 19:11:34 +02:00
|
|
|
if (box.hasHorizontalHint()) {
|
2021-06-21 10:18:31 +02:00
|
|
|
hHint = `${box.hint_id}: ${box.horizontal_hint}`;
|
|
|
|
}
|
2021-06-17 16:02:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (upper_end.getGridType() === gridType.HINT) {
|
|
|
|
var box = upper_end.getHintBox()
|
2021-06-23 19:11:34 +02:00
|
|
|
if (box.hasVerticalHint()) {
|
2021-06-21 10:18:31 +02:00
|
|
|
vHint = `${box.hint_id}: ${box.vertical_hint}`;
|
|
|
|
}
|
2021-06-17 16:02:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
this.infobox.horizontal_hint = hHint;
|
|
|
|
this.infobox.vertical_hint = vHint;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderCell(el) {
|
|
|
|
switch (el.type) {
|
|
|
|
case gridType.LETTER: {
|
2021-06-24 12:10:59 +02:00
|
|
|
return html`<grid-letter grid_id='${this.id}' gridCount='${this.gridCount}' x='${el.x}' y='${el.y}' ></grid-letter>`;
|
2021-06-17 16:02:50 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
case gridType.EMPTY: {
|
2021-06-24 12:10:59 +02:00
|
|
|
return html`<grid-box grid_id='${this.id}' gridCount='${this.gridCount}' x='${el.x}' y='${el.y}' ></grid-box>`;
|
2021-06-17 16:02:50 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
case gridType.HINT: {
|
|
|
|
var vertical_hint = this.json_grid.grid[el.y][el.x].vertical_hint;
|
|
|
|
var horizontal_hint = this.json_grid.grid[el.y][el.x].horizontal_hint;
|
|
|
|
|
2021-06-23 19:11:34 +02:00
|
|
|
if (!vertical_hint) {
|
2021-06-17 16:02:50 +02:00
|
|
|
vertical_hint = "";
|
|
|
|
}
|
2021-06-23 19:11:34 +02:00
|
|
|
if (!horizontal_hint) {
|
2021-06-17 16:02:50 +02:00
|
|
|
horizontal_hint = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
this.num_hints += 1;
|
|
|
|
|
|
|
|
return html`
|
2021-06-24 12:10:59 +02:00
|
|
|
<hint-box grid_id='${this.id}' gridCount='${this.gridCount}' x='${el.x}' y='${el.y}' horizontal_hint='${horizontal_hint}' vertical_hint='${vertical_hint}' hint_id=${this.num_hints}></hint-box>
|
2021-06-17 16:02:50 +02:00
|
|
|
`;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-23 19:11:34 +02:00
|
|
|
updateLetter(x, y, letter, revealed) {
|
2021-06-17 16:02:50 +02:00
|
|
|
var cell = this.grid[y][x];
|
2021-06-23 19:11:34 +02:00
|
|
|
if (cell.getGridType() != gridType.LETTER) {
|
2021-06-17 16:02:50 +02:00
|
|
|
console.error("received bad message");
|
|
|
|
}
|
|
|
|
cell.getGridLetter().updateLetter(letter, revealed)
|
2021-06-24 12:10:59 +02:00
|
|
|
if (cell.getGridLetter().solutionIndex >= 0) {
|
|
|
|
this.setSolutionLetter(
|
|
|
|
cell.getGridLetter().solutionIndex,
|
|
|
|
letter,
|
|
|
|
revealed
|
|
|
|
);
|
|
|
|
}
|
2021-06-17 16:02:50 +02:00
|
|
|
}
|
|
|
|
|
2021-06-23 19:11:34 +02:00
|
|
|
registerServerConnection(connection) {
|
2021-06-17 16:02:50 +02:00
|
|
|
this.serverConnection = connection
|
|
|
|
}
|
|
|
|
|
2021-06-23 19:11:34 +02:00
|
|
|
sendMessage(msg) {
|
2021-06-17 16:02:50 +02:00
|
|
|
if (!this.serverConnection) {
|
|
|
|
console.error("no server connection registered")
|
|
|
|
}
|
|
|
|
this.serverConnection.sendMessage(msg)
|
|
|
|
}
|
|
|
|
|
2021-06-25 09:48:06 +02:00
|
|
|
setSolutionLetter(solutionNumber, letter, revealed = false) {
|
2021-06-24 12:10:59 +02:00
|
|
|
this.solutionBox.setLetter(solutionNumber, letter, revealed);
|
|
|
|
const x = this.solution_locations[solutionNumber][1];
|
|
|
|
const y = this.solution_locations[solutionNumber][0];
|
|
|
|
console.log("update solution letter");
|
2021-06-25 09:48:06 +02:00
|
|
|
var old_val = this.grid[y][x].getGridLetter().value;
|
2021-06-24 12:10:59 +02:00
|
|
|
this.grid[y][x].getGridLetter().value = letter;
|
|
|
|
|
2021-06-25 09:48:06 +02:00
|
|
|
if (old_val != letter && !revealed) {
|
|
|
|
this.sendMessage({
|
|
|
|
'type': 'update',
|
|
|
|
'x': x,
|
|
|
|
'y': y,
|
|
|
|
'letter': letter
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-06-24 12:10:59 +02:00
|
|
|
}
|
|
|
|
|
2021-06-25 09:48:06 +02:00
|
|
|
|
2021-06-24 12:10:59 +02:00
|
|
|
|
2021-06-17 16:02:50 +02:00
|
|
|
render() {
|
|
|
|
this.num_hints = 0;
|
|
|
|
console.log("refreshing grid");
|
2021-06-24 12:10:59 +02:00
|
|
|
|
|
|
|
var solution_length = 0;
|
2021-06-25 09:48:06 +02:00
|
|
|
if (this.solution_locations) {
|
2021-06-24 12:10:59 +02:00
|
|
|
solution_length = this.solution_locations.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-17 16:02:50 +02:00
|
|
|
return html`
|
|
|
|
<table>
|
|
|
|
${this.grid.map((row) => html`<tr>${row.map((el) => html`<td>${this.renderCell(el)}</td>`)}</tr>`)}
|
|
|
|
</table>
|
2021-06-24 12:10:59 +02:00
|
|
|
<solution-box id="solution-box", grid_id="${this.id}", length="${solution_length}" ></solution-box>
|
2021-06-17 16:02:50 +02:00
|
|
|
`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
customElements.define('crossword-grid', CrosswordGrid);
|