billboard_hot_100_songs 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d02f8c6935da7202950e690659b6c7e3951cf8355144df4ddf5fc39a9adcdcc5
4
+ data.tar.gz: 8c5aecbc238314d09beaca3635cdf85b1f3b2f748dd1840de63204b3f3400eba
5
+ SHA512:
6
+ metadata.gz: 10de20cfaa4ffb74f7a80ab153b8739bf2e2837b6bb4bdeecc5331c9f91309bc14ac445236ca0a4caf5641f724f2543f810724b4dbd705aa7dc8416f45801a35
7
+ data.tar.gz: 1a86ce54aae34152bca8c2e64f438bd78f79dbe4b67aaf01a5da7edcc3cd6717ffa43623f7c86ed7be8ae671a91ae4a7a9a4f5d1f39b91adfb40f56a1c125891
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,6 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 2.6.1
6
+ before_install: gem install bundler -v 2.1.4
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at alexander.clamor@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [https://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: https://contributor-covenant.org
74
+ [version]: https://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "rake", "~> 12.0"
6
+ gem "rspec", "~> 3.0"
7
+ gem "colorize"
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Alexander M. Clamor
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ 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.
@@ -0,0 +1,206 @@
1
+ NOTES
2
+
3
+ ♪ THE USER: People who desire to use data on the Billboard Hot 100's webpage (https://www.billboard.com/charts/hot-100)
4
+
5
+ ♪ PAIN POINTS: This program will address the following user pain points on the Billboard Hot 100 webpage.
6
+
7
+ 1 | Customer experience. Multiple video ads pop up when the webpage is opened. As a result, it takes time to view the Chart and sort data.
8
+
9
+ 2 | Comprehensibility. Beyond viewing songs at the top of the list each week, it is not clear how else to interpret data on the Chart.
10
+
11
+ 3 | Usefullness. It is difficult to copy and past data on the webpage so that it can be used later on (e.g., for analyses that require multiple weeks of data).
12
+
13
+ ♪ PRODUCT DESIGN / BLUEPRINT: The program interface should be simple, yet elegant with some color
14
+
15
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16
+ WELCOME TO THE BILLBOARD HOT 100 CLI!
17
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18
+
19
+ WHAT WOULD YOU LIKE TO DO?
20
+ Enter 1 - 5 to select an option below.
21
+
22
+ MAIN MENU
23
+ 1 | View this week's top 10 songs.
24
+ 2 | View this week's top 100 songs.
25
+ 3 | View some analyses.
26
+ 4 | View the datasets.
27
+ 5 | Exit.
28
+
29
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30
+
31
+ -------------------------------------------
32
+ THIS WEEK'S TOP 10 SONGS
33
+ -------------------------------------------
34
+
35
+ RANK (CHANGE) - SONG - ARTIST
36
+ # 1 (-) - Hello - Adele
37
+ # 2 (+2) - Dancing with a stranger - Sam Smith
38
+ # 3 (-1) - WAP - Cardi B Featuring Megan Thee Stallion
39
+
40
+ -------------------------------------------
41
+
42
+ WHAT WOULD YOU LIKE TO DO NOW?
43
+
44
+ 1 | Go back to the main menu.
45
+ 2 | Exit.
46
+
47
+ -------------------------------------------
48
+
49
+ -------------------------------------------
50
+ ANALYSES - WHAT DO YOU WANT TO KNOW?
51
+ -------------------------------------------
52
+
53
+ 1 | Which songs are new this week?
54
+ 2 | Which songs have peaked #1?
55
+ 3 | Which songs have been on the charts the longest?
56
+ 4 | Return to the main menu
57
+ 5 | Exit
58
+
59
+ -------------------------------------------
60
+
61
+ -------------------------------------------
62
+ THIS WEEK'S NEW SONGS
63
+ -------------------------------------------
64
+
65
+ RANK - SONG - ARTIST
66
+ # 3 - Hello - Adele
67
+ # 5 - Dancing with a stranger - Sam Smith
68
+ # 11 - WAP - Cardi B Featuring Megan Thee Stallion
69
+
70
+ -------------------------------------------
71
+
72
+ WHAT WOULD YOU LIKE TO DO NOW?
73
+
74
+ 1 | Go back to the main menu.
75
+ 2 | Exit.
76
+
77
+ -------------------------------------------
78
+
79
+ -------------------------------------------
80
+ ALL SONGS THAT HAVE PEAKED #1
81
+ -------------------------------------------
82
+
83
+ RANK - SONG - ARTIST
84
+ # 3 - Hello - Adele
85
+ # 5 - Dancing with a stranger - Sam Smith
86
+ # 11 - WAP - Cardi B Featuring Megan Thee Stallion
87
+
88
+ -------------------------------------------
89
+
90
+ WHAT WOULD YOU LIKE TO DO NOW?
91
+
92
+ 1 | Go back to the main menu.
93
+ 2 | Exit.
94
+
95
+ -------------------------------------------
96
+
97
+ -------------------------------------------
98
+ TOP 10 SONGS ON CHARTS LONGEST
99
+ -------------------------------------------
100
+
101
+ DURATION - RANK - SONG - ARTIST
102
+ 35 WEEKS - RANK 6 - Hello - Adele
103
+ 31 WEEKS - RANK 7 - Dancing with a stranger - Sam Smith
104
+ 27 WEEKS - RANK 23 - WAP - Cardi B Featuring Megan Thee Stallion
105
+
106
+ -------------------------------------------
107
+
108
+ WHAT WOULD YOU LIKE TO DO NOW?
109
+
110
+ 1 | Go back to the main menu.
111
+ 2 | Exit.
112
+
113
+ -------------------------------------------
114
+
115
+ -------------------------------------------
116
+ DATASETS - HOW DO YOU WANT THE DATA SORTED?
117
+ -------------------------------------------
118
+
119
+ 1 | Sort by this week's rank.
120
+ 2 | Sort by peak rank.
121
+ 3 | Sort by duration on charts.
122
+ 4 | Return to the main menu.
123
+ 5 | Exit.
124
+
125
+ -------------------------------------------
126
+
127
+ -------------------------------------------
128
+ ALL DATA BY RANK THINK WEEK
129
+ -------------------------------------------
130
+
131
+ RANK (CHANGE) - PEAK - DURATION - SONG - ARTIST
132
+ RANK 1 (+1) - PEAK 1 - 35 WEEKS - Hello - Adele
133
+ RANK 2 (-) - PEAK 2 - 35 WEEKS - Hello - Adele
134
+ RANK 3 (-2) - PEAK 3 - 35 WEEKS - Hello - Adele
135
+
136
+ -------------------------------------------
137
+
138
+ WHAT WOULD YOU LIKE TO DO NOW?
139
+
140
+ 1 | Go back to the main menu
141
+ 2 | Exit
142
+
143
+ -------------------------------------------
144
+
145
+ -------------------------------------------
146
+ ALL DATA BY PEAK RANK
147
+ -------------------------------------------
148
+
149
+ PEAK - RANK (CHANGE) - DURATION - SONG - ARTIST
150
+ PEAK 1 - RANK 1 (+1) - 35 WEEKS - Hello - Adele
151
+ PEAK 2 - RANK 2 (-) - 35 WEEKS - Hello - Adele
152
+ PEAK 3 - RANK 3 (-2) - 35 WEEKS - Hello - Adele
153
+
154
+ -------------------------------------------
155
+
156
+ WHAT WOULD YOU LIKE TO DO NOW?
157
+
158
+ 1 | Go back to the main menu.
159
+ 2 | Exit.
160
+
161
+ -------------------------------------------
162
+
163
+ -------------------------------------------
164
+ ALL DATA BY DURATION
165
+ -------------------------------------------
166
+
167
+ DURATION - RANK (CHANGE) - PEAK - SONG - ARTIST
168
+ 35 WEEKS - RANK 6 (+1) - PEAK 3 - Hello - Adele
169
+ 30 WEEKS - RANK 6 (+1) - PEAK 3 - Hello - Adele
170
+ 25 WEEKS - RANK 6 (+1) - PEAK 3 - Hello - Adele
171
+
172
+ -------------------------------------------
173
+
174
+ WHAT WOULD YOU LIKE TO DO NOW?
175
+
176
+ 1 | Go back to the main menu.
177
+ 2 | Exit.
178
+
179
+ -------------------------------------------
180
+
181
+ -------------------------------------------
182
+ ♪ SEE YOU SOON! ♪
183
+ -------------------------------------------
184
+
185
+ ♪ OTHER:
186
+
187
+ ASCII Music Notes: ♬ ♩ ♫ ♪ ♭ ♮ ♯ ♬ ♩ ♫ ♪ ♭ ♮ ♯ ♬ ♩ ♫ ♪ ♭ ♮ ♯ ♬
188
+
189
+ Colorize color palette:
190
+
191
+ :black on :default :black on :default
192
+ :light_black on :default :light_black on :default
193
+ :red on :default :red on :default
194
+ :light_red on :default :light_red on :default
195
+ :green on :default :green on :default
196
+ :light_green on :default :light_green on :default
197
+ :yellow on :default :yellow on :default
198
+ :light_yellow on :default :light_yellow on :default
199
+ :blue on :default :blue on :default
200
+ :light_blue on :default :light_blue on :default
201
+ :magenta on :default :magenta on :default
202
+ :light_magenta on :default :light_magenta on :default
203
+ :cyan on :default :cyan on :default
204
+ :light_cyan on :default :light_cyan on :default
205
+ :white on :default :white on :default
206
+ :light_white on :default :light_white on :default
@@ -0,0 +1,53 @@
1
+ # Billboard Hot 100 Songs
2
+
3
+ Want to know what the hottest songs are this week? What about an easy way to get data from the Billboard Hot 100 without being bombarded with videos and ads?
4
+
5
+ This Ruby Gem allows you to access data on the Billboard Hot 100 (https://www.billboard.com/charts/hot-100) from the command line. Quickly generate the list of this week's Hot 100 songs with the following information,
6
+
7
+ ♪ Song name
8
+ ♪ Artist(s)
9
+ ♪ This week's rank
10
+ ♪ Change - The difference between this and last week's rank
11
+ ♪ Peak rank (or "Peak") - The highest rank that the song has ever reached on the Hot 100
12
+ ♪ Duration - The total number of weeks on the Hot 100
13
+
14
+ You can even find answers to questions like,
15
+
16
+ ♪ Which songs are new this week?
17
+ ♪ Which songs have peaked #1?
18
+ ♪ Which songs have been on the charts the longest?
19
+
20
+ Go ahead and check it out. Enjoy!
21
+
22
+ ## Preview
23
+
24
+ ![Welcome Screen](/images/1_Welcome_Screen.png)
25
+ ![Analyses Menu](/images/2_Analyses_Menu.png)
26
+ ![Datasets Menu](/images/3_Datasets_Menu.png)
27
+ ![New Songs](/images/4_New_Songs.png)
28
+ ![Datasets All Rank](/images/5_Datasets_All_Rank.png)
29
+ ![Goodbye Screen](/images/6_Goodbye_Screen.png)
30
+
31
+ ## Installation
32
+
33
+ $ gem install billboard_hot_100_songs
34
+
35
+ ## Usage
36
+
37
+ Type the below and follow the on screen prompts.
38
+
39
+ $ bin/billboard_hot_100_songs
40
+
41
+ ## Development
42
+
43
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
44
+
45
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
46
+
47
+ ## Contributing
48
+
49
+ Bug reports and pull requests are welcome on GitHub at https://github.com/alexander-mc/billboard_hot_100_songs. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
50
+
51
+ ## License
52
+
53
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,28 @@
1
+ require_relative 'lib/billboard_hot_100_songs/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "billboard_hot_100_songs"
5
+ spec.version = BillboardHot100Songs::VERSION
6
+ spec.date = '2020-09-07'
7
+ spec.authors = ["Alexander M. Clamor"]
8
+ spec.email = ["alexander.clamor@gmail.com"]
9
+
10
+ spec.summary = %q{Access data on the Billboard Hot 100 from the command line}
11
+ spec.description = %q{Quickly generate the list of this week's hottest songs and more!}
12
+ spec.homepage = "https://github.com/alexander-mc/billboard_hot_100_songs"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "bin"
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.10"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", ">= 0"
24
+ spec.add_development_dependency "pry", ">= 0"
25
+
26
+ spec.add_dependency "colorize", ">= 0"
27
+ spec.add_dependency "nokogiri", ">= 0"
28
+ end
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/billboard_hot_100_songs.rb'
4
+ BillboardHot100Songs::CLI.new.start
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "billboard_hot_100_songs"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+ IFS=$'\n\t'
5
+ set -vx
6
+
7
+ bundle install
8
+
9
+ # Do any other automated setup that you need to do here
Binary file
@@ -0,0 +1,12 @@
1
+ module BillboardHot100Songs
2
+ end
3
+
4
+ require 'pry'
5
+ require 'nokogiri'
6
+ require 'open-uri'
7
+ require 'colorize'
8
+
9
+ require_relative './billboard_hot_100_songs/song.rb'
10
+ require_relative './billboard_hot_100_songs/scraper.rb'
11
+ require_relative './billboard_hot_100_songs/cli.rb'
12
+ require_relative './billboard_hot_100_songs/version.rb'
@@ -0,0 +1,15 @@
1
+ require 'open-uri'
2
+
3
+ def extract_html
4
+
5
+ url = "https://www.billboard.com/charts/hot-100"
6
+ file = "billboard_hot_100_songs.html"
7
+
8
+ open(file, "wb") do |file|
9
+ open(url) do |uri|
10
+ file.write(uri.read)
11
+ end
12
+ end
13
+ end
14
+
15
+ extract_html
@@ -0,0 +1,333 @@
1
+ class BillboardHot100Songs::CLI
2
+
3
+ def initialize
4
+ create_songs
5
+ @indent = " " * 12 # Adjust indent spacing to your preference
6
+ end
7
+
8
+ def create_songs
9
+ song_array = BillboardHot100Songs::Scraper.scrape_main_page
10
+ BillboardHot100Songs::Song.create_from_array(song_array)
11
+ end
12
+
13
+ # MAIN MENU
14
+ # NOTE: THIS PROGRAM WAS DESIGNED WITH STATIC MENU DISPLAYS.
15
+ # THUS, MENU OPTIONS CANNOT BE CHANGED.
16
+
17
+ def start
18
+ display_main_menu
19
+ menu_options = ["1", "2", "3", "4", "5"]
20
+ @input = gets.strip
21
+ @restart = nil
22
+
23
+ check_input(menu_options)
24
+
25
+ case @input
26
+ when "1"
27
+ display_top_10_songs
28
+ when "2"
29
+ display_top_100_songs
30
+ when "3"
31
+ @set_previous_page = "3"
32
+ go_to_analyses_menu
33
+ when "4"
34
+ @set_previous_page = "4"
35
+ go_to_datasets_menu
36
+ when "5"
37
+ @exit = true
38
+ end
39
+
40
+ restart_or_exit_menu unless @restart || @exit
41
+ @restart ? start : say_goodbye
42
+ end
43
+
44
+ def display_main_menu
45
+ puts ""
46
+ puts "#{@indent}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~".light_cyan
47
+ puts "#{@indent} WELCOME TO THE BILLBOARD HOT 100 CLI! "
48
+ puts "#{@indent}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~".light_cyan
49
+ puts ""
50
+ puts "#{@indent}WHAT WOULD YOU LIKE TO DO? "
51
+ puts "#{@indent}Enter 1 - 5 to select an option below "
52
+ puts ""
53
+ puts "#{@indent}MAIN MENU "
54
+ puts "#{@indent}1 | View this week's top 10 songs "
55
+ puts "#{@indent}2 | View this week's top 100 songs "
56
+ puts "#{@indent}3 | View some analyses "
57
+ puts "#{@indent}4 | View the datasets "
58
+ puts "#{@indent}5 | Exit "
59
+ puts ""
60
+ puts "#{@indent}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~".light_cyan
61
+ end
62
+
63
+ def display_top_10_songs
64
+ puts "#{@indent}-------------------------------------------".light_green
65
+ puts "#{@indent}THIS WEEK'S TOP 10 SONGS ♪ "
66
+ puts "#{@indent}-------------------------------------------".light_green
67
+ puts ""
68
+ puts "#{@indent}RANK (CHANGE) - SONG - ARTIST "
69
+ puts ""
70
+ list_top_100_songs_this_week[0,10].each {|song| puts @indent + song}
71
+ puts ""
72
+ end
73
+
74
+ def display_top_100_songs
75
+ puts "#{@indent}-------------------------------------------".light_green
76
+ puts "#{@indent}THIS WEEK'S TOP 100 SONGS ♪ "
77
+ puts "#{@indent}-------------------------------------------".light_green
78
+ puts ""
79
+ puts "#{@indent}RANK (CHANGE) - SONG - ARTIST "
80
+ puts ""
81
+ list_top_100_songs_this_week.each {|song| puts @indent + song}
82
+ puts ""
83
+ end
84
+
85
+ def list_top_100_songs_this_week
86
+ BillboardHot100Songs::Song.sort_by_rank_this_week.map do |song|
87
+ "RANK #{song.rank_this_week} (#{song.delta}) - #{song.name} - #{song.artist}"
88
+ end
89
+ end
90
+
91
+ # ANALYSES MENU
92
+
93
+ def go_to_analyses_menu
94
+ display_analyses_menu
95
+ menu_options = ["1", "2", "3", "4", "5"]
96
+ @input = gets.strip
97
+
98
+ check_input(menu_options)
99
+
100
+ case @input
101
+ when "1"
102
+ display_new_songs_this_week
103
+ when "2"
104
+ display_no_1_peak_songs
105
+ when "3"
106
+ display_top_10_by_duration
107
+ when "4"
108
+ @restart = true
109
+ when "5"
110
+ @exit = true
111
+ end
112
+
113
+ return_menu_with_3_options unless @restart || @exit
114
+ end
115
+
116
+ def display_analyses_menu
117
+ puts "#{@indent}-------------------------------------------".light_green
118
+ puts "#{@indent}ANALYSES - WHAT DO YOU WANT TO KNOW? "
119
+ puts "#{@indent}-------------------------------------------".light_green
120
+ puts ""
121
+ puts "#{@indent}1 | Which songs are new this week? "
122
+ puts "#{@indent}2 | Which songs have peaked #1? "
123
+ puts "#{@indent}3 | Which songs have been on the chart the longest?"
124
+ puts "#{@indent}4 | Return to the main menu "
125
+ puts "#{@indent}5 | Exit "
126
+ puts ""
127
+ puts "#{@indent}-------------------------------------------".light_green
128
+ end
129
+
130
+ def display_new_songs_this_week
131
+ puts "#{@indent}-------------------------------------------".light_green
132
+ puts "#{@indent}THIS WEEK'S NEW SONGS ♪ "
133
+ puts "#{@indent}-------------------------------------------".light_green
134
+ puts ""
135
+ puts "#{@indent}DURATION - RANK - SONG - ARTIST "
136
+ puts ""
137
+ BillboardHot100Songs::Song.select_new_songs.each do |song|
138
+ puts "#{@indent}#{song.duration} WEEK - RANK #{song.rank_this_week} - #{song.name} - #{song.artist}"
139
+ end
140
+ puts ""
141
+ end
142
+
143
+ def display_no_1_peak_songs
144
+ puts "#{@indent}-------------------------------------------".light_green
145
+ puts "#{@indent}ALL SONGS THAT HAVE PEAKED #1 ♪ "
146
+ puts "#{@indent}-------------------------------------------".light_green
147
+ puts ""
148
+ puts "#{@indent}PEAK - RANK (CHANGE) - DURATION - SONG - ARTIST "
149
+ puts ""
150
+ BillboardHot100Songs::Song.select_no_1_peak_songs.each do |song|
151
+ puts "#{@indent}PEAK #{song.peak_rank} - RANK #{song.rank_this_week} (#{song.delta}) - #{song.duration} WEEKS - #{song.name} - #{song.artist}"
152
+ end
153
+ puts ""
154
+ end
155
+
156
+ def display_top_10_by_duration
157
+ puts "#{@indent}-------------------------------------------".light_green
158
+ puts "#{@indent}TOP 10 SONGS ON THE CHART LONGEST ♪ "
159
+ puts "#{@indent}-------------------------------------------".light_green
160
+ puts ""
161
+ puts "#{@indent}DURATION - RANK (CHANGE) - PEAK - SONG - ARTIST"
162
+ puts ""
163
+ BillboardHot100Songs::Song.select_top_10_by_duration.each do |song|
164
+ puts "#{@indent}#{song.duration} WEEKS - RANK #{song.rank_this_week} (#{song.delta}) - PEAK #{song.peak_rank} - #{song.name} - #{song.artist}"
165
+ end
166
+ puts""
167
+ end
168
+
169
+ # DATASETS MENU
170
+
171
+ def go_to_datasets_menu
172
+ display_dataset_menu
173
+ menu_options = ["1", "2", "3", "4", "5"]
174
+ @input = gets.strip
175
+
176
+ check_input(menu_options)
177
+
178
+ case @input
179
+ when "1"
180
+ display_dataset_by_rank_this_week
181
+ when "2"
182
+ display_dataset_by_peak_rank
183
+ when "3"
184
+ display_dataset_by_duration
185
+ when "4"
186
+ @restart = true
187
+ when "5"
188
+ @exit = true
189
+ end
190
+
191
+ return_menu_with_3_options unless @restart || @exit
192
+ end
193
+
194
+ def display_dataset_menu
195
+ puts "#{@indent}-------------------------------------------".light_green
196
+ puts "#{@indent}DATASETS - HOW DO YOU WANT THE DATA SORTED?"
197
+ puts "#{@indent}-------------------------------------------".light_green
198
+ puts ""
199
+ puts "#{@indent}1 | Sort by this week's rank "
200
+ puts "#{@indent}2 | Sort by peak rank "
201
+ puts "#{@indent}3 | Sort by duration on charts "
202
+ puts "#{@indent}4 | Return to the main menu "
203
+ puts "#{@indent}5 | Exit "
204
+ puts ""
205
+ puts "#{@indent}-------------------------------------------".light_green
206
+ end
207
+
208
+ def display_dataset_by_rank_this_week
209
+ puts "#{@indent}-------------------------------------------".light_green
210
+ puts "#{@indent}ALL DATA BY RANK THIS WEEK ♪ "
211
+ puts "#{@indent}-------------------------------------------".light_green
212
+ puts ""
213
+ puts "#{@indent}RANK (CHANGE) - PEAK - DURATION - SONG - ARTIST"
214
+ puts ""
215
+ BillboardHot100Songs::Song.sort_by_rank_this_week.each do |song|
216
+ puts "#{@indent}RANK #{song.rank_this_week} (#{song.delta}) - PEAK #{song.peak_rank} - #{song.duration} WEEKS - #{song.name} - #{song.artist}"
217
+ end
218
+ puts""
219
+ end
220
+
221
+ def display_dataset_by_peak_rank
222
+ puts "#{@indent}-------------------------------------------".light_green
223
+ puts "#{@indent}ALL DATA BY PEAK RANK ♪ "
224
+ puts "#{@indent}-------------------------------------------".light_green
225
+ puts ""
226
+ puts "#{@indent}PEAK - RANK (CHANGE) - DURATION - SONG - ARTIST"
227
+ puts ""
228
+ BillboardHot100Songs::Song.sort_by_peak_rank.each do |song|
229
+ puts "#{@indent}PEAK #{song.peak_rank} - RANK #{song.rank_this_week} (#{song.delta}) - #{song.duration} WEEKS - #{song.name} - #{song.artist}"
230
+ end
231
+ puts ""
232
+ end
233
+
234
+ def display_dataset_by_duration
235
+ puts "#{@indent}-------------------------------------------".light_green
236
+ puts "#{@indent}ALL DATA BY DURATION ♪ "
237
+ puts "#{@indent}-------------------------------------------".light_green
238
+ puts ""
239
+ puts "#{@indent}DURATION - RANK (CHANGE) - PEAK - SONG - ARTIST"
240
+ puts ""
241
+ BillboardHot100Songs::Song.sort_by_duration.each do |song|
242
+ puts "#{@indent}#{song.duration} WEEKS - RANK #{song.rank_this_week} (#{song.delta}) - PEAK #{song.peak_rank} - #{song.name} - #{song.artist}"
243
+ end
244
+ puts ""
245
+ end
246
+
247
+ # RETURN MENUS
248
+
249
+ def restart_or_exit_menu
250
+ display_restart_or_exit_menu
251
+ @input = gets.strip
252
+ menu_options = ["1", "2"]
253
+ check_input(menu_options)
254
+
255
+ @input == "1" ? @restart = true : @exit = true
256
+ end
257
+
258
+ def display_restart_or_exit_menu
259
+ puts "#{@indent}-------------------------------------------".light_green
260
+ puts "#{@indent} "
261
+ puts "#{@indent}WHAT WOULD YOU LIKE TO DO NOW? "
262
+ puts "#{@indent} "
263
+ puts "#{@indent}1 | Go back to the main menu "
264
+ puts "#{@indent}2 | Exit "
265
+ puts "#{@indent} "
266
+ puts "#{@indent}-------------------------------------------".light_green
267
+ end
268
+
269
+ def return_menu_with_3_options
270
+ display_return_menu_with_3_options
271
+ @input = gets.strip
272
+ menu_options = ["1", "2", "3"]
273
+ check_input(menu_options)
274
+
275
+ case @input
276
+ when "1"
277
+ go_to_previous_page
278
+ when "2"
279
+ @restart = true
280
+ when "3"
281
+ @exit = true
282
+ end
283
+ end
284
+
285
+ def display_return_menu_with_3_options
286
+ puts "#{@indent}-------------------------------------------".light_green
287
+ puts "#{@indent} "
288
+ puts "#{@indent}WHAT WOULD YOU LIKE TO DO NOW? "
289
+ puts "#{@indent} "
290
+ puts "#{@indent}1 | Go back to the previous menu "
291
+ puts "#{@indent}2 | Go back to the main menu "
292
+ puts "#{@indent}3 | Exit "
293
+ puts "#{@indent} "
294
+ puts "#{@indent}-------------------------------------------".light_green
295
+ end
296
+
297
+ # GO BACK
298
+
299
+ def go_to_previous_page
300
+ go_to_analyses_menu if @set_previous_page == "3" # Number is main menu option
301
+ go_to_datasets_menu if @set_previous_page == "4" # Number is main menu option
302
+ end
303
+
304
+ # CHECK INPUT
305
+
306
+ def check_input(menu_options)
307
+ while !menu_options.include?(@input)
308
+ input_error_message(menu_options)
309
+ @input = gets.strip
310
+ end
311
+ end
312
+
313
+ # ERROR MESSAGE
314
+
315
+ def input_error_message(menu_options)
316
+ if menu_options.size == 2
317
+ puts "Please enter [1] or [2]."
318
+ else
319
+ puts "Please enter a number 1 - #{menu_options.last}. Enter [#{menu_options.last}] to exit."
320
+ end
321
+ end
322
+
323
+ # GOODBYE MESSAGE
324
+
325
+ def say_goodbye
326
+ puts "#{@indent}-------------------------------------------".light_cyan
327
+ puts "#{@indent} ♭ ♫ ♯ ♪ SEE YOU SOON! ♪ ♯ ♫ ♭ "
328
+ puts "#{@indent}-------------------------------------------".light_cyan
329
+ puts ""
330
+ puts ""
331
+ end
332
+
333
+ end
@@ -0,0 +1,26 @@
1
+ class BillboardHot100Songs::Scraper
2
+
3
+ BASE_PATH = "https://www.billboard.com/charts/hot-100"
4
+
5
+ def self.scrape_main_page
6
+
7
+ page_data = Nokogiri::HTML(open(BASE_PATH))
8
+
9
+ # BACKUP HTML FOR OFFLINE USE - DATA IS FOR THE WEEK OF SEP. 5, 2020
10
+ # To work offline, uncomment the next two lines below (lines 11 and 12) and comment above code + BASE_PATH (lines 3 and 7)
11
+ # html_backup = File.read('/Users/Alexander/Documents/Coding/Flatiron School/3_Projects/billboard_hot_100_songs/lib/billboard_hot_100_songs/backup_website/billboard_hot_100_songs.html')
12
+ # page_data = Nokogiri::HTML(html_backup)
13
+
14
+ page_data.css("li.chart-list__element").map do |element|
15
+ song = {}
16
+ song[:name] = element.css("span.chart-element__information__song").text
17
+ song[:artist] = element.css("span.chart-element__information__artist").text
18
+ song[:rank_this_week] = element.css("span.chart-element__rank__number").text
19
+ song[:delta] = element.css("span.chart-element__information__delta__text.text--default").text
20
+ song[:rank_last_week] = element.css("span.chart-element__information__delta__text.text--last").text.gsub(" Last Week","")
21
+ song[:peak_rank] = element.css("span.chart-element__information__delta__text.text--peak").text.gsub(" Peak Rank","")
22
+ song[:duration] = element.css("span.chart-element__information__delta__text.text--week").text.gsub(" Weeks on Chart","")
23
+ song
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,56 @@
1
+ class BillboardHot100Songs::Song
2
+
3
+ attr_accessor :name, :artist, :rank_this_week, :rank_last_week, :delta, :peak_rank, :duration
4
+
5
+ @@all = []
6
+
7
+ def initialize(song_hash)
8
+ song_hash.each {|key, value| self.send("#{key}=", value)}
9
+ self.class.all << self
10
+ end
11
+
12
+ def self.create_from_array(song_array)
13
+ song_array.each {|song_hash| self.new(song_hash)}
14
+ end
15
+
16
+ def self.all
17
+ @@all
18
+ end
19
+
20
+ # SONGS BY RANK
21
+
22
+ def self.sort_by_rank_this_week
23
+ self.all.sort_by {|song| song.rank_this_week.to_i}
24
+ end
25
+
26
+ # SONGS BY DURATION
27
+
28
+ def self.select_new_songs
29
+ self.sort_by_rank_this_week.select {|song| song.duration == "1"}
30
+ end
31
+
32
+ def self.sort_by_duration # By descending order
33
+ self.all.sort_by {|song| song.duration.to_i}.reverse
34
+ end
35
+
36
+ def self.select_top_10_by_duration
37
+ self.sort_by_duration[0, 10]
38
+ end
39
+
40
+ # SONGS BY PEAK RANK
41
+
42
+ def self.select_no_1_peak_songs
43
+ self.sort_by_rank_this_week.select {|song| song.peak_rank == "1"}
44
+ end
45
+
46
+ def self.sort_by_peak_rank
47
+ self.all.sort_by {|song| song.peak_rank.to_i}
48
+ end
49
+
50
+ # UNUSED METHODS - MAY BE USEFUL FOR FUTURE PROGRAMS
51
+
52
+ def self.find_by_rank_this_week(rank_this_week)
53
+ self.all.find{|song| song.rank_this_week == rank_this_week}
54
+ end
55
+
56
+ end
@@ -0,0 +1,3 @@
1
+ module BillboardHot100Songs
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: billboard_hot_100_songs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alexander M. Clamor
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-09-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: colorize
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: nokogiri
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Quickly generate the list of this week's hottest songs and more!
98
+ email:
99
+ - alexander.clamor@gmail.com
100
+ executables:
101
+ - billboard_hot_100_songs
102
+ - console
103
+ - setup
104
+ extensions: []
105
+ extra_rdoc_files: []
106
+ files:
107
+ - ".gitignore"
108
+ - ".rspec"
109
+ - ".travis.yml"
110
+ - CODE_OF_CONDUCT.md
111
+ - Gemfile
112
+ - LICENSE.txt
113
+ - NOTES.md
114
+ - README.md
115
+ - Rakefile
116
+ - billboard_hot_100_songs.gemspec
117
+ - bin/billboard_hot_100_songs
118
+ - bin/console
119
+ - bin/setup
120
+ - images/1_Welcome_Screen.png
121
+ - images/2_Analyses_Menu.png
122
+ - images/3_Datasets_Menu.png
123
+ - images/4_New_Songs.png
124
+ - images/5_Datasets_All_Rank.png
125
+ - images/6_Goodbye_Screen.png
126
+ - lib/billboard_hot_100_songs.rb
127
+ - lib/billboard_hot_100_songs/backup_website/billboard_hot_100_songs.html
128
+ - lib/billboard_hot_100_songs/backup_website/extractor.rb
129
+ - lib/billboard_hot_100_songs/cli.rb
130
+ - lib/billboard_hot_100_songs/scraper.rb
131
+ - lib/billboard_hot_100_songs/song.rb
132
+ - lib/billboard_hot_100_songs/version.rb
133
+ homepage: https://github.com/alexander-mc/billboard_hot_100_songs
134
+ licenses:
135
+ - MIT
136
+ metadata: {}
137
+ post_install_message:
138
+ rdoc_options: []
139
+ require_paths:
140
+ - lib
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: 2.3.0
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ requirements: []
152
+ rubygems_version: 3.1.4
153
+ signing_key:
154
+ specification_version: 4
155
+ summary: Access data on the Billboard Hot 100 from the command line
156
+ test_files: []