pennu 0.0.1 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -15,4 +15,6 @@ rdoc
15
15
  spec/reports
16
16
  test/tmp
17
17
  test/version_tmp
18
- tmp
18
+ tmp
19
+ examples.rb
20
+ api/
data/README.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # pennu: Penn students, get fed. #
2
2
 
3
- pennu is a simple Ruby library (soon to be gem) that allows you to easily retreive the menus of Penn dining halls.
3
+ pennu is a simple Ruby gem that allows you to easily retreive the menus of Penn dining halls.
4
+
5
+ ## Installation ##
6
+
7
+ pennu is hosted on rubygems, so installation is as simple as:
8
+
9
+ ```gem install pennu```
4
10
 
5
11
  ## How to use pennu ##
6
12
 
@@ -32,7 +38,7 @@ Deli: Assorted Breads, Deli Meats and Cheeses made to order
32
38
  Good 4 You: Tofu and Red Lentil Risotto, Roasted Eggplant, Balsamic Tomatoes
33
39
  ```
34
40
 
35
- Calling ``` hill.friday.dinner``` will yield a ``` String``` like the output above. The menu items are more accessible as a hash of titles (e.g. ```Kettles``` and items (e.g. ```Mushroom Barley and Chicken Tortilla Soup```). To get the menu as a hash, simple call ```to_hash```. Running:
41
+ Calling ``` hill.friday.dinner``` will yield a ``` String``` like the output above. The menu items are more accessible as a hash of titles (e.g. ```Kettles```) and items (e.g. ```Mushroom Barley and Chicken Tortilla Soup```). To get the menu as a hash, simply call ```to_hash```. Running:
36
42
 
37
43
  ```ruby
38
44
  puts hill.friday.dinner.to_hash.inspect
@@ -54,5 +60,4 @@ pennu was written and tested on Windows; some hiccups may result from running pe
54
60
  All contributions are welcome via pull request.
55
61
 
56
62
  ## TODO ##
57
- * Create gem
58
63
  * More extensive testing
@@ -1,9 +1,26 @@
1
1
  class Day
2
- attr_accessor :date, :breakfast, :lunch, :dinner
2
+ attr_accessor :date, :dining_hall, :breakfast, :lunch, :dinner
3
3
  def initialize(dining_hall, date)
4
4
  @date = date
5
- @breakfast = Menu.new(dining_hall, date, 'breakfast')
6
- @lunch = Menu.new(dining_hall, date, 'lunch')
7
- @dinner = Menu.new(dining_hall, date, 'dinner')
5
+ @dining_hall = dining_hall
8
6
  end
7
+
8
+ def breakfast()
9
+ # fetch bfast menu for the date
10
+ @breakfast = Meal.new(@dining_hall, @date, 'breakfast')
11
+ @breakfast
12
+ end
13
+
14
+ def lunch()
15
+ # fetch lunch menu for the date
16
+ @lunch = Meal.new(@dining_hall, @date, 'lunch')
17
+ @lunch
18
+ end
19
+
20
+ def dinner()
21
+ # fetch dinner menu for the date
22
+ @dinner = Meal.new(@dining_hall, @date, 'dinner')
23
+ @dinner
24
+ end
25
+
9
26
  end
@@ -1,7 +1,7 @@
1
1
  class DiningHall
2
- attr_accessor :name, :urls, :tds, :dates, :sunday, :monday,
3
- :tuesday, :wednesday, :thursday, :friday,
4
- :saturday, :sunday
2
+ attr_accessor :name, :urls, :breakfast_tds, :lunch_tds, :dinner_tds,
3
+ :dates, :sunday, :monday, :tuesday, :wednesday, :thursday,
4
+ :friday, :saturday, :sunday
5
5
 
6
6
  # Has days, which have meals
7
7
  def initialize(name)
@@ -18,63 +18,51 @@ class DiningHall
18
18
  end
19
19
 
