Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jaren Garman #3

Open
wants to merge 59 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
7aba1c0
test: Add spec_helper
JarenGarman Jan 15, 2025
bd1a0cf
chore: Add .gitignore
JarenGarman Jan 15, 2025
eb05b25
test: Add item_spec
JarenGarman Jan 15, 2025
0e399b2
feat: Add Item class
JarenGarman Jan 15, 2025
c54ed69
test: Add test for name
JarenGarman Jan 15, 2025
6ba85ef
feat: Add name attribute
JarenGarman Jan 15, 2025
e2648e6
test: Add test for price
JarenGarman Jan 15, 2025
a802db4
test: Fix test for price
JarenGarman Jan 15, 2025
167476a
feat: Add price attribute
JarenGarman Jan 15, 2025
b6bd642
test: Refactor to remove redundant item
JarenGarman Jan 15, 2025
6e4e56b
test: Add food_truck_spec
JarenGarman Jan 15, 2025
d640dc6
feat: Add FoodTruck class
JarenGarman Jan 15, 2025
c18a8a1
test: Add test for name
JarenGarman Jan 15, 2025
c3acacd
feat: Add name attribute
JarenGarman Jan 15, 2025
9672550
test: Add test for empty inventory
JarenGarman Jan 15, 2025
d16982d
feat: Add empty inventory
JarenGarman Jan 15, 2025
4d35b4d
test: Add test for 0 stock
JarenGarman Jan 15, 2025
e685874
feat: Add check_stock method
JarenGarman Jan 15, 2025
ef7591b
test: Add tests for stock
JarenGarman Jan 15, 2025
ac954cd
test: Fix test for stock
JarenGarman Jan 15, 2025
ffd0301
feat: Add stock method
JarenGarman Jan 15, 2025
9680923
test: Add test for additional stock
JarenGarman Jan 15, 2025
cf18a7e
Merge pull request #1 from JarenGarman/feature/item
JarenGarman Jan 15, 2025
f76c94c
test: Add event_spec
JarenGarman Jan 15, 2025
730641a
feat: Add Event class
JarenGarman Jan 15, 2025
e3fb7c4
test: Add test for name
JarenGarman Jan 15, 2025
d5dd092
feat: Add name attribute
JarenGarman Jan 15, 2025
a2f83cf
test: Add test for food_trucks
JarenGarman Jan 15, 2025
84c824a
feat: Add food_trucks attribute
JarenGarman Jan 15, 2025
0b3455e
test: Add test for add_food_truck
JarenGarman Jan 15, 2025
966cbe3
feat: Add add_food_truck method
JarenGarman Jan 15, 2025
3de5fe0
test: Add test for food_truck_names
JarenGarman Jan 15, 2025
e317c21
feat: Add food_truck_names method
JarenGarman Jan 15, 2025
2dbef14
test: Add test for food_trucks_that_sell
JarenGarman Jan 15, 2025
92d053b
feat: Add food_trucks_that_sell method
JarenGarman Jan 15, 2025
769c3f9
test: Add test for potential_revenue
JarenGarman Jan 15, 2025
785551d
feat: Add potential_revenue method
JarenGarman Jan 15, 2025
1ca463e
Merge pull request #2 from JarenGarman/feature/event
JarenGarman Jan 15, 2025
058cca2
test: Add test for sorted_item_list
JarenGarman Jan 15, 2025
1febda1
test: Fix test for sorted_item_list
JarenGarman Jan 15, 2025
cccd493
feat: Add sorted_item_list method
JarenGarman Jan 15, 2025
014eeb5
test: Add test for total_inventory
JarenGarman Jan 15, 2025
446b4c0
feat: Add total_inventory
JarenGarman Jan 15, 2025
30d5d3e
test: Add test for overstocked_items
JarenGarman Jan 15, 2025
c135104
feat: Add overstocked_items method
JarenGarman Jan 15, 2025
f573d7f
Merge pull request #3 from JarenGarman/feature/items_sold_at_event
JarenGarman Jan 15, 2025
ffc0722
test: Add test for date
JarenGarman Jan 15, 2025
9c8ab99
feat: Add date
JarenGarman Jan 15, 2025
ea138f4
test: Add tests for sell
JarenGarman Jan 15, 2025
29f798f
feat: Add basic sell method
JarenGarman Jan 15, 2025
9af4c09
test: Add test for sell
JarenGarman Jan 15, 2025
d1a82d3
feat: Add sell method to FoodTruck
JarenGarman Jan 15, 2025
29c6107
test: Fix test for sell
JarenGarman Jan 15, 2025
5ab6b77
feat: Complete sell method
JarenGarman Jan 15, 2025
78c443c
Merge pull request #4 from JarenGarman/feature/date_and_sell
JarenGarman Jan 15, 2025
7aaeb33
docs: Formatting
JarenGarman Jan 15, 2025
84a88ec
refactor: Use each_with_object
JarenGarman Jan 15, 2025
cb2415d
refactor: Use sum
JarenGarman Jan 15, 2025
a67f3ba
refactor: Remove .nil? call
JarenGarman Jan 17, 2025
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
coverage
23 changes: 11 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,17 +170,16 @@ pry(main)> food_truck3.potential_revenue

