[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

[QUIZ] Current Temperature (#68

James Gray

2/24/2006 2:14:00 PM

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz until
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

http://www.rub...

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone
on Ruby Talk follow the discussion.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

by Caleb Tennis

Write a Ruby program such that given a certain argument to the program it
will return the current temperature of that location. People living in
the United States may be interested in temperature by ZIP code:

$ ruby current_temp.rb 47201
The temperature in Columbus, Indiana is 32 degrees F.

Other locales may want to use their own mailing codes, or city names:

$ ruby current_temp.rb madrid
The temperature in Madrid, Spain is 12 degrees C.

Which arguments you support is up to you.


19 Answers

Dave Burt

2/26/2006 3:15:00 PM

0

Ruby Quiz wrote:
> Write a Ruby program such that given a certain argument to the program it
> will return the current temperature of that location.

I still haven't done last week's metakoans, but I thought to myself, "Dave,"
(because I always address myself by name in my thoughts). "Dave," I thought,
"a universal Ruby-based indicator of the current temperature that works in
any location on any Ruby platform would be a great boon not only to you, but
to the entire Ruby community. In fact, why stop at the temperature? Ruby has
the power to turn almost any device into a fully functional weather station,
measuring rain, wind and snow. The world will be amazed."

So, thinking of you all, I wrote the code I now humbly present.

Cheers,
Dave.

#!/usr/bin/ruby
#
# Current Weather
#
# A response to Ruby Quiz #68 [ruby-talk:181420]
#
# This script basically turns your Ruby device into a weather machine. It
# leverages the latest technology to enable most laptops, PDAs, etc. to
capture
# meterorological metrics.
#
# WARNING: this program has a bug resulting in an infinite loop on
non-portable
# platforms.
#
# Please ONLY EXECUTE THIS PROGRAM ON PORTABLE DEVICES.
#
# Author: Dave Burt <dave at burt.id.au>
#
# Created: 23 Oct 2005
#

require 'highline/import'

# Work around bug
agree("Are you using a portable Ruby device? ") or
abort("Sorry, this program has not yet been ported to your platform.")

# Calibrate instrumentation
begin
say "Go outside."
end until agree("Are you outside now? ")

# Ascertain cloud cover
if agree("Is your Ruby device casting a defined shadow? ")
say "It's sunny."
else
say "It's overcast."
end

# Capture rainfall
if agree("Are your Ruby device or your umbrella wet? ")
say "It's raining."
else
say "It's fine."
end

# Weigh other precipitation
if agree("Is your Ruby device becoming white? ")
say "It's snowing."
else
say "It's not snowing."
end

# Discern current temperature
if agree("Are your fingers getting cold? ")
say "It's cold."
else
say "It's warm."
end

# Measure wind speed
if agree("Do you feel lateral forces on your Ruby device? ")
say "It's windy."
else
say "It's calm."
end

say "This weather report has been brought to you by Ruby, the letter D,"
say "and the number 42."


Nola Stowe

2/26/2006 3:40:00 PM

0

hahaha, thats great. Very entertaining Dave. Sometimes I wish I was
that funny :)


On 2/26/06, Dave Burt <dave@burt.id.au> wrote:
> Ruby Quiz wrote:
> > Write a Ruby program such that given a certain argument to the program it
> > will return the current temperature of that location.
>
> I still haven't done last week's metakoans, but I thought to myself, "Dave,"
> (because I always address myself by name in my thoughts). "Dave," I thought,
> "a universal Ruby-based indicator of the current temperature that works in
> any location on any Ruby platform would be a great boon not only to you, but
> to the entire Ruby community. In fact, why stop at the temperature? Ruby has
> the power to turn almost any device into a fully functional weather station,
> measuring rain, wind and snow. The world will be amazed."
>
> So, thinking of you all, I wrote the code I now humbly present.
>
> Cheers,
> Dave.
>
> #!/usr/bin/ruby
> #
> # Current Weather
> #
> # A response to Ruby Quiz #68 [ruby-talk:181420]
> #
> # This script basically turns your Ruby device into a weather machine. It
> # leverages the latest technology to enable most laptops, PDAs, etc. to
> capture
> # meterorological metrics.
> #
> # WARNING: this program has a bug resulting in an infinite loop on
> non-portable
> # platforms.
> #
> # Please ONLY EXECUTE THIS PROGRAM ON PORTABLE DEVICES.
> #
> # Author: Dave Burt <dave at burt.id.au>
> #
> # Created: 23 Oct 2005
> #
>
> require 'highline/import'
>
> # Work around bug
> agree("Are you using a portable Ruby device? ") or
> abort("Sorry, this program has not yet been ported to your platform.")
>
> # Calibrate instrumentation
> begin
> say "Go outside."
> end until agree("Are you outside now? ")
>
> # Ascertain cloud cover
> if agree("Is your Ruby device casting a defined shadow? ")
> say "It's sunny."
> else
> say "It's overcast."
> end
>
> # Capture rainfall
> if agree("Are your Ruby device or your umbrella wet? ")
> say "It's raining."
> else
> say "It's fine."
> end
>
> # Weigh other precipitation
> if agree("Is your Ruby device becoming white? ")
> say "It's snowing."
> else
> say "It's not snowing."
> end
>
> # Discern current temperature
> if agree("Are your fingers getting cold? ")
> say "It's cold."
> else
> say "It's warm."
> end
>
> # Measure wind speed
> if agree("Do you feel lateral forces on your Ruby device? ")
> say "It's windy."
> else
> say "It's calm."
> end
>
> say "This weather report has been brought to you by Ruby, the letter D,"
> say "and the number 42."
>
>
>
>


--
http://PhpGirl.b...
http://CodeS...


James Gray

2/26/2006 4:38:00 PM

0

On Feb 26, 2006, at 9:18 AM, Dave Burt wrote:

> # Calibrate instrumentation
> begin
> say "Go outside."
> end until agree("Are you outside now? ")

This step could prove very difficult for some programmers. ;)

