Last active
August 13, 2016 23:27
-
-
Save apeiros/9c9b9d39292bbeb86357f95961bcdd17 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Temperature | |
KelvinToCelsius = 273.15 | |
KelvinToFahrenheit = 459.67 | |
FahrenheitFactor = 5.0/9 | |
def self.from_kelvin(kelvin) # could just alias | |
new(k: kelvin) | |
end | |
def self.from_celsius(celsius) # IMO should be just named "celsius" | |
new(c: celsius) | |
end | |
def self.from_fahrenheit(fahrenheit) | |
new(f: fahrenheit) | |
end | |
attr_reader :in_kelvin | |
def initialize(k: nil, c: nil, f: nil) | |
if (k && c) || (c && f) || (k && f) | |
raise ArgumentError, "Must only pass one of k, c or f" | |
elsif k | |
@in_kelvin = k | |
elsif c | |
@in_kelvin = (c + KelvinToCelsius) | |
elsif f | |
@in_kelvin = ((f + KelvinToFahrenheit) * FahrenheitFactor) | |
else | |
raise ArgumentError, "Must only pass at least one of kelvin, c or f" | |
end | |
end | |
def in_celsius | |
@in_kelvin - KelvinToCelsius | |
end | |
def in_fahrenheit | |
(@in_kelvin / FahrenheitFactor) - KelvinToFahrenheit | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# @example | |
# Temperature.new(273.15).celsius # => 0.0 | |
# Temperature.celsius(50).in_unit(:fahrenheit) # => (122/1) | |
# Temperature.from_unit(50, :celsius).to_s(:fahrenheit) # => "122.00 °F" | |
class Temperature | |
CelsiusSummand = 27315/100r | |
FahrenheitSummand = 45967/100r | |
FahrenheitFactor = 5/9r | |
@inspect_unit = :kelvin | |
class << self | |
attr_accessor :inspect_unit | |
end | |
def self.symbol(unit) | |
case unit | |
when :kelvin then "K" | |
when :celsius then "°C" | |
when :fahrenheit then "°F" | |
else raise ArgumentError, "Unknown unit #{unit.inspect}, expected :kelvin, :celsius or :fahrenheit" | |
end | |
end | |
def self.from_unit(value, unit) | |
case unit | |
when :kelvin then kelvin(value) | |
when :celsius then celsius(value) | |
when :fahrenheit then fahrenheit(value) | |
else raise ArgumentError, "Unknown unit #{unit.inspect}, expected :kelvin, :celsius or :fahrenheit" | |
end | |
end | |
def self.kelvin(kelvin) | |
new(kelvin) | |
end | |
def self.celsius(celsius) | |
new(celsius + CelsiusSummand) | |
end | |
def self.fahrenheit(fahrenheit) | |
new((fahrenheit + FahrenheitSummand) * FahrenheitFactor) | |
end | |
attr_reader :kelvin | |
def initialize(kelvin) | |
raise ArgumentError, "Invalid value, kelvin must be zero or positive" if kelvin < 0 | |
@kelvin = kelvin | |
end | |
def celsius | |
@kelvin - CelsiusSummand | |
end | |
def fahrenheit | |
(@kelvin / FahrenheitFactor) - FahrenheitSummand | |
end | |
def in_unit(unit) | |
case unit | |
when :kelvin then kelvin | |
when :celsius then celsius | |
when :fahrenheit then fahrenheit | |
else raise ArgumentError, "Unknown unit #{unit.inspect}, expected :kelvin, :celsius or :fahrenheit" | |
end | |
end | |
def to_s(positional_unit=:kelvin, unit: nil, precision: 2) | |
unit ||= positional_unit | |
value = in_unit(unit) | |
sprintf "%.*f\u00a0%s", precision, value, self.class.symbol(unit) | |
end | |
def inspect | |
"<#{to_s(self.class.inspect_unit)}>" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment