refactor: extract TIER_NAMES/TIER_COLORS to shared constants module (#146)
All checks were successful
Ruff Lint / lint (pull_request) Successful in 12s
All checks were successful
Ruff Lint / lint (pull_request) Successful in 12s
Closes #146 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
224250b03d
commit
21bad7af51
@ -60,6 +60,7 @@ from helpers import (
|
||||
)
|
||||
from utilities.buttons import ask_with_buttons
|
||||
from utilities.autocomplete import cardset_autocomplete, player_autocomplete
|
||||
from helpers.refractor_constants import TIER_NAMES as REFRACTOR_TIER_NAMES
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
@ -471,15 +472,6 @@ def get_record_embed(team: dict, results: dict, league: str):
|
||||
return embed
|
||||
|
||||
|
||||
REFRACTOR_TIER_NAMES = {
|
||||
0: "Base Card",
|
||||
1: "Base Chrome",
|
||||
2: "Refractor",
|
||||
3: "Gold Refractor",
|
||||
4: "Superfractor",
|
||||
}
|
||||
|
||||
|
||||
async def _build_refractor_response(
|
||||
player_name: str,
|
||||
player_id: int,
|
||||
|
||||
@ -21,19 +21,12 @@ from discord.ext import commands
|
||||
from api_calls import db_get
|
||||
from helpers.discord_utils import get_team_embed
|
||||
from helpers.main import get_team_by_owner
|
||||
from helpers.refractor_constants import TIER_NAMES, STATUS_TIER_COLORS as TIER_COLORS
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
PAGE_SIZE = 10
|
||||
|
||||
TIER_NAMES = {
|
||||
0: "Base Card",
|
||||
1: "Base Chrome",
|
||||
2: "Refractor",
|
||||
3: "Gold Refractor",
|
||||
4: "Superfractor",
|
||||
}
|
||||
|
||||
# Tier-specific labels for the status display.
|
||||
TIER_SYMBOLS = {
|
||||
0: "Base", # Base Card — used in summary only, not in per-card display
|
||||
@ -45,15 +38,6 @@ TIER_SYMBOLS = {
|
||||
|
||||
_FULL_BAR = "▰" * 12
|
||||
|
||||
# Embed accent colors per tier (used for single-tier filtered views).
|
||||
TIER_COLORS = {
|
||||
0: 0x95A5A6, # slate grey
|
||||
1: 0xBDC3C7, # silver/chrome
|
||||
2: 0x3498DB, # refractor blue
|
||||
3: 0xF1C40F, # gold
|
||||
4: 0x1ABC9C, # teal superfractor
|
||||
}
|
||||
|
||||
|
||||
def render_progress_bar(current: int, threshold: int, width: int = 12) -> str:
|
||||
"""
|
||||
|
||||
36
helpers/refractor_constants.py
Normal file
36
helpers/refractor_constants.py
Normal file
@ -0,0 +1,36 @@
|
||||
"""
|
||||
Shared Refractor Constants
|
||||
|
||||
Single source of truth for tier names and colors used across the refractor
|
||||
system. All consumers (status view, notifications, player view) import from
|
||||
here to prevent silent divergence.
|
||||
"""
|
||||
|
||||
# Human-readable display names for each tier number.
|
||||
TIER_NAMES = {
|
||||
0: "Base Card",
|
||||
1: "Base Chrome",
|
||||
2: "Refractor",
|
||||
3: "Gold Refractor",
|
||||
4: "Superfractor",
|
||||
}
|
||||
|
||||
# Embed accent colors for the /refractor status view.
|
||||
# These use muted/metallic tones suited to a card-list display.
|
||||
STATUS_TIER_COLORS = {
|
||||
0: 0x95A5A6, # slate grey
|
||||
1: 0xBDC3C7, # silver/chrome
|
||||
2: 0x3498DB, # refractor blue
|
||||
3: 0xF1C40F, # gold
|
||||
4: 0x1ABC9C, # teal superfractor
|
||||
}
|
||||
|
||||
# Embed accent colors for tier-up notification embeds.
|
||||
# These use brighter/more celebratory tones to signal a milestone event.
|
||||
# T2 is gold (not blue) to feel like an achievement unlock, not a status indicator.
|
||||
NOTIF_TIER_COLORS = {
|
||||
1: 0x2ECC71, # green
|
||||
2: 0xF1C40F, # gold
|
||||
3: 0x9B59B6, # purple
|
||||
4: 0x1ABC9C, # teal (superfractor)
|
||||
}
|
||||
@ -12,25 +12,10 @@ import logging
|
||||
|
||||
import discord
|
||||
|
||||
from helpers.refractor_constants import TIER_NAMES, NOTIF_TIER_COLORS as TIER_COLORS
|
||||
|
||||
logger = logging.getLogger("discord_app")
|
||||
|
||||
# Human-readable display names for each tier number.
|
||||
TIER_NAMES = {
|
||||
0: "Base Card",
|
||||
1: "Base Chrome",
|
||||
2: "Refractor",
|
||||
3: "Gold Refractor",
|
||||
4: "Superfractor",
|
||||
}
|
||||
|
||||
# Tier-specific embed colors.
|
||||
TIER_COLORS = {
|
||||
1: 0x2ECC71, # green
|
||||
2: 0xF1C40F, # gold
|
||||
3: 0x9B59B6, # purple
|
||||
4: 0x1ABC9C, # teal (superfractor)
|
||||
}
|
||||
|
||||
FOOTER_TEXT = "Paper Dynasty Refractor"
|
||||
|
||||
|
||||
|
||||
@ -415,47 +415,51 @@ def mock_interaction():
|
||||
|
||||
class TestTierNamesDivergenceCheck:
|
||||
"""
|
||||
T1-6: Assert that TIER_NAMES in cogs.refractor and helpers.refractor_notifs
|
||||
are identical (same keys, same values).
|
||||
T1-6: Assert that TIER_NAMES in all three consumers (cogs.refractor,
|
||||
helpers.refractor_notifs, cogs.players) is identical.
|
||||
|
||||
Why: TIER_NAMES is duplicated in two modules. If one is updated and the
|
||||
other is not (e.g. a tier is renamed or a new tier is added), tier labels
|
||||
in the /refractor status embed and the tier-up notification embed will
|
||||
diverge silently. This test acts as a divergence tripwire — it will fail
|
||||
the moment the two copies fall out of sync, forcing an explicit fix.
|
||||
All three consumers now import from helpers.refractor_constants, so this
|
||||
test acts as a tripwire against accidental re-localization of the constant.
|
||||
If any consumer re-declares a local copy that diverges, these tests will
|
||||
catch it.
|
||||
"""
|
||||
|
||||
def test_tier_names_are_identical_across_modules(self):
|
||||
"""
|
||||
Import TIER_NAMES from both modules and assert deep equality.
|
||||
Import TIER_NAMES from all three consumers and assert deep equality.
|
||||
|
||||
The test imports the name at call-time rather than at module level to
|
||||
ensure it always reads the current definition and is not affected by
|
||||
module-level caching or monkeypatching in other tests.
|
||||
The test imports at call-time rather than module level to ensure it
|
||||
always reads the current definition and is not affected by caching or
|
||||
monkeypatching in other tests.
|
||||
"""
|
||||
from cogs.refractor import TIER_NAMES as cog_tier_names
|
||||
from helpers.refractor_notifs import TIER_NAMES as notifs_tier_names
|
||||
from helpers.refractor_constants import TIER_NAMES as constants_tier_names
|
||||
|
||||
assert cog_tier_names == notifs_tier_names, (
|
||||
"TIER_NAMES differs between cogs.refractor and helpers.refractor_notifs. "
|
||||
"Both copies must be kept in sync. "
|
||||
assert cog_tier_names == notifs_tier_names == constants_tier_names, (
|
||||
"TIER_NAMES differs across consumers. "
|
||||
f"cogs.refractor: {cog_tier_names!r} "
|
||||
f"helpers.refractor_notifs: {notifs_tier_names!r}"
|
||||
f"helpers.refractor_notifs: {notifs_tier_names!r} "
|
||||
f"helpers.refractor_constants: {constants_tier_names!r}"
|
||||
)
|
||||
|
||||
def test_tier_names_have_same_keys(self):
|
||||
"""Keys (tier numbers) must be identical in both modules."""
|
||||
"""Keys (tier numbers) must be identical in all consumers."""
|
||||
from cogs.refractor import TIER_NAMES as cog_tier_names
|
||||
from helpers.refractor_notifs import TIER_NAMES as notifs_tier_names
|
||||
from cogs.players import REFRACTOR_TIER_NAMES
|
||||
|
||||
assert set(cog_tier_names.keys()) == set(notifs_tier_names.keys()), (
|
||||
"TIER_NAMES key sets differ between modules."
|
||||
)
|
||||
assert (
|
||||
set(cog_tier_names.keys())
|
||||
== set(notifs_tier_names.keys())
|
||||
== set(REFRACTOR_TIER_NAMES.keys())
|
||||
), "TIER_NAMES key sets differ between consumers."
|
||||
|
||||
def test_tier_names_have_same_values(self):
|
||||
"""Display strings (values) must be identical for every shared key."""
|
||||
from cogs.refractor import TIER_NAMES as cog_tier_names
|
||||
from helpers.refractor_notifs import TIER_NAMES as notifs_tier_names
|
||||
from cogs.players import REFRACTOR_TIER_NAMES
|
||||
|
||||
for tier, name in cog_tier_names.items():
|
||||
assert notifs_tier_names.get(tier) == name, (
|
||||
@ -463,6 +467,11 @@ class TestTierNamesDivergenceCheck:
|
||||
f"cogs.refractor={name!r}, "
|
||||
f"helpers.refractor_notifs={notifs_tier_names.get(tier)!r}"
|
||||
)
|
||||
assert REFRACTOR_TIER_NAMES.get(tier) == name, (
|
||||
f"Tier {tier} name mismatch: "
|
||||
f"cogs.refractor={name!r}, "
|
||||
f"cogs.players.REFRACTOR_TIER_NAMES={REFRACTOR_TIER_NAMES.get(tier)!r}"
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Loading…
Reference in New Issue
Block a user