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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1136ffec0d1dc398e717e21e7c51d18082132f8f
4
- data.tar.gz: 0a409d39334fc6d0b20a5a1e4a56de89f707e246
3
+ metadata.gz: bda5fdf9228dd29ab49df6ed4af24492f3f56ee7
4
+ data.tar.gz: 3c17dd8906111c400f111264d93483a5fa43c6df
5
5
  SHA512:
6
- metadata.gz: fa1be441c56ccfc332c48015179d697dd8d071e4a6c98f44fd7e7490d4ece2840e417f5b0c4c7a08979ec7314bd33bccff3fab0b1ef526e46a5166795d9bc08f
7
- data.tar.gz: 94d1f323017db63dd6a155f43912c23f404fa6b67cf90f1e87e9e95645d7f56325b6cb12b2ccf456bca19095a27d26189c9e14539560424f162e8c9b116dc43b
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- differential (1.0.2)
4
+ differential (1.0.3)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
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
- item_id = record.id
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[item_id] = Item.new(item_id) unless items_by_id.key?(item_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[item_id].add(record, side)
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 :id, :a_records, :b_records
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
- group_id = record.group_id
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[group_id] = Group.new(group_id) unless groups_by_id.key?(group_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[group_id].add(record, side)
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, :b_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
- self
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
@@ -7,5 +7,6 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
+ require_relative 'id'
10
11
  require_relative 'reader'
11
12
  require_relative 'record'
@@ -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
@@ -8,5 +8,5 @@
8
8
  #
9
9
 
10
10
  module Differential
11
- VERSION = '1.0.2'
11
+ VERSION = '1.0.3'
12
12
  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::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 eq(300)
19
- expect(totals.b_sigma).to eq(0)
20
- expect(totals.delta).to eq(-300)
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.2
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-19 00:00:00.000000000 Z
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