bankroll 0.1.0 → 0.1.1

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
  SHA256:
3
- metadata.gz: 2fce9b108026fb88dc7010a720a419ba1c4511da3f54b4c6f227340c936b084c
4
- data.tar.gz: a565f6231e134aa9df16a44c9b99dc8fdd8154694bdf3b9be3a0e180c58e246e
3
+ metadata.gz: 3d60a1c7c561cbb9945f94a7913cb116dba1c56d050ae0f26d34543c811a1fbe
4
+ data.tar.gz: 80a97fd7345e676473515dff20c449053502a5457f653d615061ca5d27a8e508
5
5
  SHA512:
6
- metadata.gz: d9845beb9d4b8ce2fabc7a86f387e421a6c51c925304638ca0f0998291078f07a86dff5884ce7aef7a9353025b9d7fa63b2ce365c9ba085cabdd26b8ba33fec7
7
- data.tar.gz: dcf4c4f7fe1d59296669ffdc1dda48373fa228fd6909a85219823281dd671786c17d1f33e5337c8b5129a613b46f50d2d69cf4bde050edb814388841097f06b4
6
+ metadata.gz: e6fa504c7d3a0be597686abf78ac31ea7ac17d51c551d8b03737b242fd0d3eb79750d67efa430bd7d0cfa580dae50156ddd17381c410c66fdfaeb9b3d8e73275
7
+ data.tar.gz: 42793b333497660e72d893c46ab57b6ef4506c16994d34ddc17ad6d605df7b56e9160aee2826a57662e6ff2778e108202f4a39af6135e3b668f3bc06868f36de
data/.rubocop.yml CHANGED
@@ -5,6 +5,8 @@ require:
5
5
 
6
6
  # ==================== Main ==========================
7
7
  AllCops:
8
+ TargetRubyVersion: 3.1
9
+ NewCops: enable
8
10
  DisplayCopNames: true
9
11
  Exclude:
10
12
  - "bin/**/*"
@@ -68,6 +70,8 @@ Layout/LineEndStringConcatenationIndentation:
68
70
  IndentationWidth: 0
69
71
  Layout/LineLength:
70
72
  Max: 100
73
+ Exclude:
74
+ - "lib/bankroll/interest_rate.rb"
71
75
  Layout/MultilineArrayLineBreaks:
72
76
  Enabled: true
73
77
  Layout/MultilineAssignmentLayout:
@@ -118,7 +122,7 @@ Lint/ElseLayout:
118
122
  Lint/EmptyBlock:
119
123
  Enabled: true
120
124
  AllowComments: false
121
- AllowEmptyLambdas: false
125
+ AllowEmptyLambdas: true
122
126
  Lint/EmptyClass:
123
127
  Enabled: true
124
128
  Lint/EmptyConditionalBody:
@@ -199,6 +203,16 @@ Metrics/BlockLength:
199
203
  - "spec/**/*"
200
204
  Metrics/ParameterLists:
201
205
  Max: 3
206
+ Exclude:
207
+ - "lib/bankroll/interest_rate.rb"
208
+ Metrics/AbcSize:
209
+ Enabled: true
210
+ Exclude:
211
+ - "lib/bankroll/interest_rate.rb"
212
+ Metrics/MethodLength:
213
+ Enabled: true
214
+ Exclude:
215
+ - "lib/bankroll/interest_rate.rb"
202
216
  Naming/BlockForwarding:
203
217
  Enabled: true
204
218
  Naming/InclusiveLanguage:
@@ -223,8 +237,12 @@ Naming/VariableNumber:
223
237
  EnforcedStyle: snake_case
224
238
  AllowedIdentifiers:
225
239
  - capture3
240
+ Exclude:
241
+ - "lib/bankroll/interest_rate.rb"
226
242
  Naming/MethodParameterName:
227
243
  AllowNamesEndingInNumbers: false
