class Ecu::Kennfeld

def bytesize

def bytesize
  (xdim + 1) * (ydim + 1) * BYTESIZE[:number]
end

def equality_properties

def equality_properties
  [:name, :xvalue, :yvalue, :value]
end

def initialize(name:,

def initialize(name:,
               xdim:,
               ydim:,
               xvalue:,
               yvalue:,
               value:,
               xunit: nil,
               yunit: nil,
               unit: nil,
               function: nil,
               description: nil)
  value        = value.size > ydim ? value.each_slice(xdim).to_a : value
  @name        = name
  @xdim        = xdim
  @ydim        = ydim
  @xvalue      = xvalue
  @yvalue      = yvalue
  @value       = value
  @xunit       = xunit
  @yunit       = yunit
  @unit        = unit
  @function    = function
  @description = description
  init_error "Dimension mismatch: xvalue=#{xvalue.size} xdim=#{xdim}" if xvalue.size != xdim
  init_error "Dimension mismatch: yvalue=#{yvalue.size} ydim=#{ydim}" if yvalue.size != ydim
  init_error "Dimension mismatch: value.x=#{value.size} ydim=#{ydim}" if value.size != ydim
  init_error "Dimension mismatch: value.y=XXX xdim=#{xdim}" if value.any? { |r| r.size != xdim }
end

def properties

def properties
  [:name, :xdim, :ydim, :xvalue, :yvalue, :value, :xunit, :yunit, :unit, :function, :description]
end

def reinterpx(new_xvalue)

def reinterpx(new_xvalue)
  self.with \
    xvalue: new_xvalue,
    value: yvalue.map { |y| new_xvalue.map { |x| value_at(x, y) } }
end

def reinterpy(new_yvalue)

def reinterpy(new_yvalue)
  self.with \
    yvalue: new_yvalue,
    value: new_yvalue.map { |y| xvalue.map { |x| value_at(x, y) } }
end

def round_to(n)

def round_to(n)
  hsh = Hash.new
  hsh[:xvalue] = xvalue.map { |x| x.round(n) } if xvalue.all? { |x| x.is_a?(Numeric) }
  hsh[:yvalue] = yvalue.map { |x| x.round(n) } if yvalue.all? { |x| x.is_a?(Numeric) }
  if value.all? { |row| row.all? { |x| x.is_a?(Numeric) }}
    hsh[:value] = value.map { |row| row.map { |x| x.round(n) }}
  end
  self.with hsh
end

def to_dcm(indented=false)

def to_dcm(indented=false)
  fmtstr = indented ? "%-25s%s %s %s\n" : "%s %s %d %d\n"
  sprintf(fmtstr, type.upcase, name, xdim, ydim).tap do |str|
    str << "  LANGNAME #{description.enquote}\n" if description
    str << "  FUNKTION #{function}\n"            if function
    str << "  EINHEIT_X #{xunit.enquote}\n"      if xunit
    str << "  EINHEIT_Y #{yunit.enquote}\n"      if yunit
    str << "  EINHEIT_W #{unit.enquote}\n"       if unit
    str << case xvalue.first
          when Numeric then "  ST/X #{xvalue.join("   ")}\n"
          when String  then "  ST_TX/X #{xvalue.map(&:enquote).join("   ")}\n"
          end
    yvalue.each_with_index do |entry, idx|
      str << case entry
            when Numeric then "  ST/Y #{entry}\n"
            when String  then "  ST_TX/Y #{entry.enquote}\n"
            end
      str << case value[idx].first
            when Numeric then "  WERT #{value[idx].join("   ")}\n"
            when String  then "  TEXT #{value[idx].map(&:enquote).join("   ")}\n"
            end
    end
    str << "END\n"
  end
end

def to_mfile

def to_mfile
  "#{name} = [\n".tap do |str|
    value.each do |row|
      str << row.join("  ").indent << "\n"
    end
    str << "];\n"
  end
end

def to_s(detail: false)

def to_s(detail: false)
  if detail == :value
    "#{name}:\n#{to_s(detail: :justvalue)}"
  elsif detail == :justvalue
    ValuePrinter.call(self)
  elsif detail == :onelinefull
    "#{name} #{to_s(detail: :oneline)}"
  elsif detail == :oneline
    "(#{xdim}x#{ydim}) " +
      "X: #{valuestats(xvalue)}, " +
      "Y: #{valuestats(yvalue)}, " +
      "Z: #{valuestats(value, show_avg: true)}"
  else
    "#{name}: #{@xdim}x#{@ydim} #{type}".tap do |str|
      if detail
        str << "\n"
        str << "  x-Unit: \"#{xunit}\"\n"
        str << "  y-Unit: \"#{yunit}\"\n"
        str << "  z-Unit: \"#{unit}\"\n"
        str << "  Value:\n"
        str << ValuePrinter.call(self).indent(4)
        str << "\n"
      end
    end
  end
end

def value_at(x, y)

def value_at(x, y)
  Interpolator.interp2(xvalue, yvalue, value, x, y)
end