Coverage Report

Created: 2026-05-25 08:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/runner/work/MathCAT/MathCAT/src/main.rs
Line
Count
Source
1
// *** MathCAT doesn't normally want to build a binary ***
2
// *** This file is here because it is useful for trying out things ***
3
#![allow(clippy::needless_return)]
4
5
use libmathcat::interface::*;
6
use log::{debug, info};
7
use std::time::Instant;
8
use std::process::exit;
9
10
11
// Maybe also have this speak to test the TTS generation.
12
// There is a rust winapi crate that mirrors the WinPAI and has "Speak(...)" in it
13
14
// env RUST_LOG=DEBUG cargo run --features "include-zip"
15
cfg_if::cfg_if! {
16
    if #[cfg(feature = "include-zip")] {
17
        fn get_rules_dir() -> String {
18
          return "Rules".to_string();
19
        }
20
    } else {
21
0
        fn get_rules_dir() -> String {
22
          // for testing with zipped rules dir
23
          // let rules_path = std::env::current_exe().unwrap().parent().unwrap().join("../../../MathCATForPython/addon/globalPlugins/MathCAT/Rules");
24
0
          let rules_path = std::env::current_exe().unwrap().parent().unwrap().join("../../Rules");
25
0
          return rules_path.as_os_str().to_str().unwrap().to_string();
26
0
        }
27
    }
