local_ski_report 0.1.3
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 +7 -0
- data/bin/local_ski_report +5 -0
- data/config/environment.rb +9 -0
- data/lib/local_ski_report/cli.rb +163 -0
- data/lib/local_ski_report/report.rb +86 -0
- data/lib/local_ski_report/resort.rb +44 -0
- data/lib/local_ski_report/scraper.rb +36 -0
- data/lib/local_ski_report.rb +6 -0
- metadata +136 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c81b4413be043fb88b8cc99bba6ed827c7e94332
|
4
|
+
data.tar.gz: 7c1535b05eae57d6ed8a2253a35ebcb62d762144
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ef284304987708aee661fb925e5d66b7c12917ccd5f8e34bba6f909ef8a30078f2fe91081cc4d7bacc5dff44fd05f231a654b6d00b9dfd21c414078839b95451
|
7
|
+
data.tar.gz: 2588426c252a1e889187746f3bef1bb7ffd58f1fa94c84d7a62f986adecd5bb519b5c9fd700a62183b57ac594c12adb72b8578f03f47703727dee5e5de3da275
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'terminal-table'
|
5
|
+
|
6
|
+
require_relative '../lib/local_ski_report/cli'
|
7
|
+
require_relative '../lib/local_ski_report/report'
|
8
|
+
require_relative '../lib/local_ski_report/resort'
|
9
|
+
require_relative '../lib/local_ski_report/scraper'
|
@@ -0,0 +1,163 @@
|
|
1
|
+
# Our CLI Controller
|
2
|
+
class LocalSkiReport::CLI
|
3
|
+
|
4
|
+
attr_accessor :resort
|
5
|
+
|
6
|
+
STATES_WITH_RESORTS = [
|
7
|
+
{ :midwest => ["Illinois", "Indiana", "Iowa", "Kansas", "Michigan", "Minnesota", "Missouri", "Ohio","Wisconsin"] },
|
8
|
+
{ :northeast => ["Connecticut", "Maine", "Massachusetts", "New Hampshire", "New Jersey", "New York", "Pennsylvania", "Rhode Island", "Vermont"] },
|
9
|
+
{ :northwest => ["Alaska", "Idaho", "Oregon", "Washington"] },
|
10
|
+
{ :rockies => ["Colorado", "Montana", "New Mexico", "Utah", "Wyoming"] },
|
11
|
+
{ :southeast => ["Alabama", "Georgia", "Maryland", "North Carolina", "Tennessee", "Virginia", "West Virginia"] },
|
12
|
+
{ :west_coast => ["Arizona", "California", "Nevada"] }
|
13
|
+
]
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
LocalSkiReport::Scraper.scrap_resorts_page("united-states")
|
17
|
+
end
|
18
|
+
|
19
|
+
def call
|
20
|
+
greeting
|
21
|
+
menu
|
22
|
+
exit_msg
|
23
|
+
end
|
24
|
+
|
25
|
+
def menu
|
26
|
+
region_num = select_region
|
27
|
+
user_region = get_key(region_num)
|
28
|
+
separator(50)
|
29
|
+
|
30
|
+
state_num = select_state(region_num, user_region)
|
31
|
+
user_state = get_state(region_num, user_region, state_num)
|
32
|
+
separator(50)
|
33
|
+
|
34
|
+
select_resort(user_state)
|
35
|
+
display_report
|
36
|
+
|
37
|
+
input = nil
|
38
|
+
while input != "exit"
|
39
|
+
puts "Type: 'more' for detailed report, 'new' for new search, 'exit' to Quit."
|
40
|
+
input = gets.chomp.downcase
|
41
|
+
|
42
|
+
case input
|
43
|
+
when "new"
|
44
|
+
menu
|
45
|
+
break
|
46
|
+
when "more"
|
47
|
+
display_xt_report
|
48
|
+
when "exit"
|
49
|
+
puts
|
50
|
+
puts
|
51
|
+
break
|
52
|
+
else
|
53
|
+
puts "Invalid command entered."
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def greeting
|
59
|
+
separator(40)
|
60
|
+
puts "Welcome to Local Ski Report gem"
|
61
|
+
separator(40)
|
62
|
+
puts "Let's Get Your Local Ski Report"
|
63
|
+
puts " "
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_key(num)
|
67
|
+
STATES_WITH_RESORTS[num].keys[0]
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_state(reg_num, user_reg, st_num)
|
71
|
+
STATES_WITH_RESORTS[reg_num][user_reg][st_num] + ", USA"
|
72
|
+
end
|
73
|
+
|
74
|
+
def list_resorts(state)
|
75
|
+
resorts = LocalSkiReport::Resort.find_by_location(state)
|
76
|
+
# resorts = LocalSkiReport::Scraper.scrap_resorts_page(state)
|
77
|
+
resorts.each.with_index(1) { |r, i| puts "#{i}. #{r.name}" }
|
78
|
+
resorts
|
79
|
+
end
|
80
|
+
|
81
|
+
def list_regions
|
82
|
+
i = 1
|
83
|
+
STATES_WITH_RESORTS.each do |region|
|
84
|
+
region.each_key do |k|
|
85
|
+
puts "#{i}. #{k.to_s.gsub("_", " ").upcase}"
|
86
|
+
i += 1
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def list_states(num)
|
92
|
+
STATES_WITH_RESORTS[num].each_value do |states|
|
93
|
+
states.each.with_index(1) { |state, i| puts "#{i}. #{state}" }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def select_region
|
98
|
+
list_regions
|
99
|
+
separator(50)
|
100
|
+
puts "Select a region to check? type number: "
|
101
|
+
input = gets.chomp.to_i - 1
|
102
|
+
if input.between?(0, STATES_WITH_RESORTS.size - 1)
|
103
|
+
input
|
104
|
+
else
|
105
|
+
separator(55)
|
106
|
+
puts "Invalid number. Please select a number between 1 - #{STATES_WITH_RESORTS.size}: "
|
107
|
+
separator(55)
|
108
|
+
select_region
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def select_resort(state)
|
113
|
+
resorts_arr = list_resorts(state)
|
114
|
+
separator(50)
|
115
|
+
puts "Select a Resort or Ski-Area for the latest Report: "
|
116
|
+
input = gets.chomp.to_i - 1
|
117
|
+
if input.between?(0, resorts_arr.size - 1)
|
118
|
+
@resort = resorts_arr[input]
|
119
|
+
else
|
120
|
+
separator(60)
|
121
|
+
puts "Invalid Choice. Please choose a Resort # between 1 - #{resorts_arr.size}."
|
122
|
+
separator(60)
|
123
|
+
select_resort(state)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def select_state(region_num, region_key)
|
128
|
+
list_states(region_num)
|
129
|
+
separator(50)
|
130
|
+
puts "Select a State to check? type number: "
|
131
|
+
input = gets.chomp.to_i - 1
|
132
|
+
if input.between?(0, STATES_WITH_RESORTS[region_num][region_key].size - 1)
|
133
|
+
input
|
134
|
+
else
|
135
|
+
separator(55)
|
136
|
+
puts "Invalid Choice. Please choose a Resort # between 1 - #{STATES_WITH_RESORTS[region_num][region_key].size}."
|
137
|
+
separator(55)
|
138
|
+
select_state(region_num, region_key)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def separator(num)
|
143
|
+
puts "-" * num
|
144
|
+
end
|
145
|
+
|
146
|
+
def display_xt_report
|
147
|
+
report = resort.reports.first
|
148
|
+
LocalSkiReport::Scraper.scrap_report_page(report)
|
149
|
+
puts report.xt_report
|
150
|
+
end
|
151
|
+
|
152
|
+
def display_report
|
153
|
+
puts @resort.reports.first.report
|
154
|
+
end
|
155
|
+
|
156
|
+
def exit_msg
|
157
|
+
separator(60)
|
158
|
+
puts "Check back later for the latest Ski reports."
|
159
|
+
puts "Thanks for using Local Ski Report gem!"
|
160
|
+
separator(60)
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
class LocalSkiReport::Report
|
2
|
+
attr_accessor :date, :url, :status, :new_snow, :base, :lifts_open, :resort, :elevation, :trails, :tickets
|
3
|
+
|
4
|
+
@@all = []
|
5
|
+
|
6
|
+
def initialize(date, url, status, new_snow, base, lifts_open)
|
7
|
+
@date = date
|
8
|
+
@url = url
|
9
|
+
@status = status
|
10
|
+
@new_snow = new_snow
|
11
|
+
@base = base
|
12
|
+
@lifts_open = lifts_open
|
13
|
+
@@all << self
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.all
|
17
|
+
@@all
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.clear
|
21
|
+
@@all.clear
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.create(html)
|
25
|
+
date = html.css('div.lUpdate').text
|
26
|
+
url = html.css('td')[3].css('a').first['href']
|
27
|
+
status = self.get_status(html.css('td')[1].css('div').first['class'].split(" ").pop)
|
28
|
+
if html.css('td')[2].css('b')[0]
|
29
|
+
new_snow = html.css('td')[2].css('b')[0].text
|
30
|
+
else
|
31
|
+
new_snow = 'N/A'
|
32
|
+
end
|
33
|
+
base = html.css('td')[3].css('b')[0].text
|
34
|
+
lifts_open = self.get_lift_status(html)
|
35
|
+
self.new(date, url, status, new_snow, base, lifts_open)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.get_lift_status(html)
|
39
|
+
if html.css('td')[4].text.split("/").first == ""
|
40
|
+
0
|
41
|
+
else
|
42
|
+
html.css('td')[4].text.split("/").first
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.get_status(state)
|
47
|
+
case state
|
48
|
+
when "stateD1"
|
49
|
+
"Open"
|
50
|
+
when "stateD2"
|
51
|
+
"Closed"
|
52
|
+
else
|
53
|
+
"Weekends Only"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_ticket_prices(row)
|
58
|
+
arr = row.css('td').text.gsub("US","").split
|
59
|
+
[arr[1], arr[3]]
|
60
|
+
end
|
61
|
+
|
62
|
+
def report
|
63
|
+
rows = []
|
64
|
+
rows << [self.resort.name, {:value => self.date, :alignment => :center}, self.status, {:value => self.new_snow, :alignment => :center},{:value => self.base, :alignment => :center}, {:value => "#{self.lifts_open}/#{resort.lifts}", :alignment => :right}]
|
65
|
+
Terminal::Table.new :title => "Ski Report", :headings => ['Resort Name', 'Updated On', 'Status', 'New Snow', 'Base Depth', 'Lifts Open'], :rows => rows
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_xt_report_info(html)
|
69
|
+
table = html.css('table')
|
70
|
+
rows = table.css('tr')
|
71
|
+
@elevation = rows[1].css('td').text.split(" - ")
|
72
|
+
@trails = rows[2].css('td').text.gsub("|","").split
|
73
|
+
@tickets = get_ticket_prices(rows[4])
|
74
|
+
end
|
75
|
+
|
76
|
+
def xt_report
|
77
|
+
rows = []
|
78
|
+
rows << ['ELEVATION', "Base:", "#{elevation[0]}", "Summit:", "#{elevation[1]}"]
|
79
|
+
rows << ["TRAILS", "Beginner: #{trails[0]}", "Intermediate: #{trails[1]}", "Advanced: #{trails[2]}", "Expert: #{trails[3]}"]
|
80
|
+
rows << ["TICKET PRICES", "Starting at:", "#{tickets[0]}", {:value => "to", :alignment => :center}, "#{tickets[1]}"]
|
81
|
+
table = Terminal::Table.new :title => "#{self.resort.name} Full Report", :rows => rows
|
82
|
+
table.style = {:all_separators => true}
|
83
|
+
table
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class LocalSkiReport::Resort
|
2
|
+
attr_accessor :name, :url, :location, :lifts, :reports
|
3
|
+
|
4
|
+
@@all = []
|
5
|
+
|
6
|
+
def initialize(name, url, location, lifts)
|
7
|
+
@reports = []
|
8
|
+
@name = name
|
9
|
+
@url = url
|
10
|
+
@location = location
|
11
|
+
@lifts = lifts
|
12
|
+
@@all << self
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_report(report)
|
16
|
+
report.resort = self
|
17
|
+
self.reports << report
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.all
|
21
|
+
@@all
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.clear
|
25
|
+
@@all.clear
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.create(html)
|
29
|
+
name = html.css('td div.name').text
|
30
|
+
url = html.css('div.name a').first['href']
|
31
|
+
location = html.css('td div.rRegion').text
|
32
|
+
lifts = html.css('td')[4].text.split("/").last
|
33
|
+
self.new(name, url, location, lifts)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.find_by_location(location)
|
37
|
+
self.all.find_all { |resort| resort.location == location }
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.sort_by_lifts_desc
|
41
|
+
self.all.sort { |x, y| y.lifts.to_i <=> x.lifts.to_i }
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class LocalSkiReport::Scraper
|
2
|
+
|
3
|
+
def self.get_page(url)
|
4
|
+
html = open(url)
|
5
|
+
Nokogiri::HTML(html)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.get_table(html)
|
9
|
+
table = html.css('table')
|
10
|
+
table_rows = table.css('tr')
|
11
|
+
table_rows.slice(2, table_rows.size - 3)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.scrap_resorts_page(state_url)
|
15
|
+
url = "http://www.onthesnow.com/#{state_url}/skireport.html"
|
16
|
+
doc = self.get_page(url)
|
17
|
+
table = get_table(doc)
|
18
|
+
self.create_resort_report(table)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.create_resort_report(table)
|
22
|
+
table.collect do |row|
|
23
|
+
new_resort = LocalSkiReport::Resort.create(row)
|
24
|
+
new_report = LocalSkiReport::Report.create(row)
|
25
|
+
new_resort.add_report(new_report)
|
26
|
+
new_resort
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.scrap_report_page(report)
|
31
|
+
url = "http://www.onthesnow.com#{report.resort.url}"
|
32
|
+
doc = self.get_page(url)
|
33
|
+
report.get_xt_report_info(doc)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: local_ski_report
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nick Alan DAmico
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-08-12 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.14'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.14'
|
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: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.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: nokogiri
|
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: terminal-table
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.8.0
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.8.0
|
97
|
+
description: Find the latest ski report from your local ski area or resort.
|
98
|
+
email:
|
99
|
+
- nickalan82@icloud.com
|
100
|
+
executables:
|
101
|
+
- local_ski_report
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- bin/local_ski_report
|
106
|
+
- config/environment.rb
|
107
|
+
- lib/local_ski_report.rb
|
108
|
+
- lib/local_ski_report/cli.rb
|
109
|
+
- lib/local_ski_report/report.rb
|
110
|
+
- lib/local_ski_report/resort.rb
|
111
|
+
- lib/local_ski_report/scraper.rb
|
112
|
+
homepage: https://github.com/Nick-Damico/local-ski-report-cli-gem
|
113
|
+
licenses:
|
114
|
+
- MIT
|
115
|
+
metadata: {}
|
116
|
+
post_install_message:
|
117
|
+
rdoc_options: []
|
118
|
+
require_paths:
|
119
|
+
- lib
|
120
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
requirements: []
|
131
|
+
rubyforge_project:
|
132
|
+
rubygems_version: 2.5.1
|
133
|
+
signing_key:
|
134
|
+
specification_version: 4
|
135
|
+
summary: Ski Reports from local Ski Areas
|
136
|
+
test_files: []
|