Skip to content

Commit 5f46a75

Browse files
authored
Merge pull request #9 from Jim-Hodapp-Coaching/split_app_logic_and_use_debug_flag
Split app logic and use debug flag for response output
2 parents 896ad9f + 61680eb commit 5f46a75

File tree

2 files changed

+186
-162
lines changed

2 files changed

+186
-162
lines changed

src/lib.rs

Lines changed: 186 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88
//!
99
//! See the `LICENSE` file for Copyright and license details.
1010
//!
11-
//!
11+
12+
use rand::{thread_rng, Rng};
13+
use reqwest::blocking::Client;
14+
use reqwest::header::CONTENT_TYPE;
15+
use serde::{Serialize, Deserialize};
16+
use std::fmt;
1217
use clap::{Parser};
1318

1419
/// Defines the Ambi Mock Client command line interface as a struct
@@ -24,6 +29,185 @@ pub struct Cli {
2429
pub debug: bool,
2530
}
2631

32+
33+
#[derive(Serialize, Deserialize)]
34+
struct Reading {
35+
temperature: String,
36+
humidity: String,
37+
pressure: String,
38+
dust_concentration: String,
39+
air_purity: String
40+
}
41+
42+
impl Reading {
43+
fn new(
44+
temperature: String,
45+
humidity: String,
46+
pressure: String,
47+
dust_concentration: String,
48+
air_purity: String
49+
) -> Reading {
50+
Reading {
51+
temperature,
52+
humidity,
53+
pressure,
54+
dust_concentration,
55+
air_purity
56+
}
57+
}
58+
}
59+
60+
#[derive(Debug, PartialEq)]
61+
enum AirPurity {
62+
Dangerous,
63+
High,
64+
Low,
65+
FreshAir
66+
}
67+
68+
impl AirPurity {
69+
fn from_value(value: u16) -> AirPurity {
70+
match value {
71+
0..=50 => return AirPurity::FreshAir,
72+
51..=100 => return AirPurity::Low,
73+
101..=150 => return AirPurity::High,
74+
151.. => return AirPurity::Dangerous,
75+
};
76+
}
77+
}
78+
79+
// implements fmt::Display for AirPurity so that we can call .to_string() on
80+
// each enum value
81+
impl fmt::Display for AirPurity {
82+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83+
match self {
84+
AirPurity::Low => write!(f, "Fresh Air"),
85+
AirPurity::High => write!(f, "Low Pollution"),
86+
AirPurity::Dangerous => write!(f, "High Pollution"),
87+
AirPurity::FreshAir => write!(f, "Dangerous Pollution")
88+
}
89+
}
90+
}
91+
92+
fn random_gen_humidity() -> String {
93+
let mut rng = thread_rng();
94+
let value = rng.gen_range(0.0..=100.0);
95+
format!("{:.1}", value)
96+
}
97+
98+
fn random_gen_temperature() -> String {
99+
let mut rng = thread_rng();
100+
let value = rng.gen_range(15.0..=35.0);
101+
format!("{:.1}", value)
102+
}
103+
104+
fn random_gen_pressure() -> String {
105+
let mut rng = thread_rng();
106+
rng.gen_range(900..=1100).to_string()
107+
}
108+
109+
fn random_gen_dust_concentration() -> String {
110+
let mut rng = thread_rng();
111+
rng.gen_range(0..=1000).to_string()
112+
}
113+
27114
pub fn run(cli: &Cli) {
28115
println!("\r\ncli: {:?}\r\n", cli);
29-
}
116+
117+
let dust_concentration = random_gen_dust_concentration();
118+
let air_purity = AirPurity::from_value(dust_concentration.parse::<u16>().unwrap()).to_string();
119+
let reading = Reading::new(
120+
random_gen_temperature(),
121+
random_gen_humidity(),
122+
random_gen_pressure(),
123+
dust_concentration,
124+
air_purity
125+
);
126+
127+
let json = serde_json::to_string(&reading).unwrap();
128+
const URL: &str = "http://localhost:4000/api/readings/add";
129+
130+
println!("Sending POST request to {} as JSON: {}", URL, json);
131+
132+
let client = Client::new();
133+
let res = client
134+
.post(URL)
135+
.header(CONTENT_TYPE, "application/json")
136+
.body(json)
137+
.send();
138+
139+
match res {
140+
Ok(response) => {
141+
match cli.debug {
142+
true => println!("Response from Ambi backend: {:#?}", response),
143+
false => println!("Response from Ambi backend: {:?}", response.status().as_str())
144+
}
145+
}
146+
Err(e) => {
147+
match cli.debug {
148+
// Print out the entire reqwest::Error for verbose debugging
149+
true => eprintln!("Response error from Ambi backend: {:?}", e),
150+
// Keep the error reports more succinct
151+
false => {
152+
if e.is_request() {
153+
eprintln!("Response error from Ambi backend: request error");
154+
} else if e.is_timeout() {
155+
eprintln!("Response error from Ambi backend: request timed out");
156+
} else {
157+
eprintln!("Response error from Ambi backend: specific error type unknown");
158+
}
159+
}
160+
}
161+
}
162+
}
163+
}
164+
165+
#[cfg(test)]
166+
mod tests {
167+
use super::*;
168+
use regex::Regex;
169+
170+
#[test]
171+
fn random_gen_humidity_returns_correctly_formatted_humidity_data() {
172+
let result = random_gen_humidity();
173+
let regex = Regex::new(r"\d{1,2}.\d{1}").unwrap();
174+
175+
assert!(regex.is_match(&result));
176+
}
177+
178+
#[test]
179+
fn random_gen_temperature_returns_correctly_formatted_humidity_data() {
180+
let result = random_gen_temperature();
181+
let regex = Regex::new(r"\d{1,2}.\d{1}").unwrap();
182+
183+
assert!(regex.is_match(&result));
184+
}
185+
186+
#[test]
187+
fn random_gen_pressure_returns_correctly_formatted_pressure_data() {
188+
let result = random_gen_pressure();
189+
let regex = Regex::new(r"\d{3,4}").unwrap();
190+
assert!(regex.is_match(&result));
191+
}
192+
193+
#[test]
194+
fn random_gen_dust_concentration_returns_correctly_formatted_pressure_data() {
195+
let result = random_gen_dust_concentration();
196+
let regex = Regex::new(r"\d{0,4}").unwrap();
197+
assert!(regex.is_match(&result));
198+
}
199+
200+
#[test]
201+
fn air_purity_from_value_returns_correct_enum() {
202+
let mut rng = thread_rng();
203+
let fresh_air = rng.gen_range(0..=50);
204+
let low = rng.gen_range(51..=100);
205+
let high = rng.gen_range(101..=150);
206+
let dangerous = rng.gen_range(151..u16::MAX);
207+
208+
assert_eq!(AirPurity::from_value(fresh_air), AirPurity::FreshAir);
209+
assert_eq!(AirPurity::from_value(low), AirPurity::Low);
210+
assert_eq!(AirPurity::from_value(high), AirPurity::High);
211+
assert_eq!(AirPurity::from_value(dangerous), AirPurity::Dangerous);
212+
}
213+
}

