Skip to content

Instantly share code, notes, and snippets.

@wulab
Last active August 6, 2018 10:45
Show Gist options
  • Save wulab/1bab419a8ce105a4b9f3 to your computer and use it in GitHub Desktop.
Save wulab/1bab419a8ce105a4b9f3 to your computer and use it in GitHub Desktop.
Weather-O-Rama Inc.’s next generation, Internet-based Weather Monitoring Station
module Subject
def register_observer()
raise NotImplementedError
end
def remove_observer()
raise NotImplementedError
end
def notify_observers()
raise NotImplementedError
end
end
module Observer
def update()
raise NotImplementedError
end
end
module DisplayElement
def display()
raise NotImplementedError
end
# UTF-8 encoding table and Unicode characters
# http://www.utf8-chartable.de/unicode-utf8-table.pl?start=9472&unicodeinhtml=dec
def box(title, body, width=78)
lines = []
lines << "╔%s╗" % ( "[ #{title} ]".center(width, "═") )
lines << "║%s║" % ( "░" * width )
lines << "║%s║" % ( " #{body} ".center(width, "░") )
lines << "║%s║" % ( "░" * width )
lines << "╚%s╝" % ( "═" * width )
lines.join("\n")
end
end
###
class WeatherData
include Subject
attr_reader :temperature, :humidity, :pressure
attr_reader :observers
def initialize
@observers = []
end
def register_observer(observer)
observers.push(observer)
end
def remove_observer(observer)
observers.delete(observer)
end
def notify_observers()
observers.each(&:update)
end
def measurements_changed()
notify_observers()
end
def set_measurements(temperature, humidity, pressure)
@temperature = temperature
@humidity = humidity
@pressure = pressure
measurements_changed()
end
end
class CurrentConditionsDisplay
include Observer
include DisplayElement
attr_reader :temperature, :humidity
attr_reader :weather_data
def initialize(weather_data)
@weather_data = weather_data
@weather_data.register_observer(self)
end
def update()
@temperature = weather_data.temperature
@humidity = weather_data.humidity
display()
end
def display()
title = "Current Conditions"
body = "#{temperature} F degrees and #{humidity}% humidity"
puts box(title, body)
end
end
class ForecastDisplay
include Observer
include DisplayElement
attr_reader :current_pressure, :last_pressure
attr_reader :weather_data
def initialize(weather_data)
@current_pressure = 29.92
@weather_data = weather_data
@weather_data.register_observer(self)
end
def update()
@last_pressure = current_pressure
@current_pressure = weather_data.pressure
display()
end
def display()
title = "Forecast"
body = if current_pressure > last_pressure
"Improving weather on the way!"
elsif current_pressure < last_pressure
"Watch out for cooler, rainy weather"
else
"More of the same"
end
puts box(title, body)
end
end
class StatisticsDisplay
include Observer
include DisplayElement
attr_reader :max_temp, :min_temp, :temp_sum, :num_readings
attr_reader :weather_data
def initialize(weather_data)
@max_temp = 0
@min_temp = 200
@temp_sum = 0
@num_readings = 0
@weather_data = weather_data
@weather_data.register_observer(self)
end
def update()
@temp_sum += weather_data.temperature
@num_readings += 1
if weather_data.temperature > @max_temp
@max_temp = weather_data.temperature
end
if weather_data.temperature < @min_temp
@min_temp = weather_data.temperature
end
display()
end
def display()
title = "Statistics"
body = "Avg/Max/Min temperature = %s/%s/%s"
body = body % [temp_sum/num_readings, max_temp, min_temp]
puts box(title, body)
end
end
class HeatIndexDisplay
include Observer
include DisplayElement
attr_reader :heat_index
attr_reader :weather_data
def initialize(weather_data)
@weather_data = weather_data
@weather_data.register_observer(self)
end
def update()
@heat_index = compute_heat_index(
weather_data.temperature,
weather_data.humidity
)
display()
end
# The Heat Index Equation
# http://www.hpc.ncep.noaa.gov/html/heatindex_equation.shtml
def compute_heat_index(t, rh)
-42.379 + 2.04901523*t + 10.14333127*rh - 0.22475541*t*rh -
0.00683783*t*t - 0.05481717*rh*rh + 0.00122874*t*t*rh +
0.00085282*t*rh*rh - 0.00000199*t*t*rh*rh
end
def display()
title = "Heat Index"
body = "Heat index is %.2f" % @heat_index
puts box(title, body)
end
end
###
class WeatherStation
def self.start()
weather_data = WeatherData.new
current_display = CurrentConditionsDisplay.new(weather_data)
forecase_display = ForecastDisplay.new(weather_data)
statistics_display = StatisticsDisplay.new(weather_data)
heat_display = HeatIndexDisplay.new(weather_data)
weather_data.set_measurements(80, 65, 30.4)
weather_data.set_measurements(82, 70, 29.2)
weather_data.set_measurements(78, 90, 29.2)
end
end
if $0 == __FILE__
WeatherStation.start()
end
@wulab
Copy link
Author

wulab commented Sep 19, 2014

$ ruby weather_o_rama.rb 
╔════════════════════════════[ Current Conditions ]════════════════════════════╗
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░ 80 F degrees and 65% humidity ░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
╚══════════════════════════════════════════════════════════════════════════════╝
╔═════════════════════════════════[ Forecast ]═════════════════════════════════╗
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░ Improving weather on the way! ░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
╚══════════════════════════════════════════════════════════════════════════════╝
╔════════════════════════════════[ Statistics ]════════════════════════════════╗
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░ Avg/Max/Min temperature = 80/80/80 ░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
╚══════════════════════════════════════════════════════════════════════════════╝
╔════════════════════════════════[ Heat Index ]════════════════════════════════╗
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░ Heat index is 82.37 ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
╚══════════════════════════════════════════════════════════════════════════════╝
╔════════════════════════════[ Current Conditions ]════════════════════════════╗
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░ 82 F degrees and 70% humidity ░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
╚══════════════════════════════════════════════════════════════════════════════╝
╔═════════════════════════════════[ Forecast ]═════════════════════════════════╗
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░ Watch out for cooler, rainy weather ░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
╚══════════════════════════════════════════════════════════════════════════════╝
╔════════════════════════════════[ Statistics ]════════════════════════════════╗
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░ Avg/Max/Min temperature = 81/82/80 ░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
╚══════════════════════════════════════════════════════════════════════════════╝
╔════════════════════════════════[ Heat Index ]════════════════════════════════╗
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░ Heat index is 86.44 ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
╚══════════════════════════════════════════════════════════════════════════════╝
╔════════════════════════════[ Current Conditions ]════════════════════════════╗
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░ 78 F degrees and 90% humidity ░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
╚══════════════════════════════════════════════════════════════════════════════╝
╔═════════════════════════════════[ Forecast ]═════════════════════════════════╗
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ More of the same ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
╚══════════════════════════════════════════════════════════════════════════════╝
╔════════════════════════════════[ Statistics ]════════════════════════════════╗
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░ Avg/Max/Min temperature = 80/82/78 ░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
╚══════════════════════════════════════════════════════════════════════════════╝
╔════════════════════════════════[ Heat Index ]════════════════════════════════╗
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░ Heat index is 80.49 ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
║░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░║
╚══════════════════════════════════════════════════════════════════════════════╝

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment