t6d-mensa 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,12 @@
1
- = mensa
1
+ mensa
2
+ =====
2
3
 
3
4
  Fetches the daily bill of fare from the canteen page of Studentenwerk Darmstadt.
4
5
 
5
6
  It is a little fun project to get familiar with TDD techniques, git and web
6
7
  scraping.
7
8
 
8
- == Copyright
9
+ Copyright
10
+ ---------
9
11
 
10
12
  Copyright (c) 2009 Konstantin Tennhard. See LICENSE for details.
data/Rakefile CHANGED
@@ -35,6 +35,7 @@ end
35
35
  task :default => :spec
36
36
 
37
37
  require 'rake/rdoctask'
38
+
38
39
  Rake::RDocTask.new do |rdoc|
39
40
  if File.exist?('VERSION.yml')
40
41
  config = YAML.load(File.read('VERSION.yml'))
@@ -49,3 +50,9 @@ Rake::RDocTask.new do |rdoc|
49
50
  rdoc.rdoc_files.include('lib/**/*.rb')
50
51
  end
51
52
 
53
+ desc "Generates documentation with yard"
54
+ task :yardoc do
55
+ Dir.chdir(File.dirname(__FILE__)) do
56
+ `yardoc 'lib/**/*.rb'`
57
+ end
58
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.1.3
data/bin/mensa CHANGED
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $LOAD_PATH << File.join(File.dirname(__FILE__), '../lib')
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '../lib')
4
+
5
+ # its important to set the kcode to use the jcode library
6
+ $KCODE = 'u' if RUBY_VERSION < '1.9'
4
7
 
5
8
  require 'mensa'
6
9
 
data/fixtures/canteens.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  canteen "http://www.studentenwerkdarmstadt.de/essen/mensa-stadtmitte.html"
2
2
  canteen "http://www.studentenwerkdarmstadt.de/essen/mensa-haardtring.html"
3
3
  canteen "http://www.studentenwerkdarmstadt.de/essen/mensa-lichtwiese.html"
4
+ canteen "http://www.studentenwerkdarmstadt.de/essen/mensa-schofferstrase.html"
4
5
 
@@ -61,7 +61,7 @@
61
61
  <table class="contentpaneopen">
62
62
  <tr>
63
63
  <td valign="top" colspan="2">
64
- <table border="0"><tbody><tr><td><a href="stwscripts/show_image.php?abteilung=essen&amp;bild=bio-siegel.jpg"><img class="mosimage_class" src="http://www.studentenwerkdarmstadt.de/images/stories/essen/bio-siegel_k.jpg" width="80" height="66" hspace="0" alt="Bio-Siegel" title="Bio-Siegel" border="0" /></a></td><td>&nbsp;</td><td><h2>Echt bio! Jeden Mittwoch<br /></h2>Unser Bio-Essen aus biozertifizierten Produkten:<br /><strong><br /></strong><strong class="color_essen">03.06.09</strong><br />2 Texas Beanburger*<br /> mit Tomatensauce** FL 2,50 &euro;<br /> f&uuml;r G&auml;ste und MitarbeiterInnen der TU Darmstadt 3,50 &euro;&nbsp; <br /><br /></td></tr><tr><td valign="top">&nbsp;</td><td>&nbsp;</td><td valign="top"><span class="color_essen">&nbsp; *</span> Bio-Komponente - DE-007-&Ouml;ko-Kontrollstelle <span class="color_essen"><br />**</span> Komponente aus konventionellem Anbau</td></tr></tbody></table>
64
+ <table border="0"><tbody><tr><td><a href="stwscripts/show_image.php?abteilung=essen&amp;bild=bio-siegel.jpg"><img class="mosimage_class" src="http://www.studentenwerkdarmstadt.de/images/stories/essen/bio-siegel_k.jpg" width="80" height="66" hspace="0" alt="Bio-Siegel" title="Bio-Siegel" border="0" /></a></td><td>&nbsp;</td><td><h2>Echt bio! Jeden Mittwoch<br /></h2>Unser Bio-Essen aus biozertifizierten Produkten:<br /><strong><br /></strong><strong class="color_essen">10.06.09</strong><br />Lasagne &quot;Vegetaria&quot;*<br /> mit Tomatensauce** FL 3,30 &euro;<br /> f&uuml;r G&auml;ste und MitarbeiterInnen der TU Darmstadt 4,30 &euro;&nbsp; <br /><br /></td></tr><tr><td valign="top">&nbsp;</td><td>&nbsp;</td><td valign="top"><span class="color_essen">&nbsp; *</span> Bio-Komponente - DE-007-&Ouml;ko-Kontrollstelle <span class="color_essen"><br />**</span> Komponente aus konventionellem Anbau</td></tr></tbody></table>
65
65
  </tr>
