lib/cw_card_utils/decklist_parser/parser.rb
# frozen_string_literal: true module CwCardUtils module DecklistParser # Parses a decklist and returns a Deck object. class Parser attr_reader :deck def initialize(decklist, cmc_data_source = nil) @decklist = decklist.is_a?(IO) ? decklist.read : decklist @deck = Deck.new(cmc_data_source || CwCardUtils.card_data_source) end def inspect "<DecklistParser::Parser: #{@decklist.length}>" end # Parses the decklist and returns a Deck object. def parse return @deck if @deck.any? sideboard = false @decklist.each_line do |line| line = line.strip next if line.empty? sideboard = true if line.downcase.start_with?("sideboard") && (sideboard == false) if line.match?(/^(Deck|Sideboard|About|Commander|Creatures|Lands|Spells|Artifacts|Enchantments|Planeswalkers|Mainboard|Maybeboard|Companion)/i) next end next if line.start_with?("#") # skip comment-style lines next if line.start_with?("//") # skip comment-style lines next if line.start_with?("Name") # skip deck name # Match patterns like: "4 Lightning Bolt", "2 Sol Ring (CMM) 452", "1 Atraxa, Praetors' Voice" next unless match = line.match(/^(\d+)\s+(.+?)(?:\s+\(.*?\)\s+\d+)?$/) # rubocop:disable Lint/AssignmentInCondition count = match[1].to_i name = match[2].strip target = sideboard ? :sideboard : :mainboard @deck.add({ count: count, name: name }, target) end @deck end end end end