|
|
|
@ -38,53 +38,50 @@ class BoardGameComponent extends HTMLElement { |
|
|
|
|
// Technically we're mixing code and data here, but that's OK
|
|
|
|
|
// because both slotName and templateName originate from getSlotTemplateNames and is not actually arbitrary
|
|
|
|
|
for (const [slotName, templateName] of Object.entries(slotTemplateNames)) { |
|
|
|
|
this.querySelectorAll(`.${slotName}`).forEach((slot) => { |
|
|
|
|
for (const slot of Array.from(this.querySelectorAll(`.${slotName}`))) { |
|
|
|
|
ensureSlotTemplate(slot, templateName, () => this.querySelector(`template[name="${templateName}"]`)); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const buttonValues = getButtonValues(gameState); |
|
|
|
|
this.querySelectorAll("button").forEach((button) => { |
|
|
|
|
button.classList.forEach((className) => { |
|
|
|
|
for (const button of Array.from(this.querySelectorAll("button"))) { |
|
|
|
|
for (const className of Array.from(button.classList)) { |
|
|
|
|
if (Object.prototype.hasOwnProperty.call(buttonValues, className)) { |
|
|
|
|
button.value = buttonValues[className as keyof ButtonValues].serialize(); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const displayStates = getDisplayStates(gameState, currentOutcome); |
|
|
|
|
for (const [className, shouldEnable] of Object.entries(displayStates)) { |
|
|
|
|
this.classList.toggle(className, shouldEnable); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.querySelectorAll("tbody.game-board").forEach((tbody) => { |
|
|
|
|
for (const tbody of Array.from(this.querySelectorAll("tbody.game-board"))) { |
|
|
|
|
ensureRowsNumber(tbody, gameState.rows); |
|
|
|
|
|
|
|
|
|
for (let rowNumber = 0; rowNumber < tbody.rows.length; rowNumber++) { |
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- should not be empty by the definition of rowNumber
|
|
|
|
|
const row = tbody.rows[rowNumber]!; |
|
|
|
|
for (const row of Array.from(tbody.rows)) { |
|
|
|
|
ensureColumnsNumber(row, gameState.columns); |
|
|
|
|
|
|
|
|
|
for (let columnNumber = 0; columnNumber < row.cells.length; columnNumber++) { |
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- should not be empty by the definition of columnNumber
|
|
|
|
|
const cell = row.cells[columnNumber]!; |
|
|
|
|
for (const cell of Array.from(row.cells)) { |
|
|
|
|
ensureSlotTemplate(cell, "game-cell", () => this.querySelector(`template[name="game-cell"]`)); |
|
|
|
|
|
|
|
|
|
const { isDisabled, nextGameState, text, className } = getCellDisplayData({ |
|
|
|
|
gameState, |
|
|
|
|
currentOutcome, |
|
|
|
|
row: rowNumber, |
|
|
|
|
column: columnNumber, |
|
|
|
|
row: row.sectionRowIndex, |
|
|
|
|
column: cell.cellIndex, |
|
|
|
|
}); |
|
|
|
|
cell.querySelectorAll("button").forEach((button) => { |
|
|
|
|
|
|
|
|
|
for (const button of Array.from(cell.querySelectorAll("button"))) { |
|
|
|
|
button.value = nextGameState.serialize(); |
|
|
|
|
button.disabled = isDisabled; |
|
|
|
|
button.innerText = text; |
|
|
|
|
button.className = className; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
connectedCallback() { |
|
|
|
|