Class: XlsFunction::FormatString::Evaluators::NumberEvaluator
- Inherits:
-
Object
- Object
- XlsFunction::FormatString::Evaluators::NumberEvaluator
- Defined in:
- lib/xls_function/format_string/evaluators/number_evaluator.rb
Overview
TODO:
refactoring…
rubocop:disable Metrics/AbcSize
Instance Attribute Summary collapse
-
#parts ⇒ Object
readonly
Returns the value of attribute parts.
Instance Method Summary collapse
- #adjust_value(value) ⇒ Object
- #call(input) ⇒ Object
- #check_comma(comma_index) ⇒ Object
- #comma_index_pattern_millions ⇒ Object
-
#comma_index_pattern_thousands ⇒ Object
↓ check comma When % exists, check 2 or 1 chars before from %.
- #create_dec_pair(parts_list, value_stack) ⇒ Object
- #create_int_pair(parts_list, value_stack) ⇒ Object
- #decimal_parts ⇒ Object
- #eval_pairs(value_eval_pairs, int_remain: false) ⇒ Object
- #extract_parts!(input) ⇒ Object
- #format_value(value) ⇒ Object
-
#initialize(parts) ⇒ NumberEvaluator
constructor
A new instance of NumberEvaluator.
- #interger_parts ⇒ Object
- #parts_length ⇒ Object
Constructor Details
#initialize(parts) ⇒ NumberEvaluator
Returns a new instance of NumberEvaluator.
9 10 11 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 9 def initialize(parts) @parts = parts end |
Instance Attribute Details
#parts ⇒ Object (readonly)
Returns the value of attribute parts.
7 8 9 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 7 def parts @parts end |
Instance Method Details
#adjust_value(value) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 88 def adjust_value(value) decimal_value = value.to_s.to_d case @unit when :millions decimal_value /= '1000000'.to_d when :thousands decimal_value /= '1000'.to_d end decimal_value *= '100'.to_d if @has_parcentage decimal_value end |
#call(input) ⇒ Object
13 14 15 16 17 18 19 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 13 def call(input) extract_parts!(input) value = adjust_value(input) format_value(value) rescue ArgumentError input end |
#check_comma(comma_index) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 74 def check_comma(comma_index) return if comma_index.empty? if (comma_index_pattern_millions - comma_index).empty? @unit = :millions @format = true unless (comma_index - comma_index_pattern_millions).empty? elsif (comma_index_pattern_thousands - comma_index).empty? @unit = :thousands @format = true unless (comma_index - comma_index_pattern_thousands).empty? else @format = true end end |
#comma_index_pattern_millions ⇒ Object
69 70 71 72 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 69 def comma_index_pattern_millions offset = @has_parcentage ? 2 : 1 [parts_length - offset - 1, parts_length - offset] end |
#comma_index_pattern_thousands ⇒ Object
↓ check comma When % exists, check 2 or 1 chars before from %. If not, check last 2 or 1 chars.
64 65 66 67 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 64 def comma_index_pattern_thousands offset = @has_parcentage ? 2 : 1 [parts_length - offset] end |
#create_dec_pair(parts_list, value_stack) ⇒ Object
122 123 124 125 126 127 128 129 130 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 122 def create_dec_pair(parts_list, value_stack) parts_list.parts_with_index.map do |part, index| if parts_list.num?(index) [value_stack.shift_dec, part] else [part, nil] # means already evaluated end end end |
#create_int_pair(parts_list, value_stack) ⇒ Object
132 133 134 135 136 137 138 139 140 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 132 def create_int_pair(parts_list, value_stack) parts_list.parts_with_index.reverse.map do |part, index| if parts_list.num?(index) [value_stack.pop_int, part] else [part, nil] end end end |
#decimal_parts ⇒ Object
25 26 27 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 25 def decimal_parts @decimal_parts ||= PartsList.new end |
#eval_pairs(value_eval_pairs, int_remain: false) ⇒ Object
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 142 def eval_pairs(value_eval_pairs, int_remain: false) require_zero = false value_eval_pairs.map do |value, eval| next value unless eval evaluated_value = eval.call(value) if evaluated_value.strip != '' && evaluated_value != '0' require_zero = true next evaluated_value end # `#` returns empty if zero but must return zero if higher place exists. next '0' if evaluated_value == '' && (require_zero || int_remain) evaluated_value end end |
#extract_parts!(input) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 33 def extract_parts!(input) parts_target = interger_parts comma_index = [] @parts.each_with_index do |expr, i| if expr.respond_to?(:digits?) parts_target.add_parts(expr, i, true) next end # evaluate except number placeholder str = expr.call(input) # switch stack when decimal point comes parts_target = decimal_parts if str == '.' # count comma if str == ',' comma_index << i # ignore next end # last % is parcentage flag @has_parcentage = true if str == '%' && (i == parts_length - 1) parts_target.add_parts(str, i, false) end.compact check_comma(comma_index) end |
#format_value(value) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 103 def format_value(value) value_stack = ValueStack.new(value, decimal_parts.size, @format) # format decimals decimal_chars = create_dec_pair(decimal_parts, value_stack).reverse .then { |value_pairs| eval_pairs(value_pairs) } .reverse .join # format integers integer_chars = create_int_pair(interger_parts, value_stack).reverse .then { |value_pairs| eval_pairs(value_pairs, int_remain: value_stack.int_remain?) } .join "#{!value_stack.empty? ? value_stack.to_s : ''}#{integer_chars}#{decimal_chars}" end |
#interger_parts ⇒ Object
21 22 23 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 21 def interger_parts @interger_parts ||= PartsList.new end |
#parts_length ⇒ Object
29 30 31 |
# File 'lib/xls_function/format_string/evaluators/number_evaluator.rb', line 29 def parts_length @parts_length ||= parts.length end |