244
+ Exclude:
245
+ - "lib/bankroll/interest_rate.rb"
228
246
  Security/IoMethods:
229
247
  Enabled: true
230
248
  Style/AccessorGrouping:
@@ -311,7 +329,7 @@ Style/MethodCallWithArgsParentheses:
311
329
  AllowParenthesesInMultilineCall: true
312
330
  IgnoreMacros: false
313
331
  Style/MethodDefParentheses:
314
- EnforcedStyle: false
332
+ EnforcedStyle: require_parentheses
315
333
  Style/MissingElse:
316
334
  Enabled: false
317
335
  Style/MultilineInPatternThen:
@@ -438,6 +456,10 @@ Performance/Sum:
438
456
  Enabled: true
439
457
 
440
458
  # ==================== RSpec ============================
459
+ RSpec/BeEq:
460
+ Enabled: true
461
+ RSpec/BeNil:
462
+ Enabled: true
441
463
  RSpec/ContextWording:
442
464
  Prefixes:
443
465
  - when
data/Gemfile CHANGED
@@ -7,8 +7,12 @@ gemspec
7
7
 
8
8
  gem "rake", "~> 13.0"
9
9
 
10
- gem "rspec", "~> 3.0"
11
-
12
- gem "rubocop", "~> 1.21"
13
-
14
- gem "byebug"
10
+ group :development, :test do
11
+ gem "byebug"
12
+ gem "rspec", "~> 3.0"
13
+ gem "rubocop", "~> 1.21"
14
+ gem "rubocop-performance"
15
+ gem "rubocop-rake"
16
+ gem "rubocop-rspec"
17
+ gem "solargraph"
18
+ end
data/Gemfile.lock CHANGED
@@ -1,15 +1,17 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bankroll (0.1.0)
5
- dry-equalizer
6
- dry-initializer
7
- dry-types
4
+ bankroll (0.1.1)
5
+ dry-equalizer (~> 0.3.0)
6
+ dry-initializer (~> 3.1.1)
7
+ dry-types (~> 1.5.1)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
12
  ast (2.4.2)
13
+ backport (1.2.0)
14
+ benchmark (0.2.0)
13
15
  byebug (11.1.3)
14
16
  concurrent-ruby (1.1.9)
15
17
  diff-lcs (1.5.0)
@@ -33,12 +35,25 @@ GEM
33
35
  dry-core (~> 0.5, >= 0.5)
34
36
  dry-inflector (~> 0.1, >= 0.1.2)
35
37
  dry-logic (~> 1.0, >= 1.0.2)
38
+ e2mmap (0.1.0)
39
+ jaro_winkler (1.5.4)
40
+ kramdown (2.3.1)
41
+ rexml
42
+ kramdown-parser-gfm (1.1.0)
43
+ kramdown (~> 2.0)
44
+ nokogiri (1.13.3-x86_64-darwin)
45
+ racc (~> 1.4)
46
+ nokogiri (1.13.3-x86_64-linux)
47
+ racc (~> 1.4)
36
48
  parallel (1.21.0)
37
49
  parser (3.1.0.0)
38
50
  ast (~> 2.4.1)
51
+ racc (1.6.0)
39
52
  rainbow (3.1.1)
40
53
  rake (13.0.6)
41
54
  regexp_parser (2.2.0)
55
+ reverse_markdown (2.1.1)
56
+ nokogiri
42
57
  rexml (3.2.5)
43
58
  rspec (3.10.0)
44
59
  rspec-core (~> 3.10.0)
@@ -64,11 +79,39 @@ GEM
64
79
  unicode-display_width (>= 1.4.0, < 3.0)
65
80
  rubocop-ast (1.15.1)
66
81
  parser (>= 3.0.1.1)
82
+ rubocop-performance (1.13.2)
83
+ rubocop (>= 1.7.0, < 2.0)
84
+ rubocop-ast (>= 0.4.0)
85
+ rubocop-rake (0.6.0)
86
+ rubocop (~> 1.0)
87
+ rubocop-rspec (2.8.0)
88
+ rubocop (~> 1.19)
67
89
  ruby-progressbar (1.11.0)