20
20
  @urls = {
21
- 'breafast' => ROOT_URL + dining_hall_path + BREAKFAST_PATH,
21
+ 'breakfast' => ROOT_URL + dining_hall_path + BREAKFAST_PATH,
22
22
  'lunch' => ROOT_URL + dining_hall_path + LUNCH_PATH,
23
23
  'dinner' => ROOT_URL + dining_hall_path + DINNER_PATH,
24
24
  }
25
25
 
26
- self.get_menus()
26
+ # Get dates for each day in the current week
27
+ self.get_days()
28
+
29
+ # Get the tds for each #{meal} for each day of the week
30
+ @urls.each { |meal, _| self.get_meal_tds(meal) }
31
+ end
32
+
33
+ def get_days()
34
+ @dates = []
35
+ today = Date.today
36
+ @dates << today - today.wday # sunday
37
+ (1..6).each { |n| @dates << @dates[0] + n }
38
+
39
+ # Assign dates to days
40
+ # Each day will contain b, l, and d menus
41
+ @dates.each do |date|
42
+ if !(DAYS.index(date.strftime("%A").downcase).nil?)
43
+ self.instance_variable_set("@#{date.strftime("%A").downcase}", Day.new(self, date))
44
+ end
45
+ end
27
46
  end
28
47
 
29
- def get_menus()
48
+ def get_meal_tds(meal)
30
49
  # Get menu table from dining website, use dinner for dates
31
50
  agent = Mechanize.new
32
- meal_page = agent.get(self.urls['dinner'])
51
+ meal_page = agent.get(self.urls[meal])
33
52
  table = meal_page.search("div.boxbody")
34
53
 
35
54
  # Scrape all tds into array
36
- @tds = []
55
+ tds = []
37
56
  table.xpath('//tr/td').to_a.each do |td|
38
57
  td = td.text.lstrip.rstrip
39
58
  tds << td unless (td.gsub(/\s+/, "") == "" or td.gsub(/\s+/, "") == "\u00A0")
40
59
  end
41
60
 
42
61
  # Remove dining hall title, which is the first element in tds
43
- @tds.shift
62
+ tds.shift
44
63
 
45
- # Create array of dates
46
- tds_clone = @tds.clone
47
- @dates = @tds.keep_if { |td|
48
- begin
49
- DateTime.strptime(td, "%A, %B %d, %Y")
50
- rescue ArgumentError
51
- false
52
- else
53
- true
54
- end
55
- }.map { |day_string| DateTime.strptime(day_string, "%A, %B %d, %Y") }
56
-
57
- # Clone tds to preserve for later methods
58
- @tds = tds_clone
59
-
60
- # Assign dates to days
61
- # Each day will contain b, l, and d menus
62
- @dates.each do |date|
63
- if date.strftime("%A") == "Sunday"
64
- @sunday = Day.new(self, date)
65
- elsif date.strftime("%A") == "Monday"
66
- @monday = Day.new(self, date)
67
- elsif date.strftime("%A") == "Tuesday"
68
- @tuesday = Day.new(self, date)
69
- elsif date.strftime("%A") == "Wednesday"
70
- @wednesday = Day.new(self, date)
71
- elsif date.strftime("%A") == "Thursday"
72
- @thursday = Day.new(self, date)
73
- elsif date.strftime("%A") == "Friday"
74
- @friday = Day.new(self, date)
75
- elsif date.strftime("%A") == "Saturday"
76
- @saturday = Day.new(self, date)
77
- end
78
- end
64
+ # Set instance var
65
+ self.instance_variable_set("@#{meal}_tds", tds)
79
66
  end
67
+
80
68
  end
