songfile 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7df1397b9db1fa3f47f171ffb299e5bf1adb4cf13c79a46d530d38ca8bf3c827
4
+ data.tar.gz: a7fc63446d0eb7e1d0dd62e3e2e07acada88837d7c79df54fc6a0ed19eefdf82
5
+ SHA512:
6
+ metadata.gz: e6d6bbef6b0464361f0c01d50f33d1e2a552ca911c9a427f1cd34d763ab953d760af6640ccb717b642870ea040677e08851acb4976f1504cff7c2b134be4459b
7
+ data.tar.gz: 46c141fa5607114913b52f9dbf8e31080ecf31e19ff09ae5a21aed71b06e278025f3c32e3d649e26234f451cf1bd072779757e3e566843baf5b40428100120c0
data/LICENSE.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2022 Jamie Clark / 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
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.txt ADDED
@@ -0,0 +1,9 @@
1
+ ************************************** BASIC INSTRUCTIONS **************************************
2
+ TO RUN DEFAULT CSV SHEET (THE WALL)):
3
+ ruby bin/songfile
4
+
5
+ TO RUN DARK SIDE OF THE MOON ALBUM SONGS
6
+ ruby bin/songfile bin/DSOTM.csv
7
+
8
+ TO RUN SPECS:
9
+ rspec (not "rspec .")
data/bin/DSOTM.csv ADDED
@@ -0,0 +1,10 @@
1
+ Speak to Me,1000
2
+ Breathe,500
3
+ On the Run,900
4
+ Time,300
5
+ The Great Gig in the Sky,100
6
+ Money,200
7
+ Us and Them,400
8
+ Any Colour You Like,800
9
+ Brain Damage,700
10
+ Eclipse,600
data/bin/THE_WALL.csv ADDED
@@ -0,0 +1,13 @@
1
+ In the Flesh?,100
2
+ Vera,200
3
+ Hey You,300
4
+ Run Like Hell,400
5
+ Comfortably Numb,500
6
+ Pigs on the Wing,600
7
+ Another Brick in the Wall Part 1,700
8
+ Is There Anybody Out There?,800
9
+ The Trial,900
10
+ Stop,1000
11
+ Goodbye Blue Sky, 1100
12
+ Young Lust,
13
+ Nobody Home,
data/bin/songfile ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+ #(File created 9:47pm on 5/8/22)
3
+ #end of day one is 8:24pm-10:47pm 5/8/22
4
+ #day two is 5:45pm - .... 9pm 5/24/22
5
+ #day three is 9:55pm - .... 11:15pm 6/8/22 (oof)
6
+ #day four is 7:30pm - 8:30pm, resumed at 9:40pm - 1am 6/14/22
7
+ #day five is 12:45pm - 1:30pm before work 6/15/22
8
+ #day six is 12am - 7:05pm 7 hours straight 6/18/22
9
+ #day seven is 4:30pm - 8:15pm and 10pm - 12:30am 6/19/22
10
+ #day eight is 8:55pm - 11:45pm 6/20/22
11
+ #day nine is 11:47pm - 5:34am!! 6/22/22 (night)
12
+ #day ten is 8:08pm - 12:24am and 12:50am - 3:30am 6/22/22 (day)
13
+
14
+ require_relative '../lib/songfile/playlist' # calls the playlist class file
15
+ require_relative '../lib/songfile/song' # calls the song class file
16
+ require_relative '../lib/songfile/die'
17
+ require_relative '../lib/songfile/council'
18
+ require_relative '../lib/songfile/classic_song'
19
+
20
+ # (technically require_relative 'song' isnt needed here as well since it is referenced within the playlist file already)
21
+
22
+ my_list = Songfile::Playlist.new("Jamie's Pink Floyd Playlist")
23
+ default_player_file = File.join(File.dirname(__FILE__), "THE_WALL.csv") #plays an entered file OR the default (WALL.csv)
24
+ my_list.load_songs(ARGV.shift || default_player_file)
25
+
26
+ #Lines 28 and 29 can be uncommented to add a "classic song" from within the driving program file!
27
+ #classic_song = Songfile::ClassicSong.new("Time") #default rank of 10000 assigned bc not specified, then halved bc it is a ClassicSong
28
+ #my_list.add_song(classic_song)
29
+
30
+ loop do
31
+ puts "\nHow many rounds? ('quit' to exit)"
32
+ ans = gets.chomp.downcase
33
+
34
+ case ans
35
+ when /^\d+$/
36
+ if ans.to_i > 20
37
+ puts "ERROR: Maximum number of rounds allowed: 20." # I will set a limit to 20 rounds
38
+ else
39
+ my_list.play(ans.to_i) # converts to integer
40
+ end
41
+ when 'quit', 'exit', 'q', 'e', 'ex'
42
+ my_list.print_stats # currently, this must be called SEPARATELY, not from within the "play" method to get the tests to pass
43
+ break
44
+ else
45
+ puts "Please enter a number or 'quit'"
46
+ end
47
+ end
48
+
49
+ my_list.save_output #this goes after the loop
50
+
51
+ # my_list.show_titles
52
+ # ^ shows titles in the "array" format using "p"
53
+
54
+
55
+
@@ -0,0 +1,18 @@
1
+ require_relative 'song'
2
+ module Songfile
3
+ class ClassicSong < Song
4
+ attr_reader :initial_rank
5
+ def initialize(title, rank=10000)
6
+ @initial_rank = rank
7
+ @title = titleize(title)
8
+ @rank = (rank.abs()) / 2
9
+ puts "New song '#{@title}' (classic) with rank of #{@rank} was created."
10
+ # puts "The classic song '#{@title}' jumps the chart with a halved rank !"
11
+ end
12
+ end
13
+
14
+ if __FILE__ == $0
15
+ classic_song = ClassicSong.new("Time", 10000)
16
+ # puts "The classic song '#{classic_song.title}' jumps the chart with a halved rank (#{classic_song.initial_rank}/2) of #{classic_song.rank}!"
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ module Songfile #< this line nested on TOP of Reviewer = Struct.new
2
+ Reviewer = Struct.new(:name, :influence) #bigger number means more influence (I use them as multiplier values)
3
+ module Council
4
+ REVIEWERS = [
5
+ Reviewer.new(:Roger_Waters, 100),
6
+ Reviewer.new(:Nick_Mason, 50),
7
+ Reviewer.new(:David_Gilmour, 100),
8
+ Reviewer.new(:Richard_Wright, 50),
9
+ Reviewer.new(:Syd_Barrett, 25)
10
+ ]
11
+
12
+ def self.random
13
+ REVIEWERS.sample
14
+ end
15
+ end
16
+
17
+ if __FILE__ == $0
18
+ p Council::REVIEWERS.map(&:name)
19
+ person = Council.random
20
+ puts "#{person.name} is reviewing your playlist."
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ module Songfile
2
+ class Die
3
+ attr_reader :number
4
+
5
+ def roll
6
+ @number = rand(1..6)
7
+ end
8
+
9
+ def initialize
10
+ roll #the new die object now initializes as soon as "roll" is called anywhere.
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,159 @@
1
+ require_relative 'song'
2
+ require_relative 'die'
3
+ require_relative 'playlist_turn'
4
+ require_relative 'council'
5
+ require 'csv'
6
+ module Songfile
7
+ class Playlist
8
+ attr_reader :name, :list #you can read the title (name) of the playlist
9
+ def initialize(name) #this method converts a Playlist.new specified title to the correct format when created
10
+ @name = name.upcase #upcased all playlist titles for now
11
+ @list = []
12
+ puts "Playlist '#{@name}' was created."
13
+ end
14
+
15
+ def show_titles
16
+ p self.list.map(&:title) # p is used within the method to print the array properly, and it is only an array of titles
17
+ end
18
+
19
+ def show_reviewers
20
+ reviewers = Council::REVIEWERS
21
+ puts "\nThere are #{reviewers.size} playlist reviewers:"
22
+ reviewers.each do |r|
23
+ puts "#{r.name}, #{r.influence}"
24
+ end
25
+ end
26
+
27
+ def add_song(song) #when you add a song, the list re-sorts itself
28
+ @list << song
29
+ @list = @list.sort { |a, b| a.rank <=> b.rank } #this line is critical to have so that original song order by rank is displayed by the text output!
30
+ @original_list = @list # whenever a song is added, the list is stored
31
+ # NOTE: ^^ I disabled the list sorting itself whenever a new song is added. All the responsibility is
32
+ # now handed over to the sort songs method which 1) sorts all songs in array by rank then
33
+ # normalizes the rank values based on the amount of songs in the playlist!
34
+ end
35
+
36
+ def sort_songs #created this method... it looks very similar to the print_stats method
37
+ @list.each do |song| #sort by rank step 1
38
+ @list = @list.sort { |a, b| a.rank <=> b.rank }
39
+ end
40
+ end
41
+ def normalize_ranks
42
+ @list.each do |song| #step 2 (after ALL songs are sorted by rank)
43
+ song.rank = @list.index(song) + 1 # NOW you normalize rank once all songs are sorted
44
+ #song.rank = @list.index(song) + 1 # NOW you normalize rank once all songs are sorted
45
+ # puts "#{song.rank}) #{song.title}"
46
+ end
47
+ end
48
+ def multiply_ranks
49
+ @list.each do |song| #step 2 (after ALL songs are sorted by rank)
50
+ song.rank *= 10 # multiplies each song's rank by 10. This method is used after "normalize ranks" in the play method
51
+ end
52
+ end
53
+
54
+
55
+ def play(rounds=1) #play one round by default
56
+ puts "\nThere are #{@list.size} songs in this playlist:"
57
+ sort_songs # use of SELF to call sort_songs on the applicable Playlist object from inside the play method
58
+ normalize_ranks # is now separate from sorting songs
59
+ @list.each do |song|
60
+ puts "#{song.rank}) #{song.title}"
61
+ end
62
+
63
+ multiply_ranks
64
+
65
+ show_reviewers # this method is standalone, no reference to self is needed
66
+
67
+ 1.upto(rounds) do |round|
68
+ puts "\nRound #{round}:"
69
+ # puts "number rolled is #{number_rolled}"
70
+ @list.each do |song|
71
+ puts song
72
+ PlaylistTurn.take_turn(song)
73
+ puts song
74
+ end
75
+ end
76
+
77
+ #self.print_stats #activating this code will make two tests fail because sort/normalization is
78
+ #performed within the print stats method which, when enabled INSIDE the "play" method
79
+ #makes the math check test fail! (activating this code sorts/normalizes the new ranks
80
+ #before the math checker is run, aka after the "play" method is completed)
81
+ end
82
+
83
+ def print_stats
84
+ sort_songs # FIRST SORT FOR PREVIEW/DISPLAY
85
+ puts "\n#{@name} Final Rankings:"
86
+ @list.each do |song|
87
+ puts "#{song.title} (#{song.rank})"
88
+ end
89
+
90
+ puts "\nOriginal list order:"
91
+ @original_list.each do |song|
92
+ puts "#{@original_list.index(song) + 1}) #{song.title}"
93
+ end
94
+
95
+ normalize_ranks # NOW NORMALIZE RANKINGS
96
+
97
+ top_ten_songs, average_songs = @list.partition { |song| song.top_ten? }
98
+ puts "\nNew list order:"
99
+ if @list.size > 10
100
+ puts "Top 10 Songs:"
101
+ top_ten_songs.each do |song|
102
+ puts "#{song.rank}) #{song.title}"
103
+ end
104
+ puts "\nOther Songs:"
105
+ average_songs.each do |song|
106
+ puts "#{song.rank}) #{song.title}"
107
+ end
108
+ else
109
+ puts "\nTop #{@list.size} Songs:"
110
+ @list.each do |song|
111
+ puts "#{song.rank}) #{song.title}"
112
+ end
113
+ end
114
+ end
115
+
116
+ def load_songs(from_file)
117
+ CSV.foreach(from_file, 'r:bom|utf-8') do |row|
118
+ if row[1].to_i == 0
119
+ song = Song.new(row[0], 10000) # THIS is the code that sets nil to 10000 by default so that sorted song is ranked last in playlist
120
+ else
121
+ song = Song.new(row[0], row[1].to_i)# << this "index" stuff syntax allows for nil ranks to "pass/fly" (and get reassigned to default of 0) THIS is where default gets assigned.
122
+
123
+ end
124
+ add_song(song)
125
+ end
126
+ end
127
+ def save_output(to_file="songfile_output.txt")
128
+ File.open(to_file, "w") do |file|
129
+ file.puts Time.new.strftime("File updated on %m/%d/%Y at %I:%M %p")
130
+ file.puts "\nOriginal list order:"
131
+ @original_list.each do |song|
132
+ file.puts "#{@original_list.index(song) + 1}) #{song.title}"
133
+ end
134
+ file.puts "\nNew list order:"
135
+
136
+ top_ten_songs, average_songs = @list.partition { |song| song.top_ten? }
137
+
138
+ if @list.size > 10
139
+ file.puts "Top 10 Songs:" # literally copied from print stats but with "file.puts" not "puts"
140
+ top_ten_songs.each do |song|
141
+ file.puts "#{song.rank}) #{song.title}"
142
+ end
143
+ file.puts "\nOther Songs:"
144
+ average_songs.each do |song|
145
+ file.puts "#{song.rank}) #{song.title}"
146
+ end
147
+ else
148
+ file.puts "\nTop #{@list.size} Songs:"
149
+ @list.each do |song|
150
+ file.puts "#{song.rank}) #{song.title}"
151
+ end
152
+ end
153
+
154
+ end
155
+
156
+ end
157
+
158
+ end
159
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'song'
2
+ require_relative 'die'
3
+ require_relative 'council'
4
+ module Songfile
5
+ module PlaylistTurn
6
+
7
+ def self.take_turn(song)
8
+
9
+ reviewer = Council.random
10
+ #puts reviewer
11
+ puts "'#{song.title}' was reviewed by #{reviewer.name} (#{reviewer.influence} influence)"
12
+
13
+ die = Die.new
14
+ number_rolled = die.roll
15
+ case number_rolled
16
+ when 5..6
17
+ song.thumbs_up(reviewer.influence)
18
+ when 3..4
19
+ puts "'#{song.title}' was skipped."
20
+ when 1..2
21
+ song.thumbs_down(reviewer.influence)
22
+ else # (nothing is added if die roll is 3 or 4... or 0 etc.)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,78 @@
1
+ require_relative 'playlist'
2
+ # set Lowercase_words to be a global variable bc the warning was annoying!
3
+ # the warning in question: "warning: already initialized constant Lowercase_words"
4
+
5
+ $Lowercase_words = %w{and as at but by for from
6
+ if in into like near nor of off on once
7
+ onto or over past so than that the till
8
+ to up upon v. vs vs. with when yet}
9
+ module Songfile
10
+ class Song
11
+ #attr_reader :rank # allows you to print the "rank" attribute outside the Song class (GETTER method)
12
+ # attr_writer :title, :rank # allows you to write to the "title" and "rank" attributes outside the Song class (SETTER method)
13
+ attr_accessor :title, :rank # allows you to read and write to "title" and "rank" attribute outside the Song class
14
+
15
+ def titleize(title) #the actual titleize method (only hangup is "Like" (as a verb) vs "like" (as a preposition))
16
+ title.downcase.split.each_with_index.map{ |x, index| $Lowercase_words.include?(x) && index > 0 ? x : x.capitalize }.join(" ")
17
+ end
18
+
19
+ def initialize(title, rank=10000) #this method converts a Song.new specified title to the correct format when created
20
+ @title = titleize(title)
21
+ @rank = rank.abs() # the absolute value prevents anyone from typing in a NEGATIVE rank
22
+ puts "New song '#{@title}' with rank of #{@rank} was created."
23
+ end
24
+
25
+ def title=(new_title) #this method converts a Song.new specified title to the correct format when overwritten
26
+ @title = new_title
27
+ @title = titleize(@title)
28
+ end
29
+
30
+ def thumbs_up(value=1)
31
+ @rank -= value
32
+ puts "'#{@title}' received a thumbs up!"
33
+ end
34
+
35
+ def thumbs_down(value=1)
36
+ @rank += value
37
+ puts "'#{@title}' received a thumbs down!"
38
+ end
39
+
40
+ def describe
41
+ puts "'#{@title}' has a rank of #{@rank}."
42
+ end
43
+
44
+ def top_ten?
45
+ result = case @rank
46
+ when 1..10 then true
47
+ end
48
+ end
49
+
50
+ def status
51
+ top_ten? ? "*Top 10*" : "*Not Top 10*"
52
+ end
53
+
54
+ def to_s #defines what happens when you use puts on an object of class "Song"
55
+ "#{@title} (#{@rank})"
56
+ #"#{@title} (#{@rank}) #{status}"
57
+ #^^REMOVING "top 10" classification while the score is still computing!
58
+ end
59
+ end
60
+
61
+ #code that only runs inside THIS file (songfile.rb relies only on the class code and ignores this if statement code)
62
+ if __FILE__ == $0
63
+ song1 = Song.new("Run like Hell", 4)
64
+ song2 = Song.new("The Trial", 1)
65
+ song3 = Song.new("Outside the Wall", 11)
66
+ array = [song1, song2, song3]
67
+ array.each do |song|
68
+ puts song
69
+ song.describe
70
+ song.thumbs_up
71
+ song.thumbs_up
72
+ song.thumbs_down
73
+ song.thumbs_up
74
+ puts song
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,52 @@
1
+ # require_relative "council"
2
+ require 'songfile/council'
3
+ module Songfile
4
+ describe Reviewer do
5
+
6
+ before do
7
+ @reviewer = Reviewer.new(:Tre_Cool, 49)
8
+ end
9
+
10
+ it "has a name attribute" do
11
+ @reviewer.name.should == :Tre_Cool
12
+ end
13
+
14
+ it "has a correct influence (age in this case) attribute" do
15
+ @reviewer.influence.should == 49
16
+ end
17
+
18
+ end
19
+
20
+ describe Council do
21
+
22
+ it "returns a random reviewer from the council" do
23
+ reviewer = Council.random
24
+ Council::REVIEWERS.should include(reviewer)
25
+ end
26
+
27
+ it "has five reviewers" do
28
+ Council::REVIEWERS.size.should == 5
29
+ end
30
+
31
+ it "has Roger Waters (100)" do
32
+ Council::REVIEWERS[0].should == Reviewer.new(:Roger_Waters, 100)
33
+ end
34
+
35
+ it "has Nick Mason (50)" do
36
+ Council::REVIEWERS[1].should == Reviewer.new(:Nick_Mason, 50)
37
+ end
38
+
39
+ it "has David_Gilmour (100)" do
40
+ Council::REVIEWERS[2].should == Reviewer.new(:David_Gilmour, 100)
41
+ end
42
+
43
+ it "has Richard_Wright (50)" do
44
+ Council::REVIEWERS[3].should == Reviewer.new(:Richard_Wright, 50)
45
+ end
46
+
47
+ it "Syd_Barrett (25)" do
48
+ Council::REVIEWERS[4].should == Reviewer.new(:Syd_Barrett, 25)
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,108 @@
1
+ # require_relative "playlist"
2
+ require 'songfile/playlist'
3
+ # require_relative "die"
4
+ require 'songfile/die'
5
+ # require_relative "council"
6
+ require 'songfile/council'
7
+ module Songfile
8
+ describe Playlist do
9
+
10
+ before do
11
+ @playlist = Playlist.new("test playlist")
12
+ end
13
+
14
+ context "single song playlist" do
15
+
16
+ before do
17
+ @initial_rank = -10
18
+ @song = Song.new("the happiest days of our lives", @initial_rank)
19
+ @initial_rank = @song.rank #this line had to be added to update the @inital rank
20
+ #variable in the test file so that it is updated to reflect the initialization of the "rank" attribute
21
+ #of the project (which changes negative values to their absolute value versions!)
22
+ @playlist.add_song(@song)
23
+ @round_amount = 2 # you only need to change the test in one place (this line)
24
+ # to run different number of rounds in the spec file!
25
+ end
26
+
27
+ it "initial rank gets converted to a positive value" do # kind of a "duplicate" test from the one in song_spec.rb
28
+ # expect(@song.rank).to eq(@initial_rank.abs())
29
+ expect(@song.rank).to eq(10)
30
+ end
31
+
32
+ it "initial rank gets normalized correctly" do # not a duplicate test, this tests the normalize and multiplier methods
33
+ # expect(@song.rank).to eq(@initial_rank.abs())
34
+ @playlist.sort_songs
35
+ @playlist.normalize_ranks
36
+ expect(@song.rank).to eq(1)
37
+ end
38
+
39
+ it "initial rank gets normalized and multiplied correctly" do # not a duplicate test, this tests the normalize and multiplier methods
40
+ # expect(@song.rank).to eq(@initial_rank.abs())
41
+ @playlist.sort_songs
42
+ @playlist.normalize_ranks
43
+ @playlist.multiply_ranks
44
+ expect(@song.rank).to eq(10)
45
+ end
46
+
47
+ it "thumbs up on high number (5-6)" do
48
+ Die.any_instance.stub(:roll).and_return(5)
49
+ allow(Council).to receive(:random).and_return(Council::REVIEWERS[0]) # FINALLY got the right code to retrieve roger each roll!
50
+ @playlist.play(@round_amount)
51
+ expect(@song.rank).to eq((10) - (100 * @round_amount)) # the (100) represents the new ranking (normalized and multiplied) of the only song in the list
52
+ end # thumbs down makes rank number smaller therefore higher on list!
53
+
54
+ it "no change on medium number (3-4)" do
55
+ Die.any_instance.stub(:roll).and_return(3)
56
+ @playlist.play(@round_amount)
57
+ expect(@song.rank).to eq((10)) # 10: The one song in the playlist gets a normalized rank of 1 which gets multiplied to 10.
58
+ end
59
+
60
+ it "thumbs down on low number (1-2)" do
61
+ Die.any_instance.stub(:roll).and_return(1)
62
+ allow(Council).to receive(:random).and_return(Council::REVIEWERS[0])
63
+ @playlist.play(@round_amount)
64
+ expect(@song.rank).to eq((10) + (100 * @round_amount)) # the (10) represents the new ranking (normalized and multiplied) of the only song in the list
65
+ end # thumbs down makes rank bigger therefore lower on list!
66
+ end
67
+
68
+ context "multiple song playlist" do
69
+ before do
70
+ @song1 = Song.new("In the Flesh?", 500) # middle song, should come out to rank = 2
71
+ @song2 = Song.new("Vera", 1000) # last song, should come out to rank = 3
72
+ @song3 = Song.new("Comfortably Numb", 25) # top song, should come out to rank = 1
73
+
74
+ @playlist.add_song(@song1)
75
+ @playlist.add_song(@song2)
76
+ @playlist.add_song(@song3)
77
+
78
+ @playlist.sort_songs #this method sorts before running the game!
79
+ @playlist.normalize_ranks #this normalizes the ranks to the array size
80
+ end
81
+
82
+ it "all three songs are correctly sorted in the playlist" do
83
+ expect(@playlist.show_titles).to eq(["Comfortably Numb", "In the Flesh?", "Vera"])
84
+ end
85
+
86
+ it "all three songs are correctly ranked" do
87
+ expect(@song1.rank).to eq(2)
88
+ expect(@song2.rank).to eq(3)
89
+ expect(@song3.rank).to eq(1)
90
+ end
91
+
92
+ end
93
+
94
+ context "default values replacing nils (multiple song playlist)" do
95
+ before do
96
+ @my_list = Playlist.new("Jamie's Pink Floyd Playlist")
97
+
98
+ default_player_file = File.join(File.dirname(__FILE__), "../../bin/THE_WALL.csv") #plays an entered file OR the default (WALL.csv)
99
+ @my_list.load_songs(ARGV.shift || default_player_file)
100
+ end
101
+
102
+ it "replaces nil rank values with default value of 10000" do
103
+ expect(@my_list.list[11].rank).to eq(10000) # "young lust" correctly gets assigned default rank of 10000
104
+ end
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,80 @@
1
+ # ***** SONG TEST FILE *******
2
+ # require_relative 'song' # calls the song class file
3
+ require 'songfile/song'
4
+
5
+ module Songfile
6
+ describe Song do
7
+
8
+ context "song with a NEGATIVE ranking" do
9
+ before do
10
+ @song = Song.new("the happiest days of our lives", -10) # a user types in a negative rank (not ok)
11
+ end
12
+
13
+ it "automatically gets a negative rank # assigned to a positive rank #" do
14
+ expect(@song.rank).to eq(10) #rather than -10
15
+ end
16
+ end
17
+
18
+ context "default ranking song" do
19
+ before do
20
+ @initial_rank = 0
21
+ @song = Song.new("the happiest days of our lives")
22
+ end
23
+
24
+ it "has a default rank of 10000" do
25
+ #song.rank.should == 10000
26
+ @song = Song.new("the happiest days of our lives")
27
+ expect(@song.rank).to eq(10000) #Changed default to 10000 so UNRANKED songs are listed lowest in the playlist (assuming other RANKED songs are < 10000)
28
+ end
29
+
30
+ it "IS NOT a top 10 song" do
31
+ expect(@song.status).to eq("*Not Top 10*")
32
+ end
33
+ end
34
+
35
+ before do
36
+ @initial_rank = 10
37
+ @song = Song.new("the happiest days of our lives", @initial_rank)
38
+ end
39
+
40
+ it "has a capitalized title" do
41
+ #song.title.should == "The Happiest Days of Our Lives"
42
+ expect(@song.title).to eq("The Happiest Days of Our Lives") #better, new syntax
43
+ end
44
+
45
+ it "has an initial rank" do
46
+ #song.title.should == "The Happiest Days of Our Lives"
47
+ expect(@song.rank).to eq(10) #better, new syntax
48
+ expect(@initial_rank).to eq(10) #better, new syntax
49
+ end
50
+
51
+ it "has correct description" do
52
+ expect do
53
+ @song.describe
54
+ end.to output("'#{@song.title}' has a rank of #{@song.rank}.\n").to_stdout
55
+ end
56
+
57
+ it "has correct display with 'to_s' (Song)" do
58
+ expect(@song.to_s).to eq("The Happiest Days of Our Lives (10)") #removed *top 10* display from to_s method
59
+ end
60
+
61
+ it "has correct status" do
62
+ expect(@song.status).to eq("*Top 10*")
63
+ end
64
+
65
+ it "has correct rank after thumbs up" do
66
+ @song.thumbs_up
67
+ expect(@song.rank).to eq(9)
68
+ end
69
+
70
+ it "has correct rank after thumbs down" do
71
+ @song.thumbs_down
72
+ expect(@song.rank).to eq(11)
73
+ end
74
+
75
+ it "IS a top 10 song" do
76
+ expect(@song.status).to eq("*Top 10*")
77
+ end
78
+
79
+ end
80
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: songfile
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jamie Clark
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-06-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.8'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.8.0
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.8'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.8.0
33
+ description: |
34
+ ************************************** BASIC INSTRUCTIONS **************************************
35
+ TO RUN DEFAULT CSV SHEET (THE WALL)):
36
+ ruby bin/songfile
37
+
38
+ TO RUN DARK SIDE OF THE MOON ALBUM SONGS
39
+ ruby bin/songfile bin/DSOTM.csv
40
+
41
+ TO RUN SPECS:
42
+ rspec (not "rspec .")
43
+ email: clarkcjamie@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - LICENSE.txt
49
+ - README.txt
50
+ - bin/DSOTM.csv
51
+ - bin/THE_WALL.csv
52
+ - bin/songfile
53
+ - lib/songfile/classic_song.rb
54
+ - lib/songfile/council.rb
55
+ - lib/songfile/die.rb
56
+ - lib/songfile/playlist.rb
57
+ - lib/songfile/playlist_turn.rb
58
+ - lib/songfile/song.rb
59
+ - spec/songfile/council_spec.rb
60
+ - spec/songfile/playlist_spec.rb
61
+ - spec/songfile/song_spec.rb
62
+ homepage: http://pragmaticstudio.com
63
+ licenses:
64
+ - MIT
65
+ metadata: {}
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '1.9'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubygems_version: 3.3.7
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: Text based game for ranking music playlists featuring multiple rounds, a
85
+ panel of reviewers from Pink Floyd, and output of the newly ranked playlist.
86
+ test_files:
87
+ - spec/songfile/council_spec.rb
88
+ - spec/songfile/playlist_spec.rb
89
+ - spec/songfile/song_spec.rb