Skip to content

Instantly share code, notes, and snippets.

@emhoracek
Created October 21, 2017 16:35
Show Gist options
  • Save emhoracek/c76e5765f9dd40693a6065332fa94834 to your computer and use it in GitHub Desktop.
Save emhoracek/c76e5765f9dd40693a6065332fa94834 to your computer and use it in GitHub Desktop.
discounts
class Order < Struct.new(:line_items, :discount_name)
def discount
DiscountDatabase.find_by_name(discount_name)
end
def discounted_line_item_prices
line_items.map do |li|
li.discounted_total(discount)
end
end
def total
discounted_line_item_prices.reduce(:+)
end
def display_total
"Total ${}"
end
def display_line_items
line_items.map { |li| li.display_discounted(discount) }.join("\n")
end
def display
"#{display_line_items}\n---\nTotal #{total.to_money}"
end
end
class Product < Struct.new(:title, :price)
def self.find_by_id(id)
product_database[id]
end
end
class LineItem < Struct.new(:product_id, :quantity)
def discounted_total (discount)
if discount
total - total * (discount.eligible_percent(product_id).to_f / 100)
else
total
end
end
def total
product.price * quantity
end
def product
ProductDatabase.find_by_id(product_id)
end
def display_discount(discount)
if discounted_total(discount) != total
"(Original Price #{product.price.to_money}) "
else
""
end
end
def display_copies
if quantity == 1
"1 copy"
else
"#{quantity } copies"
end
end
def display_discounted(discount)
"#{discounted_total(discount).to_money} #{display_discount(discount)}for #{display_copies} of \"#{product.title}\""
end
end
class Discount < Struct.new(:name, :percent, :type, :products)
def eligible_percent (product_id)
if type == :all or products.member? product_id
percent
else
0
end
end
end
class DiscountDatabase
def self.database
{
1 => Discount.new(:WELCOME, 50, :all, nil), # this discount gives 50% off any product
2 => Discount.new(:JAC75, 75, :product_list, [1]) # this discount gives a 75% discount off of "Black Jacobins"
}
end
def self.find_by_name(name)
row = database.select { |id, discount| discount.name == name }
row.values[0] # so bad
end
end
class ProductDatabase
def self.database
{
1 => Product.new("Black Jacobins", 20_00),
2 => Product.new("Freedom Is a Constant Struggle", 15_00)
}
end
def self.find_by_id(id)
database[id]
end
end
class OrderDatabase
def self.database
{
1 => Order.new([LineItem.new(1, 1)], nil),
2 => Order.new([LineItem.new(1, 1)], :WELCOME)
}
end
def self.find_by_id(id)
database[id]
end
end
class CartApplication
def self.display_cart(cart)
"Your cart:\n\n" + cart.display()
end
end
class Numeric
def to_money
sprintf("$%.2f", (self/100))
end
end
require './cart_app'
RSpec.describe Order, "#total" do
it "should total stuff" do
cart = Order.new([LineItem.new(1, 1)], nil)
expect(cart.total).to eq 20_00
end
it "should include discounts" do
cart = Order.new([ LineItem.new(1, 1),
LineItem.new(2, 1)], :WELCOME )
expect(cart.total).to eq 17_50
end
end
RSpec.describe Order, "#discount" do
it "should total stuff" do
cart = Order.new([LineItem.new(1, 1)], nil)
expect(cart.discount).to eq nil
end
it "should include discounts" do
cart = Order.new([ LineItem.new(1, 1),
LineItem.new(2, 1)], :WELCOME )
expect(cart.discount.name).to eq :WELCOME
end
end
RSpec.describe Order, "#discounted_line_items" do
it "should total stuff" do
cart = Order.new([LineItem.new(1, 1)], nil)
expect(cart.discounted_line_item_prices).to eq [20_00]
end
it "should include discounts" do
cart = Order.new([ LineItem.new(1, 1),
LineItem.new(2, 1)], :WELCOME )
expect(cart.discounted_line_item_prices).to eq [10_00, 7_50]
end
it "should include discounts" do
cart = Order.new([ LineItem.new(1, 1),
LineItem.new(2, 1)], :JAC75)
expect(cart.discounted_line_item_prices).to eq [5_00, 15_00]
end
end
RSpec.describe Order, "#display" do
it "should display an order" do
cart = Order.new([ LineItem.new(1, 1),
LineItem.new(2, 1) ], :WELCOME)
expected_display =
"""$10.00 (Original Price $20.00) for 1 copy of \"Black Jacobins\"
$7.50 (Original Price $15.00) for 1 copy of \"Freedom Is a Constant Struggle\"
---
Total $17.50"""
expect(cart.display).to eq expected_display
end
end
RSpec.describe LineItem, "#total" do
it "should total the line item" do
line_item = LineItem.new(1, 1)
expect(line_item.total).to eq 20_00
end
end
RSpec.describe LineItem, "#discounted_total" do
it "should total the line item" do
line_item = LineItem.new(1, 1)
discount = DiscountDatabase.find_by_name(:WELCOME)
expect(line_item.discounted_total(discount)).to eq 10_00
end
it "should total the line item" do
line_item = LineItem.new(1, 1)
expect(line_item.discounted_total(nil)).to eq 20_00
end
end
RSpec.describe LineItem, "#display" do
it "should display the line item" do
line_item = LineItem.new(1, 1)
discount = DiscountDatabase.find_by_name(:WELCOME)
expected_display =
"$10.00 (Original Price $20.00) for 1 copy of \"Black Jacobins\""
expect(line_item.display_discounted(discount)).to eq expected_display
end
end
RSpec.describe ProductDatabase, "#find_product_by_id" do
it "should find the correct product" do
product = ProductDatabase.find_by_id(1)
expect(product.title).to eq "Black Jacobins"
product = ProductDatabase.find_by_id(2)
expect(product.title).to eq "Freedom Is a Constant Struggle"
end
end
RSpec.describe DiscountDatabase, "#find_discount_by_name" do
it "should find the correct discount" do
discount = DiscountDatabase.find_by_name(:WELCOME)
expect(discount.percent).to eq 50
discount = DiscountDatabase.find_by_name(:JAC75)
expect(discount.percent).to eq 75
end
end
RSpec.describe Discount, "#eligible_percent" do
context "An :all-type discount" do
it "should give the same percent for all product ids" do
discount = DiscountDatabase.find_by_name(:WELCOME)
expect(discount.eligible_percent(1)).to eq 50
expect(discount.eligible_percent(2)).to eq 50
end
end
context "A product specific discount" do
it "should give the correct percent for that product" do
discount = DiscountDatabase.find_by_name(:JAC75)
expect(discount.eligible_percent(1)).to eq 75
end
it "should give 0 percent for all other products" do
discount = DiscountDatabase.find_by_name(:JAC75)
expect(discount.eligible_percent(2)).to eq 0
end
end
end
RSpec.describe CartApplication, "#display_cart" do
it "should display a cart with an :all discount" do
cart = Order.new([ LineItem.new(1, 1),
LineItem.new(2, 1) ], :WELCOME)
expected_display =
"""Your cart:
$10.00 (Original Price $20.00) for 1 copy of \"Black Jacobins\"
$7.50 (Original Price $15.00) for 1 copy of \"Freedom Is a Constant Struggle\"
---
Total $17.50"""
expect(CartApplication.display_cart(cart)).to eq expected_display
end
it "should display a cart with a product discount" do
cart = Order.new([ LineItem.new(1, 1),
LineItem.new(2, 1)] , :JAC75)
CartApplication.display_cart(cart)
expected_display =
"""Your cart:
$5.00 (Original Price $20.00) for 1 copy of \"Black Jacobins\"
$15.00 for 1 copy of \"Freedom Is a Constant Struggle\"
---
Total $20.00"""
expect(CartApplication.display_cart(cart)).to eq expected_display
end
it "should display a cart with no discount" do
cart = Order.new([ LineItem.new(1, 1),
LineItem.new(2, 1)] , nil)
CartApplication.display_cart(cart)
expected_display =
"""Your cart:
$20.00 for 1 copy of \"Black Jacobins\"
$15.00 for 1 copy of \"Freedom Is a Constant Struggle\"
---
Total $35.00"""
expect(CartApplication.display_cart(cart)).to eq expected_display
end
it "should display a cart with multiples of a product" do
cart = Order.new([ LineItem.new(1, 3),
LineItem.new(2, 5)] , nil)
CartApplication.display_cart(cart)
expected_display =
"""Your cart:
$60.00 for 3 copies of \"Black Jacobins\"
$75.00 for 5 copies of \"Freedom Is a Constant Struggle\"
---
Total $135.00"""
expect(CartApplication.display_cart(cart)).to eq expected_display
end
it "should display a cart with multiples of a product and discount" do
cart = Order.new([ LineItem.new(1, 3),
LineItem.new(2, 5)] , :WELCOME)
CartApplication.display_cart(cart)
expected_display =
"""Your cart:
$30.00 (Original Price $20.00) for 3 copies of \"Black Jacobins\"
$37.50 (Original Price $15.00) for 5 copies of \"Freedom Is a Constant Struggle\"
---
Total $67.50"""
expect(CartApplication.display_cart(cart)).to eq expected_display
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment