Adjusted a number of print statements to be logging statements

This commit is contained in:
mwisnowski 2024-12-31 09:25:21 -08:00
parent 6c0aaf26a0
commit a5f6e4f09e

View file

@ -1040,8 +1040,8 @@ class DeckBuilder:
logging.info('Checking total land count to ensure it\'s within ideal count.\n\n') logging.info('Checking total land count to ensure it\'s within ideal count.\n\n')
self.organize_library() self.organize_library()
while self.land_cards > int(self.ideal_land_count): while self.land_cards > int(self.ideal_land_count):
logging.info(f'Num land cards: {self.land_cards}\n' logging.info(f'Total lands: {self.land_cards}')
f'Ideal num land cards {self.ideal_land_count}') logging.info(f'Ideal lands: {self.ideal_land_count}')
self.remove_basic() self.remove_basic()
self.organize_library() self.organize_library()
@ -1098,7 +1098,7 @@ class DeckBuilder:
def add_standard_non_basics(self): def add_standard_non_basics(self):
# Add lands that are good in most any commander deck # Add lands that are good in most any commander deck
logging.info('Adding "standard" non-basics') print('Adding "standard" non-basics')
self.staples = ['Reliquary Tower'] self.staples = ['Reliquary Tower']
if 'Landfall' not in self.commander_tags: if 'Landfall' not in self.commander_tags:
self.staples.append('Ash Barrens') self.staples.append('Ash Barrens')
@ -1210,7 +1210,7 @@ class DeckBuilder:
self.land_df.to_csv(f'{csv_directory}/test_lands.csv', index=False) self.land_df.to_csv(f'{csv_directory}/test_lands.csv', index=False)
def add_kindred_lands(self): def add_kindred_lands(self):
logging.info('Adding lands that care about the commander having a Kindred theme.') print('Adding lands that care about the commander having a Kindred theme.')
logging.info('Adding general Kindred lands.') logging.info('Adding general Kindred lands.')
def create_land(name: str, land_type: str) -> dict: def create_land(name: str, land_type: str) -> dict:
@ -1359,7 +1359,7 @@ class DeckBuilder:
logging.info('Skipping adding Triome land cards.') logging.info('Skipping adding Triome land cards.')
def add_misc_lands(self): def add_misc_lands(self):
logging.info('Adding additional misc. lands to the deck that fit the color identity.') print('Adding additional misc. lands to the deck that fit the color identity.')
# Add other remaining lands that match color identity # Add other remaining lands that match color identity
logging.info('Grabbing lands in your commander\'s color identity that aren\'t already in the deck.') logging.info('Grabbing lands in your commander\'s color identity that aren\'t already in the deck.')
@ -1433,77 +1433,62 @@ class DeckBuilder:
logging.info(f"{land}: {count}") logging.info(f"{land}: {count}")
logging.info(f"Total basic lands: {self.total_basics}\n") logging.info(f"Total basic lands: {self.total_basics}\n")
def remove_basic(self): def remove_basic(self, max_attempts: int = 3):
""" """
Remove a basic land while maintaining color balance. Remove a basic land while maintaining color balance.
Attempts to remove from colors with more basics first. Attempts to remove from colors with more basics first.
Args:
max_attempts: Maximum number of removal attempts before falling back to non-basics
""" """
logging.info('Land count over ideal count, removing a basic land.') logging.info('Land count over ideal count, removing a basic land.')
# Map colors to basic land names
color_to_basic = { color_to_basic = {
'W': 'Plains', 'W': 'Plains', 'U': 'Island', 'B': 'Swamp',
'U': 'Island', 'R': 'Mountain', 'G': 'Forest'
'B': 'Swamp',
'R': 'Mountain',
'G': 'Forest'
} }
# Count basics of each type # Get current basic land counts using vectorized operations
basic_counts = {} basic_counts = {
for color in self.colors: basic: len(self.card_library[self.card_library['Card Name'] == basic])
basic = color_to_basic.get(color) for color, basic in color_to_basic.items()
if basic: if color in self.colors
count = len(self.card_library[self.card_library['Card Name'] == basic]) }
if count > 0:
basic_counts[basic] = count
sum_basics = sum(basic_counts.values())
attempts = 0
while attempts < max_attempts and sum_basics > self.min_basics:
if not basic_counts: if not basic_counts:
logging.warning("No basic lands found to remove") logging.warning("No basic lands found to remove")
return break
sum_basics = sum(basic_counts.values())
# Try to remove from color with most basics
basic_land = max(basic_counts.items(), key=lambda x: x[1])[0] basic_land = max(basic_counts.items(), key=lambda x: x[1])[0]
if sum_basics > self.min_basics:
try: try:
logging.info(f'Attempting to remove {basic_land}') # Use boolean indexing for efficiency
condition = self.card_library['Card Name'] == basic_land mask = self.card_library['Card Name'] == basic_land
index_to_drop = self.card_library[condition].index[0] if not mask.any():
basic_counts.pop(basic_land)
self.card_library = self.card_library.drop(index_to_drop) continue
self.card_library = self.card_library.reset_index(drop=True)
index_to_drop = self.card_library[mask].index[0]
self.card_library = self.card_library.drop(index_to_drop).reset_index(drop=True)
logging.info(f'{basic_land} removed successfully') logging.info(f'{basic_land} removed successfully')
self.check_basics() return
except (IndexError, KeyError) as e: except (IndexError, KeyError) as e:
logging.error(f"Error removing {basic_land}: {e}") logging.error(f"Error removing {basic_land}: {e}")
# Iterative approach instead of recursion basic_counts.pop(basic_land)
while basic_counts:
basic_counts.pop(basic_land, None)
if not basic_counts:
logging.error("Failed to remove any basic land")
break
basic_land = max(basic_counts.items(), key=lambda x: x[1])[0] attempts += 1
try:
condition = self.card_library['Card Name'] == basic_land # If we couldn't remove a basic land, try removing a non-basic
index_to_drop = self.card_library[condition].index[0] logging.warning("Could not remove basic land, attempting to remove non-basic")
self.card_library = self.card_library.drop(index_to_drop)
self.card_library = self.card_library.reset_index(drop=True)
logging.info(f'{basic_land} removed successfully')
self.check_basics()
break
except (IndexError, KeyError):
continue
else:
print(f'Not enough basic lands to keep the minimum of {self.min_basics}.')
self.remove_land() self.remove_land()
def remove_land(self): def remove_land(self):
"""Remove a random non-basic, non-staple land from the deck.""" """Remove a random non-basic, non-staple land from the deck."""
print('Removing a random nonbasic land.') logging.info('Removing a random nonbasic land.')
# Define basic lands including snow-covered variants # Define basic lands including snow-covered variants
basic_lands = [ basic_lands = [
@ -1520,25 +1505,25 @@ class DeckBuilder:
].copy() ].copy()
if len(library_filter) == 0: if len(library_filter) == 0:
print("No suitable non-basic lands found to remove.") logging.warning("No suitable non-basic lands found to remove.")
return return
# Select random land to remove # Select random land to remove
card_index = np.random.choice(library_filter.index) card_index = np.random.choice(library_filter.index)
card_name = self.card_library.loc[card_index, 'Card Name'] card_name = self.card_library.loc[card_index, 'Card Name']
print(f"Removing {card_name}") logging.info(f"Removing {card_name}")
self.card_library.drop(card_index, inplace=True) self.card_library.drop(card_index, inplace=True)
self.card_library.reset_index(drop=True, inplace=True) self.card_library.reset_index(drop=True, inplace=True)
print("Card removed successfully.") logging.info("Card removed successfully.")
except Exception as e: except Exception as e:
logging.error(f"Error removing land: {e}") logging.error(f"Error removing land: {e}")
print("Failed to remove land card.") logging.warning("Failed to remove land card.")
def count_pips(self): def count_pips(self):
"""Count and display the number of colored mana symbols in casting costs.""" """Count and display the number of colored mana symbols in casting costs."""
print('Analyzing color pip distribution...') logging.info('Analyzing color pip distribution...')
pip_counts = { pip_counts = {
'W': 0, 'U': 0, 'B': 0, 'R': 0, 'G': 0 'W': 0, 'U': 0, 'B': 0, 'R': 0, 'G': 0
@ -1550,15 +1535,15 @@ class DeckBuilder:
total_pips = sum(pip_counts.values()) total_pips = sum(pip_counts.values())
if total_pips == 0: if total_pips == 0:
print("No colored mana symbols found in casting costs.") logging.error("No colored mana symbols found in casting costs.")
return return
print("\nColor Pip Distribution:") logging.info("\nColor Pip Distribution:")
for color, count in pip_counts.items(): for color, count in pip_counts.items():
if count > 0: if count > 0:
percentage = (count / total_pips) * 100 percentage = (count / total_pips) * 100
print(f"{color}: {count} pips ({percentage:.1f}%)") print(f"{color}: {count} pips ({percentage:.1f}%)")
print(f"Total colored pips: {total_pips}\n") logging.info(f"Total colored pips: {total_pips}\n")
def get_cmc(self): def get_cmc(self):
"""Calculate average converted mana cost of non-land cards.""" """Calculate average converted mana cost of non-land cards."""
@ -1588,7 +1573,7 @@ class DeckBuilder:
# First grab the first 50/30/20 cards that match each theme # First grab the first 50/30/20 cards that match each theme
"""Add cards with specific tag up to ideal_value count""" """Add cards with specific tag up to ideal_value count"""
ideal_value = math.ceil(ideal * weight * 0.9) ideal_value = math.ceil(ideal * weight * 0.9)
logging.info(f'Finding {ideal_value} cards with the "{tag}" tag...') print(f'Finding {ideal_value} cards with the "{tag}" tag...')
if 'Kindred' in tag: if 'Kindred' in tag:
tags = [tag, 'Kindred Support'] tags = [tag, 'Kindred Support']
else: else:
@ -1644,7 +1629,7 @@ class DeckBuilder:
elif (card['name'] not in multiple_copy_cards elif (card['name'] not in multiple_copy_cards
and card['name'] in self.card_library['Card Name'].values): and card['name'] in self.card_library['Card Name'].values):
print(f"{card['name']} already in Library, skipping it.") logging.warning(f"{card['name']} already in Library, skipping it.")
continue continue
# Add selected cards to library # Add selected cards to library
@ -1660,7 +1645,7 @@ class DeckBuilder:
def add_by_tags(self, tag, ideal_value=1, df=None): def add_by_tags(self, tag, ideal_value=1, df=None):
"""Add cards with specific tag up to ideal_value count""" """Add cards with specific tag up to ideal_value count"""
logging.info(f'Finding {ideal_value} cards with the "{tag}" tag...') print(f'Finding {ideal_value} cards with the "{tag}" tag...')
# Filter cards with the given tag # Filter cards with the given tag
skip_creatures = self.creature_cards > self.ideal_creature_count * 1.1 skip_creatures = self.creature_cards > self.ideal_creature_count * 1.1
@ -1730,22 +1715,22 @@ class DeckBuilder:
with error handling to ensure the deck building process continues even if with error handling to ensure the deck building process continues even if
a particular theme encounters issues. a particular theme encounters issues.
""" """
logging.info(f'Adding creatures to deck based on the ideal creature count of {self.ideal_creature_count}...') print(f'Adding creatures to deck based on the ideal creature count of {self.ideal_creature_count}...')
try: try:
if self.hidden_theme: if self.hidden_theme:
logging.info(f'Processing Hidden theme: {self.hidden_theme}') print(f'Processing Hidden theme: {self.hidden_theme}')
self.weight_by_theme(self.hidden_theme, self.ideal_creature_count, self.hidden_weight, self.creature_df) self.weight_by_theme(self.hidden_theme, self.ideal_creature_count, self.hidden_weight, self.creature_df)
logging.info(f'Processing primary theme: {self.primary_theme}') print(f'Processing primary theme: {self.primary_theme}')
self.weight_by_theme(self.primary_theme, self.ideal_creature_count, self.primary_weight, self.creature_df) self.weight_by_theme(self.primary_theme, self.ideal_creature_count, self.primary_weight, self.creature_df)
if self.secondary_theme: if self.secondary_theme:
logging.info(f'Processing secondary theme: {self.secondary_theme}') print(f'Processing secondary theme: {self.secondary_theme}')
self.weight_by_theme(self.secondary_theme, self.ideal_creature_count, self.secondary_weight, self.creature_df) self.weight_by_theme(self.secondary_theme, self.ideal_creature_count, self.secondary_weight, self.creature_df)
if self.tertiary_theme: if self.tertiary_theme:
logging.info(f'Processing tertiary theme: {self.tertiary_theme}') print(f'Processing tertiary theme: {self.tertiary_theme}')
self.weight_by_theme(self.tertiary_theme, self.ideal_creature_count, self.tertiary_weight, self.creature_df) self.weight_by_theme(self.tertiary_theme, self.ideal_creature_count, self.tertiary_weight, self.creature_df)
except Exception as e: except Exception as e: