Feat: Decks page.
This commit is contained in:
@@ -76,6 +76,7 @@ class Base():
|
||||
FLAG_TEXT_COLOUR: ClassVar[str] = 'text_colour'
|
||||
FLAG_URL: ClassVar[str] = 'url'
|
||||
FLAG_USER: ClassVar[str] = 'authorisedUser' # 'user' already used
|
||||
FLAG_VALUE: ClassVar[str] = 'value'
|
||||
FLAG_VALUE_LOCAL_VAT_EXCL: ClassVar[str] = 'value_local_vat_excl'
|
||||
FLAG_VALUE_LOCAL_VAT_INCL: ClassVar[str] = 'value_local_vat_incl'
|
||||
FLAG_WEBSITE: ClassVar[str] = 'website'
|
||||
|
||||
@@ -10,6 +10,7 @@ Feature: MTG Deck Business Object
|
||||
# internal
|
||||
from business_objects.base import Base
|
||||
from business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base
|
||||
from business_objects.tcg.mtg_deck_commander_bracket import MTG_Deck_Commander_Bracket
|
||||
import lib.argument_validation as av
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
@@ -24,6 +25,7 @@ class MTG_Deck(SQLAlchemy_ABC, Base):
|
||||
ATTR_COMMANDER_BRACKET_ID: ClassVar[str] = 'commander_bracket_id'
|
||||
FLAG_DECK: ClassVar[str] = 'deck'
|
||||
FLAG_IS_COMMANDER: ClassVar[str] = 'is_commander'
|
||||
FLAG_STATISTICS: ClassVar[str] = 'statistics'
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = ATTR_DECK_ID
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_NAME
|
||||
|
||||
@@ -41,9 +43,13 @@ class MTG_Deck(SQLAlchemy_ABC, Base):
|
||||
updated_last_by_user_id = db.Column(db.Integer)
|
||||
change_set_id = db.Column(db.Integer)
|
||||
|
||||
# commander_bracket: MTG_Deck_Commander_Bracket
|
||||
|
||||
def __init__(self):
|
||||
self.deck_id = 0
|
||||
self.is_new = False
|
||||
self.commander_bracket = None
|
||||
self.statistics = None
|
||||
super().__init__()
|
||||
|
||||
@classmethod
|
||||
@@ -83,6 +89,7 @@ class MTG_Deck(SQLAlchemy_ABC, Base):
|
||||
, self.FLAG_ACTIVE: self.active
|
||||
, self.FLAG_CREATED_ON: self.created_on
|
||||
, Base.ATTR_USER_ID: self.created_by_user_id
|
||||
, self.FLAG_STATISTICS: self.statistics
|
||||
}
|
||||
return as_json
|
||||
|
||||
|
||||
@@ -104,21 +104,19 @@ class Parameters_MTG_Deck_Commander_Bracket(Get_Many_Parameters_Base):
|
||||
get_inactive_commander_bracket: bool
|
||||
commander_bracket_ids: str
|
||||
commander_bracket_names: str
|
||||
user_ids: str
|
||||
require_all_id_filters_met: bool
|
||||
require_any_id_filters_met: bool
|
||||
require_all_non_id_filters_met: bool
|
||||
require_any_non_id_filters_met: bool
|
||||
|
||||
@classmethod
|
||||
def get_default(cls, user_id_session):
|
||||
def get_default(cls):
|
||||
return cls(
|
||||
get_all_commander_bracket = True
|
||||
, get_inactive_commander_bracket = False
|
||||
, commander_bracket_ids = ''
|
||||
, commander_bracket_names = ''
|
||||
, user_ids = str(user_id_session)
|
||||
, require_all_id_filters_met = True
|
||||
, require_all_id_filters_met = False
|
||||
, require_any_id_filters_met = True
|
||||
, require_all_non_id_filters_met = False
|
||||
, require_any_non_id_filters_met = True
|
||||
@@ -127,12 +125,11 @@ class Parameters_MTG_Deck_Commander_Bracket(Get_Many_Parameters_Base):
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
return cls(
|
||||
get_all_commander_bracket = json.get('a_get_all_commander_bracket', False)
|
||||
get_all_commander_bracket = json.get('a_get_all_commander_bracket', True)
|
||||
, get_inactive_commander_bracket = json.get('a_get_inactive_commander_bracket', False)
|
||||
, commander_bracket_ids = json.get('a_commander_bracket_ids', '')
|
||||
, commander_bracket_names = json.get('a_commander_bracket_names', '')
|
||||
, user_ids = json.get('a_user_ids', '')
|
||||
, require_all_id_filters_met = json.get('a_require_all_id_filters_met', True)
|
||||
, require_all_id_filters_met = json.get('a_require_all_id_filters_met', False)
|
||||
, require_any_id_filters_met = json.get('a_require_any_id_filters_met', True)
|
||||
, require_all_non_id_filters_met = json.get('a_require_all_non_id_filters_met', False)
|
||||
, require_any_non_id_filters_met = json.get('a_require_any_non_id_filters_met', True)
|
||||
@@ -144,7 +141,6 @@ class Parameters_MTG_Deck_Commander_Bracket(Get_Many_Parameters_Base):
|
||||
, 'a_get_inactive_commander_bracket': self.get_inactive_commander_bracket
|
||||
, 'a_commander_bracket_ids': self.commander_bracket_ids
|
||||
, 'a_commander_bracket_names': self.commander_bracket_names
|
||||
, 'a_user_ids': self.user_ids
|
||||
, 'a_require_all_id_filters_met': self.require_all_id_filters_met
|
||||
, 'a_require_any_id_filters_met': self.require_any_id_filters_met
|
||||
, 'a_require_all_non_id_filters_met': self.require_all_non_id_filters_met
|
||||
|
||||
@@ -27,8 +27,9 @@ class MTG_Game_Round_Player_Damage(SQLAlchemy_ABC, Base):
|
||||
ATTR_RECEIVED_FROM_COMMANDER_PLAYER_ID: ClassVar[str] = 'received_from_commander_player_id'
|
||||
FLAG_COMMANDER_DEATHS: ClassVar[str] = 'commander_deaths'
|
||||
FLAG_DAMAGE: ClassVar[str] = 'damage'
|
||||
FLAG_HEALTH_CHANGE: ClassVar[str] = 'health_change'
|
||||
FLAG_IS_ELIMINATED: ClassVar[str] = 'is_eliminated'
|
||||
FLAG_LIFE_GAIN: ClassVar[str] = 'life_gain'
|
||||
FLAG_LIFE_LOSS: ClassVar[str] = 'life_loss'
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = ATTR_DAMAGE_ID
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = ATTR_DAMAGE_ID
|
||||
|
||||
@@ -39,7 +40,8 @@ class MTG_Game_Round_Player_Damage(SQLAlchemy_ABC, Base):
|
||||
round_id = db.Column(db.Integer)
|
||||
player_id = db.Column(db.Integer)
|
||||
received_from_commander_player_id = db.Column(db.Integer)
|
||||
health_change = db.Column(db.Integer)
|
||||
life_gain = db.Column(db.Integer)
|
||||
life_loss = db.Column(db.Integer)
|
||||
commander_deaths = db.Column(db.Integer)
|
||||
is_eliminated = db.Column(db.Boolean)
|
||||
active = db.Column(db.Boolean)
|
||||
@@ -62,12 +64,13 @@ class MTG_Game_Round_Player_Damage(SQLAlchemy_ABC, Base):
|
||||
damage.round_id = query_row[1]
|
||||
damage.player_id = query_row[2]
|
||||
damage.received_from_commander_player_id = query_row[3]
|
||||
damage.health_change = query_row[4]
|
||||
damage.commander_deaths = query_row[5]
|
||||
damage.is_eliminated = av.input_bool(query_row[6], cls.FLAG_IS_ELIMINATED, _m)
|
||||
damage.active = av.input_bool(query_row[7], cls.FLAG_ACTIVE, _m)
|
||||
damage.created_on = query_row[8]
|
||||
damage.created_by_user_id = query_row[9]
|
||||
damage.life_gain = query_row[4]
|
||||
damage.life_loss = query_row[5]
|
||||
damage.commander_deaths = query_row[6]
|
||||
damage.is_eliminated = av.input_bool(query_row[7], cls.FLAG_IS_ELIMINATED, _m)
|
||||
damage.active = av.input_bool(query_row[8], cls.FLAG_ACTIVE, _m)
|
||||
damage.created_on = query_row[9]
|
||||
damage.created_by_user_id = query_row[10]
|
||||
return damage
|
||||
|
||||
@classmethod
|
||||
@@ -79,7 +82,8 @@ class MTG_Game_Round_Player_Damage(SQLAlchemy_ABC, Base):
|
||||
damage.round_id = json.get(cls.ATTR_ROUND_ID, None)
|
||||
damage.player_id = json.get(cls.ATTR_PLAYER_ID, None)
|
||||
damage.received_from_commander_player_id = json.get(cls.ATTR_RECEIVED_FROM_COMMANDER_PLAYER_ID, None)
|
||||
damage.health_change = json.get(cls.FLAG_HEALTH_CHANGE, 0)
|
||||
damage.life_gain = json.get(cls.FLAG_LIFE_GAIN, 0)
|
||||
damage.life_loss = json.get(cls.FLAG_LIFE_LOSS, 0)
|
||||
damage.commander_deaths = json.get(cls.FLAG_COMMANDER_DEATHS, 0)
|
||||
damage.is_eliminated = json.get(cls.FLAG_IS_ELIMINATED, False)
|
||||
damage.active = av.input_bool(json.get(cls.FLAG_ACTIVE, True), cls.FLAG_ACTIVE, _m)
|
||||
@@ -94,7 +98,8 @@ class MTG_Game_Round_Player_Damage(SQLAlchemy_ABC, Base):
|
||||
, self.ATTR_ROUND_ID: self.round_id
|
||||
, self.ATTR_PLAYER_ID: self.player_id
|
||||
, self.ATTR_RECEIVED_FROM_COMMANDER_PLAYER_ID: self.received_from_commander_player_id
|
||||
, self.FLAG_HEALTH_CHANGE: self.health_change
|
||||
, self.FLAG_LIFE_GAIN: self.life_gain
|
||||
, self.FLAG_LIFE_LOSS: self.life_loss
|
||||
, self.FLAG_COMMANDER_DEATHS: self.commander_deaths
|
||||
, self.FLAG_IS_ELIMINATED: self.is_eliminated
|
||||
, self.FLAG_ACTIVE: self.active
|
||||
@@ -110,7 +115,8 @@ class MTG_Game_Round_Player_Damage(SQLAlchemy_ABC, Base):
|
||||
{self.ATTR_ROUND_ID}: {self.round_id}
|
||||
{self.ATTR_PLAYER_ID}: {self.player_id}
|
||||
{self.ATTR_RECEIVED_FROM_COMMANDER_PLAYER_ID}: {self.received_from_commander_player_id}
|
||||
{self.FLAG_HEALTH_CHANGE}: {self.health_change}
|
||||
{self.FLAG_LIFE_GAIN}: {self.life_gain}
|
||||
{self.FLAG_LIFE_LOSS}: {self.life_loss}
|
||||
{self.FLAG_COMMANDER_DEATHS}: {self.commander_deaths}
|
||||
{self.FLAG_IS_ELIMINATED}: {self.is_eliminated}
|
||||
{self.FLAG_ACTIVE}: {self.active}
|
||||
@@ -127,7 +133,8 @@ class MTG_Game_Round_Player_Damage_Temp(db.Model, Base):
|
||||
round_id = db.Column(db.Integer)
|
||||
player_id = db.Column(db.Integer)
|
||||
received_from_commander_player_id = db.Column(db.Integer)
|
||||
health_change = db.Column(db.Integer)
|
||||
life_gain = db.Column(db.Integer)
|
||||
life_loss = db.Column(db.Integer)
|
||||
commander_deaths = db.Column(db.Integer)
|
||||
is_eliminated = db.Column(db.Boolean)
|
||||
active = db.Column(db.Boolean)
|
||||
@@ -145,7 +152,8 @@ class MTG_Game_Round_Player_Damage_Temp(db.Model, Base):
|
||||
temp.round_id = damage.round_id
|
||||
temp.player_id = damage.player_id
|
||||
temp.received_from_commander_player_id = damage.received_from_commander_player_id
|
||||
temp.health_change = damage.health_change
|
||||
temp.life_gain = damage.life_gain
|
||||
temp.life_loss = damage.life_loss
|
||||
temp.commander_deaths = damage.commander_deaths
|
||||
temp.is_eliminated = damage.is_eliminated
|
||||
temp.active = damage.active
|
||||
|
||||
287
business_objects/tcg/statistic.py
Normal file
287
business_objects/tcg/statistic.py
Normal file
@@ -0,0 +1,287 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: Business Objects
|
||||
Feature: Statistic Business Object
|
||||
"""
|
||||
|
||||
# internal
|
||||
from business_objects.base import Base
|
||||
from business_objects.db_base import SQLAlchemy_ABC, Get_Many_Parameters_Base
|
||||
import lib.argument_validation as av
|
||||
from extensions import db
|
||||
from helpers.helper_app import Helper_App
|
||||
# external
|
||||
from dataclasses import dataclass
|
||||
from typing import ClassVar
|
||||
from sqlalchemy import Uuid, Interval
|
||||
from sqlalchemy.types import Text, Boolean
|
||||
|
||||
|
||||
class Statistic(SQLAlchemy_ABC, Base):
|
||||
ATTR_ENTITY_RECORD_ID: ClassVar[str] = 'entity_record_id'
|
||||
ATTR_STATISTIC_ID: ClassVar[str] = 'statistic_id'
|
||||
FLAG_ENTITY_TYPE_CODE: ClassVar[str] = 'entity_type_code'
|
||||
FLAG_IS_BOOL: ClassVar[str] = 'is_bool'
|
||||
FLAG_IS_FLOAT: ClassVar[str] = 'is_float'
|
||||
FLAG_IS_INTERVAL: ClassVar[str] = 'is_interval'
|
||||
FLAG_IS_TEXT: ClassVar[str] = 'is_text'
|
||||
FLAG_IS_TIMESTAMP: ClassVar[str] = 'is_timestamp'
|
||||
FLAG_VALUE_BOOL: ClassVar[str] = 'value_bool'
|
||||
FLAG_VALUE_FLOAT: ClassVar[str] = 'value_float'
|
||||
FLAG_VALUE_INTERVAL: ClassVar[str] = 'value_interval'
|
||||
FLAG_VALUE_TEXT: ClassVar[str] = 'value_text'
|
||||
FLAG_VALUE_TIMESTAMP: ClassVar[str] = 'value_timestamp'
|
||||
NAME_ATTR_OPTION_VALUE: ClassVar[str] = ATTR_STATISTIC_ID
|
||||
NAME_ATTR_OPTION_TEXT: ClassVar[str] = Base.FLAG_NAME
|
||||
|
||||
__tablename__ = 'tcg_statistic'
|
||||
__table_args__ = { 'extend_existing': True }
|
||||
|
||||
statistic_id = db.Column(db.Integer, primary_key=True)
|
||||
entity_type_code = db.Column(db.Text) # replace with lookup table later
|
||||
entity_record_id = db.Column(db.Text)
|
||||
name = db.Column(db.Text)
|
||||
value_bool = db.Column(db.Boolean)
|
||||
value_float = db.Column(db.Float)
|
||||
value_interval = db.Column(Interval)
|
||||
value_text = db.Column(db.Text)
|
||||
value_timestamp = db.Column(db.DateTime)
|
||||
is_bool = db.Column(db.Boolean)
|
||||
is_float = db.Column(db.Boolean)
|
||||
is_interval = db.Column(db.Boolean)
|
||||
is_text = db.Column(db.Boolean)
|
||||
is_timestamp = db.Column(db.Boolean)
|
||||
display_order = db.Column(db.Integer)
|
||||
active = db.Column(db.Boolean)
|
||||
created_on = db.Column(db.DateTime)
|
||||
created_by_user_id = db.Column(db.Integer)
|
||||
updated_last_on = db.Column(db.DateTime)
|
||||
updated_last_by_user_id = db.Column(db.Integer)
|
||||
change_set_id = db.Column(db.Integer)
|
||||
|
||||
def __init__(self):
|
||||
self.statistic_id = 0
|
||||
self.is_new = False
|
||||
super().__init__()
|
||||
|
||||
@classmethod
|
||||
def from_db_statistic(cls, query_row):
|
||||
_m = f'{cls.__qualname__}.from_db_statistic'
|
||||
statistic = cls()
|
||||
statistic.statistic_id = query_row[0]
|
||||
statistic.entity_type_code = query_row[1]
|
||||
statistic.entity_record_id = query_row[2]
|
||||
statistic.name = query_row[3]
|
||||
statistic.value_bool = query_row[4]
|
||||
statistic.value_float = query_row[5]
|
||||
statistic.value_interval = query_row[6]
|
||||
statistic.value_text = query_row[7]
|
||||
statistic.value_timestamp = query_row[8]
|
||||
statistic.is_bool = query_row[9]
|
||||
statistic.is_float = query_row[10]
|
||||
statistic.is_interval = query_row[11]
|
||||
statistic.is_text = query_row[12]
|
||||
statistic.is_timestamp = query_row[13]
|
||||
statistic.display_order = query_row[14]
|
||||
statistic.active = av.input_bool(query_row[15], cls.FLAG_ACTIVE, _m)
|
||||
statistic.created_on = query_row[16]
|
||||
statistic.created_by_user_id = query_row[17]
|
||||
return statistic
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
_m = f'{cls.__qualname__}.from_json'
|
||||
statistic = cls()
|
||||
if json is None: return statistic
|
||||
statistic.statistic_id = json.get(cls.ATTR_STATISTIC_ID, -1)
|
||||
statistic.entity_type_code = json.get(cls.FLAG_ENTITY_TYPE_CODE, None)
|
||||
statistic.entity_record_id = json.get(cls.ATTR_ENTITY_RECORD_ID, None)
|
||||
statistic.name = json.get(cls.FLAG_NAME, '')
|
||||
statistic.value_bool = json.get(cls.FLAG_VALUE_BOOL, None)
|
||||
statistic.value_float = json.get(cls.FLAG_VALUE_FLOAT, None)
|
||||
statistic.value_interval = json.get(cls.FLAG_VALUE_INTERVAL, None)
|
||||
statistic.value_text = json.get(cls.FLAG_VALUE_TEXT, None)
|
||||
statistic.value_timestamp = json.get(cls.FLAG_VALUE_TIMESTAMP, None)
|
||||
statistic.is_bool = json.get(cls.FLAG_IS_BOOL, False)
|
||||
statistic.is_float = json.get(cls.FLAG_IS_FLOAT, False)
|
||||
statistic.is_interval = json.get(cls.FLAG_IS_INTERVAL, False)
|
||||
statistic.is_text = json.get(cls.FLAG_IS_TEXT, False)
|
||||
statistic.is_timestamp = json.get(cls.FLAG_IS_TIMESTAMP, False)
|
||||
statistic.display_order = json.get(cls.FLAG_DISPLAY_ORDER, -1)
|
||||
statistic.active = av.input_bool(json.get(cls.FLAG_ACTIVE, True), cls.FLAG_ACTIVE, _m)
|
||||
statistic.created_on = json.get(cls.FLAG_CREATED_ON, None)
|
||||
statistic.created_by_user_id = json.get(Base.ATTR_USER_ID, None)
|
||||
return statistic
|
||||
|
||||
def to_json(self):
|
||||
as_json = {
|
||||
**self.get_shared_json_attributes(self)
|
||||
, self.ATTR_STATISTIC_ID: self.statistic_id
|
||||
, self.FLAG_ENTITY_TYPE_CODE: self.entity_type_code
|
||||
, self.ATTR_ENTITY_RECORD_ID: self.entity_record_id
|
||||
, self.FLAG_NAME: self.name
|
||||
, self.FLAG_VALUE_BOOL: self.value_bool
|
||||
, self.FLAG_VALUE_FLOAT: self.value_float
|
||||
, self.FLAG_VALUE_INTERVAL: self.value_interval
|
||||
, self.FLAG_VALUE_TEXT: self.value_text
|
||||
, self.FLAG_VALUE_TIMESTAMP: self.value_timestamp
|
||||
, self.FLAG_IS_BOOL: self.is_bool
|
||||
, self.FLAG_IS_FLOAT: self.is_float
|
||||
, self.FLAG_IS_INTERVAL: self.is_interval
|
||||
, self.FLAG_IS_TEXT: self.is_text
|
||||
, self.FLAG_IS_TIMESTAMP: self.is_timestamp
|
||||
, self.FLAG_DISPLAY_ORDER: self.display_order
|
||||
, self.FLAG_ACTIVE: self.active
|
||||
, self.FLAG_CREATED_ON: self.created_on
|
||||
, Base.ATTR_USER_ID: self.created_by_user_id
|
||||
}
|
||||
return as_json
|
||||
|
||||
def __repr__(self):
|
||||
return f'''
|
||||
{self.__class__.__name__}(
|
||||
{self.ATTR_STATISTIC_ID}: {self.statistic_id}
|
||||
{self.FLAG_ENTITY_TYPE_CODE}: {self.entity_type_code}
|
||||
{self.ATTR_ENTITY_RECORD_ID}: {self.entity_record_id}
|
||||
{self.FLAG_NAME}: {self.name}
|
||||
{self.FLAG_VALUE_BOOL}: {self.value_bool}
|
||||
{self.FLAG_VALUE_FLOAT}: {self.value_float}
|
||||
{self.FLAG_VALUE_INTERVAL}: {self.value_interval}
|
||||
{self.FLAG_VALUE_TEXT}: {self.value_text}
|
||||
{self.FLAG_VALUE_TIMESTAMP}: {self.value_timestamp}
|
||||
{self.FLAG_IS_BOOL}: {self.is_bool}
|
||||
{self.FLAG_IS_FLOAT}: {self.is_float}
|
||||
{self.FLAG_IS_INTERVAL}: {self.is_interval}
|
||||
{self.FLAG_IS_TEXT}: {self.is_text}
|
||||
{self.FLAG_IS_TIMESTAMP}: {self.is_timestamp}
|
||||
{self.FLAG_DISPLAY_ORDER}: {self.display_order}
|
||||
{self.FLAG_ACTIVE}: {self.active}
|
||||
{self.FLAG_CREATED_ON}: {self.created_on}
|
||||
{Base.ATTR_USER_ID}: {self.created_by_user_id}
|
||||
)
|
||||
'''
|
||||
|
||||
def get_formatted_value(self):
|
||||
if self.is_bool:
|
||||
return self.value_bool
|
||||
elif self.is_float:
|
||||
return self.value_float
|
||||
elif self.is_interval:
|
||||
return self.value_interval
|
||||
elif self.is_text:
|
||||
return self.value_text
|
||||
elif self.is_timestamp:
|
||||
return self.value_timestamp
|
||||
else:
|
||||
return None
|
||||
|
||||
class Statistic_Temp(db.Model, Base):
|
||||
__tablename__ = 'tcg_statistic_temp'
|
||||
__table_args__ = { 'extend_existing': True }
|
||||
temp_id = db.Column(db.Integer, primary_key=True)
|
||||
statistic_id = db.Column(db.Integer)
|
||||
entity_type_code = db.Column(db.Text)
|
||||
entity_record_id = db.Column(db.Integer)
|
||||
name = db.Column(db.Integer)
|
||||
value_bool = db.Column(db.Boolean)
|
||||
value_float = db.Column(db.Float)
|
||||
value_interval = db.Column(Interval)
|
||||
value_text = db.Column(db.Text)
|
||||
value_timestamp = db.Column(db.DateTime)
|
||||
is_bool = db.Column(db.Boolean)
|
||||
is_float = db.Column(db.Boolean)
|
||||
is_interval = db.Column(db.Boolean)
|
||||
is_text = db.Column(db.Boolean)
|
||||
is_timestamp = db.Column(db.Boolean)
|
||||
display_order = db.Column(db.Integer)
|
||||
active = db.Column(db.Boolean)
|
||||
created_on = db.Column(db.DateTime)
|
||||
guid = db.Column(Uuid)
|
||||
|
||||
def __init__(self):
|
||||
self.entity_record_name = None
|
||||
super().__init__()
|
||||
|
||||
@classmethod
|
||||
def from_statistic(cls, statistic, guid):
|
||||
_m = 'Statistic_Temp.from_statistic'
|
||||
temp = cls()
|
||||
temp.statistic_id = statistic.statistic_id
|
||||
temp.entity_type_code = statistic.entity_type_code
|
||||
temp.entity_record_id = statistic.entity_record_id
|
||||
temp.name = statistic.name
|
||||
temp.value_bool = statistic.value_bool
|
||||
temp.value_float = statistic.value_float
|
||||
temp.value_interval = statistic.value_interval
|
||||
temp.value_text = statistic.value_text
|
||||
temp.value_timestamp = statistic.value_timestamp
|
||||
temp.is_bool = statistic.is_bool
|
||||
temp.is_float = statistic.is_float
|
||||
temp.is_interval = statistic.is_interval
|
||||
temp.is_text = statistic.is_text
|
||||
temp.is_timestamp = statistic.is_timestamp
|
||||
temp.display_order = statistic.display_order
|
||||
temp.active = statistic.active
|
||||
temp.created_on = statistic.created_on
|
||||
temp.guid = guid
|
||||
return temp
|
||||
|
||||
|
||||
class Parameters_Statistic(Get_Many_Parameters_Base):
|
||||
get_all_statistic: bool
|
||||
get_inactive_statistic: bool
|
||||
statistic_ids: str
|
||||
entity_type_codes: str
|
||||
entity_record_ids: str
|
||||
require_all_id_filters_met: bool
|
||||
require_any_id_filters_met: bool
|
||||
|
||||
@classmethod
|
||||
def get_default(cls):
|
||||
return cls(
|
||||
get_all_statistic = True
|
||||
, get_inactive_statistic = False
|
||||
, statistic_ids = ''
|
||||
, entity_type_codes = ''
|
||||
, entity_record_ids = ''
|
||||
, require_all_id_filters_met = True
|
||||
, require_any_id_filters_met = True
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, json):
|
||||
return cls(
|
||||
get_all_statistic = json.get('a_get_all_statistic', False)
|
||||
, get_inactive_statistic = json.get('a_get_inactive_statistic', False)
|
||||
, statistic_ids = json.get('a_statistic_ids', '')
|
||||
, entity_type_codes = json.get('a_entity_type_codes', '')
|
||||
, entity_record_ids = json.get('a_entity_record_ids', '')
|
||||
, require_all_id_filters_met = json.get('a_require_all_id_filters_met', True)
|
||||
, require_any_id_filters_met = json.get('a_require_any_id_filters_met', True)
|
||||
)
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
'a_get_all_statistic': self.get_all_statistic
|
||||
, 'a_get_inactive_statistic': self.get_inactive_statistic
|
||||
, 'a_statistic_ids': self.statistic_ids
|
||||
, 'a_entity_type_codes': self.entity_type_codes
|
||||
, 'a_entity_record_ids': self.entity_record_ids
|
||||
, 'a_require_all_id_filters_met': self.require_all_id_filters_met
|
||||
, 'a_require_any_id_filters_met': self.require_any_id_filters_met
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def get_type_hints():
|
||||
return {
|
||||
'a_get_all_statistic': Boolean
|
||||
, 'a_get_inactive_statistic': Boolean
|
||||
, 'a_statistic_ids': Text
|
||||
, 'a_entity_type_codes': Text
|
||||
, 'a_entity_record_ids': Text
|
||||
, 'a_require_all_id_filters_met': Boolean
|
||||
, 'a_require_any_id_filters_met': Boolean
|
||||
}
|
||||
@@ -13,6 +13,7 @@ MTG Game Page Controller.
|
||||
# IMPORTS
|
||||
# internal
|
||||
from business_objects.api import API
|
||||
from business_objects.tcg.mtg_deck import MTG_Deck
|
||||
from business_objects.tcg.mtg_game import MTG_Game
|
||||
from business_objects.tcg.mtg_game_player import MTG_Game_Player, Parameters_MTG_Game_Player
|
||||
from business_objects.tcg.mtg_game_round import MTG_Game_Round, Parameters_MTG_Game_Round
|
||||
@@ -21,9 +22,10 @@ from business_objects.tcg.mtg_deck import MTG_Deck, Parameters_MTG_Deck
|
||||
from business_objects.tcg.user import User, Parameters_User
|
||||
from datastores.datastore_mtg import DataStore_MTG
|
||||
from datastores.datastore_user import DataStore_User
|
||||
from forms.tcg.game import Filters_MTG_Game
|
||||
from forms.tcg.game import Filters_MTG_Game, Filters_MTG_Deck
|
||||
from helpers.helper_app import Helper_App
|
||||
from models.model_view_mtg_base import Model_View_MTG_Base
|
||||
from models.model_view_mtg_decks import Model_View_MTG_Decks
|
||||
from models.model_view_mtg_game import Model_View_MTG_Game
|
||||
from models.model_view_mtg_games import Model_View_MTG_Games
|
||||
from models.model_view_mtg_home import Model_View_MTG_Home
|
||||
@@ -373,3 +375,28 @@ def save_game_round_player_damage():
|
||||
Model_View_MTG_Base.FLAG_STATUS: Model_View_MTG_Base.FLAG_FAILURE
|
||||
, Model_View_MTG_Base.FLAG_MESSAGE: f'Bad data received by controller.\n{e}'
|
||||
})
|
||||
|
||||
|
||||
@routes_mtg_game.route(Model_View_MTG_Base.HASH_PAGE_MTG_DECKS, methods=['GET'])
|
||||
def decks():
|
||||
Helper_App.console_log('mtg decks')
|
||||
Helper_App.console_log(f'request_args: {request.args}')
|
||||
try:
|
||||
form_filters = Filters_MTG_Deck.from_json(request.args)
|
||||
except Exception as e:
|
||||
Helper_App.console_log(f'Error: {e}')
|
||||
form_filters = Filters_MTG_Deck()
|
||||
Helper_App.console_log(f'form_filters={form_filters}')
|
||||
|
||||
datastore = DataStore_MTG()
|
||||
user_session = datastore.get_user_session()
|
||||
if not user_session.get_is_logged_in():
|
||||
return redirect(url_for('routes_mtg_game.home'))
|
||||
|
||||
parameters_deck = form_filters.to_parameters()
|
||||
|
||||
model = Model_View_MTG_Decks(parameters_deck = parameters_deck)
|
||||
model.form_filters = form_filters
|
||||
Helper_App.console_log(f'form_filters={form_filters}')
|
||||
return render_template('pages/tcg/mtg/_decks.html', model=model)
|
||||
|
||||
|
||||
@@ -12,11 +12,13 @@ Datastore for MTG game data
|
||||
|
||||
# internal
|
||||
import lib.argument_validation as av
|
||||
from business_objects.tcg.mtg_deck import MTG_Deck, Parameters_MTG_Deck
|
||||
from business_objects.tcg.mtg_deck_commander_bracket import MTG_Deck_Commander_Bracket, Parameters_MTG_Deck_Commander_Bracket
|
||||
from business_objects.tcg.mtg_game import MTG_Game, Parameters_MTG_Game
|
||||
from business_objects.tcg.mtg_game_player import MTG_Game_Player, Parameters_MTG_Game_Player, MTG_Game_Player_Temp
|
||||
from business_objects.tcg.mtg_game_round import MTG_Game_Round, Parameters_MTG_Game_Round, MTG_Game_Round_Temp
|
||||
from business_objects.tcg.mtg_game_round_player_damage import MTG_Game_Round_Player_Damage, Parameters_MTG_Game_Round_Player_Damage, MTG_Game_Round_Player_Damage_Temp
|
||||
from business_objects.tcg.mtg_deck import MTG_Deck, Parameters_MTG_Deck
|
||||
from business_objects.tcg.statistic import Statistic, Statistic_Temp, Parameters_Statistic
|
||||
from business_objects.sql_error import SQL_Error, Parameters_SQL_Error
|
||||
from datastores.datastore_base import DataStore_Base
|
||||
from helpers.helper_app import Helper_App
|
||||
@@ -339,3 +341,55 @@ class DataStore_MTG(DataStore_Base):
|
||||
cls.clear_error(guid = guid)
|
||||
|
||||
return success, errors
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_many_mtg_deck_commander_bracket(cls, parameters_commander_bracket):
|
||||
_m = f'{cls.__qualname__}.get_many_mtg_deck_commander_bracket'
|
||||
argument_dict = parameters_commander_bracket.to_json()
|
||||
argument_types = Parameters_MTG_Deck.get_type_hints()
|
||||
Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}')
|
||||
|
||||
commander_brackets = []
|
||||
errors = []
|
||||
try:
|
||||
result = cls.db_function_execute('tcg.public.FN_TCG_MTG_Deck_Commander_Bracket_Get_Many', argument_dict, argument_types)
|
||||
result_set = result.fetchall()
|
||||
Helper_App.console_log(f'raw commander brackets: {result_set}')
|
||||
for row in result_set:
|
||||
new_commander_bracket = MTG_Deck_Commander_Bracket.from_db_mtg_deck_commander_bracket(row)
|
||||
commander_brackets.append(new_commander_bracket)
|
||||
Helper_App.console_log(f'commander bracket {str(type(new_commander_bracket))}: {new_commander_bracket}')
|
||||
except Exception as e:
|
||||
Helper_App.console_log(f'Error: {str(e)}')
|
||||
error = SQL_Error()
|
||||
error.msg = str(e)
|
||||
errors.append(error)
|
||||
|
||||
return commander_brackets, errors
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_many_statistic(cls, parameters_statistic):
|
||||
_m = f'{cls.__qualname__}.get_many_statistic'
|
||||
argument_dict = parameters_statistic.to_json()
|
||||
argument_types = Parameters_MTG_Deck.get_type_hints()
|
||||
Helper_App.console_log(f'{_m}\nargument_dict: {argument_dict}')
|
||||
|
||||
statistics = []
|
||||
errors = []
|
||||
try:
|
||||
result = cls.db_function_execute('tcg.public.FN_TCG_Statistic_Get_Many', argument_dict, argument_types)
|
||||
result_set = result.fetchall()
|
||||
Helper_App.console_log(f'raw commander brackets: {result_set}')
|
||||
for row in result_set:
|
||||
new_statistic = Statistic.from_db_statistic(row)
|
||||
statistics.append(new_statistic)
|
||||
Helper_App.console_log(f'statistic {str(type(new_statistic))}: {new_statistic}')
|
||||
except Exception as e:
|
||||
Helper_App.console_log(f'Error: {str(e)}')
|
||||
error = SQL_Error()
|
||||
error.msg = str(e)
|
||||
errors.append(error)
|
||||
|
||||
return statistics, errors
|
||||
|
||||
@@ -170,15 +170,15 @@ class Filters_MTG_Deck(Form_Base):
|
||||
, MTG_Deck.FLAG_IS_COMMANDER: self.is_commander.data
|
||||
}
|
||||
|
||||
def to_parameters(self, user_id_session):
|
||||
def to_parameters(self):
|
||||
return Parameters_MTG_Deck(
|
||||
get_all_deck = True
|
||||
, get_inactive_deck = not self.active_only.data
|
||||
, deck_ids = ''
|
||||
, deck_names = ''
|
||||
, deck_names = self.search.data
|
||||
, include_commander_option = True
|
||||
, commander_bracket_ids = ''
|
||||
, user_ids = str(user_id_session) if user_id_session else ''
|
||||
, require_all_id_filters_met = True
|
||||
, require_all_id_filters_met = False
|
||||
, require_any_id_filters_met = True
|
||||
, require_all_non_id_filters_met = False
|
||||
, require_any_non_id_filters_met = True
|
||||
|
||||
@@ -51,6 +51,7 @@ class Model_View_Base(BaseModel, ABC):
|
||||
COLOUR_TEXT_LINK_VISITED: ClassVar[str] = '#551A8B'
|
||||
COMPANY_ADDRESS_SHORT: ClassVar[str] = 'Russet, Sawbridge Road, Grandborough, United Kingdom, CV23 8DN'
|
||||
COMPANY_NUMBER: ClassVar[str] = '13587499'
|
||||
DECK_ENTITY_TYPE_CODE: ClassVar[str] = 'deck'
|
||||
ENDPOINT_GET_ALTCHA_CHALLENGE: ClassVar[str] = 'routes_core_contact.create_altcha_challenge'
|
||||
ENDPOINT_PAGE_ACCESSIBILITY_REPORT: ClassVar[str] = 'routes_legal.accessibility_report'
|
||||
ENDPOINT_PAGE_ACCESSIBILITY_STATEMENT: ClassVar[str] = 'routes_legal.accessibility_statement'
|
||||
@@ -162,6 +163,7 @@ class Model_View_Base(BaseModel, ABC):
|
||||
FLAG_TEMPORARY_ELEMENT: ClassVar[str] = 'temporary-element'
|
||||
FLAG_TESTIMONIAL: ClassVar[str] = 'testimonial'
|
||||
FLAG_USER: ClassVar[str] = User.FLAG_USER
|
||||
FLAG_VALUE: ClassVar[str] = Base.FLAG_VALUE
|
||||
# FLAG_VALUE_PROPOSITION: ClassVar[str] = 'value-proposition'
|
||||
FLAG_WEBSITE: ClassVar[str] = Base.FLAG_WEBSITE
|
||||
HASH_GET_ALTCHA_CHALLENGE: ClassVar[str] = '/altcha/create-challenge'
|
||||
@@ -222,6 +224,8 @@ class Model_View_Base(BaseModel, ABC):
|
||||
URL_REDDIT: ClassVar[str] = f'https://www.reddit.com/u/{USERNAME_REDDIT}/s/gZKEz2ZwHN'
|
||||
URL_TIKTOK: ClassVar[str] = f'https://www.tiktok.com/@{USERNAME_TIKTOK}'
|
||||
URL_TWITTER: ClassVar[str] = f'https://x.com/{USERNAME_TWITTER}'
|
||||
USER_ENTITY_TYPE_CODE: ClassVar[str] = 'user'
|
||||
USER_DECK_LINK_ENTITY_TYPE_CODE: ClassVar[str] = 'user_deck_link'
|
||||
|
||||
_title: str
|
||||
hash_page_current: str
|
||||
|
||||
@@ -12,11 +12,13 @@ Parent data model for MTG views
|
||||
|
||||
|
||||
# internal
|
||||
from business_objects.tcg.mtg_deck import MTG_Deck, Parameters_MTG_Deck
|
||||
from business_objects.tcg.mtg_deck_commander_bracket import MTG_Deck_Commander_Bracket
|
||||
from business_objects.tcg.mtg_game import MTG_Game, Parameters_MTG_Game
|
||||
from business_objects.tcg.mtg_game_player import MTG_Game_Player, Parameters_MTG_Game_Player
|
||||
from business_objects.tcg.mtg_game_round import MTG_Game_Round, Parameters_MTG_Game_Round
|
||||
from business_objects.tcg.mtg_game_round_player_damage import MTG_Game_Round_Player_Damage, Parameters_MTG_Game_Round_Player_Damage
|
||||
from business_objects.tcg.mtg_deck import MTG_Deck, Parameters_MTG_Deck
|
||||
from business_objects.tcg.statistic import Statistic
|
||||
from helpers.helper_app import Helper_App
|
||||
import lib.argument_validation as av
|
||||
from models.model_view_base import Model_View_Base
|
||||
@@ -29,31 +31,45 @@ from abc import abstractmethod
|
||||
|
||||
|
||||
class Model_View_MTG_Base(Model_View_Base):
|
||||
ATTR_COMMANDER_BRACKET_ID: ClassVar[str] = MTG_Deck_Commander_Bracket.ATTR_COMMANDER_BRACKET_ID
|
||||
ATTR_DAMAGE_ID: ClassVar[str] = MTG_Game_Round_Player_Damage.ATTR_DAMAGE_ID
|
||||
ATTR_DECK_ID: ClassVar[str] = MTG_Deck.ATTR_DECK_ID
|
||||
ATTR_ENTITY_RECORD_ID: ClassVar[str] = Statistic.ATTR_ENTITY_RECORD_ID
|
||||
ATTR_GAME_ID: ClassVar[str] = MTG_Game.ATTR_GAME_ID
|
||||
ATTR_PLAYER_ID: ClassVar[str] = MTG_Game_Player.ATTR_PLAYER_ID
|
||||
ATTR_ROUND_ID: ClassVar[str] = MTG_Game_Round.ATTR_ROUND_ID
|
||||
ATTR_DAMAGE_ID: ClassVar[str] = MTG_Game_Round_Player_Damage.ATTR_DAMAGE_ID
|
||||
ATTR_DECK_ID: ClassVar[str] = MTG_Deck.ATTR_DECK_ID
|
||||
FLAG_COMMANDER_DEATHS: ClassVar[str] = MTG_Game_Round_Player_Damage.FLAG_COMMANDER_DEATHS
|
||||
FLAG_DAMAGE: ClassVar[str] = MTG_Game_Round_Player_Damage.FLAG_DAMAGE
|
||||
FLAG_DECK: ClassVar[str] = MTG_Deck.FLAG_DECK
|
||||
FLAG_ENTITY_TYPE_CODE: ClassVar[str] = Statistic.FLAG_ENTITY_TYPE_CODE
|
||||
FLAG_GAME: ClassVar[str] = MTG_Game.FLAG_GAME
|
||||
FLAG_HEALTH_CHANGE: ClassVar[str] = MTG_Game_Round_Player_Damage.FLAG_HEALTH_CHANGE
|
||||
FLAG_IS_BOOL: ClassVar[str] = Statistic.FLAG_IS_BOOL
|
||||
FLAG_IS_FLOAT: ClassVar[str] = Statistic.FLAG_IS_FLOAT
|
||||
FLAG_IS_INTERVAL: ClassVar[str] = Statistic.FLAG_IS_INTERVAL
|
||||
FLAG_IS_TEXT: ClassVar[str] = Statistic.FLAG_IS_TEXT
|
||||
FLAG_IS_TIMESTAMP: ClassVar[str] = Statistic.FLAG_IS_TIMESTAMP
|
||||
FLAG_IS_COMMANDER: ClassVar[str] = MTG_Game.FLAG_IS_COMMANDER
|
||||
FLAG_IS_DRAFT: ClassVar[str] = MTG_Game.FLAG_IS_DRAFT
|
||||
FLAG_IS_SEALED: ClassVar[str] = MTG_Game.FLAG_IS_SEALED
|
||||
FLAG_LIFE_GAIN: ClassVar[str] = MTG_Game_Round_Player_Damage.FLAG_LIFE_GAIN
|
||||
FLAG_LIFE_LOSS: ClassVar[str] = MTG_Game_Round_Player_Damage.FLAG_LIFE_LOSS
|
||||
FLAG_LOCATION_NAME: ClassVar[str] = MTG_Game.FLAG_LOCATION_NAME
|
||||
FLAG_PLAYER: ClassVar[str] = MTG_Game_Player.FLAG_PLAYER
|
||||
FLAG_ROUND: ClassVar[str] = MTG_Game_Round.FLAG_ROUND
|
||||
FLAG_STARTING_LIFE: ClassVar[str] = MTG_Game.FLAG_STARTING_LIFE
|
||||
FLAG_VALUE_BOOL: ClassVar[str] = Statistic.FLAG_VALUE_BOOL
|
||||
FLAG_VALUE_FLOAT: ClassVar[str] = Statistic.FLAG_VALUE_FLOAT
|
||||
FLAG_VALUE_INTERVAL: ClassVar[str] = Statistic.FLAG_VALUE_INTERVAL
|
||||
FLAG_VALUE_TEXT: ClassVar[str] = Statistic.FLAG_VALUE_TEXT
|
||||
FLAG_VALUE_TIMESTAMP: ClassVar[str] = Statistic.FLAG_VALUE_TIMESTAMP
|
||||
HASH_GET_MTG_GAME_DAMAGE_RECORDS: ClassVar[str] = '/mtg/api/game/<game_id>/damage-records'
|
||||
HASH_GET_MTG_GAME_PLAYERS: ClassVar[str] = '/mtg/api/game/<game_id>/players'
|
||||
HASH_GET_MTG_GAME_ROUNDS: ClassVar[str] = '/mtg/api/game/<game_id>/rounds'
|
||||
HASH_GET_MTG_GAME_DAMAGE_RECORDS: ClassVar[str] = '/mtg/api/game/<game_id>/damage-records'
|
||||
HASH_SAVE_MTG_DECK: ClassVar[str] = '/mtg/save-deck'
|
||||
HASH_SAVE_MTG_GAME: ClassVar[str] = '/mtg/save-game'
|
||||
HASH_SAVE_MTG_GAME_PLAYER: ClassVar[str] = '/mtg/save-game-player'
|
||||
HASH_SAVE_MTG_GAME_ROUND: ClassVar[str] = '/mtg/save-game-round'
|
||||
HASH_SAVE_MTG_GAME_ROUND_PLAYER_DAMAGE: ClassVar[str] = '/mtg/save-game-round-player-damage'
|
||||
HASH_SAVE_MTG_DECK: ClassVar[str] = '/mtg/save-deck'
|
||||
|
||||
is_page_mtg: bool = True
|
||||
|
||||
|
||||
85
models/model_view_mtg_decks.py
Normal file
85
models/model_view_mtg_decks.py
Normal file
@@ -0,0 +1,85 @@
|
||||
"""
|
||||
Project: PARTS Website
|
||||
Author: Edward Middleton-Smith
|
||||
Precision And Research Technology Systems Limited
|
||||
|
||||
Technology: View Models
|
||||
Feature: MTG Decks View Model
|
||||
|
||||
Description:
|
||||
Data model for MTG decks view
|
||||
"""
|
||||
|
||||
# internal
|
||||
from business_objects.tcg.mtg_deck_commander_bracket import MTG_Deck_Commander_Bracket, Parameters_MTG_Deck_Commander_Bracket
|
||||
from business_objects.tcg.mtg_deck import MTG_Deck, Parameters_MTG_Deck
|
||||
from business_objects.tcg.statistic import Statistic, Parameters_Statistic
|
||||
from datastores.datastore_mtg import DataStore_MTG
|
||||
from models.model_view_mtg_base import Model_View_MTG_Base
|
||||
from helpers.helper_app import Helper_App
|
||||
import lib.argument_validation as av
|
||||
|
||||
# external
|
||||
from pydantic import BaseModel
|
||||
from typing import ClassVar
|
||||
|
||||
|
||||
class Model_View_MTG_Decks(Model_View_MTG_Base):
|
||||
FLAG_STATISTICS: ClassVar[str] = 'statistics'
|
||||
commander_brackets: list = None
|
||||
decks: list = None
|
||||
form_filters: object = None
|
||||
parameters_deck: Parameters_MTG_Deck = None
|
||||
statistics: list = None
|
||||
|
||||
def __init__(self, parameters_deck=None, hash_page_current=Model_View_MTG_Base.HASH_PAGE_MTG_DECKS):
|
||||
_m = 'Model_View_MTG_Decks.__init__'
|
||||
Helper_App.console_log(f'{_m}\nstarting...')
|
||||
super().__init__(hash_page_current=hash_page_current)
|
||||
self._title = 'MTG Decks'
|
||||
datastore = DataStore_MTG()
|
||||
|
||||
# Get all decks
|
||||
parameters_deck = Parameters_MTG_Deck.get_default()
|
||||
parameters_deck.get_all_deck = True
|
||||
parameters_deck.require_all_id_filters_met = False
|
||||
parameters_deck.require_any_id_filters_met = False
|
||||
parameters_deck.require_all_non_id_filters_met = False
|
||||
parameters_deck.require_any_non_id_filters_met = False
|
||||
self.decks, errors = datastore.get_many_mtg_deck(parameters_deck)
|
||||
|
||||
Helper_App.console_log(f'Decks IDs: {self.decks}')
|
||||
# Get all commander brackets
|
||||
parameters_commander_bracket = Parameters_MTG_Deck_Commander_Bracket.get_default()
|
||||
parameters_commander_bracket.get_all_commander_bracket = True
|
||||
parameters_commander_bracket.require_all_id_filters_met = False
|
||||
parameters_commander_bracket.require_any_id_filters_met = False
|
||||
self.commander_brackets, errors = datastore.get_many_mtg_deck_commander_bracket(parameters_commander_bracket = parameters_commander_bracket)
|
||||
|
||||
Helper_App.console_log(f'Brackets: {self.commander_brackets}')
|
||||
commander_bracket_index = {}
|
||||
for index_commander_bracket in range(len(self.commander_brackets)):
|
||||
bracket = self.commander_brackets[index_commander_bracket]
|
||||
commander_bracket_index[bracket.commander_bracket_id] = bracket
|
||||
Helper_App.console_log(f'Bracket IDs: {commander_bracket_index}')
|
||||
|
||||
deck_index = {}
|
||||
for index_deck in range(len(self.decks)):
|
||||
bracket = commander_bracket_index[self.decks[index_deck].commander_bracket_id]
|
||||
self.decks[index_deck].commander_bracket = bracket
|
||||
deck_index[self.decks[index_deck].deck_id] = self.decks[index_deck]
|
||||
|
||||
# Get all statistics
|
||||
parameters_statistic = Parameters_Statistic.get_default()
|
||||
parameters_statistic.get_all_statistic = False
|
||||
parameters_statistic.entity_type_codes = Model_View_MTG_Decks.DECK_ENTITY_TYPE_CODE
|
||||
parameters_statistic.entity_record_ids = ','.join([str(d.deck_id) for d in self.decks])
|
||||
parameters_statistic.require_all_id_filters_met = True
|
||||
parameters_statistic.require_any_id_filters_met = True
|
||||
self.statistics, errors = datastore.get_many_statistic(parameters_statistic = parameters_statistic)
|
||||
|
||||
for index_statistic in range(len(self.statistics)):
|
||||
deck = deck_index[int(self.statistics[index_statistic].entity_record_id)]
|
||||
self.statistics[index_statistic].entity_record_name = deck.name
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ CREATE TABLE tcg.public.TCG_MTG_Game (
|
||||
, location_name TEXT
|
||||
, start_on TIMESTAMP
|
||||
, end_on TIMESTAMP
|
||||
, starting_life INT
|
||||
, starting_life INT NOT NULL
|
||||
, active BOOLEAN NOT NULL DEFAULT TRUE
|
||||
, created_on TIMESTAMP NOT NULL
|
||||
, created_by_user_id INT NOT NULL
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
CREATE TABLE tcg.public.TCG_MTG_Game_Round_Player_Damage (
|
||||
damage_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY
|
||||
, round_id INT NOT NULL
|
||||
@@ -12,7 +13,8 @@ CREATE TABLE tcg.public.TCG_MTG_Game_Round_Player_Damage (
|
||||
, CONSTRAINT FK_TCG_MTG_Game_Round_Player_Damage_received_from_commander_player_id
|
||||
FOREIGN KEY (received_from_commander_player_id)
|
||||
REFERENCES tcg.public.TCG_MTG_Game_Player(player_id)
|
||||
, health_change INT NOT NULL
|
||||
, life_gain INT NOT NULL
|
||||
, life_loss INT NOT NULL
|
||||
, commander_deaths INT NOT NULL
|
||||
, is_eliminated BOOLEAN NOT NULL DEFAULT FALSE
|
||||
, active BOOLEAN NOT NULL DEFAULT TRUE
|
||||
|
||||
@@ -6,8 +6,10 @@ CREATE TABLE tcg.public.TCG_MTG_Game_Round_Player_Damage_Temp (
|
||||
, round_id INT
|
||||
, player_id INT
|
||||
, received_from_commander_player_id INT
|
||||
, health_change INT
|
||||
, life_gain INT
|
||||
, life_loss INT
|
||||
, commander_deaths INT
|
||||
, is_eliminated BOOLEAN
|
||||
, active BOOLEAN
|
||||
, created_on TIMESTAMP
|
||||
, created_by_user_id INT
|
||||
|
||||
32
static/PostgreSQL/11300_tbl_TCG_Statistic.sql
Normal file
32
static/PostgreSQL/11300_tbl_TCG_Statistic.sql
Normal file
@@ -0,0 +1,32 @@
|
||||
CREATE TABLE tcg.public.TCG_Statistic (
|
||||
statistic_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY
|
||||
, entity_type_code TEXT NOT NULL
|
||||
, entity_record_id TEXT NOT NULL
|
||||
, name TEXT NOT NULL
|
||||
, value_bool BOOLEAN
|
||||
, value_float DOUBLE PRECISION
|
||||
, value_interval INTERVAL
|
||||
, value_text TEXT
|
||||
, value_timestamp TIMESTAMP
|
||||
, is_bool BOOLEAN
|
||||
, is_float BOOLEAN
|
||||
, is_interval BOOLEAN
|
||||
, is_text BOOLEAN
|
||||
, is_timestamp BOOLEAN
|
||||
, display_order INT NOT NULL
|
||||
, active BOOLEAN NOT NULL DEFAULT TRUE
|
||||
, created_on TIMESTAMP NOT NULL
|
||||
, created_by_user_id INT NOT NULL
|
||||
, CONSTRAINT FK_TCG_Statistic_created_by_user_id
|
||||
FOREIGN KEY (created_by_user_id)
|
||||
REFERENCES tcg.public.TCG_User(user_id)
|
||||
, updated_last_on TIMESTAMP NOT NULL
|
||||
, updated_last_by_user_id INT NOT NULL
|
||||
, CONSTRAINT FK_TCG_Statistic_updated_last_by_user_id
|
||||
FOREIGN KEY (updated_last_by_user_id)
|
||||
REFERENCES tcg.public.TCG_User(user_id)
|
||||
, change_set_id INT NOT NULL
|
||||
, CONSTRAINT FK_TCG_Statistic_change_set_id
|
||||
FOREIGN KEY (change_set_id)
|
||||
REFERENCES tcg.public.TCG_Change_Set(change_set_id)
|
||||
);
|
||||
15
static/PostgreSQL/11301_tbl_TCG_Statistic_Audit.sql
Normal file
15
static/PostgreSQL/11301_tbl_TCG_Statistic_Audit.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
CREATE TABLE tcg.public.TCG_Statistic_Audit (
|
||||
audit_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY
|
||||
, statistic_id INT NOT NULL
|
||||
, CONSTRAINT FK_TCG_Statistic_Audit_statistic_id
|
||||
FOREIGN KEY (statistic_id)
|
||||
REFERENCES tcg.public.TCG_Statistic(statistic_id)
|
||||
, name_field TEXT NOT NULL
|
||||
, value_prev TEXT
|
||||
, value_new TEXT
|
||||
, change_set_id INT NOT NULL
|
||||
, CONSTRAINT FK_TCG_Statistic_Audit_change_set_id
|
||||
FOREIGN KEY (change_set_id)
|
||||
REFERENCES tcg.public.TCG_Change_Set(change_set_id)
|
||||
);
|
||||
@@ -58,9 +58,13 @@ BEGIN
|
||||
SELECT NEW.damage_id, 'received_from_commander_player_id', OLD.received_from_commander_player_id::TEXT, NEW.received_from_commander_player_id::TEXT, NEW.change_set_id
|
||||
WHERE OLD.received_from_commander_player_id IS NOT DISTINCT FROM NEW.received_from_commander_player_id
|
||||
UNION
|
||||
-- Changed health_change
|
||||
SELECT NEW.damage_id, 'health_change', OLD.health_change::TEXT, NEW.health_change::TEXT, NEW.change_set_id
|
||||
WHERE OLD.health_change IS NOT DISTINCT FROM NEW.health_change
|
||||
-- Changed life_gain
|
||||
SELECT NEW.damage_id, 'life_gain', OLD.life_gain::TEXT, NEW.life_gain::TEXT, NEW.change_set_id
|
||||
WHERE OLD.life_gain IS NOT DISTINCT FROM NEW.life_gain
|
||||
UNION
|
||||
-- Changed life_loss
|
||||
SELECT NEW.damage_id, 'life_loss', OLD.life_loss::TEXT, NEW.life_loss::TEXT, NEW.change_set_id
|
||||
WHERE OLD.life_loss IS NOT DISTINCT FROM NEW.life_loss
|
||||
UNION
|
||||
-- Changed commander_deaths
|
||||
SELECT NEW.damage_id, 'commander_deaths', OLD.commander_deaths::TEXT, NEW.commander_deaths::TEXT, NEW.change_set_id
|
||||
|
||||
96
static/PostgreSQL/31300_tri_TCG_Statistic.sql
Normal file
96
static/PostgreSQL/31300_tri_TCG_Statistic.sql
Normal file
@@ -0,0 +1,96 @@
|
||||
|
||||
CREATE OR REPLACE FUNCTION tcg.public.FN_before_insert_TCG_Statistic()
|
||||
RETURNS TRIGGER AS $$
|
||||
DECLARE
|
||||
r_change_set RECORD;
|
||||
BEGIN
|
||||
NEW.created_on = COALESCE(NEW.created_on, CURRENT_TIMESTAMP);
|
||||
NEW.updated_last_on = COALESCE(NEW.updated_last_on, CURRENT_TIMESTAMP);
|
||||
|
||||
IF NEW.change_set_id IS NULL THEN
|
||||
RAISE EXCEPTION 'Change Set ID must be provided.';
|
||||
END IF;
|
||||
|
||||
SELECT *
|
||||
INTO r_change_set
|
||||
FROM tcg.public.TCG_Change_Set CHANGE_SET
|
||||
WHERE NEW.change_set_id = CHANGE_SET.change_set_id
|
||||
;
|
||||
|
||||
IF FOUND THEN
|
||||
NEW.created_by_user_id := COALESCE(NEW.created_by_user_id, r_change_set.updated_last_by_user_id);
|
||||
NEW.updated_last_by_user_id := COALESCE(NEW.updated_last_by_user_id, r_change_set.updated_last_by_user_id);
|
||||
NEW.created_on := COALESCE(NEW.created_on, r_change_set.updated_last_on);
|
||||
ELSE
|
||||
RAISE EXCEPTION 'Change Set % not found.', NEW.change_set_id;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql
|
||||
;
|
||||
|
||||
CREATE OR REPLACE FUNCTION tcg.public.FN_before_update_TCG_Statistic()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_last_on = CURRENT_TIMESTAMP;
|
||||
|
||||
IF OLD.change_set_id IS NOT DISTINCT FROM NEW.change_set_id THEN
|
||||
RAISE EXCEPTION 'New Change Set ID must be provided.';
|
||||
END IF;
|
||||
|
||||
INSERT INTO tcg.public.TCG_Statistic_Audit (
|
||||
statistic_id
|
||||
, name_field
|
||||
, value_prev
|
||||
, value_new
|
||||
, change_set_id
|
||||
)
|
||||
-- Changed entity_type_code
|
||||
SELECT NEW.statistic_id, 'entity_type_code', OLD.entity_type_code, NEW.entity_type_code, NEW.change_set_id
|
||||
WHERE OLD.entity_type_code IS NOT DISTINCT FROM NEW.entity_type_code
|
||||
UNION
|
||||
-- Changed entity_record_id
|
||||
SELECT NEW.statistic_id, 'entity_record_id', OLD.entity_record_id::TEXT, NEW.entity_record_id::TEXT, NEW.change_set_id
|
||||
WHERE OLD.entity_record_id IS NOT DISTINCT FROM NEW.entity_record_id
|
||||
UNION
|
||||
-- Changed name
|
||||
SELECT NEW.statistic_id, 'name', OLD.name, NEW.name, NEW.change_set_id
|
||||
WHERE OLD.name IS NOT DISTINCT FROM NEW.name
|
||||
UNION
|
||||
-- Changed value_bool
|
||||
SELECT NEW.statistic_id, 'value_bool', OLD.value_bool::TEXT, NEW.value_bool::TEXT, NEW.change_set_id
|
||||
WHERE OLD.value_bool IS NOT DISTINCT FROM NEW.value_bool
|
||||
UNION
|
||||
-- Changed value_float
|
||||
SELECT NEW.statistic_id, 'value_float', OLD.value_float::TEXT, NEW.value_float::TEXT, NEW.change_set_id
|
||||
WHERE OLD.value_float IS NOT DISTINCT FROM NEW.value_float
|
||||
UNION
|
||||
-- Changed value_text
|
||||
SELECT NEW.statistic_id, 'value_text', OLD.value_text, NEW.value_text, NEW.change_set_id
|
||||
WHERE OLD.value_text IS NOT DISTINCT FROM NEW.value_text
|
||||
UNION
|
||||
-- Changed value_timestamp
|
||||
SELECT NEW.statistic_id, 'value_timestamp', OLD.value_timestamp::TEXT, NEW.value_timestamp::TEXT, NEW.change_set_id
|
||||
WHERE OLD.value_timestamp IS NOT DISTINCT FROM NEW.value_timestamp
|
||||
UNION
|
||||
-- Changed active
|
||||
SELECT NEW.statistic_id, 'active', OLD.active::TEXT, NEW.active::TEXT, NEW.change_set_id
|
||||
WHERE OLD.active IS NOT DISTINCT FROM NEW.active
|
||||
;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql
|
||||
;
|
||||
|
||||
CREATE TRIGGER TRI_before_insert_TCG_Statistic
|
||||
BEFORE INSERT ON tcg.public.TCG_Statistic
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION tcg.public.FN_before_insert_TCG_Statistic()
|
||||
;
|
||||
CREATE TRIGGER TRI_before_update_TCG_Statistic
|
||||
BEFORE UPDATE ON tcg.public.TCG_Statistic
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION tcg.public.FN_before_update_TCG_Statistic()
|
||||
;
|
||||
@@ -35,7 +35,7 @@ BEGIN
|
||||
DROP TABLE IF EXISTS Temp_User_Save_User;
|
||||
DROP TABLE IF EXISTS Temp_User_Save_Error;
|
||||
|
||||
CREATE TABLE Temp_User_Save_User (
|
||||
CREATE TEMP TABLE Temp_User_Save_User (
|
||||
user_id INT NOT NULL
|
||||
, user_auth0_id TEXT
|
||||
, firstname TEXT
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
|
||||
CREATE OR REPLACE FUNCTION tcg.public.FN_TCG_MTG_Deck_Commander_Bracket_Get_Many (
|
||||
a_get_all_commander_bracket BOOLEAN
|
||||
, a_get_inactive_commander_bracket BOOLEAN
|
||||
, a_commander_bracket_ids TEXT
|
||||
, a_commander_bracket_names TEXT
|
||||
, a_require_all_id_filters_met BOOLEAN
|
||||
, a_require_any_id_filters_met BOOLEAN
|
||||
, a_require_all_non_id_filters_met BOOLEAN
|
||||
, a_require_any_non_id_filters_met BOOLEAN
|
||||
)
|
||||
RETURNS TABLE (
|
||||
commander_bracket_id INT
|
||||
, name TEXT
|
||||
, description TEXT
|
||||
, display_order INT
|
||||
, active BOOLEAN
|
||||
, created_on TIMESTAMP
|
||||
, created_by_user_id INT
|
||||
, updated_last_on TIMESTAMP
|
||||
, updated_last_by_user_id INT
|
||||
, change_set_id INT
|
||||
)
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
v_get_all_commander_bracket BOOLEAN;
|
||||
v_get_inactive_commander_bracket BOOLEAN;
|
||||
v_commander_bracket_ids TEXT;
|
||||
v_commander_bracket_names TEXT;
|
||||
v_require_all_id_filters_met BOOLEAN;
|
||||
v_require_any_id_filters_met BOOLEAN;
|
||||
v_require_all_non_id_filters_met BOOLEAN;
|
||||
v_require_any_non_id_filters_met BOOLEAN;
|
||||
BEGIN
|
||||
v_get_all_commander_bracket := COALESCE(a_get_all_commander_bracket, TRUE);
|
||||
v_get_inactive_commander_bracket := COALESCE(a_get_inactive_commander_bracket, FALSE);
|
||||
v_commander_bracket_ids := TRIM(COALESCE(a_commander_bracket_ids, ''));
|
||||
v_commander_bracket_names := TRIM(COALESCE(a_commander_bracket_names, ''));
|
||||
v_require_all_id_filters_met := COALESCE(a_require_all_id_filters_met, FALSE);
|
||||
v_require_any_id_filters_met := COALESCE(a_require_any_id_filters_met, TRUE);
|
||||
v_require_all_non_id_filters_met := COALESCE(a_require_all_non_id_filters_met, FALSE);
|
||||
v_require_any_non_id_filters_met := COALESCE(a_require_any_non_id_filters_met, TRUE);
|
||||
|
||||
-- Outputs
|
||||
RETURN QUERY SELECT
|
||||
COMMANDER_BRACKET.commander_bracket_id
|
||||
, COMMANDER_BRACKET.name
|
||||
, COMMANDER_BRACKET.description
|
||||
, COMMANDER_BRACKET.display_order
|
||||
, COMMANDER_BRACKET.active
|
||||
, COMMANDER_BRACKET.created_on
|
||||
, COMMANDER_BRACKET.created_by_user_id
|
||||
, COMMANDER_BRACKET.updated_last_on
|
||||
, COMMANDER_BRACKET.updated_last_by_user_id
|
||||
, COMMANDER_BRACKET.change_set_id
|
||||
FROM tcg.public.TCG_MTG_Deck_Commander_Bracket COMMANDER_BRACKET
|
||||
WHERE
|
||||
(
|
||||
(
|
||||
NOT v_require_all_id_filters_met
|
||||
AND NOT v_require_any_id_filters_met
|
||||
)
|
||||
OR (
|
||||
v_require_all_id_filters_met
|
||||
AND (
|
||||
v_get_all_commander_bracket
|
||||
OR COMMANDER_BRACKET.commander_bracket_id = ANY(string_to_array(v_commander_bracket_ids, ',')::INT[])
|
||||
)
|
||||
)
|
||||
OR (
|
||||
NOT v_require_all_id_filters_met
|
||||
AND v_require_any_id_filters_met
|
||||
AND (
|
||||
v_get_all_commander_bracket
|
||||
OR COMMANDER_BRACKET.commander_bracket_id = ANY(string_to_array(v_commander_bracket_ids, ',')::INT[])
|
||||
)
|
||||
)
|
||||
)
|
||||
AND (
|
||||
(
|
||||
NOT v_require_all_non_id_filters_met
|
||||
AND NOT v_require_any_non_id_filters_met
|
||||
)
|
||||
OR (
|
||||
v_require_all_non_id_filters_met
|
||||
AND (
|
||||
v_get_all_commander_bracket
|
||||
OR COMMANDER_BRACKET.name LIKE ANY (SELECT '%' || TRIM(s) || '%' FROM unnest(string_to_array(v_commander_bracket_names, ',')) s)
|
||||
)
|
||||
)
|
||||
OR (
|
||||
NOT v_require_all_non_id_filters_met
|
||||
AND v_require_any_non_id_filters_met
|
||||
AND (
|
||||
v_get_all_commander_bracket
|
||||
OR COMMANDER_BRACKET.name LIKE ANY (SELECT '%' || TRIM(s) || '%' FROM unnest(string_to_array(v_commander_bracket_names, ',')) s)
|
||||
)
|
||||
)
|
||||
)
|
||||
AND (
|
||||
v_get_inactive_commander_bracket
|
||||
OR COMMANDER_BRACKET.active
|
||||
)
|
||||
ORDER BY COMMANDER_BRACKET.display_order
|
||||
;
|
||||
END;
|
||||
$$;
|
||||
|
||||
|
||||
SELECT *
|
||||
FROM tcg.public.FN_TCG_MTG_Deck_Commander_Bracket_Get_Many (
|
||||
a_get_all_commander_bracket := TRUE
|
||||
, a_get_inactive_commander_bracket := FALSE
|
||||
, a_commander_bracket_ids := CAST(NULL AS TEXT)
|
||||
, a_commander_bracket_names := CAST(NULL AS TEXT)
|
||||
, a_require_all_id_filters_met := FALSE
|
||||
, a_require_any_id_filters_met := FALSE
|
||||
, a_require_all_non_id_filters_met := FALSE
|
||||
, a_require_any_non_id_filters_met := FALSE
|
||||
)
|
||||
;
|
||||
|
||||
SELECT *
|
||||
FROM tcg.public.TCG_MTG_Deck_Commander_Bracket
|
||||
;
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ RETURNS TABLE (
|
||||
, round_id INT
|
||||
, player_id INT
|
||||
, received_from_commander_player_id INT
|
||||
, health_change INT
|
||||
, life_gain INT
|
||||
, life_loss INT
|
||||
, commander_deaths INT
|
||||
, is_eliminated BOOLEAN
|
||||
, active BOOLEAN
|
||||
@@ -42,7 +43,8 @@ BEGIN
|
||||
, PLAYER_DAMAGE.round_id
|
||||
, PLAYER_DAMAGE.player_id
|
||||
, PLAYER_DAMAGE.received_from_commander_player_id
|
||||
, PLAYER_DAMAGE.health_change
|
||||
, PLAYER_DAMAGE.life_gain
|
||||
, PLAYER_DAMAGE.life_loss
|
||||
, PLAYER_DAMAGE.commander_deaths
|
||||
, PLAYER_DAMAGE.is_eliminated
|
||||
, PLAYER_DAMAGE.active
|
||||
@@ -95,7 +97,7 @@ SELECT *
|
||||
FROM tcg.public.FN_TCG_MTG_Game_Round_Player_Damage_Get_Many (
|
||||
a_get_all_game := FALSE
|
||||
, a_get_inactive_game := FALSE
|
||||
, a_game_ids := '11'
|
||||
, a_game_ids := '30'
|
||||
, a_require_all_id_filters_met := TRUE
|
||||
, a_require_any_id_filters_met := FALSE
|
||||
)
|
||||
|
||||
@@ -84,7 +84,8 @@ BEGIN
|
||||
, round_id INT
|
||||
, player_id INT
|
||||
, received_from_commander_player_id INT
|
||||
, health_change INT
|
||||
, life_gain INT
|
||||
, life_loss INT
|
||||
, commander_deaths INT
|
||||
, is_eliminated BOOLEAN
|
||||
, active BOOLEAN
|
||||
@@ -177,7 +178,8 @@ BEGIN
|
||||
, round_id
|
||||
, player_id
|
||||
, received_from_commander_player_id
|
||||
, health_change
|
||||
, life_gain
|
||||
, life_loss
|
||||
, commander_deaths
|
||||
, is_eliminated
|
||||
, active
|
||||
@@ -199,7 +201,8 @@ BEGIN
|
||||
, PLAYER_DAMAGE_T.round_id
|
||||
, PLAYER_DAMAGE_T.player_id
|
||||
, PLAYER_DAMAGE_T.received_from_commander_player_id
|
||||
, COALESCE(PLAYER_DAMAGE_T.health_change, 0) -- health_change
|
||||
, ABS(COALESCE(PLAYER_DAMAGE_T.life_gain, 0)) -- life_gain
|
||||
, ABS(COALESCE(PLAYER_DAMAGE_T.life_loss, 0)) -- life_loss
|
||||
, COALESCE(PLAYER_DAMAGE_T.commander_deaths, 0) -- commander_deaths
|
||||
, COALESCE(PLAYER_DAMAGE_T.is_eliminated, FALSE) -- is_eliminated
|
||||
, COALESCE(PLAYER_DAMAGE_T.active, TRUE) -- active
|
||||
@@ -220,8 +223,10 @@ BEGIN
|
||||
, CAST(PLAYER_DAMAGE_T.player_id AS VARCHAR)
|
||||
, ', received from commander player id: '
|
||||
, CAST(PLAYER_DAMAGE_T.received_from_commander_player_id AS VARCHAR)
|
||||
, ', health change: '
|
||||
, CAST(PLAYER_DAMAGE_T.health_change AS VARCHAR)
|
||||
, ', life gain: '
|
||||
, CAST(PLAYER_DAMAGE_T.life_gain AS VARCHAR)
|
||||
, ', life loss: '
|
||||
, CAST(PLAYER_DAMAGE_T.life_loss AS VARCHAR)
|
||||
, ' }'
|
||||
) -- error_name
|
||||
FROM tcg.public.TCG_MTG_Game_Round_Player_Damage_Temp PLAYER_DAMAGE_T
|
||||
@@ -625,6 +630,7 @@ BEGIN
|
||||
, 'player_id' AS field
|
||||
FROM Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE
|
||||
WHERE T_PLAYER_DAMAGE.player_id IS NULL
|
||||
/*
|
||||
UNION
|
||||
SELECT
|
||||
T_PLAYER_DAMAGE.temp_id
|
||||
@@ -632,11 +638,24 @@ BEGIN
|
||||
FROM Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE
|
||||
WHERE T_PLAYER_DAMAGE.health_change IS NULL
|
||||
UNION
|
||||
SELECT
|
||||
T_PLAYER_DAMAGE.temp_id
|
||||
, 'life_gain' AS field
|
||||
FROM Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE
|
||||
WHERE T_PLAYER_DAMAGE.life_gain IS NULL
|
||||
UNION
|
||||
SELECT
|
||||
T_PLAYER_DAMAGE.temp_id
|
||||
, 'life_loss' AS field
|
||||
FROM Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE
|
||||
WHERE T_PLAYER_DAMAGE.life_loss IS NULL
|
||||
UNION
|
||||
SELECT
|
||||
T_PLAYER_DAMAGE.temp_id
|
||||
, 'commander_deaths' AS field
|
||||
FROM Temp_MTG_Round_Damage_Save_Round_Player_Damage T_PLAYER_DAMAGE
|
||||
WHERE T_PLAYER_DAMAGE.commander_deaths IS NULL
|
||||
*/
|
||||
)
|
||||
INSERT INTO Temp_MTG_Round_Damage_Save_Error (
|
||||
error_type_id
|
||||
@@ -910,7 +929,8 @@ BEGIN
|
||||
round_id
|
||||
, player_id
|
||||
, received_from_commander_player_id
|
||||
, health_change
|
||||
, life_gain
|
||||
, life_loss
|
||||
, commander_deaths
|
||||
, is_eliminated
|
||||
, active
|
||||
@@ -924,7 +944,8 @@ BEGIN
|
||||
T_ROUND.round_id
|
||||
, T_PLAYER_DAMAGE.player_id
|
||||
, T_PLAYER_DAMAGE.received_from_commander_player_id
|
||||
, T_PLAYER_DAMAGE.health_change
|
||||
, T_PLAYER_DAMAGE.life_gain
|
||||
, T_PLAYER_DAMAGE.life_loss
|
||||
, T_PLAYER_DAMAGE.commander_deaths
|
||||
, T_PLAYER_DAMAGE.is_eliminated
|
||||
, T_PLAYER_DAMAGE.active
|
||||
@@ -951,7 +972,8 @@ BEGIN
|
||||
round_id = T_ROUND.round_id
|
||||
, player_id = T_PLAYER_DAMAGE.player_id
|
||||
, received_from_commander_player_id = T_PLAYER_DAMAGE.received_from_commander_player_id
|
||||
, health_change = T_PLAYER_DAMAGE.health_change
|
||||
, life_gain = T_PLAYER_DAMAGE.life_gain
|
||||
, life_loss = T_PLAYER_DAMAGE.life_loss
|
||||
, commander_deaths = T_PLAYER_DAMAGE.commander_deaths
|
||||
, is_eliminated = T_PLAYER_DAMAGE.is_eliminated
|
||||
, active = T_PLAYER_DAMAGE.active
|
||||
@@ -1098,7 +1120,9 @@ LEFT JOIN tcg.public.TCG_MTG_Game GAME ON TCG_ROUND.game_id = GAME.game_id
|
||||
, round_id
|
||||
, player_id
|
||||
, received_from_commander_player_id
|
||||
, health_change
|
||||
-- , health_change
|
||||
, life_gain
|
||||
, life_loss
|
||||
, commander_deaths
|
||||
, active
|
||||
)
|
||||
@@ -1109,7 +1133,9 @@ LEFT JOIN tcg.public.TCG_MTG_Game GAME ON TCG_ROUND.game_id = GAME.game_id
|
||||
, -1 -- round_id
|
||||
, 3 -- player_id
|
||||
, NULL -- received_from_commander_player_id
|
||||
, -4 -- health_change
|
||||
-- , -4 -- health_change
|
||||
, 0 -- life_gain
|
||||
, 4 -- life_loss
|
||||
, 1 -- commander_deaths
|
||||
, TRUE -- active
|
||||
)
|
||||
@@ -1119,7 +1145,9 @@ LEFT JOIN tcg.public.TCG_MTG_Game GAME ON TCG_ROUND.game_id = GAME.game_id
|
||||
, -1 -- round_id
|
||||
, 3 -- player_id
|
||||
, 2 -- received_from_commander_player_id
|
||||
, -5 -- health_change
|
||||
-- , -5 -- health_change
|
||||
, 0 -- life_gain
|
||||
, 5 -- life_loss
|
||||
, NULL -- commander_deaths
|
||||
, TRUE -- active
|
||||
)
|
||||
@@ -1129,7 +1157,9 @@ LEFT JOIN tcg.public.TCG_MTG_Game GAME ON TCG_ROUND.game_id = GAME.game_id
|
||||
, -1 -- round_id
|
||||
, 3 -- player_id
|
||||
, 5 -- received_from_commander_player_id
|
||||
, -6 -- health_change
|
||||
-- , -6 -- health_change
|
||||
, 0 -- life_gain
|
||||
, 6 -- life_loss
|
||||
, NULL -- commander_deaths
|
||||
, TRUE -- active
|
||||
)
|
||||
|
||||
144
static/PostgreSQL/71300_fn_TCG_Statistic_Get_Many.sql
Normal file
144
static/PostgreSQL/71300_fn_TCG_Statistic_Get_Many.sql
Normal file
@@ -0,0 +1,144 @@
|
||||
|
||||
CREATE OR REPLACE FUNCTION tcg.public.FN_TCG_Statistic_Get_Many (
|
||||
a_get_all_statistic BOOLEAN
|
||||
, a_get_inactive_statistic BOOLEAN
|
||||
, a_statistic_ids TEXT
|
||||
, a_entity_type_codes TEXT
|
||||
, a_entity_record_ids TEXT
|
||||
, a_require_all_id_filters_met BOOLEAN
|
||||
, a_require_any_id_filters_met BOOLEAN
|
||||
)
|
||||
RETURNS TABLE (
|
||||
statistic_id INT
|
||||
, entity_type_code TEXT
|
||||
, entity_record_id TEXT
|
||||
, name TEXT
|
||||
, value_bool BOOLEAN
|
||||
, value_float DOUBLE PRECISION
|
||||
, value_interval INTERVAL
|
||||
, value_text TEXT
|
||||
, value_timestamp TIMESTAMP
|
||||
, is_bool BOOLEAN
|
||||
, is_float BOOLEAN
|
||||
, is_interval BOOLEAN
|
||||
, is_text BOOLEAN
|
||||
, is_timestamp BOOLEAN
|
||||
, display_order INT
|
||||
, active BOOLEAN
|
||||
, created_on TIMESTAMP
|
||||
, created_by_user_id INT
|
||||
, updated_last_on TIMESTAMP
|
||||
, updated_last_by_user_id INT
|
||||
, change_set_id INT
|
||||
)
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
v_get_all_statistic BOOLEAN;
|
||||
v_get_inactive_statistic BOOLEAN;
|
||||
v_statistic_ids TEXT;
|
||||
v_entity_type_codes TEXT;
|
||||
v_entity_record_ids TEXT;
|
||||
v_require_all_id_filters_met BOOLEAN;
|
||||
v_require_any_id_filters_met BOOLEAN;
|
||||
BEGIN
|
||||
v_get_all_statistic := COALESCE(a_get_all_statistic, FALSE);
|
||||
v_get_inactive_statistic := COALESCE(a_get_inactive_statistic, FALSE);
|
||||
v_statistic_ids := TRIM(COALESCE(a_statistic_ids, ''));
|
||||
v_entity_type_codes := TRIM(COALESCE(a_entity_type_codes, ''));
|
||||
v_entity_record_ids := TRIM(COALESCE(a_entity_record_ids, ''));
|
||||
v_require_all_id_filters_met := COALESCE(a_require_all_id_filters_met, FALSE);
|
||||
v_require_any_id_filters_met := COALESCE(a_require_any_id_filters_met, FALSE);
|
||||
|
||||
-- Outputs
|
||||
RETURN QUERY SELECT
|
||||
STATISTIC.statistic_id
|
||||
, STATISTIC.entity_type_code
|
||||
, STATISTIC.entity_record_id
|
||||
, STATISTIC.name
|
||||
, STATISTIC.value_bool
|
||||
, STATISTIC.value_float
|
||||
, STATISTIC.value_interval
|
||||
, STATISTIC.value_text
|
||||
, STATISTIC.value_timestamp
|
||||
, STATISTIC.is_bool
|
||||
, STATISTIC.is_float
|
||||
, STATISTIC.is_interval
|
||||
, STATISTIC.is_text
|
||||
, STATISTIC.is_timestamp
|
||||
, STATISTIC.display_order
|
||||
, STATISTIC.active
|
||||
, STATISTIC.created_on
|
||||
, STATISTIC.created_by_user_id
|
||||
, STATISTIC.updated_last_on
|
||||
, STATISTIC.updated_last_by_user_id
|
||||
, STATISTIC.change_set_id
|
||||
FROM tcg.public.TCG_Statistic STATISTIC
|
||||
WHERE
|
||||
(
|
||||
(
|
||||
NOT v_require_all_id_filters_met
|
||||
AND NOT v_require_any_id_filters_met
|
||||
)
|
||||
OR (
|
||||
v_require_all_id_filters_met
|
||||
AND (v_get_all_statistic OR v_statistic_ids = '' OR STATISTIC.statistic_id = ANY(string_to_array(v_statistic_ids, ',')::INT[]))
|
||||
AND (v_get_all_statistic OR v_entity_type_codes = '' OR STATISTIC.entity_type_code = ANY(string_to_array(v_entity_type_codes, ',')))
|
||||
AND (v_get_all_statistic OR v_entity_record_ids = '' OR STATISTIC.entity_record_id = ANY(string_to_array(v_entity_record_ids, ',')))
|
||||
)
|
||||
OR (
|
||||
NOT v_require_all_id_filters_met
|
||||
AND v_require_any_id_filters_met
|
||||
AND (
|
||||
v_get_all_statistic
|
||||
OR STATISTIC.statistic_id = ANY(string_to_array(v_statistic_ids, ',')::INT[])
|
||||
OR STATISTIC.entity_type_code = ANY(string_to_array(v_entity_type_codes, ','))
|
||||
OR STATISTIC.entity_record_id = ANY(string_to_array(v_entity_record_ids, ','))
|
||||
)
|
||||
)
|
||||
)
|
||||
AND (
|
||||
v_get_inactive_statistic
|
||||
OR STATISTIC.active
|
||||
)
|
||||
ORDER BY
|
||||
STATISTIC.entity_type_code
|
||||
, STATISTIC.entity_record_id
|
||||
, STATISTIC.display_order
|
||||
, STATISTIC.statistic_id
|
||||
;
|
||||
END;
|
||||
$$;
|
||||
|
||||
|
||||
SELECT *
|
||||
FROM tcg.public.FN_TCG_Statistic_Get_Many (
|
||||
a_get_all_statistic := FALSE
|
||||
, a_get_inactive_statistic := FALSE
|
||||
, a_statistic_ids := ''
|
||||
, a_entity_type_codes := 'deck'
|
||||
, a_entity_record_ids := '1,2'
|
||||
, a_require_all_id_filters_met := TRUE
|
||||
, a_require_any_id_filters_met := TRUE
|
||||
)
|
||||
;
|
||||
|
||||
|
||||
SELECT *
|
||||
FROM tcg.public.TCG_Statistic
|
||||
;
|
||||
|
||||
SELECT COUNT(*)
|
||||
FROM tcg.public.TCG_Statistic S
|
||||
WHERE S.entity_type_code = 'deck'
|
||||
;
|
||||
|
||||
SELECT COUNT(*)
|
||||
FROM tcg.public.TCG_Statistic S
|
||||
WHERE S.entity_type_code = 'user'
|
||||
;
|
||||
|
||||
SELECT COUNT(*)
|
||||
FROM tcg.public.TCG_Statistic S
|
||||
WHERE S.entity_type_code = 'user_deck_link'
|
||||
;
|
||||
9521
static/PostgreSQL/71301_usp_TCG_Statistic_Calc.sql
Normal file
9521
static/PostgreSQL/71301_usp_TCG_Statistic_Calc.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -17,8 +17,8 @@
|
||||
|
||||
.button-primary {
|
||||
background: var(--colour-accent);
|
||||
color: var(--colour-primary);
|
||||
border: 2px solid var(--colour-primary);
|
||||
color: var(--primary-color);
|
||||
border: 2px solid var(--primary-color);
|
||||
}
|
||||
|
||||
.button-primary:hover {
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
.button-light {
|
||||
background: white;
|
||||
color: var(--colour-primary);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.button-light:hover {
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
|
||||
select {
|
||||
border: 1px solid var(--colour-accent);
|
||||
background-color: var(--colour-page-background-1);
|
||||
background-color: var(--background-color-1);
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
position: fixed;
|
||||
width: 100px;
|
||||
/* height: 50%; */
|
||||
background: var(--colour-page-background);
|
||||
background: var(--background-color);
|
||||
justify-content: right;
|
||||
align-items: right;
|
||||
align-self: right;
|
||||
@@ -73,11 +73,11 @@
|
||||
border-bottom-right-radius: 12px;
|
||||
}
|
||||
#overlayHamburger > :hover {
|
||||
color: var(--colour-page-background);
|
||||
background-color: var(--colour-primary);
|
||||
color: var(--background-color);
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
#overlayHamburger .container {
|
||||
background-color: var(--colour-page-background);
|
||||
background-color: var(--tcg-accent-purple);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
@@ -93,8 +93,8 @@
|
||||
height: fit-content;
|
||||
}
|
||||
#overlayHamburger .container:hover {
|
||||
color: var(--colour-page-background);
|
||||
background-color: var(--colour-primary);
|
||||
color: var(--background-color);
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
#overlayHamburger > .container {
|
||||
/*
|
||||
@@ -105,13 +105,13 @@
|
||||
#overlayHamburger .container a {
|
||||
width: 100%;
|
||||
padding: 4.5px 0;
|
||||
color: var(--colour-text);
|
||||
color: var(--tcg-text-primary);
|
||||
text-decoration: none;
|
||||
line-height: initial;
|
||||
}
|
||||
#overlayHamburger .container a:hover {
|
||||
color: var(--colour-page-background);
|
||||
background-color: var(--colour-primary);
|
||||
color: var(--background-color);
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 400px) {
|
||||
|
||||
@@ -28,7 +28,7 @@ th.is_collapsed, td.is_collapsed {
|
||||
display: table-cell !important;
|
||||
}
|
||||
td.dirty {
|
||||
background-color: var(--colour-primary);
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
td:not(.dirty) {
|
||||
background-color: transparent;
|
||||
@@ -48,7 +48,7 @@ table button {
|
||||
}
|
||||
|
||||
table button.active {
|
||||
background-color: var(--colour-page-background);
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
tr.delete, tr.delete > td {
|
||||
|
||||
@@ -1 +1,16 @@
|
||||
|
||||
/* In sections */
|
||||
.tcg.footer {
|
||||
display: flex;
|
||||
}
|
||||
.tcg.footer > .container {
|
||||
/* display: flex; */
|
||||
}
|
||||
.footer-content {
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.footer-section {
|
||||
/* display: flex; */
|
||||
margin: auto auto;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
color: var(--colour-text-link-visited);
|
||||
}
|
||||
.topnav a:hover {
|
||||
background-color: var(--colour-page-background);
|
||||
background-color: var(--background-color);
|
||||
color: var(--colour-text)
|
||||
}
|
||||
.topnav > .container {
|
||||
@@ -149,10 +149,10 @@
|
||||
#formFilters button {
|
||||
padding: 0.5vh 0.75vh;
|
||||
background-color: var(--colour-accent);
|
||||
color: var(--colour-primary);
|
||||
color: var(--primary-color);
|
||||
font-weight: bold;
|
||||
border-radius: 0.75vh;
|
||||
border: 2px solid var(--colour-primary);
|
||||
border: 2px solid var(--primary-color);
|
||||
}
|
||||
|
||||
#formFilters button.is_collapsed {
|
||||
|
||||
@@ -4,38 +4,39 @@
|
||||
margin-top: 1vh;
|
||||
}
|
||||
|
||||
table.table-main {
|
||||
.table-main {
|
||||
overflow-x: auto;
|
||||
padding: 1vh 1vw;
|
||||
max-width: 88vw; /* min(calc(1vh * 80), calc(1vw * 90)); */
|
||||
padding: 0; /*1vh 1vw;*/
|
||||
max-width: 80vw; /* min(calc(1vh * 80), calc(1vw * 90)); */
|
||||
width: min-content;
|
||||
align-items: normal;
|
||||
justify-content: normal;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
table.table-main * {
|
||||
.table-main * {
|
||||
padding: 0.25vh 0.5vh;
|
||||
}
|
||||
|
||||
table.table-main thead {
|
||||
.table-main thead {
|
||||
max-height: 4vh;
|
||||
overflow-y: visible;
|
||||
background-color: var(--colour-text-background);
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
table.table-main tbody {
|
||||
.table-main tbody {
|
||||
max-height: 75vh;
|
||||
overflow-y: auto;
|
||||
min-width: fit-content;
|
||||
max-width: fit-content;
|
||||
overflow-x: visible;
|
||||
}
|
||||
table.table-main tbody.is_collapsed {
|
||||
.table-main tbody.is_collapsed {
|
||||
display: block;
|
||||
}
|
||||
table.table-main:has(tbody > div) tbody {
|
||||
.table-main:has(tbody > div) tbody {
|
||||
}
|
||||
table.table-main tbody > div {
|
||||
.table-main tbody > div {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
text-align: center;
|
||||
@@ -50,72 +51,72 @@ table.table-main tbody > div {
|
||||
width: 100%; /* min(calc(90vh), calc(70vw)); */
|
||||
}
|
||||
|
||||
table.table-main select,
|
||||
table.table-main input:not([type="checkbox"]),
|
||||
table.table-main textarea,
|
||||
table.table-main div {
|
||||
.table-main select,
|
||||
.table-main input:not([type="checkbox"]),
|
||||
.table-main textarea,
|
||||
.table-main div {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
border: 1px solid var(--colour-accent);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 0.5vh;
|
||||
text-align: center;
|
||||
background-color: var(--colour-text-background);
|
||||
background-color: var(--background-color);
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
table.table-main thead tr th,
|
||||
table.table-main tbody tr td {
|
||||
.table-main thead tr th,
|
||||
.table-main tbody tr td {
|
||||
max-width: 20vh;
|
||||
min-width: 20vh;
|
||||
padding: 0 0.5vh;
|
||||
}
|
||||
table.table-main tbody tr td {
|
||||
.table-main tbody tr td {
|
||||
height: 3vh;
|
||||
/* padding-top: 0.5vh; */
|
||||
}
|
||||
table.table-main thead tr th.notes,
|
||||
table.table-main tbody tr td.notes {
|
||||
.table-main thead tr th.notes,
|
||||
.table-main tbody tr td.notes {
|
||||
max-width: fit-content;
|
||||
}
|
||||
table.table-main tbody tr td:has(.dirty) {
|
||||
background-color: var(--colour-primary);
|
||||
.table-main tbody tr td:has(.dirty) {
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
table.table-main tbody tr td:has(.dirty) table tr:not(:has(.dirty)) {
|
||||
.table-main tbody tr td:has(.dirty) table tr:not(:has(.dirty)) {
|
||||
background-color: var(--colour-text-background);
|
||||
}
|
||||
table.table-main tbody tr:not(:last-of-type) td {
|
||||
.table-main tbody tr:not(:last-of-type) td {
|
||||
padding-bottom: 0.25vh;
|
||||
}
|
||||
table.table-main tbody tr td.ddl-preview div {
|
||||
.table-main tbody tr td.ddl-preview div {
|
||||
cursor: pointer;
|
||||
}
|
||||
table.table-main tbody tr td.ddl-preview div,
|
||||
table.table-main tbody tr td.ddl-preview select {
|
||||
.table-main tbody tr td.ddl-preview div,
|
||||
.table-main tbody tr td.ddl-preview select {
|
||||
padding-left: 2vh;
|
||||
padding-right: 2vh;
|
||||
}
|
||||
table.table-main thead tr th.active,
|
||||
table.table-main tbody tr td.active {
|
||||
.table-main thead tr th.active,
|
||||
.table-main tbody tr td.active {
|
||||
max-width: 6vh;
|
||||
min-width: 6vh;
|
||||
}
|
||||
table.table-main thead tr th.active svg.active.add {
|
||||
fill: var(--colour-primary);
|
||||
background-color: var(--colour-accent);
|
||||
border: 2px solid var(--colour-accent);
|
||||
.table-main thead tr th.active svg.active.add {
|
||||
fill: var(--primary-color);
|
||||
background-color: var(--background-color);
|
||||
border: 2px solid var(--border-color);
|
||||
padding: 0;
|
||||
border-radius: 1vh;
|
||||
}
|
||||
table.table-main tbody tr td.active svg.active.add {
|
||||
fill: var(--colour-primary);
|
||||
.table-main tbody tr td.active svg.active.add {
|
||||
fill: var(--primary-color);
|
||||
}
|
||||
table.table-main tbody tr td.active svg.active.delete {
|
||||
fill: var(--colour-error);
|
||||
.table-main tbody tr td.active svg.active.delete {
|
||||
fill: var(--tcg-accent-red);
|
||||
}
|
||||
table.table-main tbody tr td.display_order,
|
||||
table.table-main thead tr th.display_order {
|
||||
.table-main tbody tr td.display_order,
|
||||
.table-main thead tr th.display_order {
|
||||
max-width: 5vh;
|
||||
min-width: 5vh;
|
||||
}
|
||||
@@ -141,13 +142,13 @@ table.table-main thead tr th.display_order {
|
||||
.company-name {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
table.table-main {
|
||||
.table-main {
|
||||
max-height: 61vh;
|
||||
}
|
||||
table.table-main thead {
|
||||
.table-main thead {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
table.table-main tbody {
|
||||
.table-main tbody {
|
||||
max-height: 53vh;
|
||||
}
|
||||
}
|
||||
@@ -38,14 +38,13 @@ html {
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--colour-page-background);
|
||||
color: var(--colour-text);
|
||||
background-color: var(--background-color);
|
||||
color: var(--text-color);
|
||||
font-family: var(--font-family-base);
|
||||
font-family: Arial;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
background: linear-gradient(to bottom right, var(--colour-page-background-1), var(--colour-page-background-2)); /* var(--c_purple); */
|
||||
height: 100vh;
|
||||
/* max-height: 100vh;
|
||||
overflow-y: clip; */
|
||||
@@ -53,6 +52,7 @@ body {
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
script, link {
|
||||
@@ -88,7 +88,7 @@ script, link {
|
||||
width: 100%;
|
||||
align-self: center;
|
||||
font-size: 1rem;
|
||||
color: var(--colour-text);
|
||||
color: var(--text-color);
|
||||
}
|
||||
#pageBody > * > * {
|
||||
align-self: center;
|
||||
@@ -104,7 +104,6 @@ script, link {
|
||||
|
||||
/* Add a card effect for articles */
|
||||
.card {
|
||||
background-color: var(--colour-text-background);
|
||||
padding: 1vh 2.5vw;
|
||||
margin: 1vh 1vw;
|
||||
display: flex;
|
||||
@@ -182,7 +181,7 @@ script, link {
|
||||
|
||||
.container-input > input,
|
||||
.container-input > textarea {
|
||||
border: 2px solid var(--colour-accent);
|
||||
border: 2px solid var(--border-color);
|
||||
border-radius: 0.5vh;
|
||||
padding: 1vh 1vw;
|
||||
}
|
||||
@@ -205,10 +204,10 @@ li {
|
||||
|
||||
|
||||
:not(input,textarea,select,button).dirty {
|
||||
background-color: var(--colour-accent);
|
||||
background-color: var(--border-color);
|
||||
}
|
||||
input.dirty, textarea.dirty, select.dirty {
|
||||
border-color: var(--colour-primary);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.is-collapsed {
|
||||
|
||||
@@ -24,6 +24,9 @@ body.tcg-theme {
|
||||
}
|
||||
|
||||
/* Top Nav TCG Style */
|
||||
#buttonHamburger {
|
||||
display: none;
|
||||
}
|
||||
.topnav.tcg {
|
||||
background: var(--tcg-bg-secondary);
|
||||
border-bottom: 2px solid var(--tcg-border-color);
|
||||
@@ -88,7 +91,8 @@ body.tcg-theme {
|
||||
.footer.tcg h3 {
|
||||
font-family: 'Cinzel', serif;
|
||||
color: var(--tcg-accent-gold);
|
||||
margin-bottom: 1rem;
|
||||
/* margin-bottom: 1vh; */
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.footer.tcg a {
|
||||
@@ -174,9 +178,10 @@ body.tcg-theme {
|
||||
font-family: 'Cinzel', serif;
|
||||
font-size: 1.5rem;
|
||||
color: var(--tcg-accent-gold);
|
||||
margin-bottom: 1.5rem;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
margin: 1.5rem auto 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* TCG Form Elements */
|
||||
@@ -244,6 +249,9 @@ body.tcg-theme {
|
||||
.nav-links.tcg {
|
||||
display: none;
|
||||
}
|
||||
#buttonHamburger {
|
||||
display: block;
|
||||
}
|
||||
.topnav.tcg {
|
||||
padding-right: 30vw;
|
||||
}
|
||||
|
||||
38
static/css/pages/tcg/decks.css
Normal file
38
static/css/pages/tcg/decks.css
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
|
||||
.tcg-card {
|
||||
margin-top: 1vh;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
table.table-main tbody {
|
||||
max-height: 30vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
table.statistics {
|
||||
margin-top: 0;
|
||||
}
|
||||
table.statistics thead {
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
table.statistics tbody {
|
||||
max-height: 30vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
table.statistics thead tr th.deck,
|
||||
table.statistics tbody tr td.deck_id {
|
||||
min-width: 20vh;
|
||||
max-width: 20vh;
|
||||
}
|
||||
table.statistics thead tr th.name,
|
||||
table.statistics tbody tr td.name {
|
||||
min-width: 40vh;
|
||||
max-width: 40vh;
|
||||
}
|
||||
table.statistics thead tr th.value,
|
||||
table.statistics tbody tr td.value {
|
||||
min-width: 10vh;
|
||||
max-width: 10vh;
|
||||
}
|
||||
@@ -147,6 +147,9 @@
|
||||
}
|
||||
|
||||
/* Game Section */
|
||||
#gameSection {
|
||||
margin: 0 auto;
|
||||
}
|
||||
#gameSection .row.round {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -347,13 +350,16 @@
|
||||
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.life-controls {
|
||||
.life-gain-controls,
|
||||
.life-loss-controls {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
margin-bottom: 1vh;
|
||||
}
|
||||
|
||||
.life-btn {
|
||||
.life-gain-btn,
|
||||
.life-loss-btn {
|
||||
background: var(--tcg-bg-card);
|
||||
border: 2px solid var(--tcg-border-color);
|
||||
color: var(--tcg-text-primary);
|
||||
@@ -370,17 +376,31 @@
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.life-btn:hover {
|
||||
border-color: var(--tcg-accent-purple);
|
||||
background: var(--tcg-accent-purple);
|
||||
.life-gain-btn:hover,
|
||||
.life-loss-btn:hover {
|
||||
border-color: green; /*var(--tcg-accent-purple);*/
|
||||
background: green; /*var(--tcg-accent-purple);*/
|
||||
color: var(--tcg-bg-primary);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.life-btn:active {
|
||||
.life-loss-btn:hover {
|
||||
border-color: red;
|
||||
background: red;
|
||||
}
|
||||
|
||||
.life-gain-btn:active,
|
||||
.life-loss-btn:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.life-total label {
|
||||
color: var(--tcg-text-primary);
|
||||
width: 100%;
|
||||
margin-bottom: 1vh;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Commander Damage Section */
|
||||
.commander-damage-section {
|
||||
border-top: 1px solid var(--tcg-border-color);
|
||||
@@ -420,6 +440,7 @@
|
||||
.damage-source {
|
||||
font-size: 1rem;
|
||||
color: var(--tcg-text-secondary);
|
||||
padding-right: 1vh;
|
||||
}
|
||||
|
||||
.damage-controls {
|
||||
@@ -478,8 +499,10 @@
|
||||
.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 {
|
||||
.damage-log.container table thead tr th.life_gain,
|
||||
.damage-log.container table tbody tr td.life_gain,
|
||||
.damage-log.container table thead tr th.life_loss,
|
||||
.damage-log.container table tbody tr td.life_loss {
|
||||
width: 7vw;
|
||||
}
|
||||
.damage-log.container table thead tr th.commander-deaths,
|
||||
@@ -583,7 +606,8 @@
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.life-btn {
|
||||
.life-gain-btn,
|
||||
.life-loss-btn {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 1.5rem;
|
||||
|
||||
@@ -33,15 +33,18 @@
|
||||
position: relative;
|
||||
animation: tcg-fadeIn 0.8s ease-out 0.2s backwards;
|
||||
margin: 2vh auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Filters Form */
|
||||
@@ -88,8 +91,7 @@
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.games-table {
|
||||
width: 100%;
|
||||
#tableMain.games-table {
|
||||
border-collapse: collapse;
|
||||
font-size: 1rem;
|
||||
}
|
||||
@@ -98,7 +100,6 @@
|
||||
background: var(--tcg-bg-card);
|
||||
border-bottom: 2px solid var(--tcg-accent-purple);
|
||||
}
|
||||
|
||||
.games-table th {
|
||||
font-family: 'Cinzel', serif;
|
||||
font-size: 0.95rem;
|
||||
@@ -107,18 +108,22 @@
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
padding: 1rem;
|
||||
text-align: left;
|
||||
}
|
||||
.games-table thead tr {
|
||||
height: 4vh;
|
||||
}
|
||||
|
||||
#tableMain.games-table tbody {
|
||||
max-height: 59vh;
|
||||
}
|
||||
.games-table tbody tr {
|
||||
border-bottom: 1px solid var(--tcg-border-color);
|
||||
transition: all 0.3s ease;
|
||||
height: 4vh;
|
||||
}
|
||||
|
||||
.games-table tbody tr:hover {
|
||||
background: rgba(139, 92, 246, 0.1);
|
||||
}
|
||||
|
||||
.games-table tbody tr.inactive {
|
||||
opacity: 0.5;
|
||||
}
|
||||
@@ -132,7 +137,38 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
.game-id {
|
||||
.games-table thead tr th.game_id,
|
||||
.games-table tbody tr td.game_id {
|
||||
min-width: 10vh;
|
||||
max-width: 10vh;
|
||||
}
|
||||
.games-table thead tr th.is_commander,
|
||||
.games-table tbody tr td.is_commander {
|
||||
min-width: 12vh;
|
||||
max-width: 12vh;
|
||||
}
|
||||
.games-table thead tr th.location_name,
|
||||
.games-table tbody tr td.location_name {
|
||||
min-width: 20vh;
|
||||
max-width: 20vh;
|
||||
}
|
||||
.games-table thead tr th.start_on,
|
||||
.games-table tbody tr td.start_on {
|
||||
min-width: 14vh;
|
||||
max-width: 14vh;
|
||||
}
|
||||
#tableMain.games-table thead tr th.active,
|
||||
#tableMain.games-table tbody tr td.active {
|
||||
min-width: 8vh;
|
||||
max-width: 8vh;
|
||||
}
|
||||
.games-table thead tr th.navMtgGame,
|
||||
.games-table tbody tr td.navMtgGame {
|
||||
min-width: 13vh;
|
||||
max-width: 13vh;
|
||||
}
|
||||
|
||||
.game_id {
|
||||
font-family: 'Cinzel', serif;
|
||||
font-weight: 600;
|
||||
color: var(--tcg-text-secondary);
|
||||
@@ -223,7 +259,7 @@
|
||||
|
||||
/* Join Button */
|
||||
.btn-join {
|
||||
padding: 0.5rem 1.25rem;
|
||||
padding: 0.5vh 1vw;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
@@ -265,7 +301,7 @@
|
||||
animation: tcg-fadeIn 0.3s ease-out;
|
||||
}
|
||||
|
||||
.modal-overlay.hidden {
|
||||
.modal-overlay.is_collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -338,7 +374,6 @@
|
||||
}
|
||||
|
||||
.section-header {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,6 @@ label {
|
||||
input.dirty,
|
||||
textarea.dirty,
|
||||
select.dirty {
|
||||
border-color: var(--colour-primary);
|
||||
background-color: var(--colour-page-background-2);
|
||||
border-color: var(--primary-color);
|
||||
background-color: var(--background-color-2);
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
/* Main Table */
|
||||
#pageBody {
|
||||
max-height: 77vh;
|
||||
max-height: 82vh;
|
||||
padding: 0 5vw;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
|
||||
:root {
|
||||
--background-color: #121212;
|
||||
--text-color: #e0e0e0;
|
||||
@@ -43,5 +43,5 @@
|
||||
--card-bg: #1f1f1f;
|
||||
--card-border: #333333;
|
||||
--card-shadow: 0 0.125rem 0.25rem rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
border-radius: 2vh;
|
||||
}
|
||||
.theme-switch:hover {
|
||||
background-color: var(--colour-primary);
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
.theme-switch img.theme-icon,
|
||||
.theme-switch svg.theme-icon {
|
||||
@@ -40,7 +40,7 @@ svg.theme-icon.light-mode-icon .background {
|
||||
fill: var(--colour-secondary);
|
||||
}
|
||||
.theme-switch:hover svg.theme-icon.light-mode-icon .background {
|
||||
fill: var(--colour-primary);
|
||||
fill: var(--primary-color);
|
||||
}
|
||||
svg.theme-icon.light-mode-icon .sun {
|
||||
fill: var(--colour-text);
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
--colour-error-accent: #fc8181;
|
||||
--colour-error-highlight: #fff5f5;
|
||||
--colour-error-title: #c53030;
|
||||
--colour-page-background: #E0AAFF;
|
||||
--colour-page-background-1: #F5ECFE;
|
||||
--colour-page-background-2: #FAE0E2;
|
||||
--colour-primary: #240046;
|
||||
--background-color: #E0AAFF;
|
||||
--background-color-1: #F5ECFE;
|
||||
--background-color-2: #FAE0E2;
|
||||
--primary-color: #240046;
|
||||
--colour-secondary: #3C096C;
|
||||
--colour-success: #38a169;
|
||||
--colour-success-highlight: #f0fff4;
|
||||
|
||||
233
static/dist/css/main.bundle.css
vendored
233
static/dist/css/main.bundle.css
vendored
@@ -38,14 +38,13 @@ html {
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--colour-page-background);
|
||||
color: var(--colour-text);
|
||||
background-color: var(--background-color);
|
||||
color: var(--text-color);
|
||||
font-family: var(--font-family-base);
|
||||
font-family: Arial;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
background: linear-gradient(to bottom right, var(--colour-page-background-1), var(--colour-page-background-2)); /* var(--c_purple); */
|
||||
height: 100vh;
|
||||
/* max-height: 100vh;
|
||||
overflow-y: clip; */
|
||||
@@ -53,6 +52,7 @@ body {
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
script, link {
|
||||
@@ -88,7 +88,7 @@ script, link {
|
||||
width: 100%;
|
||||
align-self: center;
|
||||
font-size: 1rem;
|
||||
color: var(--colour-text);
|
||||
color: var(--text-color);
|
||||
}
|
||||
#pageBody > * > * {
|
||||
align-self: center;
|
||||
@@ -104,7 +104,6 @@ script, link {
|
||||
|
||||
/* Add a card effect for articles */
|
||||
.card {
|
||||
background-color: var(--colour-text-background);
|
||||
padding: 1vh 2.5vw;
|
||||
margin: 1vh 1vw;
|
||||
display: flex;
|
||||
@@ -182,7 +181,7 @@ script, link {
|
||||
|
||||
.container-input > input,
|
||||
.container-input > textarea {
|
||||
border: 2px solid var(--colour-accent);
|
||||
border: 2px solid var(--border-color);
|
||||
border-radius: 0.5vh;
|
||||
padding: 1vh 1vw;
|
||||
}
|
||||
@@ -205,10 +204,10 @@ li {
|
||||
|
||||
|
||||
:not(input,textarea,select,button).dirty {
|
||||
background-color: var(--colour-accent);
|
||||
background-color: var(--border-color);
|
||||
}
|
||||
input.dirty, textarea.dirty, select.dirty {
|
||||
border-color: var(--colour-primary);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.is-collapsed {
|
||||
@@ -234,8 +233,8 @@ input.dirty, textarea.dirty, select.dirty {
|
||||
|
||||
.button-primary {
|
||||
background: var(--colour-accent);
|
||||
color: var(--colour-primary);
|
||||
border: 2px solid var(--colour-primary);
|
||||
color: var(--primary-color);
|
||||
border: 2px solid var(--primary-color);
|
||||
}
|
||||
|
||||
.button-primary:hover {
|
||||
@@ -245,7 +244,7 @@ input.dirty, textarea.dirty, select.dirty {
|
||||
|
||||
.button-light {
|
||||
background: white;
|
||||
color: var(--colour-primary);
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.button-light:hover {
|
||||
@@ -267,7 +266,7 @@ input.dirty, textarea.dirty, select.dirty {
|
||||
|
||||
select {
|
||||
border: 1px solid var(--colour-accent);
|
||||
background-color: var(--colour-page-background-1);
|
||||
background-color: var(--background-color-1);
|
||||
}
|
||||
|
||||
img, video {
|
||||
@@ -321,7 +320,7 @@ h5 {
|
||||
position: fixed;
|
||||
width: 100px;
|
||||
/* height: 50%; */
|
||||
background: var(--colour-page-background);
|
||||
background: var(--background-color);
|
||||
justify-content: right;
|
||||
align-items: right;
|
||||
align-self: right;
|
||||
@@ -386,11 +385,11 @@ h5 {
|
||||
border-bottom-right-radius: 12px;
|
||||
}
|
||||
#overlayHamburger > :hover {
|
||||
color: var(--colour-page-background);
|
||||
background-color: var(--colour-primary);
|
||||
color: var(--background-color);
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
#overlayHamburger .container {
|
||||
background-color: var(--colour-page-background);
|
||||
background-color: var(--tcg-accent-purple);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
@@ -406,8 +405,8 @@ h5 {
|
||||
height: fit-content;
|
||||
}
|
||||
#overlayHamburger .container:hover {
|
||||
color: var(--colour-page-background);
|
||||
background-color: var(--colour-primary);
|
||||
color: var(--background-color);
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
#overlayHamburger > .container {
|
||||
/*
|
||||
@@ -418,13 +417,13 @@ h5 {
|
||||
#overlayHamburger .container a {
|
||||
width: 100%;
|
||||
padding: 4.5px 0;
|
||||
color: var(--colour-text);
|
||||
color: var(--tcg-text-primary);
|
||||
text-decoration: none;
|
||||
line-height: initial;
|
||||
}
|
||||
#overlayHamburger .container a:hover {
|
||||
color: var(--colour-page-background);
|
||||
background-color: var(--colour-primary);
|
||||
color: var(--background-color);
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 400px) {
|
||||
@@ -497,7 +496,7 @@ th.is_collapsed, td.is_collapsed {
|
||||
display: table-cell !important;
|
||||
}
|
||||
td.dirty {
|
||||
background-color: var(--colour-primary);
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
td:not(.dirty) {
|
||||
background-color: transparent;
|
||||
@@ -517,7 +516,7 @@ table button {
|
||||
}
|
||||
|
||||
table button.active {
|
||||
background-color: var(--colour-page-background);
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
tr.delete, tr.delete > td {
|
||||
@@ -560,7 +559,7 @@ table div {
|
||||
color: var(--colour-text-link-visited);
|
||||
}
|
||||
.topnav a:hover {
|
||||
background-color: var(--colour-page-background);
|
||||
background-color: var(--background-color);
|
||||
color: var(--colour-text)
|
||||
}
|
||||
.topnav > .container {
|
||||
@@ -678,10 +677,10 @@ table div {
|
||||
#formFilters button {
|
||||
padding: 0.5vh 0.75vh;
|
||||
background-color: var(--colour-accent);
|
||||
color: var(--colour-primary);
|
||||
color: var(--primary-color);
|
||||
font-weight: bold;
|
||||
border-radius: 0.75vh;
|
||||
border: 2px solid var(--colour-primary);
|
||||
border: 2px solid var(--primary-color);
|
||||
}
|
||||
|
||||
#formFilters button.is_collapsed {
|
||||
@@ -725,45 +724,62 @@ form.filter button.save, form.filter button.button-cancel {
|
||||
padding-right: 30vw;
|
||||
}
|
||||
}
|
||||
|
||||
/* In sections */
|
||||
.tcg.footer {
|
||||
display: flex;
|
||||
}
|
||||
.tcg.footer > .container {
|
||||
/* display: flex; */
|
||||
}
|
||||
.footer-content {
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.footer-section {
|
||||
/* display: flex; */
|
||||
margin: auto auto;
|
||||
}
|
||||
|
||||
|
||||
#formFilters {
|
||||
padding: 0.5vh 1vw;
|
||||
margin-top: 1vh;
|
||||
}
|
||||
|
||||
table.table-main {
|
||||
.table-main {
|
||||
overflow-x: auto;
|
||||
padding: 1vh 1vw;
|
||||
max-width: 88vw; /* min(calc(1vh * 80), calc(1vw * 90)); */
|
||||
padding: 0; /*1vh 1vw;*/
|
||||
max-width: 80vw; /* min(calc(1vh * 80), calc(1vw * 90)); */
|
||||
width: min-content;
|
||||
align-items: normal;
|
||||
justify-content: normal;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
table.table-main * {
|
||||
.table-main * {
|
||||
padding: 0.25vh 0.5vh;
|
||||
}
|
||||
|
||||
table.table-main thead {
|
||||
.table-main thead {
|
||||
max-height: 4vh;
|
||||
overflow-y: visible;
|
||||
background-color: var(--colour-text-background);
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
table.table-main tbody {
|
||||
.table-main tbody {
|
||||
max-height: 75vh;
|
||||
overflow-y: auto;
|
||||
min-width: fit-content;
|
||||
max-width: fit-content;
|
||||
overflow-x: visible;
|
||||
}
|
||||
table.table-main tbody.is_collapsed {
|
||||
.table-main tbody.is_collapsed {
|
||||
display: block;
|
||||
}
|
||||
table.table-main:has(tbody > div) tbody {
|
||||
.table-main:has(tbody > div) tbody {
|
||||
}
|
||||
table.table-main tbody > div {
|
||||
.table-main tbody > div {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
text-align: center;
|
||||
@@ -778,72 +794,72 @@ table.table-main tbody > div {
|
||||
width: 100%; /* min(calc(90vh), calc(70vw)); */
|
||||
}
|
||||
|
||||
table.table-main select,
|
||||
table.table-main input:not([type="checkbox"]),
|
||||
table.table-main textarea,
|
||||
table.table-main div {
|
||||
.table-main select,
|
||||
.table-main input:not([type="checkbox"]),
|
||||
.table-main textarea,
|
||||
.table-main div {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
border: 1px solid var(--colour-accent);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 0.5vh;
|
||||
text-align: center;
|
||||
background-color: var(--colour-text-background);
|
||||
background-color: var(--background-color);
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
table.table-main thead tr th,
|
||||
table.table-main tbody tr td {
|
||||
.table-main thead tr th,
|
||||
.table-main tbody tr td {
|
||||
max-width: 20vh;
|
||||
min-width: 20vh;
|
||||
padding: 0 0.5vh;
|
||||
}
|
||||
table.table-main tbody tr td {
|
||||
.table-main tbody tr td {
|
||||
height: 3vh;
|
||||
/* padding-top: 0.5vh; */
|
||||
}
|
||||
table.table-main thead tr th.notes,
|
||||
table.table-main tbody tr td.notes {
|
||||
.table-main thead tr th.notes,
|
||||
.table-main tbody tr td.notes {
|
||||
max-width: fit-content;
|
||||
}
|
||||
table.table-main tbody tr td:has(.dirty) {
|
||||
background-color: var(--colour-primary);
|
||||
.table-main tbody tr td:has(.dirty) {
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
table.table-main tbody tr td:has(.dirty) table tr:not(:has(.dirty)) {
|
||||
.table-main tbody tr td:has(.dirty) table tr:not(:has(.dirty)) {
|
||||
background-color: var(--colour-text-background);
|
||||
}
|
||||
table.table-main tbody tr:not(:last-of-type) td {
|
||||
.table-main tbody tr:not(:last-of-type) td {
|
||||
padding-bottom: 0.25vh;
|
||||
}
|
||||
table.table-main tbody tr td.ddl-preview div {
|
||||
.table-main tbody tr td.ddl-preview div {
|
||||
cursor: pointer;
|
||||
}
|
||||
table.table-main tbody tr td.ddl-preview div,
|
||||
table.table-main tbody tr td.ddl-preview select {
|
||||
.table-main tbody tr td.ddl-preview div,
|
||||
.table-main tbody tr td.ddl-preview select {
|
||||
padding-left: 2vh;
|
||||
padding-right: 2vh;
|
||||
}
|
||||
table.table-main thead tr th.active,
|
||||
table.table-main tbody tr td.active {
|
||||
.table-main thead tr th.active,
|
||||
.table-main tbody tr td.active {
|
||||
max-width: 6vh;
|
||||
min-width: 6vh;
|
||||
}
|
||||
table.table-main thead tr th.active svg.active.add {
|
||||
fill: var(--colour-primary);
|
||||
background-color: var(--colour-accent);
|
||||
border: 2px solid var(--colour-accent);
|
||||
.table-main thead tr th.active svg.active.add {
|
||||
fill: var(--primary-color);
|
||||
background-color: var(--background-color);
|
||||
border: 2px solid var(--border-color);
|
||||
padding: 0;
|
||||
border-radius: 1vh;
|
||||
}
|
||||
table.table-main tbody tr td.active svg.active.add {
|
||||
fill: var(--colour-primary);
|
||||
.table-main tbody tr td.active svg.active.add {
|
||||
fill: var(--primary-color);
|
||||
}
|
||||
table.table-main tbody tr td.active svg.active.delete {
|
||||
fill: var(--colour-error);
|
||||
.table-main tbody tr td.active svg.active.delete {
|
||||
fill: var(--tcg-accent-red);
|
||||
}
|
||||
table.table-main tbody tr td.display_order,
|
||||
table.table-main thead tr th.display_order {
|
||||
.table-main tbody tr td.display_order,
|
||||
.table-main thead tr th.display_order {
|
||||
max-width: 5vh;
|
||||
min-width: 5vh;
|
||||
}
|
||||
@@ -869,13 +885,13 @@ table.table-main thead tr th.display_order {
|
||||
.company-name {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
table.table-main {
|
||||
.table-main {
|
||||
max-height: 61vh;
|
||||
}
|
||||
table.table-main thead {
|
||||
.table-main thead {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
table.table-main tbody {
|
||||
.table-main tbody {
|
||||
max-height: 53vh;
|
||||
}
|
||||
}
|
||||
@@ -883,44 +899,53 @@ table.table-main thead tr th.display_order {
|
||||
|
||||
|
||||
|
||||
/* Default */
|
||||
|
||||
:root {
|
||||
/* Claude dark blue / grey theme */
|
||||
--colour-accent: #C77DFF;
|
||||
--colour-error: red;
|
||||
--colour-error-accent: #fc8181;
|
||||
--colour-error-highlight: #fff5f5;
|
||||
--colour-error-title: #c53030;
|
||||
--colour-page-background: #E0AAFF;
|
||||
--colour-page-background-1: #F5ECFE;
|
||||
--colour-page-background-2: #FAE0E2;
|
||||
--colour-primary: #240046;
|
||||
--colour-secondary: #3C096C;
|
||||
--colour-success: #38a169;
|
||||
--colour-success-highlight: #f0fff4;
|
||||
--colour-success-title: #16a34a;
|
||||
--colour-text: #10002B;
|
||||
--colour-text-background: white;
|
||||
--colour-text-link-unvisited: #0000EE;
|
||||
--colour-text-link-visited: #551A8B;
|
||||
}
|
||||
--background-color: #121212;
|
||||
--text-color: #e0e0e0;
|
||||
--primary-color: #bb86fc;
|
||||
--secondary-color: #03dac6;
|
||||
--success-color: #00c853;
|
||||
--danger-color: #cf6679;
|
||||
--warning-color: #ffab00;
|
||||
--info-color: #2196f3;
|
||||
--light-color: #2c2c2c;
|
||||
--dark-color: #1f1f1f;
|
||||
--border-color: #333333;
|
||||
--shadow-color: rgba(255, 255, 255, 0.1);
|
||||
|
||||
/*
|
||||
--c_purple_darker: #310055;
|
||||
--c_purple_dark: #4A0A77;
|
||||
--c_purple: #6818A5;
|
||||
--c_purple_light: #CBAFFE;
|
||||
--c_purple_lighter: #F5ECFE;
|
||||
/* Header * /
|
||||
--header-bg: #1f1f1f;
|
||||
--header-text: #e0e0e0;
|
||||
|
||||
--c_blue: #0044FF;
|
||||
--c_blue_pastel: #B8E0FF;
|
||||
--c_blue_light: #73E8FF;
|
||||
--c_blue_dark: #003ADB;
|
||||
/* --c_red: * /
|
||||
--c-red: #FF0000;
|
||||
--c_red_pastel: #FAE0E2;
|
||||
--c_red_lighter: #FAE0E2;
|
||||
}
|
||||
/* Footer * /
|
||||
--footer-bg: #1f1f1f;
|
||||
--footer-text: #a0a0a0;
|
||||
|
||||
/* Navigation * /
|
||||
--nav-bg: #1f1f1f;
|
||||
--nav-text: #e0e0e0;
|
||||
--nav-hover-bg: #2c2c2c;
|
||||
--nav-hover-text: #bb86fc;
|
||||
|
||||
/* Buttons * /
|
||||
--Button-primary-bg: #bb86fc;
|
||||
--Button-primary-text: #121212;
|
||||
--Button-secondary-bg: #03dac6;
|
||||
--Button-secondary-text: #121212;
|
||||
|
||||
/* Forms * /
|
||||
--input-bg: #2c2c2c;
|
||||
--input-border: #454545;
|
||||
--input-text: #e0e0e0;
|
||||
--input-focus-border: #bb86fc;
|
||||
|
||||
/* Cards * /
|
||||
--card-bg: #1f1f1f;
|
||||
--card-border: #333333;
|
||||
--card-shadow: 0 0.125rem 0.25rem rgba(255, 255, 255, 0.05);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=main.bundle.css.map*/
|
||||
2
static/dist/css/main.bundle.css.map
vendored
2
static/dist/css/main.bundle.css.map
vendored
File diff suppressed because one or more lines are too long
106
static/dist/css/tcg_decks.bundle.css
vendored
Normal file
106
static/dist/css/tcg_decks.bundle.css
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
|
||||
|
||||
.container-input > input {
|
||||
padding: 0vh 1vh;
|
||||
border-radius: 0.5vh;
|
||||
max-width: 7vh;
|
||||
}
|
||||
|
||||
|
||||
/* Right column */
|
||||
.rightcolumn {
|
||||
min-width: fit-content;
|
||||
}
|
||||
|
||||
/* Main Table */
|
||||
#pageBody {
|
||||
max-height: 82vh;
|
||||
padding: 0 5vw;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
align-content: center;
|
||||
justify-content: flex-start;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
position: absolute;
|
||||
width: 90vw;
|
||||
color: var(--colour-text);
|
||||
}
|
||||
|
||||
|
||||
/* Footer */
|
||||
.footer {
|
||||
padding: 1vh 1vw;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
max-height: 5vh;
|
||||
overflow-y: auto;
|
||||
background-color: var(--colour-accent);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 98vw;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 400px) {
|
||||
.footer {
|
||||
max-height: 8vh;
|
||||
padding: 0.75vh 2vw;
|
||||
font-size: 10px;
|
||||
width: 96vw;
|
||||
max-width: 96vw;
|
||||
}
|
||||
.footer > h4 {
|
||||
font-size: 10px;
|
||||
}
|
||||
.footer > h5 {
|
||||
font-size: 9px;
|
||||
}
|
||||
}
|
||||
|
||||
.footer > h4, h5 {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
.tcg-card {
|
||||
margin-top: 1vh;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
table.table-main tbody {
|
||||
max-height: 30vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
table.statistics {
|
||||
margin-top: 0;
|
||||
}
|
||||
table.statistics thead {
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
table.statistics tbody {
|
||||
max-height: 30vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
table.statistics thead tr th.deck,
|
||||
table.statistics tbody tr td.deck_id {
|
||||
min-width: 20vh;
|
||||
max-width: 20vh;
|
||||
}
|
||||
table.statistics thead tr th.name,
|
||||
table.statistics tbody tr td.name {
|
||||
min-width: 40vh;
|
||||
max-width: 40vh;
|
||||
}
|
||||
table.statistics thead tr th.value,
|
||||
table.statistics tbody tr td.value {
|
||||
min-width: 10vh;
|
||||
max-width: 10vh;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=tcg_decks.bundle.css.map*/
|
||||
1
static/dist/css/tcg_decks.bundle.css.map
vendored
Normal file
1
static/dist/css/tcg_decks.bundle.css.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"css/tcg_decks.bundle.css","mappings":";;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,SAAS;IACT,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C;;;AC/DA;IACI,eAAe;IACf,gBAAgB;AACpB;;;AAGA;IACI,gBAAgB;IAChB,gBAAgB;AACpB;;AAEA;IACI,aAAa;AACjB;AACA;IACI,yCAAyC;AAC7C;AACA;IACI,gBAAgB;IAChB,gBAAgB;AACpB;AACA;;IAEI,eAAe;IACf,eAAe;AACnB;AACA;;IAEI,eAAe;IACf,eAAe;AACnB;AACA;;IAEI,eAAe;IACf,eAAe;AACnB,C","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/tcg/decks.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n position: absolute;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","\n\n.tcg-card {\n margin-top: 1vh;\n margin-bottom: 0;\n}\n\n\ntable.table-main tbody {\n max-height: 30vh;\n overflow-y: auto;\n}\n\ntable.statistics {\n margin-top: 0;\n}\ntable.statistics thead {\n background-color: var(--background-color);\n}\ntable.statistics tbody {\n max-height: 30vh;\n overflow-y: auto;\n}\ntable.statistics thead tr th.deck,\ntable.statistics tbody tr td.deck_id {\n min-width: 20vh;\n max-width: 20vh;\n}\ntable.statistics thead tr th.name,\ntable.statistics tbody tr td.name {\n min-width: 40vh;\n max-width: 40vh;\n}\ntable.statistics thead tr th.value,\ntable.statistics tbody tr td.value {\n min-width: 10vh;\n max-width: 10vh;\n}"],"names":[],"sourceRoot":""}
|
||||
44
static/dist/css/tcg_game.bundle.css
vendored
44
static/dist/css/tcg_game.bundle.css
vendored
@@ -14,7 +14,7 @@
|
||||
|
||||
/* Main Table */
|
||||
#pageBody {
|
||||
max-height: 77vh;
|
||||
max-height: 82vh;
|
||||
padding: 0 5vw;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
@@ -213,6 +213,9 @@
|
||||
}
|
||||
|
||||
/* Game Section */
|
||||
#gameSection {
|
||||
margin: 0 auto;
|
||||
}
|
||||
#gameSection .row.round {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -413,13 +416,16 @@
|
||||
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.life-controls {
|
||||
.life-gain-controls,
|
||||
.life-loss-controls {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
margin-bottom: 1vh;
|
||||
}
|
||||
|
||||
.life-btn {
|
||||
.life-gain-btn,
|
||||
.life-loss-btn {
|
||||
background: var(--tcg-bg-card);
|
||||
border: 2px solid var(--tcg-border-color);
|
||||
color: var(--tcg-text-primary);
|
||||
@@ -436,17 +442,31 @@
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.life-btn:hover {
|
||||
border-color: var(--tcg-accent-purple);
|
||||
background: var(--tcg-accent-purple);
|
||||
.life-gain-btn:hover,
|
||||
.life-loss-btn:hover {
|
||||
border-color: green; /*var(--tcg-accent-purple);*/
|
||||
background: green; /*var(--tcg-accent-purple);*/
|
||||
color: var(--tcg-bg-primary);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.life-btn:active {
|
||||
.life-loss-btn:hover {
|
||||
border-color: red;
|
||||
background: red;
|
||||
}
|
||||
|
||||
.life-gain-btn:active,
|
||||
.life-loss-btn:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.life-total label {
|
||||
color: var(--tcg-text-primary);
|
||||
width: 100%;
|
||||
margin-bottom: 1vh;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Commander Damage Section */
|
||||
.commander-damage-section {
|
||||
border-top: 1px solid var(--tcg-border-color);
|
||||
@@ -486,6 +506,7 @@
|
||||
.damage-source {
|
||||
font-size: 1rem;
|
||||
color: var(--tcg-text-secondary);
|
||||
padding-right: 1vh;
|
||||
}
|
||||
|
||||
.damage-controls {
|
||||
@@ -544,8 +565,10 @@
|
||||
.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 {
|
||||
.damage-log.container table thead tr th.life_gain,
|
||||
.damage-log.container table tbody tr td.life_gain,
|
||||
.damage-log.container table thead tr th.life_loss,
|
||||
.damage-log.container table tbody tr td.life_loss {
|
||||
width: 7vw;
|
||||
}
|
||||
.damage-log.container table thead tr th.commander-deaths,
|
||||
@@ -649,7 +672,8 @@
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.life-btn {
|
||||
.life-gain-btn,
|
||||
.life-loss-btn {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 1.5rem;
|
||||
|
||||
2
static/dist/css/tcg_game.bundle.css.map
vendored
2
static/dist/css/tcg_game.bundle.css.map
vendored
File diff suppressed because one or more lines are too long
59
static/dist/css/tcg_games.bundle.css
vendored
59
static/dist/css/tcg_games.bundle.css
vendored
@@ -14,7 +14,7 @@
|
||||
|
||||
/* Main Table */
|
||||
#pageBody {
|
||||
max-height: 77vh;
|
||||
max-height: 82vh;
|
||||
padding: 0 5vw;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
@@ -99,15 +99,18 @@
|
||||
position: relative;
|
||||
animation: tcg-fadeIn 0.8s ease-out 0.2s backwards;
|
||||
margin: 2vh auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Filters Form */
|
||||
@@ -154,8 +157,7 @@
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.games-table {
|
||||
width: 100%;
|
||||
#tableMain.games-table {
|
||||
border-collapse: collapse;
|
||||
font-size: 1rem;
|
||||
}
|
||||
@@ -164,7 +166,6 @@
|
||||
background: var(--tcg-bg-card);
|
||||
border-bottom: 2px solid var(--tcg-accent-purple);
|
||||
}
|
||||
|
||||
.games-table th {
|
||||
font-family: 'Cinzel', serif;
|
||||
font-size: 0.95rem;
|
||||
@@ -173,18 +174,22 @@
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
padding: 1rem;
|
||||
text-align: left;
|
||||
}
|
||||
.games-table thead tr {
|
||||
height: 4vh;
|
||||
}
|
||||
|
||||
#tableMain.games-table tbody {
|
||||
max-height: 59vh;
|
||||
}
|
||||
.games-table tbody tr {
|
||||
border-bottom: 1px solid var(--tcg-border-color);
|
||||
transition: all 0.3s ease;
|
||||
height: 4vh;
|
||||
}
|
||||
|
||||
.games-table tbody tr:hover {
|
||||
background: rgba(139, 92, 246, 0.1);
|
||||
}
|
||||
|
||||
.games-table tbody tr.inactive {
|
||||
opacity: 0.5;
|
||||
}
|
||||
@@ -198,7 +203,38 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
.game-id {
|
||||
.games-table thead tr th.game_id,
|
||||
.games-table tbody tr td.game_id {
|
||||
min-width: 10vh;
|
||||
max-width: 10vh;
|
||||
}
|
||||
.games-table thead tr th.is_commander,
|
||||
.games-table tbody tr td.is_commander {
|
||||
min-width: 12vh;
|
||||
max-width: 12vh;
|
||||
}
|
||||
.games-table thead tr th.location_name,
|
||||
.games-table tbody tr td.location_name {
|
||||
min-width: 20vh;
|
||||
max-width: 20vh;
|
||||
}
|
||||
.games-table thead tr th.start_on,
|
||||
.games-table tbody tr td.start_on {
|
||||
min-width: 14vh;
|
||||
max-width: 14vh;
|
||||
}
|
||||
#tableMain.games-table thead tr th.active,
|
||||
#tableMain.games-table tbody tr td.active {
|
||||
min-width: 8vh;
|
||||
max-width: 8vh;
|
||||
}
|
||||
.games-table thead tr th.navMtgGame,
|
||||
.games-table tbody tr td.navMtgGame {
|
||||
min-width: 13vh;
|
||||
max-width: 13vh;
|
||||
}
|
||||
|
||||
.game_id {
|
||||
font-family: 'Cinzel', serif;
|
||||
font-weight: 600;
|
||||
color: var(--tcg-text-secondary);
|
||||
@@ -289,7 +325,7 @@
|
||||
|
||||
/* Join Button */
|
||||
.btn-join {
|
||||
padding: 0.5rem 1.25rem;
|
||||
padding: 0.5vh 1vw;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
@@ -331,7 +367,7 @@
|
||||
animation: tcg-fadeIn 0.3s ease-out;
|
||||
}
|
||||
|
||||
.modal-overlay.hidden {
|
||||
.modal-overlay.is_collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -404,7 +440,6 @@
|
||||
}
|
||||
|
||||
.section-header {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
|
||||
2
static/dist/css/tcg_games.bundle.css.map
vendored
2
static/dist/css/tcg_games.bundle.css.map
vendored
File diff suppressed because one or more lines are too long
2
static/dist/css/tcg_home.bundle.css
vendored
2
static/dist/css/tcg_home.bundle.css
vendored
@@ -14,7 +14,7 @@
|
||||
|
||||
/* Main Table */
|
||||
#pageBody {
|
||||
max-height: 77vh;
|
||||
max-height: 82vh;
|
||||
padding: 0 5vw;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
|
||||
2
static/dist/css/tcg_home.bundle.css.map
vendored
2
static/dist/css/tcg_home.bundle.css.map
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"css/tcg_home.bundle.css","mappings":";;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,SAAS;IACT,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C;ACjEA;IACI,iBAAiB;AACrB;AACA;IACI,iBAAiB;IACjB,kBAAkB;AACtB,C","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/tcg/home.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 77vh;\n padding: 0 5vw;\n margin: 0;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n position: absolute;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","#pageBody .column .row {\n margin-top: 0.5vh;\n}\n#pageBody .column .row .button {\n margin-left: auto;\n margin-right: auto;\n}"],"names":[],"sourceRoot":""}
|
||||
{"version":3,"file":"css/tcg_home.bundle.css","mappings":";;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,SAAS;IACT,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C;ACjEA;IACI,iBAAiB;AACrB;AACA;IACI,iBAAiB;IACjB,kBAAkB;AACtB,C","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/tcg/home.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n position: absolute;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","#pageBody .column .row {\n margin-top: 0.5vh;\n}\n#pageBody .column .row .button {\n margin-left: auto;\n margin-right: auto;\n}"],"names":[],"sourceRoot":""}
|
||||
6
static/dist/css/user_account.bundle.css
vendored
6
static/dist/css/user_account.bundle.css
vendored
@@ -14,7 +14,7 @@
|
||||
|
||||
/* Main Table */
|
||||
#pageBody {
|
||||
max-height: 77vh;
|
||||
max-height: 82vh;
|
||||
padding: 0 5vw;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
@@ -89,8 +89,8 @@ label {
|
||||
input.dirty,
|
||||
textarea.dirty,
|
||||
select.dirty {
|
||||
border-color: var(--colour-primary);
|
||||
background-color: var(--colour-page-background-2);
|
||||
border-color: var(--primary-color);
|
||||
background-color: var(--background-color-2);
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=user_account.bundle.css.map*/
|
||||
2
static/dist/css/user_account.bundle.css.map
vendored
2
static/dist/css/user_account.bundle.css.map
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"css/user_account.bundle.css","mappings":";;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,SAAS;IACT,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C;;;AChEA;IACI,aAAa;AACjB;;AAEA;IACI,eAAe;IACf,SAAS;IACT,WAAW;AACf;;AAEA;IACI,cAAc;AAClB;AACA;IACI,iBAAiB;AACrB;AACA;IACI,gBAAgB;AACpB;;AAEA;;;IAGI,mCAAmC;IACnC,iDAAiD;AACrD,C","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/user/user.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 77vh;\n padding: 0 5vw;\n margin: 0;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n position: absolute;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","\n#formFilters {\n display: none;\n}\n\n.container.save.button-cancel {\n position: fixed;\n top: 10vh;\n right: 10vh;\n}\n\n.container-input {\n margin: 0 auto;\n}\nlabel {\n font-weight: bold;\n}\n.container-input input {\n max-width: 250px;\n}\n\ninput.dirty, \ntextarea.dirty, \nselect.dirty {\n border-color: var(--colour-primary);\n background-color: var(--colour-page-background-2);\n}"],"names":[],"sourceRoot":""}
|
||||
{"version":3,"file":"css/user_account.bundle.css","mappings":";;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,SAAS;IACT,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C;;;AChEA;IACI,aAAa;AACjB;;AAEA;IACI,eAAe;IACf,SAAS;IACT,WAAW;AACf;;AAEA;IACI,cAAc;AAClB;AACA;IACI,iBAAiB;AACrB;AACA;IACI,gBAAgB;AACpB;;AAEA;;;IAGI,kCAAkC;IAClC,2CAA2C;AAC/C,C","sources":["webpack://app/./static/css/sections/tcg.css","webpack://app/./static/css/pages/user/user.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n position: absolute;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}","\n#formFilters {\n display: none;\n}\n\n.container.save.button-cancel {\n position: fixed;\n top: 10vh;\n right: 10vh;\n}\n\n.container-input {\n margin: 0 auto;\n}\nlabel {\n font-weight: bold;\n}\n.container-input input {\n max-width: 250px;\n}\n\ninput.dirty, \ntextarea.dirty, \nselect.dirty {\n border-color: var(--primary-color);\n background-color: var(--background-color-2);\n}"],"names":[],"sourceRoot":""}
|
||||
2
static/dist/css/user_accounts.bundle.css
vendored
2
static/dist/css/user_accounts.bundle.css
vendored
@@ -15,7 +15,7 @@
|
||||
|
||||
/* Main Table */
|
||||
#pageBody {
|
||||
max-height: 77vh;
|
||||
max-height: 82vh;
|
||||
padding: 0 5vw;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
|
||||
2
static/dist/css/user_accounts.bundle.css.map
vendored
2
static/dist/css/user_accounts.bundle.css.map
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"css/user_accounts.bundle.css","mappings":";;;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,SAAS;IACT,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C","sources":["webpack://app/./static/css/sections/tcg.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 77vh;\n padding: 0 5vw;\n margin: 0;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n position: absolute;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}"],"names":[],"sourceRoot":""}
|
||||
{"version":3,"file":"css/user_accounts.bundle.css","mappings":";;;AAEA;IACI,gBAAgB;IAChB,oBAAoB;IACpB,cAAc;AAClB;;;AAGA,iBAAiB;AACjB;IACI,sBAAsB;AAC1B;;AAEA,eAAe;AACf;IACI,gBAAgB;IAChB,cAAc;IACd,SAAS;IACT,SAAS;IACT,qBAAqB;IACrB,2BAA2B;IAC3B,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,WAAW;IACX,yBAAyB;AAC7B;;;AAGA,WAAW;AACX;IACI,gBAAgB;IAChB,kBAAkB;IAClB,SAAS;IACT,eAAe;IACf,gBAAgB;IAChB,sCAAsC;IACtC,kBAAkB;IAClB,SAAS;IACT,WAAW;AACf;;AAEA;IACI;QACI,eAAe;QACf,mBAAmB;QACnB,eAAe;QACf,WAAW;QACX,eAAe;IACnB;IACA;QACI,eAAe;IACnB;IACA;QACI,cAAc;IAClB;AACJ;;AAEA;IACI,UAAU;IACV,SAAS;AACb,C","sources":["webpack://app/./static/css/sections/tcg.css"],"sourcesContent":["\n\n.container-input > input {\n padding: 0vh 1vh;\n border-radius: 0.5vh;\n max-width: 7vh;\n}\n\n\n/* Right column */\n.rightcolumn {\n min-width: fit-content;\n}\n\n/* Main Table */\n#pageBody {\n max-height: 82vh;\n padding: 0 5vw;\n margin: 0;\n border: 0;\n align-content: center;\n justify-content: flex-start;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n overflow-y: auto;\n overflow-x: hidden;\n position: absolute;\n width: 90vw;\n color: var(--colour-text);\n}\n\n\n/* Footer */\n.footer {\n padding: 1vh 1vw;\n text-align: center;\n margin: 0;\n max-height: 5vh;\n overflow-y: auto;\n background-color: var(--colour-accent);\n position: absolute;\n bottom: 0;\n width: 98vw;\n}\n\n@media screen and (max-width: 400px) {\n .footer {\n max-height: 8vh;\n padding: 0.75vh 2vw;\n font-size: 10px; \n width: 96vw;\n max-width: 96vw;\n }\n .footer > h4 {\n font-size: 10px;\n }\n .footer > h5 {\n font-size: 9px;\n }\n}\n\n.footer > h4, h5 {\n padding: 0;\n margin: 0;\n}"],"names":[],"sourceRoot":""}
|
||||
300
static/dist/js/main.bundle.js
vendored
300
static/dist/js/main.bundle.js
vendored
@@ -746,6 +746,7 @@ class BasePage {
|
||||
// , buttonSave = null, buttonCancel = null
|
||||
if (Validation.isEmpty(buttonContainerSelector)) buttonContainerSelector = '.' + flagContainer + '.' + flagSave + '.' + flagCancel;
|
||||
let buttonSave = document.querySelector(buttonContainerSelector + ' ' + idButtonSave);
|
||||
if (buttonSave == null) return;
|
||||
let buttonCancel = document.querySelector(buttonContainerSelector + ' ' + idButtonCancel);
|
||||
utils_Utils.consoleLogIfNotProductionEnvironment({
|
||||
show,
|
||||
@@ -1116,6 +1117,7 @@ class TableBasePage extends BasePage {
|
||||
cacheRowBlank() {
|
||||
let selectorRowNew = idTableMain + ' tbody tr.' + flagRowNew;
|
||||
let rowBlankTemp = document.querySelector(selectorRowNew);
|
||||
if (rowBlankTemp == null) return;
|
||||
utils_Utils.consoleLogIfNotProductionEnvironment("row blank temp: ", rowBlankTemp);
|
||||
let countRows = document.querySelectorAll(idTableMain + ' > tbody > tr').length;
|
||||
_rowBlank = rowBlankTemp.cloneNode(true);
|
||||
@@ -1524,13 +1526,89 @@ class TableBasePage extends BasePage {
|
||||
DOM.toggleElementHasClassnameFlag(columnTh, isRequiredFlag, classnameFlag);
|
||||
}
|
||||
updateAndToggleShowButtonsSaveCancel() {
|
||||
let pageBody = document.querySelector(idPageBody);
|
||||
// let pageBody = document.querySelector(idPageBody);
|
||||
let isDirty = DOM.hasDirtyChildrenContainer(pageBody);
|
||||
let buttonContainerSelector = '.' + flagContainer + '.' + flagSave + '.' + flagCancel;
|
||||
let buttonSave = document.querySelector(buttonContainerSelector + ' ' + idButtonSave);
|
||||
let areVisibleSaveCancelButtons = !buttonSave.classList.contains(flagIsCollapsed);
|
||||
console.log({
|
||||
pageBody,
|
||||
isDirty
|
||||
isDirty,
|
||||
areVisibleSaveCancelButtons
|
||||
});
|
||||
this.toggleShowButtonsSaveCancel(isDirty);
|
||||
this.toggleShowButtonsSaveCancel(isDirty || areVisibleSaveCancelButtons);
|
||||
}
|
||||
}
|
||||
;// ./static/js/pages/tcg/mtg_decks.js
|
||||
|
||||
|
||||
|
||||
|
||||
class PageMtgDecks extends TableBasePage {
|
||||
static hash = hashPageMtgDecks;
|
||||
static attrIdRowObject = attrDeckId;
|
||||
callSaveTableContent = API.saveDeck;
|
||||
constructor(router) {
|
||||
super(router);
|
||||
}
|
||||
initialize() {
|
||||
this.sharedInitialize();
|
||||
}
|
||||
hookupFilters() {
|
||||
/*
|
||||
this.sharedHookupFilters();
|
||||
this.hookupFilterActive();
|
||||
*/
|
||||
}
|
||||
loadRowTable(rowJson) {
|
||||
if (rowJson == null) return;
|
||||
if (_verbose) {
|
||||
utils_Utils.consoleLogIfNotProductionEnvironment("applying data row: ", rowJson);
|
||||
}
|
||||
}
|
||||
getJsonRow(row) {
|
||||
return;
|
||||
}
|
||||
initialiseRowNew(tbody, row) {}
|
||||
postInitialiseRowNewCallback(tbody) {
|
||||
let newRows = tbody.querySelectorAll('tr.' + flagRowNew);
|
||||
let newestRow = newRows[0];
|
||||
let clickableElementsSelector = ['td.' + attrCommanderBracketId + ' div.' + attrCommanderBracketId].join('');
|
||||
newestRow.querySelectorAll(clickableElementsSelector).forEach(clickableElement => {
|
||||
clickableElement.click();
|
||||
});
|
||||
}
|
||||
hookupTableMain() {
|
||||
super.hookupTableMain();
|
||||
this.hookupTableMainRows();
|
||||
this.hookupFieldsNameTable();
|
||||
this.hookupTableMainIsCommanderCheckboxes();
|
||||
this.hookupTableMainCommanderBracketPreviews();
|
||||
this.hookupFieldsActive();
|
||||
}
|
||||
hookupTableMainRows() {
|
||||
return;
|
||||
// removed by dead control flow
|
||||
|
||||
// removed by dead control flow
|
||||
|
||||
}
|
||||
static toggleShowDeckStatisticsSection(showSection) {
|
||||
let statisticsSectionTableBody = document.querySelector('table.' + flagStatistics + ' tbody');
|
||||
if (showSection) {
|
||||
statisticsSectionTableBody.classList.remove(flagIsCollapsed);
|
||||
} else {
|
||||
statisticsSectionTableBody.classList.add(flagIsCollapsed);
|
||||
}
|
||||
}
|
||||
hookupTableMainIsCommanderCheckboxes() {
|
||||
this.hookupChangeHandlerTableCells(idTableMain + ' td.' + flagIsCommander + ' .' + flagIsCommander);
|
||||
}
|
||||
hookupTableMainCommanderBracketPreviews() {
|
||||
this.hookupTableCellDdlPreviews(attrCommanderBracketId, utils_Utils.getListFromDict(commanderBrackets));
|
||||
}
|
||||
leave() {
|
||||
super.leave();
|
||||
}
|
||||
}
|
||||
;// ./static/js/pages/tcg/mtg_game.js
|
||||
@@ -1698,28 +1776,16 @@ class PageMtgGame extends TableBasePage {
|
||||
const grid = document.getElementById('playersGrid');
|
||||
grid.innerHTML = '';
|
||||
|
||||
// Build a damage lookup: { playerId: { fromPlayerId: damageAmount } }
|
||||
/*
|
||||
const damageLookup = {};
|
||||
damageRecords.forEach(damage => {
|
||||
if (!damageLookup[damage.player_id]) {
|
||||
damageLookup[damage.player_id] = {};
|
||||
}
|
||||
if (damage.received_from_commander_player_id) {
|
||||
damageLookup[damage.player_id][damage.received_from_commander_player_id] = damage.health_change || 0;
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
let activeRoundId = PageMtgGame.getActiveRoundId();
|
||||
// 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();
|
||||
let activeRound = rounds.filter(round => round[flagDisplayOrder] == currentRoundDisplayOrder)[0];
|
||||
if (activeRound == null) {
|
||||
activeRound = PageMtgGame.makeDefaultGameRound(currentRoundDisplayOrder);
|
||||
rounds.push(activeRound);
|
||||
}
|
||||
const latestRound = rounds.filter(round => round[attrRoundId] == activeRoundId)[0];
|
||||
DOM.setElementValueCurrent(roundDisplayOrderLabel, latestRound[flagDisplayOrder]);
|
||||
DOM.setElementValueCurrent(roundDisplayOrderLabel, activeRound[flagDisplayOrder]);
|
||||
const previousRoundIds = rounds.filter(round => round[flagDisplayOrder] <= currentRoundDisplayOrder).map(round => round[attrRoundId]);
|
||||
players.forEach((player, index) => {
|
||||
// Build display name: prefer user_name + deck_name, fallback to player name
|
||||
const playerId = player[attrPlayerId];
|
||||
@@ -1730,17 +1796,26 @@ class PageMtgGame extends TableBasePage {
|
||||
let maxCommanderDamageReceived = 0;
|
||||
damagePlayerPairs.forEach(damagePlayerPair => {
|
||||
const sourceId = damagePlayerPair[attrPlayerId];
|
||||
const filteredPlayerDamages = damageRecords.filter(damage => damage[attrRoundId] == activeRoundId && damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == sourceId); //[playerId] || {};
|
||||
const filteredPlayerDamages = damageRecords.filter(damage => damage[attrRoundId] == activeRound[attrRoundId]
|
||||
// previousRoundIds.includes(damage[attrRoundId])
|
||||
&& damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == sourceId); //[playerId] || {};
|
||||
if (filteredPlayerDamages.length == 0) {
|
||||
damageRecords.push(PageMtgGame.makeDefaultGameRoundPlayerDamage(playerId, sourceId));
|
||||
}
|
||||
maxCommanderDamageReceived = Math.max(maxCommanderDamageReceived, damageRecords.filter(damage => damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == sourceId).map(damage => damage[flagHealthChange]).reduce((acc, curr) => acc + curr, 0));
|
||||
maxCommanderDamageReceived = Math.max(maxCommanderDamageReceived, damageRecords.filter(damage => damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == sourceId && damage[attrReceivedFromCommanderPlayerId] != null && previousRoundIds.includes(damage[attrRoundId])).map(damage => damage[flagLifeLoss]).reduce((a, b) => a + b, 0));
|
||||
});
|
||||
const totalDamage = damageRecords.filter(damage => damage[attrPlayerId] == playerId && previousRoundIds.includes(damage[attrRoundId])).map(damage => damage[flagLifeLoss] - damage[flagLifeGain]).reduce((a, b) => a + b, 0);
|
||||
let life = startingLife - totalDamage;
|
||||
let isEliminatedByForce = damageRecords.filter(damage => damage[attrPlayerId] == playerId && previousRoundIds.includes(damage[attrRoundId])).map(damage => damage[flagIsEliminated]).some(Boolean);
|
||||
console.log("renderPlayers");
|
||||
console.log({
|
||||
isEliminatedByForce,
|
||||
player,
|
||||
life,
|
||||
maxCommanderDamageReceived
|
||||
});
|
||||
const totalDamage = damageRecords.filter(damage => damage[attrPlayerId] == playerId).map(damage => damage[flagHealthChange]).reduce((acc, curr) => acc + curr, 0);
|
||||
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] == activeRoundId)[0];
|
||||
const totalCommanderDeaths = damageRecords.filter(damage => damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == null && damage[attrRoundId] == activeRound[attrRoundId]).map(damage => damage[flagCommanderDeaths]).reduce((a, b) => a + b, 0);
|
||||
const card = document.createElement('div');
|
||||
card.className = `player-card ${isEliminated ? 'eliminated' : ''}`;
|
||||
card.style.animationDelay = `${index * 0.1}s`;
|
||||
@@ -1755,7 +1830,7 @@ class PageMtgGame extends TableBasePage {
|
||||
<span>Commander Deaths:</span>
|
||||
<div class="death-counter">
|
||||
<button class="death-btn death-minus" data-player-id="${playerId}">−</button>
|
||||
<span class="death-display" data-player-id="${playerId}" ${attrValuePrevious}="${playerOwnDamage[flagCommanderDeaths]}">${playerOwnDamage[flagCommanderDeaths]}</span>
|
||||
<span class="death-display" data-player-id="${playerId}" ${attrValuePrevious}="${totalCommanderDeaths}">${totalCommanderDeaths}</span>
|
||||
<button class="death-btn death-plus" data-player-id="${playerId}">+</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1768,11 +1843,19 @@ class PageMtgGame extends TableBasePage {
|
||||
<div class="life-total">
|
||||
<input type="hidden" class="life-value" data-player-id="${playerId}" value="${life}">
|
||||
<div class="life-display" data-player-id="${playerId}" ${attrValuePrevious}="${life}">${life}</div>
|
||||
<div class="life-controls">
|
||||
<button class="life-btn" data-player-id="${playerId}" data-amount="-5">-5</button>
|
||||
<button class="life-btn" data-player-id="${playerId}" data-amount="-1">-1</button>
|
||||
<button class="life-btn" data-player-id="${playerId}" data-amount="1">+1</button>
|
||||
<button class="life-btn" data-player-id="${playerId}" data-amount="5">+5</button>
|
||||
<label>Gain</label>
|
||||
<div class="life-gain-controls">
|
||||
<button class="life-gain-btn" data-player-id="${playerId}" data-amount="-5">-5</button>
|
||||
<button class="life-gain-btn" data-player-id="${playerId}" data-amount="-1">-1</button>
|
||||
<button class="life-gain-btn" data-player-id="${playerId}" data-amount="1">+1</button>
|
||||
<button class="life-gain-btn" data-player-id="${playerId}" data-amount="5">+5</button>
|
||||
</div>
|
||||
<label>Loss</label>
|
||||
<div class="life-loss-controls">
|
||||
<button class="life-loss-btn" data-player-id="${playerId}" data-amount="-5">-5</button>
|
||||
<button class="life-loss-btn" data-player-id="${playerId}" data-amount="-1">-1</button>
|
||||
<button class="life-loss-btn" data-player-id="${playerId}" data-amount="1">+1</button>
|
||||
<button class="life-loss-btn" data-player-id="${playerId}" data-amount="5">+5</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1795,13 +1878,15 @@ class PageMtgGame extends TableBasePage {
|
||||
this.hookupPlayerCardEvents();
|
||||
}
|
||||
static renderCommanderDamageLog() {
|
||||
const roundDisplayOrderLabel = PageMtgGame.getRoundDisplayOrderLabel();
|
||||
const currentRoundDisplayOrder = Number(DOM.getElementValueCurrent(roundDisplayOrderLabel));
|
||||
const currentRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();
|
||||
const damageTableBody = document.querySelector('.' + flagDamageLog + '.' + flagContainer + ' table tbody');
|
||||
damageTableBody.innerHTML = '';
|
||||
const previousRoundIds = rounds.filter(round => round[flagDisplayOrder] <= currentRoundDisplayOrder).map(round => round[attrRoundId]);
|
||||
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) {
|
||||
if (damage[flagActive] && (damage[flagCommanderDeaths] > 0 || damage[flagLifeGain] != 0 || damage[flagLifeLoss] != 0 || damage[flagIsEliminated])
|
||||
// && rounds.filter(r => r[attrRoundId] == damage[attrRoundId])[0][flagDisplayOrder] <= currentRoundDisplayOrder
|
||||
&& previousRoundIds.includes(damage[attrRoundId])) {
|
||||
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 ? {
|
||||
@@ -1812,7 +1897,8 @@ class PageMtgGame extends TableBasePage {
|
||||
<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="${flagLifeGain}">${damage[flagLifeGain]}</td>
|
||||
<td class="${flagLifeLoss}">${damage[flagLifeLoss]}</td>
|
||||
<td class="${flagCommanderDeaths}">${damage[flagCommanderDeaths]}</td>
|
||||
<td class="${flagIsEliminated}">${damage[flagIsEliminated]}</td>
|
||||
</tr>
|
||||
@@ -1828,8 +1914,10 @@ class PageMtgGame extends TableBasePage {
|
||||
[attrRoundId]: roundId,
|
||||
[attrPlayerId]: playerId,
|
||||
[attrReceivedFromCommanderPlayerId]: receivedFromCommanderPlayerId,
|
||||
[flagHealthChange]: 0,
|
||||
[flagLifeGain]: 0,
|
||||
[flagLifeLoss]: 0,
|
||||
[flagCommanderDeaths]: 0,
|
||||
[flagIsEliminated]: false,
|
||||
[flagActive]: true
|
||||
};
|
||||
}
|
||||
@@ -1852,10 +1940,13 @@ class PageMtgGame extends TableBasePage {
|
||||
}
|
||||
return roundId;
|
||||
}
|
||||
static getActiveRoundId() {
|
||||
static getActiveRoundDisplayOrder() {
|
||||
const roundDisplayOrderLabel = PageMtgGame.getRoundDisplayOrderLabel();
|
||||
const currentRoundDisplayOrder = Number(DOM.getElementValueCurrent(roundDisplayOrderLabel));
|
||||
let roundId = -1;
|
||||
return Number(DOM.getElementValueCurrent(roundDisplayOrderLabel));
|
||||
}
|
||||
static getActiveRoundId() {
|
||||
const currentRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();
|
||||
let roundId = 0;
|
||||
if (rounds.length > 0) {
|
||||
let filteredRounds = rounds.filter(round => round[flagDisplayOrder] == currentRoundDisplayOrder);
|
||||
if (filteredRounds.length > 0) roundId = filteredRounds[0][attrRoundId];
|
||||
@@ -1878,11 +1969,14 @@ class PageMtgGame extends TableBasePage {
|
||||
return player[flagName] || `${user == null ? 'Error' : user[flagName]} - ${deck == null ? 'Error' : deck[flagName]}`;
|
||||
}
|
||||
static renderCommanderDamageRows(playerId) {
|
||||
// const roundId = PageMtgGame.getLatestRoundId();
|
||||
const activeRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();
|
||||
const previousRoundIds = rounds.filter(round => round[flagDisplayOrder] <= activeRoundDisplayOrder).map(round => round[attrRoundId]);
|
||||
return players.filter(otherPlayer => otherPlayer[attrPlayerId] !== playerId).map(otherPlayer => {
|
||||
const sourceId = otherPlayer[attrPlayerId];
|
||||
let otherPlayerDisplayName = PageMtgGame.makePlayerDisplayName(sourceId);
|
||||
const totalDamage = damageRecords.filter(damage => damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == sourceId).map(damage => -damage[flagHealthChange]).reduce((acc, curr) => acc + curr, 0);
|
||||
const totalDamage = damageRecords.filter(damage => damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == sourceId
|
||||
// && damage[attrRoundId] == roundId
|
||||
&& previousRoundIds.includes(damage[attrRoundId])).map(damage => damage[flagLifeLoss]).reduce((acc, curr) => acc + curr, 0);
|
||||
const isLethal = totalDamage >= 21;
|
||||
return `
|
||||
<div class="damage-row" data-player-id="${playerId}" data-source-id="${sourceId}">
|
||||
@@ -1922,15 +2016,31 @@ class PageMtgGame extends TableBasePage {
|
||||
};
|
||||
}
|
||||
hookupPlayerCardEvents() {
|
||||
// Life buttons
|
||||
let lifeButtonSelector = '.life-btn';
|
||||
Events.hookupEventHandler("click", lifeButtonSelector, (event, button) => {
|
||||
// Life gain buttons
|
||||
let lifeGainButtonSelector = '.life-gain-btn';
|
||||
Events.hookupEventHandler("click", lifeGainButtonSelector, (event, button) => {
|
||||
const playerId = button.dataset.playerId;
|
||||
const amount = parseInt(button.dataset.amount);
|
||||
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 // isLifeGainNotLoss
|
||||
, true // updateDamage
|
||||
, damageIndex // damageIndex
|
||||
);
|
||||
});
|
||||
|
||||
// Life loss buttons
|
||||
let lifeLossButtonSelector = '.life-loss-btn';
|
||||
Events.hookupEventHandler("click", lifeLossButtonSelector, (event, button) => {
|
||||
const playerId = button.dataset.playerId;
|
||||
const amount = parseInt(button.dataset.amount);
|
||||
const activeRoundId = PageMtgGame.getActiveRoundId();
|
||||
const damageIndex = damageRecords.findIndex(damage => damage[attrRoundId] == activeRoundId && damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] == null);
|
||||
this.changeLife(playerId // playerId
|
||||
, amount // amount
|
||||
, false // isLifeGainNotLoss
|
||||
, true // updateDamage
|
||||
, damageIndex // damageIndex
|
||||
);
|
||||
@@ -1962,19 +2072,21 @@ class PageMtgGame extends TableBasePage {
|
||||
this.toggleEliminate(playerId);
|
||||
});
|
||||
}
|
||||
changeLife(playerId, amount, updateDamage = false, damageIndex = null) {
|
||||
changeLife(playerId, amount, isLifeGainNotLoss = false, updateDamage = false, damageIndex = null) {
|
||||
const card = document.querySelector(`.player-card[data-player-id="${playerId}"]`);
|
||||
if (!card || card.classList.contains('eliminated')) return;
|
||||
// if (!card || card.classList.contains('eliminated')) return;
|
||||
|
||||
const lifeInput = card.querySelector(`.life-value[data-player-id="${playerId}"]`);
|
||||
const lifeDisplay = card.querySelector(`.life-display[data-player-id="${playerId}"]`);
|
||||
const currentLife = parseInt(lifeInput.value) || 0;
|
||||
const newLife = Math.max(0, currentLife + amount);
|
||||
const newLife = currentLife + amount * (isLifeGainNotLoss ? 1 : -1);
|
||||
DOM.setElementAttributeValueCurrent(lifeDisplay, newLife);
|
||||
DOM.isElementDirty(lifeDisplay);
|
||||
lifeInput.value = newLife;
|
||||
lifeDisplay.textContent = newLife;
|
||||
if (updateDamage) {
|
||||
damageRecords[damageIndex][flagHealthChange] += amount;
|
||||
let fieldFlag = isLifeGainNotLoss ? flagLifeGain : flagLifeLoss;
|
||||
damageRecords[damageIndex][fieldFlag] += amount;
|
||||
}
|
||||
PageMtgGame.renderCommanderDamageLog();
|
||||
|
||||
@@ -1983,7 +2095,8 @@ class PageMtgGame extends TableBasePage {
|
||||
}
|
||||
changeCommanderDamage(playerId, sourceId, amount) {
|
||||
const card = document.querySelector(`.player-card[data-player-id="${playerId}"]`);
|
||||
if (!card || card.classList.contains('eliminated')) return;
|
||||
// if (!card || card.classList.contains('eliminated')) return;
|
||||
|
||||
const damageInput = card.querySelector(`.damage-value[data-player-id="${playerId}"][data-source-id="${sourceId}"]`);
|
||||
const damageDisplay = card.querySelector(`.damage-display[data-player-id="${playerId}"][data-source-id="${sourceId}"]`);
|
||||
const currentDamage = parseInt(damageInput.value) || 0;
|
||||
@@ -2002,9 +2115,11 @@ class PageMtgGame extends TableBasePage {
|
||||
}
|
||||
const activeRoundId = PageMtgGame.getActiveRoundId();
|
||||
const damageIndex = damageRecords.findIndex(damageRecord => damageRecord[attrRoundId] == activeRoundId && damageRecord[attrPlayerId] == playerId && damageRecord[attrReceivedFromCommanderPlayerId] == sourceId);
|
||||
damageRecords[damageIndex][flagHealthChange] -= amount;
|
||||
damageRecords[damageIndex][flagLifeLoss] += amount;
|
||||
let isLifeGainNotLoss = false;
|
||||
this.changeLife(playerId // playerId
|
||||
, -amount // amount
|
||||
, isLifeGainNotLoss // isLifeGainNotLoss
|
||||
, false // updateDamage
|
||||
, damageIndex // damageIndex
|
||||
);
|
||||
@@ -2012,7 +2127,8 @@ class PageMtgGame extends TableBasePage {
|
||||
}
|
||||
changeCommanderDeaths(playerId, amount) {
|
||||
const card = document.querySelector(`.player-card[data-player-id="${playerId}"]`);
|
||||
if (!card || card.classList.contains('eliminated')) return;
|
||||
// if (!card || card.classList.contains('eliminated')) return;
|
||||
|
||||
const deathDisplay = card.querySelector(`.death-display[data-player-id="${playerId}"]`);
|
||||
const currentDeaths = parseInt(deathDisplay.textContent) || 0;
|
||||
const newDeaths = Math.max(0, currentDeaths + amount);
|
||||
@@ -2064,14 +2180,14 @@ class PageMtgGame extends TableBasePage {
|
||||
[flagDisplayOrder]: index
|
||||
});
|
||||
});
|
||||
let activeRoundId = PageMtgGame.getActiveRoundId();
|
||||
let activeRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();
|
||||
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;
|
||||
isEliminatedAsIntA = PageMtgGame.isPlayerEliminated(playerIdA, activeRoundDisplayOrder) ? 1 : 0;
|
||||
isEliminatedAsIntB = PageMtgGame.isPlayerEliminated(playerIdB, activeRoundDisplayOrder) ? 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]);
|
||||
@@ -2085,18 +2201,31 @@ class PageMtgGame extends TableBasePage {
|
||||
});
|
||||
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;
|
||||
static isPlayerEliminated(playerId, roundDisplayOrder = null) {
|
||||
if (roundDisplayOrder == null) roundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();
|
||||
const filteredRoundIds = rounds.filter(round => round[flagDisplayOrder] <= roundDisplayOrder).map(round => round[attrRoundId]);
|
||||
let hasDamageWithIsEliminated = damageRecords.filter(damage =>
|
||||
// damage[attrRoundId] <= roundDisplayOrder
|
||||
filteredRoundIds.includes(damage[attrRoundId]) && 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 => {
|
||||
damageRecords.filter(damage =>
|
||||
// damage[attrRoundId] <= roundId
|
||||
filteredRoundIds.includes(damage[attrRoundId]) && damage[attrPlayerId] == playerId && damage[attrReceivedFromCommanderPlayerId] != null).forEach(damage => {
|
||||
otherPlayerId = damage[attrReceivedFromCommanderPlayerId];
|
||||
damageFromOtherPlayers[otherPlayerId] = damage[flagHealthChange] + (damageFromOtherPlayers[otherPlayerId] == null ? 0 : damageFromOtherPlayers[otherPlayerId]);
|
||||
damageFromOtherPlayers[otherPlayerId] = damage[flagLifeLoss] + (damageFromOtherPlayers[otherPlayerId] == null ? 0 : damageFromOtherPlayers[otherPlayerId]);
|
||||
});
|
||||
let maxDamageFromOtherCommander = Object.keys(damageFromOtherPlayers).map(playerId => damageFromOtherPlayers[playerId]).reduce((acc, cur) => Math.max(acc, cur), 0);
|
||||
let totalDamageTaken = damageRecords.filter(damage =>
|
||||
// damage[attrRoundId] <= roundId
|
||||
filteredRoundIds.includes(damage[attrRoundId]) && damage[attrPlayerId] == playerId).map(damage => damage[flagLifeLoss] - damage[flagLifeGain]).reduce((a, b) => a + b, 0);
|
||||
console.log({
|
||||
roundDisplayOrder,
|
||||
filteredRoundIds,
|
||||
hasDamageWithIsEliminated,
|
||||
maxDamageFromOtherCommander,
|
||||
totalDamageTaken
|
||||
});
|
||||
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() {
|
||||
@@ -2156,7 +2285,8 @@ class PageMtgGame extends TableBasePage {
|
||||
nameInput = playerSetupWrapper.querySelector('.playerName input');
|
||||
userId = DOM.getElementValueCurrent(userDdl);
|
||||
deckId = DOM.getElementValueCurrent(deckDdl);
|
||||
name = nameInput ? nameInput.value.trim() || `Player ${i + 1}` : `Player ${i + 1}`;
|
||||
name = nameInput ? nameInput.value.trim() || null : null; // `Player ${i + 1}` : `Player ${i + 1}`;
|
||||
|
||||
playerId = playerSetupWrapper.getAttribute(attrPlayerId);
|
||||
player = players.filter(p => p[attrPlayerId] == playerId)[0];
|
||||
playersToSave.push({
|
||||
@@ -2272,12 +2402,32 @@ class PageMtgGames extends TableBasePage {
|
||||
}
|
||||
initialize() {
|
||||
this.sharedInitialize();
|
||||
}
|
||||
hookupFilters() {
|
||||
/*
|
||||
this.sharedHookupFilters();
|
||||
this.hookupFilterActive();
|
||||
*/
|
||||
}
|
||||
loadRowTable(rowJson) {
|
||||
if (rowJson == null) return;
|
||||
if (_verbose) {
|
||||
utils_Utils.consoleLogIfNotProductionEnvironment("applying data row: ", rowJson);
|
||||
}
|
||||
}
|
||||
getJsonRow(row) {
|
||||
return;
|
||||
}
|
||||
initialiseRowNew(tbody, row) {}
|
||||
postInitialiseRowNewCallback(tbody) {}
|
||||
hookupTableMain() {
|
||||
super.hookupTableMain();
|
||||
// this.hookupTableMainRows();
|
||||
this.hookupTcgGames();
|
||||
// PageMtgGames.hideNewGameForm();
|
||||
}
|
||||
hookupTcgGames() {
|
||||
this.initGamesPage();
|
||||
}
|
||||
initGamesPage() {
|
||||
console.log("hookupTableMain PageMtgGames");
|
||||
// Initialize form submission
|
||||
const newGameForm = document.getElementById('newGameForm');
|
||||
if (newGameForm) {
|
||||
@@ -2322,7 +2472,7 @@ class PageMtgGames extends TableBasePage {
|
||||
static showNewGameForm() {
|
||||
const modal = document.getElementById('newGameModal');
|
||||
if (modal) {
|
||||
modal.classList.remove('hidden');
|
||||
modal.classList.remove(flagIsCollapsed);
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
// Focus on first input
|
||||
@@ -2335,7 +2485,7 @@ class PageMtgGames extends TableBasePage {
|
||||
static hideNewGameForm() {
|
||||
const modal = document.getElementById('newGameModal');
|
||||
if (modal) {
|
||||
modal.classList.add('hidden');
|
||||
modal.classList.add(flagIsCollapsed);
|
||||
document.body.style.overflow = '';
|
||||
|
||||
// Reset form
|
||||
@@ -2425,7 +2575,7 @@ class PageMtgGames extends TableBasePage {
|
||||
if (errorLabel) {
|
||||
errorLabel.textContent = message;
|
||||
}
|
||||
errorOverlay.classList.remove('hidden');
|
||||
errorOverlay.classList.remove(flagIsCollapsed);
|
||||
errorOverlay.style.display = 'flex';
|
||||
} else {
|
||||
// Fallback to alert
|
||||
@@ -2754,6 +2904,7 @@ class PageUsers extends TableBasePage {
|
||||
|
||||
|
||||
|
||||
|
||||
// Legal
|
||||
|
||||
|
||||
@@ -2774,6 +2925,10 @@ class Router {
|
||||
this.pages = {};
|
||||
// Core
|
||||
// TCG
|
||||
this.pages[hashPageMtgDecks] = {
|
||||
name: 'PageMtgDecks',
|
||||
module: PageMtgDecks
|
||||
};
|
||||
this.pages[hashPageMtgGame] = {
|
||||
name: 'PageMtgGame',
|
||||
module: PageMtgGame
|
||||
@@ -2818,6 +2973,7 @@ class Router {
|
||||
this.routes = {};
|
||||
// Core
|
||||
// TCG
|
||||
this.routes[hashPageMtgDecks] = (isPopState = false) => this.navigateToHash(hashPageMtgDecks, isPopState);
|
||||
this.routes[hashPageMtgGame] = (isPopState = false) => this.navigateToHash(hashPageMtgGame, isPopState);
|
||||
this.routes[hashPageMtgGames] = (isPopState = false) => this.navigateToHash(hashPageMtgGames, isPopState);
|
||||
this.routes[hashPageMtgHome] = (isPopState = false) => this.navigateToHash(hashPageMtgHome, isPopState);
|
||||
|
||||
2
static/dist/js/main.bundle.js.map
vendored
2
static/dist/js/main.bundle.js.map
vendored
File diff suppressed because one or more lines are too long
17
static/dist/js/tcg_decks.bundle.js
vendored
Normal file
17
static/dist/js/tcg_decks.bundle.js
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
// This entry needs to be wrapped in an IIFE because it needs to be isolated against other entry modules.
|
||||
(() => {
|
||||
// extracted by mini-css-extract-plugin
|
||||
|
||||
})();
|
||||
|
||||
// This entry needs to be wrapped in an IIFE because it needs to be isolated against other entry modules.
|
||||
(() => {
|
||||
// extracted by mini-css-extract-plugin
|
||||
|
||||
})();
|
||||
|
||||
/******/ })()
|
||||
;
|
||||
//# sourceMappingURL=tcg_decks.bundle.js.map
|
||||
1
static/dist/js/tcg_decks.bundle.js.map
vendored
Normal file
1
static/dist/js/tcg_decks.bundle.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"js/tcg_decks.bundle.js","mappings":";;;;AAAA;;;;;;ACAA","sources":["webpack://app/./static/css/sections/tcg.css?b213","webpack://app/./static/css/pages/tcg/decks.css?c1be"],"sourcesContent":["// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};"],"names":[],"sourceRoot":""}
|
||||
@@ -150,6 +150,7 @@ export default class BasePage {
|
||||
toggleShowButtonsSaveCancel(show, buttonContainerSelector = null) { // , buttonSave = null, buttonCancel = null
|
||||
if (Validation.isEmpty(buttonContainerSelector)) buttonContainerSelector = '.' + flagContainer + '.' + flagSave + '.' + flagCancel;
|
||||
let buttonSave = document.querySelector(buttonContainerSelector + ' ' + idButtonSave);
|
||||
if (buttonSave == null) return;
|
||||
let buttonCancel = document.querySelector(buttonContainerSelector + ' ' + idButtonCancel);
|
||||
Utils.consoleLogIfNotProductionEnvironment({ show, buttonContainerSelector, buttonCancel, buttonSave });
|
||||
if (show) {
|
||||
|
||||
@@ -335,6 +335,7 @@ export default class TableBasePage extends BasePage {
|
||||
cacheRowBlank() {
|
||||
let selectorRowNew = idTableMain + ' tbody tr.' + flagRowNew;
|
||||
let rowBlankTemp = document.querySelector(selectorRowNew);
|
||||
if (rowBlankTemp == null) return;
|
||||
Utils.consoleLogIfNotProductionEnvironment("row blank temp: ", rowBlankTemp);
|
||||
let countRows = document.querySelectorAll(idTableMain + ' > tbody > tr').length;
|
||||
_rowBlank = rowBlankTemp.cloneNode(true);
|
||||
@@ -734,11 +735,15 @@ export default class TableBasePage extends BasePage {
|
||||
}
|
||||
|
||||
updateAndToggleShowButtonsSaveCancel() {
|
||||
let pageBody = document.querySelector(idPageBody);
|
||||
// let pageBody = document.querySelector(idPageBody);
|
||||
let isDirty = DOM.hasDirtyChildrenContainer(pageBody);
|
||||
|
||||
console.log({ pageBody, isDirty });
|
||||
let buttonContainerSelector = '.' + flagContainer + '.' + flagSave + '.' + flagCancel;
|
||||
let buttonSave = document.querySelector(buttonContainerSelector + ' ' + idButtonSave);
|
||||
let areVisibleSaveCancelButtons = !buttonSave.classList.contains(flagIsCollapsed);
|
||||
|
||||
this.toggleShowButtonsSaveCancel(isDirty);
|
||||
console.log({ pageBody, isDirty, areVisibleSaveCancelButtons });
|
||||
|
||||
this.toggleShowButtonsSaveCancel(isDirty || areVisibleSaveCancelButtons);
|
||||
}
|
||||
}
|
||||
|
||||
110
static/js/pages/tcg/mtg_decks.js
Normal file
110
static/js/pages/tcg/mtg_decks.js
Normal file
@@ -0,0 +1,110 @@
|
||||
|
||||
import API from "../../api.js";
|
||||
import Events from "../../lib/events.js";
|
||||
import TableBasePage from "../base_table.js";
|
||||
import Utils from "../../lib/utils.js";
|
||||
|
||||
export default class PageMtgDecks extends TableBasePage {
|
||||
static hash = hashPageMtgDecks;
|
||||
static attrIdRowObject = attrDeckId;
|
||||
callSaveTableContent = API.saveDeck;
|
||||
|
||||
constructor(router) {
|
||||
super(router);
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this.sharedInitialize();
|
||||
}
|
||||
hookupFilters() {
|
||||
/*
|
||||
this.sharedHookupFilters();
|
||||
this.hookupFilterActive();
|
||||
*/
|
||||
}
|
||||
|
||||
loadRowTable(rowJson) {
|
||||
if (rowJson == null) return;
|
||||
if (_verbose) { Utils.consoleLogIfNotProductionEnvironment("applying data row: ", rowJson); }
|
||||
}
|
||||
getJsonRow(row) {
|
||||
return;
|
||||
}
|
||||
initialiseRowNew(tbody, row) {
|
||||
}
|
||||
postInitialiseRowNewCallback(tbody) {
|
||||
let newRows = tbody.querySelectorAll('tr.' + flagRowNew);
|
||||
let newestRow = newRows[0];
|
||||
let clickableElementsSelector = [
|
||||
'td.' + attrCommanderBracketId + ' div.' + attrCommanderBracketId
|
||||
].join('');
|
||||
newestRow.querySelectorAll(clickableElementsSelector).forEach((clickableElement) => {
|
||||
clickableElement.click();
|
||||
});
|
||||
}
|
||||
|
||||
hookupTableMain() {
|
||||
super.hookupTableMain();
|
||||
this.hookupTableMainRows();
|
||||
this.hookupFieldsNameTable();
|
||||
this.hookupTableMainIsCommanderCheckboxes();
|
||||
this.hookupTableMainCommanderBracketPreviews();
|
||||
this.hookupFieldsActive();
|
||||
}
|
||||
hookupTableMainRows() {
|
||||
return;
|
||||
let rowSelector = 'table.' + flagTableMain + ' tbody tr';
|
||||
Events.hookupEventHandler("click", rowSelector, (event, row) => {
|
||||
let isRowExpanded = row.classList.contains(flagActive);
|
||||
let showSection;
|
||||
if (isRowExpanded) {
|
||||
showSection = false;
|
||||
PageMtgDecks.toggleShowDeckStatisticsSection(showSection);
|
||||
}
|
||||
else {
|
||||
showSection = true;
|
||||
let deckId = row.getAttribute(attrDeckId);
|
||||
let statisticsSectionTableBody = document.querySelector('table.' + flagStatistics + ' tbody');
|
||||
statisticsSectionTableBody.innerHTML = '';
|
||||
let deck = decks.filter(d => d[attrDeckId] == deckId)[0];
|
||||
if (deck[flagStatistics].length > 0) {
|
||||
let newStatisticRowsHtml = '';
|
||||
deck[flagStatistics]
|
||||
.sort((a, b) => a[flagDisplayOrder] - b[flagDisplayOrder])
|
||||
.forEach((statistic) => {
|
||||
newStatisticRowsHtml += `
|
||||
<tr ${attrStatisticId}="${statistic[attrStatisticId]}">
|
||||
<td class="${flagName}">${statistic[flagName]}</td>
|
||||
<td class="${flagValue}">${statistic[flagValue]}</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
statisticsSectionTableBody.innerHTML = newStatisticRowsHtml;
|
||||
}
|
||||
PageMtgDecks.toggleShowDeckStatisticsSection(showSection);
|
||||
}
|
||||
});
|
||||
}
|
||||
static toggleShowDeckStatisticsSection(showSection) {
|
||||
let statisticsSectionTableBody = document.querySelector('table.' + flagStatistics + ' tbody');
|
||||
if (showSection) {
|
||||
statisticsSectionTableBody.classList.remove(flagIsCollapsed);
|
||||
}
|
||||
else {
|
||||
statisticsSectionTableBody.classList.add(flagIsCollapsed);
|
||||
}
|
||||
}
|
||||
hookupTableMainIsCommanderCheckboxes() {
|
||||
this.hookupChangeHandlerTableCells(idTableMain + ' td.' + flagIsCommander + ' .' + flagIsCommander);
|
||||
}
|
||||
hookupTableMainCommanderBracketPreviews() {
|
||||
this.hookupTableCellDdlPreviews(
|
||||
attrCommanderBracketId
|
||||
, Utils.getListFromDict(commanderBrackets)
|
||||
);
|
||||
}
|
||||
|
||||
leave() {
|
||||
super.leave();
|
||||
}
|
||||
}
|
||||
@@ -196,29 +196,18 @@ export default class PageMtgGame extends TableBasePage {
|
||||
const grid = document.getElementById('playersGrid');
|
||||
grid.innerHTML = '';
|
||||
|
||||
// Build a damage lookup: { playerId: { fromPlayerId: damageAmount } }
|
||||
/*
|
||||
const damageLookup = {};
|
||||
damageRecords.forEach(damage => {
|
||||
if (!damageLookup[damage.player_id]) {
|
||||
damageLookup[damage.player_id] = {};
|
||||
}
|
||||
if (damage.received_from_commander_player_id) {
|
||||
damageLookup[damage.player_id][damage.received_from_commander_player_id] = damage.health_change || 0;
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
let activeRoundId = PageMtgGame.getActiveRoundId();
|
||||
// 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();
|
||||
let activeRound = rounds.filter(round => round[flagDisplayOrder] == currentRoundDisplayOrder)[0];
|
||||
if (activeRound == null) {
|
||||
activeRound = PageMtgGame.makeDefaultGameRound(currentRoundDisplayOrder);
|
||||
rounds.push(activeRound);
|
||||
}
|
||||
const latestRound = rounds.filter(round => round[attrRoundId] == activeRoundId)[0];
|
||||
DOM.setElementValueCurrent(roundDisplayOrderLabel, latestRound[flagDisplayOrder]);
|
||||
DOM.setElementValueCurrent(roundDisplayOrderLabel, activeRound[flagDisplayOrder]);
|
||||
|
||||
const previousRoundIds = rounds.filter(round => round[flagDisplayOrder] <= currentRoundDisplayOrder)
|
||||
.map(round => round[attrRoundId]);
|
||||
players.forEach((player, index) => {
|
||||
// Build display name: prefer user_name + deck_name, fallback to player name
|
||||
const playerId = player[attrPlayerId];
|
||||
@@ -228,7 +217,8 @@ export default class PageMtgGame extends TableBasePage {
|
||||
damagePlayerPairs.forEach(damagePlayerPair => {
|
||||
const sourceId = damagePlayerPair[attrPlayerId];
|
||||
const filteredPlayerDamages = damageRecords.filter(damage => (
|
||||
damage[attrRoundId] == activeRoundId
|
||||
damage[attrRoundId] == activeRound[attrRoundId]
|
||||
// previousRoundIds.includes(damage[attrRoundId])
|
||||
&& damage[attrPlayerId] == playerId
|
||||
&& damage[attrReceivedFromCommanderPlayerId] == sourceId
|
||||
)); //[playerId] || {};
|
||||
@@ -240,20 +230,30 @@ export default class PageMtgGame extends TableBasePage {
|
||||
, damageRecords.filter(damage => (
|
||||
damage[attrPlayerId] == playerId
|
||||
&& damage[attrReceivedFromCommanderPlayerId] == sourceId
|
||||
&& damage[attrReceivedFromCommanderPlayerId] != null
|
||||
&& previousRoundIds.includes(damage[attrRoundId])
|
||||
))
|
||||
.map(damage => damage[flagHealthChange])
|
||||
.reduce((acc, curr) => acc + curr, 0)
|
||||
.map(damage => damage[flagLifeLoss])
|
||||
.reduce((a, b) => a + b, 0)
|
||||
);
|
||||
});
|
||||
|
||||
const totalDamage = damageRecords.filter(damage => ( damage[attrPlayerId] == playerId ))
|
||||
.map(damage => damage[flagHealthChange])
|
||||
.reduce((acc, curr) => acc + curr, 0);
|
||||
let life = startingLife + totalDamage;
|
||||
const totalDamage = damageRecords.filter(damage => (
|
||||
damage[attrPlayerId] == playerId
|
||||
&& previousRoundIds.includes(damage[attrRoundId])
|
||||
))
|
||||
.map(damage => damage[flagLifeLoss] - damage[flagLifeGain])
|
||||
.reduce((a, b) => a + b, 0);
|
||||
let life = startingLife - totalDamage;
|
||||
|
||||
let isEliminatedByForce = damageRecords.filter(damage => ( damage[attrPlayerId] == playerId ))
|
||||
let isEliminatedByForce = damageRecords.filter(damage => (
|
||||
damage[attrPlayerId] == playerId
|
||||
&& previousRoundIds.includes(damage[attrRoundId])
|
||||
))
|
||||
.map(damage => damage[flagIsEliminated])
|
||||
.some(Boolean);
|
||||
console.log("renderPlayers");
|
||||
console.log({isEliminatedByForce, player, life, maxCommanderDamageReceived});
|
||||
const isEliminated = (
|
||||
isEliminatedByForce
|
||||
|| !player[flagActive]
|
||||
@@ -261,11 +261,13 @@ export default class PageMtgGame extends TableBasePage {
|
||||
|| maxCommanderDamageReceived >= 21
|
||||
);
|
||||
|
||||
const playerOwnDamage = damageRecords.filter(damage => (
|
||||
const totalCommanderDeaths = damageRecords.filter(damage => (
|
||||
damage[attrPlayerId] == playerId
|
||||
&& damage[attrReceivedFromCommanderPlayerId] == null
|
||||
&& damage[attrRoundId] == activeRoundId
|
||||
))[0];
|
||||
&& damage[attrRoundId] == activeRound[attrRoundId]
|
||||
))
|
||||
.map(damage => damage[flagCommanderDeaths])
|
||||
.reduce((a, b) => a + b, 0);
|
||||
const card = document.createElement('div');
|
||||
card.className = `player-card ${isEliminated ? 'eliminated' : ''}`;
|
||||
card.style.animationDelay = `${index * 0.1}s`;
|
||||
@@ -281,7 +283,7 @@ export default class PageMtgGame extends TableBasePage {
|
||||
<span>Commander Deaths:</span>
|
||||
<div class="death-counter">
|
||||
<button class="death-btn death-minus" data-player-id="${playerId}">−</button>
|
||||
<span class="death-display" data-player-id="${playerId}" ${attrValuePrevious}="${playerOwnDamage[flagCommanderDeaths]}">${playerOwnDamage[flagCommanderDeaths]}</span>
|
||||
<span class="death-display" data-player-id="${playerId}" ${attrValuePrevious}="${totalCommanderDeaths}">${totalCommanderDeaths}</span>
|
||||
<button class="death-btn death-plus" data-player-id="${playerId}">+</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -294,11 +296,19 @@ export default class PageMtgGame extends TableBasePage {
|
||||
<div class="life-total">
|
||||
<input type="hidden" class="life-value" data-player-id="${playerId}" value="${life}">
|
||||
<div class="life-display" data-player-id="${playerId}" ${attrValuePrevious}="${life}">${life}</div>
|
||||
<div class="life-controls">
|
||||
<button class="life-btn" data-player-id="${playerId}" data-amount="-5">-5</button>
|
||||
<button class="life-btn" data-player-id="${playerId}" data-amount="-1">-1</button>
|
||||
<button class="life-btn" data-player-id="${playerId}" data-amount="1">+1</button>
|
||||
<button class="life-btn" data-player-id="${playerId}" data-amount="5">+5</button>
|
||||
<label>Gain</label>
|
||||
<div class="life-gain-controls">
|
||||
<button class="life-gain-btn" data-player-id="${playerId}" data-amount="-5">-5</button>
|
||||
<button class="life-gain-btn" data-player-id="${playerId}" data-amount="-1">-1</button>
|
||||
<button class="life-gain-btn" data-player-id="${playerId}" data-amount="1">+1</button>
|
||||
<button class="life-gain-btn" data-player-id="${playerId}" data-amount="5">+5</button>
|
||||
</div>
|
||||
<label>Loss</label>
|
||||
<div class="life-loss-controls">
|
||||
<button class="life-loss-btn" data-player-id="${playerId}" data-amount="-5">-5</button>
|
||||
<button class="life-loss-btn" data-player-id="${playerId}" data-amount="-1">-1</button>
|
||||
<button class="life-loss-btn" data-player-id="${playerId}" data-amount="1">+1</button>
|
||||
<button class="life-loss-btn" data-player-id="${playerId}" data-amount="5">+5</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -325,22 +335,25 @@ export default class PageMtgGame extends TableBasePage {
|
||||
this.hookupPlayerCardEvents();
|
||||
}
|
||||
static renderCommanderDamageLog() {
|
||||
const roundDisplayOrderLabel = PageMtgGame.getRoundDisplayOrderLabel();
|
||||
const currentRoundDisplayOrder = Number(DOM.getElementValueCurrent(roundDisplayOrderLabel));
|
||||
const currentRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();
|
||||
|
||||
const damageTableBody = document.querySelector('.' + flagDamageLog + '.' + flagContainer + ' table tbody');
|
||||
damageTableBody.innerHTML = '';
|
||||
|
||||
const previousRoundIds = rounds.filter(round => round[flagDisplayOrder] <= currentRoundDisplayOrder)
|
||||
.map(round => round[attrRoundId]);
|
||||
let newTableBodyHtml = '';
|
||||
damageRecords.forEach((damage) => {
|
||||
if (
|
||||
damage[flagActive]
|
||||
&& (
|
||||
damage[flagCommanderDeaths] > 0
|
||||
|| damage[flagHealthChange] != 0
|
||||
|| damage[flagLifeGain] != 0
|
||||
|| damage[flagLifeLoss] != 0
|
||||
|| damage[flagIsEliminated]
|
||||
)
|
||||
&& rounds.filter(r => r[attrRoundId] == damage[attrRoundId])[0][flagDisplayOrder] <= currentRoundDisplayOrder
|
||||
// && rounds.filter(r => r[attrRoundId] == damage[attrRoundId])[0][flagDisplayOrder] <= currentRoundDisplayOrder
|
||||
&& previousRoundIds.includes(damage[attrRoundId])
|
||||
) {
|
||||
let round = rounds.filter(r => r[attrRoundId] == damage[attrRoundId])[0];
|
||||
let player = players.filter(p => p[attrPlayerId] == damage[attrPlayerId])[0];
|
||||
@@ -350,7 +363,8 @@ export default class PageMtgGame extends TableBasePage {
|
||||
<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="${flagLifeGain}">${damage[flagLifeGain]}</td>
|
||||
<td class="${flagLifeLoss}">${damage[flagLifeLoss]}</td>
|
||||
<td class="${flagCommanderDeaths}">${damage[flagCommanderDeaths]}</td>
|
||||
<td class="${flagIsEliminated}">${damage[flagIsEliminated]}</td>
|
||||
</tr>
|
||||
@@ -366,8 +380,10 @@ export default class PageMtgGame extends TableBasePage {
|
||||
, [attrRoundId]: roundId
|
||||
, [attrPlayerId]: playerId
|
||||
, [attrReceivedFromCommanderPlayerId]: receivedFromCommanderPlayerId
|
||||
, [flagHealthChange]: 0
|
||||
, [flagLifeGain]: 0
|
||||
, [flagLifeLoss]: 0
|
||||
, [flagCommanderDeaths]: 0
|
||||
, [flagIsEliminated]: false
|
||||
, [flagActive]: true
|
||||
};
|
||||
}
|
||||
@@ -384,10 +400,13 @@ export default class PageMtgGame extends TableBasePage {
|
||||
}
|
||||
return roundId;
|
||||
}
|
||||
static getActiveRoundId() {
|
||||
static getActiveRoundDisplayOrder() {
|
||||
const roundDisplayOrderLabel = PageMtgGame.getRoundDisplayOrderLabel();
|
||||
const currentRoundDisplayOrder = Number(DOM.getElementValueCurrent(roundDisplayOrderLabel));
|
||||
let roundId = -1;
|
||||
return Number(DOM.getElementValueCurrent(roundDisplayOrderLabel));
|
||||
}
|
||||
static getActiveRoundId() {
|
||||
const currentRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();
|
||||
let roundId = 0;
|
||||
if (rounds.length > 0) {
|
||||
let filteredRounds = rounds.filter(round => round[flagDisplayOrder] == currentRoundDisplayOrder);
|
||||
if (filteredRounds.length > 0) roundId = filteredRounds[0][attrRoundId];
|
||||
@@ -406,7 +425,9 @@ export default class PageMtgGame extends TableBasePage {
|
||||
return player[flagName] || `${(user == null) ? 'Error' : user[flagName]} - ${(deck == null) ? 'Error' : deck[flagName]}`;
|
||||
}
|
||||
static renderCommanderDamageRows(playerId) {
|
||||
// const roundId = PageMtgGame.getLatestRoundId();
|
||||
const activeRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();
|
||||
const previousRoundIds = rounds.filter(round => round[flagDisplayOrder] <= activeRoundDisplayOrder)
|
||||
.map(round => round[attrRoundId]);
|
||||
return players
|
||||
.filter(otherPlayer => otherPlayer[attrPlayerId] !== playerId)
|
||||
.map(otherPlayer => {
|
||||
@@ -415,10 +436,12 @@ export default class PageMtgGame extends TableBasePage {
|
||||
const totalDamage = damageRecords.filter(damage => (
|
||||
damage[attrPlayerId] == playerId
|
||||
&& damage[attrReceivedFromCommanderPlayerId] == sourceId
|
||||
// && damage[attrRoundId] == roundId
|
||||
&& previousRoundIds.includes(damage[attrRoundId])
|
||||
))
|
||||
.map(damage => -damage[flagHealthChange])
|
||||
.map(damage => damage[flagLifeLoss])
|
||||
.reduce((acc, curr) => acc + curr, 0);
|
||||
const isLethal = totalDamage >= 21;
|
||||
const isLethal = (totalDamage >= 21);
|
||||
|
||||
return `
|
||||
<div class="damage-row" data-player-id="${playerId}" data-source-id="${sourceId}">
|
||||
@@ -460,9 +483,9 @@ export default class PageMtgGame extends TableBasePage {
|
||||
};
|
||||
}
|
||||
hookupPlayerCardEvents() {
|
||||
// Life buttons
|
||||
let lifeButtonSelector = '.life-btn';
|
||||
Events.hookupEventHandler("click", lifeButtonSelector, (event, button) => {
|
||||
// Life gain buttons
|
||||
let lifeGainButtonSelector = '.life-gain-btn';
|
||||
Events.hookupEventHandler("click", lifeGainButtonSelector, (event, button) => {
|
||||
const playerId = button.dataset.playerId;
|
||||
const amount = parseInt(button.dataset.amount);
|
||||
const activeRoundId = PageMtgGame.getActiveRoundId();
|
||||
@@ -474,6 +497,27 @@ export default class PageMtgGame extends TableBasePage {
|
||||
this.changeLife(
|
||||
playerId // playerId
|
||||
, amount // amount
|
||||
, true // isLifeGainNotLoss
|
||||
, true // updateDamage
|
||||
, damageIndex // damageIndex
|
||||
);
|
||||
});
|
||||
|
||||
// Life loss buttons
|
||||
let lifeLossButtonSelector = '.life-loss-btn';
|
||||
Events.hookupEventHandler("click", lifeLossButtonSelector, (event, button) => {
|
||||
const playerId = button.dataset.playerId;
|
||||
const amount = parseInt(button.dataset.amount);
|
||||
const activeRoundId = PageMtgGame.getActiveRoundId();
|
||||
const damageIndex = damageRecords.findIndex(damage => (
|
||||
damage[attrRoundId] == activeRoundId
|
||||
&& damage[attrPlayerId] == playerId
|
||||
&& damage[attrReceivedFromCommanderPlayerId] == null
|
||||
));
|
||||
this.changeLife(
|
||||
playerId // playerId
|
||||
, amount // amount
|
||||
, false // isLifeGainNotLoss
|
||||
, true // updateDamage
|
||||
, damageIndex // damageIndex
|
||||
);
|
||||
@@ -506,22 +550,24 @@ export default class PageMtgGame extends TableBasePage {
|
||||
});
|
||||
}
|
||||
|
||||
changeLife(playerId, amount, updateDamage = false, damageIndex = null) {
|
||||
changeLife(playerId, amount, isLifeGainNotLoss = false, updateDamage = false, damageIndex = null) {
|
||||
const card = document.querySelector(`.player-card[data-player-id="${playerId}"]`);
|
||||
if (!card || card.classList.contains('eliminated')) return;
|
||||
// if (!card || card.classList.contains('eliminated')) return;
|
||||
|
||||
const lifeInput = card.querySelector(`.life-value[data-player-id="${playerId}"]`);
|
||||
const lifeDisplay = card.querySelector(`.life-display[data-player-id="${playerId}"]`);
|
||||
|
||||
const currentLife = parseInt(lifeInput.value) || 0;
|
||||
const newLife = Math.max(0, currentLife + amount);
|
||||
const newLife = currentLife + amount * ((isLifeGainNotLoss) ? 1 : -1);
|
||||
|
||||
DOM.setElementAttributeValueCurrent(lifeDisplay, newLife);
|
||||
DOM.isElementDirty(lifeDisplay);
|
||||
lifeInput.value = newLife;
|
||||
lifeDisplay.textContent = newLife;
|
||||
|
||||
if (updateDamage) {
|
||||
damageRecords[damageIndex][flagHealthChange] += amount;
|
||||
let fieldFlag = (isLifeGainNotLoss) ? flagLifeGain : flagLifeLoss;
|
||||
damageRecords[damageIndex][fieldFlag] += amount;
|
||||
}
|
||||
|
||||
PageMtgGame.renderCommanderDamageLog();
|
||||
@@ -532,7 +578,7 @@ export default class PageMtgGame extends TableBasePage {
|
||||
|
||||
changeCommanderDamage(playerId, sourceId, amount) {
|
||||
const card = document.querySelector(`.player-card[data-player-id="${playerId}"]`);
|
||||
if (!card || card.classList.contains('eliminated')) return;
|
||||
// if (!card || card.classList.contains('eliminated')) return;
|
||||
|
||||
const damageInput = card.querySelector(`.damage-value[data-player-id="${playerId}"][data-source-id="${sourceId}"]`);
|
||||
const damageDisplay = card.querySelector(`.damage-display[data-player-id="${playerId}"][data-source-id="${sourceId}"]`);
|
||||
@@ -558,11 +604,13 @@ export default class PageMtgGame extends TableBasePage {
|
||||
&& damageRecord[attrPlayerId] == playerId
|
||||
&& damageRecord[attrReceivedFromCommanderPlayerId] == sourceId
|
||||
));
|
||||
damageRecords[damageIndex][flagHealthChange] -= amount;
|
||||
damageRecords[damageIndex][flagLifeLoss] += amount;
|
||||
|
||||
let isLifeGainNotLoss = false;
|
||||
this.changeLife(
|
||||
playerId // playerId
|
||||
, -amount // amount
|
||||
, isLifeGainNotLoss // isLifeGainNotLoss
|
||||
, false // updateDamage
|
||||
, damageIndex // damageIndex
|
||||
);
|
||||
@@ -571,7 +619,7 @@ export default class PageMtgGame extends TableBasePage {
|
||||
|
||||
changeCommanderDeaths(playerId, amount) {
|
||||
const card = document.querySelector(`.player-card[data-player-id="${playerId}"]`);
|
||||
if (!card || card.classList.contains('eliminated')) return;
|
||||
// if (!card || card.classList.contains('eliminated')) return;
|
||||
|
||||
const deathDisplay = card.querySelector(`.death-display[data-player-id="${playerId}"]`);
|
||||
const currentDeaths = parseInt(deathDisplay.textContent) || 0;
|
||||
@@ -641,14 +689,14 @@ export default class PageMtgGame extends TableBasePage {
|
||||
, [flagDisplayOrder]: index
|
||||
});
|
||||
});
|
||||
let activeRoundId = PageMtgGame.getActiveRoundId();
|
||||
let activeRoundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();
|
||||
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;
|
||||
isEliminatedAsIntA = PageMtgGame.isPlayerEliminated(playerIdA, activeRoundDisplayOrder) ? 1 : 0;
|
||||
isEliminatedAsIntB = PageMtgGame.isPlayerEliminated(playerIdB, activeRoundDisplayOrder) ? 1 : 0;
|
||||
playerA = players.filter(p => p[attrPlayerId] == playerIdA)[0];
|
||||
playerB = players.filter(p => p[attrPlayerId] == playerIdB)[0];
|
||||
return (
|
||||
@@ -671,35 +719,41 @@ export default class PageMtgGame extends TableBasePage {
|
||||
|
||||
this.hookupPlayerCardEvents();
|
||||
}
|
||||
static isPlayerEliminated(playerId, roundId = null) {
|
||||
if (roundId == null) roundId = PageMtgGame.getActiveRoundId();
|
||||
static isPlayerEliminated(playerId, roundDisplayOrder = null) {
|
||||
if (roundDisplayOrder == null) roundDisplayOrder = PageMtgGame.getActiveRoundDisplayOrder();
|
||||
const filteredRoundIds = rounds.filter(round => round[flagDisplayOrder] <= roundDisplayOrder)
|
||||
.map(round => round[attrRoundId]);
|
||||
let hasDamageWithIsEliminated = damageRecords.filter(damage => (
|
||||
damage[attrRoundId] <= roundId
|
||||
// damage[attrRoundId] <= roundDisplayOrder
|
||||
filteredRoundIds.includes(damage[attrRoundId])
|
||||
&& damage[attrPlayerId] == playerId
|
||||
&& damage[flagIsEliminated]
|
||||
)).length > 0;
|
||||
let damageFromOtherPlayers = {};
|
||||
let otherPlayerId;
|
||||
damageRecords.filter(damage => (
|
||||
damage[attrRoundId] <= roundId
|
||||
// damage[attrRoundId] <= roundId
|
||||
filteredRoundIds.includes(damage[attrRoundId])
|
||||
&& damage[attrPlayerId] == playerId
|
||||
&& damage[attrReceivedFromCommanderPlayerId] != null
|
||||
))
|
||||
.forEach((damage) => {
|
||||
otherPlayerId = damage[attrReceivedFromCommanderPlayerId];
|
||||
damageFromOtherPlayers[otherPlayerId] =
|
||||
damage[flagHealthChange]
|
||||
damage[flagLifeLoss]
|
||||
+ ((damageFromOtherPlayers[otherPlayerId] == null) ? 0 : damageFromOtherPlayers[otherPlayerId]);
|
||||
});
|
||||
let maxDamageFromOtherCommander = Math.max(Object.keys(damageFromOtherPlayers)
|
||||
.map((playerId) => damageFromOtherPlayers[playerId]));
|
||||
// .reduce((acc, cur) => acc + cur, 0);
|
||||
let maxDamageFromOtherCommander = Object.keys(damageFromOtherPlayers)
|
||||
.map((playerId) => damageFromOtherPlayers[playerId])
|
||||
.reduce((acc, cur) => Math.max(acc, cur), 0);
|
||||
let totalDamageTaken = damageRecords.filter(damage => (
|
||||
damage[attrRoundId] <= roundId
|
||||
// damage[attrRoundId] <= roundId
|
||||
filteredRoundIds.includes(damage[attrRoundId])
|
||||
&& damage[attrPlayerId] == playerId
|
||||
))
|
||||
.map((damage) => damage[flagHealthChange])
|
||||
.reduce((acc, cur) => acc + cur, 0);
|
||||
.map((damage) => damage[flagLifeLoss] - damage[flagLifeGain])
|
||||
.reduce((a, b) => a + b, 0);
|
||||
console.log({ roundDisplayOrder, filteredRoundIds, hasDamageWithIsEliminated, maxDamageFromOtherCommander, totalDamageTaken });
|
||||
return (
|
||||
hasDamageWithIsEliminated
|
||||
|| maxDamageFromOtherCommander >= 21
|
||||
@@ -771,7 +825,7 @@ export default class PageMtgGame extends TableBasePage {
|
||||
|
||||
userId = DOM.getElementValueCurrent(userDdl);
|
||||
deckId = DOM.getElementValueCurrent(deckDdl);
|
||||
name = nameInput ? nameInput.value.trim() || `Player ${i + 1}` : `Player ${i + 1}`;
|
||||
name = nameInput ? nameInput.value.trim() || null : null; // `Player ${i + 1}` : `Player ${i + 1}`;
|
||||
|
||||
playerId = playerSetupWrapper.getAttribute(attrPlayerId);
|
||||
player = players.filter(p => p[attrPlayerId] == playerId)[0];
|
||||
|
||||
@@ -14,12 +14,34 @@ export default class PageMtgGames extends TableBasePage {
|
||||
|
||||
initialize() {
|
||||
this.sharedInitialize();
|
||||
}
|
||||
hookupFilters() {
|
||||
/*
|
||||
this.sharedHookupFilters();
|
||||
this.hookupFilterActive();
|
||||
*/
|
||||
}
|
||||
|
||||
loadRowTable(rowJson) {
|
||||
if (rowJson == null) return;
|
||||
if (_verbose) { Utils.consoleLogIfNotProductionEnvironment("applying data row: ", rowJson); }
|
||||
}
|
||||
getJsonRow(row) {
|
||||
return;
|
||||
}
|
||||
initialiseRowNew(tbody, row) {
|
||||
}
|
||||
postInitialiseRowNewCallback(tbody) {
|
||||
}
|
||||
|
||||
hookupTableMain() {
|
||||
super.hookupTableMain();
|
||||
// this.hookupTableMainRows();
|
||||
this.hookupTcgGames();
|
||||
// PageMtgGames.hideNewGameForm();
|
||||
}
|
||||
hookupTcgGames() {
|
||||
this.initGamesPage();
|
||||
}
|
||||
initGamesPage() {
|
||||
console.log("hookupTableMain PageMtgGames");
|
||||
// Initialize form submission
|
||||
const newGameForm = document.getElementById('newGameForm');
|
||||
if (newGameForm) {
|
||||
@@ -69,7 +91,7 @@ export default class PageMtgGames extends TableBasePage {
|
||||
static showNewGameForm() {
|
||||
const modal = document.getElementById('newGameModal');
|
||||
if (modal) {
|
||||
modal.classList.remove('hidden');
|
||||
modal.classList.remove(flagIsCollapsed);
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
// Focus on first input
|
||||
@@ -82,7 +104,7 @@ export default class PageMtgGames extends TableBasePage {
|
||||
static hideNewGameForm() {
|
||||
const modal = document.getElementById('newGameModal');
|
||||
if (modal) {
|
||||
modal.classList.add('hidden');
|
||||
modal.classList.add(flagIsCollapsed);
|
||||
document.body.style.overflow = '';
|
||||
|
||||
// Reset form
|
||||
@@ -182,7 +204,7 @@ export default class PageMtgGames extends TableBasePage {
|
||||
if (errorLabel) {
|
||||
errorLabel.textContent = message;
|
||||
}
|
||||
errorOverlay.classList.remove('hidden');
|
||||
errorOverlay.classList.remove(flagIsCollapsed);
|
||||
errorOverlay.style.display = 'flex';
|
||||
} else {
|
||||
// Fallback to alert
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Pages
|
||||
// Core
|
||||
// TCG
|
||||
import PageMtgDecks from './pages/tcg/mtg_decks.js';
|
||||
import PageMtgGame from './pages/tcg/mtg_game.js';
|
||||
import PageMtgGames from './pages/tcg/mtg_games.js';
|
||||
import PageMtgHome from './pages/tcg/mtg_home.js';
|
||||
@@ -28,6 +29,7 @@ export default class Router {
|
||||
this.pages = {};
|
||||
// Core
|
||||
// TCG
|
||||
this.pages[hashPageMtgDecks] = { name: 'PageMtgDecks', module: PageMtgDecks };
|
||||
this.pages[hashPageMtgGame] = { name: 'PageMtgGame', module: PageMtgGame };
|
||||
this.pages[hashPageMtgGames] = { name: 'PageMtgGames', module: PageMtgGames };
|
||||
this.pages[hashPageMtgHome] = { name: 'PageMtgGame', module: PageMtgHome };
|
||||
@@ -45,6 +47,7 @@ export default class Router {
|
||||
this.routes = {};
|
||||
// Core
|
||||
// TCG
|
||||
this.routes[hashPageMtgDecks] = (isPopState = false) => this.navigateToHash(hashPageMtgDecks, isPopState);
|
||||
this.routes[hashPageMtgGame] = (isPopState = false) => this.navigateToHash(hashPageMtgGame, isPopState);
|
||||
this.routes[hashPageMtgGames] = (isPopState = false) => this.navigateToHash(hashPageMtgGames, isPopState);
|
||||
this.routes[hashPageMtgHome] = (isPopState = false) => this.navigateToHash(hashPageMtgHome, isPopState);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
{% set value_previous = '0' if is_blank_row else commander_bracket_preview.commander_bracket_id %}
|
||||
{% set text_previous = '' if is_blank_row else commander_bracket_preview.name %}
|
||||
|
||||
<div class="{{ model.ATTR_COMMANDER_BRACKET_ID }}" {{ model.ATTR_VALUE_PREVIOUS }}="{{ value_previous }}" {{ model.ATTR_VALUE_CURRENT }}="{{ value_previous }}">{{ text_previous }}</div>
|
||||
44
templates/components/tcg/_row_deck.html
Normal file
44
templates/components/tcg/_row_deck.html
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
{% if is_blank_row %}
|
||||
<tr class="{{ model.FLAG_ROW_NEW }} {{ model.FLAG_DECK }}" {{ model.ATTR_DECK_ID }}>
|
||||
<td class="{{ model.FLAG_NAME }}">
|
||||
<input type="text"
|
||||
class="{{ model.FLAG_NAME }}"
|
||||
{{ model.ATTR_VALUE_CURRENT }} {{ model.ATTR_VALUE_PREVIOUS }} />
|
||||
</td>
|
||||
<td class="{{ model.FLAG_IS_COMMANDER }}">
|
||||
<input type="checkbox"
|
||||
class="{{ model.FLAG_IS_COMMANDER }}"
|
||||
{{ model.ATTR_VALUE_CURRENT }} {{ model.ATTR_VALUE_PREVIOUS }} />
|
||||
</td>
|
||||
<td class="{{ model.ATTR_COMMANDER_BRACKET_ID }} {{ model.FLAG_DDL_PREVIEW }}">
|
||||
{% include 'components/tcg/_preview_ddl_commander_bracket.html' %}
|
||||
</td>
|
||||
{% set active = True %}
|
||||
{% include 'components/common/inputs/_td_active.html' %}
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr class="{{ model.FLAG_DECK }}" {{ model.ATTR_DECK_ID }}="{{ deck.deck_id }}">
|
||||
<td class="{{ model.FLAG_NAME }}">
|
||||
<input type="text"
|
||||
class="{{ model.FLAG_NAME }}"
|
||||
{{ model.ATTR_VALUE_CURRENT }}="{{ deck.name }}"
|
||||
{{ model.ATTR_VALUE_PREVIOUS }}="{{ deck.name }}"
|
||||
value="{{ deck.name }}" />
|
||||
</td>
|
||||
<td class="{{ model.FLAG_IS_COMMANDER }}">
|
||||
<input type="checkbox"
|
||||
class="{{ model.FLAG_IS_COMMANDER }}"
|
||||
{{ model.ATTR_VALUE_CURRENT }}="{{ deck.is_commander | lower }}"
|
||||
{{ model.ATTR_VALUE_PREVIOUS }}="{{ deck.is_commander | lower }}"
|
||||
{% if deck.is_commander %}checked{% endif %}
|
||||
value="{{ deck.is_commander | lower }}" />
|
||||
</td>
|
||||
{% set commander_bracket_preview = deck.commander_bracket %}
|
||||
<td class="{{ model.ATTR_COMMANDER_BRACKET_ID }} {{ model.FLAG_DDL_PREVIEW }}">
|
||||
{% include 'components/tcg/_preview_ddl_commander_bracket.html' %}
|
||||
</td>
|
||||
{% set active = deck.active %}
|
||||
{% include 'components/common/inputs/_td_active.html' %}
|
||||
</tr>
|
||||
{% endif %}
|
||||
@@ -1,23 +1,36 @@
|
||||
|
||||
<script>
|
||||
var attrCommanderBracketId = "{{ model.ATTR_COMMANDER_BRACKET_ID }}";
|
||||
var attrDamageId = "{{ model.ATTR_DAMAGE_ID }}";
|
||||
var attrDeckId = "{{ model.ATTR_DECK_ID }}";
|
||||
var attrGameId = "{{ model.ATTR_GAME_ID }}";
|
||||
var attrPlayerId = "{{ model.ATTR_PLAYER_ID }}";
|
||||
var attrRoundId = "{{ model.ATTR_ROUND_ID }}";
|
||||
var attrDamageId = "{{ model.ATTR_DAMAGE_ID }}";
|
||||
var attrDeckId = "{{ model.ATTR_DECK_ID }}";
|
||||
var attrUserId = "{{ model.ATTR_USER_ID }}";
|
||||
var attrUserAuth0Id = "{{ model.ATTR_USER_AUTH0_ID }}";
|
||||
var flagGame = "{{ model.FLAG_GAME }}";
|
||||
var flagPlayer = "{{ model.FLAG_PLAYER }}";
|
||||
var flagRound = "{{ model.FLAG_ROUND }}";
|
||||
var flagCommanderDeaths = "{{ model.FLAG_COMMANDER_DEATHS }}";
|
||||
var flagDamage = "{{ model.FLAG_DAMAGE }}";
|
||||
var flagDeck = "{{ model.FLAG_DECK }}";
|
||||
var flagGame = "{{ model.FLAG_GAME }}";
|
||||
var flagIsBool = "{{ model.FLAG_IS_BOOL }}";
|
||||
var flagIsCommander = "{{ model.FLAG_IS_COMMANDER }}";
|
||||
var flagIsDraft = "{{ model.FLAG_IS_DRAFT }}";
|
||||
var flagIsEliminated = "{{ model.FLAG_IS_ELIMINATED }}";
|
||||
var flagIsFloat = "{{ model.FLAG_IS_FLOAT }}";
|
||||
var flagIsInterval = "{{ model.FLAG_IS_INTERVAL }}";
|
||||
var flagIsSealed = "{{ model.FLAG_IS_SEALED }}";
|
||||
var flagHealthChange = "{{ model.FLAG_HEALTH_CHANGE }}";
|
||||
var flagCommanderDeaths = "{{ model.FLAG_COMMANDER_DEATHS }}";
|
||||
var flagIsText = "{{ model.FLAG_IS_TEXT }}";
|
||||
var flagIsTimestamp = "{{ model.FLAG_IS_TIMESTAMP }}";
|
||||
var flagLifeGain = "{{ model.FLAG_LIFE_GAIN }}";
|
||||
var flagLifeLoss = "{{ model.FLAG_LIFE_LOSS }}";
|
||||
var flagPlayer = "{{ model.FLAG_PLAYER }}";
|
||||
var flagRound = "{{ model.FLAG_ROUND }}";
|
||||
var flagUser = "{{ model.FLAG_USER }}";
|
||||
var flagValueBool = "{{ model.FLAG_VALUE_BOOL }}";
|
||||
var flagValueFloat = "{{ model.FLAG_VALUE_FLOAT }}";
|
||||
var flagValueInterval = "{{ model.FLAG_VALUE_INTERVAL }}";
|
||||
var flagValueText = "{{ model.FLAG_VALUE_TEXT }}";
|
||||
var flagValueTimestamp = "{{ model.FLAG_VALUE_TIMESTAMP }}";
|
||||
var hashSaveMtgGame = "{{ model.HASH_SAVE_MTG_GAME }}";
|
||||
var hashSaveMtgGamePlayer = "{{ model.HASH_SAVE_MTG_GAME_PLAYER }}";
|
||||
var hashSaveMtgGameRound = "{{ model.HASH_SAVE_MTG_GAME_ROUND }}";
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
var flagTableMain = "{{ model.FLAG_TABLE_MAIN }}";
|
||||
var flagTemporaryElement = "{{ model.FLAG_TEMPORARY_ELEMENT }}";
|
||||
var flagUser = "{{ model.FLAG_USER }}";
|
||||
var flagValue = "{{ model.FLAG_VALUE }}";
|
||||
var flagWebsite = "{{ model.FLAG_WEBSITE }}";
|
||||
var hashGetALTCHAChallenge = "{{ model.HASH_GET_ALTCHA_CHALLENGE }}";
|
||||
var hashPageAccessibilityReport = "{{ model.HASH_PAGE_ACCESSIBILITY_REPORT }}";
|
||||
|
||||
@@ -43,24 +43,20 @@
|
||||
<div class="footer-content">
|
||||
<div class="footer-section">
|
||||
<h3>{{ model.NAME_COMPANY }}</h3>
|
||||
<p>Company Number: {{ model.COMPANY_NUMBER }}</p>
|
||||
<p>Registered in England and Wales</p>
|
||||
<p>Registered Office: {{ model.COMPANY_ADDRESS_SHORT }}</p>
|
||||
<p>Email: {{ model.get_mail_contact_public() }}</p>
|
||||
</div>
|
||||
|
||||
<div class="footer-section">
|
||||
<h3>Legal</h3>
|
||||
<ul>
|
||||
<li><a href="{{ model.HASH_PAGE_PRIVACY_POLICY }}">Privacy Policy</a></li>
|
||||
<li><a href="{{ model.HASH_PAGE_ACCESSIBILITY_STATEMENT }}">Accessibility Statement</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<a href="{{ model.HASH_PAGE_PRIVACY_POLICY }}">Privacy Policy</a>
|
||||
<a href="{{ model.HASH_PAGE_ACCESSIBILITY_STATEMENT }}">Accessibility Statement</a>
|
||||
</div>
|
||||
|
||||
<div class="footer-bottom">
|
||||
<div class="footer-section">
|
||||
<p>© {{ current_year }} {{ model.NAME_COMPANY }}. <a href="{{ model.HASH_PAGE_LICENSE }}" alt="License" aria-label="License">All rights reserved.</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{% include 'layouts/_shared_scripts.html' %}
|
||||
|
||||
111
templates/pages/tcg/mtg/_decks.html
Normal file
111
templates/pages/tcg/mtg/_decks.html
Normal file
@@ -0,0 +1,111 @@
|
||||
{% extends 'layouts/layout_tcg.html' %}
|
||||
|
||||
{% block page_head %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='dist/css/tcg_decks.bundle.css') }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block page_body %}
|
||||
{#
|
||||
<div class="section-header">
|
||||
<h2 class="tcg-section-title">Decks</h2>
|
||||
</div>
|
||||
#}
|
||||
|
||||
<!-- Filters Form -->
|
||||
<form id="{{ model.ID_FORM_FILTERS }}" class="tcg-card {{ model.FLAG_FILTER }} {{ model.FLAG_ROW }} {{ model.FLAG_CARD }}">
|
||||
{{ model.form_filters.hidden_tag() }}
|
||||
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_COLUMN }}">
|
||||
<div class="{{ model.FLAG_CONTAINER_INPUT }} {{ model.FLAG_COLUMN }} {{ model.FLAG_FILTER }} {{ model.FLAG_SEARCH }}"
|
||||
{{ model.ATTR_VALUE_PREVIOUS }}="{{ model.form_filters.search.data }}">
|
||||
{{ model.form_filters.search.label(class="tcg-label") }}
|
||||
{{ model.form_filters.search(class="tcg-input", placeholder="Search decks...") }}
|
||||
</div>
|
||||
<div class="{{ model.FLAG_CONTAINER_INPUT }} {{ model.FLAG_COLUMN }} {{ model.FLAG_FILTER }} {{ model.FLAG_ACTIVE }}"
|
||||
{{ model.ATTR_VALUE_PREVIOUS }}="{{ model.form_filters.active_only.data }}">
|
||||
{{ model.form_filters.active_only() }}
|
||||
{{ model.form_filters.active_only.label(class="tcg-label") }}
|
||||
</div>
|
||||
<div class="{{ model.FLAG_CONTAINER_INPUT }} {{ model.FLAG_COLUMN }} {{ model.FLAG_FILTER }} {{ model.FLAG_IS_COMMANDER }}"
|
||||
{{ model.ATTR_VALUE_PREVIOUS }}="{{ model.form_filters.is_commander.data }}">
|
||||
{{ model.form_filters.is_commander() }}
|
||||
{{ model.form_filters.is_commander.label(class="tcg-label") }}
|
||||
</div>
|
||||
</div>
|
||||
{% set block_id = 'buttons_table_default' %}
|
||||
{% include 'components/common/buttons/_buttons_save_cancel.html' %}
|
||||
</form>
|
||||
{#
|
||||
{% set block_id = 'container_buttons_save_cancel' %}
|
||||
{% include 'components/common/buttons/_buttons_save_cancel.html' %}
|
||||
</form>
|
||||
#}
|
||||
|
||||
<div class="decks-section tcg-card">
|
||||
<!-- Decks Table -->
|
||||
<table class="decks-table {{ model.FLAG_TABLE_MAIN }} {{ model.FLAG_ROW }} {{ model.FLAG_CARD }} {{ model.FLAG_DECK }}" id="{{ model.ID_TABLE_MAIN }}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="{{ model.FLAG_NAME }}">Name</th>
|
||||
<th class="{{ model.FLAG_IS_COMMANDER }}">Is Commander</th>
|
||||
<th class="{{ model.ATTR_COMMANDER_BRACKET_ID }}">Commander Bracket</th>
|
||||
<th class="{{ model.FLAG_ACTIVE }}">
|
||||
{% set class_name = model.FLAG_ACTIVE %}
|
||||
{% set attribute_text = '' %}
|
||||
{% include 'components/common/buttons/_icon_add.html' %}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% set is_blank_row = False %}
|
||||
{% for deck in model.decks %}
|
||||
{% include 'components/tcg/_row_deck.html' %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Statistics -->
|
||||
<div class="section-header">
|
||||
<h2 class="tcg-section-title">Statistics</h2>
|
||||
</div>
|
||||
<table class="{{ model.FLAG_STATISTICS }} {{ model.FLAG_ROW }} {{ model.FLAG_CARD }} {{ model.FLAG_DECK }}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="{{ model.FLAG_DECK }}">Deck</th>
|
||||
<th class="{{ model.FLAG_NAME }}">Name</th>
|
||||
<th class="{{ model.FLAG_VALUE }}">Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for statistic in model.statistics %}
|
||||
<tr class="{{ model.FLAG_ROW_NEW }} {{ model.FLAG_STATISTIC }}" {{ model.ATTR_STATISTIC_ID }}>
|
||||
<td class="{{ model.ATTR_DECK_ID }} {{ model.ATTR_ENTITY_RECORD_ID }}">{{ statistic.entity_record_name }}</td>
|
||||
<td class="{{ model.FLAG_NAME }}">{{ statistic.name }}</td>
|
||||
<td class="{{ model.FLAG_VALUE }}">{{ statistic.get_formatted_value() }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% include 'components/common/temporary/_overlay_confirm.html' %}
|
||||
{% include 'components/common/temporary/_overlay_error.html' %}
|
||||
|
||||
<div id="{{ model.ID_CONTAINER_TEMPLATE_ELEMENTS }}">
|
||||
<!-- Active column -->
|
||||
<!-- Delete -->
|
||||
{% set class_name = '' %}
|
||||
{% include 'components/common/buttons/_icon_trash.html' %}
|
||||
<!-- Undelete -->
|
||||
{% set class_name = model.FLAG_ACTIVE %}
|
||||
{% set attribute_text = '' %}
|
||||
{% include 'components/common/buttons/_icon_add.html' %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var attrCommanderBracketId = "{{ model.ATTR_COMMANDER_BRACKET_ID }}";
|
||||
var commanderBrackets = {{ model.convert_list_objects_to_json(model.commander_brackets) | tojson | safe }};
|
||||
var decks = {{ model.convert_list_objects_to_json(model.decks) | tojson | safe }};
|
||||
var flagStatistics = "{{ model.FLAG_STATISTICS }}";
|
||||
var flagIsCommander = "{{ model.FLAG_IS_COMMANDER }}";
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -135,7 +135,8 @@
|
||||
<th class="{{ model.ATTR_ROUND_ID }}">Round</th>
|
||||
<th class="{{ model.ATTR_PLAYER_ID }}">Player</th>
|
||||
<th class="{{ model.ATTR_RECEIVED_FROM_COMMANDER_PLAYER_ID }}">Received From Commander</th>
|
||||
<th class="{{ model.FLAG_HEALTH_CHANGE }}">Health Change</th>
|
||||
<th class="{{ model.FLAG_LIFE_GAIN }}">Life Gain</th>
|
||||
<th class="{{ model.FLAG_LIFE_LOSS }}">Life Loss</th>
|
||||
<th class="{{ model.FLAG_COMMANDER_DEATHS }}">Commander Deaths</th>
|
||||
<th class="{{ model.FLAG_IS_ELIMINATED }}">Is Eliminated</th>
|
||||
</tr>
|
||||
@@ -181,9 +182,6 @@
|
||||
var damageRecords = {{ model.convert_list_objects_to_json(model.damage_records) | tojson | safe }};
|
||||
var decks = {{ model.convert_list_objects_to_json(model.decks) | tojson | safe }};
|
||||
var flagDamageLog = "{{ model.FLAG_DAMAGE_LOG }}";
|
||||
var flagDisplayOrder = "{{ model.FLAG_DISPLAY_ORDER }}";
|
||||
var flagHealthChange = "{{ model.FLAG_HEALTH_CHANGE }}";
|
||||
var flagIsEliminated = "{{ model.FLAG_IS_ELIMINATED }}";
|
||||
var flagRoundDisplayOrderButton = "{{ model.FLAG_ROUND_DISPLAY_ORDER_BUTTON }}";
|
||||
var flagRoundDisplayOrderMinus = "{{ model.FLAG_ROUND_DISPLAY_ORDER_MINUS }}";
|
||||
var flagRoundDisplayOrderPlus = "{{ model.FLAG_ROUND_DISPLAY_ORDER_PLUS }}";
|
||||
|
||||
@@ -40,24 +40,23 @@
|
||||
</form>
|
||||
|
||||
<!-- Games Table -->
|
||||
<div class="games-table-container">
|
||||
<table class="games-table" id="gamesTable">
|
||||
<table class="games-table {{ model.FLAG_TABLE_MAIN }} {{ model.FLAG_ROW }} {{ model.FLAG_CARD }} {{ model.FLAG_DECK }}" id="{{ model.ID_TABLE_MAIN }}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Game ID</th>
|
||||
<th>Type</th>
|
||||
<th>Location</th>
|
||||
<th>Started</th>
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
<th class="{{ model.ATTR_GAME_ID }}">Game ID</th>
|
||||
<th class="{{ model.FLAG_IS_COMMANDER }}">Type</th>
|
||||
<th class="{{ model.FLAG_LOCATION_NAME }}">Location</th>
|
||||
<th class="{{ model.FLAG_START_ON }}">Started</th>
|
||||
<th class="{{ model.FLAG_ACTIVE }}">Status</th>
|
||||
<th class="{{ model.FLAG_NAV_MTG_GAME }}">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if model.games and model.games|length > 0 %}
|
||||
{% for game in model.games %}
|
||||
<tr class="game-row {% if not game.active %}inactive{% endif %}" data-game-id="{{ game.game_id }}">
|
||||
<td class="game-id">#{{ game.game_id }}</td>
|
||||
<td class="game-type">
|
||||
<td class="{{ model.ATTR_GAME_ID }}">#{{ game.game_id }}</td>
|
||||
<td class="{{ model.FLAG_IS_COMMANDER }}">
|
||||
{% if game.is_commander %}
|
||||
<span class="badge badge-commander">Commander</span>
|
||||
{% elif game.is_draft %}
|
||||
@@ -68,9 +67,9 @@
|
||||
<span class="badge badge-standard">Standard</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="game-location">{{ game.location_name or 'Unknown' }}</td>
|
||||
<td class="game-date">{{ model.format_datetime_text(game.start_on) if game.start_on else 'Not started' }}</td>
|
||||
<td class="game-status">
|
||||
<td class="{{ model.FLAG_LOCATION_NAME }}">{{ game.location_name or 'Unknown' }}</td>
|
||||
<td class="{{ model.FLAG_START_ON }}">{{ model.format_datetime_text(game.start_on) if game.start_on else 'Not started' }}</td>
|
||||
<td class="{{ model.FLAG_ACTIVE }}">
|
||||
{% if game.end_on %}
|
||||
<span class="status status-ended">Ended</span>
|
||||
{% elif game.active %}
|
||||
@@ -79,7 +78,7 @@
|
||||
<span class="status status-inactive">Inactive</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="game-actions">
|
||||
<td class="{{ model.FLAG_NAV_MTG_GAME }}">
|
||||
<a href="{{ model.HASH_PAGE_MTG_GAME }}/{{ game.game_id }}" class="btn-tcg btn-join">Join Game</a>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -97,10 +96,9 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- New Game Modal -->
|
||||
<div id="newGameModal" class="modal-overlay hidden">
|
||||
<div id="newGameModal" class="modal-overlay {{ model.FLAG_IS_COLLAPSED }}">
|
||||
<div class="modal-content tcg-card">
|
||||
<div class="modal-header">
|
||||
<h2 class="tcg-section-title">Create New Game</h2>
|
||||
@@ -158,5 +156,4 @@
|
||||
var flagStartOn = "{{ model.FLAG_START_ON }}";
|
||||
var flagStartingLife = "{{ model.FLAG_STARTING_LIFE }}";
|
||||
</script>
|
||||
{# <script src="{{ url_for('static', filename='js/pages/tcg/mtg_games.js') }}"></script> #}
|
||||
{% endblock %}
|
||||
|
||||
4
todo.txt
4
todo.txt
@@ -3,5 +3,9 @@
|
||||
Winner of game animation - bring to centre with trophy icon and show updates player + deck stats (+ charts?), add end time
|
||||
Game start + end times left / right of game location
|
||||
Deck mulligan rate - add to player table and then just get statistics whenever wanted
|
||||
Ensure no duplicate players by Game ID and User ID and Deck ID
|
||||
|
||||
player save with null name not pulling user and deck names
|
||||
create damage from commander fills is_eliminated with false, but create from player's own damage leaves is_eliminated undefined
|
||||
|
||||
Change round - update player cards to show damage at that point for easier editing
|
||||
|
||||
@@ -24,7 +24,7 @@ module.exports = {
|
||||
path.resolve(__dirname, 'static/css/lib/typography.css'),
|
||||
path.resolve(__dirname, 'static/css/lib/utils.css'),
|
||||
path.resolve(__dirname, 'static/css/lib/variables.css'),
|
||||
path.resolve(__dirname, 'static/css/themes/light.css'),
|
||||
path.resolve(__dirname, 'static/css/themes/dark.css'),
|
||||
// ...glob.sync(path.resolve(__dirname, 'static/css/main/** /*.css')) // Include CSS files for the main page
|
||||
],
|
||||
// Core
|
||||
@@ -53,6 +53,10 @@ module.exports = {
|
||||
path.resolve(__dirname, 'static/css/pages/legal/privacy_policy.css')
|
||||
],
|
||||
// TCG
|
||||
tcg_decks: [
|
||||
path.resolve(__dirname, 'static/css/sections/tcg.css'),
|
||||
path.resolve(__dirname, 'static/css/pages/tcg/decks.css')
|
||||
],
|
||||
tcg_game: [
|
||||
path.resolve(__dirname, 'static/css/sections/tcg.css'),
|
||||
path.resolve(__dirname, 'static/css/pages/tcg/game.css')
|
||||
|
||||
Reference in New Issue
Block a user