90
+ solargraph (0.44.3)
91
+ backport (~> 1.2)
92
+ benchmark
93
+ bundler (>= 1.17.2)
94
+ diff-lcs (~> 1.4)
95
+ e2mmap
96
+ jaro_winkler (~> 1.5)
97
+ kramdown (~> 2.3)
98
+ kramdown-parser-gfm (~> 1.1)
99
+ parser (~> 3.0)
100
+ reverse_markdown (>= 1.0.5, < 3)
101
+ rubocop (>= 0.52)
102
+ thor (~> 1.0)
103
+ tilt (~> 2.0)
104
+ yard (~> 0.9, >= 0.9.24)
105
+ thor (1.2.1)
106
+ tilt (2.0.10)
68
107
  unicode-display_width (2.1.0)
108
+ webrick (1.7.0)
109
+ yard (0.9.27)
110
+ webrick (~> 1.7.0)
69
111
 
70
112
  PLATFORMS
71
113
  x86_64-darwin-20
114
+ x86_64-linux
72
115
 
73
116
  DEPENDENCIES
74
117
  bankroll!
@@ -76,6 +119,10 @@ DEPENDENCIES
76
119
  rake (~> 13.0)
77
120
  rspec (~> 3.0)
78
121
  rubocop (~> 1.21)
122
+ rubocop-performance
123
+ rubocop-rake
124
+ rubocop-rspec
125
+ solargraph
79
126
 
80
127
  BUNDLED WITH
81
128
  2.2.32
data/README.md CHANGED
@@ -46,8 +46,9 @@ puts payment #=> Bankroll::Decimal["3_216.40"]
46
46
  original_amount = Bankroll.present_value(
47
47
  periods: 360, # 30 years
48
48
  monthly_payment: 3_216.40,
49
- interest_rate: 0.01 / 12.0, # 2.5%
49
+ interest_rate: 0.01 / 12.0, # 1% APR
50
50
  ).round
51
+
51
52
  puts original_amount #=> Bankroll::Decimal["1_000_001.49"]
52
53
 
53
54
  # What does the balance look like after a single mortgage payment?
@@ -58,6 +59,7 @@ unpaid_balance = Bankroll.unpaid_balance(
58
59
  period: 1,
59
60
  payment: 3_216.40
60
61
  ).round
62
+
61
63
  puts unpaid_balance #=> Bankroll::Decimal["997_616.94"]
62
64
 
63
65
  # What was the interest rate?
@@ -66,6 +68,7 @@ interest_rate = Bankroll.interest_rate(
66
68
  periods: 360,
67
69
  payment: -3_216.40,
68
70
  ).round(3)
71
+
69
72
  puts interest_rate #=> Bankroll::Decimal["0.833e-3"]
70
73
 
71
74
  # What is the annuity factor of a rate for n periods?
@@ -73,6 +76,7 @@ annuity_factor = Bankroll.annuity_factor(
73
76
  interest_rate: 0.01,
74
77
  periods: 2
75
78
  ).round(4)
79
+
76
80
  puts annuity_factor #=> Bankroll::Decimal["1.9704"]
77
81
 
78
82
  # What is the total interest paid on a 500_000 1% mortgage
@@ -82,6 +86,7 @@ interest_paid = Bankroll.cumulative_interest(
82
86
  payment: 1_608.20,
83
87
  present_value: 500_000
84
88
  ).round
89
+
85
90
  puts interest_paid #=> Bankroll::Decimal["832.34"]
86
91
 
87
92
  # What is the total cost of a 500_000 1% loan with interest?
@@ -91,6 +96,7 @@ total_amount = Bankroll.future_value(
91
96
  periods: 360,
92
97
  payment: 1_608.20
93
98
  ).round