James Edward Gray II



Aditya Mahajan

2/26/2006 5:28:00 PM

0

gordon

2/26/2006 5:48:00 PM

0

> Write a Ruby program such that given a certain argument to the program it
> will return the current temperature of that location. People living in
> the United States may be interested in temperature by ZIP code:

This is my first submission to rubyquiz. I've been learning ruby for
about 6 months now, and it's my first foray into programming. I'd love
some feedback.

Thanks,

# current_temp.rb

require 'net/http'
require 'rexml/document'
require 'optparse'

class CurrentTemp
include REXML

def initialize(loc,u='f')
uri = "http://xml.weather.yahoo.com/forec...{loc}&u=#{u}"
@doc = Document.new Net::HTTP.get(URI.parse(uri))
raise "Invalid city, #{loc}" if /error/i =~
@doc.elements["//description"].to_s
end

def method_missing(methodname)
XPath.match(@doc,"//*[starts-with(name(), 'yweather')]").each
do|elem|
return elem.attributes[methodname.to_s] if
elem.attributes[methodname.to_s]
end
Object.method_missing(methodname)
end

def unit
self.temperature
end

def state
self.region
end

def to_s
"The current temperature in #{self.city}, #{self.state} is
#{self.temp} degrees #{self.unit}."
end

end

opts = OptionParser.new
opts.banner = "Usage:\n\n current_temp.rb city [-u unit]\n\n "
opts.banner += "city should be a zip code, or a Yahoo Weather location
id.\n\n"
opts.on("-uARG", "--unit ARG","Should be f or c", String) {|val| @u =
val }
opts.on("-h", "--help") {puts opts.to_s ; exit 0}

loc = opts.parse!
@u ||='f'

begin

puts CurrentTemp.new(loc,@u)

rescue
puts $!
puts opts.to_s
exit 1
end

horndude77

2/26/2006 5:52:00 PM

0

My solution uses yahoo weather like another of the solutions here. It's
easy to use with US zip codes, but for international cities you have to
know the yahoo weather location id. I looked around for a big list of
these but couldn't find it. Anyways it would be nice to have some sort
of searching mechanism to turn a city name into a location id.

Also I used rexml to parse the rss feed. I tried to use the rss library,
but couldn't figure out how to pull out the 'yweather' tags.

Anyways, fun quiz. I enjoyed it a lot.

-----Jay Anderson


require 'rexml/document'
require 'open-uri'

