|
|
|
|
@@ -159,12 +159,38 @@ export default class PageMtgGame extends TableBasePage {
|
|
|
|
|
console.log({ savedPlayers, damageRecords });
|
|
|
|
|
|
|
|
|
|
// Render players to DOM
|
|
|
|
|
const latestRoundId = PageMtgGame.getLatestRoundId();
|
|
|
|
|
const latestRound = rounds.filter(round => round[attrRoundId] == latestRoundId)[0];
|
|
|
|
|
const roundDisplayOrderLabel = PageMtgGame.getRoundDisplayOrderLabel();
|
|
|
|
|
DOM.setElementValuesCurrentAndPrevious(roundDisplayOrderLabel, latestRound[flagDisplayOrder]);
|
|
|
|
|
|
|
|
|
|
this.renderPlayers();
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error loading game from server:', error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
static getRoundDisplayOrderLabel() {
|
|
|
|
|
return document.querySelector([
|
|
|
|
|
'#gameSection'
|
|
|
|
|
, ' > .'
|
|
|
|
|
, flagRow
|
|
|
|
|
, '.'
|
|
|
|
|
, flagRound
|
|
|
|
|
, ' > .'
|
|
|
|
|
, flagRow
|
|
|
|
|
, '.'
|
|
|
|
|
, flagRound
|
|
|
|
|
, ' > .'
|
|
|
|
|
, flagRound
|
|
|
|
|
, '.'
|
|
|
|
|
, flagDisplayOrder
|
|
|
|
|
, ' > span.'
|
|
|
|
|
, flagRound
|
|
|
|
|
, '.'
|
|
|
|
|
, flagDisplayOrder
|
|
|
|
|
].join(''));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
renderPlayers() {
|
|
|
|
|
const grid = document.getElementById('playersGrid');
|
|
|
|
|
@@ -182,8 +208,17 @@ export default class PageMtgGame extends TableBasePage {
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
*/
|
|
|
|
|
const latestRoundId = PageMtgGame.getLatestRoundId();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let activeRoundId = PageMtgGame.getActiveRoundId();
|
|
|
|
|
const roundDisplayOrderLabel = PageMtgGame.getRoundDisplayOrderLabel();
|
|
|
|
|
if (activeRoundId < 0) {
|
|
|
|
|
const currentRoundDisplayOrder = Number(DOM.getElementValueCurrent(roundDisplayOrderLabel));
|
|
|
|
|
rounds.push(PageMtgGame.makeDefaultGameRound(currentRoundDisplayOrder));
|
|
|
|
|
activeRoundId = PageMtgGame.getActiveRoundId();
|
|
|
|
|
}
|
|
|
|
|
const latestRound = rounds.filter(round => round[attrRoundId] == activeRoundId)[0];
|
|
|
|
|
DOM.setElementValueCurrent(roundDisplayOrderLabel, latestRound[flagDisplayOrder]);
|
|
|
|
|
|
|
|
|
|
players.forEach((player, index) => {
|
|
|
|
|
// Build display name: prefer user_name + deck_name, fallback to player name
|
|
|
|
|
const playerId = player[attrPlayerId];
|
|
|
|
|
@@ -193,7 +228,7 @@ export default class PageMtgGame extends TableBasePage {
|
|
|
|
|
damagePlayerPairs.forEach(damagePlayerPair => {
|
|
|
|
|
const sourceId = damagePlayerPair[attrPlayerId];
|
|
|
|
|
const filteredPlayerDamages = damageRecords.filter(damage => (
|
|
|
|
|
damage[attrRoundId] == latestRoundId
|
|
|
|
|
damage[attrRoundId] == activeRoundId
|
|
|
|
|
&& damage[attrPlayerId] == playerId
|
|
|
|
|
&& damage[attrReceivedFromCommanderPlayerId] == sourceId
|
|
|
|
|
)); //[playerId] || {};
|
|
|
|
|
@@ -229,7 +264,7 @@ export default class PageMtgGame extends TableBasePage {
|
|
|
|
|
const playerOwnDamage = damageRecords.filter(damage => (
|
|
|
|
|
damage[attrPlayerId] == playerId
|
|
|
|
|
&& damage[attrReceivedFromCommanderPlayerId] == null
|
|
|
|
|
&& damage[attrRoundId] == latestRoundId
|
|
|
|
|
&& damage[attrRoundId] == activeRoundId
|
|
|
|
|
))[0];
|
|
|
|
|
const card = document.createElement('div');
|
|
|
|
|
card.className = `player-card ${isEliminated ? 'eliminated' : ''}`;
|
|
|
|
|
@@ -281,11 +316,51 @@ export default class PageMtgGame extends TableBasePage {
|
|
|
|
|
grid.appendChild(card);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.reorderPlayerCards();
|
|
|
|
|
|
|
|
|
|
PageMtgGame.renderCommanderDamageLog();
|
|
|
|
|
|
|
|
|
|
// Hookup all event handlers
|
|
|
|
|
this.hookupGameRoundEvents();
|
|
|
|
|
this.hookupPlayerCardEvents();
|
|
|
|
|
}
|
|
|
|
|
static renderCommanderDamageLog() {
|
|
|
|
|
const roundDisplayOrderLabel = PageMtgGame.getRoundDisplayOrderLabel();
|
|
|
|
|
const currentRoundDisplayOrder = Number(DOM.getElementValueCurrent(roundDisplayOrderLabel));
|
|
|
|
|
|
|
|
|
|
const damageTableBody = document.querySelector('.' + flagDamageLog + '.' + flagContainer + ' table tbody');
|
|
|
|
|
damageTableBody.innerHTML = '';
|
|
|
|
|
|
|
|
|
|
let newTableBodyHtml = '';
|
|
|
|
|
damageRecords.forEach((damage) => {
|
|
|
|
|
if (
|
|
|
|
|
damage[flagActive]
|
|
|
|
|
&& (
|
|
|
|
|
damage[flagCommanderDeaths] > 0
|
|
|
|
|
|| damage[flagHealthChange] != 0
|
|
|
|
|
|| damage[flagIsEliminated]
|
|
|
|
|
)
|
|
|
|
|
&& rounds.filter(r => r[attrRoundId] == damage[attrRoundId])[0][flagDisplayOrder] <= currentRoundDisplayOrder
|
|
|
|
|
) {
|
|
|
|
|
let round = rounds.filter(r => r[attrRoundId] == damage[attrRoundId])[0];
|
|
|
|
|
let player = players.filter(p => p[attrPlayerId] == damage[attrPlayerId])[0];
|
|
|
|
|
let receivedFromPlayer = (damage[attrReceivedFromCommanderPlayerId] == null) ? { [flagName]: ''} : players.filter(p => p[attrPlayerId] == damage[attrReceivedFromCommanderPlayerId])[0];
|
|
|
|
|
newTableBodyHtml += `
|
|
|
|
|
<tr ${attrDamageId}="${damage[attrDamageId]}">
|
|
|
|
|
<td class="${attrRoundId}">${round[flagDisplayOrder]}</td>
|
|
|
|
|
<td class="${attrPlayerId}">${player[flagName]}</td>
|
|
|
|
|
<td class="${attrReceivedFromCommanderPlayerId}">${receivedFromPlayer[flagName]}</td>
|
|
|
|
|
<td class="${flagHealthChange}">${damage[flagHealthChange]}</td>
|
|
|
|
|
<td class="${flagCommanderDeaths}">${damage[flagCommanderDeaths]}</td>
|
|
|
|
|
<td class="${flagIsEliminated}">${damage[flagIsEliminated]}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
damageTableBody.innerHTML = newTableBodyHtml;
|
|
|
|
|
}
|
|
|
|
|
static makeDefaultGameRoundPlayerDamage(playerId, receivedFromCommanderPlayerId) {
|
|
|
|
|
let roundId = PageMtgGame.getLatestRoundId();
|
|
|
|
|
let roundId = PageMtgGame.getActiveRoundId();
|
|
|
|
|
return {
|
|
|
|
|
[attrDamageId]: -1 - damageRecords.length
|
|
|
|
|
, [attrRoundId]: roundId
|
|
|
|
|
@@ -299,9 +374,24 @@ export default class PageMtgGame extends TableBasePage {
|
|
|
|
|
static getLatestRoundId() {
|
|
|
|
|
let roundId = -1;
|
|
|
|
|
if (rounds.length > 0) {
|
|
|
|
|
let highestRoundDisplayOrder = Math.max(rounds.map(round => { return round[flagDisplayOrder]; }));
|
|
|
|
|
roundId = rounds.filter(round => round[flagDisplayOrder] == highestRoundDisplayOrder)[0][attrRoundId];
|
|
|
|
|
console.log({ "method": "getLatestRoundId", highestRoundDisplayOrder, roundId });
|
|
|
|
|
const highestRoundDisplayOrder = rounds.map(round => { return round[flagDisplayOrder]; })
|
|
|
|
|
.reduce((acc, cur) => Math.max(acc, cur), 0);
|
|
|
|
|
const filteredRounds = rounds.filter(round => round[flagDisplayOrder] == highestRoundDisplayOrder);
|
|
|
|
|
if (filteredRounds.length > 0) {
|
|
|
|
|
roundId = filteredRounds[0][attrRoundId];
|
|
|
|
|
}
|
|
|
|
|
console.log({ "method": "getLatestRoundId", highestRoundDisplayOrder, filteredRounds, roundId });
|
|
|
|
|
}
|
|
|
|
|
return roundId;
|
|
|
|
|
}
|
|
|
|
|
static getActiveRoundId() {
|
|
|
|
|
const roundDisplayOrderLabel = PageMtgGame.getRoundDisplayOrderLabel();
|
|
|
|
|
const currentRoundDisplayOrder = Number(DOM.getElementValueCurrent(roundDisplayOrderLabel));
|
|
|
|
|
let roundId = -1;
|
|
|
|
|
if (rounds.length > 0) {
|
|
|
|
|
let filteredRounds = rounds.filter(round => round[flagDisplayOrder] == currentRoundDisplayOrder);
|
|
|
|
|
if (filteredRounds.length > 0) roundId = filteredRounds[0][attrRoundId];
|
|
|
|
|
console.log({ "method": "getActiveRoundId", filteredRounds, roundId });
|
|
|
|
|
}
|
|
|
|
|
return roundId;
|
|
|
|
|
}
|
|
|
|
|
@@ -345,15 +435,39 @@ export default class PageMtgGame extends TableBasePage {
|
|
|
|
|
.join('');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hookupGameRoundEvents() {
|
|
|
|
|
let incrementRoundButtonSelector = '#gameSection .' + flagRow + '.' + flagRound + ' button.' + flagRoundDisplayOrderButton;
|
|
|
|
|
Events.hookupEventHandler("click", incrementRoundButtonSelector, (event, button) => {
|
|
|
|
|
const amount = button.classList.contains(flagRoundDisplayOrderPlus) ? 1 : -1;
|
|
|
|
|
const roundDisplayOrderButtonContainer = button.parentElement;
|
|
|
|
|
const roundDisplayOrderLabel = roundDisplayOrderButtonContainer.querySelector('span.' + flagRound + '.' + flagDisplayOrder);
|
|
|
|
|
const currentRoundDisplayOrder = Number(DOM.getElementValueCurrent(roundDisplayOrderLabel));
|
|
|
|
|
const newDisplayOrder = currentRoundDisplayOrder + amount;
|
|
|
|
|
DOM.setElementValueCurrent(roundDisplayOrderLabel, newDisplayOrder);
|
|
|
|
|
DOM.isElementDirty(roundDisplayOrderLabel);
|
|
|
|
|
this.updateAndToggleShowButtonsSaveCancel();
|
|
|
|
|
this.renderPlayers();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
static makeDefaultGameRound(displayOrder) {
|
|
|
|
|
const newDisplayOrder = (displayOrder != null) ? displayOrder : 1 + Math.max(rounds.map(round => round[flagDisplayOrder]));
|
|
|
|
|
return {
|
|
|
|
|
[attrRoundId]: -newDisplayOrder
|
|
|
|
|
, [attrGameId]: gameId
|
|
|
|
|
, [flagNotes]: null
|
|
|
|
|
, [flagDisplayOrder]: newDisplayOrder
|
|
|
|
|
, [flagActive]: true
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
hookupPlayerCardEvents() {
|
|
|
|
|
// Life buttons
|
|
|
|
|
let lifeButtonSelector = '.life-btn';
|
|
|
|
|
Events.hookupEventHandler("click", lifeButtonSelector, (event, button) => {
|
|
|
|
|
const playerId = button.dataset.playerId;
|
|
|
|
|
const amount = parseInt(button.dataset.amount);
|
|
|
|
|
const latestRoundId = PageMtgGame.getLatestRoundId();
|
|
|
|
|
const activeRoundId = PageMtgGame.getActiveRoundId();
|
|
|
|
|
const damageIndex = damageRecords.findIndex(damage => (
|
|
|
|
|
damage[attrRoundId] == latestRoundId
|
|
|
|
|
damage[attrRoundId] == activeRoundId
|
|
|
|
|
&& damage[attrPlayerId] == playerId
|
|
|
|
|
&& damage[attrReceivedFromCommanderPlayerId] == null
|
|
|
|
|
));
|
|
|
|
|
@@ -410,6 +524,8 @@ export default class PageMtgGame extends TableBasePage {
|
|
|
|
|
damageRecords[damageIndex][flagHealthChange] += amount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PageMtgGame.renderCommanderDamageLog();
|
|
|
|
|
|
|
|
|
|
// PageMtgGame.debouncedSave();
|
|
|
|
|
this.updateAndToggleShowButtonsSaveCancel();
|
|
|
|
|
}
|
|
|
|
|
@@ -436,9 +552,9 @@ export default class PageMtgGame extends TableBasePage {
|
|
|
|
|
damageDisplay.classList.remove('lethal');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const latestRoundId = PageMtgGame.getLatestRoundId();
|
|
|
|
|
const activeRoundId = PageMtgGame.getActiveRoundId();
|
|
|
|
|
const damageIndex = damageRecords.findIndex(damageRecord => (
|
|
|
|
|
damageRecord[attrRoundId] == latestRoundId
|
|
|
|
|
damageRecord[attrRoundId] == activeRoundId
|
|
|
|
|
&& damageRecord[attrPlayerId] == playerId
|
|
|
|
|
&& damageRecord[attrReceivedFromCommanderPlayerId] == sourceId
|
|
|
|
|
));
|
|
|
|
|
@@ -465,14 +581,16 @@ export default class PageMtgGame extends TableBasePage {
|
|
|
|
|
DOM.setElementAttributeValueCurrent(deathDisplay, newDeaths);
|
|
|
|
|
DOM.isElementDirty(deathDisplay);
|
|
|
|
|
|
|
|
|
|
const latestRoundId = PageMtgGame.getLatestRoundId();
|
|
|
|
|
const activeRoundId = PageMtgGame.getActiveRoundId();
|
|
|
|
|
const damageIndex = damageRecords.findIndex(damage => (
|
|
|
|
|
damage[attrRoundId] == latestRoundId
|
|
|
|
|
damage[attrRoundId] == activeRoundId
|
|
|
|
|
&& damage[attrPlayerId] == playerId
|
|
|
|
|
&& damage[attrReceivedFromCommanderPlayerId] == null
|
|
|
|
|
));
|
|
|
|
|
damageRecords[damageIndex][flagCommanderDeaths] = newDeaths;
|
|
|
|
|
|
|
|
|
|
PageMtgGame.renderCommanderDamageLog();
|
|
|
|
|
|
|
|
|
|
// PageMtgGame.debouncedSave();
|
|
|
|
|
this.updateAndToggleShowButtonsSaveCancel();
|
|
|
|
|
}
|
|
|
|
|
@@ -493,9 +611,9 @@ export default class PageMtgGame extends TableBasePage {
|
|
|
|
|
}
|
|
|
|
|
const isEliminated = card.classList.contains('eliminated');
|
|
|
|
|
|
|
|
|
|
const latestRoundId = PageMtgGame.getLatestRoundId();
|
|
|
|
|
const activeRoundId = PageMtgGame.getActiveRoundId();
|
|
|
|
|
const damageIndex = damageRecords.findIndex(damage => (
|
|
|
|
|
damage[attrRoundId] == latestRoundId
|
|
|
|
|
damage[attrRoundId] == activeRoundId
|
|
|
|
|
&& damage[attrPlayerId] == playerId
|
|
|
|
|
&& damage[attrReceivedFromCommanderPlayerId] == null
|
|
|
|
|
));
|
|
|
|
|
@@ -503,9 +621,91 @@ export default class PageMtgGame extends TableBasePage {
|
|
|
|
|
|
|
|
|
|
DOM.setElementAttributeValueCurrent(eliminateBtn, isEliminated);
|
|
|
|
|
DOM.isElementDirty(eliminateBtn);
|
|
|
|
|
|
|
|
|
|
this.reorderPlayerCards();
|
|
|
|
|
PageMtgGame.renderCommanderDamageLog();
|
|
|
|
|
|
|
|
|
|
// PageMtgGame.debouncedSave();
|
|
|
|
|
this.updateAndToggleShowButtonsSaveCancel();
|
|
|
|
|
}
|
|
|
|
|
reorderPlayerCards() {
|
|
|
|
|
let playerGrid = document.getElementById('playersGrid');
|
|
|
|
|
let currentPlayerCards = playerGrid.querySelectorAll('.player-card');
|
|
|
|
|
let newPlayerCards = [];
|
|
|
|
|
let playerCardMetas = [];
|
|
|
|
|
currentPlayerCards.forEach((playerCard, index) => {
|
|
|
|
|
newPlayerCards.push(playerCard.cloneNode(true));
|
|
|
|
|
playerCardMetas.push({
|
|
|
|
|
[flagIsEliminated]: playerCard.classList.contains(flagIsEliminated)
|
|
|
|
|
, [attrPlayerId]: playerCard.dataset["playerId"]
|
|
|
|
|
, [flagDisplayOrder]: index
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
let activeRoundId = PageMtgGame.getActiveRoundId();
|
|
|
|
|
let newPlayerGridInnerHTML = '';
|
|
|
|
|
let playerIdA, playerIdB, isEliminatedAsIntA, isEliminatedAsIntB, playerA, playerB, indexPlayerCard;
|
|
|
|
|
playerCardMetas.sort((a, b) => {
|
|
|
|
|
playerIdA = a[attrPlayerId];
|
|
|
|
|
playerIdB = b[attrPlayerId];
|
|
|
|
|
isEliminatedAsIntA = PageMtgGame.isPlayerEliminated(playerIdA, activeRoundId) ? 1 : 0;
|
|
|
|
|
isEliminatedAsIntB = PageMtgGame.isPlayerEliminated(playerIdB, activeRoundId) ? 1 : 0;
|
|
|
|
|
playerA = players.filter(p => p[attrPlayerId] == playerIdA)[0];
|
|
|
|
|
playerB = players.filter(p => p[attrPlayerId] == playerIdB)[0];
|
|
|
|
|
return (
|
|
|
|
|
players.length * isEliminatedAsIntA
|
|
|
|
|
+ playerA[flagDisplayOrder]
|
|
|
|
|
) - (
|
|
|
|
|
players.length * isEliminatedAsIntB
|
|
|
|
|
+ playerB[flagDisplayOrder]
|
|
|
|
|
);
|
|
|
|
|
}).forEach((playerCardMeta) => {
|
|
|
|
|
indexPlayerCard = playerCardMeta[flagDisplayOrder];
|
|
|
|
|
newPlayerGridInnerHTML += newPlayerCards[indexPlayerCard].outerHTML;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
playerGrid.innerHTML = newPlayerGridInnerHTML;
|
|
|
|
|
|
|
|
|
|
playerGrid.querySelectorAll('.' + flagInitialised).forEach((initialisedElement) => {
|
|
|
|
|
initialisedElement.classList.remove(flagInitialised);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.hookupPlayerCardEvents();
|
|
|
|
|
}
|
|
|
|
|
static isPlayerEliminated(playerId, roundId = null) {
|
|
|
|
|
if (roundId == null) roundId = PageMtgGame.getActiveRoundId();
|
|
|
|
|
let hasDamageWithIsEliminated = damageRecords.filter(damage => (
|
|
|
|
|
damage[attrRoundId] <= roundId
|
|
|
|
|
&& damage[attrPlayerId] == playerId
|
|
|
|
|
&& damage[flagIsEliminated]
|
|
|
|
|
)).length > 0;
|
|
|
|
|
let damageFromOtherPlayers = {};
|
|
|
|
|
let otherPlayerId;
|
|
|
|
|
damageRecords.filter(damage => (
|
|
|
|
|
damage[attrRoundId] <= roundId
|
|
|
|
|
&& damage[attrPlayerId] == playerId
|
|
|
|
|
&& damage[attrReceivedFromCommanderPlayerId] != null
|
|
|
|
|
))
|
|
|
|
|
.forEach((damage) => {
|
|
|
|
|
otherPlayerId = damage[attrReceivedFromCommanderPlayerId];
|
|
|
|
|
damageFromOtherPlayers[otherPlayerId] =
|
|
|
|
|
damage[flagHealthChange]
|
|
|
|
|
+ ((damageFromOtherPlayers[otherPlayerId] == null) ? 0 : damageFromOtherPlayers[otherPlayerId]);
|
|
|
|
|
});
|
|
|
|
|
let maxDamageFromOtherCommander = Math.max(Object.keys(damageFromOtherPlayers)
|
|
|
|
|
.map((playerId) => damageFromOtherPlayers[playerId]));
|
|
|
|
|
// .reduce((acc, cur) => acc + cur, 0);
|
|
|
|
|
let totalDamageTaken = damageRecords.filter(damage => (
|
|
|
|
|
damage[attrRoundId] <= roundId
|
|
|
|
|
&& damage[attrPlayerId] == playerId
|
|
|
|
|
))
|
|
|
|
|
.map((damage) => damage[flagHealthChange])
|
|
|
|
|
.reduce((acc, cur) => acc + cur, 0);
|
|
|
|
|
return (
|
|
|
|
|
hasDamageWithIsEliminated
|
|
|
|
|
|| maxDamageFromOtherCommander >= 21
|
|
|
|
|
|| totalDamageTaken >= startingLife
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static updatePlayerSetup() {
|
|
|
|
|
const playerCountInput = document.getElementById('playerCount');
|
|
|
|
|
@@ -636,13 +836,13 @@ export default class PageMtgGame extends TableBasePage {
|
|
|
|
|
window.location.reload();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
console.error('Failed to save players:', data[flagMessage]);
|
|
|
|
|
PageMtgGame.showError('An error occurred while creating the game');
|
|
|
|
|
console.error('Failed to save player damages:', data[flagMessage]);
|
|
|
|
|
PageMtgGame.showError('An error occurred while saving player damages');
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(error => {
|
|
|
|
|
console.error('Error creating game:', error);
|
|
|
|
|
PageMtgGame.showError('An error occurred while creating the game');
|
|
|
|
|
console.error('Error saving player damages:', error);
|
|
|
|
|
PageMtgGame.showError('An error occurred while saving player damages');
|
|
|
|
|
})
|
|
|
|
|
.finally(() => {
|
|
|
|
|
});
|
|
|
|
|
|