66
66
  </table>
67
67
 
@@ -82,20 +82,8 @@
82
82
  <p>&Auml;nderungen behalten wir uns vor.</p>
83
83
 
84
84
  <a href="http://www.studentenwerkdarmstadt.de/index.php?option=com_spk&amp;task=sch�fferstra�e&amp;view=week">Wochenansicht</a>
85
- <br />&nbsp;<br /><table border="1" class="spk_table"><tr><th></th><th class="hl_today">Donnerstag, den 28.05.2009</th></tr>
86
- <tr><td valign="top">Mensa</td><td valign="top"><img class="spk_img" src="components/com_spk/images/gefluegelpict_k.jpg" alt="gefluegel" width="50px" />H&auml;hnchen-Nuggets-im Knuspermantel dazu ein Kr&auml;uterdip G 1,90 �</td></tr>
87
- <tr><td valign="top">&nbsp;</td><td valign="top"><img class="spk_img" src="components/com_spk/images/schweinpict_k.jpg" alt="schwein" width="50px" />Grillbraten vom Schweinenacken mit Thymianjus S 2,00 �</td></tr>
88
- <tr><td valign="top">&nbsp;</td><td valign="top"><img class="spk_img" src="components/com_spk/images/gefluegelpict_k.jpg" alt="gefluegel" width="50px" />Wokpfanne &quot;Hot-Asia-Style&quot; mit H&auml;hnchenbrust und Mie-Nudeln G 2,80 �</td></tr>
89
- <tr><td valign="top">&nbsp;</td><td valign="top"><img class="spk_img" src="components/com_spk/images/pict_k.jpg" alt="" width="50px" />Spargelwoche !!! Bitte beachten Sie unsere Aush&auml;nge ! </td></tr>
90
- <tr><td valign="top">&nbsp;</td><td valign="top"><img class="spk_img" src="components/com_spk/images/fleischlospict_k.jpg" alt="fleischlos" width="50px" />R&uuml;hreier mit Rahmspinat FL 1,20 �</td></tr>
91
- </table><br />
92
- <div class="legende">
93
- (S) Schweinefleisch # (R) Rindfleisch # (K) Kalbfleisch # (L) Lammfleisch # (G) Gefl&uuml;gel # (F) Fisch # (FL) Fleischlos
94
- </div>
95
- <div class="legende">
96
- (1) Farbstoff # (2) Konservierungsstoff # (3) Antioxidationsmittel # (4) Geschmacksverst&auml;rker # (5) geschwefelt # (6) geschw&auml;rzt # (7) gewachst # (8) Phosphat # (9) S&uuml;ssungsmittel # (11) Phenylalaninquelle
97
- </div>
98
- <br />
85
+ <p><br /><b>Am Samstag, den 13.06.2009 bleibt die Mensa geschlossen.</b></p>
86
+
99
87
  <table class="contentpaneopen">
100
88
  <tr><td>
101
89
  </td></tr>
@@ -129,4 +117,4 @@ I</div><div id="footer2">
129
117
 
130
118
  </body>
131
119
  </html>
132
- <!-- 1243545358 -->
120
+ <!-- 1244894038 -->
data/fixtures/output.txt CHANGED
@@ -45,3 +45,10 @@
45
45
 
46
46
  Country Kartoffeln mit Quark 1,10 €
47
47
 