#Returns a hash containing the location and temperature information
#Accepts US zip codes or Yahoo location id's
def yahoo_weather_query(loc_id, units)
h = {}
open("http://xml.weather.yahoo.com/forec...{loc_id}&u=#{units}")
do |http|
response = http.read
doc = REXML::Document.new(response)
root = doc.root
channel = root.elements['channel']
location = channel.elements['yweather:location']
h[:city] = location.attributes["city"]
h[:region] = location.attributes["region"]
h[:country] = location.attributes["country"]
h[:temp] =
channel.elements["item"].elements["yweather:condition"].attributes["temp"]
end
h
end

if ARGV.length < 1 then
puts "usage: #$0 <location> [f|c]"
exit
end
loc_id = ARGV[0]
units = (ARGV[1] || 'f').downcase
units = (units =~ /^(f|c)$/) ? units : 'f'

#An improvement would be to allow searches for the yahoo location id
#loc_id = yahoo_loc_search(loc_id)
weather_info = yahoo_weather_query(loc_id, units)
city = weather_info[:city]
region = weather_info[:region]
country = weather_info[:country]
temp = weather_info[:temp]

puts "The temperature in #{city}, #{region}, #{country} is #{temp}
degrees #{units.upcase}"



--
Posted via http://www.ruby-....


Ryan Leavengood

2/26/2006 6:37:00 PM

0

On 2/26/06, gordon <gthiesfeld@sbcglobal.net> wrote:
>
> This is my first submission to rubyquiz. I've been learning ruby for
> about 6 months now, and it's my first foray into programming. I'd love
> some feedback.

I think this is pretty darn slick Gordon, and you should continue in
programming.

My only suggestion would be that you check for an empty argument list
explicitly so that someone will a slow internet connection does not
have to wait for the request to go to Yahoo to get an error.

Ryan


Stephen Waits

2/26/2006 6:57:00 PM

0


On Feb 26, 2006, at 9:53 AM, gordon wrote:

> I've been learning ruby for
> about 6 months now, and it's my first foray into programming. I'd
> love
> some feedback.

As Ryan said, excellent job! Keep at it.

--Steve



Jeff McNeil

2/26/2006 7:33:00 PM

0

This is also my first Ruby Quiz submission.

I was going to neglect this one as well, but I got to thinking how
nicely lazy.rb might work with some web services. Once someone
actually came across a working SOAP service (xmethods lists quite a
few that are iffy),
I decided to give it a go.

Thanks =)

Jeff


#!/usr/bin/env ruby

require 'lazy'
require 'soap/wsdlDriver'
require 'rexml/document'
$-w = nil

$wsdl_loc = "http://www.webservicex.net/globalweather.asmx?...
class WeatherState
def initialize(city, country)
stub = SOAP::WSDLDriverFactory.new($wsdl_loc).create_rpc_driver

@keep_me = promise do
conditions = stub.getWeather(:CityName
=>city, :CountryName=>country)
data = REXML::Document.new(conditions.getWeatherResult.gsub(/<
\?.*?>\n/, ''))
{ :temp => data.elements["//Temperature"].text, loc =>
data.elements["//Location"].text }
end
end

def temp
demand(@keep_me)[:temp]
end

def loc
demand(@keep_me)[:loc]
end
end

if ARGV.length != 2
abort("Usage: weather.rb city country")
end

# Create Weather Object
weatherProxy = WeatherState.new(ARGV[0], ARGV[1])
puts "Location: " + weatherProxy.loc
puts "Current Temp: " + weatherProxy.temp.strip


Adam Shelly

2/26/2006 8:20:00 PM

0

On 2/24/06, Ruby Quiz <james@grayproductions.net> wrote:
> Write a Ruby program such that given a certain argument to the program it
> will return the current temperature of that location. People living in
> the United States may be interested in temperature by ZIP code:

I used Yahoo Weather's RSS feed. net/http and simple-rss did most of
the work for me.
But Yahoo keeps some interesting data in the attributes of some custom
tags, like <yweather:condition temp="99"... \>. SimpleRSS wasn't
returning the attribute values (I'm not even sure if Yahoo's method is
compliant RSS). So I extended SimpleRSS to give me the values I want.
Then I added an basic RSSFeeder class which puts Net fetch and RSS
parse together, and adds caching, so that you can run it continuously
without hammering the server. The script takes a zipcode and an
optional -f to get today's forecast, too