## Iteration 3 - Items sold at the Event

Use TDD to update the `Event` class so that it adds the following functionality. You need to complete at least 2 of the 3 methods in Iteration 3 to pass, as well as all of Iteration 1 and 2.

Use TDD to update the `Event` class so that it adds the following functionality. You need to complete at least 2 of the 3 methods in Iteration 3 to pass, as well as all of Iteration 1 and 2.

1. An `Event` can return a list of *names* of all items the `FoodTrucks` have in stock, sorted alphabetically. This list should not include any duplicate items.
1. An `Event` can return a hash of total inventory that reports the available inventory of all items sold at the event. Specifically, it should include:
- All items available for sale, and each item should identify the total inventory/quantity for that item, as well as a list of `FoodTruck`s that sell that item.
* All items available for sale, and each item should identify the total inventory/quantity for that item, as well as a list of `FoodTruck`s that sell that item.
1. Return a list of overstocked Items for an `Event`. An item is overstocked if it is sold by more than 1 food truck AND the total quantity is greater than 50.

| Method Name | Return Value (type)
| ------------------------- | ---------------------------
| `sorted_item_list` | Alphabetically sorted `Array` of all `FoodTruck` item <u>names</u> (no duplicates!). Array of Strings.
| `sorted_item_list` | Alphabetically sorted `Array` of all `FoodTruck` item names (no duplicates!). Array of Strings.
| `total_inventory` | `Hash` with `Item`s as keys and a sub-hash as the value. The sub-hash should have `quantity` and `food_trucks` keys.(See example below)
| `overstocked_items` | `Array` of `Item` objects

Expand Down Expand Up @@ -211,22 +210,22 @@ Use TDD to update the `Event` class so that it adds the following functionality:
1. Event #date
2. Event #sell

| Method Name | Return Value |
| ----------- | ------------ |
| `date` | string ex. `"24/02/2023"` (see below) |
| `sell(item, quantity)` | boolean (see below) |
| Method Name | Return Value
| ----------- | ------------
| `date` | string ex. `"24/02/2023"` (see below)
| `sell(item, quantity)` | boolean (see below)

**#date**
### #date

You will need to add `require "date"` to the top of your `Event` class.

