Feat: Game Rounds and Damage Log.

This commit is contained in:
2026-02-11 22:11:15 +00:00
parent 29ddd1ded0
commit 1cd9b7c976
20 changed files with 860 additions and 171 deletions

View File

@@ -18,6 +18,7 @@ RETURNS TABLE (
, location_name TEXT
, start_on TIMESTAMP
, end_on TIMESTAMP
, starting_life INT
, active BOOLEAN
, created_on TIMESTAMP
, created_by_user_id INT
@@ -60,6 +61,7 @@ BEGIN
, GAME.location_name
, GAME.start_on
, GAME.end_on
, GAME.starting_life
, GAME.active
, GAME.created_on
, GAME.created_by_user_id

View File

@@ -26,7 +26,7 @@ BEGIN
DROP TABLE IF EXISTS Temp_MTG_Round_Damage_Save_Round_Player_Damage;
DROP TABLE IF EXISTS Temp_MTG_Round_Damage_Save_Error;
CREATE TABLE Temp_MTG_Round_Damage_Save_Game (
CREATE TEMP TABLE Temp_MTG_Round_Damage_Save_Game (
game_id INT NOT NULL
, notes TEXT
, is_commander BOOLEAN
@@ -43,7 +43,7 @@ BEGIN
, change_set_id INT
);
CREATE TABLE Temp_MTG_Round_Damage_Save_Player (
CREATE TEMP TABLE Temp_MTG_Round_Damage_Save_Player (
player_id INT NOT NULL
, game_id INT
, user_id INT
@@ -59,7 +59,7 @@ BEGIN
, change_set_id INT
);
CREATE TABLE Temp_MTG_Round_Damage_Save_Round (
CREATE TEMP TABLE Temp_MTG_Round_Damage_Save_Round (
temp_id INT NOT NULL
, round_id INT
, game_id INT
@@ -74,10 +74,10 @@ BEGIN
, is_new BOOLEAN
, error_name TEXT
, is_duplicate BOOLEAN
, is_duplicate BOOLEAN DEFAULT FALSE
);
CREATE TABLE Temp_MTG_Round_Damage_Save_Round_Player_Damage (
CREATE TEMP TABLE Temp_MTG_Round_Damage_Save_Round_Player_Damage (
temp_id INT NOT NULL
, damage_id INT
, temp_round_id INT
@@ -96,7 +96,7 @@ BEGIN
, is_new BOOLEAN
, error_name TEXT
, is_duplicate BOOLEAN
, is_duplicate BOOLEAN DEFAULT FALSE
);
CREATE TEMP TABLE Temp_MTG_Round_Damage_Save_Error (
@@ -147,7 +147,7 @@ BEGIN
, COALESCE(ROUND_T.updated_last_on, v_time_start) -- updated_last_on
, COALESCE(ROUND_T.updated_last_by_user_id, a_user_id) -- updated_last_by_user_id
, CASE WHEN ROUND.round_id IS NULL THEN TRUE ELSE FALSE END AS is_new
, CASE WHEN TCG_ROUND.round_id IS NULL THEN TRUE ELSE FALSE END AS is_new
, CONCAT(
'Round { id: '
, CAST(ROUND_T.round_id AS VARCHAR)
@@ -160,12 +160,12 @@ BEGIN
, ' }'
) -- error_name
FROM tcg.public.TCG_MTG_Game_Round_Temp ROUND_T
LEFT JOIN tcg.public.TCG_MTG_Game_Round ROUND
ON ROUND_T.round_id = ROUND.round_id
LEFT JOIN tcg.public.TCG_MTG_Game_Round TCG_ROUND
ON ROUND_T.round_id = TCG_ROUND.round_id
OR (
COALESCE(ROUND_T.round_id, 0) < 1
AND ROUND_T.game_id = ROUND.game_id
AND ROUND_T.display_order = ROUND.display_order
AND ROUND_T.game_id = TCG_ROUND.game_id
AND ROUND_T.display_order = TCG_ROUND.display_order
)
WHERE ROUND_T.guid = a_guid
;
@@ -243,16 +243,18 @@ BEGIN
WHERE PLAYER_DAMAGE_T.guid = a_guid
;
UPDATE Temp_MTG_Round_Damage_Save_Round
SET round_id = COALESCE(ROUND.round_id, ROUND_T.round_id, 0)
FROM tcg.public.TCG_MTG_Game_Round_Temp ROUND_T
LEFT JOIN tcg.public.TCG_MTG_Game_Round ROUND
ON ROUND_T.round_id = ROUND.round_id
OR (
ROUND_T.game_id = ROUND.game_id
AND ROUND_T.display_order = ROUND.display_order
UPDATE Temp_MTG_Round_Damage_Save_Round T_ROUND
SET round_id = COALESCE(TCG_ROUND.round_id, T_ROUND.round_id)
FROM tcg.public.TCG_MTG_Game_Round TCG_ROUND
WHERE
(
T_ROUND.round_id = TCG_ROUND.round_id
OR (
T_ROUND.game_id = TCG_ROUND.game_id
AND T_ROUND.display_order = TCG_ROUND.display_order
)
)
WHERE COALESCE(ROUND_T.round_id, 0) < 1
AND COALESCE(T_ROUND.round_id, 0) < 1
;
UPDATE Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE
@@ -350,6 +352,22 @@ BEGIN
OR PLAYER.player_id = T_PLAYER_DAMAGE.received_from_commander_player_id
;
/*
INSERT INTO Temp_MTG_Round_Damage_Save_Error (
error_type_id
, message
)
SELECT
v_bad_data_error_type_id -- error_type_id
, CONCAT(
'Rounds: '
, STRING_AGG(T_ROUND.error_name, ', ')
, '.'
) -- message
FROM Temp_MTG_Round_Damage_Save_Round T_ROUND
;
*/
-- Validate Round
-- Missing fields
WITH Round_Missing_Field AS (
@@ -404,7 +422,25 @@ BEGIN
-- Duplicate
WITH
All_Round AS (
Existing_Round AS (
SELECT
TCG_ROUND.round_id
, TCG_ROUND.game_id
, TCG_ROUND.display_order
FROM tcg.public.TCG_MTG_Game_Round TCG_ROUND
LEFT JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND ON TCG_ROUND.round_id = T_ROUND.round_id
WHERE
TCG_ROUND.active
/*
AND NOT EXISTS (
SELECT 1
FROM Temp_MTG_Round_Damage_Save_Round T_ROUND
WHERE T_ROUND.round_id = TCG_ROUND.round_id
)
*/
AND T_ROUND.temp_id IS NULL
)
, All_Round AS (
SELECT
T_ROUND.temp_id
, T_ROUND.game_id
@@ -414,27 +450,23 @@ BEGIN
UNION
SELECT
NULL AS temp_id
, ROUND.game_id
, ROUND.display_order
, EXISTING_ROUND.game_id
, EXISTING_ROUND.display_order
, FALSE AS is_save_record
FROM tcg.public.TCG_MTG_Game_Round ROUND
LEFT JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND ON ROUND.round_id = T_ROUND.round_id
WHERE
T_ROUND.round_id IS NULL
AND ROUND.active
FROM Existing_Round EXISTING_ROUND
)
, Unique_Game_Round AS (
SELECT
ALL_ROUND.game_id
, ALL_ROUND.display_order
, COUNT(*) AS count
, COUNT(*) AS count_rounds
FROM All_Round ALL_ROUND
GROUP BY
ALL_ROUND.game_id
, ALL_ROUND.display_order
)
UPDATE Temp_MTG_Round_Damage_Save_Round T_ROUND
SET is_duplicate = CASE WHEN COALESCE(UNIQUE_GAME_ROUND.count, 0) > 1 THEN TRUE ELSE FALSE END
SET is_duplicate = CASE WHEN COALESCE(UNIQUE_GAME_ROUND.count_rounds, 0) > 1 THEN TRUE ELSE FALSE END
FROM Unique_Game_Round UNIQUE_GAME_ROUND
WHERE
T_ROUND.game_id = UNIQUE_GAME_ROUND.game_id
@@ -462,6 +494,123 @@ BEGIN
;
END IF;
/*
-- Testing TESTING
WITH
Existing_Round AS (
SELECT
TCG_ROUND.round_id
, TCG_ROUND.game_id
, TCG_ROUND.display_order
FROM tcg.public.TCG_MTG_Game_Round TCG_ROUND
LEFT JOIN Temp_MTG_Round_Damage_Save_Round T_ROUND ON TCG_ROUND.round_id = T_ROUND.round_id
WHERE
TCG_ROUND.active
/*
AND NOT EXISTS (
SELECT *
FROM Temp_MTG_Round_Damage_Save_Round T_ROUND
WHERE T_ROUND.round_id = TCG_ROUND.round_id
)
*/
AND T_ROUND.temp_id IS NULL
)
, All_Round AS (
SELECT
T_ROUND.temp_id
, T_ROUND.round_id
, T_ROUND.game_id
, T_ROUND.display_order
, TRUE AS is_save_record
FROM Temp_MTG_Round_Damage_Save_Round T_ROUND
UNION
SELECT
NULL AS temp_id
, EXISTING_ROUND.round_id
, EXISTING_ROUND.game_id
, EXISTING_ROUND.display_order
, FALSE AS is_save_record
FROM Existing_Round EXISTING_ROUND
)
, Unique_Game_Round AS (
SELECT
ALL_ROUND.game_id
, ALL_ROUND.display_order
, COUNT(*) AS count_rounds
FROM All_Round ALL_ROUND
GROUP BY
ALL_ROUND.game_id
, ALL_ROUND.display_order
)
INSERT INTO Temp_MTG_Round_Damage_Save_Error (
error_type_id
, message
)
SELECT
v_bad_data_error_type_id -- error_type_id
, CONCAT(
'TEST: Existing rounds: '
, STRING_AGG(
CONCAT(
'{ Round ID: '
, CAST(EXISTING_ROUND.round_id AS VARCHAR)
, ', Game ID: '
, CAST(EXISTING_ROUND.game_id AS VARCHAR)
, ', Display order: '
, CAST(EXISTING_ROUND.display_order AS VARCHAR)
, ' }'
)
, ', '
)
) -- message
FROM Existing_Round EXISTING_ROUND
UNION
SELECT
v_bad_data_error_type_id -- error_type_id
, CONCAT(
'TEST: All rounds: '
-- , STRING_AGG(CONCAT(ALL_ROUND.temp_id, ' - ', ALL_ROUND.game_id, ' - ', ALL_ROUND.display_order), ', ')
, STRING_AGG(
CONCAT(
'{ Temp ID: '
, CAST(ALL_ROUND.temp_id AS VARCHAR)
, ', Round ID: '
, CAST(ALL_ROUND.round_id AS VARCHAR)
, ', Game ID: '
, CAST(ALL_ROUND.game_id AS VARCHAR)
, ', Display order: '
, CAST(ALL_ROUND.display_order AS VARCHAR)
, ' }'
)
, ', '
)
) -- message
FROM All_Round ALL_ROUND
UNION
SELECT
v_bad_data_error_type_id -- error_type_id
, CONCAT(
'TEST: Unique rounds: '
-- , STRING_AGG(CONCAT(UNIQUE_ROUND.game_id, ' - ', UNIQUE_ROUND.display_order, ' - ', UNIQUE_ROUND.count_rounds), ', ')
, STRING_AGG(
CONCAT(
'{ Game ID: '
, CAST(UNIQUE_ROUND.game_id AS VARCHAR)
, ', Display order: '
, CAST(UNIQUE_ROUND.display_order AS VARCHAR)
, ' Count: '
, CAST(UNIQUE_ROUND.count_rounds AS VARCHAR)
, ' }'
)
, ', '
)
) -- message
FROM Unique_Game_Round UNIQUE_ROUND
;
*/
-- Validate Damage
-- Missing fields
WITH Player_Damage_Missing_Field AS (
@@ -550,7 +699,18 @@ BEGIN
-- Duplicate Round Player Damage
WITH
All_Player_Damage AS (
Existing_Player_Damage AS (
SELECT
T_PLAYER_DAMAGE.round_id
, T_PLAYER_DAMAGE.player_id
, COALESCE(T_PLAYER_DAMAGE.received_from_commander_player_id, 0) AS received_from_commander_player_id
FROM tcg.public.TCG_MTG_Game_Round_Player_Damage PLAYER_DAMAGE
LEFT JOIN Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE ON PLAYER_DAMAGE.damage_id = T_PLAYER_DAMAGE.damage_id
WHERE
T_PLAYER_DAMAGE.temp_id IS NULL
AND PLAYER_DAMAGE.active
)
, All_Player_Damage AS (
SELECT
T_PLAYER_DAMAGE.temp_id
, T_PLAYER_DAMAGE.round_id
@@ -561,22 +721,18 @@ BEGIN
UNION
SELECT
NULL AS temp_id
, T_PLAYER_DAMAGE.round_id
, T_PLAYER_DAMAGE.player_id
, COALESCE(T_PLAYER_DAMAGE.received_from_commander_player_id, 0) AS received_from_commander_player_id
, EXISTING_PLAYER_DAMAGE.round_id
, EXISTING_PLAYER_DAMAGE.player_id
, EXISTING_PLAYER_DAMAGE.received_from_commander_player_id
, FALSE AS is_save_record
FROM tcg.public.TCG_MTG_Game_Round_Player_Damage PLAYER_DAMAGE
LEFT JOIN Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE ON PLAYER_DAMAGE.damage_id = T_PLAYER_DAMAGE.damage_id
WHERE
T_PLAYER_DAMAGE.damage_id IS NULL
AND PLAYER_DAMAGE.active
FROM Existing_Player_Damage EXISTING_PLAYER_DAMAGE
)
, Unique_Game_Player_Damage AS (
SELECT
ALL_PLAYER_DAMAGE.round_id
, ALL_PLAYER_DAMAGE.player_id
, ALL_PLAYER_DAMAGE.received_from_commander_player_id
, COUNT(*) AS count
, COUNT(*) AS count_damage
FROM All_Player_Damage ALL_PLAYER_DAMAGE
GROUP BY
ALL_PLAYER_DAMAGE.round_id
@@ -584,12 +740,12 @@ BEGIN
, ALL_PLAYER_DAMAGE.received_from_commander_player_id
)
UPDATE Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE
SET is_duplicate = CASE WHEN COALESCE(UNIQUE_PLAYER_DAMAGE.count, 0) > 1 THEN TRUE ELSE FALSE END
SET is_duplicate = CASE WHEN COALESCE(UNIQUE_PLAYER_DAMAGE.count_damage, 0) > 1 THEN TRUE ELSE FALSE END
FROM Unique_Game_Player_Damage UNIQUE_PLAYER_DAMAGE
WHERE
T_PLAYER_DAMAGE.round_id = UNIQUE_PLAYER_DAMAGE.round_id
AND T_PLAYER_DAMAGE.player_id = UNIQUE_PLAYER_DAMAGE.player_id
AND T_PLAYER_DAMAGE.received_from_commander_player_id = UNIQUE_PLAYER_DAMAGE.received_from_commander_player_id
AND COALESCE(T_PLAYER_DAMAGE.received_from_commander_player_id, 0) = UNIQUE_PLAYER_DAMAGE.received_from_commander_player_id
;
IF EXISTS (
@@ -725,7 +881,7 @@ BEGIN
, T_ROUND.display_order
;
UPDATE tcg.public.TCG_MTG_Game_Round ROUND
UPDATE tcg.public.TCG_MTG_Game_Round TCG_ROUND
SET
game_id = T_ROUND.game_id
, notes = T_ROUND.notes
@@ -736,16 +892,16 @@ BEGIN
, change_set_id = v_change_set_id
FROM Temp_MTG_Round_Damage_Save_Round T_ROUND
WHERE
ROUND.round_id = T_ROUND.round_id
TCG_ROUND.round_id = T_ROUND.round_id
AND NOT T_ROUND.is_new
;
UPDATE Temp_MTG_Round_Damage_Save_Round T_ROUND
SET round_id = ROUND.round_id
FROM tcg.public.TCG_MTG_Game_Round ROUND
SET round_id = TCG_ROUND.round_id
FROM tcg.public.TCG_MTG_Game_Round TCG_ROUND
WHERE
T_ROUND.game_id = ROUND.game_id
AND T_ROUND.display_order = ROUND.display_order
T_ROUND.game_id = TCG_ROUND.game_id
AND T_ROUND.display_order = TCG_ROUND.display_order
AND T_ROUND.is_new
;
@@ -865,8 +1021,59 @@ DECLARE
v_user_id INT := 3;
v_success BOOLEAN;
BEGIN
v_guid := gen_random_uuid();
v_guid := '6307bed6-73a1-41ab-9a90-79e18e14dd81'::UUID; -- gen_random_uuid();
CALL tcg.public.USP_TCG_MTG_Game_Round_Damage_Save (
a_comment := v_comment -- a_comment
, a_guid := v_guid -- a_guid
, a_user_id := v_user_id -- a_user_id
, o_success := v_success -- o_success
);
RAISE NOTICE 'Success: %', CASE WHEN v_success THEN 'TRUE' ELSE 'FALSE' END;
END;
$$;
SELECT *
-- DELETE
FROM tcg.public.Error ERROR
LEFT JOIN tcg.public.Error_Type ERROR_TYPE ON ERROR.error_type_id = ERROR_TYPE.error_type_id
;
SELECT *
FROM tcg.public.Error_Type ERROR_TYPE
;
SELECT *
FROM tcg.public.TCG_Change_Set CHANGE_SET
ORDER BY CHANGE_SET.change_set_id DESC
;
/*
SELECT *
FROM tcg.public.TCG_MTG_Game
;
;
*/
SELECT *
-- DELETE
FROM tcg.public.TCG_MTG_Game_Round_Temp
;
SELECT *
-- DELETE
FROM tcg.public.TCG_MTG_Game_Round_Player_Damage_Temp
;
SELECT *
-- DELETE
FROM tcg.public.TCG_MTG_Game_Round TCG_ROUND
LEFT JOIN tcg.public.TCG_MTG_Game GAME ON TCG_ROUND.game_id = GAME.game_id
;
SELECT *
-- DELETE
FROM tcg.public.TCG_MTG_Game_Round_Player_Damage PLAYER_DAMAGE
LEFT JOIN tcg.public.TCG_MTG_Game_Round TCG_ROUND ON PLAYER_DAMAGE.round_id = TCG_ROUND.round_id
LEFT JOIN tcg.public.TCG_MTG_Game GAME ON TCG_ROUND.game_id = GAME.game_id
;
/*
INSERT INTO tcg.public.TCG_MTG_Game_Round_Temp (
guid
, round_id
@@ -927,52 +1134,8 @@ BEGIN
, TRUE -- active
)
;
CALL tcg.public.USP_TCG_MTG_Game_Round_Damage_Save (
a_comment := v_comment -- a_comment
, a_guid := v_guid -- a_guid
, a_user_id := v_user_id -- a_user_id
, o_success := v_success -- o_success
);
RAISE NOTICE 'Success: %', CASE WHEN v_success THEN 'TRUE' ELSE 'FALSE' END;
END;
$$;
SELECT *
-- DELETE
FROM tcg.public.Error ERROR
LEFT JOIN tcg.public.Error_Type ERROR_TYPE ON ERROR.error_type_id = ERROR_TYPE.error_type_id
;
SELECT *
FROM tcg.public.Error_Type ERROR_TYPE
;
SELECT *
FROM tcg.public.TCG_Change_Set CHANGE_SET
ORDER BY CHANGE_SET.change_set_id DESC
;
/*
SELECT *
FROM tcg.public.TCG_MTG_Game
;
*/
SELECT *
-- DELETE
FROM tcg.public.TCG_MTG_Game_Round_Temp
;
SELECT *
-- DELETE
FROM tcg.public.TCG_MTG_Game_Round_Player_Damage_Temp
;
SELECT *
-- DELETE
FROM tcg.public.TCG_MTG_Game_Round ROUND
LEFT JOIN tcg.public.TCG_MTG_Game GAME ON ROUND.game_id = GAME.game_id
;
SELECT *
-- DELETE
FROM tcg.public.TCG_MTG_Game_Round_Player_Damage PLAYER_DAMAGE
LEFT JOIN tcg.public.TCG_MTG_Game_Round ROUND ON PLAYER_DAMAGE.round_id = ROUND.round_id
LEFT JOIN tcg.public.TCG_MTG_Game GAME ON ROUND.game_id = GAME.game_id
;
*/

View File

@@ -49,7 +49,7 @@
.topnav .container .logo {
/* min-width: 35vh; */
max-width: 30vw;
width: 30vw;
/* width: 30vw; */
/* min-height: 6vh; */
max-height: 6vh;
margin: 0.5vh;

View File

@@ -83,9 +83,6 @@ body.tcg-theme {
.footer.tcg {
background: var(--tcg-bg-secondary);
border-top: 2px solid var(--tcg-border-color);
color: var(--tcg-text-secondary);
padding: 2rem;
margin-top: 3rem;
}
.footer.tcg h3 {

View File

@@ -146,6 +146,62 @@
text-align: center;
}
/* Game Section */
#gameSection .row.round {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.9rem;
color: var(--tcg-text-secondary);
margin: 0 auto 0.5vh;
width: fit-content;
}
#gameSection .row.round .row.round .round.display_order {
display: flex;
align-items: center;
gap: 0.5rem;
background: var(--tcg-bg-card);
border: 1px solid var(--tcg-border-color);
border-radius: 6px;
padding: 0.25rem 0.5rem;
}
/*
#gameSection .row.round label {
margin-left: 30vw;
color: var(--tcg-text-secondary);
font-size: 1rem;
width: 4vw;
}
#gameSection .row.round input {
width: 10vw;
margin: 0 3vw 1vh;
}
*/
#gameSection .row.round .row.round span.round.display_order {
font-family: 'Cinzel', serif;
font-weight: 600;
color: var(--tcg-text-primary);
min-width: 20px;
justify-content: center;
}
#gameSection .row.round .row.round button.btn-round-display-order {
background: transparent;
border: none;
color: var(--tcg-text-secondary);
cursor: pointer;
font-size: 1rem;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
#gameSection .row.round .row.round button.btn-round-display-order:hover {
color: var(--tcg-accent-red);
transform: scale(1.2);
}
/* Players Grid */
.players-grid {
display: flex; /* grid;
@@ -407,6 +463,34 @@
color: var(--tcg-bg-primary);
}
.damage-log.container {
color: white;
margin: 2vh auto 0;
text-align: center;
}
.damage-log.container table thead tr th.round_id,
.damage-log.container table tbody tr td.round_id {
width: 7vw;
}
.damage-log.container table thead tr th.player_id,
.damage-log.container table tbody tr td.player_id,
.damage-log.container table thead tr th.received_from_commander_player_id,
.damage-log.container table tbody tr td.received_from_commander_player_id {
width: 20vw;
}
.damage-log.container table thead tr th.health_change,
.damage-log.container table tbody tr td.health_change {
width: 7vw;
}
.damage-log.container table thead tr th.commander-deaths,
.damage-log.container table tbody tr td.commander-deaths {
width: 7vw;
}
.damage-log.container table thead tr th.is_eliminated,
.damage-log.container table tbody tr td.is_eliminated {
width: 7vw;
}
/* Save Indicator */
.save-indicator {
position: fixed;

View File

@@ -578,7 +578,7 @@ table div {
.topnav .container .logo {
/* min-width: 35vh; */
max-width: 30vw;
width: 30vw;
/* width: 30vw; */
/* min-height: 6vh; */
max-height: 6vh;
margin: 0.5vh;

File diff suppressed because one or more lines are too long

View File

@@ -212,6 +212,62 @@
text-align: center;
}
/* Game Section */
#gameSection .row.round {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.9rem;
color: var(--tcg-text-secondary);
margin: 0 auto 0.5vh;
width: fit-content;
}
#gameSection .row.round .row.round .round.display_order {
display: flex;
align-items: center;
gap: 0.5rem;
background: var(--tcg-bg-card);
border: 1px solid var(--tcg-border-color);
border-radius: 6px;
padding: 0.25rem 0.5rem;
}
/*
#gameSection .row.round label {
margin-left: 30vw;
color: var(--tcg-text-secondary);
font-size: 1rem;
width: 4vw;
}
#gameSection .row.round input {
width: 10vw;
margin: 0 3vw 1vh;
}
*/
#gameSection .row.round .row.round span.round.display_order {
font-family: 'Cinzel', serif;
font-weight: 600;
color: var(--tcg-text-primary);
min-width: 20px;
justify-content: center;
}
#gameSection .row.round .row.round button.btn-round-display-order {
background: transparent;
border: none;
color: var(--tcg-text-secondary);
cursor: pointer;
font-size: 1rem;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
}
#gameSection .row.round .row.round button.btn-round-display-order:hover {
color: var(--tcg-accent-red);
transform: scale(1.2);
}
/* Players Grid */
.players-grid {
display: flex; /* grid;
@@ -473,6 +529,34 @@
color: var(--tcg-bg-primary);
}
.damage-log.container {
color: white;
margin: 2vh auto 0;
text-align: center;
}
.damage-log.container table thead tr th.round_id,
.damage-log.container table tbody tr td.round_id {
width: 7vw;
}
.damage-log.container table thead tr th.player_id,
.damage-log.container table tbody tr td.player_id,
.damage-log.container table thead tr th.received_from_commander_player_id,
.damage-log.container table tbody tr td.received_from_commander_player_id {
width: 20vw;
}
.damage-log.container table thead tr th.health_change,
.damage-log.container table tbody tr td.health_change {
width: 7vw;
}
.damage-log.container table thead tr th.commander-deaths,
.damage-log.container table tbody tr td.commander-deaths {
width: 7vw;
}
.damage-log.container table thead tr th.is_eliminated,
.damage-log.container table tbody tr td.is_eliminated {
width: 7vw;
}
/* Save Indicator */
.save-indicator {
position: fixed;

File diff suppressed because one or more lines are too long

View File

@@ -260,7 +260,6 @@ class DOM {
return returnVal;
}
static getElementAttributeValueCurrent(element) {
// debugger;
if (Validation.isEmpty(element)) return null;
return element.getAttribute(attrValueCurrent);
}
@@ -1024,12 +1023,6 @@ class TableBasePage extends BasePage {
}
let formElement = TableBasePage.getFormFilters();
let comment = DOM.getElementValueCurrent(document.querySelector(idTextareaConfirm));
/*
Utils.consoleLogIfNotProductionEnvironment({ formElement, comment, records });
Utils.consoleLogIfNotProductionEnvironment('records');
Utils.consoleLogIfNotProductionEnvironment(records);
debugger;
*/
this.callSaveTableContent(records, formElement, comment).then(data => {
if (data[flagStatus] == flagSuccess) {
if (_verbose) {
@@ -1689,11 +1682,18 @@ class PageMtgGame extends TableBasePage {
});
// 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');
grid.innerHTML = '';
@@ -1710,7 +1710,16 @@ 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];
@@ -1721,7 +1730,7 @@ class PageMtgGame extends TableBasePage {
let maxCommanderDamageReceived = 0;
damagePlayerPairs.forEach(damagePlayerPair => {
const sourceId = damagePlayerPair[attrPlayerId];
const filteredPlayerDamages = damageRecords.filter(damage => damage[attrRoundId] == latestRoundId && damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == sourceId); //[playerId] || {};
const filteredPlayerDamages = damageRecords.filter(damage => damage[attrRoundId] == activeRoundId && damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == sourceId); //[playerId] || {};
if (filteredPlayerDamages.length == 0) {
damageRecords.push(PageMtgGame.makeDefaultGameRoundPlayerDamage(playerId, sourceId));
}
@@ -1731,7 +1740,7 @@ class PageMtgGame extends TableBasePage {
let life = startingLife + totalDamage;
let isEliminatedByForce = damageRecords.filter(damage => damage[attrPlayerId] == playerId).map(damage => damage[flagIsEliminated]).some(Boolean);
const isEliminated = isEliminatedByForce || !player[flagActive] || life < 1 || maxCommanderDamageReceived >= 21;
const playerOwnDamage = damageRecords.filter(damage => damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == null && damage[attrRoundId] == latestRoundId)[0];
const playerOwnDamage = damageRecords.filter(damage => damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == null && damage[attrRoundId] == activeRoundId)[0];
const card = document.createElement('div');
card.className = `player-card ${isEliminated ? 'eliminated' : ''}`;
card.style.animationDelay = `${index * 0.1}s`;
@@ -1778,12 +1787,42 @@ 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,
@@ -1797,13 +1836,32 @@ class PageMtgGame extends TableBasePage {
static getLatestRoundId() {
let roundId = -1;
if (rounds.length > 0) {
let highestRoundDisplayOrder = Math.max(rounds.map(round => {
const highestRoundDisplayOrder = rounds.map(round => {
return round[flagDisplayOrder];
}));
roundId = rounds.filter(round => round[flagDisplayOrder] == highestRoundDisplayOrder)[0][attrRoundId];
}).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
});
}
@@ -1839,14 +1897,38 @@ 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 damageIndex = damageRecords.findIndex(damage => damage[attrRoundId] == latestRoundId && damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == null);
const activeRoundId = PageMtgGame.getActiveRoundId();
const damageIndex = damageRecords.findIndex(damage => damage[attrRoundId] == activeRoundId && damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == null);
this.changeLife(playerId // playerId
, amount // amount
, true // updateDamage
@@ -1894,6 +1976,7 @@ class PageMtgGame extends TableBasePage {
if (updateDamage) {
damageRecords[damageIndex][flagHealthChange] += amount;
}
PageMtgGame.renderCommanderDamageLog();
// PageMtgGame.debouncedSave();
this.updateAndToggleShowButtonsSaveCancel();
@@ -1917,8 +2000,8 @@ class PageMtgGame extends TableBasePage {
} else {
damageDisplay.classList.remove('lethal');
}
const latestRoundId = PageMtgGame.getLatestRoundId();
const damageIndex = damageRecords.findIndex(damageRecord => damageRecord[attrRoundId] == latestRoundId && damageRecord[attrPlayerId] == playerId && damageRecord[attrReceivedFromCommanderPlayerId] == sourceId);
const activeRoundId = PageMtgGame.getActiveRoundId();
const damageIndex = damageRecords.findIndex(damageRecord => damageRecord[attrRoundId] == activeRoundId && damageRecord[attrPlayerId] == playerId && damageRecord[attrReceivedFromCommanderPlayerId] == sourceId);
damageRecords[damageIndex][flagHealthChange] -= amount;
this.changeLife(playerId // playerId
, -amount // amount
@@ -1936,9 +2019,10 @@ class PageMtgGame extends TableBasePage {
deathDisplay.textContent = newDeaths;
DOM.setElementAttributeValueCurrent(deathDisplay, newDeaths);
DOM.isElementDirty(deathDisplay);
const latestRoundId = PageMtgGame.getLatestRoundId();
const damageIndex = damageRecords.findIndex(damage => damage[attrRoundId] == latestRoundId && damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == null);
const activeRoundId = PageMtgGame.getActiveRoundId();
const damageIndex = damageRecords.findIndex(damage => damage[attrRoundId] == activeRoundId && damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == null);
damageRecords[damageIndex][flagCommanderDeaths] = newDeaths;
PageMtgGame.renderCommanderDamageLog();
// PageMtgGame.debouncedSave();
this.updateAndToggleShowButtonsSaveCancel();
@@ -1956,14 +2040,65 @@ class PageMtgGame extends TableBasePage {
eliminateBtn.textContent = 'Revive';
}
const isEliminated = card.classList.contains('eliminated');
const latestRoundId = PageMtgGame.getLatestRoundId();
const damageIndex = damageRecords.findIndex(damage => damage[attrRoundId] == latestRoundId && damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == null);
const activeRoundId = PageMtgGame.getActiveRoundId();
const damageIndex = damageRecords.findIndex(damage => damage[attrRoundId] == activeRoundId && damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == null);
damageRecords[damageIndex][flagIsEliminated] = isEliminated;
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');
if (!playerCountInput) return;
@@ -2076,12 +2211,12 @@ class PageMtgGame extends TableBasePage {
self.leave();
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(() => {});
}
/*
@@ -2232,15 +2367,12 @@ class PageMtgGames extends TableBasePage {
submitBtn.disabled = true;
const games = [gameData];
const comment = 'Create new game';
debugger;
// const self = this;
API.saveGame(games, form, comment).then(data => {
if (data[flagStatus] == flagSuccess) {
if (_verbose) {
utils_Utils.consoleLogIfNotProductionEnvironment('Records saved!');
utils_Utils.consoleLogIfNotProductionEnvironment('Data received:', data);
}
// this.callFilterTableContent(data[attrGameId]); // gameData.game_id
const gamePageHash = `${hashPageGame}/${data[attrGameId]}`;
let filtersJson = {};
this.leave();

File diff suppressed because one or more lines are too long

View File

@@ -141,7 +141,6 @@ export default class DOM {
return returnVal;
}
static getElementAttributeValueCurrent(element) {
// debugger;
if (Validation.isEmpty(element)) return null;
return element.getAttribute(attrValueCurrent);
}

View File

@@ -236,12 +236,6 @@ export default class TableBasePage extends BasePage {
}
let formElement = TableBasePage.getFormFilters();
let comment = DOM.getElementValueCurrent(document.querySelector(idTextareaConfirm));
/*
Utils.consoleLogIfNotProductionEnvironment({ formElement, comment, records });
Utils.consoleLogIfNotProductionEnvironment('records');
Utils.consoleLogIfNotProductionEnvironment(records);
debugger;
*/
this.callSaveTableContent(records, formElement, comment)
.then(data => {
if (data[flagStatus] == flagSuccess) {

View File

@@ -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(() => {
});

View File

@@ -118,8 +118,6 @@ export default class PageMtgGames extends TableBasePage {
const games = [gameData];
const comment = 'Create new game';
debugger;
// const self = this;
API.saveGame(games, form, comment)
.then(data => {
if (data[flagStatus] == flagSuccess) {
@@ -127,7 +125,6 @@ export default class PageMtgGames extends TableBasePage {
Utils.consoleLogIfNotProductionEnvironment('Records saved!');
Utils.consoleLogIfNotProductionEnvironment('Data received:', data);
}
// this.callFilterTableContent(data[attrGameId]); // gameData.game_id
const gamePageHash = `${hashPageGame}/${data[attrGameId]}`;
let filtersJson = {};
this.leave();