rms_flicks 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +21 -0
- data/README +6 -0
- data/bin/flicks +76 -0
- data/bin/movie_rankings.csv +4 -0
- data/bin/movies.csv +3 -0
- data/lib/movie.rb +165 -0
- data/lib/movie3d.rb +56 -0
- data/lib/playlist.rb +173 -0
- data/lib/rankable.rb +40 -0
- data/lib/snack_bar.rb +68 -0
- data/lib/waldorf_and_statler.rb +43 -0
- data/spec/movie3d_spec.rb +35 -0
- data/spec/movie_spec.rb +153 -0
- data/spec/playlist_spec.rb +64 -0
- data/spec/snack_bar_spec.rb +32 -0
- metadata +82 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2012 The Pragmatic Studio
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
- You may not use this Software in other training contexts.
|
11
|
+
|
12
|
+
- The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README
ADDED
data/bin/flicks
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# above says to find the ruby environment to get the ruby interpretor
|
4
|
+
# also we ran the following from reviewRuby: 'chmod +x bin/flicks'
|
5
|
+
# this makes it executable.
|
6
|
+
# so we can run it from reviewRuby with: 'bin/flicks'
|
7
|
+
# if installed as a gem, they said it would just run as flicks. - ??? we'll see!
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
# used to test code.
|
12
|
+
|
13
|
+
# this file is now in the bin directory
|
14
|
+
# we can run it from the terminal in the top directory ('reviewRuby') with 'ruby bin/flicks.rb'
|
15
|
+
# so the playlist is up one then back down to the lib directory
|
16
|
+
require_relative '../lib/playlist'
|
17
|
+
|
18
|
+
# ?? i think that since movie3d requires_relative movie - and it is relative to movie3d - this works
|
19
|
+
require_relative '../lib/movie3d'
|
20
|
+
|
21
|
+
# movie1 = Movie.new("goonies", 10)
|
22
|
+
# movie2 = Movie.new("ghostbusters", 9)
|
23
|
+
# movie3 = Movie.new("goldfinger")
|
24
|
+
|
25
|
+
playlist1 = Flicks::Playlist.new("Kermit")
|
26
|
+
|
27
|
+
|
28
|
+
# playlist1.add_movie(movie1)
|
29
|
+
# playlist1.add_movie(movie2)
|
30
|
+
# playlist1.add_movie(movie3)
|
31
|
+
# removed above and added below in files video - after changes (add load method) to playlist
|
32
|
+
|
33
|
+
# make movies.csv the default
|
34
|
+
# but allow user to enter file
|
35
|
+
# command line arguments are stored in a global varible called ARGV
|
36
|
+
# also we call shift which will remove the passed in varible and shift all other elements down one.
|
37
|
+
# the 'or' operator allows for a default.
|
38
|
+
|
39
|
+
|
40
|
+
# we need to do something about the directory for movies.csv
|
41
|
+
# we'll make a default file varible using the File class
|
42
|
+
# -> which will give it an 'absolute path'
|
43
|
+
default_movie_file =
|
44
|
+
File.join(File.dirname(__FILE__), 'movies.csv')
|
45
|
+
|
46
|
+
|
47
|
+
playlist1.load(ARGV.shift || default_movie_file)
|
48
|
+
|
49
|
+
# here we add some movie3d stuff to demonstrate polymorphism
|
50
|
+
# we are going to co-mingle movies and 3d movies in our playlist code
|
51
|
+
|
52
|
+
movie3d = Flicks::Movie3D.new('glee', 5, 20)
|
53
|
+
playlist1.add_movie(movie3d)
|
54
|
+
|
55
|
+
# without changing anything else - 'glee' will get added in to the playlist activities - yeah!
|
56
|
+
|
57
|
+
|
58
|
+
loop do
|
59
|
+
puts "How many viewings? 'quit' to exit"
|
60
|
+
answer = gets.chomp.downcase
|
61
|
+
case answer
|
62
|
+
when /^\d+$/ # 1 or more numbers and end with numbers???
|
63
|
+
playlist1.play(answer.to_i)
|
64
|
+
when 'quit', 'exit'
|
65
|
+
playlist1.print_stats
|
66
|
+
break
|
67
|
+
else
|
68
|
+
puts "Please enter a number or 'quit'."
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# the save methods runs after viewings and creates a file of the the lastest rankings
|
73
|
+
# movie_rankings.csv
|
74
|
+
|
75
|
+
playlist1.save
|
76
|
+
|
data/bin/movies.csv
ADDED
data/lib/movie.rb
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
require_relative 'rankable'
|
2
|
+
require_relative 'snack_bar'
|
3
|
+
|
4
|
+
module Flicks
|
5
|
+
class Movie
|
6
|
+
include Rankable
|
7
|
+
# changed :rank to an accessor in mixins
|
8
|
+
attr_accessor :rank
|
9
|
+
# attr_accessor does a reader and a writer as described below
|
10
|
+
attr_accessor :title
|
11
|
+
|
12
|
+
# attributes have the possiblility to expose date to the outside world
|
13
|
+
# having rank as only a reader means that it can only be changed by the
|
14
|
+
#=> outside world through behaviour methods such as thumbs_up thumbs_down
|
15
|
+
# on the other hand - we will allow someone to change attr_accessor varibles
|
16
|
+
|
17
|
+
# attr_reader :title, :rank
|
18
|
+
# the above line of code is a short cut for the code commented out below
|
19
|
+
|
20
|
+
# def title
|
21
|
+
# @title
|
22
|
+
# end
|
23
|
+
# in programming this is commonly know as a getter method - attr_reader is a short cut to that.
|
24
|
+
|
25
|
+
# attr_writer :title
|
26
|
+
#### does not do the capitalization
|
27
|
+
# the above line of code is a short cut for the code commented out below
|
28
|
+
|
29
|
+
# def title=(new_title)
|
30
|
+
# @title = new_title
|
31
|
+
# end
|
32
|
+
# in programming this is commonly know as a writer method - attr_writer is a short cut to that.
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
def initialize(title, rank=0)
|
38
|
+
# the new method expects there to be an initialize method
|
39
|
+
# this method accepts the passed in varibles
|
40
|
+
# if you want these varibles to be available you need make them instance varibles
|
41
|
+
# they don't have to be the same name as the parameters - but it often makes sense
|
42
|
+
# these instance varibles live for the life of the object and can be accessed.
|
43
|
+
@title = title.capitalize
|
44
|
+
@rank = rank
|
45
|
+
# added with Hashes
|
46
|
+
# there will of coursee be a set of these for every instance of movie.
|
47
|
+
@snack_carbs = Hash.new(0)
|
48
|
+
end
|
49
|
+
|
50
|
+
# added with input/output video
|
51
|
+
|
52
|
+
def self.from_csv(line) # we don't have a movie object to call here - s0 we call from self
|
53
|
+
title, rank = line.split(',')
|
54
|
+
# we changed this so it will raise an exception instead of bomb with an error - rank.to_i)
|
55
|
+
Movie.new(title, Integer(rank))
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_csv
|
59
|
+
"#{@title}, #{@rank}"
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
# added with iterators
|
65
|
+
def each_snack
|
66
|
+
# take the @snack_cards hash we added in hashes video
|
67
|
+
@snack_carbs.each do |name, carbs|
|
68
|
+
# create 'snack' object from our Struct with the name and carbs from each element
|
69
|
+
snack = Snack.new(name, carbs)
|
70
|
+
# then 'yield' that snack object over to block in playlist.print_status
|
71
|
+
yield snack
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
# added with Hashes
|
81
|
+
def carbs_consumed # total
|
82
|
+
@snack_carbs.values.reduce(0, :+)
|
83
|
+
end
|
84
|
+
|
85
|
+
def ate_snack(snack)
|
86
|
+
# we want to accumulate the carbs for each type snack consumed in this Hash instance for a movie.
|
87
|
+
@snack_carbs[snack.name] += snack.carbs
|
88
|
+
puts "#{@title} let to #{snack.carbs} #{snack.name} carbs being consumed."
|
89
|
+
puts "#{@title}'s snacks: #{@snack_carbs}" # just so we can see the accumulation.
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
# the initialize method has to do with state.
|
95
|
+
# below methods has to do with behaviour expressed as instance methods.
|
96
|
+
|
97
|
+
# below is a virtualized attribute - or attribute that is derived from instance varibles.
|
98
|
+
# can be called from within class
|
99
|
+
# when it's called from the class, the receiver object that's calling
|
100
|
+
# => turns out to be "self" which in the case below is movie3 object. that's why it's cool that
|
101
|
+
# "self", since the next time we call it may be from movie2 object.
|
102
|
+
# see the call below in the to_s method.
|
103
|
+
|
104
|
+
# in the mixin video, we removed methods below and put them in rankable.rb
|
105
|
+
# this encapsulates the notion of rankable and makes it geneic
|
106
|
+
|
107
|
+
# def hit?
|
108
|
+
# @rank >= 10
|
109
|
+
# end
|
110
|
+
|
111
|
+
# def status
|
112
|
+
# hit? ? "Hit" : "Flop"
|
113
|
+
|
114
|
+
# end
|
115
|
+
|
116
|
+
# def normalized_rank
|
117
|
+
# normalized_rank = @rank / 1.0
|
118
|
+
# end
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
# # below we are going to override the spaceship comparison method.
|
123
|
+
# def <=>(other_movie)
|
124
|
+
# # this will compare the passed in movie with the rank of the current movie.?? see sorting.rb
|
125
|
+
# other_movie.rank <=> @rank
|
126
|
+
# end
|
127
|
+
|
128
|
+
|
129
|
+
# what if i wanted to be able to run the listing method by just saying "puts movie3"
|
130
|
+
# well - with no method on call to the object, the default is to run
|
131
|
+
#=> the to_s method - which isn't particularly useful.
|
132
|
+
# so let's create another method called to_s which will override the default to_
|
133
|
+
#=> and make it do they same thing as our listing method.
|
134
|
+
# we could of course just get rid of the listing method - but lets leave it for now
|
135
|
+
#=> just to show the idea.
|
136
|
+
|
137
|
+
def listing
|
138
|
+
"#{@title} initialized with rank of #{@rank}."
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
def to_s
|
143
|
+
# - "Just to confirm, this is run when we call movies."
|
144
|
+
"#{@title} initialized with rank of #{normalized_rank} (#{status})."
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
|
149
|
+
# an old programming axiom is "Tell - Don't Ask"
|
150
|
+
# meaning - don't ask an object for it's state - rather just Tell it.
|
151
|
+
|
152
|
+
# removed these in mixin video to put in separate mixin module called 'rankable.rb'
|
153
|
+
# def thumbs_up
|
154
|
+
# @rank += 1
|
155
|
+
# end
|
156
|
+
|
157
|
+
# def thumbs_down
|
158
|
+
# @rank -= 1
|
159
|
+
# end
|
160
|
+
|
161
|
+
end # of Movie class
|
162
|
+
end # of Flicks module
|
163
|
+
|
164
|
+
|
165
|
+
|
data/lib/movie3d.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative 'movie'
|
2
|
+
|
3
|
+
module Flicks
|
4
|
+
|
5
|
+
class Movie3D < Movie
|
6
|
+
|
7
|
+
# this new initialize is necessary because we want to add wow_factor
|
8
|
+
# but we don't want to mess up title & rank
|
9
|
+
# therefore the line super(title, rank) which says - let movie handle setting up these instance vars.
|
10
|
+
# then we set up @wow_factor.
|
11
|
+
# now - initalizing a movie requires 3 parameters
|
12
|
+
|
13
|
+
|
14
|
+
# added this in after realizing movie3d_spec wasn't working - ?? see where i missed it
|
15
|
+
attr_reader :wow_factor
|
16
|
+
|
17
|
+
def initialize(title, rank, wow_factor)
|
18
|
+
super(title, rank)
|
19
|
+
@wow_factor = wow_factor
|
20
|
+
end
|
21
|
+
# specialized traits
|
22
|
+
def thumbs_up
|
23
|
+
# wow_factor = 10
|
24
|
+
|
25
|
+
# instead of doing the line below
|
26
|
+
# let's make so that it does whatever 'movie class' is doing times 10
|
27
|
+
# that way, if thumbs up in movie changes, the effect here will be more predictable
|
28
|
+
# @rank += ( 1 * @wow_factor)
|
29
|
+
@wow_factor.times { super }
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
# new traits
|
35
|
+
def show_effect
|
36
|
+
# wow_factor = 10
|
37
|
+
puts "Wow!" * @wow_factor
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end # of Movie3d class
|
42
|
+
|
43
|
+
end # of Flicks module
|
44
|
+
|
45
|
+
if __FILE__ == $0
|
46
|
+
# the following can be run before anything is added. it behaves just like movie.rb class
|
47
|
+
|
48
|
+
movie3d = Flicks::Movie3D.new('glee', 5, 10)
|
49
|
+
puts movie3d.title
|
50
|
+
puts movie3d.rank
|
51
|
+
puts movie3d
|
52
|
+
movie3d.show_effect
|
53
|
+
movie3d.thumbs_up
|
54
|
+
puts movie3d
|
55
|
+
|
56
|
+
end
|
data/lib/playlist.rb
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
require_relative 'movie'
|
2
|
+
require_relative 'movie3d'
|
3
|
+
require_relative 'waldorf_and_statler'
|
4
|
+
require_relative 'snack_bar'
|
5
|
+
|
6
|
+
module Flicks
|
7
|
+
class Playlist
|
8
|
+
|
9
|
+
# added this after seeing it in their code - don't know how i missed it ???
|
10
|
+
attr_reader :name
|
11
|
+
|
12
|
+
def initialize(name)
|
13
|
+
@name = name
|
14
|
+
@movies = [] # empty array
|
15
|
+
end
|
16
|
+
|
17
|
+
def load(from_file)
|
18
|
+
# copied from files.rb - changed to accept parameter
|
19
|
+
File.readlines(from_file).each do |line|
|
20
|
+
|
21
|
+
# removed to add better code
|
22
|
+
# title, rank = line.split(',')
|
23
|
+
# movie = Movie.new(title, rank.to_i)
|
24
|
+
# # removed after copy from files to add line below ->puts movie
|
25
|
+
# add_movie(movie)
|
26
|
+
add_movie(Movie.from_csv(line))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def save(to_file="movie_rankings.csv")
|
31
|
+
File.open(to_file, "w") do |file|
|
32
|
+
@movies.sort.each do |movie|
|
33
|
+
# removed & replace with csv method implemented in movie class
|
34
|
+
# -> file.puts "#{movie.title}, #{movie.rank}"
|
35
|
+
file.puts movie.to_csv
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_movie(movie)
|
41
|
+
@movies << movie # append the 'movie' passed to the method to array
|
42
|
+
end
|
43
|
+
|
44
|
+
# added parameter 'viewings' as example for blocks. viewings being the number of times to play.
|
45
|
+
def play(viewings)
|
46
|
+
puts "#{@name}'s playlist:"
|
47
|
+
# this sort will use our spaceship override method (<=>) in movie
|
48
|
+
puts @movies.sort
|
49
|
+
|
50
|
+
# the following added after the Symbols&Structs video - see snack_bar.rb
|
51
|
+
snacks = SnackBar::SNACKS
|
52
|
+
puts "\nThere are #{snacks.size} snacks available in the Snack Bar."
|
53
|
+
# now, iterate through the snacks array and print them out as a menu.
|
54
|
+
snacks.each do |snack|
|
55
|
+
puts "#{snack.name} has #{snack.carbs} carbs."
|
56
|
+
end
|
57
|
+
|
58
|
+
1.upto(viewings) do |count|
|
59
|
+
puts "\nViewing #{count}:"
|
60
|
+
@movies.each do |movie|
|
61
|
+
WaldorfAndStatler.review(movie)
|
62
|
+
# added after Symbols&Struts - get a random snace with a movie viewing.
|
63
|
+
snack = SnackBar.random
|
64
|
+
# added with Hashes
|
65
|
+
movie.ate_snack(snack)
|
66
|
+
|
67
|
+
|
68
|
+
# took out on Hashes ->puts "#{movie.title} led to #{snack.carbs} #{snack.name} carbs being consumed."
|
69
|
+
|
70
|
+
puts movie
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def total_carbs_consumed
|
76
|
+
|
77
|
+
@movies.reduce(0) do |sum, movie|
|
78
|
+
sum + movie.carbs_consumed
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
def print_stats
|
85
|
+
puts "\n#{@name}'s Stats:"
|
86
|
+
|
87
|
+
puts "#{total_carbs_consumed} total cards consumed."
|
88
|
+
|
89
|
+
@movies.sort.each do |movie|
|
90
|
+
puts "\n#{movie.title}'s snack totals:"
|
91
|
+
# added in iterators - add a method 'each_snack' in movie class
|
92
|
+
movie.each_snack do |snack|
|
93
|
+
puts "#{snack.carbs} total #{snack.name} carbs"
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
puts "#{movie.carbs_consumed} grand total carbs."
|
98
|
+
end
|
99
|
+
|
100
|
+
hits, flops = @movies.partition { |movie| movie.hit? }
|
101
|
+
|
102
|
+
puts "\nHits:"
|
103
|
+
puts hits.sort
|
104
|
+
|
105
|
+
# when we call puts on an array it will call to_s on each of those elements
|
106
|
+
# => so the to_s method in movie will be called.
|
107
|
+
|
108
|
+
puts "\nFlops:"
|
109
|
+
puts flops.sort
|
110
|
+
end
|
111
|
+
|
112
|
+
end # -> of playlist class
|
113
|
+
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
end # -> of Flicks module
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
# below is tester code for the Movie & Playlist class
|
124
|
+
# '__FILE__' is the varible that holds the file name for this file
|
125
|
+
# '$0' is the varible that holds the file that is running.
|
126
|
+
# so this code only gets run when we run this file
|
127
|
+
# if this class is getting called from another program - it does not run
|
128
|
+
|
129
|
+
if __FILE__ == $0
|
130
|
+
|
131
|
+
# the .new method expects there to be an initialize method
|
132
|
+
movie1 = Flicks::Movie.new("goonies",10)
|
133
|
+
movie1.thumbs_down
|
134
|
+
puts movie1.listing
|
135
|
+
movie2 = Flicks::Movie.new("ghostbusters",9)
|
136
|
+
puts movie2.listing
|
137
|
+
movie3 = Flicks::Movie.new("goldfinger",100)
|
138
|
+
# below runs method that affects behaviour
|
139
|
+
movie3.thumbs_up
|
140
|
+
# allows access to current state.
|
141
|
+
puts movie3
|
142
|
+
# below made possible by attr_reader
|
143
|
+
puts movie3.title
|
144
|
+
puts movie3.rank
|
145
|
+
movie3.title = ("goonies 2.0")
|
146
|
+
puts movie3.title
|
147
|
+
puts movie3.normalized_rank
|
148
|
+
|
149
|
+
|
150
|
+
puts "begin object_interact code"
|
151
|
+
playlist1 = Flicks::Playlist.new("Kermit")
|
152
|
+
playlist1.add_movie(movie1)
|
153
|
+
playlist1.add_movie(movie2)
|
154
|
+
playlist1.add_movie(movie3)
|
155
|
+
playlist1.play(1)
|
156
|
+
|
157
|
+
# add another playlist
|
158
|
+
playlist2 = Flicks::Playlist.new("Fozzie")
|
159
|
+
# put a movie in that playlist
|
160
|
+
playlist2.add_movie(movie3)
|
161
|
+
|
162
|
+
# add a new move using the Movie class
|
163
|
+
movie4 = Flicks::Movie.new("Gremlins", 15)
|
164
|
+
|
165
|
+
# now add that movie to playlist2
|
166
|
+
playlist2.add_movie(movie4)
|
167
|
+
|
168
|
+
# and now play - which actually just displays the playlist
|
169
|
+
playlist2.play(1)
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
|
data/lib/rankable.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Flicks
|
2
|
+
module Rankable
|
3
|
+
|
4
|
+
# changed all the '@rank' to rank
|
5
|
+
# it is considered better to depend
|
6
|
+
# => on a method or an attribute rather than an instance varible in the host class.
|
7
|
+
|
8
|
+
def thumbs_up
|
9
|
+
self.rank += 1
|
10
|
+
end
|
11
|
+
|
12
|
+
def thumbs_down
|
13
|
+
self.rank -= 1
|
14
|
+
end
|
15
|
+
def hit?
|
16
|
+
self.rank >= 10
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def status
|
21
|
+
hit? ? "Hit" : "Flop"
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def normalized_rank
|
26
|
+
normalized_rank = self.rank / 1.0
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
# below we are going to override the spaceship comparison method.
|
32
|
+
# we changed the spaceship to just 'other' to make it more generic
|
33
|
+
def <=>(other)
|
34
|
+
# this will compare the passed in movie with the rank of the current movie.?? see sorting.rb
|
35
|
+
other.rank <=> self.rank
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
end # of module Rankable
|
40
|
+
end # of module Flicks
|
data/lib/snack_bar.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
|
2
|
+
# we could do the following class - but it may be overkill - we can just use a struct
|
3
|
+
|
4
|
+
# class Snack
|
5
|
+
# attr_reader :name, :carbs
|
6
|
+
|
7
|
+
# def initialize(name, carbs)
|
8
|
+
# @name = name
|
9
|
+
# @carbs = carbs
|
10
|
+
# end
|
11
|
+
|
12
|
+
# end
|
13
|
+
|
14
|
+
# the struct below will do the same thing
|
15
|
+
module Flicks
|
16
|
+
|
17
|
+
Snack = Struct.new(:name, :carbs)
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
# the Struct above could be in module but leave out for now
|
22
|
+
module SnackBar
|
23
|
+
|
24
|
+
# constant SNACKS array of Struct instances...
|
25
|
+
SNACKS = [
|
26
|
+
Snack.new(:popcorn, 20),
|
27
|
+
Snack.new(:candy, 15),
|
28
|
+
Snack.new(:nachos, 40),
|
29
|
+
Snack.new(:pretzel, 10),
|
30
|
+
Snack.new(:soda, 5)
|
31
|
+
]
|
32
|
+
|
33
|
+
# now we can add a method to our module that gets a random snack
|
34
|
+
# module methods start with self.
|
35
|
+
def self.random
|
36
|
+
|
37
|
+
# sample is a ruby method that gets a random element from an array.??? cool...
|
38
|
+
SNACKS.sample
|
39
|
+
end
|
40
|
+
|
41
|
+
end # of Snack Struct
|
42
|
+
end # of module Flicks
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
if __FILE__ == $0
|
50
|
+
|
51
|
+
|
52
|
+
# to get access, we use our module name, then the 'scope resolution operator' (::) then the constant.
|
53
|
+
|
54
|
+
popcorn = Snack.new('popcorn', 20)
|
55
|
+
puts popcorn.name
|
56
|
+
puts popcorn.carbs
|
57
|
+
|
58
|
+
candy = Snack.new('candy', 15)
|
59
|
+
puts candy.name
|
60
|
+
puts candy.carbs
|
61
|
+
|
62
|
+
puts SnackBar::SNACKS
|
63
|
+
|
64
|
+
snack = SnackBar.random
|
65
|
+
puts snack
|
66
|
+
puts "Enjoy your #{snack.name} (#{snack.carbs} carbs)."
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative 'movie'
|
2
|
+
|
3
|
+
module Flicks
|
4
|
+
|
5
|
+
module WaldorfAndStatler
|
6
|
+
|
7
|
+
# use modules when you don't need objects or state but rather
|
8
|
+
# -> methods that takes parameters such as objects
|
9
|
+
# use as a bucket of related methods
|
10
|
+
# also use as mixins and namespaces
|
11
|
+
|
12
|
+
# you can't instanstiate a module
|
13
|
+
|
14
|
+
# a method can be called from a class as an instance of the class
|
15
|
+
# but in a module, we can instanctiate so we have to add "self" to the method to be to call it.
|
16
|
+
# the self allows us to call it directely as below.
|
17
|
+
|
18
|
+
def self.review(movie)
|
19
|
+
number_rolled = roll_die
|
20
|
+
# in the playlist_spec file, we'll stub the number_rolled for testing
|
21
|
+
case number_rolled
|
22
|
+
when 1..2
|
23
|
+
movie.thumbs_down
|
24
|
+
puts "#{movie.title} got a thumbs down for a low roll."
|
25
|
+
when 3..4
|
26
|
+
puts "#{movie.title} was skipped."
|
27
|
+
else
|
28
|
+
movie.thumbs_up # reward for rolling 5 or better
|
29
|
+
puts "#{movie.title} got a thumbs up for rolling 5 or better!"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.roll_die
|
35
|
+
rand(1..6)
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
end # of module WaldorfAndStatler
|
40
|
+
end # of module Flicks
|
41
|
+
|
42
|
+
|
43
|
+
# WaldorfAndStatler.review
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'movie3d'
|
2
|
+
|
3
|
+
module Flicks
|
4
|
+
describe Movie3D do
|
5
|
+
before do
|
6
|
+
@initial_rank = 10
|
7
|
+
@wow_factor = 5
|
8
|
+
@movie = Movie3D.new('Glee', @initial_rank, @wow_factor)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "has a title" do
|
12
|
+
@movie.title.should == "Glee"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "has a rank" do
|
16
|
+
@movie.rank.should == 10
|
17
|
+
end
|
18
|
+
|
19
|
+
it "has a wow factor" do
|
20
|
+
@movie.wow_factor.should == 5
|
21
|
+
end
|
22
|
+
|
23
|
+
it "increases rank by 1 times the wow factor when given a thumbs up" do
|
24
|
+
@movie.thumbs_up
|
25
|
+
|
26
|
+
@movie.rank.should == @initial_rank + (1 * @wow_factor)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "decreases rank by 1 when given a thumbs down" do
|
30
|
+
@movie.thumbs_down
|
31
|
+
|
32
|
+
@movie.rank.should == @initial_rank - 1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/spec/movie_spec.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
# rspec convenction is to test class with file called "ClassName_spec.rb"
|
2
|
+
|
3
|
+
|
4
|
+
# the following will run all files in the current directory with _spec from the command line
|
5
|
+
# rspec . --color --format doc
|
6
|
+
|
7
|
+
|
8
|
+
# first thing is to requre class
|
9
|
+
|
10
|
+
require 'movie'
|
11
|
+
|
12
|
+
module Flicks
|
13
|
+
|
14
|
+
describe Movie do
|
15
|
+
|
16
|
+
before do
|
17
|
+
|
18
|
+
# we add the '@' to these varibles makeing them instance varibles so we can call them in the code.
|
19
|
+
@initial_rank = 10
|
20
|
+
@movie = Movie.new("goonies", @initial_rank)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "has a capitalized title" do
|
24
|
+
|
25
|
+
@movie.title.should == "Goonies"
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
it "has a rank of 10" do
|
30
|
+
|
31
|
+
@movie.rank.should == @initial_rank
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
it "has a string representation" do
|
36
|
+
|
37
|
+
@movie.to_s.should == "Goonies initialized with rank of #{@initial_rank/1.0} (Hit)."
|
38
|
+
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
it "increased rank by 1 when given a thumbs up" do
|
45
|
+
|
46
|
+
@movie.thumbs_up
|
47
|
+
|
48
|
+
@movie.rank.should == @initial_rank + 1
|
49
|
+
end
|
50
|
+
|
51
|
+
it "decreased rank by 1 when given a thumbs down" do
|
52
|
+
|
53
|
+
@movie.thumbs_down
|
54
|
+
|
55
|
+
@movie.rank.should == @initial_rank - 1
|
56
|
+
end
|
57
|
+
|
58
|
+
context "created with a default rank" do
|
59
|
+
before do
|
60
|
+
@movie = Movie.new("goonies")
|
61
|
+
end
|
62
|
+
|
63
|
+
it "has a rank of 0" do
|
64
|
+
@movie.rank.should == 0
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
context "with a rank of at least 10" do
|
70
|
+
before do
|
71
|
+
@movie = Movie.new("goonies", 10)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "is a hit" do
|
75
|
+
@movie.should be_hit # took out the .hit? - was be_true or == true
|
76
|
+
end
|
77
|
+
|
78
|
+
it "is a hit status" do
|
79
|
+
@movie.status.should == "Hit"
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
context "with a rank of less than 10" do
|
85
|
+
before do
|
86
|
+
@movie = Movie.new("goonies", 9)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "is NOT a hit" do
|
90
|
+
@movie.should_not be_hit # took out the .hit? without the _not - was be_false or == false
|
91
|
+
end
|
92
|
+
|
93
|
+
it "has a flop status" do
|
94
|
+
@movie.status.should == "Flop"
|
95
|
+
end
|
96
|
+
|
97
|
+
it "is sorted by decreasing rank" do
|
98
|
+
movie1 = Movie.new("goonies", 100)
|
99
|
+
movie2 = Movie.new("ghostbusters", 200)
|
100
|
+
movie3 = Movie.new("goldfinger", 300)
|
101
|
+
|
102
|
+
movies = [movie1, movie2, movie3]
|
103
|
+
|
104
|
+
movies.sort.should == [movie3, movie2, movie1]
|
105
|
+
end
|
106
|
+
|
107
|
+
it "computes carbs consumed as the sum of all snack carbs consumed" do
|
108
|
+
@movie.carbs_consumed.should == 0
|
109
|
+
|
110
|
+
@movie.ate_snack(Snack.new(:popcorn, 10))
|
111
|
+
|
112
|
+
@movie.carbs_consumed.should == 10
|
113
|
+
|
114
|
+
@movie.ate_snack(Snack.new(:popcorn, 10))
|
115
|
+
|
116
|
+
@movie.carbs_consumed.should == 20
|
117
|
+
|
118
|
+
@movie.ate_snack(Snack.new(:soda, 5))
|
119
|
+
|
120
|
+
@movie.carbs_consumed.should == 25
|
121
|
+
end
|
122
|
+
|
123
|
+
it "yields each snack" do
|
124
|
+
@movie.ate_snack(Snack.new(:popcorn, 10))
|
125
|
+
@movie.ate_snack(Snack.new(:popcorn, 10))
|
126
|
+
@movie.ate_snack(Snack.new(:soda, 5))
|
127
|
+
|
128
|
+
yielded = []
|
129
|
+
@movie.each_snack do |snack|
|
130
|
+
yielded << snack
|
131
|
+
end
|
132
|
+
|
133
|
+
yielded.should == [Snack.new(:popcorn, 20), Snack.new(:soda, 5)]
|
134
|
+
end
|
135
|
+
|
136
|
+
it "can be instantiated from a CSV string" do
|
137
|
+
movie = Movie.from_csv("goonies,10")
|
138
|
+
|
139
|
+
movie.title.should == "Goonies"
|
140
|
+
movie.rank.should == 10
|
141
|
+
end
|
142
|
+
|
143
|
+
it "can be serialized to a CSV string" do
|
144
|
+
movie = Movie.new("Goonies", 10)
|
145
|
+
|
146
|
+
movie.to_csv.should == "Goonies, 10"
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
end # of describe
|
152
|
+
|
153
|
+
end # of Flicks module
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'playlist'
|
2
|
+
|
3
|
+
module Flicks
|
4
|
+
|
5
|
+
# the following will run all files in the current directory with _spec from the command line
|
6
|
+
# rspec . --color --format doc
|
7
|
+
|
8
|
+
describe Playlist do
|
9
|
+
before do
|
10
|
+
@playlist = Playlist.new("Bobby")
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
it "has a name" do
|
15
|
+
@playlist.name.should == "Bobby"
|
16
|
+
end
|
17
|
+
|
18
|
+
context "being played with one movie" do
|
19
|
+
before do
|
20
|
+
@initial_rank = 10
|
21
|
+
@movie = Movie.new("goonies", @initial_rank)
|
22
|
+
@playlist.add_movie(@movie)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "gives the movie a thumbs up if a high number is rolled" do
|
26
|
+
# stub the roll_die method for testing since we don't want the random number for the test.
|
27
|
+
WaldorfAndStatler.stub(:roll_die).and_return(6)
|
28
|
+
|
29
|
+
@playlist.play(2)
|
30
|
+
|
31
|
+
@movie.rank.should == @initial_rank + 2
|
32
|
+
|
33
|
+
WaldorfAndStatler.stub(:roll_die).and_return(5)
|
34
|
+
@playlist.play(2)
|
35
|
+
@movie.rank.should == @initial_rank + 4
|
36
|
+
end
|
37
|
+
|
38
|
+
it "skips the movie if a medium number is rolled" do
|
39
|
+
WaldorfAndStatler.stub(:roll_die).and_return(4)
|
40
|
+
|
41
|
+
@playlist.play(2)
|
42
|
+
|
43
|
+
@movie.rank.should == @initial_rank
|
44
|
+
WaldorfAndStatler.stub(:roll_die).and_return(3)
|
45
|
+
@playlist.play(2)
|
46
|
+
@movie.rank.should == @initial_rank
|
47
|
+
end
|
48
|
+
|
49
|
+
it "gives the movie a thumbs down if a low number is rolled" do
|
50
|
+
WaldorfAndStatler.stub(:roll_die).and_return(2)
|
51
|
+
@playlist.play(2)
|
52
|
+
@movie.rank.should == @initial_rank - 2
|
53
|
+
|
54
|
+
WaldorfAndStatler.stub(:roll_die).and_return(1)
|
55
|
+
@playlist.play(2)
|
56
|
+
@movie.rank.should == @initial_rank - 4
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
end # -> of Describe Playlist
|
63
|
+
|
64
|
+
end # -> of Flicks module
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'snack_bar'
|
2
|
+
|
3
|
+
module Flicks
|
4
|
+
describe Snack do
|
5
|
+
before do
|
6
|
+
@snack = Snack.new(:pretzel, 10)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "has a name attribute" do
|
10
|
+
@snack.name.should == :pretzel
|
11
|
+
end
|
12
|
+
|
13
|
+
it "has a carbs attribute" do
|
14
|
+
@snack.carbs.should == 10
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Flicks
|
21
|
+
describe SnackBar do
|
22
|
+
it "has a trove of treasures" do
|
23
|
+
SnackBar::SNACKS.should_not be_empty
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns a random treasure" do
|
27
|
+
snack = SnackBar.random
|
28
|
+
|
29
|
+
SnackBar::SNACKS.should include(snack)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rms_flicks
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Pragmatic Studio student
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: ! "This is an example application used in The Pragmatic Studio's \nRuby
|
31
|
+
Programming course, as described at\n\n http://pragmaticstudio.com\n\nThis code
|
32
|
+
is Copyright 2012 The Pragmatic Studio. See the LICENSE file."
|
33
|
+
email: rmckinleys@gmail.com
|
34
|
+
executables:
|
35
|
+
- flicks
|
36
|
+
extensions: []
|
37
|
+
extra_rdoc_files: []
|
38
|
+
files:
|
39
|
+
- bin/flicks
|
40
|
+
- bin/movie_rankings.csv
|
41
|
+
- bin/movies.csv
|
42
|
+
- lib/movie.rb
|
43
|
+
- lib/movie3d.rb
|
44
|
+
- lib/playlist.rb
|
45
|
+
- lib/rankable.rb
|
46
|
+
- lib/snack_bar.rb
|
47
|
+
- lib/waldorf_and_statler.rb
|
48
|
+
- spec/movie3d_spec.rb
|
49
|
+
- spec/movie_spec.rb
|
50
|
+
- spec/playlist_spec.rb
|
51
|
+
- spec/snack_bar_spec.rb
|
52
|
+
- LICENSE
|
53
|
+
- README
|
54
|
+
homepage: http://pragmaticstudio.com
|
55
|
+
licenses: []
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '1.9'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 1.8.24
|
75
|
+
signing_key:
|
76
|
+
specification_version: 3
|
77
|
+
summary: Plays and reviews movies
|
78
|
+
test_files:
|
79
|
+
- spec/movie3d_spec.rb
|
80
|
+
- spec/movie_spec.rb
|
81
|
+
- spec/playlist_spec.rb
|
82
|
+
- spec/snack_bar_spec.rb
|