trifle-stats 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,161 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Trifle
4
- module Stats
5
- class Nocturnal # rubocop:disable Metrics/ClassLength
6
- UNIT_MAP = {
7
- 's' => :second,
8
- 'm' => :minute,
9
- 'h' => :hour,
10
- 'd' => :day,
11
- 'w' => :week,
12
- 'mo' => :month,
13
- 'q' => :quarter,
14
- 'y' => :year
15
- }.freeze
16
-
17
- DAYS_INTO_WEEK = {
18
- sunday: 0, monday: 1, tuesday: 2, wednesday: 3,
19
- thursday: 4, friday: 5, saturday: 6
20
- }.freeze
21
-
22
- def self.timeline(from:, to:, granularity:, config: nil)
23
- list = []
24
- from = new(from, config: config).send(granularity)
25
- to = new(to, config: config).send(granularity)
26
- item = from.dup
27
- while item <= to
28
- list << item
29
- item = Nocturnal.new(item, config: config).send("next_#{granularity}")
30
- end
31
- list
32
- end
33
-
34
- def initialize(at, config: nil)
35
- @at = at
36
- @config = config
37
- end
38
-
39
- def config
40
- @config || Trifle::Stats.default
41
- end
42
-
43
- def change(**fractions)
44
- Time.new(
45
- fractions.fetch(:year, @at.year),
46
- fractions.fetch(:month, @at.month),
47
- fractions.fetch(:day, @at.day),
48
- fractions.fetch(:hour, @at.hour),
49
- fractions.fetch(:minute, @at.min),
50
- fractions.fetch(:second, 0),
51
- config.tz.utc_offset
52
- )
53
- end
54
-
55
- def second
56
- change(second: @at.sec)
57
- end
58
-
59
- def next_second
60
- Nocturnal.new(
61
- second + 1,
62
- config: config
63
- ).second
64
- end
65
-
66
- def minute
67
- change(second: 0)
68
- end
69
-
70
- def next_minute
71
- Nocturnal.new(
72
- minute + 60,
73
- config: config
74
- ).minute
75
- end
76
-
77
- def hour
78
- change(minute: 0)
79
- end
80
-
81
- def next_hour
82
- Nocturnal.new(
83
- hour + 60 * 60,
84
- config: config
85
- ).hour
86
- end
87
-
88
- def day
89
- change(hour: 0, minute: 0)
90
- end
91
-
92
- def next_day
93
- Nocturnal.new(
94
- day + 60 * 60 * 24,
95
- config: config
96
- ).day
97
- end
98
-
99
- def week
100
- today = day
101
-
102
- (today.to_date - days_to_week_start).to_time
103
- end
104
-
105
- def next_week
106
- Nocturnal.new(
107
- week + 60 * 60 * 24 * 7,
108
- config: config
109
- ).week
110
- end
111
-
112
- def days_to_week_start
113
- start_day_number = DAYS_INTO_WEEK.fetch(
114
- config.beginning_of_week
115
- )
116
-
117
- (@at.wday - start_day_number) % 7
118
- end
119
-
120
- def month
121
- change(day: 1, hour: 0, minute: 0)
122
- end
123
-
124
- def next_month
125
- Nocturnal.new(
126
- month + 60 * 60 * 24 * 31,
127
- config: config
128
- ).month
129
- end
130
-
131
- def quarter
132
- first_quarter_month = @at.month - (2 + @at.month) % 3
133
-
134
- change(
135
- month: first_quarter_month,
136
- day: 1,
137
- hour: 0,
138
- minute: 0
139
- )
140
- end
141
-
142
- def next_quarter
143
- Nocturnal.new(
144
- quarter + 60 * 60 * 24 * 31 * 3,
145
- config: config
146
- ).quarter
147
- end
148
-
149
- def year
150
- change(month: 1, day: 1, hour: 0, minute: 0)
151
- end
152
-
153
- def next_year
154
- Nocturnal.new(
155
- year + 60 * 60 * 24 * 31 * 12,
156
- config: config
157
- ).year
158
- end
159
- end
160
- end
161
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Trifle
4
- module Stats
5
- class Transponder
6
- class Add
7
- include Trifle::Stats::Mixins::Packer
8
- Trifle::Stats::Series.register_transponder(:add, self)
9
-
10
- def transpond(series:, left:, right:, response: 'add') # rubocop:disable Metrics/MethodLength
11
- left_keys = left.to_s.split('.')
12
- right_keys = right.to_s.split('.')
13
-
14
- series[:values] = series[:values].map do |data|
15
- dleft = data.dig(*left_keys)
16
- dright = data.dig(*right_keys)
17
- next data unless dleft && dright
18
-
19
- dres = dleft + dright
20
- signal = {
21
- response => dres
22
- }
23
- self.class.deep_merge(data, self.class.unpack(hash: signal))
24
- end
25
- series
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Trifle
4
- module Stats
5
- class Transponder
6
- class Divide
7
- include Trifle::Stats::Mixins::Packer
8
- Trifle::Stats::Series.register_transponder(:divide, self)
9
-
10
- def transpond(series:, left:, right:, response: 'divide') # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
11
- left_keys = left.to_s.split('.')
12
- right_keys = right.to_s.split('.')
13
-
14
- series[:values] = series[:values].map do |data|
15
- dleft = data.dig(*left_keys)
16
- dright = data.dig(*right_keys)
17
- next data unless dleft && dright
18
-
19
- dres = (dleft / dright)
20
- signal = {
21
- response => dres.nan? ? BigDecimal(0) : dres
22
- }
23
- self.class.deep_merge(data, self.class.unpack(hash: signal))
24
- end
25
- series
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Trifle
4
- module Stats
5
- class Transponder
6
- class Max
7
- include Trifle::Stats::Mixins::Packer
8
- Trifle::Stats::Series.register_transponder(:max, self)
9
-
10
- def transpond(series:, paths:, response: 'max') # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
11
- path_keys = paths.map { |path| path.to_s.split('.') }
12
-
13
- series[:values] = series[:values].map do |data|
14
- dvalues = path_keys.map { |path_key| data.dig(*path_key) }
15
- next data if dvalues.any?(&:nil?)
16
-
17
- numeric_values = dvalues.select { |v| v.is_a?(Numeric) }
18
- next data if numeric_values.empty?
19
-
20
- dres = numeric_values.max
21
- signal = {
22
- response => dres
23
- }
24
- self.class.deep_merge(data, self.class.unpack(hash: signal))
25
- end
26
- series
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Trifle
4
- module Stats
5
- class Transponder
6
- class Mean
7
- include Trifle::Stats::Mixins::Packer
8
- Trifle::Stats::Series.register_transponder(:mean, self)
9
-
10
- def transpond(series:, paths:, response: 'mean') # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
11
- path_keys = paths.map { |path| path.to_s.split('.') }
12
-
13
- series[:values] = series[:values].map do |data|
14
- dvalues = path_keys.map { |path_key| data.dig(*path_key) }
15
- next data if dvalues.any?(&:nil?)
16
-
17
- numeric_values = dvalues.select { |v| v.is_a?(Numeric) }
18
- next data if numeric_values.empty?
19
-
20
- dres = (numeric_values.sum.to_f / numeric_values.length)
21
- signal = {
22
- response => dres.nan? ? BigDecimal(0) : dres
23
- }
24
- self.class.deep_merge(data, self.class.unpack(hash: signal))
25
- end
26
- series
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Trifle
4
- module Stats
5
- class Transponder
6
- class Min
7
- include Trifle::Stats::Mixins::Packer
8
- Trifle::Stats::Series.register_transponder(:min, self)
9
-
10
- def transpond(series:, paths:, response: 'min') # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
11
- path_keys = paths.map { |path| path.to_s.split('.') }
12
-
13
- series[:values] = series[:values].map do |data|
14
- dvalues = path_keys.map { |path_key| data.dig(*path_key) }
15
- next data if dvalues.any?(&:nil?)
16
-
17
- numeric_values = dvalues.select { |v| v.is_a?(Numeric) }
18
- next data if numeric_values.empty?
19
-
20
- dres = numeric_values.min
21
- signal = {
22
- response => dres
23
- }
24
- self.class.deep_merge(data, self.class.unpack(hash: signal))
25
- end
26
- series
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Trifle
4
- module Stats
5
- class Transponder
6
- class Multiply
7
- include Trifle::Stats::Mixins::Packer
8
- Trifle::Stats::Series.register_transponder(:multiply, self)
9
-
10
- def transpond(series:, left:, right:, response: 'multiply') # rubocop:disable Metrics/MethodLength
11
- left_keys = left.to_s.split('.')
12
- right_keys = right.to_s.split('.')
13
-
14
- series[:values] = series[:values].map do |data|
15
- dleft = data.dig(*left_keys)
16
- dright = data.dig(*right_keys)
17
- next data unless dleft && dright
18
-
19
- dres = dleft * dright
20
- signal = {
21
- response => dres
22
- }
23
- self.class.deep_merge(data, self.class.unpack(hash: signal))
24
- end
25
- series
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Trifle
4
- module Stats
5
- class Transponder
6
- class Ratio
7
- include Trifle::Stats::Mixins::Packer
8
- Trifle::Stats::Series.register_transponder(:ratio, self)
9
-
10
- def transpond(series:, left:, right:, response: 'ratio') # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
11
- left_keys = left.to_s.split('.')
12
- right_keys = right.to_s.split('.')
13
-
14
- series[:values] = series[:values].map do |data|
15
- dleft = data.dig(*left_keys)
16
- dright = data.dig(*right_keys)
17
- next data unless dleft && dright
18
-
19
- dres = (dleft / dright) * 100
20
- signal = {
21
- response => dres.nan? ? BigDecimal(0) : dres
22
- }
23
- self.class.deep_merge(data, self.class.unpack(hash: signal))
24
- end
25
- series
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Trifle
4
- module Stats
5
- class Transponder
6
- class StandardDeviation
7
- include Trifle::Stats::Mixins::Packer
8
- Trifle::Stats::Series.register_transponder(:standard_deviation, self)
9
-
10
- def transpond(series:, left:, right:, square:, response: 'sd') # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
11
- left_keys = left.to_s.split('.')
12
- right_keys = right.to_s.split('.')
13
- square_keys = square.to_s.split('.')
14
-
15
- series[:values] = series[:values].map do |data|
16
- dright = data.dig(*right_keys)
17
- dsquare = data.dig(*square_keys)
18
- dleft = data.dig(*left_keys)
19
- next data unless dright && dsquare && dleft
20
-
21
- dres = Math.sqrt(
22
- (dright * dsquare - dleft * dleft) / (dright * (dright - 1)) # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
23
- )
24
- signal = {
25
- response => dres.nan? ? BigDecimal(0) : dres
26
- }
27
- self.class.deep_merge(data, self.class.unpack(hash: signal))
28
- end
29
- series
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Trifle
4
- module Stats
5
- class Transponder
6
- class Subtract
7
- include Trifle::Stats::Mixins::Packer
8
- Trifle::Stats::Series.register_transponder(:subtract, self)
9
-
10
- def transpond(series:, left:, right:, response: 'subtract') # rubocop:disable Metrics/MethodLength
11
- left_keys = left.to_s.split('.')
12
- right_keys = right.to_s.split('.')
13
-
14
- series[:values] = series[:values].map do |data|
15
- dleft = data.dig(*left_keys)
16
- dright = data.dig(*right_keys)
17
- next data unless dleft && dright
18
-
19
- dres = dleft - dright
20
- signal = {
21
- response => dres
22
- }
23
- self.class.deep_merge(data, self.class.unpack(hash: signal))
24
- end
25
- series
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Trifle
4
- module Stats
5
- class Transponder
6
- class Sum
7
- include Trifle::Stats::Mixins::Packer
8
- Trifle::Stats::Series.register_transponder(:sum, self)
9
-
10
- def transpond(series:, paths:, response: 'sum') # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
11
- path_keys = paths.map { |path| path.to_s.split('.') }
12
-
13
- series[:values] = series[:values].map do |data|
14
- dvalues = path_keys.map { |path_key| data.dig(*path_key) }
15
- next data if dvalues.any?(&:nil?)
16
-
17
- dres = dvalues.sum { |v| v.is_a?(Numeric) ? v : 0 }
18
- signal = {
19
- response => dres
20
- }
21
- self.class.deep_merge(data, self.class.unpack(hash: signal))
22
- end
23
- series
24
- end
25
- end
26
- end
27
- end
28
- end