Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion lib/fbe/award.rb
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ def line(value, text)
text.gsub(/\$\{([^}]*)\}/) do |_x|
k = Regexp.last_match[1].to_sym
raise(Fbe::Error, "Undefined variable '#{k}' used in award text: #{text}") unless @vars.key?(k)
@vars[k].is_a?(Float) ? whole(@vars[k]) : @vars[k]
@vars[k].is_a?(Float) ? short(@vars[k]) : @vars[k]
end
return if value.zero?
@lines << { v: value, t: text }
Expand Down Expand Up @@ -416,6 +416,15 @@ def greeting
def whole(value)
Integer(Float(value).round)
end

# Rounds a Float to two decimals, dropping the fraction when it is zero.
#
# @param [Float] value The value to print in the text of a line
# @return [Float, Integer] The value as short as it can be printed
def short(value)
r = value.round(2)
r == r.round ? r.round : r
end
end

# A class for generating human-readable bylaws.
Expand Down
35 changes: 35 additions & 0 deletions test/fbe/test_award.rb
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,39 @@ def test_rounds_float_variable_in_award_text
def test_div_does_not_truncate_integers
assert_equal(3, Fbe::Award.new('(award (give (times (div 3 2) 2) "x"))').bill.points)
end

def test_prints_float_rate_in_award_text
seed = Random.new_seed
k = Random.new(seed).rand(1..99) / 100.0
g = Fbe::Award.new(
"(award (give 1 \"base\") (in hoc \"hits\") (let k #{k}) (set b (times hoc k)) (give b \"at ${k} each\"))"
).bill(hoc: 1000).greeting
assert_includes(g, "at #{k} each", "rate is not printed as is, seed #{seed}")
end

def test_rounds_float_in_award_text_to_two_decimals
g = Fbe::Award.new('(award (give 1 "base") (set r (div 1 3)) (give 5 "at ${r} each"))').bill.greeting
assert_includes(g, 'at 0.33 each', 'float is not rounded to two decimals')
end

def test_prints_whole_float_in_award_text_without_fraction
seed = Random.new_seed
n = Random.new(seed).rand(1..1000)
g = Fbe::Award.new(
"(award (give 1 \"base\") (set d (times 0.5 #{n * 2})) (give 5 \"for ${d} days\"))"
).bill.greeting
assert_includes(g, "for #{n} days", "whole float is printed with a fraction, seed #{seed}")
end

def test_prints_tiny_negative_float_in_award_text_as_zero
g = Fbe::Award.new('(award (give 1 "base") (set d (times -0.001 1)) (give 5 "for ${d} days"))').bill.greeting
assert_includes(g, 'for 0 days', 'tiny negative float is not printed as zero')
end

def test_prints_negative_float_rate_in_award_text
seed = Random.new_seed
k = -Random.new(seed).rand(1..99) / 100.0
g = Fbe::Award.new("(award (give 1 \"base\") (let k #{k}) (give 5 \"at ${k} each\"))").bill.greeting
assert_includes(g, "at #{k} each", "negative rate is not printed as is, seed #{seed}")
end
end
Loading