diff --git a/award.rb b/award.rb index 5208232..cd0e146 100644 --- a/award.rb +++ b/award.rb @@ -1 +1,13 @@ -Award = Struct.new(:name, :expires_in, :quality) +Award = Struct.new(:name, :expires_in, :quality) do |new_class| + def increase_quality(quality) + self.quality += quality + end + + def decrease_quality(quality) + self.quality -= quality + end + + def decrease_expiration(day) + self.expires_in -= day + end +end diff --git a/reward_modifier.rb b/reward_modifier.rb new file mode 100644 index 0000000..cad54a8 --- /dev/null +++ b/reward_modifier.rb @@ -0,0 +1,56 @@ +require 'award' + +class RewardModifier + attr_accessor :awards + WHITE_LIST = ['Blue First', 'Blue Compare', 'Blue Distinction Plus'] + + def initialize(awards) + @awards = awards + end + + def update_quality + awards.each do |award| + calculate_quality(award) + modify_expiration_date(award) + calculate_expired_quality(award) if expiration_passed?(award) + end + end + + def modify_expiration_date(award) + award.decrease_expiration(1) if award.name != 'Blue Distinction Plus' + end + + def calculate_quality(award) + case award.name + when *WHITE_LIST + award.increase_quality(1) if award.quality < 50 + if award.name == 'Blue Compare' + award.increase_quality(1) if award.expires_in < 11 && award.quality < 50 + award.increase_quality(1) if award.expires_in < 6 && award.quality < 50 + end + else + if !award.quality.zero? && award.name != 'Blue Star' + award.decrease_quality(1) + elsif !award.quality.zero? && award.name == 'Blue Star' + award.decrease_quality(2) + end + end + end + + def expiration_passed?(award) + award.expires_in < 0 + end + + def calculate_expired_quality(award) + unless award.name == 'Blue First' + if award.name != 'Blue Compare' + award.decrease_quality(1) if award.name != 'Blue Distinction Plus' && award.quality > 0 && award.name != 'Blue Star' + award.decrease_quality(2) if award.name == 'Blue Star' && award.quality > 0 + else + award.quality = 0 + end + end + + award.increase_quality(1) if award.name == 'Blue First' && award.quality < 50 + end +end diff --git a/update_quality.rb b/update_quality.rb deleted file mode 100644 index bd1f10f..0000000 --- a/update_quality.rb +++ /dev/null @@ -1,49 +0,0 @@ -require 'award' - -def update_quality(awards) - awards.each do |award| - if award.name != 'Blue First' && award.name != 'Blue Compare' - if award.quality > 0 - if award.name != 'Blue Distinction Plus' - award.quality -= 1 - end - end - else - if award.quality < 50 - award.quality += 1 - if award.name == 'Blue Compare' - if award.expires_in < 11 - if award.quality < 50 - award.quality += 1 - end - end - if award.expires_in < 6 - if award.quality < 50 - award.quality += 1 - end - end - end - end - end - if award.name != 'Blue Distinction Plus' - award.expires_in -= 1 - end - if award.expires_in < 0 - if award.name != 'Blue First' - if award.name != 'Blue Compare' - if award.quality > 0 - if award.name != 'Blue Distinction Plus' - award.quality -= 1 - end - end - else - award.quality = award.quality - award.quality - end - else - if award.quality < 50 - award.quality += 1 - end - end - end - end -end diff --git a/update_quality_spec.rb b/update_quality_spec.rb index 973940d..9b79156 100644 --- a/update_quality_spec.rb +++ b/update_quality_spec.rb @@ -1,237 +1,322 @@ require 'rspec' -require 'update_quality' +#require 'update_quality' +require 'reward_modifier' -describe '#update_quality' do +RSpec.describe RewardModifier do - context 'Given a single award' do - let(:initial_expires_in) { 5 } - let(:initial_quality) { 10 } - let(:award) { Award.new(name, initial_expires_in, initial_quality) } - - context 'when quality is updated' do - before do - update_quality([award]) - end - - context 'given a normal award' do - let(:name) { 'NORMAL ITEM' } + describe '#update_quality' do + context 'Given a single award' do + let(:initial_expires_in) { 5 } + let(:initial_quality) { 10 } + let(:award) { Award.new(name, initial_expires_in, initial_quality) } + let(:subject) { RewardModifier.new([award]) } + context 'when quality is updated' do before do - # Verify that this is always true in the current context - expect(award.expires_in).to eq(initial_expires_in-1) + subject.update_quality end - context 'before expiration date' do - specify { expect(award.quality).to eq(initial_quality-1) } - end + context 'given a normal award' do + let(:name) { 'NORMAL ITEM' } - context 'on expiration date' do - let(:initial_expires_in) { 0 } - specify { expect(award.quality).to eq(initial_quality-2) } - end + before do + # Verify that this is always true in the current context + expect(award.expires_in).to eq(initial_expires_in-1) + end - context 'after expiration date' do - let(:initial_expires_in) { -10 } - specify { expect(award.quality).to eq(initial_quality-2) } - end + context 'before expiration date' do + specify { expect(award.quality).to eq(initial_quality-1) } + end - context 'of zero quality' do - let(:initial_quality) { 0 } - specify { expect(award.quality).to eq(0) } - end - end + context 'on expiration date' do + let(:initial_expires_in) { 0 } + specify { expect(award.quality).to eq(initial_quality-2) } + end - context 'given Blue First' do - let(:name) { 'Blue First' } + context 'after expiration date' do + let(:initial_expires_in) { -10 } + specify { expect(award.quality).to eq(initial_quality-2) } + end - before do - # Verify that this is always true in the current context - award.expires_in.should == initial_expires_in-1 + context 'of zero quality' do + let(:initial_quality) { 0 } + specify { expect(award.quality).to eq(0) } + end end - context 'before expiration date' do - specify { expect(award.quality).to eq(initial_quality+1) } + context 'given Blue First' do + let(:name) { 'Blue First' } - context 'with max quality' do - let(:initial_quality) { 50 } - specify { expect(award.quality).to eq(initial_quality) } + before do + # Verify that this is always true in the current context + award.expires_in.should == initial_expires_in-1 end - end - context 'on expiration date' do - let(:initial_expires_in) { 0 } - specify { expect(award.quality).to eq(initial_quality+2) } + context 'before expiration date' do + specify { expect(award.quality).to eq(initial_quality+1) } - context 'near max quality' do - let(:initial_quality) { 49 } - specify { expect(award.quality).to eq(50) } + context 'with max quality' do + let(:initial_quality) { 50 } + specify { expect(award.quality).to eq(initial_quality) } + end end - context 'with max quality' do - let(:initial_quality) { 50 } - specify { expect(award.quality).to eq(initial_quality) } + context 'on expiration date' do + let(:initial_expires_in) { 0 } + specify { expect(award.quality).to eq(initial_quality+2) } + + context 'near max quality' do + let(:initial_quality) { 49 } + specify { expect(award.quality).to eq(50) } + end + + context 'with max quality' do + let(:initial_quality) { 50 } + specify { expect(award.quality).to eq(initial_quality) } + end end - end - context 'after expiration date' do - let(:initial_expires_in) { -10 } - specify { expect(award.quality).to eq(initial_quality+2) } + context 'after expiration date' do + let(:initial_expires_in) { -10 } + specify { expect(award.quality).to eq(initial_quality+2) } - context 'with max quality' do - let(:initial_quality) { 50 } - specify { expect(award.quality).to eq(initial_quality) } + context 'with max quality' do + let(:initial_quality) { 50 } + specify { expect(award.quality).to eq(initial_quality) } + end end end - end - context 'given Blue Distinction Plus' do - let(:initial_quality) { 80 } - let(:name) { 'Blue Distinction Plus' } + context 'given Blue Distinction Plus' do + let(:initial_quality) { 80 } + let(:name) { 'Blue Distinction Plus' } - before do - # Verify that this is always true in the current context - award.expires_in.should == initial_expires_in - end + before do + # Verify that this is always true in the current context + award.expires_in.should == initial_expires_in + end - context 'before expiration date' do - specify { expect(award.quality).to eq(initial_quality) } - end + context 'before expiration date' do + specify { expect(award.quality).to eq(initial_quality) } + end - context 'on expiration date' do - let(:initial_expires_in) { 0 } - specify { expect(award.quality).to eq(initial_quality) } - end + context 'on expiration date' do + let(:initial_expires_in) { 0 } + specify { expect(award.quality).to eq(initial_quality) } + end - context 'after expiration date' do - let(:initial_expires_in) { -10 } - specify { expect(award.quality).to eq(initial_quality) } + context 'after expiration date' do + let(:initial_expires_in) { -10 } + specify { expect(award.quality).to eq(initial_quality) } + end end - end - context 'given Blue Compare' do - let(:name) { 'Blue Compare' } + context 'given Blue Compare' do + let(:name) { 'Blue Compare' } - before do - # Verify that this is always true in the current context - award.expires_in.should == initial_expires_in-1 - end + before do + # Verify that this is always true in the current context + award.expires_in.should == initial_expires_in-1 + end - context 'long before expiration date' do - let(:initial_expires_in) { 11 } - specify { expect(award.quality).to eq(initial_quality+1) } + context 'long before expiration date' do + let(:initial_expires_in) { 11 } + specify { expect(award.quality).to eq(initial_quality+1) } - context 'at max quality' do - let(:initial_quality) { 50 } + context 'at max quality' do + let(:initial_quality) { 50 } + end end - end - context 'medium close to expiration date (upper bound)' do - let(:initial_expires_in) { 10 } - specify { expect(award.quality).to eq(initial_quality+2) } + context 'medium close to expiration date (upper bound)' do + let(:initial_expires_in) { 10 } + specify { expect(award.quality).to eq(initial_quality+2) } - context 'at max quality' do - let(:initial_quality) { 50 } - specify { expect(award.quality).to eq(initial_quality) } + context 'at max quality' do + let(:initial_quality) { 50 } + specify { expect(award.quality).to eq(initial_quality) } + end end - end - context 'medium close to expiration date (lower bound)' do - let(:initial_expires_in) { 6 } - specify { expect(award.quality).to eq(initial_quality+2) } + context 'medium close to expiration date (lower bound)' do + let(:initial_expires_in) { 6 } + specify { expect(award.quality).to eq(initial_quality+2) } - context 'at max quality' do - let(:initial_quality) { 50 } - specify { expect(award.quality).to eq(initial_quality) } + context 'at max quality' do + let(:initial_quality) { 50 } + specify { expect(award.quality).to eq(initial_quality) } + end end - end - context 'very close to expiration date (upper bound)' do - let(:initial_expires_in) { 5 } - specify { expect(award.quality).to eq(initial_quality+3) } + context 'very close to expiration date (upper bound)' do + let(:initial_expires_in) { 5 } + specify { expect(award.quality).to eq(initial_quality+3) } - context 'at max quality' do - let(:initial_quality) { 50 } - specify { expect(award.quality).to eq(initial_quality) } + context 'at max quality' do + let(:initial_quality) { 50 } + specify { expect(award.quality).to eq(initial_quality) } + end end - end - context 'very close to expiration date (lower bound)' do - let(:initial_expires_in) { 1 } - specify { expect(award.quality).to eq(initial_quality+3) } + context 'very close to expiration date (lower bound)' do + let(:initial_expires_in) { 1 } + specify { expect(award.quality).to eq(initial_quality+3) } - context 'at max quality' do - let(:initial_quality) { 50 } - specify { expect(award.quality).to eq(initial_quality) } + context 'at max quality' do + let(:initial_quality) { 50 } + specify { expect(award.quality).to eq(initial_quality) } + end end - end - context 'on expiration date' do - let(:initial_expires_in) { 0 } - specify { expect(award.quality).to eq(0) } - end + context 'on expiration date' do + let(:initial_expires_in) { 0 } + specify { expect(award.quality).to eq(0) } + end - context 'after expiration date' do - let(:initial_expires_in) { -10 } - specify { expect(award.quality).to eq(0) } + context 'after expiration date' do + let(:initial_expires_in) { -10 } + specify { expect(award.quality).to eq(0) } + end end - end - context 'given a Blue Star award' do - before { pending } - let(:name) { 'Blue Star' } - before { award.expires_in.should == initial_expires_in-1 } + context 'given a Blue Star award' do - context 'before the expiration date' do - let(:initial_expires_in) { 5 } - specify { expect(award.quality).to eq(initial_quality-2) } + let(:name) { 'Blue Star' } + before { award.expires_in.should == initial_expires_in-1 } - context 'at zero quality' do - let(:initial_quality) { 0 } - specify { expect(award.quality).to eq(initial_quality) } + context 'before the expiration date' do + let(:initial_expires_in) { 5 } + specify { expect(award.quality).to eq(initial_quality-2) } + + context 'at zero quality' do + let(:initial_quality) { 0 } + specify { expect(award.quality).to eq(initial_quality) } + end end - end - context 'on expiration date' do - let(:initial_expires_in) { 0 } - specify { expect(award.quality).to eq(initial_quality-4) } + context 'on expiration date' do + let(:initial_expires_in) { 0 } + specify { expect(award.quality).to eq(initial_quality-4) } - context 'at zero quality' do - let(:initial_quality) { 0 } - specify { expect(award.quality).to eq(initial_quality) } + context 'at zero quality' do + let(:initial_quality) { 0 } + specify { expect(award.quality).to eq(initial_quality) } + end end - end - context 'after expiration date' do - let(:initial_expires_in) { -10 } - specify { expect(award.quality).to eq(initial_quality-4) } + context 'after expiration date' do + let(:initial_expires_in) { -10 } + specify { expect(award.quality).to eq(initial_quality-4) } - context 'at zero quality' do - let(:initial_quality) { 0 } - specify { expect(award.quality).to eq(initial_quality) } + context 'at zero quality' do + let(:initial_quality) { 0 } + specify { expect(award.quality).to eq(initial_quality) } + end end end end end + + context 'Given several award' do + let(:awards) { + [ + Award.new('NORMAL ITEM', 5, 10), + Award.new('Blue First', 3, 10), + ] + } + + let(:subject) { RewardModifier.new(awards) } + + context 'when quality is updated' do + before do + subject.update_quality + end + + specify { expect(awards[0].quality).to eq(9) } + specify { expect(awards[0].expires_in).to eq(4) } + + specify { expect(awards[1].quality).to eq(11) } + specify { expect(awards[1].expires_in).to eq(2) } + end + end end - context 'Given several award' do - let(:awards) { + describe '#calculate_expired_quality' do + let(:awards) do [ - Award.new('NORMAL ITEM', 5, 10), - Award.new('Blue First', 3, 10), + Award.new('Blue First', 10, 20), + Award.new('Blue Distinction Plus', 0, 80), + Award.new('Blue Star', -1, 15), + Award.new('Other Award', 8, 30) ] - } + end - context 'when quality is updated' do - before do - update_quality(awards) - end + it 'calculates the quality of awards that have expired' do + reward_modifier = RewardModifier.new(awards) + reward_modifier.calculate_expired_quality(awards[0]) # Blue First + reward_modifier.calculate_expired_quality(awards[1]) # Blue Distinction Plus + reward_modifier.calculate_expired_quality(awards[2]) # Blue Star + reward_modifier.calculate_expired_quality(awards[3]) # Other Award + + expect(awards[0].quality).to eq(21) + expect(awards[1].quality).to eq(80) + expect(awards[2].quality).to eq(13) + expect(awards[3].quality).to eq(29) + end + end + + describe '#modify_expiration_date' do + let(:awards) do + [ + Award.new('Blue First', 10, 20), + Award.new('Blue Compare', 5, 7), + Award.new('Blue Distinction Plus', 0, 80), + Award.new('Blue Star', 2, 15), + Award.new('Other Award', 8, 30) + ] + end + + it 'decreases the expiration date by 1 for non-Blue Distinction Plus awards' do + reward_modifier = RewardModifier.new(awards) + reward_modifier.modify_expiration_date(awards[0]) # Blue First + reward_modifier.modify_expiration_date(awards[1]) # Blue Compare + reward_modifier.modify_expiration_date(awards[3]) # Blue Star - specify { expect(awards[0].quality).to eq(9) } - specify { expect(awards[0].expires_in).to eq(4) } + expect(awards[0].expires_in).to eq(9) + expect(awards[1].expires_in).to eq(4) + expect(awards[3].expires_in).to eq(1) + end + + it 'does not modify the expiration date for Blue Distinction Plus awards' do + reward_modifier = RewardModifier.new(awards) + reward_modifier.modify_expiration_date(awards[2]) # Blue Distinction Plus + + expect(awards[2].expires_in).to eq(0) + end + end + + describe '#expiration_passed?' do + let(:awards) do + [ + Award.new('Blue First', 10, 20), + Award.new('Blue Compare', 5, 7), + Award.new('Blue Distinction Plus', 0, 80), + Award.new('Blue Star', -1, 15), + Award.new('Other Award', 8, 30) + ] + end + + it 'returns true if the expiration has passed' do + reward_modifier = RewardModifier.new(awards) + expect(reward_modifier.expiration_passed?(awards[3])).to eq true + end - specify { expect(awards[1].quality).to eq(11) } - specify { expect(awards[1].expires_in).to eq(2) } + it 'returns false if the expiration has not passed' do + reward_modifier = RewardModifier.new(awards) + expect(reward_modifier.expiration_passed?(awards[2])).to eq false + expect(reward_modifier.expiration_passed?(awards[0])).to eq false + expect(reward_modifier.expiration_passed?(awards[1])).to eq false + expect(reward_modifier.expiration_passed?(awards[4])).to eq false end end end