differential 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
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