weatherhacks 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.1.0 2007-12-12
2
+
3
+ * Keita Yamaguchi:
4
+ * Initial release
data/License.txt ADDED
@@ -0,0 +1,56 @@
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the GPL
3
+ (see the file GPL), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) give non-standard binaries non-standard names, with
21
+ instructions on where to get the original software distribution.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or binary form,
26
+ provided that you do at least ONE of the following:
27
+
28
+ a) distribute the binaries and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under these terms.
43
+
44
+ For the list of those files and their copying conditions, see the
45
+ file LEGAL.
46
+
47
+ 5. The scripts and library files supplied as input to or produced as
48
+ output from the software do not automatically fall under the
49
+ copyright of the software, but belong to whomever generated them,
50
+ and may be sold commercially, and may be aggregated with this
51
+ software.
52
+
53
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
54
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
55
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ PURPOSE.
data/Manifest.txt ADDED
@@ -0,0 +1,30 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ bin/lwws
7
+ config/hoe.rb
8
+ config/requirements.rb
9
+ lib/weatherhacks.rb
10
+ lib/weatherhacks/forecastmap.rb
11
+ lib/weatherhacks/lwws.rb
12
+ lib/weatherhacks/version.rb
13
+ misc/forecastmap.xsl
14
+ script/destroy
15
+ script/generate
16
+ script/txt2html
17
+ setup.rb
18
+ spec/lwws_spec.rb
19
+ spec/spec.opts
20
+ spec/spec_helper.rb
21
+ tasks/deployment.rake
22
+ tasks/environment.rake
23
+ tasks/rspec.rake
24
+ tasks/weatherhacks.rake
25
+ tasks/website.rake
26
+ website/index.html
27
+ website/index.txt
28
+ website/javascripts/rounded_corners_lite.inc.js
29
+ website/stylesheets/screen.css
30
+ website/template.rhtml
data/README.txt ADDED
@@ -0,0 +1,9 @@
1
+ README for ruby-weatherhacks
2
+ ============================
3
+ ruby-weatherhacks is a wrapper library for livdoor WeatherHacks API.
4
+
5
+ livedoor ... http://www.livedoor.com/
6
+ WeatherHacks ... http://weather.livedoor.com/weather_hacks/
7
+
8
+ Copyright (C) 2007 Keita Yamaguchi
9
+ Mail: keita.yamaguchi@gmail.com
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
data/bin/lwws ADDED
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby -Ku
2
+
3
+ begin
4
+ require "weatherhacks"
5
+ rescue LoadError
6
+ require "rubygems"
7
+ require "weatherhacks"
8
+ end
9
+
10
+ require "optparse"
11
+
12
+ OptionParser.new do |opt|
13
+ opt.on("--list") do
14
+ $mode = :list
15
+ end
16
+ opt.parse!
17
+ end
18
+
19
+ def temperature(forecast)
20
+ line = []
21
+ if forecast.celsius.min
22
+ line << "最低気温" + forecast.celsius.min.to_s + "度"
23
+ end
24
+ if forecast.celsius.max
25
+ line << "最高気温" + forecast.celsius.max.to_s + "度"
26
+ end
27
+ "(" + line.join(", ") + ")"
28
+ end
29
+
30
+ def show_forecast
31
+ today = WeatherHacks::LWWS.request($city.id, :today)
32
+ tomorrow = WeatherHacks::LWWS.request($city.id, :tomorrow)
33
+ dayaftertomorrow = WeatherHacks::LWWS.request($city.id, :dayaftertomorrow)
34
+ puts <<LOCATION
35
+ #{today.location.area}地方/#{today.location.pref}/#{today.location.city}
36
+ 今日: #{today.telop}#{temperature(today)}
37
+ 明日: #{tomorrow.telop}#{temperature(tomorrow)}
38
+ 明後日: #{dayaftertomorrow.telop}#{temperature(dayaftertomorrow)}
39
+ LOCATION
40
+ end
41
+
42
+ case $mode
43
+ when :list
44
+ WeatherHacks::ForecastMap::AREAS.each do |area|
45
+ puts "[#{area.name}]"
46
+ area.prefs.each do |pref|
47
+ puts "#{pref.name}: " + pref.cities.map{|city| city.name}.join(", ")
48
+ end
49
+ end
50
+ else
51
+ if ARGV[0] and WeatherHacks::ForecastMap::CITY.has_key?(ARGV[0])
52
+ $city = WeatherHacks::ForecastMap::CITY[ARGV[0]]
53
+ else
54
+ puts "Unknown city name: " + ARGV[0]
55
+ exit 0
56
+ end
57
+ show_forecast
58
+ end
data/config/hoe.rb ADDED
@@ -0,0 +1,71 @@
1
+ require 'weatherhacks/version'
2
+
3
+ AUTHOR = 'Keita Yamaguchi' # can also be an array of Authors
4
+ EMAIL = "keita.yamaguchi@gmail.com"
5
+ DESCRIPTION = "description of gem"
6
+ GEM_NAME = 'weatherhacks' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'weatherhacks' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+
11
+ @config_file = "~/.rubyforge/user-config.yml"
12
+ @config = nil
13
+ RUBYFORGE_USERNAME = "unknown"
14
+ def rubyforge_username
15
+ unless @config
16
+ begin
17
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
18
+ rescue
19
+ puts <<-EOS
20
+ ERROR: No rubyforge config file found: #{@config_file}
21
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
22
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
23
+ EOS
24
+ exit
25
+ end
26
+ end
27
+ RUBYFORGE_USERNAME.replace @config["username"]
28
+ end
29
+
30
+
31
+ REV = nil
32
+ # UNCOMMENT IF REQUIRED:
33
+ # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
34
+ VERS = WeatherHacks::VERSION::STRING + (REV ? ".#{REV}" : "")
35
+ RDOC_OPTS = ['--quiet', '--title', 'weatherhacks documentation',
36
+ "--opname", "index.html",
37
+ "--line-numbers",
38
+ "--main", "README",
39
+ "--inline-source"]
40
+
41
+ class Hoe
42
+ def extra_deps
43
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
44
+ @extra_deps
45
+ end
46
+ end
47
+
48
+ # Generate all the Rake tasks
49
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
50
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
51
+ p.author = AUTHOR
52
+ p.description = DESCRIPTION
53
+ p.email = EMAIL
54
+ p.summary = DESCRIPTION
55
+ p.url = HOMEPATH
56
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
57
+ p.test_globs = ["test/**/test_*.rb"]
58
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
59
+
60
+ # == Optional
61
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
62
+ #p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
63
+
64
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
65
+
66
+ end
67
+
68
+ CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
69
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
70
+ hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
71
+ hoe.rsync_args = '-av --delete --ignore-errors'
@@ -0,0 +1,17 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
16
+
17
+ require 'weatherhacks'
@@ -0,0 +1,266 @@
1
+ module WeatherHacks
2
+ module ForecastMap
3
+ area("北海道地方", "http://weather.livedoor.com/forecast/rss/1.xml") do
4
+ pref("道北") do
5
+ city("稚内", 1, "http://weather.livedoor.com/forecast/rss/1a/1.xml")
6
+ city("旭川", 2, "http://weather.livedoor.com/forecast/rss/1a/2.xml")
7
+ city("留萌", 3, "http://weather.livedoor.com/forecast/rss/1a/3.xml")
8
+ end
9
+ pref("道央") do
10
+ city("札幌", 4, "http://weather.livedoor.com/forecast/rss/1b/4.xml")
11
+ city("岩見沢", 5, "http://weather.livedoor.com/forecast/rss/1b/5.xml")
12
+ city("倶知安", 6, "http://weather.livedoor.com/forecast/rss/1b/6.xml")
13
+ end
14
+ pref("道東") do
15
+ city("網走", 7, "http://weather.livedoor.com/forecast/rss/1c/7.xml")
16
+ city("北見", 8, "http://weather.livedoor.com/forecast/rss/1c/8.xml")
17
+ city("紋別", 9, "http://weather.livedoor.com/forecast/rss/1c/9.xml")
18
+ city("根室", 10, "http://weather.livedoor.com/forecast/rss/1c/10.xml")
19
+ city("釧路", 11, "http://weather.livedoor.com/forecast/rss/1c/11.xml")
20
+ city("帯広", 12, "http://weather.livedoor.com/forecast/rss/1c/12.xml")
21
+ end
22
+ pref("道南") do
23
+ city("室蘭", 13, "http://weather.livedoor.com/forecast/rss/1d/13.xml")
24
+ city("浦河", 14, "http://weather.livedoor.com/forecast/rss/1d/14.xml")
25
+ city("函館", 15, "http://weather.livedoor.com/forecast/rss/1d/15.xml")
26
+ city("江差", 16, "http://weather.livedoor.com/forecast/rss/1d/16.xml")
27
+ end
28
+ end
29
+ area("東北地方", "http://weather.livedoor.com/forecast/rss/2.xml") do
30
+ pref("青森県") do
31
+ city("青森", 17, "http://weather.livedoor.com/forecast/rss/2/17.xml")
32
+ city("むつ", 18, "http://weather.livedoor.com/forecast/rss/2/18.xml")
33
+ city("八戸", 19, "http://weather.livedoor.com/forecast/rss/2/19.xml")
34
+ end
35
+ pref("秋田県") do
36
+ city("秋田", 20, "http://weather.livedoor.com/forecast/rss/5/20.xml")
37
+ city("横手", 21, "http://weather.livedoor.com/forecast/rss/5/21.xml")
38
+ end
39
+ pref("岩手県") do
40
+ city("盛岡", 22, "http://weather.livedoor.com/forecast/rss/3/22.xml")
41
+ city("宮古", 23, "http://weather.livedoor.com/forecast/rss/3/23.xml")
42
+ city("大船渡", 24, "http://weather.livedoor.com/forecast/rss/3/24.xml")
43
+ end
44
+ pref("宮城県") do
45
+ city("仙台", 25, "http://weather.livedoor.com/forecast/rss/4/25.xml")
46
+ city("白石", 26, "http://weather.livedoor.com/forecast/rss/4/26.xml")
47
+ end
48
+ pref("山形県") do
49
+ city("山形", 27, "http://weather.livedoor.com/forecast/rss/6/27.xml")
50
+ city("米沢", 28, "http://weather.livedoor.com/forecast/rss/6/28.xml")
51
+ city("酒田", 29, "http://weather.livedoor.com/forecast/rss/6/29.xml")
52
+ city("新庄", 30, "http://weather.livedoor.com/forecast/rss/6/30.xml")
53
+ end
54
+ pref("福島県") do
55
+ city("福島", 31, "http://weather.livedoor.com/forecast/rss/7/31.xml")
56
+ city("小名浜", 32, "http://weather.livedoor.com/forecast/rss/7/32.xml")
57
+ city("若松", 33, "http://weather.livedoor.com/forecast/rss/7/33.xml")
58
+ end
59
+ end
60
+ area("関東地方", "http://weather.livedoor.com/forecast/rss/3.xml") do
61
+ pref("茨城県") do
62
+ city("水戸", 54, "http://weather.livedoor.com/forecast/rss/8/54.xml")
63
+ city("土浦", 55, "http://weather.livedoor.com/forecast/rss/8/55.xml")
64
+ end
65
+ pref("栃木県") do
66
+ city("宇都宮", 56, "http://weather.livedoor.com/forecast/rss/9/56.xml")
67
+ city("大田原", 57, "http://weather.livedoor.com/forecast/rss/9/57.xml")
68
+ end
69
+ pref("群馬県") do
70
+ city("前橋", 58, "http://weather.livedoor.com/forecast/rss/10/58.xml")
71
+ city("みなかみ", 59, "http://weather.livedoor.com/forecast/rss/10/59.xml")
72
+ end
73
+ pref("埼玉県") do
74
+ city("さいたま", 60, "http://weather.livedoor.com/forecast/rss/11/60.xml")
75
+ city("熊谷", 61, "http://weather.livedoor.com/forecast/rss/11/61.xml")
76
+ city("秩父", 62, "http://weather.livedoor.com/forecast/rss/11/62.xml")
77
+ end
78
+ pref("東京都") do
79
+ city("東京", 63, "http://weather.livedoor.com/forecast/rss/13/63.xml")
80
+ city("大島", 64, "http://weather.livedoor.com/forecast/rss/13/64.xml")
81
+ city("八丈島", 65, "http://weather.livedoor.com/forecast/rss/13/65.xml")
82
+ city("父島", 66, "http://weather.livedoor.com/forecast/rss/13/66.xml")
83
+ end
84
+ pref("千葉県") do
85
+ city("千葉", 67, "http://weather.livedoor.com/forecast/rss/12/67.xml")
86
+ city("銚子", 68, "http://weather.livedoor.com/forecast/rss/12/68.xml")
87
+ city("館山", 69, "http://weather.livedoor.com/forecast/rss/12/69.xml")
88
+ end
89
+ pref("神奈川県") do
90
+ city("横浜", 70, "http://weather.livedoor.com/forecast/rss/14/70.xml")
91
+ city("小田原", 71, "http://weather.livedoor.com/forecast/rss/14/71.xml")
92
+ end
93
+ pref("山梨県") do
94
+ city("甲府", 75, "http://weather.livedoor.com/forecast/rss/19/75.xml")
95
+ city("河口湖", 76, "http://weather.livedoor.com/forecast/rss/19/76.xml")
96
+ end
97
+ end
98
+ area("信越・北陸地方", "http://weather.livedoor.com/forecast/rss/4.xml") do
99
+ pref("富山県") do
100
+ city("富山", 44, "http://weather.livedoor.com/forecast/rss/16/44.xml")
101
+ city("伏木", 45, "http://weather.livedoor.com/forecast/rss/16/45.xml")
102
+ end
103
+ pref("石川県") do
104
+ city("金沢", 46, "http://weather.livedoor.com/forecast/rss/17/46.xml")
105
+ city("輪島", 47, "http://weather.livedoor.com/forecast/rss/17/47.xml")
106
+ end
107
+ pref("福井県") do
108
+ city("福井", 48, "http://weather.livedoor.com/forecast/rss/18/48.xml")
109
+ city("敦賀", 49, "http://weather.livedoor.com/forecast/rss/18/49.xml")
110
+ end
111
+ pref("新潟県") do
112
+ city("新潟", 50, "http://weather.livedoor.com/forecast/rss/15/50.xml")
113
+ city("長岡", 51, "http://weather.livedoor.com/forecast/rss/15/51.xml")
114
+ city("高田", 52, "http://weather.livedoor.com/forecast/rss/15/52.xml")
115
+ city("相川", 53, "http://weather.livedoor.com/forecast/rss/15/53.xml")
116
+ end
117
+ pref("長野県") do
118
+ city("長野", 72, "http://weather.livedoor.com/forecast/rss/20/72.xml")
119
+ city("松本", 73, "http://weather.livedoor.com/forecast/rss/20/73.xml")
120
+ city("飯田", 74, "http://weather.livedoor.com/forecast/rss/20/74.xml")
121
+ end
122
+ end
123
+ area("東海地方", "http://weather.livedoor.com/forecast/rss/5.xml") do
124
+ pref("静岡県") do
125
+ city("静岡", 34, "http://weather.livedoor.com/forecast/rss/22/34.xml")
126
+ city("網代", 35, "http://weather.livedoor.com/forecast/rss/22/35.xml")
127
+ city("三島", 36, "http://weather.livedoor.com/forecast/rss/22/36.xml")
128
+ city("浜松", 37, "http://weather.livedoor.com/forecast/rss/22/37.xml")
129
+ end
130
+ pref("愛知県") do
131
+ city("名古屋", 38, "http://weather.livedoor.com/forecast/rss/23/38.xml")
132
+ city("豊橋", 39, "http://weather.livedoor.com/forecast/rss/23/39.xml")
133
+ end
134
+ pref("岐阜県") do
135
+ city("岐阜", 40, "http://weather.livedoor.com/forecast/rss/21/40.xml")
136
+ city("高山", 41, "http://weather.livedoor.com/forecast/rss/21/41.xml")
137
+ end
138
+ pref("三重県") do
139
+ city("津", 42, "http://weather.livedoor.com/forecast/rss/24/42.xml")
140
+ city("尾鷲", 43, "http://weather.livedoor.com/forecast/rss/24/43.xml")
141
+ end
142
+ end
143
+ area("近畿地方", "http://weather.livedoor.com/forecast/rss/6.xml") do
144
+ pref("滋賀県") do
145
+ city("大津", 77, "http://weather.livedoor.com/forecast/rss/25/77.xml")
146
+ city("彦根", 78, "http://weather.livedoor.com/forecast/rss/25/78.xml")
147
+ end
148
+ pref("京都府") do
149
+ city("京都", 79, "http://weather.livedoor.com/forecast/rss/26/79.xml")
150
+ city("舞鶴", 80, "http://weather.livedoor.com/forecast/rss/26/80.xml")
151
+ end
152
+ pref("大阪府") do
153
+ city("大阪", 81, "http://weather.livedoor.com/forecast/rss/27/81.xml")
154
+ end
155
+ pref("兵庫県") do
156
+ city("神戸", 82, "http://weather.livedoor.com/forecast/rss/28/82.xml")
157
+ city("豊岡", 83, "http://weather.livedoor.com/forecast/rss/28/83.xml")
158
+ end
159
+ pref("奈良県") do
160
+ city("奈良", 84, "http://weather.livedoor.com/forecast/rss/29/84.xml")
161
+ city("風屋", 85, "http://weather.livedoor.com/forecast/rss/29/85.xml")
162
+ end
163
+ pref("和歌山県") do
164
+ city("和歌山", 86, "http://weather.livedoor.com/forecast/rss/30/86.xml")
165
+ city("潮岬", 87, "http://weather.livedoor.com/forecast/rss/30/87.xml")
166
+ end
167
+ end
168
+ area("中国地方", "http://weather.livedoor.com/forecast/rss/7.xml") do
169
+ pref("岡山県") do
170
+ city("岡山", 88, "http://weather.livedoor.com/forecast/rss/33/88.xml")
171
+ city("津山", 89, "http://weather.livedoor.com/forecast/rss/33/89.xml")
172
+ end
173
+ pref("広島県") do
174
+ city("広島", 90, "http://weather.livedoor.com/forecast/rss/34/90.xml")
175
+ city("庄原", 91, "http://weather.livedoor.com/forecast/rss/34/91.xml")
176
+ end
177
+ pref("島根県") do
178
+ city("松江", 92, "http://weather.livedoor.com/forecast/rss/32/92.xml")
179
+ city("浜田", 93, "http://weather.livedoor.com/forecast/rss/32/93.xml")
180
+ city("西郷", 94, "http://weather.livedoor.com/forecast/rss/32/94.xml")
181
+ end
182
+ pref("鳥取県") do
183
+ city("鳥取", 95, "http://weather.livedoor.com/forecast/rss/31/95.xml")
184
+ city("米子", 96, "http://weather.livedoor.com/forecast/rss/31/96.xml")
185
+ end
186
+ pref("山口県") do
187
+ city("下関", 97, "http://weather.livedoor.com/forecast/rss/35/97.xml")
188
+ city("山口", 98, "http://weather.livedoor.com/forecast/rss/35/98.xml")
189
+ city("柳井", 99, "http://weather.livedoor.com/forecast/rss/35/99.xml")
190
+ city("萩", 100, "http://weather.livedoor.com/forecast/rss/35/100.xml")
191
+ end
192
+ end
193
+ area("四国地方", "http://weather.livedoor.com/forecast/rss/8.xml") do
194
+ pref("徳島県") do
195
+ city("徳島", 101, "http://weather.livedoor.com/forecast/rss/36/101.xml")
196
+ city("日和佐", 102, "http://weather.livedoor.com/forecast/rss/36/102.xml")
197
+ end
198
+ pref("香川県") do
199
+ city("高松", 103, "http://weather.livedoor.com/forecast/rss/37/103.xml")
200
+ end
201
+ pref("愛媛県") do
202
+ city("松山", 104, "http://weather.livedoor.com/forecast/rss/38/104.xml")
203
+ city("新居浜", 105, "http://weather.livedoor.com/forecast/rss/38/105.xml")
204
+ city("宇和島", 106, "http://weather.livedoor.com/forecast/rss/38/106.xml")
205
+ end
206
+ pref("高知県") do
207
+ city("高知", 107, "http://weather.livedoor.com/forecast/rss/39/107.xml")
208
+ city("室戸", 108, "http://weather.livedoor.com/forecast/rss/39/108.xml")
209
+ city("清水", 109, "http://weather.livedoor.com/forecast/rss/39/109.xml")
210
+ end
211
+ end
212
+ area("九州地方", "http://weather.livedoor.com/forecast/rss/9.xml") do
213
+ pref("福岡県") do
214
+ city("福岡", 110, "http://weather.livedoor.com/forecast/rss/40/110.xml")
215
+ city("八幡", 111, "http://weather.livedoor.com/forecast/rss/40/111.xml")
216
+ city("飯塚", 112, "http://weather.livedoor.com/forecast/rss/40/112.xml")
217
+ city("久留米", 113, "http://weather.livedoor.com/forecast/rss/40/113.xml")
218
+ end
219
+ pref("大分県") do
220
+ city("大分", 114, "http://weather.livedoor.com/forecast/rss/44/114.xml")
221
+ city("中津", 115, "http://weather.livedoor.com/forecast/rss/44/115.xml")
222
+ city("日田", 116, "http://weather.livedoor.com/forecast/rss/44/116.xml")
223
+ city("佐伯", 117, "http://weather.livedoor.com/forecast/rss/44/117.xml")
224
+ end
225
+ pref("長崎県") do
226
+ city("長崎", 118, "http://weather.livedoor.com/forecast/rss/42/118.xml")
227
+ city("佐世保", 119, "http://weather.livedoor.com/forecast/rss/42/119.xml")
228
+ city("厳原", 120, "http://weather.livedoor.com/forecast/rss/42/120.xml")
229
+ city("福江", 121, "http://weather.livedoor.com/forecast/rss/42/121.xml")
230
+ end
231
+ pref("佐賀県") do
232
+ city("佐賀", 122, "http://weather.livedoor.com/forecast/rss/41/122.xml")
233
+ city("伊万里", 123, "http://weather.livedoor.com/forecast/rss/41/123.xml")
234
+ end
235
+ pref("熊本県") do
236
+ city("熊本", 124, "http://weather.livedoor.com/forecast/rss/43/124.xml")
237
+ city("阿蘇乙姫", 125, "http://weather.livedoor.com/forecast/rss/43/125.xml")
238
+ city("牛深", 126, "http://weather.livedoor.com/forecast/rss/43/126.xml")
239
+ city("人吉", 127, "http://weather.livedoor.com/forecast/rss/43/127.xml")
240
+ end
241
+ pref("宮崎県") do
242
+ city("宮崎", 128, "http://weather.livedoor.com/forecast/rss/45/128.xml")
243
+ city("延岡", 129, "http://weather.livedoor.com/forecast/rss/45/129.xml")
244
+ city("都城", 130, "http://weather.livedoor.com/forecast/rss/45/130.xml")
245
+ city("高千穂", 131, "http://weather.livedoor.com/forecast/rss/45/131.xml")
246
+ end
247
+ pref("鹿児島県") do
248
+ city("鹿児島", 132, "http://weather.livedoor.com/forecast/rss/46/132.xml")
249
+ city("鹿屋", 133, "http://weather.livedoor.com/forecast/rss/46/133.xml")
250
+ city("種子島", 134, "http://weather.livedoor.com/forecast/rss/46/134.xml")
251
+ city("名瀬", 135, "http://weather.livedoor.com/forecast/rss/46/135.xml")
252
+ end
253
+ end
254
+ area("南西諸島地方", "http://weather.livedoor.com/forecast/rss/10.xml") do
255
+ pref("沖縄県") do
256
+ city("那覇", 136, "http://weather.livedoor.com/forecast/rss/47/136.xml")
257
+ city("名護", 137, "http://weather.livedoor.com/forecast/rss/47/137.xml")
258
+ city("久米島", 138, "http://weather.livedoor.com/forecast/rss/47/138.xml")
259
+ city("南大東島", 139, "http://weather.livedoor.com/forecast/rss/47/139.xml")
260
+ city("宮古島", 140, "http://weather.livedoor.com/forecast/rss/47/140.xml")
261
+ city("石垣島", 141, "http://weather.livedoor.com/forecast/rss/47/141.xml")
262
+ city("与那国島", 142, "http://weather.livedoor.com/forecast/rss/47/142.xml")
263
+ end
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,140 @@
1
+ require "uri"
2
+ require "rexml/document"
3
+ require "net/http"
4
+ require "time"
5
+
6
+ module WeatherHacks::LWWS
7
+ URL = URI.parse("http://weather.livedoor.com/forecast/webservice/rest/v1")
8
+
9
+ def self.path(city_id, day) #:nodoc:
10
+ URL.path + "?city=#{city_id}&day=#{day}"
11
+ end
12
+
13
+ class Error < StandardError
14
+ attr_reader :res
15
+ def initialize(res)
16
+ @res = res
17
+ end
18
+ end
19
+
20
+ class Forecast
21
+ attr_reader :author, :location, :title, :link, :forecastday, :day
22
+ attr_reader :forecastdate, :publictime, :telop, :description, :image
23
+ attr_reader :celsius, :fahrenheit, :pinpoints, :copyright
24
+
25
+ def initialize(doc)
26
+ raise ArgumentError, doc unless doc.kind_of? REXML::Document
27
+ elt = doc.root.elements["/lwws"]
28
+ @author = elt.elements["author"].text
29
+ @location = Location.new(elt.elements["location"])
30
+ @title = elt.elements["title"].text
31
+ @link = URI.parse(elt.elements["link"].text)
32
+ @forecastday = elt.elements["forecastday"].text
33
+ @day = elt.elements["day"].text
34
+ @forecastdate = Time.parse(elt.elements["forecastdate"].text)
35
+ @publictime = Time.parse(elt.elements["publictime"].text)
36
+ @telop = elt.elements["telop"].text
37
+ @description = elt.elements["description"].text
38
+ @image = Image.new(elt.elements["image"])
39
+ @celsius, @fahrenheit = Temperature.create(elt.elements["temperature"])
40
+ @pinpoints = Array.new
41
+ elt.elements.collect("pinpoint/location") do |node|
42
+ @pinpoints << PinpointLocation.new(node)
43
+ end
44
+ @copyright = Copyright.new(elt.elements["copyright"])
45
+ end
46
+ end
47
+
48
+ class Location
49
+ attr_reader :city, :area, :pref
50
+ def initialize(elt)
51
+ @area = elt.attributes["area"]
52
+ @pref = elt.attributes["pref"]
53
+ @city = elt.attributes["city"]
54
+ end
55
+ end
56
+
57
+ class Image
58
+ attr_reader :title, :link, :url, :width, :height
59
+ def initialize(elt)
60
+ @title = elt.elements["title"].text
61
+ @link = URI.parse(elt.elements["link"].text)
62
+ @url = URI.parse(elt.elements["url"].text)
63
+ @width = elt.elements["width"].text.to_i
64
+ @height = elt.elements["height"].text.to_i
65
+ end
66
+ end
67
+
68
+ class Temperature
69
+ attr_reader :max, :min
70
+ def self.create(elt)
71
+ return Celsius.new(elt), Fahrenheit.new(elt)
72
+ end
73
+ end
74
+
75
+ class Celsius < Temperature
76
+ def initialize(elt)
77
+ max = elt.elements["max/celsius"].text
78
+ @max = max.to_i if max
79
+ min = elt.elements["min/celsius"].text
80
+ @max = min.to_i if min
81
+ end
82
+ end
83
+
84
+ class Fahrenheit < Temperature
85
+ def initialize(elt)
86
+ max = elt.elements["max/fahrenheit"].text
87
+ @max = max.to_f if max
88
+ min = elt.elements["min/fahrenheit"].text
89
+ @max = min.to_f if min
90
+ end
91
+ end
92
+
93
+ class PinpointLocation
94
+ attr_reader :title, :link, :publictime
95
+ def initialize(elt)
96
+ raise ArgumentError, elt unless elt.kind_of? REXML::Element
97
+ @title = elt.elements["title"].text
98
+ @link = URI.parse(elt.elements["link"].text)
99
+ @publictime = Time.parse(elt.elements["publictime"].text)
100
+ end
101
+ end
102
+
103
+ class Copyright
104
+ attr_reader :title, :link, :image, :providers
105
+ def initialize(elt)
106
+ @title = elt.elements["title"].text
107
+ @link = URI.parse(elt.elements["link"].text)
108
+ @image = Image.new(elt.elements["image"])
109
+ @providers = Array.new
110
+ elt.each_element("provider") do |provider|
111
+ @providers << Provider.new(provider)
112
+ end
113
+ end
114
+ end
115
+
116
+ class Provider
117
+ attr_reader :name, :link
118
+ def initialize(elt)
119
+ @name = elt.attributes["name"]
120
+ @link = URI.parse(elt.attributes["link"])
121
+ end
122
+ end
123
+
124
+ # Returns a Forecast object.
125
+ # city_id:: city id
126
+ # day:: :today, :tomorrow or :dayaftertomorrow
127
+ def self.request(city_id, day = :today)
128
+ unless day == :today or day == :tomorrow or day == :dayaftertomorrow
129
+ raise ArgumentError, day
130
+ end
131
+ req = Net::HTTP::Get.new(path(city_id, day.to_s))
132
+ http = Net::HTTP.new(URL.host)
133
+ case res = http.request(req)
134
+ when Net::HTTPSuccess
135
+ Forecast.new(REXML::Document.new(res.body))
136
+ else
137
+ raise Error.new(res)
138
+ end
139
+ end
140
+ end