1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use std::error::Error;
use std::fmt;
#[derive(Debug, Clone, Copy)]
pub struct Grade {
val: usize,
}
impl fmt::Display for Grade {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let out_val = (self.val as f32) / 10.0;
write!(f, "{:.1}", out_val)
}
}
impl PartialEq for Grade {
fn eq(&self, other: &Self) -> bool {
self.val == other.val
}
}
impl Grade {
pub fn from(input: &str) -> Result<Grade, Box<dyn Error>> {
let parsed_val = input.replace(",", ".").parse::<f32>()?;
let val = (parsed_val * 10.0) as usize;
if val >= 10 && val <= 50 {
Ok(Grade { val })
} else {
Err(format!("{} is out of bounds! Must be between 1.0 and 5.0", input).into())
}
}
pub fn verbal(&self) -> &str {
if self.val >= 10 && self.val < 16 {
"Grade A"
} else if self.val >= 16 && self.val < 25 {
"Grade B"
} else if self.val >= 26 && self.val < 35 {
"Grade C"
} else if self.val >= 36 && self.val < 41 {
"Grade D"
} else if self.val >= 41 && self.val <= 50 {
"Grade F"
} else {
unreachable!()
}
}
}
pub fn avg(grade_list: &[Grade]) -> Option<Grade> {
if !grade_list.is_empty() {
let acc: usize = grade_list.iter().map(|e| e.val).sum();
let grade = (acc / grade_list.len()) as usize;
Some(Grade { val: grade })
} else {
None
}
}
pub fn avg_prec(grade_list: &[Grade]) -> Option<f64> {
if !grade_list.is_empty() {
let acc: usize = grade_list.iter().map(|grade| grade.val).sum();
Some((acc as f64) / (10.0 * grade_list.len() as f64))
} else {
None
}
}