99
+
94
100
  puts total_amount #=> Bankroll::Decimal["647_846.10"]
95
101
 
96
102
  # What is the interest payment on the 17th period of a $165,000 3% mortgage?
@@ -100,6 +106,7 @@ interest_payment = Bankroll.interest_payment(
100
106
  period: 17,
101
107
  present_value: 165_000
102
108
  ).round
109
+
103
110
  puts interest_payment #=> Bankroll::Decimal["400.96"]
104
111
 
105
112
  # How many periods until a -$1000 account with -$100/month reaches $10_000 with
@@ -110,6 +117,7 @@ total_periods = Bankroll.total_periods(
110
117
  present_value: -1_000,
111
118
  future_value: 10_000
112
119
  )
120
+
113
121
  puts total_periods #=> Bankroll::Decimal["59.67"]
114
122
 
115
123
  # What is the amortization schedule of a $165_000 3% 30 year mortgage?
@@ -118,6 +126,7 @@ amortization_schedule = Bankroll.amortization_schedule(
118
126
  interest_rate: 0.03 / 12.0,
119
127
  periods: 360
120
128
  )
129
+
121
130
  puts amortization_schedule.payments #=> [
122
131
  # Bankroll::AmortizationSchedule::Payment.new(
123
132
  # payment: Bankroll::Decimal["695.65"],
data/bankroll.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = "Mortgage and refinance calculations for ruby"
13
13
  spec.homepage = "https://github.com/nolantait/bankroll"
14
14
  spec.license = "MIT"
15
- spec.required_ruby_version = ">= 2.6.0"
15
+ spec.required_ruby_version = ">= 3.1.0"
16
16
 
17
17
  spec.metadata["homepage_uri"] = spec.homepage
18
18
  spec.metadata["source_code_uri"] = "https://github.com/nolantait/bankroll"
@@ -22,18 +22,20 @@ Gem::Specification.new do |spec|
22
22
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
23
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
24
  `git ls-files -z`.split("\x0").reject do |f|