src/main.rs

Lines changed: 0 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -10,97 +10,11 @@
1010
//! See the `LICENSE` file for Copyright and license details.
1111
//!
1212
13-
use rand::{thread_rng, Rng};
14-
use reqwest::blocking::Client;
15-
use reqwest::header::CONTENT_TYPE;
16-
use serde::{Serialize, Deserialize};
17-
use std::fmt;
1813
use clap::{Parser};
1914

2015
// Internal library namespace for separation of app logic
2116
use ambi_mock_client;
2217

23-
#[derive(Serialize, Deserialize)]
24-
struct Reading {
25-
temperature: String,
26-
humidity: String,
27-
pressure: String,
28-
dust_concentration: String,
29-
air_purity: String
30-
}
31-
32-
impl Reading {
33-
fn new(
34-
temperature: String,
35-
humidity: String,
36-
pressure: String,
37-
dust_concentration: String,
38-
air_purity: String
39-
) -> Reading {
40-
Reading {
41-
temperature,
42-
humidity,
43-
pressure,
44-
dust_concentration,
45-
air_purity
46-
}
47-
}
48-
}
49-
50-
#[derive(Debug, PartialEq)]
51-
enum AirPurity {
52-
Dangerous,
53-
High,
54-
Low,
55-
FreshAir
56-
}
57-
58-
impl AirPurity {
59-
fn from_value(value: u16) -> AirPurity {
60-
match value {
61-
0..=50 => return AirPurity::FreshAir,
62-
51..=100 => return AirPurity::Low,
63-
101..=150 => return AirPurity::High,
64-
151.. => return AirPurity::Dangerous,
65-
};
66-
}
67-
}
68-
69-
// implements fmt::Display for AirPurity so that we can call .to_string() on
70-
// each enum value
71-
impl fmt::Display for AirPurity {
72-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73-
match self {
74-
AirPurity::Low => write!(f, "Fresh Air"),
75-
AirPurity::High => write!(f, "Low Pollution"),
76-
AirPurity::Dangerous => write!(f, "High Pollution"),
77-
AirPurity::FreshAir => write!(f, "Dangerous Pollution")
78-
}
79-
}
80-
}
81-
82-
fn random_gen_humidity() -> String {
83-
let mut rng = thread_rng();
84-
let value = rng.gen_range(0.0..=100.0);
85-
format!("{:.1}", value)
86-
}
87-
88-
fn random_gen_temperature() -> String {
89-
let mut rng = thread_rng();
90-
let value = rng.gen_range(15.0..=35.0);
91-
format!("{:.1}", value)
92-
}
93-
94-
fn random_gen_pressure() -> String {
95-
let mut rng = thread_rng();
96-
rng.gen_range(900..=1100).to_string()
97-
}
98-
99-
fn random_gen_dust_concentration() -> String {
100-
let mut rng = thread_rng();
101-
rng.gen_range(0..=1000).to_string()
102-
}
103-
10418
fn main() {
10519
// Parses the provided command line interface arguments and flags
10620
let cli = ambi_mock_client::Cli::parse();
@@ -111,78 +25,4 @@ fn main() {
11125
}
11226

11327
ambi_mock_client::run(&cli);
114-
115-
let dust_concentration = random_gen_dust_concentration();
116-
let air_purity = AirPurity::from_value(dust_concentration.parse::<u16>().unwrap()).to_string();
117-
let reading = Reading::new(
118-
random_gen_temperature(),
119-
random_gen_humidity(),
120-
random_gen_pressure(),
121-
dust_concentration,
122-
air_purity
123-
);
124-
125-
let json = serde_json::to_string(&reading).unwrap();
126-
const URL: &str = "http://localhost:4000/api/readings/add";
127-
128-
println!("Sending POST request to {} as JSON: {}", URL, json);
129-
130-
let client = Client::new();
131-
let res = client
132-
.post(URL)
133-
.header(CONTENT_TYPE, "application/json")
134-
.body(json)
135-
.send();
136-
137-
println!("Response: {:#?}", res);
138-
}
139-
140-
#[cfg(test)]
141-
mod tests {
142-
use super::*;
143-
use regex::Regex;
144-
145-
#[test]
146-
fn random_gen_humidity_returns_correctly_formatted_humidity_data() {
147-
let result = random_gen_humidity();
148-
let regex = Regex::new(r"\d{1,2}.\d{1}").unwrap();
149-
150-
assert!(regex.is_match(&result));
151-
}
152-
153-
#[test]
154-
fn random_gen_temperature_returns_correctly_formatted_humidity_data() {
155-
let result = random_gen_temperature();
156-
let regex = Regex::new(r"\d{1,2}.\d{1}").unwrap();
157-
158-
assert!(regex.is_match(&result));
159-
}
160-
161-
#[test]
162-
fn random_gen_pressure_returns_correctly_formatted_pressure_data() {
163-
let result = random_gen_pressure();
164-
let regex = Regex::new(r"\d{3,4}").unwrap();
165-
assert!(regex.is_match(&result));
166-
}
167-
168-
#[test]
169-
fn random_gen_dust_concentration_returns_correctly_formatted_pressure_data() {
170-
let result = random_gen_dust_concentration();
171-
let regex = Regex::new(r"\d{0,4}").unwrap();
172-
assert!(regex.is_match(&result));
173-
}
174-
175-
#[test]
176-
fn air_purity_from_value_returns_correct_enum() {
177-
let mut rng = thread_rng();
178-
let fresh_air = rng.gen_range(0..=50);
179-
let low = rng.gen_range(51..=100);
180-
let high = rng.gen_range(101..=150);
181-
let dangerous = rng.gen_range(151..u16::MAX);
182-
183-
assert_eq!(AirPurity::from_value(fresh_air), AirPurity::FreshAir);
184-
assert_eq!(AirPurity::from_value(low), AirPurity::Low);
185-
assert_eq!(AirPurity::from_value(high), AirPurity::High);
186-
assert_eq!(AirPurity::from_value(dangerous), AirPurity::Dangerous);
187-
}
18828
}

0 commit comments

Comments
 (0)