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 let mut range = ExcelReader::new(path, self.sheet)?;
23
24 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 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 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 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 if let Some(h) = header {
84 table.add_record([Cow::Borrowed("#"), Cow::Borrowed(""), Cow::from(h)]);
85 }
86
87 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 if let Some(h) = header {
104 wtr.write_str_unchecked(h);
105 }
106
107 queue.into_sorted_items().into_iter().for_each(|i| {
109 wtr.write_str_unchecked(i.item);
110 });
111}