25
- (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
25
+ (f == __FILE__) ||
26
+ f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
26
27
  end
27
28
  end
28
29
  spec.bindir = "exe"
29
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.executables = spec.files.grep(%r(\Aexe/)) { |f| File.basename(f) }
30
31
  spec.require_paths = ["lib"]
31
32
 
32
33
  # Uncomment to register a new dependency of your gem
33
- spec.add_dependency "dry-types"
34
- spec.add_dependency "dry-initializer"
35
- spec.add_dependency "dry-equalizer"
34
+ spec.add_dependency "dry-equalizer", "~> 0.3.0"
35
+ spec.add_dependency "dry-initializer", "~> 3.1.1"
36
+ spec.add_dependency "dry-types", "~> 1.5.1"
36
37
 
37
38
  # For more information and examples about making a new gem, checkout our
38
39
  # guide at: https://bundler.io/guides/creating_gem.html
40
+ spec.metadata["rubygems_mfa_required"] = "true"
39
41
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bankroll
2
4
  class AmortizationSchedule
3
5
  extend Dry::Initializer
@@ -18,22 +20,14 @@ module Bankroll
18
20
 
19
21
  def each
20
22
  Enumerator.new do |yielder|
21
- total_interest = Decimal["0"]
22
- balance = @present_value
23
+ current_payment = Payment.new(
24
+ payment: monthly_payment.round,
25
+ total_interest: Decimal["0"],
26
+ balance: @present_value
27
+ )
23
28
 
24
29
  periods.times do |period|
25
- interest = interest_payment(period + 1)
26
- principal = payment - interest
27
- total_interest += interest
28
- balance -= principal
29
-
30
- yielder << Payment.new(
31
- payment: payment.round,
32
- principal: principal.round,
33
- interest: interest.round,
34
- total_interest: total_interest.round,
35
- balance: balance.round
36
- )
30
+ yielder << current_payment = payment_for_period(period, current_payment)
37
31
  end
38
32
  end
39
33
  end
@@ -48,18 +42,31 @@ module Bankroll
48
42
 
49
43
  private
50
44
 
45
+ def payment_for_period(period, last_payment)
46
+ interest = interest_payment(period + 1)
47
+ principal = last_payment.payment - interest
48
+
49
+ Payment.new(
50
+ payment: last_payment.payment,
51
+ principal: principal.round,
52
+ interest: interest.round,
53
+ total_interest: (last_payment.total_interest + interest).round,
54
+ balance: (last_payment.balance - principal).round
55
+ )
56
+ end
57
+
51
58
  def interest_payment(period)
52
59
  InterestPayment.call(
53
60
  interest_rate: @interest_rate,
54
61
  periods: @periods,
55
- period: period,
62
+ period:,
56
63
  present_value: @present_value,
57
- payment: -payment
64
+ payment: -monthly_payment
58
65
  )
59
66
  end
60
67
 
61
- def payment
62
- @payment ||= Bankroll::Payment.call(
68
+ def monthly_payment
69
+ @monthly_payment ||= Bankroll::Payment.call(
63
70
  present_value: @present_value,
64
71
  interest_rate: @interest_rate,
65
72
  periods: @periods
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bankroll
2
4
  class AnnuityFactor
3
5
  extend Callable
4
6
  extend Dry::Initializer
5
7
 
6
- ONE = Decimal['1'].freeze
8
+ ONE = Decimal["1"].freeze
7
9
 
8
10
  option :periods, Types["bankroll.decimal"]
9
11
  option :interest_rate, Types["bankroll.decimal"]
@@ -19,7 +21,7 @@ module Bankroll
19
21
  end
20
22
 
21
23
  def interest_contribution_per_period
22
- (ONE + @interest_rate) ** -@periods
24
+ (ONE + @interest_rate)**-@periods
23
25
  end
24
26
  end
25
27
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bankroll
2
4
  module Callable
3
5
  def call(**kwargs)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bankroll
2
4
  class CumulativeInterest
3
5
  # Calculate the total interest paid at any period
@@ -11,7 +13,7 @@ module Bankroll
11
13
  option :present_value, Types["bankroll.decimal"]
12
14
 
13
15
  def call
14
- payments_made +
16
+ payments_made +
15
17
  ((total_interest - @payment) * percentage_of_interest_per_period)
16
18
  end
17
19
 
@@ -26,7 +28,7 @@ module Bankroll
26
28
  end
27
29
 
28
30
  def compound_rate
29
- (ONE + @interest_rate) ** @periods
31
+ (ONE + @interest_rate)**@periods
30
32
  end
31
33
 
32
34
  def total_interest
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bankroll
2
- class Decimal < Delegator
4
+ class Decimal < SimpleDelegator
3
5
  include Dry::Equalizer.new(:value)
4
6
 
5
7
  ROUNDING = :half_even
@@ -13,17 +15,19 @@ module Bankroll
13
15
  end
14
16
 
15
17
  attr_reader :value
16
- alias_method :__getobj__, :value
18
+
19
+ alias __getobj__ value
17
20
 
18
21
  def initialize(value)
19
22
  decimal = case value
20
- when self.class
21
- value.value.to_s
22
- else
23
- value.to_s
24
- end
23
+ when self.class
24
+ value.value.to_s
25
+ else
26
+ value.to_s
27
+ end
25
28
 
26
29
  @value = BigDecimal(Types["string"][decimal])
30
+ super(@value)
27
31
  end
28
32
 
29
33
  def round(precision = 2, rounding = ROUNDING)
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bankroll
2
4
  class FutureValue
3
- # Future value is the value to which an investment will grow
4
- # after one or more periods. Usage is with a fixed payment
5
+ # Future value is the value to which an investment will grow
6
+ # after one or more periods. Usage is with a fixed payment
5
7
 
6
8
  extend Callable
7
9
  extend Dry::Initializer
@@ -13,13 +15,13 @@ module Bankroll
13
15
 
14
16
  def call
15
17
  (effective_rate * present_value) +
16
- (@payment * (1 + @interest_rate * 0) * (effective_rate - 1) / @interest_rate)
18
+ (@payment * (1 + (@interest_rate * 0)) * (effective_rate - 1) / @interest_rate)
17
19
  end
18
20
 
19
21
  private
20
22
 
21
23
  def effective_rate
22
- (ONE + @interest_rate) ** @periods
24
+ (ONE + @interest_rate)**@periods
23
25
  end
24
26
  end
25
27
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bankroll
2
4
  class InterestPayment
3
5
  # The interest portion of a payment at period N
@@ -9,7 +11,7 @@ module Bankroll
9
11
  option :periods, Types["bankroll.decimal"]
10
12
  option :period, Types["integer"]
11
13
  option :present_value, Types["bankroll.decimal"]
12
- option :payment, Types["bankroll.decimal"] | Types["nil"], default: -> { nil }
14
+ option :payment, Types["bankroll.decimal"] | Types["nil"], default: -> {}
13
15
 
14
16
  def call
15
17
  future_loan_balance * @interest_rate
@@ -20,7 +22,7 @@ module Bankroll
20
22
  def future_loan_balance
21
23
  FutureValue.call(
22
24
  periods: @period - 1,
23
- payment: payment,
25
+ payment:,
24
26
  present_value: @present_value,
25
27
  interest_rate: @interest_rate
26
28
  )
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bankroll
2
4
  class InterestRate
3
5
  extend Dry::Initializer
@@ -15,7 +17,9 @@ module Bankroll
15
17
  significance_required = 1e-6
16
18
  stop = false
17
19
 
18
- begin
20
+ next_guess = 0
21
+
22
+ loop do
19
23
  temp = newton_iteration(
20
24
  guess,
21
25
  @periods,
@@ -28,20 +32,20 @@ module Bankroll
28
32
  difference = (next_guess - guess).abs
29
33
  stop = difference < significance_required
30
34
  guess = next_guess
31
- end while !stop
35
+ break if stop
36
+ end
32
37
 
33
38
  next_guess
34
39
  end
35
40
 
36
41
  private
37
42
 
38
-
39
43
  # This method was borrowed from the NumPy rate formula
40
44
  # which was generated by Sage
41
45
  def newton_iteration(r, n, p, x, y, w)
42
- t1 = (r+1)**n
43
- t2 = (r+1)**(n-1)
44
- ((y + t1*x + p*(t1 - 1)*(r*w + 1)/r) / (n*t2*x - p*(t1 - 1)*(r*w + 1)/(r**2) + n*p*t2*(r*w + 1)/r + p*(t1 - 1)*w/r))
46
+ t1 = (r + 1)**n
47
+ t2 = (r + 1)**(n - 1)
48
+ ((y + (t1 * x) + (p * (t1 - 1) * ((r * w) + 1) / r)) / ((n * t2 * x) - (p * (t1 - 1) * ((r * w) + 1) / (r**2)) + (n * p * t2 * ((r * w) + 1) / r) + (p * (t1 - 1) * w / r)))
45
49
  end
46
50
  end
47
51
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bankroll
2
4
  class Payment
3
5
  extend Callable
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bankroll
2
4
  class PresentValue
3
5
  extend Callable
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bankroll
2
4
  class TotalPeriods
3
5
  extend Callable
@@ -28,16 +30,16 @@ module Bankroll
28
30
  end
29
31
 
30
32
  def percentage_of_total_interest_on_principal
31
- (-@future_value + initial_payment_interest) /
33
+ (-@future_value + initial_payment_interest) /
32
34
  (@present_value + initial_payment_interest)
33
35
  end
34
36
 
35
37
  def initial_payment_interest
36
38
  case type
37
- when :ordinary
38
- (@payment * (1 + @interest_rate)) / @interest_rate
39
- else
40
- 0
39
+ when :ordinary
40
+ (@payment * (1 + @interest_rate)) / @interest_rate
41
+ else
42
+ 0
41
43
  end
42
44
  end
43
45
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bankroll
2
4
  module Types
3
5
  include Dry.Types()
@@ -13,11 +15,9 @@ module Bankroll
13
15
  end
14
16
 
15
17
  ConvertToDecimal = lambda do |value|
16
- if value.is_a? Bankroll::Decimal
17
- return value
18
- else
19
- Bankroll::Decimal[value.to_s]
20
- end
18
+ return value if value.is_a? Bankroll::Decimal
19
+
20
+ Bankroll::Decimal[value.to_s]
21
21
  end
22
22
 
23
23
  register("bankroll.decimal", Constructor[Bankroll::Decimal, fn: ConvertToDecimal])
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bankroll
2
4
  class UnpaidBalance
3
5
  extend Callable
4
6
  extend Dry::Initializer
5
7
 
6
- ONE = Decimal['1'].freeze
8
+ ONE = Decimal["1"].freeze
7
9
 
8
10
  option :present_value, Types["bankroll.decimal"]
9
11
  option :interest_rate, Types["bankroll.decimal"]
@@ -30,7 +32,7 @@ module Bankroll
30
32
 
31
33
  def annuity_factor
32
34
  AnnuityFactor.call(
33
- interest_rate: @interest_rate,
35
+ interest_rate: @interest_rate,
34
36
  periods: remaining
35
37
  )
36
38
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bankroll
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/lib/bankroll.rb CHANGED
@@ -25,9 +25,8 @@ require_relative "bankroll/interest_rate"
25
25
  BigDecimal.mode(BigDecimal::ROUND_MODE, Bankroll::Decimal::ROUNDING)
26
26
 
27
27
  module Bankroll
28
- ZERO = Decimal['0'].freeze
29
- ONE = Decimal['1'].freeze
30
-
28
+ ZERO = Decimal["0"].freeze
29
+ ONE = Decimal["1"].freeze
31
30
 
32
31
  class Error < StandardError; end
33
32
  # Your code goes here...
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bankroll
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nolan J Tait
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-16 00:00:00.000000000 Z
11
+ date: 2022-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: dry-types
14
+ name: dry-equalizer
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 0.3.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 0.3.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: dry-initializer
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: 3.1.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: 3.1.1
41
41
  - !ruby/object:Gem::Dependency
42
- name: dry-equalizer
42
+ name: dry-types
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 1.5.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 1.5.1
55
55
  description: Mortgage and refinance calculations for ruby
56
56
  email:
57
57
  - nolanjtait@gmail.com
@@ -94,6 +94,7 @@ metadata:
94
94
  homepage_uri: https://github.com/nolantait/bankroll
95
95
  source_code_uri: https://github.com/nolantait/bankroll
96
96
  changelog_uri: https://github.com/nolantait/bankroll/CHANGELOG.md
97
+ rubygems_mfa_required: 'true'
97
98
  post_install_message:
98
99
  rdoc_options: []
99
100
  require_paths:
@@ -102,14 +103,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
102
103
  requirements:
103
104
  - - ">="
104
105
  - !ruby/object:Gem::Version
105
- version: 2.6.0
106
+ version: 3.1.0
106
107
  required_rubygems_version: !ruby/object:Gem::Requirement
107
108
  requirements:
108
109
  - - ">="
109
110
  - !ruby/object:Gem::Version
110
111
  version: '0'
111
112
  requirements: []
112
- rubygems_version: 3.2.32
113
+ rubygems_version: 3.3.3
113
114
  signing_key:
114
115
  specification_version: 4
115
116
  summary: Mortgage and refinance calculations for ruby