compensate 0.1.2 → 0.1.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/Gemfile +2 -2
- data/Gemfile.lock +1 -1
- data/README.md +4 -14
- data/Rakefile +3 -3
- data/bin/console +3 -3
- data/compensate.gemspec +13 -13
- data/lib/compensate/version.rb +1 -1
- data/lib/compensate.rb +47 -49
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 949fc8bf33efa35797a6375ceaf9e43cec2e9b0d
|
4
|
+
data.tar.gz: 577722fd3834171ed51631da7f71b71dd23521ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b42aa22b8bcb64d910008e6a4770f99923894e1b2e99237f3cf246679979594033d955db657cb1a9a0c8b448a11f2973db639783412cea1b15f31413d43c8b1
|
7
|
+
data.tar.gz: f6ce6c77b05f9e8c8d7df66518b55f4bc8ff3a986f0bde84d4dc64f4d800231305e6cd9192a61103899935d79cc6bdeca48e6b798c483d1ccfbcb88fff754e00
|
data/Gemfile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
3
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
4
4
|
|
5
5
|
# Specify your gem's dependencies in compensate.gemspec
|
6
6
|
gemspec
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -6,17 +6,7 @@ Completed as a technical exercise during interview process for [Simple Thread](h
|
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
```ruby
|
12
|
-
gem 'compensate'
|
13
|
-
```
|
14
|
-
|
15
|
-
And then execute:
|
16
|
-
|
17
|
-
$ bundle
|
18
|
-
|
19
|
-
Or install it yourself as:
|
9
|
+
Install this gem directly with:
|
20
10
|
|
21
11
|
$ gem install compensate
|
22
12
|
|
@@ -24,7 +14,7 @@ Or install it yourself as:
|
|
24
14
|
|
25
15
|
Inputs accepted are .csv files with the following headers: `Rate, Start, End` where `Rate` is either `high` or `low`, and `Start, End` are dates in the format of `MM/DD/YY`. Ensure the header rows exist on a given CSV.
|
26
16
|
|
27
|
-
This gem is packaged with an executable script. Use the following command to process a CSV named `test.csv`:
|
17
|
+
This gem is packaged with an executable command-line script. Use the following shell command to process a CSV named `test.csv`:
|
28
18
|
|
29
19
|
`compensate test.csv`
|
30
20
|
|
@@ -36,7 +26,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
36
26
|
|
37
27
|
## Contributing
|
38
28
|
|
39
|
-
Bug reports and pull requests are welcome on
|
29
|
+
Bug reports and pull requests are welcome on GitLab at https://gitlab.com/kfrz/compensate. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
40
30
|
|
41
31
|
## License
|
42
32
|
|
@@ -44,4 +34,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
44
34
|
|
45
35
|
## Code of Conduct
|
46
36
|
|
47
|
-
Everyone interacting in the Compensate project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://
|
37
|
+
Everyone interacting in the Compensate project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://gitlab.com/kfrz/compensate/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'compensate'
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +10,5 @@ require "compensate"
|
|
10
10
|
# require "pry"
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
-
require
|
13
|
+
require 'irb'
|
14
14
|
IRB.start(__FILE__)
|
data/compensate.gemspec
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
|
2
|
-
lib = File.expand_path(
|
2
|
+
lib = File.expand_path('lib', __dir__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
4
|
+
require 'compensate/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'compensate'
|
8
8
|
spec.version = Compensate::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
9
|
+
spec.authors = ['Keifer Furzland']
|
10
|
+
spec.email = ['kfrz.code@gmail.com']
|
11
11
|
|
12
|
-
spec.summary =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
12
|
+
spec.summary = 'Calculate total reimbursement amount for a given CSV of project date ranges'
|
13
|
+
spec.homepage = 'https://gitlab.com/kfrz/compensate'
|
14
|
+
spec.license = 'MIT'
|
15
15
|
|
16
16
|
# Specify which files should be added to the gem when it is released.
|
17
17
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
18
|
-
spec.files = Dir.chdir(File.expand_path(
|
18
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
19
19
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
20
20
|
end
|
21
21
|
spec.executables << 'compensate'
|
22
|
-
spec.require_paths = [
|
22
|
+
spec.require_paths = ['lib']
|
23
23
|
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
25
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
26
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
27
27
|
end
|
data/lib/compensate/version.rb
CHANGED
data/lib/compensate.rb
CHANGED
@@ -1,53 +1,38 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'compensate/version'
|
2
|
+
require 'csv'
|
3
3
|
|
4
4
|
module Compensate
|
5
5
|
class ProjectSet
|
6
|
-
RATE_HIGH = '85'
|
7
|
-
RATE_LOW = '75'
|
8
|
-
TRAVEL_RATE_HIGH = '55'
|
9
|
-
TRAVEL_RATE_LOW = '45'
|
10
|
-
|
6
|
+
RATE_HIGH = '85'.freeze
|
7
|
+
RATE_LOW = '75'.freeze
|
8
|
+
TRAVEL_RATE_HIGH = '55'.freeze
|
9
|
+
TRAVEL_RATE_LOW = '45'.freeze
|
11
10
|
|
12
11
|
def initialize(csv)
|
13
12
|
@projects = projects_from_csv(csv)
|
14
13
|
end
|
15
14
|
|
16
15
|
def total
|
17
|
-
|
16
|
+
parse_projects_and_handle_duplicates
|
17
|
+
apply_billing_rates_to_hash
|
18
18
|
calculate_total
|
19
19
|
end
|
20
20
|
|
21
21
|
private
|
22
22
|
|
23
|
-
def
|
24
|
-
billing_hash.key?(date_to_string(day))
|
25
|
-
end
|
26
|
-
|
27
|
-
def hash_entry_for(day)
|
28
|
-
billing_hash[date_to_string(day)].to_sym
|
29
|
-
end
|
30
|
-
|
31
|
-
def build_billing_hash
|
23
|
+
def parse_projects_and_handle_duplicates
|
32
24
|
# Split projects up and determine what rate to bill at
|
33
25
|
@projects.each do |project|
|
34
26
|
rate = project[:rate]
|
35
27
|
days_in(project).each do |day|
|
36
28
|
date = date_to_string(day)
|
37
|
-
|
38
|
-
billing_hash[date] = if billing_hash[date] == 'high'
|
39
|
-
'high'
|
40
|
-
else
|
41
|
-
billing_hash[date]
|
42
|
-
end
|
43
|
-
else
|
44
|
-
billing_hash[date] = rate
|
45
|
-
end
|
29
|
+
billing_hash[date] = rate unless has_been_logged?(day)
|
46
30
|
end
|
47
31
|
end
|
48
32
|
end
|
49
33
|
|
50
|
-
def
|
34
|
+
def apply_billing_rates_to_hash
|
35
|
+
# splice in the correct billing rate
|
51
36
|
billing_hash.each do |k, v|
|
52
37
|
billing_hash[k] = if v == 'low'
|
53
38
|
RATE_LOW
|
@@ -55,33 +40,53 @@ module Compensate
|
|
55
40
|
RATE_HIGH
|
56
41
|
end
|
57
42
|
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def calculate_total
|
46
|
+
total = all_project_sums.map(&:sum)
|
47
|
+
"Total is $#{total.sum}.00"
|
48
|
+
end
|
49
|
+
|
50
|
+
def all_project_sums
|
51
|
+
ranges = split_projects_into_ranges
|
52
|
+
|
53
|
+
# Apply travel rate to first and last days in each range
|
54
|
+
ranges.each do |range|
|
55
|
+
range.each_with_index do |r, i|
|
56
|
+
r[1] = travel_rate_for(r) if (i == 0) || (i == range.size - 1)
|
57
|
+
end
|
58
|
+
end
|
58
59
|
|
60
|
+
# Sum each range's billing amount
|
61
|
+
ranges.map do |range|
|
62
|
+
range.map { |r| total = + r[1].to_i }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def split_projects_into_ranges
|
59
67
|
date_array = billing_hash.to_a
|
60
68
|
previous = date_array[0]
|
61
69
|
|
70
|
+
# Calculate where project ranges have gaps
|
62
71
|
ranges = date_array.slice_before do |e|
|
63
72
|
subsequent = previous
|
64
73
|
previous = e
|
65
74
|
to_date(subsequent[0]).next_day != to_date(e[0])
|
66
75
|
end
|
76
|
+
end
|
67
77
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
r[1] = travel_rate(r)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
78
|
+
def days_in(project)
|
79
|
+
start_date = to_date(project[:start])
|
80
|
+
end_date = to_date(project[:end])
|
75
81
|
|
76
|
-
|
77
|
-
|
78
|
-
end
|
82
|
+
(start_date..end_date)
|
83
|
+
end
|
79
84
|
|
80
|
-
|
81
|
-
|
85
|
+
def has_been_logged?(day)
|
86
|
+
billing_hash.key?(date_to_string(day))
|
82
87
|
end
|
83
88
|
|
84
|
-
|
89
|
+
def travel_rate_for(day)
|
85
90
|
case day[1]
|
86
91
|
when RATE_HIGH
|
87
92
|
TRAVEL_RATE_HIGH
|
@@ -90,13 +95,6 @@ module Compensate
|
|
90
95
|
end
|
91
96
|
end
|
92
97
|
|
93
|
-
def days_in(project)
|
94
|
-
start = to_date(project[:start])
|
95
|
-
end_date = to_date(project[:end])
|
96
|
-
|
97
|
-
(start..end_date)
|
98
|
-
end
|
99
|
-
|
100
98
|
def to_date(string)
|
101
99
|
DateTime.strptime(string.to_s, date_format)
|
102
100
|
end
|
@@ -105,14 +103,14 @@ module Compensate
|
|
105
103
|
date.strftime(date_format)
|
106
104
|
end
|
107
105
|
|
108
|
-
|
106
|
+
def date_format
|
109
107
|
'%m/%d/%y'
|
110
108
|
end
|
111
109
|
|
112
110
|
def projects_from_csv(csv)
|
113
111
|
project_array = []
|
114
112
|
CSV.foreach(csv, headers: true) do |row|
|
115
|
-
project_array << {rate: row[0], start: row[1], end: row[2]}
|
113
|
+
project_array << { rate: row[0], start: row[1], end: row[2] }
|
116
114
|
end
|
117
115
|
project_array
|
118
116
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: compensate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keifer Furzland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-06-
|
11
|
+
date: 2018-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|