48
+
49
+
50
+ Mensa Schöfferstraße 13.06.
51
+ ============================================================================
52
+
53
+ geschlossen
54
+
data/lib/mensa/canteen.rb CHANGED
@@ -4,10 +4,18 @@ module Mensa
4
4
  class Canteen
5
5
  attr_reader :document
6
6
 
7
+ ##
8
+ # Creates a new canteen for a given uri
9
+ # @param [String]
10
+ # @return [Canteen]
7
11
  def initialize(uri)
8
12
  @document = Nokogiri::HTML(Document.new(uri).to_s)
9
13
  end
10
14
 
15
+ ##
16
+ # Extracts the bill of fare
17
+ #
18
+ # @return [Array]
11
19
  def fares
12
20
  if @fares.nil?
13
21
  @fares = []
@@ -33,28 +41,49 @@ module Mensa
33
41
  @fares
34
42
  end
35
43
 
44
+ ##
45
+ # A canteen is opened if it offers at least one fare
46
+ #
47
+ # @return [true | false]
36
48
  def opened?
37
49
  !fares.empty?
38
50
  end
39
51
 
52
+ ##
53
+ # A canteen is closed if it offers no fares
54
+ #
55
+ # @return [true | false]
40
56
  def closed?
41
57
  fares.empty?
42
58
  end
43
59
 
60
+ ##
61
+ # Extracts the date
62
+ #
63
+ # @return [Time]
44
64
  def date
45
- string = document.css('.spk_table th:last-child').first.text.strip
65
+ node = document.css('div.inside p b')
66
+ node = document.css('.spk_table th:last-child') if node.empty?
67
+ raise "Website does not contain a proper date" if node.empty?
46
68
 
47
- if date = /(\d{2})\.(\d{2})\.(\d{4})/.match(string)[1..3].reverse
48
- return Time.local(*(date.map { |e| e.to_i }))
49
- end
69
+ date = /(\d{2})\.(\d{2})\.(\d{4})/.match(node.first.text.strip)
50
70
 
51
- nil
71
+ Time.local(*(date.captures.reverse.map { |e| e.to_i }))
52
72
  end
53
73
 
74
+ ##
75
+ # Extracts the name
76
+ #
77
+ # @return [String]
54
78
  def name
55
79
  document.css('.contentheading').first.text.strip
56
80
  end
57
81
 
82
+ ##
83
+ # Compares two canteens based on their date, state and name
84
+ #
85
+ # @param [Canteen]
86
+ # @return [true | false]
58
87
  def ==(other)
59
88
  self.name == other.name && self.date == other.date &&
60
89
  self.closed? == other.closed? && self.opened? == other.opened?
data/lib/mensa/client.rb CHANGED
@@ -65,9 +65,11 @@ module Mensa
65
65
  end
66
66
 
67
67
  def print_header(canteen)
68
+ pad = (RUBY_VERSION < '1.9' ? canteen.name.length - canteen.name.jlength : 0) + 70
69
+
68
70
  result = "\n"
69
71
  result += " "
70
- result += canteen.name.ljust(70)
72
+ result += canteen.name.ljust(pad)
71
73
  result += canteen.date.strftime('%d.%m.')
72
74
  result += "\n"
73
75
  result += " "
@@ -80,14 +82,19 @@ module Mensa
80
82
  lines << ' '
81
83
 
82
84
  fare.name.split(' ').each do |word|
83
- if (lines.last.length + word.length) < 64
85
+ word_length = RUBY_VERSION < '1.9' ? word.jlength : word.length
86
+
87
+ if (lines.last.length + word_length) < 64
84
88
  lines.push(lines.pop + ' ' + word)
85
89
  else
86
90
  lines << " #{word}"
87
91
  end
88
92
  end
89
93
 
90
- result = lines.shift.ljust(70)
94
+ # calculates the right amount of space padding (ruby < 1.9 compatibility hack)
95
+ pad = (RUBY_VERSION < '1.9' ? lines.first.length - lines.first.jlength : 0) + 70
96
+
97
+ result = lines.shift.ljust(pad)
91
98
  result += "%1d,%02d €" % [fare.price / 100, fare.price % 100]
