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.
- data/{README.rdoc → README.md} +4 -2
- data/Rakefile +7 -0
- data/VERSION +1 -1
- data/bin/mensa +4 -1
- data/fixtures/canteens.rb +1 -0
- data/fixtures/mensa-schofferstrase.html +4 -16
- data/fixtures/output.txt +7 -0
- data/lib/mensa/canteen.rb +34 -5
- data/lib/mensa/client.rb +10 -3
- data/lib/mensa.rb +2 -0
- data/mensa.gemspec +5 -5
- data/spec/mensa/canteen_spec.rb +29 -13
- data/spec/mensa/client_spec.rb +15 -1
- metadata +4 -4
data/{README.rdoc → README.md}
RENAMED
@@ -1,10 +1,12 @@
|
|
1
|
-
|
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
|
-
|
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.
|
1
|
+
0.1.3
|
data/bin/mensa
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
$LOAD_PATH
|
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&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> </td><td><h2>Echt bio! Jeden Mittwoch<br /></h2>Unser Bio-Essen aus biozertifizierten Produkten:<br /><strong><br /></strong><strong class="color_essen">
|
64
|
+
<table border="0"><tbody><tr><td><a href="stwscripts/show_image.php?abteilung=essen&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> </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 "Vegetaria"*<br /> mit Tomatensauce** FL 3,30 €<br /> für Gäste und MitarbeiterInnen der TU Darmstadt 4,30 € <br /><br /></td></tr><tr><td valign="top"> </td><td> </td><td valign="top"><span class="color_essen"> *</span> Bio-Komponente - DE-007-Ö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>Änderungen behalten wir uns vor.</p>
|
83
83
|
|
84
84
|
<a href="http://www.studentenwerkdarmstadt.de/index.php?option=com_spk&task=sch�fferstra�e&view=week">Wochenansicht</a>
|
85
|
-
<br
|
86
|
-
|
87
|
-
<tr><td valign="top"> </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"> </td><td valign="top"><img class="spk_img" src="components/com_spk/images/gefluegelpict_k.jpg" alt="gefluegel" width="50px" />Wokpfanne "Hot-Asia-Style" mit Hähnchenbrust und Mie-Nudeln G 2,80 �</td></tr>
|
89
|
-
<tr><td valign="top"> </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änge ! </td></tr>
|
90
|
-
<tr><td valign="top"> </td><td valign="top"><img class="spk_img" src="components/com_spk/images/fleischlospict_k.jpg" alt="fleischlos" width="50px" />Rü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ügel # (F) Fisch # (FL) Fleischlos
|
94
|
-
</div>
|
95
|
-
<div class="legende">
|
96
|
-
(1) Farbstoff # (2) Konservierungsstoff # (3) Antioxidationsmittel # (4) Geschmacksverstärker # (5) geschwefelt # (6) geschwärzt # (7) gewachst # (8) Phosphat # (9) Sü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
|
-
<!--
|
120
|
+
<!-- 1244894038 -->
|
data/fixtures/output.txt
CHANGED
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
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
|
-
|
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
|
-
|
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
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.
|
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-
|
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.
|
15
|
+
"README.md"
|
16
16
|
]
|
17
17
|
s.files = [
|
18
18
|
".document",
|
19
19
|
".gitignore",
|
20
20
|
"LICENSE",
|
21
|
-
"README.
|
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.
|
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",
|
data/spec/mensa/canteen_spec.rb
CHANGED
@@ -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
|
-
|
8
|
-
uri[:
|
9
|
-
|
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]
|
34
|
-
date[:lichtwiese]
|
35
|
-
date[:haardtring]
|
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]
|
39
|
-
name[:lichtwiese]
|
40
|
-
name[: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 \"
|
82
|
+
it "should be \"#{name[canteen]}\"" do
|
67
83
|
subject.name.should == name[canteen]
|
68
84
|
end
|
69
85
|
end
|
data/spec/mensa/client_spec.rb
CHANGED
@@ -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(
|
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.
|
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-
|
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.
|
33
|
+
- README.md
|
34
34
|
files:
|
35
35
|
- .document
|
36
36
|
- .gitignore
|
37
37
|
- LICENSE
|
38
|
-
- README.
|
38
|
+
- README.md
|
39
39
|
- Rakefile
|
40
40
|
- VERSION
|
41
41
|
- bin/mensa
|