1use crate::{
7 aim::{WriterLike, Writer},
8 literals::{Literal, parse_unsigned},
9 values::Value,
10};
11use nom::{
12 IResult, Parser,
13 character::complete::{char, multispace0},
14 combinator::map,
15 sequence::delimited,
16};
17use std::{
18 fmt,
19};
20
21#[derive(Debug, Clone, PartialEq)]
25pub struct Eval {
26 score: u32,
27 count: u32,
28}
29
30impl Eval {
31 pub fn as_value(score: u32, count: u32) -> Value {
33 Value::Eval(Eval { score, count })
34 }
35
36 pub fn to_pass(&self) -> Value {
38 Self::as_value(self.score + 1, self.count + 1)
39 }
40
41 pub fn to_fail(&self) -> Value {
43 Self::as_value(self.score, self.count + 1)
44 }
45
46 pub fn score(&self) -> u32 {
47 self.score
48 }
49
50 pub fn count(&self) -> u32 {
51 self.count
52 }
53
54 pub fn ratio(&self) -> Value {
56 if self.count == 0 {
57 Value::Literal(Literal::Number(0.0))
58 } else {
59 Value::Literal(Literal::Number(self.score as f64 / self.count as f64))
60 }
61 }
62
63 pub fn print(&self, writer: &mut Writer) {
65 writer.write_unsigned(self.score);
66 writer.write_str(" / ");
67 writer.write_unsigned(self.count);
68 }
69
70 pub fn to_formula(&self) -> String {
72 let mut writer = Writer::formulizer();
73 self.print(&mut writer);
74 writer.finish()
75 }
76}
77
78impl WriterLike for Eval {
79 fn write(&self, writer: &mut Writer) {
80 self.print(writer);
81 }
82}
83
84impl fmt::Display for Eval {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 write!(f, "{}", self.to_stringized())
87 }
88}
89
90pub fn parse_eval(input: &str) -> IResult<&str, Eval> {
92 map(
93 (
94 parse_unsigned,
95 delimited(multispace0, char('/'), multispace0),
96 parse_unsigned,
97 ),
98 |(score, _, count)| Eval { score, count },
99 )
100 .parse(input)
101}