28
}
29
30
0
fn main() {
31
0
  env_logger::builder()
32
0
      .format_timestamp(None)
33
0
      .format_module_path(false)
34
0
      .format_indent(Some(2))
35
0
      .format_level(false)
36
0
      .init();
37
38
//    let expr = r#"
39
//    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
40
//    <mrow>
41
//      <msup>
42
//        <mi>e</mi>
43
//        <mrow>
44
//          <mo>&#x2212;</mo>
45
//          <mfrac>
46
//            <mn>1</mn>
47
//            <mn>2</mn>
48
//          </mfrac>
49
//          <msup>
50
//            <mrow>
51
//              <mrow>
52
//                <mo>(</mo>
53
//                <mrow>
54
//                  <mfrac>
55
//                    <mrow>
56
//                      <mi>x</mi>
57
//                      <mo>&#x2212;</mo>
58
//                      <mi>&#x03BC;</mi>
59
//                    </mrow>
60
//                    <mi>&#x03C3;</mi>
61
//                  </mfrac>
62
//                </mrow>
63
//                <mo>)</mo>
64
//              </mrow>
65
//            </mrow>
66
//            <mn>2</mn>
67
//          </msup>
68
//        </mrow>
69
//      </msup>
70
//    </mrow>
71
//  </math>
72
// "#;
73
  // let expr = "<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML'>
74
  //       <msup intent='power($base(2, $base),silly($exp,-1.))'>
75
  //       <mi arg='base'>x</mi>
76
  //       <mi arg='exp'>n</mi>
77
  //     </msup>
78
  //       </math>
79
  //     ";
80
  // let expr = "<mrow intent='pre@prefix(in@infix($a, x))(post@postfix($b))'>
81
  //     <mi arg='a'>A</mi>
82
  //     <mover>
83
  //         <mo intent='map'>⟶</mo>
84
  //         <mo intent='congruence'>≅</mo>
85
  //     </mover>
86
  //     <mi arg='b'>B</mi>
87
  //   </mrow>";
88
  // let expr = "<math><mi>Na</mi><mi>S</mi><mo>(</mo><mi>l</mi><mo>)</mo></math>";
89
90
91
  // let expr = "<math xmlns='http://www.w3.org/1998/Math/MathML' display='block'>
92
  //     <mrow>
93
  //       <mo stretchy='false'>[</mo>
94
  //       <mrow>
95
  //         <mi>Co</mi>
96
  //       </mrow>
97
  //       <mo stretchy='false'>(</mo>
98
  //       <mrow>
99
  //         <mi>NH</mi>
100
  //       </mrow>
101
  //       <msub>
102
  //         <mrow>
103
  //           <mrow>
104
  //             <mpadded width='0'>
105
  //               <mphantom>
106
  //                 <mi>A</mi>
107
  //               </mphantom>
108
  //             </mpadded>
109
  //           </mrow>
110
  //         </mrow>
111
  //         <mrow>
112
  //           <mrow>
113
  //             <mpadded height='0'>
114
  //               <mn>3</mn>
115
  //             </mpadded>
116
  //           </mrow>
117
  //         </mrow>
118
  //       </msub>
119
  //       <mo stretchy='false'>)</mo>
120
  //       <msub>
121
  //         <mrow>
122
  //           <mrow>
123
  //             <mpadded width='0'>
124
  //               <mphantom>
125
  //                 <mi>A</mi>
126
  //               </mphantom>
127
  //             </mpadded>
128
  //           </mrow>
129
  //         </mrow>
130
  //         <mrow>
131
  //           <mrow>
132
  //             <mpadded height='0'>
133
  //               <mn>6</mn>
134
  //             </mpadded>
135
  //           </mrow>
136
  //         </mrow>
137
  //       </msub>
138
  //       <mo stretchy='false'>]</mo>
139
  //       <msup>
140
  //         <mrow>
141
  //           <mrow>
142
  //             <mpadded width='0'>
143
  //               <mphantom>
144
  //                 <mi>A</mi>
145
  //               </mphantom>
146
  //             </mpadded>
147
  //           </mrow>
148
  //         </mrow>
149
  //         <mrow>
150
  //           <mn>3</mn>
151
  //           <mo>+</mo>
152
  //         </mrow>
153
  //       </msup>
154
  //       <mtext>&#xA0;</mtext>
155
  //       <mo stretchy='false'>(</mo>
156
  //       <mrow>
157
  //         <mi>Cl</mi>
158
  //       </mrow>
159
  //       <msub>
160
  //         <mrow>
161
  //           <mrow>
162
  //             <mpadded width='0'>
163
  //               <mphantom>
164
  //                 <mi>A</mi>
165
  //               </mphantom>
166
  //             </mpadded>
167
  //           </mrow>
168
  //         </mrow>
169
  //         <mrow>
170
  //           <mrow>
171
  //             <mpadded height='0'>
172
  //               <mn>3</mn>
173
  //             </mpadded>
174
  //           </mrow>
175
  //         </mrow>
176
  //       </msub>
177
  //       <mo stretchy='false'>)</mo>
178
  //       <msup>
179
  //         <mrow>
180
  //           <mrow>
181
  //             <mpadded width='0'>
182
  //               <mphantom>
183
  //                 <mi>A</mi>
184
  //               </mphantom>
185
  //             </mpadded>
186
  //           </mrow>
187
  //         </mrow>
188
  //         <mrow>
189
  //           <mo>&#x2212;</mo>, 
190
  //         </mrow>
191
  //       </msup>
192
  //     </mrow>
193
  //   </math>";
194
195
0
  let expr = r#"
196
0
<math> <mn>1</mn> <mi>kg</mi> <msup> <mi intent=':unit'>sec</mi> <mrow><mo>−</mo><mn>1</mn></mrow> </msup> <msup> <mi intent='unit'>m</mi> <mrow><mo>−</mo><mn>1</mn></mrow> </msup> </math>
197
0
198
0
         "#;
199
  // let instant = Instant::now();
200
201
  // let rules_dir = "".to_string();    // Use MathCATRulesDir, potentially pointing to a zipped version
202
0
  if let Err(e) = set_rules_dir(get_rules_dir()) {
203
0
    eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);
204
0
  }
205
0
  debug!("Languages: {}", libmathcat::interface::get_supported_languages().unwrap_or_default().join(", "));
206
207
  #[cfg(feature = "include-zip")]
208
  info!("***********include-zip is present**********");
209
0
  info!("Version = '{}' using Rules dir {}", get_version(), get_rules_dir());
210
0
  set_preference("Language", "en").unwrap();
211
0
  set_preference("DecimalSeparator", "Auto").unwrap();
212
0
  set_preference("BrailleCode", "UEB").unwrap();
213
0
  set_preference("BrailleNavHighlight", "On").unwrap();
214
0
  set_preference("TTS", "None").unwrap();
215
0
  set_preference("Verbosity", "Verbose").unwrap();
216
0
  set_preference("NavVerbosity", "Verbose").unwrap();
217
0
  set_preference("NavMode", "Enhanced").unwrap();
218
0
  set_preference("Impairment", "Blindness").unwrap();
