rsv_lib/excel/
sample.rs

1use crate::args::Sample;
2use crate::utils::cli_result::CliResult;
3use crate::utils::excel::datatype_vec_to_string;
4use crate::utils::filename::new_path;
5use crate::utils::priority_queue::PriorityQueue;
6use crate::utils::reader::ExcelReader;
7use crate::utils::table::Table;
8use crate::utils::writer::Writer;
9use rand::rng;
10use rand::rngs::StdRng;
11use rand::{Rng, SeedableRng};
12use std::borrow::Cow;
13use std::path::Path;
14use std::time::Instant;
15
16impl Sample {
17    pub fn excel_run(&self) -> CliResult {
18        let path = &self.path();
19        let time_limit = (self.time_limit - 0.7).clamp(0.0, f32::MAX);
20
21        // open files
22        let mut range = ExcelReader::new(path, self.sheet)?;
23
24        // header
25        let header = match self.no_header {
26            true => None,
27            false => match range.next() {
28                Some(r) => Some(datatype_vec_to_string(r)),
29                None => return Ok(()),
30            },
31        };
32
33        // seed
34        let mut rng = match self.seed {
35            Some(s) => StdRng::seed_from_u64(s as u64),
36            None => StdRng::from_rng(&mut rng()),
37        };
38
39        // read
40        let time = Instant::now();
41        let mut queue = PriorityQueue::with_capacity(self.n);
42        for (line_n, r) in range.iter().skip(range.next_called).enumerate() {
43            let priority = rng.random::<f64>();
44            if queue.can_insert(priority) {
45                let line = datatype_vec_to_string(r);
46                queue.push(line_n, priority, line);
47            }
48
49            if time_limit > 0.0 && line_n % 10000 == 0 && time.elapsed().as_secs_f32() >= time_limit
50            {
51                break;
52            }
53        }
54
55        match (self.export, self.show_number) {
56            (true, _) => write_to_file(path, header, queue),
57            (false, true) => print_to_stdout(header, queue),
58            (false, false) => print_to_stdout_no_number(header, queue),
59        }
60
61        Ok(())
62    }
63}
64
65fn write_to_file(path: &Path, header: Option<String>, queue: PriorityQueue<String>) {
66    // new file
67    let out = new_path(path, "-sampled").with_extension("csv");
68    let mut wtr = Writer::new(&out).unwrap();
69    if let Some(r) = header {
70        wtr.write_str_unchecked(&r);
71    }
72    for r in queue.into_sorted_items() {
73        wtr.write_str_unchecked(&r.item);
74    }
75
76    println!("Saved to file: {}", out.display());
77}
78
79fn print_to_stdout(header: Option<String>, queue: PriorityQueue<String>) {
80    let mut table = Table::new();
81
82    // header
83    if let Some(h) = header {
84        table.add_record([Cow::Borrowed("#"), Cow::Borrowed(""), Cow::from(h)]);
85    }
86
87    // samples
88    queue.into_sorted_items().into_iter().for_each(|i| {
89        table.add_record([
90            Cow::from(i.line_n_as_string()),
91            Cow::Borrowed("->"),
92            Cow::from(i.item),
93        ])
94    });
95
96    table.print_blank_unchecked();
97}
98
99fn print_to_stdout_no_number(header: Option<String>, queue: PriorityQueue<String>) {
100    let mut wtr = Writer::stdout().unwrap();
101
102    // header
103    if let Some(h) = header {
104        wtr.write_str_unchecked(h);
105    }
106
107    // samples
108    queue.into_sorted_items().into_iter().for_each(|i| {
109        wtr.write_str_unchecked(i.item);
110    });
111}