Class: TrendLineCalculator
- Defined in:
- lib/jirametrics/trend_line_calculator.rb
Instance Method Summary collapse
-
#calc_y(x:) ⇒ Object
rubocop:disable Naming/MethodParameterName.
-
#chart_datapoints(range:, max_y:, min_y: 0) ⇒ Object
If the trend line can’t be calculated then return an empty array.
- #horizontal? ⇒ Boolean
- #initialize(points) ⇒ TrendLineCalculator constructor
-
#line_crosses_at(y:) ⇒ Object
rubocop:disable Naming/MethodParameterName.
- #valid? ⇒ Boolean
- #vertical? ⇒ Boolean
Constructor Details
#initialize(points) ⇒ TrendLineCalculator
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/jirametrics/trend_line_calculator.rb', line 6 def initialize points # We can't do trend calculations with less than two data points @valid = points.size >= 2 return unless valid? sum_of_x = points.collect { |x, _y| x }.sum sum_of_y = points.collect { |_x, y| y }.sum sum_of_xy = points.collect { |x, y| x * y }.sum sum_of_x2 = points.collect { |x, _y| x * x }.sum n = points.size.to_f @slope = ((n * sum_of_xy) - (sum_of_x * sum_of_y)) / ((n * sum_of_x2) - (sum_of_x * sum_of_x)) @offset = (sum_of_y - (@slope * sum_of_x)) / n @valid = false if vertical? end |
Instance Method Details
#calc_y(x:) ⇒ Object
rubocop:disable Naming/MethodParameterName
27 28 29 |
# File 'lib/jirametrics/trend_line_calculator.rb', line 27 def calc_y x: # rubocop:disable Naming/MethodParameterName ((x * @slope) + @offset).to_i end |
#chart_datapoints(range:, max_y:, min_y: 0) ⇒ Object
If the trend line can’t be calculated then return an empty array. Otherwise, return an array with two (x,y) points, with which you can draw the trend line.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/jirametrics/trend_line_calculator.rb', line 39 def chart_datapoints range:, max_y:, min_y: 0 raise 'max_y is nil' if max_y.nil? return [] unless valid? data_points = [] x_start = range.begin y_start = calc_y(x: range.begin).to_i x_end = range.end y_end = calc_y(x: range.end).to_i if y_start < min_y x_start = line_crosses_at y: 0 y_start = 0 end if y_start > max_y x_start = line_crosses_at y: max_y y_start = max_y end if y_end < min_y x_end = line_crosses_at y: 0 y_end = 0 end if y_end > max_y x_end = line_crosses_at y: max_y y_end = max_y end data_points << { x: x_start, y: y_start } data_points << { x: x_end, y: y_end } data_points end |
#horizontal? ⇒ Boolean
24 |
# File 'lib/jirametrics/trend_line_calculator.rb', line 24 def horizontal? = @slope.zero? |
#line_crosses_at(y:) ⇒ Object
rubocop:disable Naming/MethodParameterName
31 32 33 34 35 |
# File 'lib/jirametrics/trend_line_calculator.rb', line 31 def line_crosses_at y: # rubocop:disable Naming/MethodParameterName raise "line will never cross #{y}. Trend is perfectly horizontal" if horizontal? ((y.to_f - @offset) / @slope).to_i end |
#valid? ⇒ Boolean
23 |
# File 'lib/jirametrics/trend_line_calculator.rb', line 23 def valid? = @valid |
#vertical? ⇒ Boolean
25 |
# File 'lib/jirametrics/trend_line_calculator.rb', line 25 def vertical? = @slope.nan? || @slope.infinite? |