This commit eliminates 150+ lines of duplicated, error-prone nested if/elif logic by extracting rarity cost calculations into a lookup table and function. ## Changes Made 1. **Add RARITY_COST_ADJUSTMENTS lookup table** (creation_helpers.py) - Maps (old_rarity, new_rarity) → (cost_adjustment, minimum_cost) - Covers all 30 possible rarity transitions - Self-documenting with comments for each rarity tier - Single source of truth for all cost adjustments 2. **Add calculate_rarity_cost_adjustment() function** (creation_helpers.py) - Takes old_rarity, new_rarity, old_cost - Returns new cost with adjustments and minimums applied - Includes comprehensive docstring with examples - Handles edge cases (same rarity, undefined transitions) - Logs warnings for undefined transitions 3. **Update batters/creation.py** - Import calculate_rarity_cost_adjustment - Replace 75-line nested if/elif block with 7-line function call - Identical behavior, much cleaner code 4. **Update pitchers/creation.py** - Import calculate_rarity_cost_adjustment - Replace 75-line nested if/elif block with 7-line function call - Eliminates duplication between batters and pitchers 5. **Add comprehensive tests** (tests/test_rarity_cost_adjustments.py) - 22 tests covering all scenarios - Tests individual transitions (Diamond→Gold, Common→Bronze, etc.) - Tests all upward and downward transitions - Tests minimum cost enforcement - Tests edge cases (zero cost, very high cost, negative cost) - Tests symmetry (up then down returns close to original) ## Impact ### Lines Eliminated - **Batters:** 75 lines → 7 lines (89% reduction) - **Pitchers:** 75 lines → 7 lines (89% reduction) - **Total:** 150 lines of nested logic eliminated ### Benefits ✅ Eliminates 150+ lines of duplicated code ✅ Data-driven approach makes adjustments clear and modifiable ✅ Single source of truth prevents inconsistencies ✅ Independently testable business logic ✅ 22 comprehensive tests ensure correctness ✅ Easy to add new rarity tiers or modify costs ✅ Reduced risk of typos in magic numbers ## Test Results ✅ 22/22 new tests pass ✅ All existing tests still pass ✅ 100% backward compatible - identical behavior ## Files Modified - creation_helpers.py: +104 lines (table + function + docs) - batters/creation.py: -68 lines (replaced nested logic) - pitchers/creation.py: -68 lines (replaced nested logic) - tests/test_rarity_cost_adjustments.py: +174 lines (new tests) **Net change:** 150+ lines of complex logic replaced with simple, tested, data-driven approach. Part of ongoing refactoring to reduce code fragility.
185 lines
8.6 KiB
Python
185 lines
8.6 KiB
Python
"""
|
|
Tests for rarity cost adjustment logic.
|
|
|
|
This test verifies that calculate_rarity_cost_adjustment() correctly:
|
|
1. Adjusts costs when rarity changes
|
|
2. Enforces minimum costs where specified
|
|
3. Handles all rarity transitions (1-5, 99)
|
|
4. Returns original cost when rarity doesn't change
|
|
"""
|
|
import pytest
|
|
from creation_helpers import calculate_rarity_cost_adjustment
|
|
|
|
|
|
class TestRarityCostAdjustments:
|
|
"""Test suite for rarity cost adjustment calculations."""
|
|
|
|
def test_no_change_same_rarity(self):
|
|
"""Cost should not change if rarity stays the same."""
|
|
assert calculate_rarity_cost_adjustment(1, 1, 1000) == 1000
|
|
assert calculate_rarity_cost_adjustment(5, 5, 50) == 50
|
|
assert calculate_rarity_cost_adjustment(99, 99, 2400) == 2400
|
|
|
|
def test_diamond_to_gold(self):
|
|
"""Diamond (1) to Gold (2): -540, min 100."""
|
|
assert calculate_rarity_cost_adjustment(1, 2, 1000) == 460
|
|
assert calculate_rarity_cost_adjustment(1, 2, 500) == 100 # min enforced
|
|
assert calculate_rarity_cost_adjustment(1, 2, 50) == 100 # min enforced
|
|
|
|
def test_diamond_to_silver(self):
|
|
"""Diamond (1) to Silver (3): -720, min 50."""
|
|
assert calculate_rarity_cost_adjustment(1, 3, 1000) == 280
|
|
assert calculate_rarity_cost_adjustment(1, 3, 500) == 50 # min enforced
|
|
assert calculate_rarity_cost_adjustment(1, 3, 100) == 50 # min enforced
|
|
|
|
def test_diamond_to_bronze(self):
|
|
"""Diamond (1) to Bronze (4): -780, min 15."""
|
|
assert calculate_rarity_cost_adjustment(1, 4, 1000) == 220
|
|
assert calculate_rarity_cost_adjustment(1, 4, 500) == 15 # min enforced
|
|
assert calculate_rarity_cost_adjustment(1, 4, 50) == 15 # min enforced
|
|
|
|
def test_diamond_to_common(self):
|
|
"""Diamond (1) to Common (5): -800, min 5."""
|
|
assert calculate_rarity_cost_adjustment(1, 5, 1000) == 200
|
|
assert calculate_rarity_cost_adjustment(1, 5, 500) == 5 # min enforced
|
|
assert calculate_rarity_cost_adjustment(1, 5, 100) == 5 # min enforced
|
|
|
|
def test_diamond_to_special(self):
|
|
"""Diamond (1) to Special (99): +1600, no min."""
|
|
assert calculate_rarity_cost_adjustment(1, 99, 1000) == 2600
|
|
assert calculate_rarity_cost_adjustment(1, 99, 100) == 1700
|
|
|
|
def test_gold_to_diamond(self):
|
|
"""Gold (2) to Diamond (1): +540, no min."""
|
|
assert calculate_rarity_cost_adjustment(2, 1, 200) == 740
|
|
assert calculate_rarity_cost_adjustment(2, 1, 100) == 640
|
|
|
|
def test_gold_to_silver(self):
|
|
"""Gold (2) to Silver (3): -180, min 50."""
|
|
assert calculate_rarity_cost_adjustment(2, 3, 300) == 120
|
|
assert calculate_rarity_cost_adjustment(2, 3, 100) == 50 # min enforced
|
|
|
|
def test_silver_to_gold(self):
|
|
"""Silver (3) to Gold (2): +180, no min."""
|
|
assert calculate_rarity_cost_adjustment(3, 2, 100) == 280
|
|
assert calculate_rarity_cost_adjustment(3, 2, 50) == 230
|
|
|
|
def test_silver_to_bronze(self):
|
|
"""Silver (3) to Bronze (4): -60, min 15."""
|
|
assert calculate_rarity_cost_adjustment(3, 4, 100) == 40
|
|
assert calculate_rarity_cost_adjustment(3, 4, 50) == 15 # min enforced
|
|
|
|
def test_bronze_to_common(self):
|
|
"""Bronze (4) to Common (5): -20, min 5."""
|
|
assert calculate_rarity_cost_adjustment(4, 5, 50) == 30
|
|
assert calculate_rarity_cost_adjustment(4, 5, 20) == 5 # min enforced
|
|
|
|
def test_common_to_bronze(self):
|
|
"""Common (5) to Bronze (4): +20, no min."""
|
|
assert calculate_rarity_cost_adjustment(5, 4, 10) == 30
|
|
assert calculate_rarity_cost_adjustment(5, 4, 50) == 70
|
|
|
|
def test_common_to_diamond(self):
|
|
"""Common (5) to Diamond (1): +800, no min."""
|
|
assert calculate_rarity_cost_adjustment(5, 1, 10) == 810
|
|
assert calculate_rarity_cost_adjustment(5, 1, 50) == 850
|
|
|
|
def test_special_to_diamond(self):
|
|
"""Special (99) to Diamond (1): -1600, min 800."""
|
|
assert calculate_rarity_cost_adjustment(99, 1, 2400) == 800
|
|
assert calculate_rarity_cost_adjustment(99, 1, 2000) == 800 # min enforced
|
|
assert calculate_rarity_cost_adjustment(99, 1, 3000) == 1400
|
|
|
|
def test_special_to_gold(self):
|
|
"""Special (99) to Gold (2): -2140, min 100."""
|
|
assert calculate_rarity_cost_adjustment(99, 2, 2400) == 260
|
|
assert calculate_rarity_cost_adjustment(99, 2, 2000) == 100 # min enforced
|
|
|
|
def test_special_to_common(self):
|
|
"""Special (99) to Common (5): -2400, min 5."""
|
|
assert calculate_rarity_cost_adjustment(99, 5, 2400) == 5 # min enforced
|
|
assert calculate_rarity_cost_adjustment(99, 5, 3000) == 600
|
|
|
|
def test_all_upward_transitions(self):
|
|
"""Test all transitions that increase rarity (decrease number)."""
|
|
# Common (5) moving up
|
|
assert calculate_rarity_cost_adjustment(5, 4, 10) == 30 # +20
|
|
assert calculate_rarity_cost_adjustment(5, 3, 10) == 90 # +80
|
|
assert calculate_rarity_cost_adjustment(5, 2, 10) == 270 # +260
|
|
assert calculate_rarity_cost_adjustment(5, 1, 10) == 810 # +800
|
|
|
|
# Bronze (4) moving up
|
|
assert calculate_rarity_cost_adjustment(4, 3, 30) == 90 # +60
|
|
assert calculate_rarity_cost_adjustment(4, 2, 30) == 270 # +240
|
|
assert calculate_rarity_cost_adjustment(4, 1, 30) == 810 # +780
|
|
|
|
# Silver (3) moving up
|
|
assert calculate_rarity_cost_adjustment(3, 2, 90) == 270 # +180
|
|
assert calculate_rarity_cost_adjustment(3, 1, 90) == 810 # +720
|
|
|
|
# Gold (2) moving up
|
|
assert calculate_rarity_cost_adjustment(2, 1, 270) == 810 # +540
|
|
|
|
def test_all_downward_transitions_with_minimums(self):
|
|
"""Test all transitions that decrease rarity (increase number) with minimum enforcement."""
|
|
# Diamond (1) moving down - all have minimums
|
|
assert calculate_rarity_cost_adjustment(1, 2, 100) == 100 # would be -440, min 100
|
|
assert calculate_rarity_cost_adjustment(1, 3, 100) == 50 # would be -620, min 50
|
|
assert calculate_rarity_cost_adjustment(1, 4, 100) == 15 # would be -680, min 15
|
|
assert calculate_rarity_cost_adjustment(1, 5, 100) == 5 # would be -700, min 5
|
|
|
|
# Gold (2) moving down - all have minimums
|
|
assert calculate_rarity_cost_adjustment(2, 3, 100) == 50 # would be -80, min 50
|
|
assert calculate_rarity_cost_adjustment(2, 4, 100) == 15 # would be -140, min 15
|
|
assert calculate_rarity_cost_adjustment(2, 5, 100) == 5 # would be -160, min 5
|
|
|
|
# Silver (3) moving down - all have minimums
|
|
assert calculate_rarity_cost_adjustment(3, 4, 50) == 15 # would be -10, min 15
|
|
assert calculate_rarity_cost_adjustment(3, 5, 50) == 5 # would be -30, min 5
|
|
|
|
def test_edge_cases(self):
|
|
"""Test edge cases: zero cost, very high cost, etc."""
|
|
# Zero cost
|
|
assert calculate_rarity_cost_adjustment(5, 1, 0) == 800
|
|
assert calculate_rarity_cost_adjustment(1, 5, 0) == 5 # min enforced
|
|
|
|
# Very high cost
|
|
assert calculate_rarity_cost_adjustment(5, 1, 10000) == 10800
|
|
assert calculate_rarity_cost_adjustment(99, 1, 10000) == 8400
|
|
|
|
def test_symmetry(self):
|
|
"""Test that adjustments are symmetric (up then down returns close to original)."""
|
|
# Diamond to Common and back (won't be exact due to minimums, but should be logical)
|
|
original = 810
|
|
after_down = calculate_rarity_cost_adjustment(1, 5, original) # 810 - 800 = 10, min 5 → 5
|
|
after_up = calculate_rarity_cost_adjustment(5, 1, after_down) # 5 + 800 = 805
|
|
assert after_down == 10
|
|
assert after_up == 810
|
|
|
|
# Gold to Bronze and back
|
|
original = 270
|
|
after_down = calculate_rarity_cost_adjustment(2, 4, original) # 270 - 240 = 30
|
|
after_up = calculate_rarity_cost_adjustment(4, 2, after_down) # 30 + 240 = 270
|
|
assert after_down == 30
|
|
assert after_up == 270
|
|
|
|
|
|
class TestRarityCostAdjustmentEdgeCases:
|
|
"""Test edge cases and error handling."""
|
|
|
|
def test_undefined_transition(self):
|
|
"""Test that undefined transitions are handled gracefully."""
|
|
# There's no transition from 1 to 1 (same), but it's handled
|
|
result = calculate_rarity_cost_adjustment(1, 1, 500)
|
|
assert result == 500
|
|
|
|
# There's no transition from rarity 10 (doesn't exist) but should return old cost
|
|
result = calculate_rarity_cost_adjustment(10, 5, 500)
|
|
assert result == 500 # Falls back to old cost
|
|
|
|
def test_negative_costs(self):
|
|
"""Test behavior with negative costs (shouldn't happen, but test it)."""
|
|
# Negative costs should still get adjusted
|
|
result = calculate_rarity_cost_adjustment(5, 1, -100)
|
|
assert result == 700 # -100 + 800 = 700
|