require "simple_xlsx_reader" class Codinginfo CVAR_PREFIX_REGEXP = /^CVAR_[A-Za-z0-9_]+_\d+\./ PARAM_ASSIGNMENT_HEADERS = { name: /Parameter/, cvar: /Schalter/, package: /Komponente/ } class Cvar # The CVAR must have a name and _may_ have a package and value # the package and value can be merged attr_reader :name, :value, :package def initialize(name:, package: nil, value: nil) @name = name @package = package @value = value end def label_prefix return /^#{name}_(\w+_)?#{value}\./ if package.nil? [name, package, value].join("_") + "." end def to_s = "#{name}=#{value}" def ==(other) = name == other.name def merge(other) fail "Cannot merge #{name} with #{other.name}" unless self == other self.class.new \ name: name, package: package || other.package, value: value || other.value end end class Variant def initialize(headers, row) @properties = headers.zip(row).to_h end def cvars @properties .select { |key, _| key.match?(/^CVAR_/) } .map { Cvar.new(name: _1, value: _2.to_i) } end end def initialize(ids, filepath) @doc = SimpleXlsxReader.open(filepath) @headers = [] @variants = [] @assignments = {} overview_sheet .rows .each do |row| parse_headers(row) if @headers.empty? next if @headers.empty? next if row[1].nil? || row[3].nil? next unless ids.any? { row[1].match?(/#{_1}/i) } next unless row[3].match?(/CVAR/) @variants << Variant.new(@headers, row) end param_assignment_sheet .rows .each(headers: PARAM_ASSIGNMENT_HEADERS) do |row| next if row[:cvar].nil? @assignments[row[:name]] = Cvar.new(name: row[:cvar], package: row[:package]) end end def overview_sheet @doc .sheets .find { _1.name == "Gesamtübersicht" } .tap { fail "Cannot find sheet Gesamtübersicht" if _1.nil? } end def param_assignment_sheet @doc .sheets .find { _1.name == "Parameterdefinition" } .tap { fail "Cannot find sheet Parameterdefinition" if _1.nil? } end def variant fail "No variant matching #{id} found!" if @variants.empty? fail "More than one variant matching #{id} found!" if @variants.size > 1 @variants.first end def unflatten_list(list) Ecu::LabelList.new \ list.flat_map { |label| if has_cvar_assignment?(label) @variants.map { label.with(name: add_cvar_prefix(label, _1)) } else label end } end def flatten_list(list) list .select { !cvar_coded?(_1) || has_matching_cvar?(_1) } .map_int { _1.with(name: remove_cvar_prefix(_1.name)) } end def cvar_coded?(label) label.name.match?(CVAR_PREFIX_REGEXP) end def has_cvar_assignment?(label) @assignments.key?(label.name) end def has_matching_cvar?(label) variant.cvars.any? { label.name.match?(_1.label_prefix) } end def add_cvar_prefix(label, variant) variant .cvars .find { _1 == @assignments[label.name] } .then { _1.merge(@assignments[label.name]) } .then { _1.label_prefix + label.name } end def remove_cvar_prefix(name) name.sub(CVAR_PREFIX_REGEXP, "") end def parse_headers(row) return unless row[1]&.match?(/SWFK-ID/) return unless row[1]&.match?(/CVAR_BeguData/) return unless row[2]&.match?(/Kommentar/) @headers = row .map(&:chomp) .map(&:lstrip) .map(&:strip) .map { _1.sub(/\n.*/, "") } .tap { _1[0] = "typestr" } end end