require './ordered_hash' class BalanceSheet < ActiveSupport::OrderedHash attr_accessor :assets, :liabilities, :MAX, :RESERVE_REQUIREMENT, :name, :DEBUG def initialize(name = 'Balance Sheet', *args) super(name) @MAX = 40 @name = name @headers = [] args.each { |header| @headers.push(header) } @assets = Array.new @liabilities = Array.new @RESERVE_REQUIREMENT = 0.2 @asset_total = 0.0 @liability_total = 0.0 @DEBUG = 0 #@DEBUG = 1 #@outstanding_loans = 0.0 self['assets'] = @assets self['liabilities'] = @liabilities end def draw(maxstring = 16) puts;puts max = getLongestString(); max += 3 if maxstring > max then max = maxstring end if max > @MAX then max = @MAX end #puts "max==#{max}" total = 2*max+3 puts @name.center(total) @headers.each { |header| puts header.center(total) } printf("%-#{max}s | %#{max}s", "assets","liabilities") puts total.times { print '-' }; puts total_assets = 0; total_liabilities = 0 self['assets'].each_with_index { |element, index| #puts "balancesheet.draw: element == #{element}" minus = false begin if element =~ /^\-/ then minus = true end #puts "balancesheet.draw: element = #{element}; minus=#{minus}" if element =~ /\$(\d+[.,]?\d*)(.*)/ asset_value = $1.to_f; rest = $2.to_s if minus then asset_value = -asset_value end total_assets += asset_value formatted_element = sprintf("$%.2f%s", asset_value, rest) if formatted_element == "$0.00" then formatted_element = ' ' end else; formatted_element = element; end rescue; end minus = false begin #if element =~ /^\-/ then minus = true end if self['liabilities'][index] =~ /^\-/ then minus = true end if self['liabilities'][index] =~ /\$(\d+[.,]?\d*)(.*)/ liability_value = $1.to_f if minus then liability_value = -liability_value end total_liabilities += liability_value formatted_liability = sprintf("$%.2f%s", liability_value, $2.to_s) if formatted_liability == "$0.00" then formatted_liability = ' ' end else; formatted_liability = self['liabilities'][index]; end rescue; end #TODO: nicely wrap entries that are longer than @MAX #printf("%-#{max}s | %#{max}s", element, self['liabilities'][index]) printf("%-#{max}s | %#{max}s", formatted_element, formatted_liability) puts #printf("%-#{max}s | %#{max}s", ' ', ' '); puts # insert blank line #printf("%-#{max}s | %#{max}s", ' ', ' '); puts # insert blank line } printf("%-#{max}s | %#{max}s", ' ', ' '); puts # insert blank line formatted_total_assets = sprintf("%.2f", total_assets) formatted_total_liabilities = sprintf("%.2f", total_liabilities) printf("%-#{max}s | %#{max}s", "Total: $#{formatted_total_assets}", "Total: $#{formatted_total_liabilities}") unless formatted_total_assets == "0.00" puts;puts @asset_total = total_assets; @liability_total = total_liabilities return end def getLongestString() if @assets.length == 0 @assets.push(' ') end while @assets.length > @liabilities.length @liabilities.push(' ') end while @assets.length < @liabilities.length @assets.push(' ') end #puts @assets, @liabilities max = @assets.max{ |c1, c2| c1.length <=> c2.length } max2 = @liabilities.max{ |c1, c2| c1.length <=> c2.length } return max.length unless max2.length > max.length max2.length end def draw_as_string(maxstring = 16) output = "\n\n" max = getLongestString(); max += 3 if max > @MAX then max = @MAX end total = 2*max+3 output += @name.center(total) + "\n" @headers.each { |header| output += header.center(total) + "\n" } output += sprintf("%-#{max}s | %#{max}s", "assets","liabilities") output += "\n" total.times { output += "-" }; output += "\n" total_assets = 0; total_liabilities = 0 self['assets'].each_with_index { |element, index| begin if element =~ /\$(\d+[.,]?\d*)(.*)/ asset_value = $1.to_f; rest = $2.to_s total_assets += asset_value formatted_element = sprintf("$%.2f%s", asset_value, rest) if formatted_element == "$0.00" then formatted_element = ' ' end else; formatted_element = element; end rescue; end begin if self['liabilities'][index] =~ /\$(\d+[.,]?\d*)(.*)/ liability_value = $1.to_f; rest = $2.to_s total_liabilities += liability_value formatted_liability = sprintf("$%.2f%s", liability_value, rest) if formatted_liability == "$0.00" then formatted_liability = ' ' end else; formatted_liability = self['liabilities'][index]; end rescue; end output += sprintf("%-#{max}s | %#{max}s", formatted_element, formatted_liability) output += "\n" } output += sprintf("%-#{max}s | %#{max}s", ' ', ' '); puts # insert blank line formatted_total_assets = sprintf("%.2f", total_assets) formatted_total_liabilities = sprintf("%.2f", total_liabilities) output += sprintf("%-#{max}s | %#{max}s", "Total: $#{formatted_total_assets}", "Total: $#{formatted_total_liabilities}") unless formatted_total_assets == "0.00" output += "\n\n" @asset_total = total_assets; @liability_total = total_liabilities return output end def lend_long(loan_to = "loan") # calculate reserve and outstanding loan totals reserves = 0.0 outstanding_loans = 0.0 @assets.each { |asset| puts "asset: #{asset}" unless @DEBUG == 0 if asset =~ /\$(\d+[.,]?\d*) reserves/ begin reserves += $1.to_f puts "reserves 1: #{reserves}" unless @DEBUG == 0 rescue; end next end if asset =~ /\$(\d+[,.]?\d*) loan/ begin value = $1.to_f outstanding_loans = value rescue; end end } new_reserves = @liability_total * @RESERVE_REQUIREMENT #new_reserves = (new_reserves*100).round / 100.0 puts "new_reserves: #{new_reserves}" unless @DEBUG == 0 puts "reserves: #{reserves}" unless @DEBUG == 0 puts "outstanding_loans: #{outstanding_loans}" unless @DEBUG == 0 amount_to_lend_long = reserves - new_reserves #- outstanding_loans #amount_to_lend_long = outstanding_loans + (reserves - new_reserves) puts "amount_to_lend_long: #{amount_to_lend_long}" unless @DEBUG == 0 # now, reset reserves, and lend long #@assets.each { |asset| # if asset =~ /$(\d+[.,]?\d*) reserves/ # asset = "$#{new_reserves} reserves" # end #} @assets.map! { |asset| asset =~ /\$(\d+[.,]?\d*) reserves/ ? "$#{new_reserves} reserves" : asset } @assets.uniq! @assets.push("$#{amount_to_lend_long} #{loan_to}") return amount_to_lend_long end def decrement_entry(entry) decrement_asset(entry) decrement_liability(entry) end def increment_entry(entry) increment_asset(entry) increment_liability(entry) end def decrement_asset(entry) @assets.each_with_index { |asset,index| if entry == asset asset = '-' + asset @assets[index] = asset end } end def decrement_liability(entry) @liabilities.each_with_index { |liability,index| if entry == liability liability = '-' + liability @liabilities[index] = liability end } end def increment_asset(entry) @assets.each_with_index { |asset, index| if entry == asset asset = '+' + asset @assets[index] = asset end } end def increment_liability(entry) @liabilities.each_with_index { |liability,index| if entry == liability liability = '+' + liability @liabilities[index] = liability end } end end