pennu 0.0.1 → 0.1

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/.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