parse_monitors/monitors/reports/loader/
y2021_25.rs

1use std::time::Instant;
2use std::{fs::File, io::Read, path::Path};
3
4use regex::Regex;
5
6use crate::{Exertion, Monitors, MonitorsError};
7
8use super::MonitorsLoader;
9
10type Result<T> = std::result::Result<T, MonitorsError>;
11
12impl<const Y: u32> MonitorsLoader<Y> {
13    #[cfg(feature = "bzip2")]
14    fn decompress(&self) -> Result<String> {
15        let mut contents = String::new();
16        let data_path = Path::new(&self.path).with_extension("csv.bz2");
17        let csv_file =
18            File::open(&data_path).map_err(|e| MonitorsError::Io(e, data_path.clone()))?;
19
20        log::info!("Loading {:?}...", csv_file);
21        let buf = std::io::BufReader::new(csv_file);
22        let mut bz2 = bzip2::bufread::BzDecoder::new(buf);
23        bz2.read_to_string(&mut contents)
24            .map_err(|e| MonitorsError::Io(e, data_path))?;
25        Ok(contents)
26    }
27    #[cfg(not(feature = "bzip2"))]
28    fn decompress(&self) -> Result<String> {
29        use flate2::read::GzDecoder;
30
31        use crate::MonitorsError;
32
33        let mut contents = String::new();
34        let data_path = Path::new(&self.path).with_extension("csv.z");
35        log::info!("Loading {:?}...", data_path);
36        let csv_file =
37            File::open(&data_path).map_err(|e| MonitorsError::Io(e, data_path.clone()))?;
38        let mut gz = GzDecoder::new(csv_file);
39        gz.read_to_string(&mut contents)
40            .map_err(|e| MonitorsError::Io(e, data_path))?;
41        Ok(contents)
42    }
43    pub fn load(self) -> Result<Monitors> {
44        let now = Instant::now();
45        let contents = self.decompress()?;
46        let mut rdr = csv::Reader::from_reader(contents.as_bytes());
47
48        let headers: Vec<_> = {
49            let headers = rdr.headers()?;
50            //headers.iter().take(20).for_each(|h| println!("{}", h));
51            headers.into_iter().map(|h| h.to_string()).collect()
52        };
53        if Y == 2025 {
54            headers
55                .iter()
56                .find(|h| h.contains("M1c_"))
57                .ok_or(MonitorsError::YearMismatch(2021, Y))?;
58        }
59
60        let re_htc = Regex::new(
61            r"(\w+) Monitor: Surface Average of Heat Transfer Coefficient \(W/m\^2-K\)",
62        )?;
63        //Cabs_X Monitor 2: Force (N)
64        let re_force = Regex::new(r"(.+)_([XYZ]) Monitor(?:: Force)? \(N\)")?;
65        let re_moment = Regex::new(r"(.+)Mom_([XYZ]) Monitor(?:: Moment)? \(N-m\)")?;
66
67        let re_header = Regex::new(&self.header_regex)?;
68        let re_x_header = if let Some(re) = self.header_exclude_regex {
69            Some(Regex::new(&re)?)
70        } else {
71            None
72        };
73
74        let mut monitors = Monitors::default();
75
76        for result in rdr.records() {
77            let record = result?;
78            let time = record.iter().next().unwrap().parse::<f64>()?;
79            if time < self.time_range.0 - 1. / 40. || time > self.time_range.1 + 1. / 40. {
80                continue;
81            };
82            monitors.time.push(time);
83            for (data, header) in record.iter().skip(1).zip(headers.iter().skip(1)).filter(
84                |(_, h)| match &re_x_header {
85                    Some(re_x_header) => re_header.is_match(h) && !re_x_header.is_match(h),
86                    None => re_header.is_match(h),
87                },
88            ) {
89                // HTC
90                if let Some(capts) = re_htc.captures(header) {
91                    let key = capts.get(1).unwrap().as_str().to_owned();
92                    let value = data.parse::<f64>()?;
93                    monitors
94                        .heat_transfer_coefficients
95                        .entry(key)
96                        .or_insert_with(Vec::new)
97                        .push(value.abs());
98                }
99                // FORCE
100                if let Some(capts) = re_force.captures(header) {
101                    let key = capts.get(1).unwrap().as_str().to_owned();
102                    let value = data.parse::<f64>()?;
103                    let exertions = monitors
104                        .forces_and_moments
105                        .entry(key)
106                        .or_insert(vec![Exertion::default()]);
107                    let exertion = exertions.last_mut().unwrap();
108                    match capts.get(2).unwrap().as_str() {
109                        "X" => match exertion.force.x {
110                            Some(_) => exertions.push(Exertion::from_force_x(value)),
111                            None => {
112                                exertion.force.x = Some(value);
113                            }
114                        },
115                        "Y" => match exertion.force.y {
116                            Some(_) => exertions.push(Exertion::from_force_y(value)),
117                            None => {
118                                exertion.force.y = Some(value);
119                            }
120                        },
121                        "Z" => match exertion.force.z {
122                            Some(_) => exertions.push(Exertion::from_force_z(value)),
123                            None => {
124                                exertion.force.z = Some(value);
125                            }
126                        },
127                        &_ => (),
128                    };
129                }
130                // MOMENT
131                if let Some(capts) = re_moment.captures(header) {
132                    let key = capts
133                        .get(1)
134                        .unwrap()
135                        .as_str()
136                        .trim_end_matches('_')
137                        .to_owned();
138                    let value = data.parse::<f64>()?;
139                    let exertions = monitors
140                        .forces_and_moments
141                        .entry(key)
142                        .or_insert(vec![Exertion::default()]);
143                    let exertion = exertions.last_mut().unwrap();
144                    match capts.get(2).unwrap().as_str() {
145                        "X" => match exertion.moment.x {
146                            Some(_) => exertions.push(Exertion::from_moment_x(value)),
147                            None => {
148                                exertion.moment.x = Some(value);
149                            }
150                        },
151                        "Y" => match exertion.moment.y {
152                            Some(_) => exertions.push(Exertion::from_moment_y(value)),
153                            None => {
154                                exertion.moment.y = Some(value);
155                            }
156                        },
157                        "Z" => match exertion.moment.z {
158                            Some(_) => exertions.push(Exertion::from_moment_z(value)),
159                            None => {
160                                exertion.moment.z = Some(value);
161                            }
162                        },
163                        &_ => (),
164                    };
165                }
166            }
167        }
168        log::info!("... loaded in {:}s", now.elapsed().as_secs());
169        Ok(monitors)
170    }
171}