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
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,11 @@ build-iPhoneSimulator/

# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc

#simplecov

coverage

#system

.DS_store

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

23 changes: 23 additions & 0 deletions lib/date_range.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require 'date'

module Hotel
class DateRange
attr_reader :check_in, :check_out, :nights_spent

def initialize(check_in, check_out)
raise ArgumentError, 'Invalid date range given.' unless check_out > check_in

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's helpful to include the invalid arguments when you raise an ArgumentError.

Suggested change
raise ArgumentError, 'Invalid date range given.' unless check_out > check_in
raise ArgumentError, "Invalid date range given. check_in: #{check_in} check_out: #{check_out}" unless check_out > check_in

@check_in = check_in
@check_out = check_out
@nights_spent = (@check_out - @check_in)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parenthesis here are unnecessary:

Suggested change
@nights_spent = (@check_out - @check_in)
@nights_spent = @check_out - @check_in

end

def to_id
return (@check_in.year.to_s + @check_in.mon.to_s + @check_in.mday.to_s)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need parenthesis around return values:

Suggested change
return (@check_in.year.to_s + @check_in.mon.to_s + @check_in.mday.to_s)
return @check_in.year.to_s + @check_in.mon.to_s + @check_in.mday.to_s

end

def overlap? (other_check_in, other_check_out)
return ((@check_in..@check_out).cover? (other_check_in)) || ((@check_in-1...@check_out).cover? (other_check_out))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clever use of cover?!

end

end
end
21 changes: 21 additions & 0 deletions lib/reservation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'date'

require_relative 'date_range'
require_relative 'room'

module Hotel
class Reservation
attr_reader :id, :dates, :occupancy

def initialize(type, dates, occupancy)
@id = type[0] + dates.to_id
@dates = dates
@occupancy = occupancy
end

def total_price
return @occupancy.sum { |occupancy| occupancy[:room].price * @dates.nights_spent }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect indentation:

Suggested change
return @occupancy.sum { |occupancy| occupancy[:room].price * @dates.nights_spent }
return @occupancy.sum { |occupancy| occupancy[:room].price * @dates.nights_spent }

end

end
end
67 changes: 67 additions & 0 deletions lib/reservation_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
require 'time'

require_relative 'room'
require_relative 'reservation'

module Hotel
class ReservationManager
attr_reader :rooms, :reservations

def initialize(room_count)
@rooms = generate_rooms(room_count)
@reservations = []
end

# Parameters:
# -type: symbol (:SINGLE, :BLOCK) that indicates type of reservation
# -range: DateRange object
# -occupancy: Hash or String
# Returns: newly created Reservation object
Comment on lines +15 to +19

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like that you documented your parameters but it would be more helpful if you mentioned more than just the type but also what they represent.

Really the only confusing bit here is occupancy. Everything else is pretty self explanatory or well explained (like type).

def create_reservation(type, range, occupancy)
raise ArgumentError.new("Invalid reservation type (given #{type}, must be :SINGLE or :BLOCK)") unless
type == :SINGLE || type == :BLOCK
Comment on lines +21 to +22

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great use of a guard clause with a good message!


occupancy = [{:room => @rooms.sample, :guest => occupancy}] if occupancy.class == String

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're going to check a type I'd recommend using kind_of? instead of class since that way you allow subclasses too:

Suggested change
occupancy = [{:room => @rooms.sample, :guest => occupancy}] if occupancy.class == String
occupancy = [{:room => @rooms.sample, :guest => occupancy}] if occupancy.kind_of? String


new_reservation = Reservation.new(type, range, occupancy)
@reservations << new_reservation
return new_reservation
end

# Parameters: Date object
# Returns: an Array of all Reservation instances that contain that date
def find_reservations_by_date(check_in, check_out)
by_date = @reservations.select { |reservation| reservation.dates.overlap?(check_in, check_out)}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works because of implicit return, but I don't think you meant to assign here (since you don't use the variable):

Suggested change
by_date = @reservations.select { |reservation| reservation.dates.overlap?(check_in, check_out)}
return @reservations.select { |reservation| reservation.dates.overlap?(check_in, check_out)}

end