219
0
  set_preference("SpeechOverrides_CapitalLetters", "").unwrap();
220
0
  set_preference("MathRate", "80").unwrap();
221
  // set_preference("CapitalLetters_UseWord", "true").unwrap();
222
  // set_preference("CapitalLetters_Pitch", "30").unwrap();
223
0
  set_preference("CapitalLetters_Beep", "true").unwrap();
224
0
  set_preference("IntentErrorRecovery", "Error").unwrap();
225
  // set_preference("MathRate", "77").unwrap();
226
227
0
  set_preference("Bookmark", "false").unwrap();
228
0
  set_preference("SpeechStyle", "ClearSpeak").unwrap();
229
0
  info!("Languages: {}", libmathcat::interface::get_supported_languages().unwrap_or_default().join(", "));
230
0
  info!("Speech styles: {}", libmathcat::interface::get_supported_speech_styles("ClearSpeak").unwrap_or_default().join(", "));
231
0
  info!("BrailleCodes: {}", libmathcat::interface::get_supported_braille_codes().unwrap_or_default().join(", "));
232
  // set_preference("DecimalSeparators", ",").unwrap();
233
  // set_preference("BlockSeparators", ". ").unwrap();
234
0
  if let Err(e) = set_mathml(expr) {
235
0
    eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1); 
236
0
  };
237
238
  // match do_navigate_command("ZoomIn".to_string())  {
239
  //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
240
  //   Ok(speech) => info!("\nZoomIn speech: '{speech}'"),
241
  // }
242
  // match do_navigate_command("ToggleZoomLockUp".to_string()) {
243
  //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
244
  //   Ok(speech) => info!("ToggleZoomLockUp speech: '{speech}'"),
245
  // }
246
  // match do_navigate_command("MovePrevious".to_string()) {
247
  //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
248
  //   Ok(speech) => info!("MovePrevious speech: '{speech}'"),
249
  // }
250
  // match do_navigate_command("MovePrevious".to_string()) {
251
  //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
252
  //   Ok(speech) => info!("MovePrevious speech: '{}'", speech),
253
  // }
254
  // match do_navigate_command("MovePrevious".to_string()) {
255
  //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
256
  //   Ok(speech) => info!("MovePrevious speech: '{}'", speech),
257
  // }
258
  // match do_navigate_command("MoveNext".to_string()) {
259
  //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
260
  //   Ok(speech) => info!("MoveNext speech: '{}'", speech),
261
  // }
262
  // match do_navigate_command("MoveNext".to_string()) {
263
  //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
264
  //   Ok(speech) => info!("MoveNext speech: '{}'", speech),
265
  // }
266
  // match do_navigate_command("MoveNext".to_string()) {
267
  //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
268
  //   Ok(speech) => info!("MoveNext speech: '{}'", speech),
269
  // }
270
  // match do_navigate_command("MoveNext".to_string()) {
271
  //   Err(e) => eprintln!("Error: exiting -- {}", errors_to_string(&e)); exit(1);,
272
  //   Ok(speech) => info!("MoveNext speech: '{}'", speech),
273
  // }
274
  // match get_spoken_text() {
275
  //   Ok(speech) => info!("Computed speech string:\n   '{speech}'"),
276
  //   Err(e) => eprintln!("{}", errors_to_string(&e)); exit(1);,
277
  // }
278
0
  debug!("Speech language is {}", get_preference("Language").unwrap());
279
0
  debug!("DecimalSeparator: {:?}", get_preference("DecimalSeparator").unwrap());
280
0
  debug!("DecimalSeparators: {:?}, BlockSeparators: {:?}", get_preference("DecimalSeparators").unwrap(), get_preference("BlockSeparators").unwrap());
281
0
  debug!("SpeechStyle: {:?}", get_preference("SpeechStyle").unwrap());
282
0
  debug!("Verbosity: {:?}", get_preference("Verbosity").unwrap());
283
 
284
  // info!("Time taken for loading+speech+braille: {}ms", instant.elapsed().as_millis());
285
  // let instant = Instant::now();
286
0
  match get_spoken_text() {
287
0
    Ok(speech) => info!("Computed speech string:\n   '{}'", speech),
288
0
    Err(e) => {eprintln!("{}", errors_to_string(&e)); exit(1);},
289
  }