An `Event` has a start date that is returned in the format of `"dd/mm/yyyy"`. The addition of a `date` to the `Event` should NOT break any previous tests. We want you to test this with a date that is IN THE PAST. In order to test the date method in a way that will work today, tomorrow and on any date in the future, you will need to use a [stub](https://backend.turing.edu/module1/lessons/mocks_stubs#:~:text=full%20Paint%20objects.-,Stubs,-In%20our%20next) 🙂.

**#sell**
### #sell

An `Event` can sell an item of a given quantity. There are two possible outcomes for selling an item:

- If the `Event` does not have enough of the item in stock to satisfy the given quantity, this method should return `false`.
- If the `Event` has enough of the item in stock to satisfy the given quantity, this method should return `true`. Additionally, this method should reduce the stock of the `FoodTruck`. It should look through the `FoodTruck`s in the order they were added and sell the item from the first `FoodTruck` with that item in stock. If that `FoodTruck` does not have enough stock to satisfy the given quantity, the `FoodTruck`'s entire stock of that item will be depleted, and the remaining quantity will be sold from the next `FoodTruck` with that item in stock. It will follow this pattern until the entire quantity requested has been sold.
* If the `Event` does not have enough of the item in stock to satisfy the given quantity, this method should return `false`.
* If the `Event` has enough of the item in stock to satisfy the given quantity, this method should return `true`. Additionally, this method should reduce the stock of the `FoodTruck`. It should look through the `FoodTruck`s in the order they were added and sell the item from the first `FoodTruck` with that item in stock. If that `FoodTruck` does not have enough stock to satisfy the given quantity, the `FoodTruck`'s entire stock of that item will be depleted, and the remaining quantity will be sold from the next `FoodTruck` with that item in stock. It will follow this pattern until the entire quantity requested has been sold.

For example, suppose food_truck1 has 35 `peach pies` and food_truck3 has 65 `peach pies`, and food_truck1 was added to the event first. If the method `sell(<ItemXXX, @name = 'Peach Pie'...>, 40)` is called, the method should return `true`, food_truck1's new stock of `peach pies` should be 0, and food_truck3's new stock of `peach pies` should be 60.
74 changes: 74 additions & 0 deletions lib/event.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# frozen_string_literal: true

require 'date'

# Create an event to host food trucks
class Event
attr_reader :name, :food_trucks, :date

def initialize(name, date = Date.today.strftime('%d/%m/%Y'))
@name = name
@food_trucks = []
@date = date
end

def add_food_truck(food_truck)
@food_trucks << food_truck
end

def food_truck_names
@food_trucks.map do |food_truck| # rubocop:disable Style/SymbolProc
food_truck.name
end
end

def food_trucks_that_sell(item)
@food_trucks.find_all do |food_truck|
food_truck.inventory[item]
end
end

def sorted_item_list
@food_trucks.map do |food_truck|
food_truck.inventory.keys.map do |item| # rubocop:disable Style/SymbolProc
item.name
end
end.flatten.uniq.sort
end

def total_inventory # rubocop:disable Metrics/MethodLength
@food_trucks.each_with_object({}) do |food_truck, total_inventory|
food_truck.inventory.each do |item, amount|
next if amount.zero?

if total_inventory[item]
total_inventory[item][:quantity] += amount
total_inventory[item][:food_trucks] << food_truck
else
total_inventory[item] = { quantity: amount, food_trucks: [food_truck] }
end
end
end
end

def overstocked_items
total_inventory.select do |_item, item_hash|
item_hash[:quantity] > 50 && item_hash[:food_trucks].length > 1
end.keys
end

def sell(item, amount) # rubocop:disable Metrics/MethodLength
return false if total_inventory[item][:quantity] < amount

food_trucks_that_sell(item).each do |food_truck|
if food_truck.check_stock(item) < amount
amount -= food_truck.check_stock(item)
food_truck.sell(item, food_truck.check_stock(item))
else
food_truck.sell(item, amount)
break
end
end
true
end
end
35 changes: 35 additions & 0 deletions lib/food_truck.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

# Create a food truck to hold items
class FoodTruck
attr_reader :name, :inventory

def initialize(name)
@name = name
@inventory = {}
end

def check_stock(item)
return 0 unless @inventory[item]

@inventory[item]
end

def stock(item, amount)
@inventory[item] = if inventory[item]
inventory[item] + amount
else
amount
end
end

def potential_revenue
@inventory.sum do |item, amount|
item.price * amount
end
end

def sell(item, amount)
@inventory[item] -= amount
end
end
11 changes: 11 additions & 0 deletions lib/item.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

# Create an item to stock on the food truck
class Item
attr_reader :name, :price

def initialize(item_params)
@name = item_params[:name]
@price = item_params[:price].delete_prefix('$').to_f
end
end
Empty file removed spec/.gitkeep
Empty file.
142 changes: 142 additions & 0 deletions spec/event_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# frozen_string_literal: true

require_relative 'spec_helper'

RSpec.describe Event do
subject(:event) { described_class.new('South Pearl Street Farmers Market') }

let(:first_food_truck) { FoodTruck.new('Rocky Mountain Pies') }
let(:second_food_truck) { FoodTruck.new('Ba-Nom-a-Nom') }
let(:third_food_truck) { FoodTruck.new('Palisade Peach Shack') }

describe '#initialize' do
it { is_expected.to be_instance_of described_class }

it 'has a name' do
expect(event.name).to eq('South Pearl Street Farmers Market')
end

it 'has no food trucks' do
expect(event.food_trucks).to eq([])
end

it 'has a date' do
allow(Date).to receive(:today).and_return(Date.new(1912, 6, 23))

expect(event.date).to eq('23/06/1912')
end
end

describe '#add_food_truck' do
before do
event.add_food_truck(first_food_truck)
event.add_food_truck(second_food_truck)
event.add_food_truck(third_food_truck)
end

it 'can add food trucks' do
expect(event.food_trucks).to eq([first_food_truck, second_food_truck, third_food_truck])
end

it 'can get food truck names' do
expect(event.food_truck_names).to eq(['Rocky Mountain Pies', 'Ba-Nom-a-Nom', 'Palisade Peach Shack'])
end
end

describe 'Methods with items' do # rubocop:disable RSpec/MultipleMemoizedHelpers
let(:first_item) { instance_double(Item, name: 'Peach Pie (Slice)', price: 3.75) }
let(:second_item) { instance_double(Item, name: 'Apple Pie (Slice)', price: 2.50) }
let(:third_item) { instance_double(Item, name: 'Peach-Raspberry Nice Cream', price: 5.30) }
let(:fourth_item) { instance_double(Item, name: 'Banana Nice Cream', price: 4.25) }

before do
event.add_food_truck(first_food_truck)
event.add_food_truck(second_food_truck)
event.add_food_truck(third_food_truck)
first_food_truck.stock(first_item, 35)
first_food_truck.stock(second_item, 7)
second_food_truck.stock(third_item, 25)
second_food_truck.stock(fourth_item, 50)
third_food_truck.stock(first_item, 65)
end

describe '#food_trucks_that_sell' do # rubocop:disable RSpec/MultipleMemoizedHelpers
it 'can find trucks that sell item' do
expect(event.food_trucks_that_sell(first_item)).to eq([first_food_truck, third_food_truck])
end
end

describe '#sorted_item_list' do # rubocop:disable RSpec/MultipleMemoizedHelpers
it 'can get sorted item list' do # rubocop:disable RSpec/ExampleLength
expect(event.sorted_item_list).to eq([
'Apple Pie (Slice)',
'Banana Nice Cream',
'Peach Pie (Slice)',
'Peach-Raspberry Nice Cream'
])
end
end

describe '#total_inventory' do # rubocop:disable RSpec/MultipleMemoizedHelpers
it 'can get total inventory' do # rubocop:disable RSpec/ExampleLength
expect(event.total_inventory).to eq({
first_item => {
quantity: 100,
food_trucks: [first_food_truck, third_food_truck]
},
second_item => {
quantity: 7,
food_trucks: [first_food_truck]
},
third_item => {
quantity: 25,
food_trucks: [second_food_truck]
},
fourth_item => {
quantity: 50,
food_trucks: [second_food_truck]
}
})
end
end

describe '#overstocked_items' do # rubocop:disable RSpec/MultipleMemoizedHelpers
it 'can get overstocked items' do
expect(event.overstocked_items).to eq([first_item])
end
end

describe '#sell' do # rubocop:disable RSpec/MultipleMemoizedHelpers
it 'cannot sell more items than it has' do
expect(event.sell(second_item, 8)).to be false
end

it 'can sell items' do
expect(event.sell(first_item, 40)).to be true
end

it 'can sell items from multiple trucks' do # rubocop:disable RSpec/ExampleLength
event.sell(first_item, 40)

expect(event.total_inventory).to eq({
first_item => {
quantity: 60,
food_trucks: [third_food_truck]
},
second_item => {
quantity: 7,
food_trucks: [first_food_truck]
},
third_item => {
quantity: 25,
food_trucks: [second_food_truck]
},
fourth_item => {
quantity: 50,
food_trucks: [second_food_truck]
}
})
end
end
end
end
64 changes: 64 additions & 0 deletions spec/food_truck_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# frozen_string_literal: true

require_relative 'spec_helper'

RSpec.describe FoodTruck do
subject(:food_truck) { described_class.new('Rocky Mountain Pies') }

let(:first_item) { instance_double(Item, name: 'Peach Pie (Slice)', price: 3.75) }
let(:second_item) { instance_double(Item, name: 'Apple Pie (Slice)', price: 2.50) }

describe '#initialize' do
it { is_expected.to be_instance_of described_class }

it 'has a name' do
expect(food_truck.name).to eq('Rocky Mountain Pies')
end

it 'has empty inventory' do
expect(food_truck.inventory).to eq({})
end

it 'has no stock' do
expect(food_truck.check_stock(first_item)).to eq(0)
end
end

describe '#stock' do
before do
food_truck.stock(first_item, 30)
end

it 'adds to inventory' do
expect(food_truck.inventory).to eq({ first_item => 30 })
end

it 'adds to stock' do
expect(food_truck.check_stock(first_item)).to eq(30)
end

it 'can add additional stock' do
food_truck.stock(first_item, 25)

expect(food_truck.check_stock(first_item)).to eq(55)
end
end

describe '#potential_revenue' do
it 'can find potential revenue' do
food_truck.stock(first_item, 35)
food_truck.stock(second_item, 7)

expect(food_truck.potential_revenue).to eq(148.75)
end
end

describe '#sell' do
it 'can sell items' do
food_truck.stock(first_item, 35)
food_truck.stock(second_item, 7)

expect(food_truck.sell(first_item, 35)).to eq(0)
end
end
end
Loading