-
Notifications
You must be signed in to change notification settings - Fork 6
/
chapter_1.rb
170 lines (136 loc) · 3.99 KB
/
chapter_1.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
class Movie
REGULAR = 0
NEW_RELEASE = 1
CHILDRENS = 2
attr_reader :title
attr_writer :price
def initialize(title, the_price_code)
@title, self.price = title, the_price_code
end
def charge(days_rented)
@price.charge(days_rented)
end
def frequent_renter_points(days_rented)
@price.frequent_renter_points(days_rented)
end
end
module DefaultPrice
def frequent_renter_points(days_rented)
1
end
end
class RegularPrice
include DefaultPrice
def charge(days_rented)
result = 2
result += (days_rented - 2) * 1.5 if days_rented > 2
result
end
end
class NewReleasePrice
def charge(days_rented)
days_rented * 3
end
def frequent_renter_points(days_rented)
days_rented > 1 ? 2 : 1
end
end
class ChildrensPrice
include DefaultPrice
def charge(days_rented)
result = 1.5
result += (days_rented - 3) * 1.5 if days_rented > 3
result
end
end
class Rental
attr_reader :movie, :days_rented
def initialize(movie, days_rented)
@movie, @days_rented = movie, days_rented
end
def charge
movie.charge(days_rented)
end
def frequent_renter_points
movie.frequent_renter_points(days_rented)
end
end
class Customer
attr_reader :name
def initialize(name)
@name = name
@rentals = []
end
def add_rental(arg)
@rentals << arg
end
def statement
frequent_renter_points = 0
result = "Rental Record for #{@name}\n"
@rentals.each do |element|
# show figures for this rental
result += "\t" + element.movie.title + "\t" + element.charge.to_s + "\n"
end
#add footer lines
result += "Amount owed is #{total_charge}\n"
result += "You earned #{total_frequent_renter_points} frequent renter points"
result
end
def html_statement
result = "<h1>Rentals for <em>#{@name}</em></h1><p>\n"
@rentals.each do |element|
# show figures for this rental
result += "\t" + element.movie.title + ": " + element.charge.to_s + "<br>\n"
end
# add footer lines
result += "<p>You owe <em>#{total_charge}</em></p>\n"
result += "<p>On this rental you earned " +
"<em>#{total_frequent_renter_points}</em> " +
"frequent renter points</p>"
result
end
private
def total_charge
@rentals.inject(0) {|sum, element| sum + element.charge}
end
def total_frequent_renter_points
@rentals.inject(0) {|sum, element| sum + element.frequent_renter_points}
end
end
require "test/unit"
class VideoRentalTest < Test::Unit::TestCase
def test_statement
customer = Customer.new('Chap')
movie1 = Movie.new('Joe Versus the Volcano', RegularPrice.new)
rental1 = Rental.new(movie1, 5)
customer.add_rental(rental1)
assert_equal "Rental Record for Chap\n" +
"\tJoe Versus the Volcano\t6.5\n" +
"Amount owed is 6.5\n" +
"You earned 1 frequent renter points", customer.statement
movie2 = Movie.new('Sleepless in Seattle', ChildrensPrice.new)
rental2 = Rental.new(movie2, 1)
customer.add_rental(rental2)
assert_equal "Rental Record for Chap\n" +
"\tJoe Versus the Volcano\t6.5\n" +
"\tSleepless in Seattle\t1.5\n" +
"Amount owed is 8.0\n" +
"You earned 2 frequent renter points", customer.statement
movie3 = Movie.new('You\'ve Got Mail', NewReleasePrice.new)
rental3 = Rental.new(movie3, 15)
customer.add_rental(rental3)
assert_equal "Rental Record for Chap\n" +
"\tJoe Versus the Volcano\t6.5\n" +
"\tSleepless in Seattle\t1.5\n" +
"\tYou've Got Mail\t45\n" +
"Amount owed is 53.0\n" +
"You earned 4 frequent renter points", customer.statement
assert_equal "<h1>Rentals for <em>Chap</em></h1><p>\n" +
"\tJoe Versus the Volcano: 6.5<br>\n" +
"\tSleepless in Seattle: 1.5<br>\n" +
"\tYou've Got Mail: 45<br>\n" +
"<p>You owe <em>53.0</em></p>\n" +
"<p>On this rental you earned " +
"<em>4</em> frequent renter points</p>", customer.html_statement
end
end