Module: Crunchr::ClassMethods

Defined in:
lib/crunchr.rb

Instance Method Summary collapse

Instance Method Details

#as_table(list, opts = {}) ⇒ Object

pass in a list off data-objects with and get a nice table

list = [ Object.data({ doors: 1, keys: 2}), Object.data({ doors: 1, keys: 3 }, ... ]

table = Object.as_table(list, keys: %w[doors keys])
# => [ [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 3, 8 ] ]

Or use lists in lists

deep_list = [ list, list list ]
table = Object.as_table(deep_list, keys: %[doors keys], list_operator: delta)
# => [ [ 2, 6 ] ]  (differnece of mac and min for both doors and keys)

Parameters:

  • list (Array)

    List (1d or 2d) of data objects

  • opts (Hash) (defaults to: {})

    Options

Options Hash (opts):

  • keys (Array)

    List of keys to fetch, may contain calculations, eg: [‘doors’, ‘keys’, ‘doors / keys’]

  • list_operator (Symbol)

    With a 2d list, what operator to apply to each given list to determine the 1d value, any of

    • :mean

    • :stddev

    • :median

    • :range

    • :mode

    • :sum

    • :min

    • ;max



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/crunchr.rb', line 128

def as_table(list, opts = {})
  keys = opts[:keys] || raise("Need keys")

  table = []

  list.each do |statistic|
    iteration_keys = keys.dup

    if statistic.is_a?(Array)
      (iteration_keys, statistic) = flatten(statistic, opts)
    end

    row = []

    iteration_keys.each do |key|
      value = zero()

      if key == :date
        value = opts[:date_fmt] ?
          statistic.created_at.strftime(opts[:date_fmt]) :
          statistic.created_at.to_date

      else
        value = statistic.fetch(key)

        if value.respond_to? :round
          value = case opts[:round]
                  when nil
                    value
                  when 0
                    value.round rescue value
                  else
                    value.round(opts[:round])
                  end
        end

        value = opts[:str_fmt] % value if opts[:str_fmt]

        value = value.to_f if value.is_a?(BigDecimal)
      end

      row << checked(value)
    end

    if opts[:delta] && table.any?
      new_row = []
      row.each_with_index do |value, idx|
        next unless value.kind_of?(Numeric)
        new_row[idx] = checked(row[idx] - @prev[idx])
      end

      @prev = row.dup
      row = new_row
    else
      @prev = row
    end

    table << row
  end

  return table
end

#checked(value) ⇒ Object



237
238
239
240
241
242
243
244
# File 'lib/crunchr.rb', line 237

def checked(value)
  value = zero() if value.respond_to?(:nan?) && value.nan?
  value = zero() if value.respond_to?(:infinity?) && value.infinity?
  value = zero() if value.nil?
  value = value.to_f if value.is_a? BigDecimal

  value
end

#flatten(array, opts) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/crunchr.rb', line 191

def flatten(array, opts)
  keys = opts[:keys].dup

  # this must be an interval period : find the mean, sum, max, whatever
  opts[:list_operator] ||= :mean

  collection = self.new( :data => {} )

  keys.each_with_index do |key, idx|
    if key == :date
      collection.created_at = array.first.created_at
      next
    end

    collection_key = key.to_s.gsub(/[\s*\/:x+-]+/, '_')
    keys[idx] = collection_key if collection_key != key

    array.each do |item|
      collection.data[collection_key] ||= []
      collection.data[collection_key] << (item.fetch(key) || 0)
    end

    # turn the collection into a single value
    value = if opts[:list_operator] == :delta
      collection.data[collection_key].max -
      collection.data[collection_key].min

    else
       collection.data[collection_key].send(opts[:list_operator])

    end

    collection.data[collection_key] = value
  end

  collection
  collection.readonly! if collection.respond_to?(:readonly!)

  return [keys, collection]
end

#zeroObject



233
234
235
# File 'lib/crunchr.rb', line 233

def zero
  BigDecimal.new("0.0")
end