Skip to content

Commit 1be1503

Browse files
committed
Validate step values on inputs
1 parent 426c7cd commit 1be1503

1 file changed

Lines changed: 37 additions & 0 deletions

File tree

app/models/scenario_updater/services/validate_input_values.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,46 @@ def validate_numeric_input(key, input, input_data, value, errors)
6969
# and will be validated after balancing
7070
return if input.share_group.present?
7171

72+
# Validate step alignment first - skip min/max check if step invalid
73+
step_valid = validate_step(key, value, input_data[:min], input_data[:step], errors)
74+
return unless step_valid
75+
7276
validate_min_max(key, value, input_data[:min], input_data[:max], errors)
7377
end
7478

79+
def validate_step(key, value, min, step, errors)
80+
return true unless step.present? && step.positive?
81+
return true if value_on_valid_step?(value, min, step)
82+
83+
nearest_lower = calculate_nearest_step(value, min, step)
84+
nearest_higher = nearest_lower + step
85+
precision = decimal_places(step)
86+
87+
errors << "Input #{key} value #{value} must align with step size #{step}. " \
88+
"Nearest valid values: #{nearest_lower.round(precision)} or #{nearest_higher.round(precision)}"
89+
90+
false
91+
end
92+
93+
def value_on_valid_step?(value, min, step)
94+
remainder = ((value - min) % step).abs
95+
remainder < 0.0001 || (step - remainder).abs < 0.0001
96+
end
97+
98+
def calculate_nearest_step(value, min, step)
99+
steps_from_min = ((value - min) / step).round
100+
min + (steps_from_min * step)
101+
end
102+
103+
def decimal_places(num)
104+
return 0 if num.to_i == num
105+
106+
num_str = num.to_s
107+
return 0 unless num_str.include?('.')
108+
109+
num_str.split('.')[1].gsub(/0+$/, '').length
110+
end
111+
75112
def validate_min_max(key, value, min, max, errors)
76113
if value < min
77114
errors << "Input #{key} cannot be less than #{min}"

0 commit comments

Comments
 (0)