290
  // info!("Time taken (second time for speech): {}ms", instant.elapsed().as_millis());
291
  // info!("SpeechStyle: {:?}", get_preference("SpeechStyle"));
292
293
0
  match get_braille("") {
294
0
    Ok(braille) => info!("Computed braille string:\n   '{braille}'"),
295
0
    Err(e) => {eprintln!("{}", errors_to_string(&e)); exit(1);},
296
  }
297
0
  debug!("...using BrailleCode: {:?}", get_preference("BrailleCode").unwrap());
298
  // let xpath_counts = libmathcat::speech::xpath_count();
299
  // info!("#xpath = {}; duplicates = {}", xpath_counts.0, xpath_counts.1);
300
  // info!("Time taken (second time for speech + braille): {}ms", instant.elapsed().as_millis());
301
  // debug!("Hashmap sizes:\n{}", libmathcat::speech::SpeechRules::print_sizes());
302
0
  timing_test(expr, 000);
303
304
0
}
305
306
0
fn timing_test(expr: &str, n_loops: usize) {
307
0
  if n_loops == 0 {
308
0
    return;
309
0
  }
310
  
311
0
  let n_loops_float = n_loops as f64;
312
0
  let instant = Instant::now();
313
0
  for _ in 0..n_loops {
314
0
    if let Err(e) = set_mathml(expr) {
315
0
      eprintln!("Error: exiting -- {}", errors_to_string(&e));
316
0
    };
317
0
    match get_spoken_text() {
318
0
      Ok(_) =>( ),
319
0
      Err(e) => {eprintln!("{}", errors_to_string(&e)); exit(1);},
320
    }
321
0
    match get_braille("") {
322
0
      Ok(_) => (),
323
0
      Err(e) => {eprintln!("{}", errors_to_string(&e)); exit(1);},
324
    }
325
  }
326
0
  info!("Time taken (time for set, speech, {} braille averaged over {} loops): {}ms", get_preference("BrailleCode").unwrap(), n_loops, instant.elapsed().as_millis() as f64/n_loops_float);
327
328
0
  let instant = Instant::now();
329
0
  for _ in 0..n_loops {
330
0
    if let Err(e) = set_mathml(expr) {
331
0
      eprintln!("Error: exiting -- {}", errors_to_string(&e));
332
0
    };
333
  }
334
0
  info!("Time taken (time for set averaged over {} loops): {}ms", n_loops, instant.elapsed().as_millis() as f64/n_loops_float);
335
336
0
  let instant = Instant::now();
337
0
  for _ in 0..n_loops {
338
0
    match get_spoken_text() {
339
0
      Ok(_) =>( ),
340
0
      Err(e) => {eprintln!("{}", errors_to_string(&e)); exit(1);},
341
    }
342
  }
343
0
  info!("Time taken (time for get_spoken_text() averaged over {} loops): {}ms", n_loops, instant.elapsed().as_millis() as f64/n_loops_float);
344
345
0
  set_preference("BrailleCode", "UEB").unwrap();
346
0
  get_braille("").unwrap();
347
0
  let instant = Instant::now();
348
0
  for _ in 0..n_loops {
349
0
    match get_braille("") {
350
0
      Ok(_) => (),
351
0
      Err(e) => {eprintln!("{}", errors_to_string(&e)); exit(1);},
352
    }
353
  }
354
0
  info!("Time taken (time for {} braille averaged over {} loops): {}ms", get_preference("BrailleCode").unwrap(), n_loops, instant.elapsed().as_millis() as f64/n_loops_float);
355
356
0
    if let Err(e) = set_mathml(expr) {
357
0
      eprintln!("Error: exiting -- {}", errors_to_string(&e));
358
0
    };
359
0
  set_preference("BrailleCode", "Nemeth").unwrap();
360
0
  get_braille("").unwrap();
361
0
  let instant = Instant::now();
362
0
  for _ in 0..n_loops {
363
0
    match get_braille("") {
364
0
      Ok(_) => (),
365
0
      Err(e) => {eprintln!("{}", errors_to_string(&e)); exit(1);} ,
366
    }
367
  }
368
0
  info!("Time taken (time for {} braille averaged over {} loops): {}ms", get_preference("BrailleCode").unwrap(), n_loops, instant.elapsed().as_millis() as f64/n_loops_float);
369
0
}