Class: Latinum::Bank

Inherits:
Object
  • Object
show all
Defined in:
lib/latinum/bank.rb

Overview

A bank defines exchange rates and formatting rules for resources. It is a centralised location for resource formatting and metadata.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*imports) ⇒ Bank

Imports all given currencies.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/latinum/bank.rb', line 37

def initialize(*imports)
	@rates = []
	@exchange = {}
	
	# This implementation may change:
	@currencies = {}
	@formatters = {}
	
	# Symbols and their associated priorities
	@symbols = {}
	
	imports&.each do |resources|
		import(resources)
	end
end

Instance Attribute Details

#currenciesObject (readonly)

The supported currents and assocaited formatting details.



84
85
86
# File 'lib/latinum/bank.rb', line 84

def currencies
  @currencies
end

#ratesObject (readonly)

Returns the value of attribute rates.



76
77
78
# File 'lib/latinum/bank.rb', line 76

def rates
  @rates
end

#symbolsObject (readonly)

A map of all recognised symbols ordered by priority.



80
81
82
# File 'lib/latinum/bank.rb', line 80

def symbols
  @symbols
end

Instance Method Details

#<<(rate) ⇒ Object

Add an exchange rate to the bank.



88
89
90
91
92
93
# File 'lib/latinum/bank.rb', line 88

def <<(rate)
	@rates << rate
	
	@exchange[rate.input] ||= {}
	@exchange[rate.input][rate.output] = rate
end

#[](name) ⇒ Object

Look up a currency by name.



72
73
74
# File 'lib/latinum/bank.rb', line 72

def [](name)
	@currencies[name]
end

#dump(resource) ⇒ Object



135
136
137
# File 'lib/latinum/bank.rb', line 135

def dump(resource)
	resource.to_s if resource
end

#exchange(resource, for_name) ⇒ Object

Exchange one resource for another using internally specified rates.



96
97
98
99
100
101
102
103
104
# File 'lib/latinum/bank.rb', line 96

def exchange(resource, for_name)
	unless rate = @exchange.dig(resource.name, for_name)
		raise ArgumentError.new("Rate #{rate} unavailable")
	end
	
	config = self[for_name]
	
	return resource.exchange(rate.factor, for_name, config[:precision])
end

#format(resource, *arguments, **options) ⇒ Object

Format a resource as a string according to the loaded currencies.



160
161
162
163
164
165
166
# File 'lib/latinum/bank.rb', line 160

def format(resource, *arguments, **options)
	unless formatter = @formatters[resource.name]
		raise ArgumentError.new("No formatter found for #{resource.name}")
	end
	
	formatter.format(resource.amount, *arguments, **options)
end

#from_integral(amount, name) ⇒ Object

Convert the resource from an integral representation based on the currency’s precision.



181
182
183
184
185
# File 'lib/latinum/bank.rb', line 181

def from_integral(amount, name)
	formatter = @formatters[name]
	
	Resource.new(formatter.from_integral(amount), name)
end

#import(resources) ⇒ Object

Import a list of resource templates, e.g. currencies.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/latinum/bank.rb', line 54

def import(resources)
	resources.each do |name, config|
		name = (config[:name] || name).to_s
		
		@currencies[name] = config
		
		# Create a formatter:
		@formatters[name] = config[:formatter].new(**config)
		
		if config[:symbol]
			symbols = (@symbols[config[:symbol]] ||= [])
			symbols << [config.fetch(:priority, -1), name.to_s]
			symbols.sort!.uniq!
		end
	end
end

#load(input) ⇒ Object



128
129
130
131
132
133
# File 'lib/latinum/bank.rb', line 128

def load(input)
	if input.is_a?(String)
		input = input.strip
		return parse(input) unless input.empty?
	end
end

#parse(string, default_name: nil) ⇒ Object

Parse a string according to the loaded currencies.



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/latinum/bank.rb', line 107

def parse(string, default_name: nil)
	parts = string.strip.split(/\s+/, 2)
	
	if parts.size == 2
		return parse_named_resource(parts[1], parts[0])
	else
		# Lookup the named symbol, e.g. '$', and get the highest priority name:
		symbol = @symbols.fetch(string.gsub(/[\-\.,0-9]/, ''), []).last
		
		if symbol
			name = symbol.last.to_s
		elsif default_name
			name = default_name
		else
			raise ArgumentError, "Could not parse #{string}, could not determine resource name!"
		end
		
		return parse_named_resource(name, string)
	end
end

#round(resource) ⇒ Object

Rounds the specified resource to the maximum precision as specified by the formatter. Whe computing things like tax, you often get fractional amounts which are unpayable because they are smaller than the minimum discrete unit of the currency. This method helps to round a currency to a payable amount.



150
151
152
153
154
155
156
# File 'lib/latinum/bank.rb', line 150

def round(resource)
	unless formatter = @formatters[resource.name]
		raise ArgumentError.new("No formatter found for #{resource.name}")
	end
	
	return Resource.new(formatter.round(resource.amount), resource.name)
end

#to_integral(resource) ⇒ Object

Convert the resource to an integral representation based on the currency’s precision.



171
172
173
174
175
# File 'lib/latinum/bank.rb', line 171

def to_integral(resource)
	formatter = @formatters[resource.name]
	
	formatter.to_integral(resource.amount)
end