differential 1.0.2 → 1.0.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +19 -3
- data/lib/differential/calculator/group.rb +4 -3
- data/lib/differential/calculator/item.rb +4 -2
- data/lib/differential/calculator/report.rb +4 -3
- data/lib/differential/calculator/totals.rb +27 -2
- data/lib/differential/parser/id.rb +44 -0
- data/lib/differential/parser/parser.rb +1 -0
- data/lib/differential/parser/reader.rb +11 -1
- data/lib/differential/parser/record.rb +2 -2
- data/lib/differential/version.rb +1 -1
- data/spec/differential/calculator/group_spec.rb +20 -0
- data/spec/differential/calculator/item_spec.rb +20 -0
- data/spec/differential/calculator/totals_spec.rb +11 -3
- data/spec/differential/parser/reader_spec.rb +45 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bda5fdf9228dd29ab49df6ed4af24492f3f56ee7
|
4
|
+
data.tar.gz: 3c17dd8906111c400f111264d93483a5fa43c6df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1aaa8b0917eb018a6d1cc0506a66af739432c108241f91b1486b8181a55617a7ab736119e5c486652569b96f9effd27f4120be792c32ff9bb407edf7a571f89
|
7
|
+
data.tar.gz: 6b1abb55a1383f7d43ebb5cd15bd582ce2def298fa84e3a45134f72ed7a27a5ec1ac70b22fd6b9b796cdc0149a727e9b2c3719e2e0e7d1b3670052652139c266
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,4 @@
|
|
1
|
+
## 1.0.3 (December 19, 2018)
|
2
|
+
|
3
|
+
- Added a_size and b_size for totals. This allows you to see how many items contributed to a calculation.
|
4
|
+
- Changed ID to be a first-class object instead of a string. Now groups and items can have their respective ID parts consumed using: ```id.data```. The string representation is still accessible via ```id.value```.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -110,7 +110,7 @@ reader_config = {
|
|
110
110
|
To run the report, run:
|
111
111
|
|
112
112
|
```
|
113
|
-
report = Differential.calculate(week1_data, week2_data, reader_config)
|
113
|
+
report = Differential.calculate(dataset_a: week1_data, dataset_b: week2_data, reader_config: reader_config)
|
114
114
|
```
|
115
115
|
|
116
116
|
The report variable will now hold a Report object with the following methods:
|
@@ -149,7 +149,7 @@ reader_config = {
|
|
149
149
|
Then execute:
|
150
150
|
|
151
151
|
```
|
152
|
-
report = Differential.calculate(week1_data, week2_data, reader_config)
|
152
|
+
report = Differential.calculate(dataset_a: week1_data, dataset_b: week2_data, reader_config: reader_config)
|
153
153
|
```
|
154
154
|
|
155
155
|
### By Employee, Grouped By Transport Type Report
|
@@ -167,7 +167,7 @@ reader_config = {
|
|
167
167
|
Then execute:
|
168
168
|
|
169
169
|
```
|
170
|
-
report = Differential.calculate(week1_data, week2_data, reader_config)
|
170
|
+
report = Differential.calculate(dataset_a: week1_data, dataset_b: week2_data, reader_config: reader_config)
|
171
171
|
```
|
172
172
|
|
173
173
|
Now, this will output a report with two groups instead of one which will allow you to present this with sub-totals.
|
@@ -218,6 +218,22 @@ Also, do not forget to run Rubocop:
|
|
218
218
|
bundle exec rubocop
|
219
219
|
````
|
220
220
|
|
221
|
+
### Publishing
|
222
|
+
|
223
|
+
Note: ensure you have proper authorization before trying to publish new versions.
|
224
|
+
|
225
|
+
After code changes have successfully gone through the Pull Request review process then the following steps should be followed for publishing new versions:
|
226
|
+
|
227
|
+
1. Merge Pull Request into master
|
228
|
+
2. Update [lib/differential/version.rb](https://github.com/bluemarblepayroll/differential/blob/master/lib/differential/version.rb) [version number](https://semver.org/)
|
229
|
+
3. Bundle
|
230
|
+
4. Update CHANGELOG.md
|
231
|
+
5. Commit & Push master to remote and ensure CI builds master successfully
|
232
|
+
6. Build the project locally: `gem build differential`
|
233
|
+
7. Publish package to NPM: `gem push differential-X.gem` where X is the version to push
|
234
|
+
8. Tag master with new version: `git tag <version>`
|
235
|
+
9. Push tags remotely: `git push origin --tags`
|
236
|
+
|
221
237
|
## License
|
222
238
|
|
223
239
|
This project is MIT Licensed.
|
@@ -44,12 +44,13 @@ module Differential
|
|
44
44
|
private
|
45
45
|
|
46
46
|
def upsert_item(record, side)
|
47
|
-
|
47
|
+
item_id_key = record.id.value
|
48
|
+
item_id = record.id
|
48
49
|
|
49
50
|
# Create a new item if one does not exist
|
50
|
-
items_by_id[
|
51
|
+
items_by_id[item_id_key] = Item.new(item_id) unless items_by_id.key?(item_id_key)
|
51
52
|
|
52
|
-
items_by_id[
|
53
|
+
items_by_id[item_id_key].add(record, side)
|
53
54
|
|
54
55
|
nil
|
55
56
|
end
|
@@ -16,14 +16,16 @@ module Differential
|
|
16
16
|
include ::Differential::Calculator::HasTotals
|
17
17
|
include ::Differential::Calculator::Side
|
18
18
|
|
19
|
-
attr_reader :
|
19
|
+
attr_reader :a_records,
|
20
|
+
:b_records,
|
21
|
+
:id
|
20
22
|
|
21
23
|
def initialize(id)
|
22
24
|
raise ArgumentError, 'id is required' unless id
|
23
25
|
|
24
|
-
@id = id
|
25
26
|
@a_records = []
|
26
27
|
@b_records = []
|
28
|
+
@id = id
|
27
29
|
end
|
28
30
|
|
29
31
|
def add(record, side)
|
@@ -36,12 +36,13 @@ module Differential
|
|
36
36
|
private
|
37
37
|
|
38
38
|
def upsert_group(record, side)
|
39
|
-
|
39
|
+
group_id_key = record.group_id.value
|
40
|
+
group_id = record.group_id
|
40
41
|
|
41
42
|
# Create a new group if one does not exist
|
42
|
-
groups_by_id[
|
43
|
+
groups_by_id[group_id_key] = Group.new(group_id) unless groups_by_id.key?(group_id_key)
|
43
44
|
|
44
|
-
groups_by_id[
|
45
|
+
groups_by_id[group_id_key].add(record, side)
|
45
46
|
|
46
47
|
nil
|
47
48
|
end
|
@@ -16,11 +16,16 @@ module Differential
|
|
16
16
|
class Totals
|
17
17
|
include ::Differential::Calculator::Side
|
18
18
|
|
19
|
-
attr_reader :a_sigma,
|
19
|
+
attr_reader :a_sigma,
|
20
|
+
:a_size,
|
21
|
+
:b_sigma,
|
22
|
+
:b_size
|
20
23
|
|
21
24
|
def initialize
|
22
25
|
@a_sigma = 0
|
26
|
+
@a_size = 0
|
23
27
|
@b_sigma = 0
|
28
|
+
@b_size = 0
|
24
29
|
end
|
25
30
|
|
26
31
|
def delta
|
@@ -28,6 +33,13 @@ module Differential
|
|
28
33
|
end
|
29
34
|
|
30
35
|
def add(value, side)
|
36
|
+
increment_sigma(value, side)
|
37
|
+
increment_size(side)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def increment_sigma(value, side)
|
31
43
|
case side
|
32
44
|
when A
|
33
45
|
@a_sigma += value
|
@@ -37,7 +49,20 @@ module Differential
|
|
37
49
|
raise ArgumentError, "unknown side: #{side}"
|
38
50
|
end
|
39
51
|
|
40
|
-
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def increment_size(side)
|
56
|
+
case side
|
57
|
+
when A
|
58
|
+
@a_size += 1.0
|
59
|
+
when B
|
60
|
+
@b_size += 1.0
|
61
|
+
else
|
62
|
+
raise ArgumentError, "unknown side: #{side}"
|
63
|
+
end
|
64
|
+
|
65
|
+
nil
|
41
66
|
end
|
42
67
|
end
|
43
68
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2018-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
module Differential
|
11
|
+
module Parser
|
12
|
+
# TODO
|
13
|
+
class Id
|
14
|
+
attr_reader :data, :value
|
15
|
+
|
16
|
+
def initialize(data)
|
17
|
+
@data = Array(data)
|
18
|
+
@value = make_value(data)
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
value
|
23
|
+
end
|
24
|
+
|
25
|
+
def eql?(other)
|
26
|
+
if other.is_a?(self.class)
|
27
|
+
value == other.value
|
28
|
+
else
|
29
|
+
make_value(other) == value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def ==(other)
|
34
|
+
eql?(other)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def make_value(val)
|
40
|
+
Array(val).join(':')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -34,7 +34,9 @@ module Differential
|
|
34
34
|
def each(hashes)
|
35
35
|
return enum_for(:each) unless block_given?
|
36
36
|
|
37
|
-
hashes.each do |hash|
|
37
|
+
array(hashes).each do |hash|
|
38
|
+
next unless hash
|
39
|
+
|
38
40
|
record = read(hash)
|
39
41
|
yield record
|
40
42
|
end
|
@@ -68,6 +70,14 @@ module Differential
|
|
68
70
|
def group_id_key_array
|
69
71
|
@group_id_key_array ||= Array(group_id_key)
|
70
72
|
end
|
73
|
+
|
74
|
+
def array(hashes)
|
75
|
+
if hashes.is_a?(Hash)
|
76
|
+
[hashes]
|
77
|
+
else
|
78
|
+
Array(hashes)
|
79
|
+
end
|
80
|
+
end
|
71
81
|
end
|
72
82
|
end
|
73
83
|
end
|
@@ -15,8 +15,8 @@ module Differential
|
|
15
15
|
attr_reader :id, :group_id, :value, :data
|
16
16
|
|
17
17
|
def initialize(id:, group_id:, value:, data:)
|
18
|
-
@id = id
|
19
|
-
@group_id = group_id
|
18
|
+
@id = ::Differential::Parser::Id.new(id)
|
19
|
+
@group_id = ::Differential::Parser::Id.new(group_id)
|
20
20
|
@value = value
|
21
21
|
@data = data
|
22
22
|
end
|
data/lib/differential/version.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2018-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require './spec/spec_helper'
|
11
|
+
|
12
|
+
describe ::Differential::Calculator::Group do
|
13
|
+
let(:id) { 'matt' }
|
14
|
+
|
15
|
+
let(:group) { ::Differential::Calculator::Group.new(id) }
|
16
|
+
|
17
|
+
it 'should initialize correctly' do
|
18
|
+
expect(group.id).to eq(id)
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2018-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require './spec/spec_helper'
|
11
|
+
|
12
|
+
describe ::Differential::Calculator::Item do
|
13
|
+
let(:id) { 'matt' }
|
14
|
+
|
15
|
+
let(:item) { ::Differential::Calculator::Item.new(id) }
|
16
|
+
|
17
|
+
it 'should initialize correctly' do
|
18
|
+
expect(item.id).to eq(id)
|
19
|
+
end
|
20
|
+
end
|
@@ -15,26 +15,34 @@ describe ::Differential::Calculator::Totals do
|
|
15
15
|
|
16
16
|
totals.add(300, ::Differential::Calculator::Side::A)
|
17
17
|
|
18
|
-
expect(totals.a_sigma).to
|
19
|
-
expect(totals.
|
20
|
-
expect(totals.
|
18
|
+
expect(totals.a_sigma).to eq(300)
|
19
|
+
expect(totals.a_size).to eq(1)
|
20
|
+
expect(totals.b_sigma).to eq(0)
|
21
|
+
expect(totals.b_size).to eq(0)
|
22
|
+
expect(totals.delta).to eq(-300)
|
21
23
|
|
22
24
|
totals.add(400, ::Differential::Calculator::Side::B)
|
23
25
|
|
24
26
|
expect(totals.a_sigma).to eq(300)
|
27
|
+
expect(totals.a_size).to eq(1)
|
25
28
|
expect(totals.b_sigma).to eq(400)
|
29
|
+
expect(totals.b_size).to eq(1)
|
26
30
|
expect(totals.delta).to eq(100)
|
27
31
|
|
28
32
|
totals.add(2.5, ::Differential::Calculator::Side::A)
|
29
33
|
|
30
34
|
expect(totals.a_sigma).to eq(302.5)
|
35
|
+
expect(totals.a_size).to eq(2)
|
31
36
|
expect(totals.b_sigma).to eq(400)
|
37
|
+
expect(totals.b_size).to eq(1)
|
32
38
|
expect(totals.delta).to eq(97.5)
|
33
39
|
|
34
40
|
totals.add(2.50, ::Differential::Calculator::Side::B)
|
35
41
|
|
36
42
|
expect(totals.a_sigma).to eq(302.5)
|
43
|
+
expect(totals.a_size).to eq(2)
|
37
44
|
expect(totals.b_sigma).to eq(402.5)
|
45
|
+
expect(totals.b_size).to eq(2)
|
38
46
|
expect(totals.delta).to eq(100)
|
39
47
|
end
|
40
48
|
end
|
@@ -49,6 +49,51 @@ describe ::Differential::Parser::Reader do
|
|
49
49
|
expect(record.value).to eq(hash[:minutes])
|
50
50
|
expect(record.data).to eq(hash)
|
51
51
|
end
|
52
|
+
|
53
|
+
it 'should skip null records' do
|
54
|
+
reader = ::Differential::Parser::Reader.new(record_id_key: :name,
|
55
|
+
value_key: :minutes)
|
56
|
+
|
57
|
+
hashes = [nil]
|
58
|
+
|
59
|
+
records = []
|
60
|
+
reader.each(hashes) do |record|
|
61
|
+
records << record
|
62
|
+
end
|
63
|
+
|
64
|
+
expect(records.length).to eq(0)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should read non-array input' do
|
69
|
+
reader = ::Differential::Parser::Reader.new(record_id_key: :name,
|
70
|
+
value_key: :minutes)
|
71
|
+
|
72
|
+
hashes = {
|
73
|
+
name: 'Matt',
|
74
|
+
minutes: 34
|
75
|
+
}
|
76
|
+
|
77
|
+
records = []
|
78
|
+
reader.each(hashes) do |record|
|
79
|
+
records << record
|
80
|
+
end
|
81
|
+
|
82
|
+
expect(records.length).to eq(1)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should read null input' do
|
86
|
+
reader = ::Differential::Parser::Reader.new(record_id_key: :name,
|
87
|
+
value_key: :minutes)
|
88
|
+
|
89
|
+
hashes = nil
|
90
|
+
|
91
|
+
records = []
|
92
|
+
reader.each(hashes) do |record|
|
93
|
+
records << record
|
94
|
+
end
|
95
|
+
|
96
|
+
expect(records.length).to eq(0)
|
52
97
|
end
|
53
98
|
|
54
99
|
context 'When reading singular keys' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: differential
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Ruggio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-12-
|
11
|
+
date: 2018-12-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: guard-rspec
|
@@ -67,6 +67,7 @@ files:
|
|
67
67
|
- ".rubocop.yml"
|
68
68
|
- ".ruby-version"
|
69
69
|
- ".travis.yml"
|
70
|
+
- CHANGELOG.md
|
70
71
|
- Gemfile
|
71
72
|
- Gemfile.lock
|
72
73
|
- Guardfile
|
@@ -82,10 +83,13 @@ files:
|
|
82
83
|
- lib/differential/calculator/side.rb
|
83
84
|
- lib/differential/calculator/totals.rb
|
84
85
|
- lib/differential/differential.rb
|
86
|
+
- lib/differential/parser/id.rb
|
85
87
|
- lib/differential/parser/parser.rb
|
86
88
|
- lib/differential/parser/reader.rb
|
87
89
|
- lib/differential/parser/record.rb
|
88
90
|
- lib/differential/version.rb
|
91
|
+
- spec/differential/calculator/group_spec.rb
|
92
|
+
- spec/differential/calculator/item_spec.rb
|
89
93
|
- spec/differential/calculator/report_spec.rb
|
90
94
|
- spec/differential/calculator/side_spec.rb
|
91
95
|
- spec/differential/calculator/totals_spec.rb
|
@@ -118,6 +122,8 @@ signing_key:
|
|
118
122
|
specification_version: 4
|
119
123
|
summary: Dataset Differential Engine
|
120
124
|
test_files:
|
125
|
+
- spec/differential/calculator/group_spec.rb
|
126
|
+
- spec/differential/calculator/item_spec.rb
|
121
127
|
- spec/differential/calculator/report_spec.rb
|
122
128
|
- spec/differential/calculator/side_spec.rb
|
123
129
|
- spec/differential/calculator/totals_spec.rb
|