-Adam

#------ weatherman.rb -------------
require 'net/http'
require 'simple-rss'

class Object
def metaclass; class << self; self; end; end
end #thanks, _why

#Extends Simple RSS to add tag attributes as methods to the tag object
# given <sometag var="2">hello</sometag>,
# allows item.sometag ==> hello
# and item.sometag.var ==> 2
class SimpleRSSwAttributes < SimpleRSS
def clean_content(tag, attrs, content)
s= super
while n= (attrs =~ /((\w*)="([^"]*)" )/mi)
attr_name = clean_tag($2)
s.metaclass.send(:attr_reader, attr_name)
s.instance_variable_set("@#{attr_name}",unescape($3))
attrs.slice!(n,$1.length)
end
s
end
def method_missing meth
nil
end
end

#Simple RSS feed reader.
# takes url, array of custom tags, and optional filename for caching results
# provides #each_item and #item(title) methods

class RSSFeeder
def initialize feed_url, extra_tags=[], cache=nil
raise 'Invalid URL' unless feed_url =~ /(.*\w*\.\w*\.\w*)(\/.*)/
#separate host, rest
@url,@feed = $1, $2
@cache = cache
extra_tags.each{|tag| SimpleRSSwAttributes.feed_tags << tag}
end

#tyields [item,channel] for item with title matching name
def item name, &block
fetch
i=@data.items.find{|item| item.title =~ name} if @data
yield [i,@data.channel] if i
end
def each_item &block
fetch
@data.items.each{|item| yield item}
end

private
def time_to_fetch?
@timestamp.nil? || (@timestamp < Time.now)
end

def fetch
#read the cache if we don't have data
if !@data && @cache
File.open(@cache, "r") {|f|
@timestamp = Time.parse(f.gets)
@data = SimpleRSSwAttributes.parse(f)
} if File.exists?(@cache)
end
#only fetch data from net if current data is expired
time_to_fetch? ? net_fetch : @data
end

def net_fetch
text = Net::HTTP.start(@url).get(@feed).body
@data = SimpleRSSwAttributes.parse(text)
#try to create a reasonable expiration date. Defaults to 10 mins in future
date = @data.lastBuildDate || @data.pubDate ||
@data.expirationDate || Time.now
@timestamp = date + (@data.ttl ? @data.ttl.to_i*60 : 600)
@timestamp = Time.now + 600 if @timestamp < Time.now

File.open(@cache, "w+"){|f|
f.puts @timestamp;
f.write text
} if @cache
end
end


if __FILE__==$0
exit(-1+puts("Usage #{$0} zipcode [-f]\nGives current temperature
for zipcode, "+
"-f to get forecast too").to_i) if ARGV.size < 1
zipcode = ARGV[0]

yahoo_tags = %w(yweather:condition yweather:location yweather:forecast)
w = RSSFeeder.new("xml.weather.yahoo.com/forecastrss?p=#{zipcode}",
yahoo_tags, "yahoo#{zipcode}.xml")
w.item(/Conditions/) { |item,chan|
puts "The #{item.title} are:\n\t#{chan.yweather_condition.temp}F and "+
"#{chan.yweather_condition.text}"
}
w.item(/Conditions/) { |item,chan|
puts "\nThe forecast for #{chan.yweather_location.city}, "+
"#{chan.yweather_location.region} for #{chan.yweather_forecast.day}, "+
"#{chan.yweather_forecast.date} is:\n"+
"\t#{chan.yweather_forecast.text} with a high of
#{chan.yweather_forecast.high} "+
"and a low of #{chan.yweather_forecast.low}"
} if ARGV[1]=~/f/i
#catch errors
w.item(/not found/) { |item,chan| puts item.description }

#Alternate feed
#w2 = RSSFeeder.new("rss.weather.com/weather/rss/local/#{zipcode}?cm_ven=LWO&cm_cat=rss&par=LWO_rss")
#w2.item(/Current Weather/){|item,rss|
# puts item.title,item.description.gsub(/&deg;/,248.chr)}
#w2.item(/10-Day Forecast/){|item,rss|
# puts item.title,item.description.gsub(/&deg;/,248.chr)} if ARGV[1]=~/f/i

end