parse_monitors/report/
htc.rs

1use crate::{
2    cfd::{self, BaselineTrait},
3    report::ReportError,
4    MonitorsLoader,
5};
6use rayon::prelude::*;
7use std::{fs::File, io::Write, path::Path};
8
9#[derive(Debug, thiserror::Error)]
10pub enum HTCError {
11    #[error("dome seeing report error")]
12    Reporting(#[from] ReportError),
13}
14type Result<T> = std::result::Result<T, HTCError>;
15pub struct HTC<const CFD_YEAR: u32> {
16    part: u8,
17    stats_time_range: f64,
18}
19impl<const CFD_YEAR: u32> HTC<CFD_YEAR> {
20    pub fn new(part: u8, stats_time_range: f64) -> Self {
21        Self {
22            part,
23            stats_time_range,
24        }
25    }
26}
27impl<const CFD_YEAR: u32> super::Report<CFD_YEAR> for HTC<CFD_YEAR> {
28    type Error = HTCError;
29    /// Chapter section
30    fn chapter_section(
31        &self,
32        cfd_case: cfd::CfdCase<CFD_YEAR>,
33        _: Option<usize>,
34    ) -> Result<String> {
35        let path_to_case = cfd::Baseline::<CFD_YEAR>::path()
36            .map_err(|e| ReportError::Baseline(e))?
37            .join(&cfd_case.to_string());
38        let monitors = MonitorsLoader::<CFD_YEAR>::default()
39            .data_path(path_to_case)
40            .load()
41            .map_err(|e| ReportError::Monitors(e))?;
42        Ok(format!(
43            r#"
44\section{{{}}}
45\begin{{longtable}}{{crrrr}}\toprule
46 ELEMENT & MEAN & STD & MIN & MAX \\\hline
47{}
48\bottomrule
49\end{{longtable}}
50"#,
51            &cfd_case.to_pretty_string(),
52            monitors
53                .htc_latex_table(self.stats_time_range)
54                .unwrap_or_default()
55        ))
56    }
57    /// Chapter assembly
58    fn chapter(
59        &self,
60        zenith_angle: cfd::ZenithAngle,
61        cfd_cases_subset: Option<&[cfd::CfdCase<CFD_YEAR>]>,
62    ) -> Result<()> {
63        let report_path = Path::new("report");
64        let part = format!("part{}.", self.part);
65        let chapter_filename = match zenith_angle {
66            cfd::ZenithAngle::Zero => part + "chapter1.tex",
67            cfd::ZenithAngle::Thirty => part + "chapter2.tex",
68            cfd::ZenithAngle::Sixty => part + "chapter3.tex",
69        };
70        let cfd_cases = cfd::Baseline::<CFD_YEAR>::at_zenith(zenith_angle)
71            .into_iter()
72            .filter(|cfd_case| {
73                if let Some(cases) = cfd_cases_subset {
74                    cases.contains(cfd_case)
75                } else {
76                    true
77                }
78            })
79            .collect::<Vec<cfd::CfdCase<CFD_YEAR>>>();
80        let results: Vec<_> = cfd_cases
81            .into_par_iter()
82            .map(|cfd_case| self.chapter_section(cfd_case, None).unwrap())
83            .collect();
84        let path = report_path.join(chapter_filename);
85        let mut file =
86            File::create(&path).map_err(|e| ReportError::Creating(e, path.to_path_buf()))?;
87        write!(
88            file,
89            r#"
90\chapter{{{}}}
91{}
92"#,
93            zenith_angle.chapter_title(),
94            results.join("\n")
95        )
96        .map_err(|e| ReportError::Writing(e, path.to_path_buf()))?;
97        Ok(())
98    }
99    fn part_name(&self) -> String {
100        String::from("HTC")
101    }
102}