automotive-ecu 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/bin/bundle +114 -0
  3. data/bin/coderay +29 -0
  4. data/bin/console +14 -0
  5. data/bin/htmldiff +29 -0
  6. data/bin/irb +29 -0
  7. data/bin/ldiff +29 -0
  8. data/bin/pry +29 -0
  9. data/bin/rake +29 -0
  10. data/bin/rspec +29 -0
  11. data/bin/setup +8 -0
  12. data/lib/core_ext.rb +69 -0
  13. data/lib/ecu/combined_list.rb +25 -0
  14. data/lib/ecu/combined_list_comparison.rb +50 -0
  15. data/lib/ecu/interfaces/a2l/label_list.rb +18 -0
  16. data/lib/ecu/interfaces/a2l/signal_list.rb +15 -0
  17. data/lib/ecu/interfaces/dbc/signal_list.rb +12 -0
  18. data/lib/ecu/interfaces/dcm/buffer.rb +39 -0
  19. data/lib/ecu/interfaces/dcm/festkennfeld.rb +9 -0
  20. data/lib/ecu/interfaces/dcm/festkennlinie.rb +9 -0
  21. data/lib/ecu/interfaces/dcm/festwert.rb +20 -0
  22. data/lib/ecu/interfaces/dcm/festwerteblock.rb +26 -0
  23. data/lib/ecu/interfaces/dcm/functions.rb +13 -0
  24. data/lib/ecu/interfaces/dcm/gruppenkennfeld.rb +9 -0
  25. data/lib/ecu/interfaces/dcm/gruppenkennlinie.rb +9 -0
  26. data/lib/ecu/interfaces/dcm/kennfeld.rb +32 -0
  27. data/lib/ecu/interfaces/dcm/kennlinie.rb +25 -0
  28. data/lib/ecu/interfaces/dcm/label.rb +25 -0
  29. data/lib/ecu/interfaces/dcm/label_list.rb +94 -0
  30. data/lib/ecu/interfaces/dcm/malformed_dcm_error.rb +34 -0
  31. data/lib/ecu/interfaces/dcm/property_parser.rb +51 -0
  32. data/lib/ecu/interfaces/dcm/stuetzstellenverteilung.rb +20 -0
  33. data/lib/ecu/interfaces/lab/combined_list.rb +32 -0
  34. data/lib/ecu/interfaces/lab/lab_parser.rb +61 -0
  35. data/lib/ecu/interfaces/lab/label.rb +21 -0
  36. data/lib/ecu/interfaces/lab/label_list.rb +29 -0
  37. data/lib/ecu/interfaces/lab/signal.rb +15 -0
  38. data/lib/ecu/interfaces/lab/signal_list.rb +29 -0
  39. data/lib/ecu/interfaces/mfile/festwert.rb +10 -0
  40. data/lib/ecu/interfaces/mfile/festwerteblock.rb +12 -0
  41. data/lib/ecu/interfaces/mfile/kennfeld.rb +12 -0
  42. data/lib/ecu/interfaces/mfile/kennlinie.rb +7 -0
  43. data/lib/ecu/interfaces/mfile/label_list.rb +13 -0
  44. data/lib/ecu/interfaces/mfile/stuetzstellenverteilung.rb +7 -0
  45. data/lib/ecu/labels/festwert.rb +58 -0
  46. data/lib/ecu/labels/festwerteblock.rb +80 -0
  47. data/lib/ecu/labels/interpolator.rb +55 -0
  48. data/lib/ecu/labels/kennfeld.rb +107 -0
  49. data/lib/ecu/labels/kennlinie.rb +84 -0
  50. data/lib/ecu/labels/label.rb +82 -0
  51. data/lib/ecu/labels/label_list.rb +137 -0
  52. data/lib/ecu/labels/label_list_comparison.rb +65 -0
  53. data/lib/ecu/labels/stuetzstellenverteilung.rb +65 -0
  54. data/lib/ecu/labels/value_comparison.rb +37 -0
  55. data/lib/ecu/labels/value_printer.rb +49 -0
  56. data/lib/ecu/labels.rb +2 -0
  57. data/lib/ecu/signals/signal.rb +73 -0
  58. data/lib/ecu/signals/signal_list.rb +68 -0
  59. data/lib/ecu/signals/signal_list_comparison.rb +52 -0
  60. data/lib/ecu/signals.rb +2 -0
  61. data/lib/ecu/version.rb +3 -0
  62. data/lib/ecu.rb +59 -0
  63. metadata +161 -0