@@ -0,0 +1,4 @@
1
+ # More descriptive errors
2
+
3
+ class NoDataError < StandardError
4
+ end
@@ -0,0 +1,63 @@
1
+ class Meal
2
+ # Scrapes for one dining hall, one day, one meal
3
+ def initialize(dining_hall, date, meal)
4
+ @date = date
5
+ @meal = meal
6
+ @dining_hall = dining_hall
7
+
8
+ @day_items = self.get_day_items(@meal, @date)
9
+ end
10
+
11
+ def to_hash()
12
+ # Add date key to beginning of hash and
13
+ # return hash of items and titles
14
+ {'date' => @date.to_s}.merge @day_items
15
+ end
16
+
17
+ def to_s()
18
+ str = "Menu for #{@meal} at #{@dining_hall.name.titlecase} on #{@date.strftime("%A, %B %d, %Y")}:\n"
19
+ @day_items.each do |title, item|
20
+ str += "#{title}: #{item}\n"
21
+ end
22
+ str.rstrip
23
+ end
24
+
25
+ def fetch_menu(meal)
26
+ # Get menu table from dining website, use dinner for dates
27
+ agent = Mechanize.new
28
+ meal_page = agent.get(@dining_hall.urls[meal])
29
+ table = meal_page.search("div.boxbody")
30
+
31
+ # Scrape all tds into array
32
+ @tds = []
33
+ table.xpath('//tr/td').to_a.each do |td|
34
+ td = td.text.lstrip.rstrip
35
+ @tds << td unless (td.gsub(/\s+/, "") == "" or td.gsub(/\s+/, "") == "\u00A0")
36
+ end
37
+
38
+ # Remove dining hall title, which is the first element in tds
39
+ @tds.shift
40
+ end
41
+
42
+ def get_day_items(meal, date)
43
+ # Split dining hall tds array by date delimiter
44
+ # Each child array contains menu titles and items for one day
45
+ tds = @dining_hall.instance_variable_get("@#{meal}_tds")
46
+ days_items = tds.split do |td|
47
+ begin
48
+ DateTime.strptime(td, "%A, %B %d, %Y")
49
+ rescue ArgumentError
50
+ false
51
+ else
52
+ true
53
+ end
54
+ end
55
+
56
+ begin
57
+ Hash[*days_items[DAYS.index(date.strftime("%A").downcase) + 1].flatten]
58
+ rescue NoMethodError => e
59
+ raise NoDataError, "Menu data unavailable for this meal."
60
+ end
61
+ end
62
+
63
+ end
@@ -1,5 +1,5 @@
1
1
  module Pennu
2
2
  module Ruby
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pennu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: '0.1'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-22 00:00:00.000000000 Z
12
+ date: 2012-11-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mechanize
@@ -41,7 +41,8 @@ files:
41
41
  - lib/classes/array.rb
42
42
  - lib/classes/day.rb
43
43
  - lib/classes/dininghall.rb
44
- - lib/classes/menu.rb
44
+ - lib/classes/errors.rb
45
+ - lib/classes/meal.rb
45
46
  - lib/classes/string.rb
46
47
  - lib/pennu.rb
47
48
  - lib/pennu/version.rb
@@ -1,35 +0,0 @@
1
- class Menu
2
- # Scrapes for one dining hall, one day, one meal
3
- def initialize(dining_hall, date, meal)
4
- @date = date
5
- @meal = meal
6
- @dining_hall = dining_hall
7
-
8
- # Split dining hall tds array by date delimiter
9
- # Each child array contains menu titles and items for one day
10
- days_items = @dining_hall.tds.split do |td|
11
- begin
12
- DateTime.strptime(td, "%A, %B %d, %Y")
13
- rescue ArgumentError
14
- false
15
- else
16
- true
17
- end
18
- end
19
-
20
- @day_items = Hash[*days_items[DAYS.index(date.strftime("%A").downcase)].flatten]
21
- end
22
-
23
- def to_hash()
24
- # Return hash of items and titles
25
- @day_items
26
- end
27
-
28
- def to_s()
29
- str = "Menu for #{@meal} at #{@dining_hall.name.titlecase} on #{@date.strftime("%A, %B %d, %Y")}:\n"
30
- @day_items.each do |title, item|
31
- str += "#{title}: #{item}\n"
32
- end
33
- str.rstrip
34
- end
35
- end