differential 1.0.1
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 +7 -0
- data/.editorconfig +8 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +5 -0
- data/.ruby-version +1 -0
- data/.travis.yml +12 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +87 -0
- data/Guardfile +16 -0
- data/LICENSE +7 -0
- data/README.md +223 -0
- data/differential.gemspec +29 -0
- data/lib/differential.rb +10 -0
- data/lib/differential/calculator/calculator.rb +15 -0
- data/lib/differential/calculator/group.rb +62 -0
- data/lib/differential/calculator/has_totals.rb +24 -0
- data/lib/differential/calculator/item.rb +57 -0
- data/lib/differential/calculator/report.rb +54 -0
- data/lib/differential/calculator/side.rb +19 -0
- data/lib/differential/calculator/totals.rb +44 -0
- data/lib/differential/differential.rb +31 -0
- data/lib/differential/parser/parser.rb +11 -0
- data/lib/differential/parser/reader.rb +73 -0
- data/lib/differential/parser/record.rb +25 -0
- data/lib/differential/version.rb +12 -0
- data/spec/differential/calculator/report_spec.rb +137 -0
- data/spec/differential/calculator/side_spec.rb +30 -0
- data/spec/differential/calculator/totals_spec.rb +40 -0
- data/spec/differential/differential_spec.rb +34 -0
- data/spec/differential/parser/reader_spec.rb +113 -0
- data/spec/differential/parser/record_spec.rb +28 -0
- data/spec/spec_helper.rb +10 -0
- metadata +127 -0
@@ -0,0 +1,30 @@
|
|
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::Side do
|
13
|
+
it 'should contain the correct number of constants' do
|
14
|
+
constants = ::Differential::Calculator::Side.constants
|
15
|
+
|
16
|
+
expect(constants.length).to eq(2)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should contain the correct constant for side a' do
|
20
|
+
value = ::Differential::Calculator::Side.const_get(:A)
|
21
|
+
|
22
|
+
expect(value).to eq(:a)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should contain the correct constant for side a' do
|
26
|
+
value = ::Differential::Calculator::Side.const_get(:B)
|
27
|
+
|
28
|
+
expect(value).to eq(:b)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,40 @@
|
|
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::Totals do
|
13
|
+
it 'should properly calculate sigmas and delta' do
|
14
|
+
totals = ::Differential::Calculator::Totals.new
|
15
|
+
|
16
|
+
totals.add(300, ::Differential::Calculator::Side::A)
|
17
|
+
|
18
|
+
expect(totals.a_sigma).to eq(300)
|
19
|
+
expect(totals.b_sigma).to eq(0)
|
20
|
+
expect(totals.delta).to eq(-300)
|
21
|
+
|
22
|
+
totals.add(400, ::Differential::Calculator::Side::B)
|
23
|
+
|
24
|
+
expect(totals.a_sigma).to eq(300)
|
25
|
+
expect(totals.b_sigma).to eq(400)
|
26
|
+
expect(totals.delta).to eq(100)
|
27
|
+
|
28
|
+
totals.add(2.5, ::Differential::Calculator::Side::A)
|
29
|
+
|
30
|
+
expect(totals.a_sigma).to eq(302.5)
|
31
|
+
expect(totals.b_sigma).to eq(400)
|
32
|
+
expect(totals.delta).to eq(97.5)
|
33
|
+
|
34
|
+
totals.add(2.50, ::Differential::Calculator::Side::B)
|
35
|
+
|
36
|
+
expect(totals.a_sigma).to eq(302.5)
|
37
|
+
expect(totals.b_sigma).to eq(402.5)
|
38
|
+
expect(totals.delta).to eq(100)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,34 @@
|
|
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 do
|
13
|
+
it 'should calculate a report' do
|
14
|
+
dataset_a = [
|
15
|
+
{ name: 'Matt', minutes: 100, transport: 'Bike' }
|
16
|
+
]
|
17
|
+
|
18
|
+
dataset_b = [
|
19
|
+
{ name: 'Matt', minutes: 20, transport: 'Car' }
|
20
|
+
]
|
21
|
+
|
22
|
+
reader_config = {
|
23
|
+
record_id_key: :name,
|
24
|
+
value_key: :minutes,
|
25
|
+
group_id_key: :transport
|
26
|
+
}
|
27
|
+
|
28
|
+
report = ::Differential.calculate(dataset_a: dataset_a,
|
29
|
+
dataset_b: dataset_b,
|
30
|
+
reader_config: reader_config)
|
31
|
+
|
32
|
+
expect(report.groups.length).to eq(2)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,113 @@
|
|
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::Parser::Reader do
|
13
|
+
it 'should initialize correctly' do
|
14
|
+
hash = {
|
15
|
+
record_id_key: :name,
|
16
|
+
value_key: :minutes,
|
17
|
+
group_id_key: :transport
|
18
|
+
}
|
19
|
+
|
20
|
+
reader = ::Differential::Parser::Reader.new(hash)
|
21
|
+
|
22
|
+
expect(reader.record_id_key).to eq(hash[:record_id_key])
|
23
|
+
expect(reader.value_key).to eq(hash[:value_key])
|
24
|
+
expect(reader.group_id_key).to eq(hash[:group_id_key])
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'When reading just id and value' do
|
28
|
+
it 'should properly create a record from a hash' do
|
29
|
+
reader = ::Differential::Parser::Reader.new(record_id_key: :name,
|
30
|
+
value_key: :minutes)
|
31
|
+
|
32
|
+
hashes = [
|
33
|
+
{
|
34
|
+
name: 'Matt',
|
35
|
+
minutes: 34
|
36
|
+
}
|
37
|
+
]
|
38
|
+
|
39
|
+
records = []
|
40
|
+
reader.each(hashes) do |record|
|
41
|
+
records << record
|
42
|
+
end
|
43
|
+
|
44
|
+
record = records.first
|
45
|
+
hash = hashes.first
|
46
|
+
|
47
|
+
expect(record.id).to eq(hash[:name])
|
48
|
+
expect(record.group_id).to eq('')
|
49
|
+
expect(record.value).to eq(hash[:minutes])
|
50
|
+
expect(record.data).to eq(hash)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'When reading singular keys' do
|
55
|
+
it 'should properly create a record from a hash' do
|
56
|
+
reader = ::Differential::Parser::Reader.new(record_id_key: :name,
|
57
|
+
value_key: :minutes,
|
58
|
+
group_id_key: :transport)
|
59
|
+
|
60
|
+
hashes = [
|
61
|
+
{
|
62
|
+
name: 'Matt',
|
63
|
+
minutes: 34,
|
64
|
+
transport: 'Train'
|
65
|
+
}
|
66
|
+
]
|
67
|
+
|
68
|
+
records = []
|
69
|
+
reader.each(hashes) do |record|
|
70
|
+
records << record
|
71
|
+
end
|
72
|
+
|
73
|
+
record = records.first
|
74
|
+
hash = hashes.first
|
75
|
+
|
76
|
+
expect(record.id).to eq(hash[:name])
|
77
|
+
expect(record.group_id).to eq(hash[:transport])
|
78
|
+
expect(record.value).to eq(hash[:minutes])
|
79
|
+
expect(record.data).to eq(hash)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'When reading multiple id keys' do
|
84
|
+
it 'should properly create a record from a hash' do
|
85
|
+
reader = ::Differential::Parser::Reader.new(record_id_key: %i[first last],
|
86
|
+
value_key: :minutes,
|
87
|
+
group_id_key: %i[transport direction])
|
88
|
+
|
89
|
+
hashes = [
|
90
|
+
{
|
91
|
+
first: 'Matt',
|
92
|
+
last: 'Smith',
|
93
|
+
minutes: 34,
|
94
|
+
transport: 'Train',
|
95
|
+
direction: 'Outbound'
|
96
|
+
}
|
97
|
+
]
|
98
|
+
|
99
|
+
records = []
|
100
|
+
reader.each(hashes) do |record|
|
101
|
+
records << record
|
102
|
+
end
|
103
|
+
|
104
|
+
record = records.first
|
105
|
+
hash = hashes.first
|
106
|
+
|
107
|
+
expect(record.id).to eq("#{hash[:first]}:#{hash[:last]}")
|
108
|
+
expect(record.group_id).to eq("#{hash[:transport]}:#{hash[:direction]}")
|
109
|
+
expect(record.value).to eq(hash[:minutes])
|
110
|
+
expect(record.data).to eq(hash)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,28 @@
|
|
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::Parser::Record do
|
13
|
+
it 'should initialize correctly' do
|
14
|
+
hash = {
|
15
|
+
id: '1',
|
16
|
+
group_id: '2',
|
17
|
+
value: 3,
|
18
|
+
data: { id: '1' }
|
19
|
+
}
|
20
|
+
|
21
|
+
record = ::Differential::Parser::Record.new(hash)
|
22
|
+
|
23
|
+
expect(record.id).to eq(hash[:id])
|
24
|
+
expect(record.group_id).to eq(hash[:group_id])
|
25
|
+
expect(record.value).to eq(hash[:value])
|
26
|
+
expect(record.data).to eq(hash[:data])
|
27
|
+
end
|
28
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
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 './lib/differential'
|
metadata
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: differential
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matthew Ruggio
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-12-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: guard-rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.8'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.8'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.59'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.59'
|
55
|
+
description: |2
|
56
|
+
Differential is a numeric-based library will compare two datasets and give you three
|
57
|
+
levels of comparison: report, group, and item level.
|
58
|
+
Each level provides the sum of each dataset and the difference.
|
59
|
+
email:
|
60
|
+
- mruggio@bluemarblepayroll.com
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- ".editorconfig"
|
66
|
+
- ".gitignore"
|
67
|
+
- ".rubocop.yml"
|
68
|
+
- ".ruby-version"
|
69
|
+
- ".travis.yml"
|
70
|
+
- Gemfile
|
71
|
+
- Gemfile.lock
|
72
|
+
- Guardfile
|
73
|
+
- LICENSE
|
74
|
+
- README.md
|
75
|
+
- differential.gemspec
|
76
|
+
- lib/differential.rb
|
77
|
+
- lib/differential/calculator/calculator.rb
|
78
|
+
- lib/differential/calculator/group.rb
|
79
|
+
- lib/differential/calculator/has_totals.rb
|
80
|
+
- lib/differential/calculator/item.rb
|
81
|
+
- lib/differential/calculator/report.rb
|
82
|
+
- lib/differential/calculator/side.rb
|
83
|
+
- lib/differential/calculator/totals.rb
|
84
|
+
- lib/differential/differential.rb
|
85
|
+
- lib/differential/parser/parser.rb
|
86
|
+
- lib/differential/parser/reader.rb
|
87
|
+
- lib/differential/parser/record.rb
|
88
|
+
- lib/differential/version.rb
|
89
|
+
- spec/differential/calculator/report_spec.rb
|
90
|
+
- spec/differential/calculator/side_spec.rb
|
91
|
+
- spec/differential/calculator/totals_spec.rb
|
92
|
+
- spec/differential/differential_spec.rb
|
93
|
+
- spec/differential/parser/reader_spec.rb
|
94
|
+
- spec/differential/parser/record_spec.rb
|
95
|
+
- spec/spec_helper.rb
|
96
|
+
homepage: https://github.com/bluemarblepayroll/differential
|
97
|
+
licenses:
|
98
|
+
- MIT
|
99
|
+
metadata: {}
|
100
|
+
post_install_message:
|
101
|
+
rdoc_options: []
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: 2.3.1
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
requirements: []
|
115
|
+
rubyforge_project:
|
116
|
+
rubygems_version: 2.5.2.3
|
117
|
+
signing_key:
|
118
|
+
specification_version: 4
|
119
|
+
summary: Dataset Differential Engine
|
120
|
+
test_files:
|
121
|
+
- spec/differential/calculator/report_spec.rb
|
122
|
+
- spec/differential/calculator/side_spec.rb
|
123
|
+
- spec/differential/calculator/totals_spec.rb
|
124
|
+
- spec/differential/differential_spec.rb
|
125
|
+
- spec/differential/parser/reader_spec.rb
|
126
|
+
- spec/differential/parser/record_spec.rb
|
127
|
+
- spec/spec_helper.rb
|