@@ -0,0 +1,9 @@
1
+ require_relative "kennfeld"
2
+
3
+ class Ecu
4
+ class Gruppenkennfeld < Kennfeld
5
+ def self.dcm_header
6
+ %r{^GRUPPENKENNFELD\s+(?<name>[A-Za-z0-9\._]+)\s+(?<xdim>\d+)\s+(?<ydim>\d+)}
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require_relative "kennlinie"
2
+
3
+ class Ecu
4
+ class Gruppenkennlinie < Kennlinie
5
+ def self.dcm_header
6
+ %r{^GRUPPENKENNLINIE\s+(?<name>[A-Za-z0-9\._]+)\s+(?<xdim>\d+)}
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,32 @@
1
+ class Ecu
2
+ class Kennfeld < Label
3
+ def self.dcm_header
4
+ %r{^KENNFELD\s+(?<name>[A-Za-z0-9\._]+)\s+(?<xdim>\d+)\s+(?<ydim>\d+)}
5
+ end
6
+
7
+ def to_dcm
8
+ "#{type.upcase} #{name} #{xdim} #{ydim}\n".tap do |str|
9
+ str << " LANGNAME #{description.enquote}\n" if description
10
+ str << " FUNKTION #{function}\n" if function
11
+ str << " EINHEIT_X #{xunit.enquote}\n" if xunit
12
+ str << " EINHEIT_Y #{yunit.enquote}\n" if yunit
13
+ str << " EINHEIT_W #{unit.enquote}\n" if unit
14
+ str << case xvalue.first
15
+ when Numeric then " ST/X #{xvalue.join(" ")}\n"
16
+ when String then " ST_TX/X #{xvalue.map(&:enquote).join(" ")}\n"
17
+ end
18
+ yvalue.each_with_index do |entry, idx|
19
+ str << case entry
20
+ when Numeric then " ST/Y #{entry}\n"
21
+ when String then " ST_TX/Y #{entry.enquote}\n"
22
+ end
23
+ str << case value[idx].first
24
+ when Numeric then " WERT #{value[idx].join(" ")}\n"
25
+ when String then " TEXT #{value[idx].map(&:enquote).join(" ")}\n"
26
+ end
27
+ end
28
+ str << "END\n"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ class Ecu
2
+ class Kennlinie < Label
3
+ def self.dcm_header
4
+ %r{^KENNLINIE\s+(?<name>[A-Za-z0-9\._]+)\s+(?<xdim>\d+)}
5
+ end
6
+
7
+ def to_dcm
8
+ "#{type.upcase} #{name} #{xdim}\n".tap do |str|
9
+ str << " LANGNAME #{description.enquote}\n" if description
10
+ str << " FUNKTION #{function}\n" if function
11
+ str << " EINHEIT_X #{xunit.enquote}\n" if xunit
12
+ str << " EINHEIT_W #{unit.enquote}\n" if unit
13
+ str << case xvalue.first
14
+ when Numeric then " ST/X #{xvalue.join(" ")}\n"
15
+ when String then " ST_TX/X #{xvalue.map(&:enquote).join(" ")}\n"
16
+ end
17
+ str << case value.first
18
+ when Numeric then " WERT #{value.join(" ")}\n"
19
+ when String then " TEXT #{value.map(&:enquote).join(" ")}\n"
20
+ end
21
+ str << "END\n"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ require_relative "property_parser"
2
+
3
+ class Ecu
4
+ class Label
5
+ def self.from_dcm(input)
6
+ lines = case input
7
+ in Array then input
8
+ in String then input.lines
9
+ end
10
+ hsh = dcm_header.extract_captures(lines.first)
11
+
12
+ hsh[:xdim] = hsh[:xdim].to_i if hsh.key?(:xdim)
13
+ hsh[:ydim] = hsh[:ydim].to_i if hsh.key?(:ydim)
14
+
15
+ fail "Malformed DCM" if hsh.empty?
16
+ fail "Malformed DCM" unless lines.last.match?(/^END$/)
17
+
18
+ lines[1..-2]
19
+ .map { DcmPropertyParser.call(_1) }
20
+ .each { hsh.merge!(_1) { |_, old, new| old + new } }
21
+
22
+ new(**hsh)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,94 @@
1
+ require_relative "functions"
2
+ require_relative "festwert"
3
+ require_relative "festwerteblock"
4
+ require_relative "kennlinie"
5
+ require_relative "gruppenkennlinie"
6
+ require_relative "festkennlinie"
7
+ require_relative "kennfeld"
8
+ require_relative "gruppenkennfeld"
9
+ require_relative "festkennfeld"
10
+ require_relative "stuetzstellenverteilung"
11
+ require_relative "malformed_dcm_error"
12
+ require_relative "buffer"
13
+
14
+ class Ecu
15
+ class LabelList
16
+
17
+ DCM_HEADER = "KONSERVIERUNG_FORMAT 2.0"
18
+ BLANKLINE_REGEX = /^\s*$/
19
+ COMMENT_REGEX = /^\*.*/
20
+
21
+ def self.from_dcm(str)
22
+ buffer = DcmBuffer.new
23
+ headers = []
24
+ subheaders = []
25
+ functions = []
26
+ labels = {}
27
+
28
+ str.each_line.lazy.with_index(1).each do |line, n|
29
+ line = normalize_whitespace(line)
30
+ case line
31
+ when BLANKLINE_REGEX then next
32
+ when COMMENT_REGEX
33
+ case buffer.header
34
+ when :pre then headers << line[1..].strip
35
+ when :after then subheaders << line[1..].strip
36
+ when :done then # Header time over, do nothing
37
+ end
38
+ when DCM_HEADER then buffer.header_seen!
39
+ when Functions.dcm_header then buffer.start!(Functions, [line])
40
+ when Festwert.dcm_header then buffer.start!(Festwert, [line])
41
+ when Festwerteblock.dcm_header then buffer.start!(Festwerteblock, [line])
42
+ when Kennlinie.dcm_header then buffer.start!(Kennlinie, [line])
43
+ when Gruppenkennlinie.dcm_header then buffer.start!(Gruppenkennlinie, [line])
44
+ when Festkennlinie.dcm_header then buffer.start!(Festkennlinie, [line])
45
+ when Kennfeld.dcm_header then buffer.start!(Kennfeld, [line])
46
+ when Gruppenkennfeld.dcm_header then buffer.start!(Gruppenkennfeld, [line])
47
+ when Festkennfeld.dcm_header then buffer.start!(Festkennfeld, [line])
48
+ when Stuetzstellenverteilung.dcm_header then buffer.start!(Stuetzstellenverteilung, [line])
49
+ when "END" then
50
+ case obj = buffer.finish!(line)
51
+ when Label
52
+ fail "Duplicate label #{obj.name}" unless labels[obj.name].nil?
53
+
54
+ labels[obj.name] = obj
55
+ when Functions
56
+ fail "Duplicate functions definition" unless functions.empty?
57
+
58
+ functions = obj
59
+ else
60
+ fail "Unknown object #{obj}"
61
+ end
62
+ else
63
+ buffer.append!(line)
64
+ end
65
+ rescue RuntimeError => e
66
+ raise MalformedDcmError.new(e.message, n, str), e.message
67
+ end
68
+
69
+ new(labels.values, headers, subheaders, true)
70
+ end
71
+
72
+ def self.normalize_whitespace(line)
73
+ line.chomp.gsub(/[[:space:]]/, " ").rstrip
74
+ end
75
+
76
+ def to_dcm
77
+ out = []
78
+
79
+ unless headers.empty?
80
+ out += headers.map { "* " + _1 }.push("")
81
+ end
82
+
83
+ out << DCM_HEADER << ""
84
+
85
+ unless subheaders.empty?
86
+ out += subheaders.map { "* " + _1 }.push("")
87
+ end
88
+
89
+ out += map(&:to_dcm)
90
+
91
+ out.join("\n")
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,34 @@
1
+ class Ecu
2
+ class MalformedDcmError < StandardError
3
+ attr_reader :lineno, :filecontent
4
+ def initialize(msg, lineno, filecontent)
5
+ super(msg)
6
+ @lineno = lineno
7
+ @filecontent = filecontent
8
+ end
9
+
10
+ def to_s = "Malformed DCM: #{super} near line ##{lineno}"
11
+ def to_str = to_s
12
+
13
+ def context
14
+ filecontent
15
+ .lines
16
+ .each
17
+ .with_index(1)
18
+ .map { |line, n| present(line, n, n == lineno) }
19
+ .then { _1[ctx_startline..ctx_endline] }
20
+ end
21
+
22
+ def present(line, n, highlight)
23
+ case highlight
24
+ when true then fmt(n) + " => | " + line
25
+ when false then fmt(n) + " | " + line
26
+ end
27
+ end
28
+
29
+ def ctx_startline = [0, lineno - 7].max
30
+ def ctx_endline = @endline ||= [filecontent.lines.count - 1, lineno + 3].min
31
+ def fmt_str = "%#{(ctx_endline + 1).to_s.length}d"
32
+ def fmt(n) = fmt_str % n
33
+ end
34
+ end
@@ -0,0 +1,51 @@
1
+ class Ecu
2
+ class DcmPropertyParser
3
+
4
+ def self.call(line)
5
+ key, _, value = line.strip.partition(/\s+/)
6
+ eval_property(key, value)
7
+ end
8
+
9
+ private
10
+
11
+ def self.eval_property(key, value)
12
+ case key
13
+ when "ST/X" then { xvalue: numeric_array(value) }
14
+ when "ST/Y" then { yvalue: numeric_array(value) }
15
+ when "WERT" then { value: numeric_array(value) }
16
+ when "ST_TX/X" then { xvalue: string_array(value) }
17
+ when "ST_TX/Y" then { yvalue: string_array(value) }
18
+ when "TEXT" then { value: string_array(value) }
19
+ when "FUNKTION" then { function: value }
20
+ when "EINHEIT_X" then { xunit: string_value(value) }
21
+ when "EINHEIT_Y" then { yunit: string_value(value) }
22
+ when "EINHEIT_W" then { unit: string_value(value) }
23
+ when "LANGNAME" then { description: string_value(value) }
24
+ when "DISPLAYNAME" then { }
25
+ else fail ArgumentError, "Unknown key #{key}"
26
+ end
27
+ end
28
+
29
+ def self.string_value(str)
30
+ str.delete_surrounding('"')
31
+ end
32
+
33
+ def self.numeric_array(str)
34
+ str.split.map { Float(_1) rescue Label::InvalidValue.new(_1) }
35
+ end
36
+
37
+ def self.string_array(str)
38
+ str.scan(/"([^"]*)"/).flatten
39
+ end
40
+
41
+ end
42
+
43
+ class Label
44
+ InvalidValue = Struct.new(:value) do
45
+ def to_s
46
+ "<InvalidValue: \"#{value}\">"
47
+ end
48
+ def inspect; to_s; end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,20 @@
1
+ class Ecu
2
+ class Stuetzstellenverteilung < Label
3
+ def self.dcm_header
4
+ %r{STUETZSTELLENVERTEILUNG\s+(?<name>[A-Za-z0-9\._]+)\s+(?<xdim>\d+)}
5
+ end
6
+
7
+ def to_dcm
8
+ "#{type.upcase} #{name} #{xdim}\n".tap do |str|
9
+ str << " LANGNAME #{description.enquote}\n" if description
10
+ str << " FUNKTION #{function}\n" if function
11
+ str << " EINHEIT_X #{xunit.enquote}\n" if xunit
12
+ str << case xvalue.first
13
+ when Numeric then " ST/X #{xvalue.join(" ")}\n"
14
+ when String then " ST_TX/X #{xvalue.map(&:enquote).join(" ")}\n"
15
+ end
16
+ str << "END\n"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,32 @@
1
+ require_relative "signal_list"
2
+ require_relative "label_list"
3
+
4
+ class Ecu
5
+ class CombinedList
6
+ def self.from_lab(str)
7
+ signals, labels, headers, subheaders = LabParser.call(str)
8
+ new(signals, labels, headers, subheaders)
9
+ end
10
+
11
+ def to_lab
12
+ out = []
13
+
14
+ out.append(*headers.map { |l| "; #{l}" }, "") unless headers.empty?
15
+
16
+ out.append("[SETTINGS]")
17
+ out.append("Version;V1.1")
18
+ out.append("MultiRasterSeparator;&")
19
+ out.append("")
20
+
21
+ out.append(*subheaders.map { |l| "; #{l}" }, "") unless subheaders.empty?
22
+
23
+ out.append("[RAMCELL]")
24
+ out.append(*signals.map(&:to_lab))
25
+
26
+ out.append("[Label]")
27
+ out.append(*labels.map(&:to_lab))
28
+
29
+ out.join("\n")
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,61 @@
1
+ require_relative "../../labels"
2
+ require_relative "../../signals"
3
+
4
+ class LabParser
5
+ def self.call(str)
6
+ lines = str.lines
7
+
8
+ [
9
+ extract_signals(block_bounded_by(lines, "[RAMCELL]", /\A\[/)),
10
+ extract_labels(block_bounded_by(lines, "[Label]", /\A\[/)),
11
+ extract_headers(block_bounded_by(lines, 0, "[SETTINGS]")),
12
+ extract_headers(block_bounded_by(lines, "[SETTINGS]", /\A\[/)),
13
+ ]
14
+ end
15
+
16
+ def self.extract_labels(lines)
17
+ Ecu::LabelList.new lines.
18
+ reject { |l| l.blank? }.
19
+ reject { |l| l.start_with?(";") }.
20
+ map { |l| Ecu::Label.from_lab(l) }
21
+ end
22
+
23
+ def self.extract_signals(lines)
24
+ Ecu::SignalList.new lines.
25
+ reject { |l| l.blank? }.
26
+ reject { |l| l.start_with?(";") }.
27
+ map { |l| Ecu::Signal.from_lab(l) }
28
+ end
29
+
30
+ def self.extract_headers(lines)
31
+ lines.
32
+ select { |l| l.match(/\A; /) }.
33
+ map { |l| l[2..-1].chomp }
34
+ end
35
+
36
+ def self.block_bounded_by(lines, upper, lower)
37
+ upper = case upper
38
+ when Integer then upper
39
+ when String
40
+ return [] unless lines.any? { |l| l.strip.downcase == upper.downcase }
41
+ lines.index { |l| l.strip.downcase == upper.downcase } + 1
42
+ when Regexp
43
+ return [] unless lines.any? { |l| l.match?(upper) }
44
+ lines.index { |l| l.match?(upper) } + 1
45
+ end
46
+
47
+ segment = lines[upper..-1]
48
+
49
+ lower = case lower
50
+ when Integer then lower
51
+ when String
52
+ return lines[upper..-1] unless segment.any? { |l| l.strip.downcase == lower.downcase }
53
+ upper + segment.index { |l| l.strip.downcase == lower.downcase }
54
+ when Regexp
55
+ return lines[upper..-1] unless segment.any? { |l| l.match?(lower) }
56
+ upper + segment.index { |l| l.match?(lower) }
57
+ end
58
+
59
+ lines[upper...lower]
60
+ end
61
+ end
@@ -0,0 +1,21 @@
1
+ class Ecu
2
+ class Label
3
+
4
+ # This is a silly hack, since the *.lab file doesn't contain any information
5
+ # about the label in question (just the name). Subsequently, just initialize
6
+ # a Festwert with no value and hope if does the job correctly
7
+
8
+ def self.from_lab(line)
9
+ name, description = line.strip.split(";")
10
+ if description.nil?
11
+ Festwert.new(name: name, value: nil)
12
+ else
13
+ Festwert.new(name: name, value: nil, description: description)
14
+ end
15
+ end
16
+
17
+ def to_lab
18
+ "#{name};#{description}"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ require_relative "../../../core_ext"
2
+ require_relative "lab_parser"
3
+
4
+ class Ecu
5
+ class LabelList
6
+ def self.from_lab(str)
7
+ _, labels, headers, subheaders = LabParser.call(str)
8
+ new(labels, headers, subheaders)
9
+ end
10
+
11
+ def to_lab
12
+ out = []
13
+
14
+ out.append(*headers.map { |l| "; #{l}" }, "") unless headers.empty?
15
+
16
+ out.append("[SETTINGS]")
17
+ out.append("Version;V1.1")
18
+ out.append("MultiRasterSeparator;&")
19
+ out.append("")
20
+
21
+ out.append(*subheaders.map { |l| "; #{l}" }, "") unless subheaders.empty?
22
+
23
+ out.append("[Label]")
24
+ out.append(*map(&:to_lab))
25
+
26
+ out.join("\n")
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,15 @@
1
+ class Ecu
2
+ class Signal
3
+ def self.from_lab(line)
4
+ name, tasks, comment = line.strip.split(";")
5
+ maintask = tasks.split("&").first rescue nil
6
+ new(name: name,
7
+ task: maintask,
8
+ description: comment&.strip)
9
+ end
10
+
11
+ def to_lab
12
+ "#{name};#{task};#{description}"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,29 @@
1
+ require_relative "../../../core_ext"
2
+ require_relative "lab_parser"
3
+
4
+ class Ecu
5
+ class SignalList
6
+ def self.from_lab(str)
7
+ signals, _, headers, subheaders = LabParser.call(str)
8
+ new(signals, headers, subheaders)
9
+ end
10
+
11
+ def to_lab
12
+ out = []
13
+
14
+ out.append(*headers.map { |l| "; #{l}" }, "") unless headers.empty?
15
+
16
+ out.append("[SETTINGS]")
17
+ out.append("Version;V1.1")
18
+ out.append("MultiRasterSeparator;&")
19
+ out.append("")
20
+
21
+ out.append(*subheaders.map { |l| "; #{l}" }, "") unless subheaders.empty?
22
+
23
+ out.append("[RAMCELL]")
24
+ out.append(*map(&:to_lab))
25
+
26
+ out.join("\n")
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,10 @@
1
+ class Ecu
2
+ class Festwert < Label
3
+ def to_mfile
4
+ case value
5
+ when Numeric then "#{name} = #{value};\n"
6
+ when String then "#{name} = '#{value}';\n"
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ class Ecu
2
+ class Festwerteblock < Label
3
+ def to_mfile
4
+ "#{name} = [\n".tap do |str|
5
+ value.each do |row|
6
+ str << row.join(" ").indent << "\n"
7
+ end
8
+ str << "];\n"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ class Ecu
2
+ class Kennfeld < Label
3
+ def to_mfile
4
+ "#{name} = [\n".tap do |str|
5
+ value.each do |row|
6
+ str << row.join(" ").indent << "\n"
7
+ end
8
+ str << "];\n"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ class Ecu
2
+ class Kennlinie < Label
3
+ def to_mfile
4
+ "#{name} = [#{value.join(" ")}];\n"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ require_relative "festwert"
2
+ require_relative "festwerteblock"
3
+ require_relative "kennlinie"
4
+ require_relative "kennfeld"
5
+ require_relative "stuetzstellenverteilung"
6
+
7
+ class Ecu
8
+ class LabelList
9
+ def to_mfile
10
+ self.map(&:to_mfile).join("\n")
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ class Ecu
2
+ class Stuetzstellenverteilung < Label
3
+ def to_mfile
4
+ "#{name} = [#{xvalue.join(" ")}];\n"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,58 @@
1
+ require_relative "label"
2
+
3
+ class Ecu
4
+ class Festwert < Label
5
+
6
+ attr_reader :value, :unit
7
+
8
+ def initialize(name:,
9
+ value:,
10
+ unit: nil,
11
+ function: nil,
12
+ description: nil)
13
+ @name = name
14
+ @value = value.is_a?(Array) ? value.first : value
15
+ @unit = unit
16
+ @function = function
17
+ @description = description
18
+ end
19
+
20
+ def round_to(n)
21
+ return self unless value.is_a?(Numeric)
22
+ self.with \
23
+ value: value.round(n)
24
+ end
25
+
26
+ def bytesize
27
+ BYTESIZE[:number]
28
+ end
29
+
30
+ def to_s(detail: false)
31
+ if detail == :justvalue
32
+ value.to_s
33
+ elsif detail == :value
34
+ "#{name}: #{value}"
35
+ elsif detail == :onelinefull
36
+ "#{name}: #{to_s(detail: :oneline)}"
37
+ elsif detail == :oneline
38
+ "#{value}"
39
+ elsif detail
40
+ <<~EOS
41
+ #{name}: #{type}
42
+ Value: #{value}
43
+ Unit: "#{unit}"
44
+ EOS
45
+ else
46
+ "#{name}: #{type}"
47
+ end
48
+ end
49
+
50
+ def properties
51
+ [:name, :value, :unit, :function, :description]
52
+ end
53
+
54
+ def equality_properties
55
+ [:name, :value]
56
+ end
57
+ end
58
+ end