def find_reservations_by_room(room)
by_room = @reservations.select { |reservation| reservation.occupancy.detect { |occupancy| occupancy[:room] == room }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

Suggested change
by_room = @reservations.select { |reservation| reservation.occupancy.detect { |occupancy| occupancy[:room] == room }}
return @reservations.select { |reservation| reservation.occupancy.detect { |occupancy| occupancy[:room] == room }}

end

def list_all_available(check_in, check_out)
reserved = find_reservations_by_date(check_in, check_out)

if reserved.length > 0
occupancies = reserved.map { |reservation| reservation.occupancy }
occupied_rooms = occupancies.flatten
occupied_rooms_ids = occupied_rooms.map { |occupancy| occupancy[:room].id }
end

rooms = @rooms.map { |room| room.id }

return (rooms - occupied_rooms_ids)

end

private

def generate_rooms(room_count)
rooms = []
room_count.times do |num|
rooms << Room.new(num+1)
end
return rooms
Comment on lines +59 to +63

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good use of a private method!

You can simplify this a little using a range and map though:

Suggested change
rooms = []
room_count.times do |num|
rooms << Room.new(num+1)
end
return rooms
return (1..room_count).map do |num|
Room.new(num)
end

end

end
end
12 changes: 12 additions & 0 deletions lib/room.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Hotel
class Room
attr_reader :id, :price, :type

def initialize(id)
@id = id.to_s
@price = 200
@type = "standard"
end
end

end
28 changes: 28 additions & 0 deletions test/date_range_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require_relative 'test_helper'

describe "DateRange class" do
describe "initialize" do

before do
@dates = Hotel::DateRange.new(Date.new, Date.new + 2)
end

it "creates an instance of DateRange" do
expect(@dates).must_be_kind_of Hotel::DateRange
end

it "raises an error for invalid dates" do
expect{(Hotel::DateRange.new(Date.new+2, Date.new))}.must_raise ArgumentError
end

it "returns accurate count of nights spent" do
expect(@dates.nights_spent).must_equal 2
end

it "returns accurate start Date" do
expect(@dates.check_in).must_be_kind_of Date
end

end

end
122 changes: 122 additions & 0 deletions test/reservation_manager_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
require_relative 'test_helper'

describe "ReservationManager class" do
before do
@reservation_manager = Hotel::ReservationManager.new(20)
end

describe "Initializer" do
it "is an instance of ReservationManager" do
expect(@reservation_manager).must_be_kind_of Hotel::ReservationManager
end

it "initializes correct number of rooms" do
expect(@reservation_manager.rooms.length).must_equal 20
end

it "populates valid room objects" do
expect(@reservation_manager.rooms[1]).must_be_kind_of Hotel::Room
end
Comment on lines +17 to +19

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A better check here would be to loop through all of the rooms with individual assertions:

Suggested change
it "populates valid room objects" do
expect(@reservation_manager.rooms[1]).must_be_kind_of Hotel::Room
end
it "populates valid room objects" do
@reservation_manager.rooms.each do |room|
expect(room).must_be_kind_of Hotel::Room
end
end


it "initializes with zero reservations" do
expect(@reservation_manager.reservations.length).must_equal 0
end

it "manages a hotel with 0 rooms" do
reservation_manager = Hotel::ReservationManager.new(0)
expect(reservation_manager.rooms.length).must_equal 0

end
end

describe "create reservation" do
before do
@room = Hotel::Room.new(100)
@occupancy = [{:room => @room, :guest => "Picchu"}]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this like the pokemon?

Pichu

@date = Hotel::DateRange.new(Date.new, Date.new + 2)
@reservation = @reservation_manager.create_reservation(:SINGLE, @date, @occupancy)
end

it "creates an instance of Reservation object" do
expect(@reservation).must_be_kind_of Hotel::Reservation
end

it "creates valid objects inside of a Reservation" do
expect(@reservation.occupancy).must_be_kind_of Array
end

end

describe "find_reservations_by_date" do
before do
date = Hotel::DateRange.new(Date.new, Date.new + 2)
@reservation_manager.create_reservation(:SINGLE, date, [{:room => Hotel::Room.new(100), :guest => "Elvy"}])
@reservation_manager.create_reservation(:SINGLE, date, [{:room => Hotel::Room.new(200), :guest => "Picchu"}] )
end

it "has accurate number of reservations" do
expect(@reservation_manager.reservations.length).must_equal 2
end

it "finds all reservations for a date" do
results = @reservation_manager.find_reservations_by_date(Date.new, Date.new + 3)
expect(results).must_be_kind_of Array
expect(results.length).must_equal 2
expect(results[0]).must_be_kind_of Hotel::Reservation
expect(results[0].occupancy).must_be_kind_of Array
expect(results[0].occupancy[0]).must_be_kind_of Hash
expect(results[0].occupancy[0][:room]).must_be_kind_of Hotel::Room
expect(results[0].occupancy[0][:room].id).must_equal "100"
expect(results[0].occupancy[0][:guest]).must_equal "Elvy"

end
end

describe "find_by_room" do
before do
@room = Hotel::Room.new(100)
@reservation_manager.create_reservation(
:SINGLE,
Hotel::DateRange.new(Date.new + 5, Date.new + 10),
[{:room => @room, :guest => "Picchu"}]
)
@reservation_manager.create_reservation(
:SINGLE,
Hotel::DateRange.new(Date.new + 11, Date.new + 15),
[{:room => @room, :guest => "Elvy"}]
)
@reservation_manager.create_reservation(
:SINGLE,
Hotel::DateRange.new(Date.new + 16, Date.new + 18),
[{:room => @room, :guest => "Tater Tot"}]
)
@reservation_manager.create_reservation(
:BLOCK,
Hotel::DateRange.new(Date.new + 19, Date.new + 23),
[{:room => Hotel::Room.new(300), :guest => "Peaches"},{:room => @room, :guest => "Tater Tot"},{:room => Hotel::Room.new(200), :guest => "Finn"}]
)
end

it "finds all reservations for a given room" do
results = @reservation_manager.find_reservations_by_room(@room)
expect(results).must_be_kind_of Array
expect(results.length).must_equal 4
expect(results.all? {|result| result.class == Hotel::Reservation}).must_equal true
end
end

describe "list_all_available" do
before do
date = Hotel::DateRange.new(Date.new, Date.new + 2)
@reservation_manager.create_reservation(:SINGLE, date, [{:room => @reservation_manager.rooms[0], :guest => "Elvy"}])
@reservation_manager.create_reservation(:SINGLE, date, [{:room => @reservation_manager.rooms[1], :guest => "Picchu"}] )
@reservation_manager.create_reservation(:SINGLE, date, [{:room => @reservation_manager.rooms[2], :guest => "Brom"}] )
end

it "returns list of available rooms for a given date range" do
results = @reservation_manager.list_all_available(Date.new, Date.new + 2)
expect(results.length).must_equal 17
end

end
end
34 changes: 34 additions & 0 deletions test/reservation_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require_relative 'test_helper'

describe "Reservation class" do
before do
@date = Hotel::DateRange.new(Date.new, Date.new + 2)
@occupancy = [{:room => Hotel::Room.new(12), :guest => "Picchu"}]
@reservation = Hotel::Reservation.new(:SINGLE, @date, @occupancy)
end

describe "initializer" do

it "creates a valid Reservation" do
expect(@reservation.id).must_be_kind_of String
expect(@reservation.dates).must_be_kind_of Hotel::DateRange
end

end

describe "total_price" do

it "calculates total price on single room" do
expect(@reservation.total_price).must_equal (400)
end

it "calculates total price of a block" do
occupancy = [{:room => Hotel::Room.new(12), :guest => "Picchu"},{:room => Hotel::Room.new(14), :guest => "Elvy"}]
reservation = Hotel::Reservation.new(:BLOCK, @date, occupancy)

expect(reservation.total_price).must_equal (800)
end

end

end
24 changes: 24 additions & 0 deletions test/room_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require_relative 'test_helper'

describe "Room class" do
before do
@room = Hotel::Room.new(1)
end

describe "initialize" do
it "creates a valid room object" do
expect(@room).must_be_kind_of Hotel::Room
end
end

describe "Room methods" do
it "sets price to 200" do
expect(@room.price).must_equal 200
end

it "gives room a default type" do
expect(@room.type).must_equal "standard"
end
end

end
11 changes: 10 additions & 1 deletion test/test_helper.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
# Add simplecov
require 'simplecov'
SimpleCov.start do
add_filter 'test/' # Tests should not be checked for coverage.
end

require "minitest"
require "minitest/autorun"
require "minitest/reporters"

Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new

# require_relative your lib files here!
require_relative "../lib/reservation_manager.rb"
require_relative "../lib/room.rb"
require_relative "../lib/reservation.rb"
require_relative "../lib/date_range.rb"