92
99
  result += "\n"
93
100
 
data/lib/mensa.rb CHANGED
@@ -4,6 +4,8 @@ require 'uri'
4
4
  require 'net/http'
5
5
  require 'iconv'
6
6
 
7
+ require 'jcode' if RUBY_VERSION < '1.9'
8
+
7
9
  require 'rubygems'
8
10
  require 'nokogiri'
9
11
 
data/mensa.gemspec CHANGED
@@ -2,23 +2,23 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{mensa}
5
- s.version = "0.1.2"
5
+ s.version = "0.1.3"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Konstantin Tennhard"]
9
- s.date = %q{2009-06-04}
9
+ s.date = %q{2009-06-14}
10
10
  s.default_executable = %q{mensa}
11
11
  s.email = %q{development@tennhard.net}
12
12
  s.executables = ["mensa"]
13
13
  s.extra_rdoc_files = [
14
14
  "LICENSE",
15
- "README.rdoc"
15
+ "README.md"
16
16
  ]
17
17
  s.files = [
18
18
  ".document",
19
19
  ".gitignore",
20
20
  "LICENSE",
21
- "README.rdoc",
21
+ "README.md",
22
22
  "Rakefile",
23
23
  "VERSION",
24
24
  "bin/mensa",
@@ -47,7 +47,7 @@ Gem::Specification.new do |s|
47
47
  s.homepage = %q{http://github.com/t6d/mensa}
48
48
  s.rdoc_options = ["--charset=UTF-8"]
49
49
  s.require_paths = ["lib"]
50
- s.rubygems_version = %q{1.3.3}
50
+ s.rubygems_version = %q{1.3.4}
51
51
  s.summary = %q{Fetches the daily bill of fare from the canteen page of Studentenwerk Darmstadt.}
52
52
  s.test_files = [
53
53
  "spec/mensa/canteen_spec.rb",
@@ -3,10 +3,19 @@
3
3
  require File.join(File.dirname(__FILE__), '../spec_helper')
4
4
 
5
5
  module Mensa
6
+ ##
7
+ # Setup
8
+ ##
9
+
6
10
  uri = {}
7
- uri[:stadtmitte] = "http://www.studentenwerkdarmstadt.de/essen/mensa-stadtmitte.html"
8
- uri[:lichtwiese] = "http://www.studentenwerkdarmstadt.de/essen/mensa-lichtwiese.html"
9
- uri[:haardtring] = "http://www.studentenwerkdarmstadt.de/essen/mensa-haardtring.html"
11
+ # open - 6 fares offering
12
+ uri[:stadtmitte] = "http://www.studentenwerkdarmstadt.de/essen/mensa-stadtmitte.html"
13
+ # open - 8 fares offering
14
+ uri[:lichtwiese] = "http://www.studentenwerkdarmstadt.de/essen/mensa-lichtwiese.html"
15
+ # closed
16
+ uri[:haardtring] = "http://www.studentenwerkdarmstadt.de/essen/mensa-haardtring.html"
17
+ # closed (unexpected markup)
18
+ uri[:schoefferstrasse] = "http://www.studentenwerkdarmstadt.de/essen/mensa-schofferstrase.html"
10
19
 
11
20
  fares = {}
12
21
  fares[:stadtmitte] = [
@@ -27,20 +36,27 @@ module Mensa
27
36
  Fare.new("Wokpfanne \"Thai 7 Spice\" mit Putenbrust und Basmatireis", :poultry, 280),
28
37
  Fare.new("Country Kartoffeln mit Quark", :meatless, 110)
29
38
  ]
30
- fares[:haardtring] = []
39
+ fares[:haardtring] = []
40
+ fares[:schoefferstrasse] = []
31
41
 
32
42
  date = {}
33
- date[:stadtmitte] = Time.local(2009, 5, 28)
34
- date[:lichtwiese] = Time.local(2009, 5, 29)
35
- date[:haardtring] = Time.local(2009, 6, 1)
43
+ date[:stadtmitte] = Time.local(2009, 5, 28)
44
+ date[:lichtwiese] = Time.local(2009, 5, 29)
45
+ date[:haardtring] = Time.local(2009, 6, 1)
46
+ date[:schoefferstrasse] = Time.local(2009, 6, 13)
36
47
 
37
48
  name = {}
38
- name[:stadtmitte] = "Mensa Stadtmitte"
39
- name[:lichtwiese] = "Mensa Lichtwiese"
40
- name[:haardtring] = "Mensa Haardtring"
49
+ name[:stadtmitte] = "Mensa Stadtmitte"
50
+ name[:lichtwiese] = "Mensa Lichtwiese"
51
+ name[:haardtring] = "Mensa Haardtring"
52
+ name[:schoefferstrasse] = "Mensa Schöfferstraße"
53
+
54
+ ##
55
+ # Specs
56
+ ##
41
57
 
42
- [:stadtmitte, :lichtwiese, :haardtring].each do |canteen|
43
- describe "#{canteen.to_s.capitalize} am #{date[canteen].strftime('%d.%m.%Y')} Canteen" do
58
+ [:stadtmitte, :lichtwiese, :haardtring, :schoefferstrasse].each do |canteen|
59
+ describe "#{canteen.to_s.capitalize} am #{date[canteen].strftime('%d.%m.%Y')}: Canteen" do
44
60
  subject { Canteen.new(uri[canteen]) }
45
61
 
46
62
  it { should have(fares[canteen].length).fares }
@@ -63,7 +79,7 @@ module Mensa
63
79
  end
64
80
 
65
81
  describe "#name" do
66
- it "should be \"Mensa Stadtmitte\"" do
82
+ it "should be \"#{name[canteen]}\"" do
67
83
  subject.name.should == name[canteen]
68
84
  end
69
85
  end
@@ -4,9 +4,19 @@ require File.join(File.dirname(__FILE__), '../spec_helper')
4
4
 
5
5
  module Mensa
6
6
  describe Client do
7
+ ##
8
+ # Setup
9
+ ##
10
+
11
+ ##
12
+ # Access to the configuration file is _mocked out_!
7
13
  user_config_file = File.join(ENV['HOME'], ".mensarc")
8
14
  global_config_file = File.join(MENSA_DIR, 'config/canteens.rb')
9
15
 
16
+ ##
17
+ # used to check if canteens are displayed in the order of the user
18
+ # specific configuration file
19
+ # (see spec 'Client with user specific settings')
10
20
  canteens = {}
11
21
  canteens[:stadtmitte] = Canteen.new(
12
22
  'http://www.studentenwerkdarmstadt.de/essen/mensa-stadtmitte.html'
@@ -15,6 +25,10 @@ module Mensa
15
25
  'http://www.studentenwerkdarmstadt.de/essen/mensa-haardtring.html'
16
26
  )
17
27
 
28
+ ##
29
+ # Specs
30
+ ##
31
+
18
32
  subject { Client.new(StringIO.new) }
19
33
 
20
34
  describe 'with global settings (config/canteens.rb)' do
@@ -36,7 +50,7 @@ module Mensa
36
50
  File.should_receive(:read).with(user_config_file).and_return(config)
37
51
  end
38
52
 
39
- it { should have(3).canteens }
53
+ it { should have(4).canteens }
40
54
 
41
55
  it 'should have "Mensa Stadtmitte" as first canteen' do
42
56
  subject.canteens[0].should == canteens[:stadtmitte]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: t6d-mensa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Tennhard
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-04 00:00:00 -07:00
12
+ date: 2009-06-14 00:00:00 -07:00
13
13
  default_executable: mensa
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -30,12 +30,12 @@ extensions: []
30
30
 
31
31
  extra_rdoc_files:
32
32
  - LICENSE
33
- - README.rdoc
33
+ - README.md
34
34
  files:
35
35
  - .document
36
36
  - .gitignore
37
37
  - LICENSE
38
- - README.rdoc
38
+ - README.md
39
39
  - Rakefile
40
40
  - VERSION
41
41
  - bin/mensa