import re def parse_deck_list(text): """ Parses a deck list string and returns a list of dictionaries with quantity, card name, and is_sideboard. Supported formats: - Arena/Moxfield: "1 Laughing Jasper Flint (OTJ) 215 *F*" - MTGO: "1 Arcane Signet" - Plain Text: "1 Arcane Signet" Returns: list of dict: [{'quantity': int, 'name': str, 'is_sideboard': bool}] """ lines = text.strip().split('\n') parsed_cards = [] is_sideboard = False # Regex for Arena/Moxfield lines: e.g., "1 Card Name (SET) 123" # Captures: Qty, Name # We ignore Set code and collector number for lookup simplicity for now, relying on name. # Pattern: Digit+ space Name space (SetCode) space ... arena_pattern = re.compile(r'^(\d+)\s+(.+?)\s+\([A-Z0-9]+\)\s+\S+') # Regex for simple Quantity + Name: "1 Card Name" simple_pattern = re.compile(r'^(\d+)\s+(.+)$') for line in lines: line = line.strip() if not line: continue if line.lower().startswith('sideboard'): is_sideboard = True continue # Try Arena/Moxfield/detailed format first match = arena_pattern.match(line) if match: qty = int(match.group(1)) name = match.group(2).strip() parsed_cards.append({ 'quantity': qty, 'name': name, 'is_sideboard': is_sideboard }) continue # Try simple format match = simple_pattern.match(line) if match: qty = int(match.group(1)) name = match.group(2).strip() parsed_cards.append({ 'quantity': qty, 'name': name, 'is_sideboard': is_sideboard }) continue return parsed_cards