class FortuneTeller::Simulator

Simulates personal finances.

Attributes

partner[RW]
primary[RW]
spending_strategy[RW]

Public Class Methods

new() click to toggle source
# File lib/fortuneteller/simulator.rb, line 6
def initialize
  @objects = {}
  @available_keys = ('AA'..'ZZ').to_a
end

Public Instance Methods

calculate_take_home_pay(_date) click to toggle source
# File lib/fortuneteller/simulator.rb, line 20
def calculate_take_home_pay(_date)
  # TODO: make this date dependant
  @objects[:job].each_value.map(&:calculate_take_home_pay).sum
end
inflating_int(int, start_date = nil) click to toggle source
# File lib/fortuneteller/simulator.rb, line 35
def inflating_int(int, start_date = nil)
  FortuneTeller::InflatingInt.new(
    int: int,
    start_date: (start_date.nil? ? Date.today : start_date)
  )
end
simulate() click to toggle source
# File lib/fortuneteller/simulator.rb, line 25
def simulate
  validate_plan!
  end_date = first_day_of_year((youngest_birthday.year + 101))
  states = [initial_state]
  while states.last.date != end_date
    states << simulate_next_state(states.last)
  end
  puts states.as_json
end

Private Instance Methods

add_object(type:, object:) click to toggle source
# File lib/fortuneteller/simulator.rb, line 101
def add_object(type:, object:)
  key = @available_keys.shift
  @objects[type] ||= {}
  @objects[type][key] = object
  key
end
evolve_state(state, transforms, to) click to toggle source
# File lib/fortuneteller/simulator.rb, line 60
def evolve_state(state, transforms, to)
  state = state.init_next
  transforms.each { |t| t.apply_to(state) }
  state.pass_time(to: to)
  state
end
first_day_of_year(year) click to toggle source
# File lib/fortuneteller/simulator.rb, line 56
def first_day_of_year(year)
  Date.new(year, 1, 1)
end
initial_state() click to toggle source
# File lib/fortuneteller/simulator.rb, line 91
def initial_state
  s = FortuneTeller::State.new(start_date: Date.today)
  @objects[:account].each { |k, a| s.add_account(key: k, account: a) }
  s
end
no_partner?() click to toggle source
# File lib/fortuneteller/simulator.rb, line 83
def no_partner?
  @partner.nil?
end
no_primary?() click to toggle source
# File lib/fortuneteller/simulator.rb, line 87
def no_primary?
  @primary.nil?
end
retrieve_objects(type:) click to toggle source
# File lib/fortuneteller/simulator.rb, line 108
def retrieve_objects(type:)
  @objects[type]
rescue NoMethodError
  {}
end
simulate_next_state(last) click to toggle source
# File lib/fortuneteller/simulator.rb, line 44
def simulate_next_state(last)
  end_date = first_day_of_year((last.date.year + 1))
  transforms = static_transforms(from: last.date, to: end_date)
  state = evolve_state(last, transforms, end_date)
  extra = spending_strategy.resolution_transforms(state: state)
  unless extra.empty?
    transforms.concat(extra).sort!
    state = evolve_state(last, transforms, end_date)
  end
  state
end
static_transforms(from:, to:) click to toggle source
# File lib/fortuneteller/simulator.rb, line 67
def static_transforms(from:, to:)
  transforms = []
  %i[job social_security].each do |object_type|
    @objects[object_type].each_value { |o| transforms.push(o) }
  end
  transforms = transforms.map do |x|
    x.bounded_gen_transforms(from: from, to: to, plan: self)
  end
  transforms.reduce([], :concat).sort
end
validate_plan!() click to toggle source
# File lib/fortuneteller/simulator.rb, line 97
def validate_plan!
  throw 'Please assign primary' if no_primary?
end
youngest_birthday() click to toggle source
# File lib/fortuneteller/simulator.rb, line 78
def youngest_birthday
  return @primary.birthday if no_partner?
  [@primary.birthday, @partner.birthday].min
end