Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
b1eb7b4
created new reservation class and test for initialization, tested wit…
wangjoc Mar 2, 2020
3cdf2cc
Add coverage directory to .gitignore file and psuedocode
wangjoc Mar 2, 2020
98111fc
Add coverage directory to .gitignore file, second attempt
wangjoc Mar 2, 2020
5edd847
created initial tests and code for res class
wangjoc Mar 2, 2020
a580e7d
added initial room class and tests
wangjoc Mar 2, 2020
3da32e8
added in reservation manager class and related tests
wangjoc Mar 2, 2020
e87d650
implemented search by date range function and error checking for room…
wangjoc Mar 3, 2020
67ee9eb
cleaned up some comments and spacing
wangjoc Mar 3, 2020
72a1b8d
wrote out pseudocode for wave 3 (hotel block)
wangjoc Mar 3, 2020
f568610
initial update to reservation manager to accomodate reservation blocks
wangjoc Mar 3, 2020
fd9cce8
refactored some guard clauses
wangjoc Mar 3, 2020
5576ca6
moved search date validation to separate method
wangjoc Mar 3, 2020
2e9819e
updated search by room/date range function for reservation blocks
wangjoc Mar 4, 2020
234dbb4
updated search by date function for block reservation
wangjoc Mar 4, 2020
eae6465
updaated list by room range function for registration block
wangjoc Mar 4, 2020
d115215
refactored reservation class
wangjoc Mar 4, 2020
6bf7df6
refactored code to get rid of warning messages from minitest
wangjoc Mar 4, 2020
8556ff7
cleaned up require relative requests
wangjoc Mar 4, 2020
954cda2
removed hotel file
wangjoc Mar 4, 2020
78161ca
refactored reservation block
wangjoc Mar 4, 2020
df14352
consolidated add reservation and add reservation block. Updated test …
wangjoc Mar 4, 2020
76281e7
added in initial tests for assigning first available room to new rese…
wangjoc Mar 4, 2020
32bc695
added functionality to create new reservation given only dates
wangjoc Mar 4, 2020
564b097
added more tests for reservation class
wangjoc Mar 4, 2020
e44d9cd
added in csv files with dummy data (reservations, reservation blocks,…
wangjoc Mar 5, 2020
435462a
cleaned up test for csv record instantiation
wangjoc Mar 5, 2020
199e02e
updated load all section to pass tests
wangjoc Mar 5, 2020
4adadc2
updated load all test to require implementation in child class
wangjoc Mar 5, 2020
89f0332
updated load all tests and removed the original template code
wangjoc Mar 5, 2020
77473d3
updates to comments
wangjoc Mar 6, 2020
2225275
updated tests and related code to look off reservation block rather t…
wangjoc Mar 6, 2020
1e00923
migrate reservation methods over to reservation block
wangjoc Mar 6, 2020
00dfcea
deleted reservation class and related code
wangjoc Mar 6, 2020
e731461
removed reservations holder and related code
wangjoc Mar 6, 2020
683adf1
updated add reservation to only work with reservation blocks
wangjoc Mar 6, 2020
407eb0a
modified main tests for adding reservations
wangjoc Mar 6, 2020
5337847
added in test for if no rooms are available through list
wangjoc Mar 6, 2020
805f644
moved order of test sections around
wangjoc Mar 6, 2020
1f54f6a
changed name of reservation block to reservation
wangjoc Mar 6, 2020
d8cf487
removed data validation code from reservation manager
wangjoc Mar 6, 2020
c2e1e7f
cleaned out some extra comments
wangjoc Mar 6, 2020
0fd096b
fixed build_path test
wangjoc Mar 6, 2020
17c3016
finished csv record testing by creating a test class
wangjoc Mar 6, 2020
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
Expand Up @@ -48,3 +48,4 @@ build-iPhoneSimulator/

# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc
coverage
53 changes: 53 additions & 0 deletions lib/csv_record.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
################################
## ADAPTED FROM OO-RIDE-SHARE ##
################################

require 'csv'
require 'pry'

module HotelManager
class CsvRecord
attr_reader :id

def initialize(id)
self.class.validate_id(id)
@id = id
end

# Takes either full_path or directory and optional file_name
# Default file name matches class name
def self.load_all(full_path: nil, directory: nil, file_name: nil)

full_path ||= build_path(directory, file_name)

return CSV.read(
full_path,
headers: true,
header_converters: :symbol,
converters: :numeric
).map { |record| from_csv(record) }
end

def self.validate_id(id)
if id.nil? || id <= 0
raise ArgumentError, 'ID cannot be blank or less than one.'
end
end

def self.from_csv(record)
raise NotImplementedError, 'Implement me in a child class!'
end

def self.build_path(directory, file_name)
raise ArgumentError, "Either full_path or directory is required" if directory.nil?

if file_name.nil?
class_name = self.to_s.split('::').last
file_name = "#{class_name.downcase}s.csv"
end

return "#{directory}/#{file_name}"
end

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

require_relative 'room'

module HotelManager
class Reservation

attr_reader :id, :customer_id, :start_date, :end_date, :room_cost, :rooms, :room_ids

# Room default cost of $200
def initialize id: ,
customer_id: ,
start_date: ,
end_date: ,
room_cost: 200,
rooms: nil,
room_ids: nil

@id = id
@customer_id = customer_id
@start_date = start_date
@end_date = end_date
@room_cost = room_cost
@rooms = rooms
@room_ids = room_ids

validate_date
@rooms.nil? ? validate_room(@room_ids) : validate_room(@rooms)
end

def validate_room(attribute)

Choose a reason for hiding this comment

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

Consider giving this method a name like validate_block or adding a comment to increase readability.

raise ArgumentError, "Room or room_id is required" if @rooms.nil? && @room_ids.nil?

if attribute.length < 1 || attribute.length > 5
raise ArgumentError, "#{attribute.length} is an invalid number of rooms for a hotel block"
end
end

# Check input validation
def validate_date
if !@start_date.is_a?(Date) || !@end_date.is_a?(Date)
raise ArgumentError, "Expected #{@start_date} and #{@end_date} to be date"
elsif @start_date >= @end_date
raise ArgumentError, "#{@start_date} must be before #{@end_date}"
end
end

# Calculate cost of reservation, exclusive of last date
def total_cost
@room_cost * (@end_date - @start_date - 1) * @rooms.length
end

# Checks if reservation exists on a specific date
def check_date(search_date)
(search_date >= @start_date) && (search_date <= @end_date)
end

# Checks whether reservation is within a given date range
def check_reservation_range(date_one, date_two)
first_date = date_one < date_two ? date_one : date_two
second_date = date_one < date_two ? date_two : date_one
first_date < @end_date && second_date > @start_date

Choose a reason for hiding this comment

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

Remember the ada way is to use explicit return :)

end

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

require_relative 'reservation'
require_relative 'room'

module HotelManager
class ReservationManager

attr_reader :rooms, :reservation_blocks

# Populate hotel with 20 rooms upon initialization
def initialize
@rooms = []
@reservation_blocks = []

20.times do |index|
@rooms << HotelManager::Room.new(id: index + 1)
end
end

# Creates and saves new reservation/block to instance variables
def save_reservation(first_date, second_date, num_of_rooms: 1, customer_id: nil, room_cost: 200)

# change list_room_by_range to return argument rather than string
available_rooms = list_room_by_range(first_date,second_date)
chosen_rooms = available_rooms.take(num_of_rooms)

raise ArgumentError, "No rooms available" if chosen_rooms.empty?

chosen_rooms.map!{|room| room.id}

new_reservation = HotelManager::Reservation.new(
id: @reservation_blocks.length + 1,
customer_id: customer_id,
start_date: first_date,
end_date: second_date,
room_cost: room_cost,
room_ids: chosen_rooms
)

@reservation_blocks << new_reservation
end

def find_room(id)
@rooms.find { |room| room.id == id }
end

# List out all rooms in hotel
def rooms_list
@rooms.map {|room| "Room: #{room.id}"}.join(", ")
end

# List out all reservations by room and date range
def search_by_room_date(room, first_date, second_date)
raise ArgumentError, "Room #{room} does not exist" if @rooms.last.id < room

reservation_room_date = []

@reservation_blocks.each do |reservation_block|
found_room = reservation_block.room_ids.include? room
if reservation_block.check_reservation_range(first_date,second_date) && found_room
reservation_room_date << reservation_block
end
end

return reservation_found?(reservation_room_date, "reservations")
end

# List out reservations by specific date
def search_by_date(date)
reservation_by_date = []

@reservation_blocks.each do |reservation_block|
reservation_by_date << reservation_block if reservation_block.check_date(date)
end

return reservation_found?(reservation_by_date, "reservations")
end

def list_room_by_range(first_date, second_date)
available_rooms = @rooms.dup

@reservation_blocks.each do |reservation_block|
if reservation_block.check_reservation_range(first_date, second_date)
reservation_block.room_ids.each do |room_id|
available_rooms -= [find_room(room_id)]
end
end
end

return reservation_found?(available_rooms, "rooms")
end

# Raise argument error if no items found
def reservation_found? tracker, type
raise ArgumentError, "No #{type} available in date range." if tracker.empty?

return tracker
end

end
end
11 changes: 11 additions & 0 deletions lib/room.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module HotelManager
class Room

attr_reader :id

def initialize id:
@id = id
end

end
end
97 changes: 97 additions & 0 deletions test/csv_record_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
################################
## ADAPTED FROM OO-RIDE-SHARE ##
################################

require_relative 'test_helper'

TEST_DATA_DIR = 'test/test_data'

describe 'CSV Record Class' do
it 'is an instance of CSV Record' do
record = HotelManager::CsvRecord.new(1)
expect(record.id).must_equal 1
end

it 'raises error if invalid id is used' do
expect {HotelManager::CsvRecord.new(-7)}.must_raise ArgumentError
expect {HotelManager::CsvRecord.new("One")}.must_raise ArgumentError
end

it 'validates that id accepts natural numbers' do
[1, 10, 9999].each {|id| HotelManager::CsvRecord.validate_id(id)}
end

it 'raises for negative numbers and 0' do
[0, -1, -10, -9999].each {|id| expect { HotelManager::CsvRecord.validate_id(id) }.must_raise ArgumentError}
end

it 'raises for nil' do
expect {HotelManager::CsvRecord.validate_id(nil)}.must_raise ArgumentError
end
end

describe 'CSV Record Class - Load All' do
it "raise argument error if invalid file path" do
expect {HotelManager::CsvRecord.load_all}.must_raise ArgumentError
end

it "raises an error if missing directory or file path" do
expect {HotelManager::CsvRecord.build_path(nil,"")}.must_raise ArgumentError
end

it "raises an error if invoked directly (without subclassing)" do
full_path = "#{TEST_DATA_DIR}/testrecords.csv"
expect {HotelManager::CsvRecord.load_all(full_path: full_path)}.must_raise NotImplementedError
end
end

describe 'CSV Record Class - Test Class' do
class TestRecord < HotelManager::CsvRecord
attr_reader :call_count

def initialize(id:, customer_id:, start_date:, end_date: , num_of_rooms:)
super(id)
end

def self.load_all(*args, **kwargs)
@call_count = 0
super
end

def self.from_csv(record)
new(**record)
@call_count += 1
end

def self.call_count
@call_count
end
end

describe 'load_all' do
file_name = 'testrecords.csv'
record_count = CSV.read("#{TEST_DATA_DIR}/#{file_name}", headers: true).length

it 'finds data given just a directory' do
records = TestRecord.load_all(directory: TEST_DATA_DIR)
expect(records.length).must_equal record_count
end

it 'finds data given a directory and filename' do
records = TestRecord.load_all(directory: TEST_DATA_DIR, file_name: file_name)

expect(records.length).must_equal record_count
end

it 'finds data given a full path' do
records = TestRecord.load_all(full_path: "#{TEST_DATA_DIR}/#{file_name}")

expect(records.length).must_equal record_count
end

it 'calls `from_csv` for each record in the file' do
TestRecord.load_all(directory: TEST_DATA_DIR)
expect(TestRecord.call_count).must_equal record_count
end
end
end
Loading