diff --git a/.history/lib/reservation_20190921132905.rb b/.history/lib/reservation_20190921132905.rb new file mode 100644 index 000000000..0b183901b --- /dev/null +++ b/.history/lib/reservation_20190921132905.rb @@ -0,0 +1,32 @@ +<<<<<<< HEAD +require_relative '../lib/time' +require_relative '../lib/service' + + + +class Reservation + attr_accessor :room, :price, :duration, :cost, :check_in, :check_out, :reservations + + + def initialize(check_in, check_out) + @check_in = check_in + @check_out = check_out + @duration = Dates.new.reserve_time(check_in, check_out) + @cost = Service.new.room_cost(@duration) + @room = rand(1..20) + end + + +======= +module Hotel + class Reservation + # Feel free to change this method signature as needed. Make sure to update the tests! + def initialize(start_date, end_date, room) + end + + def cost + return 3 + end + end +>>>>>>> origin/design-scaffolding +end diff --git a/.history/lib/reservation_20190921134233.rb b/.history/lib/reservation_20190921134233.rb new file mode 100644 index 000000000..af7dceb7b --- /dev/null +++ b/.history/lib/reservation_20190921134233.rb @@ -0,0 +1,15 @@ + + +======= +module Hotel + class Reservation + # Feel free to change this method signature as needed. Make sure to update the tests! + def initialize(start_date, end_date, room) + end + + def cost + return 3 + end + end + >>>>>>> origin/design-scaffolding +end diff --git a/.history/lib/reservation_20190921134326.rb b/.history/lib/reservation_20190921134326.rb new file mode 100644 index 000000000..ec13f3ef2 --- /dev/null +++ b/.history/lib/reservation_20190921134326.rb @@ -0,0 +1,12 @@ + +module Hotel + class Reservation + # Feel free to change this method signature as needed. Make sure to update the tests! + def initialize(start_date, end_date, room) + end + + def cost + return 3 + end + end +end diff --git a/design-activity.md b/design-activity.md new file mode 100644 index 000000000..197aaf3b7 --- /dev/null +++ b/design-activity.md @@ -0,0 +1,19 @@ +Evaluation Responsibility: + +1. A includes the classes CartEntry, ShoppingCart, and Order. B has the same classes. + +2. CartEntry is a class that initializes unit_price and quantity. Shopping cart initializes an array of entries, and Order creates a new instance of ShoppingCart and stores it in the instance variable cart. +In implementation A, CartEntry unit_price and quantity are shared with Order to return total price. Shopping cart shares entries with Order, which is used in the method total_price. Order creates a new instance of shopping cart. In implementation B, Order relies on the information stored in CartEntry and ShoppingCart to make a new instance of cart. In Implementation B, the methods for that class are created within the class then accessed by creating an instance of that class. + +3. In Implementation A, CartEntry has no methods, Shopping cart has no methods, and Order has a total price method using the instance variables from CartEntry, and the instance of cart from Order. In Implementation B, CartEntry has a method of price, calculated by multiplying the instances of unit and quantity. Shopping cart has a separate method for price, which adds the price of each entry and creates a total sum for entries. Order has the method total_price which returns the price for an instance of cart, then returns a total price including sales tax. The second implementation uses instances of another class rather than instance variables stored within that class. + +4. For Implementation A, the price is computed in Order. Total_price is directly manipulating instance variable of other classes. In Implementation B, each lower level class creates its own instance of price. + +5. For items bought in bulk, I think Implementation B would be easier to modify, because price could be altered in the lower level classes fairly easily rather than having to change the entire method in Implementation A's Order class. + +6. The implementation that better adheres to the single responsibility principle (and is more loosely coupled) is Implementation B. + + +Revisiting Hotel: + +In Hotel Controller, the available rooms method is creating a new instance of the class DateRange instead of taking instances of DateRange. I may be able to simply remove that portion of the code, since it looks like it may be redundant in relation to the rest of the code in that method. If not, the method should be written to be taking instance variables in the until loop rather than local variables. After looking at the code, I think that it's a flaw in the original intention of the design, rather than an area that needs to be refactored. \ No newline at end of file diff --git a/design-scaffolding-notes.md b/design-scaffolding-notes.md new file mode 100644 index 000000000..141f71585 --- /dev/null +++ b/design-scaffolding-notes.md @@ -0,0 +1,38 @@ +# Hotel Design Scaffolding + +## Purpose + +This scaffolding is intended for students who are feeling overwhelmed by the open-ended nature of the Hotel project. Its goal is to answer some of the initial questions about how project files should be laid out, so that students can focus on designing the object interactions and complex Ruby logic that are the core learning goals of the project. The hope is to do so without removing too much of the interesting design work. + +This document and the associated code is intended to be student-facing - if you have a student you think would benefit from this, send them a link! + +### What it includes + +- Three class stubs, `HotelController`, `Reservation` and `DateRange` +- Stubs for public methods of each class from waves 1 and 2, as described in the user stories +- "Interface" tests for each class method that invoke it with the right parameters and verify the return type +- Full test stubs for the `DateRange` class + +### What it does not include + +- Opinions about how classes should interact or data should be stored +- Opinions about whether there should be a `Room` class, or whether it should know about `Reservation`s +- Private helper methods to keep code organized + +Students should feel free to modify any code as they see fit, including changing method signatures, adding new classes and methods, reordering things, not looking at the `DateRange` tests because they want to give it a shot on their own, etc. + +## How to use this code + +Design scaffolding code lives on the `design-scaffolding` branch. + +You can use this code either as inspiration, or as a starting point. If using it as an inspiration, it follows our standard project layout, with product code under `lib/` and tests under `spec/`. + +If you choose to use the code on this branch as a starting point, follow these steps to start your project: + +``` +$ git clone +$ cd hotel +$ git merge origin/design-scaffolding +``` + +You can try to merge in the design scaffolding after you've started, but you'll probably end up with merge conflicts. See an instructor if you're not able to resolve them yourself. diff --git a/lib/date_range.rb b/lib/date_range.rb new file mode 100644 index 000000000..bc4f7f46e --- /dev/null +++ b/lib/date_range.rb @@ -0,0 +1,46 @@ + +require 'pry' + +module Hotel + class DateRange + + attr_accessor :start_date, :end_date + + def initialize(start_date, end_date) + @start_date = start_date + @end_date = end_date + + + if start_date == nil || end_date == nil + raise ArgumentError.new + elsif end_date <= start_date + raise ArgumentError.new + end + end + + def nights + nights = (end_date - start_date) - 1 + nights = nights.to_i + end + + + + def overlap?(range) + if range.end_date > @start_date && range.end_date < @end_date + return true + elsif range.start_date < @start_date && range.end_date > @end_date + return true + elsif range.start_date == @start_date + return true + else + return false + end + + end + + # def include?(date) + # return false + # end + + end +end diff --git a/lib/hotel_controller.rb b/lib/hotel_controller.rb new file mode 100644 index 000000000..ff8ba38eb --- /dev/null +++ b/lib/hotel_controller.rb @@ -0,0 +1,94 @@ +require_relative 'date_range' +require_relative 'reservation' +require 'pry' + +module Hotel + class HotelController + + # does this need to be accessor? idk, look it up + + attr_accessor :reservation_list, :rooms, :reservation + + # Wave 1 + def initialize + @rooms = (1..20).to_a + @reservation_list = [] + @reservation = reservation + end + + # may be complete nonsense, need to test with more than one occurence, but will return first index for empty list + def reserve_room(start_date, end_date) + + current_room = () + if @reservation_list.empty? == true + current_room = rooms.shift + elsif @reservation_list.empty? == false + @reservation_list.include?(start_date) + count = @reservation_list.count(start_date) + current_room = rooms[count - 1] + end + + + room = current_room + range = Hotel::DateRange.new(start_date, end_date) + start_date = range.start_date + end_date = range.end_date + nights = range.nights + + # if the range has overlapping dates, then it will return true + # if the range returns true + + reservation = Reservation.new(start_date, end_date, nights, room) + + # if @reservations_list.overlap?(range) + # raise ArgumentError.new + # end + + @reservation_list << reservation + return reservation + end + + # possible trickery, reassess when more reservations are generated? + def reservations(date) + reservation_list.each do |index, date| + if reservation_list[index].include?(date) + print reservation_list[index] + end + end + end + + # Wave 2 + def available_rooms(start_date, end_date) + # range = Hotel::DateRange.new(start_date, end_date) + # start_date = range.start_date + # end_date = range.end_date + # nights = range.nights + length = end_date - start_date + check = 1 + + until check == length do + if @reservation_list.empty? == false + @reservation_list.each do + @reservation.include?(@start_date) + rooms.delete(@reservation.room) + end + elsif @reservation_list.empty? + break + end + @start_date + 1 + check += 1 + end + return rooms + end + + end + +end +# if the reservation list includes that date +# check for room numbers for that date +# delete that room number from a generic list of rooms +# iterate to next date (nights) + + +# start_date and end_date should be instances of class Date + diff --git a/lib/reservation.rb b/lib/reservation.rb new file mode 100644 index 000000000..846e40b5c --- /dev/null +++ b/lib/reservation.rb @@ -0,0 +1,19 @@ +require_relative 'date_range' + + +module Hotel + class Reservation + + attr_reader :room, :nights + # Feel free to change this method signature as needed. Make sure to update the tests! + def initialize(start_date, end_date, nights, room) + @room = room + @nights = nights + end + + def cost + price = 200 + cost = price * nights + end + end +end diff --git a/spec/date_range_spec.rb b/spec/date_range_spec.rb new file mode 100644 index 000000000..7c155a0b1 --- /dev/null +++ b/spec/date_range_spec.rb @@ -0,0 +1,78 @@ +require_relative "spec_helper" + +describe Hotel::DateRange do + describe "consructor" do + it "Can be initialized with two dates" do + start_date = Date.new(2017, 01, 01) + end_date = start_date + 3 + + range = Hotel::DateRange.new(start_date, end_date) + + expect(range.start_date).must_equal start_date + expect(range.end_date).must_equal end_date + end + + xit "is an an error for negative-lenght ranges" do + end + + xit "is an error to create a 0-length range" do + end + end + + describe "overlap?" do + before do + start_date = Date.new(2017, 01, 01) + end_date = start_date + 3 + + @range = Hotel::DateRange.new(start_date, end_date) + end + + it "returns true for the same range" do + start_date = @range.start_date + end_date = @range.end_date + test_range = Hotel::DateRange.new(start_date, end_date) + + expect(@range.overlap?(test_range)).must_equal true + end + + xit "returns true for a contained range" do + end + + xit "returns true for a range that overlaps in front" do + end + + xit "returns true for a range that overlaps in the back" do + end + + xit "returns true for a containing range" do + end + + xit "returns false for a range starting on the end_date date" do + end + + xit "returns false for a range ending on the start_date date" do + end + + xit "returns false for a range completely before" do + end + + xit "returns false for a date completely after" do + end + end + + xdescribe "include?" do + it "reutrns false if the date is clearly out" do + end + + it "returns true for dates in the range" do + end + + it "returns false for the end_date date" do + end + end + + xdescribe "nights" do + it "returns the correct number of nights" do + end + end +end diff --git a/spec/hotel_controller_spec.rb b/spec/hotel_controller_spec.rb new file mode 100644 index 000000000..daf78c0b3 --- /dev/null +++ b/spec/hotel_controller_spec.rb @@ -0,0 +1,50 @@ +require_relative "spec_helper" + +describe Hotel::HotelController do + before do + @hotel_controller = Hotel::HotelController.new + @date = Date.parse("2020-08-04") + end + describe "wave 1" do + describe "rooms" do + it "returns a list" do + rooms = @hotel_controller.rooms + expect(rooms).must_be_kind_of Array + end + end + describe "reserve_room" do + it "takes two Date objects and returns a Reservation" do + start_date = @date + end_date = start_date + 3 + + reservation = @hotel_controller.reserve_room(start_date, end_date) + + expect(reservation).must_be_kind_of Hotel::Reservation + end + end + + describe "reservations" do + it "takes a Date and returns a list of Reservations" do + reservation_list = @hotel_controller.reservations(@date) + + expect(reservation_list).must_be_kind_of Array + reservation_list.each do |res| + res.must_be_kind_of Reservation + end + end + end + end + + describe "wave 2" do + describe "available_rooms" do + it "takes two dates and returns a list" do + start_date = @date + end_date = start_date + 3 + + room_list = @hotel_controller.available_rooms(start_date, end_date) + + expect(room_list).must_be_kind_of Array + end + end + end +end diff --git a/spec/reservation_spec.rb b/spec/reservation_spec.rb new file mode 100644 index 000000000..a3be669c0 --- /dev/null +++ b/spec/reservation_spec.rb @@ -0,0 +1,12 @@ +require_relative "spec_helper" + +describe Hotel::Reservation do + describe "cost" do + it "returns a number" do + start_date = Date.new(2017, 01, 01) + end_date = start_date + 3 + reservation = Hotel::Reservation.new(start_date, end_date, nil) + expect(reservation.cost).must_be_kind_of Numeric + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 000000000..cbf8c253e --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,14 @@ +# Add simplecov +require "minitest" +require "minitest/autorun" +require "minitest/reporters" +require "minitest/skip_dsl" + +require "date" + +Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new + +# Require_relative your lib files here! +require_relative "../lib/hotel_controller.rb" +require_relative "../lib/reservation.rb" +require_relative "../lib/date_range.rb" diff --git a/test/controller_test.rb b/test/controller_test.rb new file mode 100644 index 000000000..053c24d4b --- /dev/null +++ b/test/controller_test.rb @@ -0,0 +1,50 @@ +require_relative "test_helper" + +describe Hotel::HotelController do + before do + @hotel_controller = Hotel::HotelController.new + @date = Date.parse("2020-08-04") + end + describe "wave 1" do + describe "rooms" do + it "returns a list" do + rooms = @hotel_controller.rooms + expect(rooms).must_be_kind_of Array + end + end + describe "reserve_room" do + it "takes two Date objects and returns a Reservation" do + start_date = @date + end_date = start_date + 3 + + reservation = @hotel_controller.reserve_room(start_date, end_date) + + expect(reservation).must_be_kind_of Hotel::Reservation + end + end + + describe "reservations" do + it "takes a Date and returns a list of Reservations" do + reservation_list = @hotel_controller.reservations(@date) + + expect(reservation_list).must_be_kind_of Array + reservation_list.each do |res| + res.must_be_kind_of Reservation + end + end + end + end + + describe "wave 2" do + describe "available_rooms" do + it "takes two dates and returns a list" do + start_date = @date + end_date = start_date + 3 + + room_list = @hotel_controller.available_rooms(start_date, end_date) + + expect(room_list).must_be_kind_of Array + end + end + end +end diff --git a/test/date_range_test.rb b/test/date_range_test.rb new file mode 100644 index 000000000..190cc3c57 --- /dev/null +++ b/test/date_range_test.rb @@ -0,0 +1,126 @@ +require_relative "test_helper" + +describe Hotel::DateRange do + describe "constructor" do + it "Can be initialized with two dates" do + start_date = Date.new(2017, 01, 01) + end_date = start_date + 3 + + range = Hotel::DateRange.new(start_date, end_date) + + expect(range.start_date).must_equal start_date + expect(range.end_date).must_equal end_date + end + + it "is an an error for negative-length ranges" do + start_date = Date.new(2010, 12, 20) + end_date = Date.new(2010, 12, 19) + + expect{Hotel::DateRange.new(start_date, end_date)}.must_raise ArgumentError + end + + it "is an error to create a 0-length range" do + start_date = Date.new(2010, 12, 20) + end_date = Date.new(2010, 12, 20) + + expect{Hotel::DateRange.new(start_date, end_date)}.must_raise ArgumentError + end + end + + describe "overlap?" do + before do + start_date = Date.new(2017, 01, 10) + end_date = start_date + 3 + + @range = Hotel::DateRange.new(start_date, end_date) + end + + it "returns true for the same range" do + start_date = @range.start_date + end_date = @range.end_date + test_range = Hotel::DateRange.new(start_date, end_date) + + expect(@range.overlap?(test_range)).must_equal true + end + + it "returns true for a contained range" do + start_date = @range.start_date + 1 + end_date = @range.end_date - 1 + test_range = Hotel::DateRange.new(start_date, end_date) + + expect(@range.overlap?(test_range)).must_equal true + end + + it "returns true for a range that overlaps in front" do + start_date = Date.new(2017, 01, 8) + end_date = @range.end_date - 2 + test_range = Hotel::DateRange.new(start_date, end_date) + + expect(@range.overlap?(test_range)).must_equal true + end + + it "returns true for a range that overlaps in the back" do + start_date = Date.new(2017, 01, 8) + end_date = @range.end_date - 2 + test_range = Hotel::DateRange.new(start_date, end_date) + + expect(@range.overlap?(test_range)).must_equal true + end + + it "returns true for a containing range" do + start_date = Date.new(2017, 01, 9) + end_date = @range.end_date + 2 + test_range = Hotel::DateRange.new(start_date, end_date) + + expect(@range.overlap?(test_range)).must_equal true + end + + it "returns false for a range starting on the end_date date" do + start_date = Date.new(2017, 01, 11) + end_date = @range.end_date + test_range = Hotel::DateRange.new(start_date, end_date) + + expect(@range.overlap?(test_range)).must_equal false + end + + it "returns false for a range ending on the start_date date" do + start_date = Date.new(2017, 01, 05) + end_date = @range.start_date + test_range = Hotel::DateRange.new(start_date, end_date) + + expect(@range.overlap?(test_range)).must_equal false + end + + it "returns false for a range completely before" do + start_date = Date.new(2016, 01, 01) + end_date = @range.start_date + test_range = Hotel::DateRange.new(start_date, end_date) + + expect(@range.overlap?(test_range)).must_equal false + end + + it "returns false for a date completely after" do + start_date = Date.new(2016, 06, 05) + end_date = @range.start_date + test_range = Hotel::DateRange.new(start_date, end_date) + + expect(@range.overlap?(test_range)).must_equal false + end + end + + xdescribe "include?" do + it "returns false if the date is clearly out" do + end + + it "returns true for dates in the range" do + end + + it "returns false for the end_date date" do + end + end + + xdescribe "nights" do + it "returns the correct number of nights" do + end + end +end diff --git a/test/reservation_test.rb b/test/reservation_test.rb new file mode 100644 index 000000000..c6c9e0795 --- /dev/null +++ b/test/reservation_test.rb @@ -0,0 +1,14 @@ +require_relative "test_helper" + +describe Hotel::Reservation do + describe "cost" do + it "returns a number" do + start_date = Date.new(2017, 01, 01) + end_date = start_date + 3 + nights = 3 + reservation = Hotel::Reservation.new(start_date, end_date, nights, nil) + expect(reservation.cost).must_be_kind_of Numeric + expect(reservation.cost).must_equal 600 + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index c3a7695cf..cbf8c253e 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -2,7 +2,13 @@ require "minitest" require "minitest/autorun" require "minitest/reporters" +require "minitest/skip_dsl" + +require "date" Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new -# require_relative your lib files here! +# Require_relative your lib files here! +require_relative "../lib/hotel_controller.rb" +require_relative "../lib/reservation.rb" +require_relative "../lib/date_range.rb"