use std::fmt;
use std::io;
use Temperature::*;
#[derive(Debug, PartialEq, Copy, Clone)]
/**
An enum representing the different Temperature scales.
These are the available temperature scales to be converted between with this script.
*/
pub enum Temperature {
Kelvin(f64),
Celsius(f64),
Fahrenheit(f64),
Rankine(f64),
}
impl fmt::Display for Temperature {
fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
match *self {
Kelvin(k) => write!(fmtr, "{}K", k),
Celsius(c) => write!(fmtr, "{}°C", c),
Fahrenheit(f) => write!(fmtr, "{}°F", f),
Rankine(r) => write!(fmtr, "{}°R", r),
}
}
}
impl Temperature {
/// Convert the Temperature unit into Celsius
pub fn to_celsius(self) -> Temperature {
match self {
Kelvin(k) => Celsius(k - 273.15),
c @ Celsius(_) => c,
Fahrenheit(f) => Celsius((f - 32.0) * (5.0 / 9.0)),
Rankine(r) => Celsius((r - 491.67) * 5.0 / 9.0),
}
}
/// Convert the Temperature unit into Fahrenheit
pub fn to_fahrenheit(self) -> Temperature {
match self {
Kelvin(k) => Fahrenheit((k * (9.0 / 5.0)) - 459.67),
Celsius(c) => Fahrenheit((c * (9.0 / 5.0)) + 32.0),
f @ Fahrenheit(_) => f,
Rankine(r) => Fahrenheit(r - 459.67),
}
}
/// Convert the Temperature unit into Kelvin
pub fn to_kelvin(self) -> Temperature {
match self {
k @ Kelvin(_) => k,
Celsius(c) => Kelvin(c + 273.15),
Fahrenheit(f) => Kelvin((f + 459.67) * (5.0 / 9.0)),
Rankine(r) => Kelvin(r * 5.0 / 9.0),
}
}
/// Convert the Temperature unit into Rankine
pub fn to_rankine(self) -> Temperature {
match self {
r @ Rankine(_) => r,
Celsius(c) => Rankine((c + 273.15) * 9.0 / 5.0),
Fahrenheit(f) => Rankine(f + 459.67),
Kelvin(k) => Rankine(k * 9.0 / 5.0),
}
}
}
/**
# Temperature Conversion Formulas.
These are the formulas used in the crate for temperature conversions.
| From | To | Formula | Notes |
| ---- | --- | ------- | --- |
| Celsius | Fahrenheit | F = (C * 9.0 / 5.0) + 32.0 | |
| Celsius | Kelvin | K = C + 273.15 | |
| Celsius | Rankine | R = (C + 273.15) * 9.0 / 5.0 | |
| Fahrenheit | Celsius | C = (F - 32.0) * 5.0 / 9.0 | |
| Fahrenheit | Kelvin | K = (F + 459.67) * 5.0 / 9.0 | |
| Fahrenheit | Rankine | R = F + 459.67 | |
| Kelvin | Celsius | C = K - 273.15 | |
| Kelvin | Fahrenheit | F = K * 9.0 / 5.0 - 459.67 | |
| Kelvin | Rankine | R = K * 9.0 / 5.0 | |
| Rankine | Celsius | C = (R - 491.67) * 5.0 / 9.0 | |
| Rankine | Fahrenheit | F = R - 459.67 | |
| Rankine | Kelvin | K = R * 5.0 / 9.0 | |
# Memo:
The only temperature where the Kelvin and Fahrenheit values are equal is at 574.59.
The only temperature where the Celsius and Fahrenheit values are equal is at -40.
*/
pub fn convert_temp(temperature: &Temperature) -> f64 {
match *temperature {
Temperature::Fahrenheit(degrees) => (degrees - 32.0) / 1.8,
Temperature::Fahrenheit(degrees) => ((degrees - 32.0) / 1.8) + 273.15,
Temperature::Fahrenheit(degrees) => (degrees + 456.67),
Temperature::Celsius(degrees) => (degrees * 1.8) + 32.0,
Temperature::Celsius(degrees) => (degrees + 273.15),
Temperature::Celsius(degrees) => ((degrees + 273.15) * 9.0 / 5.0),
Temperature::Kelvin(degrees) => (degrees - 273.15),
Temperature::Kelvin(degrees) => ((degrees - 273.15) * 1.8) + 32.0,
Temperature::Kelvin(degrees) => (degrees * 9.0 / 5.0),
Temperature::Rankine(degrees) => ((degrees - 491.67) * 5.0 / 9.0),
Temperature::Rankine(degrees) => (degrees * 9.0 / 5.0 - 459.67),
Temperature::Rankine(degrees) => (degrees * 5.0 / 9.0),
}
}
/**
# Print the final converted temp scale
This will print the converted temperature into the temperature scale the user has requested.
*/
pub fn print_temp(temperature: &Temperature) {
match *temperature {
Temperature::Fahrenheit(degrees) => {
println!("{}F = {}C", degrees, convert_temp(temperature))
}
Temperature::Fahrenheit(degrees) => {
println!("{}F = {}K", degrees, convert_temp(temperature))
}
Temperature::Fahrenheit(degrees) => {
println!("{}F = {}R", degrees, convert_temp(temperature))
}
Temperature::Celsius(degrees) => println!("{}C = {}F", degrees, convert_temp(temperature)),
Temperature::Celsius(degrees) => println!("{}C = {}K", degrees, convert_temp(temperature)),
Temperature::Celsius(degrees) => println!("{}C = {}R", degrees, convert_temp(temperature)),
Temperature::Kelvin(degrees) => println!("{}K = {}C", degrees, convert_temp(temperature)),
Temperature::Kelvin(degrees) => println!("{}K = {}F", degrees, convert_temp(temperature)),
Temperature::Kelvin(degrees) => println!("{}K = {}R", degrees, convert_temp(temperature)),
Temperature::Rankine(degrees) => println!("{}R = {}C", degrees, convert_temp(temperature)),
Temperature::Rankine(degrees) => println!("{}R = {}F", degrees, convert_temp(temperature)),
Temperature::Rankine(degrees) => println!("{}R = {}K", degrees, convert_temp(temperature)),
}
}
/**
# Get the user input
Add a question to allow the user to specify which scale the temperature should be converted
into.
*/
pub fn get_user_temp() {
println!("\nType \"exit\" to exit the program");
loop {
let mut temp_input = String::new();
println!(
"\nPlease input a temperature you want to convert (Example: 10R, 10F, 10K, or \
-10C):"
);
io::stdin()
.read_line(&mut temp_input)
.expect("Failed to read line");
let trimmed = temp_input.trim();
if trimmed == "exit" {
break;
}
let (temp, scale) = trimmed.split_at(trimmed.len() - 1);
let temp: f64 = match temp.parse() {
Ok(num) => num,
Err(_) => continue,
};
let temp: Temperature = match scale {
"C" => Temperature::Celsius(temp),
"F" => Temperature::Fahrenheit(temp),
"K" => Temperature::Kelvin(temp),
"R" => Temperature::Rankine(temp),
_ => continue,
};
print_temp(&temp);
}
}
fn main() {
println!("This is a temperature converter!\n");
get_user_temp();
}