From 5b1cdc6b386052f7d245f95f6b7eba8d13c26a3f Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Tue, 27 Oct 2020 22:20:54 -0400 Subject: [PATCH 01/18] Pulled out my other attempt at optional, order-independent parameters --- crates/datis-core/src/extract.rs | 92 ++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 22 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index 8d7a8bf..d12ae12 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -52,33 +52,65 @@ pub fn extract_atis_station_frequencies(situation: &str) -> HashMap Option { let re = RegexBuilder::new( - r"^ATIS ([a-zA-Z- ]+) ([1-3]\d{2}(\.\d{1,3})?)(,[ ]?TRAFFIC ([1-3]\d{2}(\.\d{1,3})?))?(,[ ]?VOICE ([a-zA-Z-:]+))?(,[ ]?INFO ([a-zA-Z]))?$", + r"^ATIS ([a-zA-Z- ]+) ([1-3]\d{2}(\.\d{1,3})?)", ) .case_insensitive(true) .build() .unwrap(); - re.captures(config).map(|caps| { - let name = caps.get(1).unwrap().as_str(); - let atis_freq = caps.get(2).unwrap().as_str(); - let atis_freq = (f64::from_str(atis_freq).unwrap() * 1_000_000.0) as u64; - let traffic_freq = caps - .get(5) - .map(|freq| (f64::from_str(freq.as_str()).unwrap() * 1_000_000.0) as u64); - let tts = caps - .get(8) - .and_then(|s| TextToSpeechProvider::from_str(s.as_str()).ok()); - let info_ltr = caps - .get(10) - .map(|ilo| ((ilo.as_str()).chars().next().unwrap().to_ascii_uppercase()) as char); - StationConfig { - name: name.to_string(), - atis: atis_freq, - traffic: traffic_freq, - tts, - info_ltr_override: info_ltr, - } - }) + let caps = re.captures(config).unwrap(); + let name = caps.get(1).unwrap().as_str().to_string(); + let atis_freq = caps.get(2).unwrap(); + let atis_freq = (f64::from_str(atis_freq.as_str()).unwrap() * 1_000_000.0) as u64; + + // Parse out voice, iff it exists + let re = RegexBuilder::new( + r",[ ]?VOICE ([a-zA-Z-:]+)", + ) + .case_insensitive(true).build().unwrap(); + let caps = re.captures(config); + let tts = if let Some(captured) = caps { + captured.get(1).map_or(None, + |s| TextToSpeechProvider::from_str(s.as_str()).ok()) + } else { + None + }; + + // Parse out traffic, iff it exists + let re = RegexBuilder::new( + r",[ ]?TRAFFIC ([1-3]\d{2}\.*\d{0,3})", + ) + .case_insensitive(true).build().unwrap(); + let caps = re.captures(config); + let traffic_freq = if let Some(captured) = caps { + captured.get(1).map_or(None, + |freq| Some((f64::from_str(freq.as_str()).unwrap() * 1_000_000.0) as u64)) + } else { + None + }; + + // Parse information letter override, iff it exists + let re = RegexBuilder::new( + r",[ ]?INFO ([a-zA-Z])", + ) + .case_insensitive(true).build().unwrap(); + let caps = re.captures(config); + let info_ltr_override = if let Some(captured) = caps { + captured.get(1).map_or(None, + |param| (Some(param.as_str().chars().next().unwrap().to_ascii_uppercase()))) + } else { + None + }; + + let result = StationConfig { + name: name, + atis: atis_freq, + traffic: traffic_freq, + tts, + info_ltr_override: info_ltr_override, + }; + + Some(result) } pub fn extract_carrier_station_config(config: &str) -> Option { @@ -387,6 +419,22 @@ mod test { ); } + // Test parameters in another order + assert_eq!( + extract_atis_station_config( + "ATIS Kutaisi 251.000, VOICE en-US-Standard-E, TRAFFIC 123.45" + ), + Some(StationConfig { + name: "Kutaisi".to_string(), + atis: 251_000_000, + traffic: Some(123_450_000), + tts: Some(TextToSpeechProvider::GoogleCloud { + voice: gcloud::VoiceKind::StandardE + }), + info_ltr_override: None, + }) + ); + #[test] fn test_broadcast_config_extraction() { assert_eq!( From ab3c462ba663027f1c4cbab0d29c6ac2bd5f7f8f Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Sun, 8 Nov 2020 19:20:31 -0500 Subject: [PATCH 02/18] First key/value options parser --- crates/datis-core/src/extract.rs | 134 +++++++++++++++++++------------ 1 file changed, 82 insertions(+), 52 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index d12ae12..207e568 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -58,49 +58,52 @@ pub fn extract_atis_station_config(config: &str) -> Option { .build() .unwrap(); - let caps = re.captures(config).unwrap(); + let caps = re.captures(config).unwrap(); let name = caps.get(1).unwrap().as_str().to_string(); let atis_freq = caps.get(2).unwrap(); let atis_freq = (f64::from_str(atis_freq.as_str()).unwrap() * 1_000_000.0) as u64; - // Parse out voice, iff it exists - let re = RegexBuilder::new( - r",[ ]?VOICE ([a-zA-Z-:]+)", - ) - .case_insensitive(true).build().unwrap(); - let caps = re.captures(config); - let tts = if let Some(captured) = caps { - captured.get(1).map_or(None, - |s| TextToSpeechProvider::from_str(s.as_str()).ok()) - } else { - None - }; - - // Parse out traffic, iff it exists - let re = RegexBuilder::new( - r",[ ]?TRAFFIC ([1-3]\d{2}\.*\d{0,3})", - ) - .case_insensitive(true).build().unwrap(); - let caps = re.captures(config); - let traffic_freq = if let Some(captured) = caps { - captured.get(1).map_or(None, - |freq| Some((f64::from_str(freq.as_str()).unwrap() * 1_000_000.0) as u64)) - } else { - None - }; + let mut traffic_freq = None; + let mut tts = None; + let mut info_ltr_override = None; - // Parse information letter override, iff it exists - let re = RegexBuilder::new( - r",[ ]?INFO ([a-zA-Z])", + let rex_option = RegexBuilder::new( + r"([^ ]*) (.*)", ) - .case_insensitive(true).build().unwrap(); - let caps = re.captures(config); - let info_ltr_override = if let Some(captured) = caps { - captured.get(1).map_or(None, - |param| (Some(param.as_str().chars().next().unwrap().to_ascii_uppercase()))) - } else { - None - }; + .case_insensitive(true) + .build() + .unwrap(); + for token in config.split(",").skip(1){ + let caps = rex_option.captures(token.trim()).unwrap(); + let option_key = caps.get(1).unwrap().as_str(); + let option_value = caps.get(2); + /* parse traffic value, and log a useful error if the value does not match the expected pattern */ + match option_key { + "TRAFFIC" => { + //println!("Processing traffic {}", option_value); + /*traffic_freq = + option_value.map_or(None, + |freq| Some((f64::from_str(freq.as_str()).unwrap() * 1_000_000.0) as u64));*/ + traffic_freq = option_value.parse::().ok(); + if traffic_freq.is_none() { + log::warn!("Unable to extract ATIS station traffic frequency from {}", option_value);//option_value.unwrap().as_str()); + }else{ + traffic_freq = (traffic_freq.unwrap()*1_000_000.0) as u64; + } + } + "VOICE" => { + tts = caps.get(2).map_or(None, + |s| TextToSpeechProvider::from_str(s.as_str()).ok()); + } + "INFO" => { + info_ltr_override = caps.get(2).map_or(None, + |param| (Some(param.as_str().chars().next().unwrap().to_ascii_uppercase()))); + } + _ => { + log::warn!("Unsupported ATIS station option {}", option_key); + } + } + } let result = StationConfig { name: name, @@ -350,6 +353,30 @@ mod test { info_ltr_override: None, }) ); + + // Test handling invalid value + assert_eq!( + extract_atis_station_config("ATIS Kutaisi 131.400, TRAFFIC Potatoe"), + Some(StationConfig { + name: "Kutaisi".to_string(), + atis: 131_400_000, + traffic: None, + tts: None, + info_ltr_override: None, + }) + ); +/* + // Test handling invalid key + assert_eq!( + extract_atis_station_config("ATIS Kutaisi 131.400, GRAVITY 7"), + Some(StationConfig { + name: "Kutaisi".to_string(), + atis: 131_400_000, + traffic: None, + tts: None, + info_ltr_override: None, + }) + );*/ } #[test] @@ -419,21 +446,24 @@ mod test { ); } - // Test parameters in another order - assert_eq!( - extract_atis_station_config( - "ATIS Kutaisi 251.000, VOICE en-US-Standard-E, TRAFFIC 123.45" - ), - Some(StationConfig { - name: "Kutaisi".to_string(), - atis: 251_000_000, - traffic: Some(123_450_000), - tts: Some(TextToSpeechProvider::GoogleCloud { - voice: gcloud::VoiceKind::StandardE - }), - info_ltr_override: None, - }) - ); + #[test] + fn test_reordered_parameters() { + // Test parameters in another order + assert_eq!( + extract_atis_station_config( + "ATIS Kutaisi 251.000, VOICE en-US-Standard-E, TRAFFIC 123.45" + ), + Some(StationConfig { + name: "Kutaisi".to_string(), + atis: 251_000_000, + traffic: Some(123_450_000), + tts: Some(TextToSpeechProvider::GoogleCloud { + voice: gcloud::VoiceKind::StandardE + }), + info_ltr_override: None, + }) + ); + } #[test] fn test_broadcast_config_extraction() { From 466e29b920c6a5942fbc8490f5aafb2f561aa629 Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Sun, 8 Nov 2020 19:20:52 -0500 Subject: [PATCH 03/18] Fixed test_debug makefile command --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f1433b7..c4ff594 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ test: cargo test --workspace --exclude datis test_debug: - cargo test -- --nocapture + cargo test --workspace --exclude datis -- --nocapture release: cargo build --release --package datis From 99214bd01f5783029210d006699fb9a388e1fe28 Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Sun, 8 Nov 2020 19:52:00 -0500 Subject: [PATCH 04/18] Fixing build errors from last commit. Working on error logging. --- crates/datis-core/src/extract.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index 207e568..c0343cb 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -63,10 +63,12 @@ pub fn extract_atis_station_config(config: &str) -> Option { let atis_freq = caps.get(2).unwrap(); let atis_freq = (f64::from_str(atis_freq.as_str()).unwrap() * 1_000_000.0) as u64; - let mut traffic_freq = None; + let mut traffic_freq: Option = None; let mut tts = None; let mut info_ltr_override = None; + // Or, this does make a good case for nom: https://stevedonovan.github.io/rust-gentle-intro/nom-intro.html + let rex_option = RegexBuilder::new( r"([^ ]*) (.*)", ) @@ -76,19 +78,20 @@ pub fn extract_atis_station_config(config: &str) -> Option { for token in config.split(",").skip(1){ let caps = rex_option.captures(token.trim()).unwrap(); let option_key = caps.get(1).unwrap().as_str(); - let option_value = caps.get(2); - /* parse traffic value, and log a useful error if the value does not match the expected pattern */ + let option_value = caps.get(2).map_or("", |m| m.as_str()); + match option_key { "TRAFFIC" => { //println!("Processing traffic {}", option_value); /*traffic_freq = option_value.map_or(None, |freq| Some((f64::from_str(freq.as_str()).unwrap() * 1_000_000.0) as u64));*/ - traffic_freq = option_value.parse::().ok(); - if traffic_freq.is_none() { + //traffic_freq = option_value.filter_map(|s| s.parse::().ok()).collect::>(); + let traffic_freq_hz = option_value.parse::().ok(); + if traffic_freq_hz.is_none() { log::warn!("Unable to extract ATIS station traffic frequency from {}", option_value);//option_value.unwrap().as_str()); }else{ - traffic_freq = (traffic_freq.unwrap()*1_000_000.0) as u64; + traffic_freq = Some((traffic_freq_hz.unwrap()*1_000_000.0) as u64); } } "VOICE" => { @@ -365,7 +368,7 @@ mod test { info_ltr_override: None, }) ); -/* + // Test handling invalid key assert_eq!( extract_atis_station_config("ATIS Kutaisi 131.400, GRAVITY 7"), @@ -376,7 +379,7 @@ mod test { tts: None, info_ltr_override: None, }) - );*/ + ); } #[test] From 748e85c52d5b67728c027e384a751bc29c90e805 Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Sun, 8 Nov 2020 19:58:54 -0500 Subject: [PATCH 05/18] Upgraded to an if let pattern --- crates/datis-core/src/extract.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index c0343cb..391c310 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -82,16 +82,10 @@ pub fn extract_atis_station_config(config: &str) -> Option { match option_key { "TRAFFIC" => { - //println!("Processing traffic {}", option_value); - /*traffic_freq = - option_value.map_or(None, - |freq| Some((f64::from_str(freq.as_str()).unwrap() * 1_000_000.0) as u64));*/ - //traffic_freq = option_value.filter_map(|s| s.parse::().ok()).collect::>(); - let traffic_freq_hz = option_value.parse::().ok(); - if traffic_freq_hz.is_none() { - log::warn!("Unable to extract ATIS station traffic frequency from {}", option_value);//option_value.unwrap().as_str()); + if let Some(traffic_freq_hz) = option_value.parse::().ok() { + traffic_freq = Some((traffic_freq_hz*1_000_000.0) as u64); }else{ - traffic_freq = Some((traffic_freq_hz.unwrap()*1_000_000.0) as u64); + log::warn!("Unable to extract ATIS station traffic frequency from {}", option_value); } } "VOICE" => { From 676110c883a3dda6ae0a59ec6e10a19f882d27bb Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Sun, 8 Nov 2020 20:01:40 -0500 Subject: [PATCH 06/18] Cleanup and a comment --- crates/datis-core/src/extract.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index 391c310..6629cdb 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -67,8 +67,6 @@ pub fn extract_atis_station_config(config: &str) -> Option { let mut tts = None; let mut info_ltr_override = None; - // Or, this does make a good case for nom: https://stevedonovan.github.io/rust-gentle-intro/nom-intro.html - let rex_option = RegexBuilder::new( r"([^ ]*) (.*)", ) @@ -89,10 +87,12 @@ pub fn extract_atis_station_config(config: &str) -> Option { } } "VOICE" => { + // TODO: Log an error if this failes, same as the TRAFFIC option tts = caps.get(2).map_or(None, |s| TextToSpeechProvider::from_str(s.as_str()).ok()); } "INFO" => { + // TODO: Log an error if this failes, same as the TRAFFIC option info_ltr_override = caps.get(2).map_or(None, |param| (Some(param.as_str().chars().next().unwrap().to_ascii_uppercase()))); } From 4e05d258ffd43f9a71884da087c12d5876eb784b Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Sat, 14 Nov 2020 21:30:24 -0500 Subject: [PATCH 07/18] Added error log when parsing voice --- crates/datis-core/src/extract.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index 6629cdb..b88b7a7 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -64,7 +64,7 @@ pub fn extract_atis_station_config(config: &str) -> Option { let atis_freq = (f64::from_str(atis_freq.as_str()).unwrap() * 1_000_000.0) as u64; let mut traffic_freq: Option = None; - let mut tts = None; + let mut tts: Option = None; let mut info_ltr_override = None; let rex_option = RegexBuilder::new( @@ -87,12 +87,13 @@ pub fn extract_atis_station_config(config: &str) -> Option { } } "VOICE" => { - // TODO: Log an error if this failes, same as the TRAFFIC option - tts = caps.get(2).map_or(None, - |s| TextToSpeechProvider::from_str(s.as_str()).ok()); + if let Some(tts_provider) = TextToSpeechProvider::from_str(option_value).ok() { + tts = Some(tts_provider); + }else{ + log::warn!("Unable to extract Voice from {}", option_value); + } } - "INFO" => { - // TODO: Log an error if this failes, same as the TRAFFIC option + "INFO" => { info_ltr_override = caps.get(2).map_or(None, |param| (Some(param.as_str().chars().next().unwrap().to_ascii_uppercase()))); } From 06d0021859f90104736fbf9211922da18fcdf4d9 Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Sat, 14 Nov 2020 22:11:04 -0500 Subject: [PATCH 08/18] Applied variables parameters to BROADCAST extraction --- crates/datis-core/src/extract.rs | 61 ++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index b88b7a7..2ac3c9b 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -152,19 +152,52 @@ pub fn extract_custom_broadcast_config(config: &str) -> Option .case_insensitive(true) .build() .unwrap(); - re.captures(config).map(|caps| { - let freq = caps.get(1).unwrap().as_str(); - let freq = (f32::from_str(freq).unwrap() * 1_000_000.0) as u64; - let tts = caps - .get(4) - .and_then(|s| TextToSpeechProvider::from_str(s.as_str()).ok()); - let message = caps.get(5).unwrap().as_str(); - BroadcastConfig { - freq, - message: message.to_string(), - tts, + + let caps = re.captures(config).unwrap(); + let freq = caps.get(1).unwrap(); + let options = caps.get(3); + let freq = (f64::from_str(freq.as_str()).unwrap() * 1_000_000.0) as u64; + let message = caps.get(4).unwrap().as_str().to_string(); + + let mut tts: Option = None; + + if options.is_some() + { + println!("Considering broadcast option {:?} ", options.unwrap().as_str()); + let rex_option = RegexBuilder::new( + r"([^ ]*) (.*)", + ) + .case_insensitive(true) + .build() + .unwrap(); + + for token in options.unwrap().as_str().split(",").skip(1){ + let caps = rex_option.captures(token.trim()).unwrap(); + let option_key = caps.get(1).unwrap().as_str(); + let option_value = caps.get(2).map_or("", |m| m.as_str()); + + match option_key { + "VOICE" => { + if let Some(tts_provider) = TextToSpeechProvider::from_str(option_value).ok() { + tts = Some(tts_provider); + }else{ + log::warn!("Unable to extract Voice from {}", option_value); + } + } + _ => { + log::warn!("Unsupported BROADCAST station option {}", option_key); + } + } } - }) + } + + let result = BroadcastConfig { + freq, + message, + tts, + }; + + Some(result) } #[derive(Debug, PartialEq)] @@ -475,9 +508,9 @@ mod test { ); assert_eq!( - extract_custom_broadcast_config("BROADCAST 251.000, VOICE AWS:Brian: Bla bla"), + extract_custom_broadcast_config("BROADCAST 251.500, VOICE AWS:Brian: Bla bla"), Some(BroadcastConfig { - freq: 251_000_000, + freq: 251_500_000, message: "Bla bla".to_string(), tts: Some(TextToSpeechProvider::AmazonWebServices { voice: aws::VoiceKind::Brian From df9b40bcbc48c688bf4cd532f45ca4b6e051ea40 Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Sat, 14 Nov 2020 22:11:56 -0500 Subject: [PATCH 09/18] Oops, part of last commit missed --- crates/datis-core/src/extract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index 2ac3c9b..7e9b4b3 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -147,7 +147,7 @@ pub struct BroadcastConfig { pub fn extract_custom_broadcast_config(config: &str) -> Option { let re = RegexBuilder::new( - r"^BROADCAST ([1-3]\d{2}(\.\d{1,3})?)(,[ ]?VOICE ([a-zA-Z-:]+))?:[ ]*(.+)$", + r"^BROADCAST ([1-3]\d{2}(\.\d{1,3})?)(.*): ([^:]+)$", ) .case_insensitive(true) .build() From f41f7ce6b5f598be1b8efc79706d55e9d9a5fee2 Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Sat, 21 Nov 2020 23:24:29 -0500 Subject: [PATCH 10/18] New extract style for CARRIER --- crates/datis-core/src/extract.rs | 64 ++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index 7e9b4b3..3bbebf8 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -116,26 +116,58 @@ pub fn extract_atis_station_config(config: &str) -> Option { pub fn extract_carrier_station_config(config: &str) -> Option { let re = RegexBuilder::new( - r"^CARRIER ([a-zA-Z- ]+) ([1-3]\d{2}(\.\d{1,3})?)(,[ ]?VOICE ([a-zA-Z-:]+))?$", + r"^CARRIER ([a-zA-Z- ]+) ([1-3]\d{2}(\.\d{1,3})?)", ) .case_insensitive(true) .build() .unwrap(); - re.captures(config).map(|caps| { - let name = caps.get(1).unwrap().as_str(); - let atis_freq = caps.get(2).unwrap().as_str(); - let atis_freq = (f64::from_str(atis_freq).unwrap() * 1_000_000.0) as u64; - let tts = caps - .get(5) - .and_then(|s| TextToSpeechProvider::from_str(s.as_str()).ok()); - StationConfig { - name: name.to_string(), - atis: atis_freq, - traffic: None, - tts, - info_ltr_override: None, - } - }) + + let caps = re.captures(config).unwrap(); + let name = caps.get(1).unwrap().as_str().to_string(); + let atis_freq = caps.get(2).unwrap(); + let atis_freq = (f64::from_str(atis_freq.as_str()).unwrap() * 1_000_000.0) as u64; + + let mut tts: Option = None; + let mut info_ltr_override = None; + + let rex_option = RegexBuilder::new( + r"([^ ]*) (.*)", + ) + .case_insensitive(true) + .build() + .unwrap(); + for token in config.split(",").skip(1){ + let caps = rex_option.captures(token.trim()).unwrap(); + let option_key = caps.get(1).unwrap().as_str(); + let option_value = caps.get(2).map_or("", |m| m.as_str()); + + match option_key { + "VOICE" => { + if let Some(tts_provider) = TextToSpeechProvider::from_str(option_value).ok() { + tts = Some(tts_provider); + }else{ + log::warn!("Unable to extract Voice from {}", option_value); + } + } + "INFO" => { + info_ltr_override = caps.get(2).map_or(None, + |param| (Some(param.as_str().chars().next().unwrap().to_ascii_uppercase()))); + } + _ => { + log::warn!("Unsupported CARRIER station option {}", option_key); + } + } + } + + let result = StationConfig { + name: name, + atis: atis_freq, + traffic: None, + tts, + info_ltr_override: info_ltr_override, + }; + + Some(result) } #[derive(Debug, PartialEq)] From 09858a2861d353abe64e2802fe564389789b4bb0 Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Sat, 21 Nov 2020 23:31:08 -0500 Subject: [PATCH 11/18] New extract style for weather station --- crates/datis-core/src/extract.rs | 55 ++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index 3bbebf8..8569f10 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -241,24 +241,51 @@ pub struct WetherStationConfig { pub fn extract_weather_station_config(config: &str) -> Option { let re = RegexBuilder::new( - r"^WEATHER ([a-zA-Z- ]+) ([1-3]\d{2}(\.\d{1,3})?)(,[ ]?VOICE ([a-zA-Z-:]+))?$", + r"^WEATHER ([a-zA-Z- ]+) ([1-3]\d{2}(\.\d{1,3})?)", ) .case_insensitive(true) .build() .unwrap(); - re.captures(config).map(|caps| { - let name = caps.get(1).unwrap().as_str(); - let freq = caps.get(2).unwrap().as_str(); - let freq = (f64::from_str(freq).unwrap() * 1_000_000.0) as u64; - let tts = caps - .get(5) - .and_then(|s| TextToSpeechProvider::from_str(s.as_str()).ok()); - WetherStationConfig { - name: name.to_string(), - freq, - tts, - } - }) + + let caps = re.captures(config).unwrap(); + let name = caps.get(1).unwrap().as_str().to_string(); + let station_freq = caps.get(2).unwrap(); + let station_freq = (f64::from_str(station_freq.as_str()).unwrap() * 1_000_000.0) as u64; + + let mut tts: Option = None; + + let rex_option = RegexBuilder::new( + r"([^ ]*) (.*)", + ) + .case_insensitive(true) + .build() + .unwrap(); + for token in config.split(",").skip(1){ + let caps = rex_option.captures(token.trim()).unwrap(); + let option_key = caps.get(1).unwrap().as_str(); + let option_value = caps.get(2).map_or("", |m| m.as_str()); + + match option_key { + "VOICE" => { + if let Some(tts_provider) = TextToSpeechProvider::from_str(option_value).ok() { + tts = Some(tts_provider); + }else{ + log::warn!("Unable to extract Voice from {}", option_value); + } + } + _ => { + log::warn!("Unsupported WEATHER station option {}", option_key); + } + } + } + + let result = WetherStationConfig { + name: name, + freq: station_freq, + tts + }; + + Some(result) } #[cfg(test)] From 3c2f448b25c09d23ea18344162f737fcad34aa46 Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Sat, 21 Nov 2020 23:32:20 -0500 Subject: [PATCH 12/18] Cleanup out debug output --- crates/datis-core/src/extract.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index 8569f10..9860768 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -192,10 +192,8 @@ pub fn extract_custom_broadcast_config(config: &str) -> Option let message = caps.get(4).unwrap().as_str().to_string(); let mut tts: Option = None; - if options.is_some() { - println!("Considering broadcast option {:?} ", options.unwrap().as_str()); let rex_option = RegexBuilder::new( r"([^ ]*) (.*)", ) From 60952f3b4843430cddef347352c1de3e332789c6 Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Sat, 21 Nov 2020 23:33:58 -0500 Subject: [PATCH 13/18] cargo fmt on extract --- crates/datis-core/src/extract.rs | 152 ++++++++++++++----------------- 1 file changed, 68 insertions(+), 84 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index 9860768..f3c7741 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -51,12 +51,10 @@ pub fn extract_atis_station_frequencies(situation: &str) -> HashMap Option { - let re = RegexBuilder::new( - r"^ATIS ([a-zA-Z- ]+) ([1-3]\d{2}(\.\d{1,3})?)", - ) - .case_insensitive(true) - .build() - .unwrap(); + let re = RegexBuilder::new(r"^ATIS ([a-zA-Z- ]+) ([1-3]\d{2}(\.\d{1,3})?)") + .case_insensitive(true) + .build() + .unwrap(); let caps = re.captures(config).unwrap(); let name = caps.get(1).unwrap().as_str().to_string(); @@ -67,40 +65,42 @@ pub fn extract_atis_station_config(config: &str) -> Option { let mut tts: Option = None; let mut info_ltr_override = None; - let rex_option = RegexBuilder::new( - r"([^ ]*) (.*)", - ) - .case_insensitive(true) - .build() - .unwrap(); - for token in config.split(",").skip(1){ + let rex_option = RegexBuilder::new(r"([^ ]*) (.*)") + .case_insensitive(true) + .build() + .unwrap(); + for token in config.split(",").skip(1) { let caps = rex_option.captures(token.trim()).unwrap(); let option_key = caps.get(1).unwrap().as_str(); let option_value = caps.get(2).map_or("", |m| m.as_str()); - + match option_key { - "TRAFFIC" => { + "TRAFFIC" => { if let Some(traffic_freq_hz) = option_value.parse::().ok() { - traffic_freq = Some((traffic_freq_hz*1_000_000.0) as u64); - }else{ - log::warn!("Unable to extract ATIS station traffic frequency from {}", option_value); + traffic_freq = Some((traffic_freq_hz * 1_000_000.0) as u64); + } else { + log::warn!( + "Unable to extract ATIS station traffic frequency from {}", + option_value + ); } } "VOICE" => { if let Some(tts_provider) = TextToSpeechProvider::from_str(option_value).ok() { tts = Some(tts_provider); - }else{ + } else { log::warn!("Unable to extract Voice from {}", option_value); } } "INFO" => { - info_ltr_override = caps.get(2).map_or(None, - |param| (Some(param.as_str().chars().next().unwrap().to_ascii_uppercase()))); + info_ltr_override = caps.get(2).map_or(None, |param| { + (Some(param.as_str().chars().next().unwrap().to_ascii_uppercase())) + }); } - _ => { + _ => { log::warn!("Unsupported ATIS station option {}", option_key); } - } + } } let result = StationConfig { @@ -115,12 +115,10 @@ pub fn extract_atis_station_config(config: &str) -> Option { } pub fn extract_carrier_station_config(config: &str) -> Option { - let re = RegexBuilder::new( - r"^CARRIER ([a-zA-Z- ]+) ([1-3]\d{2}(\.\d{1,3})?)", - ) - .case_insensitive(true) - .build() - .unwrap(); + let re = RegexBuilder::new(r"^CARRIER ([a-zA-Z- ]+) ([1-3]\d{2}(\.\d{1,3})?)") + .case_insensitive(true) + .build() + .unwrap(); let caps = re.captures(config).unwrap(); let name = caps.get(1).unwrap().as_str().to_string(); @@ -130,33 +128,32 @@ pub fn extract_carrier_station_config(config: &str) -> Option { let mut tts: Option = None; let mut info_ltr_override = None; - let rex_option = RegexBuilder::new( - r"([^ ]*) (.*)", - ) - .case_insensitive(true) - .build() - .unwrap(); - for token in config.split(",").skip(1){ + let rex_option = RegexBuilder::new(r"([^ ]*) (.*)") + .case_insensitive(true) + .build() + .unwrap(); + for token in config.split(",").skip(1) { let caps = rex_option.captures(token.trim()).unwrap(); let option_key = caps.get(1).unwrap().as_str(); let option_value = caps.get(2).map_or("", |m| m.as_str()); - + match option_key { "VOICE" => { if let Some(tts_provider) = TextToSpeechProvider::from_str(option_value).ok() { tts = Some(tts_provider); - }else{ + } else { log::warn!("Unable to extract Voice from {}", option_value); } } "INFO" => { - info_ltr_override = caps.get(2).map_or(None, - |param| (Some(param.as_str().chars().next().unwrap().to_ascii_uppercase()))); + info_ltr_override = caps.get(2).map_or(None, |param| { + (Some(param.as_str().chars().next().unwrap().to_ascii_uppercase())) + }); } - _ => { + _ => { log::warn!("Unsupported CARRIER station option {}", option_key); } - } + } } let result = StationConfig { @@ -178,12 +175,10 @@ pub struct BroadcastConfig { } pub fn extract_custom_broadcast_config(config: &str) -> Option { - let re = RegexBuilder::new( - r"^BROADCAST ([1-3]\d{2}(\.\d{1,3})?)(.*): ([^:]+)$", - ) - .case_insensitive(true) - .build() - .unwrap(); + let re = RegexBuilder::new(r"^BROADCAST ([1-3]\d{2}(\.\d{1,3})?)(.*): ([^:]+)$") + .case_insensitive(true) + .build() + .unwrap(); let caps = re.captures(config).unwrap(); let freq = caps.get(1).unwrap(); @@ -192,40 +187,33 @@ pub fn extract_custom_broadcast_config(config: &str) -> Option let message = caps.get(4).unwrap().as_str().to_string(); let mut tts: Option = None; - if options.is_some() - { - let rex_option = RegexBuilder::new( - r"([^ ]*) (.*)", - ) - .case_insensitive(true) - .build() - .unwrap(); + if options.is_some() { + let rex_option = RegexBuilder::new(r"([^ ]*) (.*)") + .case_insensitive(true) + .build() + .unwrap(); - for token in options.unwrap().as_str().split(",").skip(1){ + for token in options.unwrap().as_str().split(",").skip(1) { let caps = rex_option.captures(token.trim()).unwrap(); let option_key = caps.get(1).unwrap().as_str(); let option_value = caps.get(2).map_or("", |m| m.as_str()); - + match option_key { "VOICE" => { if let Some(tts_provider) = TextToSpeechProvider::from_str(option_value).ok() { tts = Some(tts_provider); - }else{ + } else { log::warn!("Unable to extract Voice from {}", option_value); } } - _ => { + _ => { log::warn!("Unsupported BROADCAST station option {}", option_key); } } } } - let result = BroadcastConfig { - freq, - message, - tts, - }; + let result = BroadcastConfig { freq, message, tts }; Some(result) } @@ -238,12 +226,10 @@ pub struct WetherStationConfig { } pub fn extract_weather_station_config(config: &str) -> Option { - let re = RegexBuilder::new( - r"^WEATHER ([a-zA-Z- ]+) ([1-3]\d{2}(\.\d{1,3})?)", - ) - .case_insensitive(true) - .build() - .unwrap(); + let re = RegexBuilder::new(r"^WEATHER ([a-zA-Z- ]+) ([1-3]\d{2}(\.\d{1,3})?)") + .case_insensitive(true) + .build() + .unwrap(); let caps = re.captures(config).unwrap(); let name = caps.get(1).unwrap().as_str().to_string(); @@ -251,36 +237,34 @@ pub fn extract_weather_station_config(config: &str) -> Option = None; - - let rex_option = RegexBuilder::new( - r"([^ ]*) (.*)", - ) - .case_insensitive(true) - .build() - .unwrap(); - for token in config.split(",").skip(1){ + + let rex_option = RegexBuilder::new(r"([^ ]*) (.*)") + .case_insensitive(true) + .build() + .unwrap(); + for token in config.split(",").skip(1) { let caps = rex_option.captures(token.trim()).unwrap(); let option_key = caps.get(1).unwrap().as_str(); let option_value = caps.get(2).map_or("", |m| m.as_str()); - + match option_key { "VOICE" => { if let Some(tts_provider) = TextToSpeechProvider::from_str(option_value).ok() { tts = Some(tts_provider); - }else{ + } else { log::warn!("Unable to extract Voice from {}", option_value); } } - _ => { + _ => { log::warn!("Unsupported WEATHER station option {}", option_key); } - } + } } let result = WetherStationConfig { name: name, freq: station_freq, - tts + tts, }; Some(result) From 1fec535fb25c37c161cca494aed1f409a3f9716b Mon Sep 17 00:00:00 2001 From: Talbot Date: Sun, 6 Dec 2020 17:49:48 -0500 Subject: [PATCH 14/18] Fixed warnings about extra brackets --- crates/datis-core/src/extract.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index f3c7741..b762c32 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -94,7 +94,7 @@ pub fn extract_atis_station_config(config: &str) -> Option { } "INFO" => { info_ltr_override = caps.get(2).map_or(None, |param| { - (Some(param.as_str().chars().next().unwrap().to_ascii_uppercase())) + Some(param.as_str().chars().next().unwrap().to_ascii_uppercase()) }); } _ => { @@ -147,7 +147,7 @@ pub fn extract_carrier_station_config(config: &str) -> Option { } "INFO" => { info_ltr_override = caps.get(2).map_or(None, |param| { - (Some(param.as_str().chars().next().unwrap().to_ascii_uppercase())) + Some(param.as_str().chars().next().unwrap().to_ascii_uppercase()) }); } _ => { From 50479ce258c992a8b7b857686b6fa6cea32769ea Mon Sep 17 00:00:00 2001 From: Talbot Date: Sun, 6 Dec 2020 17:50:46 -0500 Subject: [PATCH 15/18] Fix extract of non-stations, as per PR comment --- crates/datis-core/src/extract.rs | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index b762c32..7aa4527 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -56,7 +56,7 @@ pub fn extract_atis_station_config(config: &str) -> Option { .build() .unwrap(); - let caps = re.captures(config).unwrap(); + let caps = re.captures(config)?; let name = caps.get(1).unwrap().as_str().to_string(); let atis_freq = caps.get(2).unwrap(); let atis_freq = (f64::from_str(atis_freq.as_str()).unwrap() * 1_000_000.0) as u64; @@ -120,7 +120,7 @@ pub fn extract_carrier_station_config(config: &str) -> Option { .build() .unwrap(); - let caps = re.captures(config).unwrap(); + let caps = re.captures(config)?; let name = caps.get(1).unwrap().as_str().to_string(); let atis_freq = caps.get(2).unwrap(); let atis_freq = (f64::from_str(atis_freq.as_str()).unwrap() * 1_000_000.0) as u64; @@ -180,7 +180,7 @@ pub fn extract_custom_broadcast_config(config: &str) -> Option .build() .unwrap(); - let caps = re.captures(config).unwrap(); + let caps = re.captures(config)?; let freq = caps.get(1).unwrap(); let options = caps.get(3); let freq = (f64::from_str(freq.as_str()).unwrap() * 1_000_000.0) as u64; @@ -231,7 +231,7 @@ pub fn extract_weather_station_config(config: &str) -> Option Date: Sun, 6 Dec 2020 18:11:44 -0500 Subject: [PATCH 16/18] Correct use of if let Ok --- crates/datis-core/src/extract.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index 7aa4527..b95480b 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -76,7 +76,7 @@ pub fn extract_atis_station_config(config: &str) -> Option { match option_key { "TRAFFIC" => { - if let Some(traffic_freq_hz) = option_value.parse::().ok() { + if let Ok(traffic_freq_hz) = option_value.parse::() { traffic_freq = Some((traffic_freq_hz * 1_000_000.0) as u64); } else { log::warn!( @@ -86,7 +86,7 @@ pub fn extract_atis_station_config(config: &str) -> Option { } } "VOICE" => { - if let Some(tts_provider) = TextToSpeechProvider::from_str(option_value).ok() { + if let Ok(tts_provider) = TextToSpeechProvider::from_str(option_value) { tts = Some(tts_provider); } else { log::warn!("Unable to extract Voice from {}", option_value); @@ -139,7 +139,7 @@ pub fn extract_carrier_station_config(config: &str) -> Option { match option_key { "VOICE" => { - if let Some(tts_provider) = TextToSpeechProvider::from_str(option_value).ok() { + if let Ok(tts_provider) = TextToSpeechProvider::from_str(option_value) { tts = Some(tts_provider); } else { log::warn!("Unable to extract Voice from {}", option_value); @@ -200,7 +200,7 @@ pub fn extract_custom_broadcast_config(config: &str) -> Option match option_key { "VOICE" => { - if let Some(tts_provider) = TextToSpeechProvider::from_str(option_value).ok() { + if let Ok(tts_provider) = TextToSpeechProvider::from_str(option_value) { tts = Some(tts_provider); } else { log::warn!("Unable to extract Voice from {}", option_value); @@ -249,7 +249,7 @@ pub fn extract_weather_station_config(config: &str) -> Option { - if let Some(tts_provider) = TextToSpeechProvider::from_str(option_value).ok() { + if let Ok(tts_provider) = TextToSpeechProvider::from_str(option_value) { tts = Some(tts_provider); } else { log::warn!("Unable to extract Voice from {}", option_value); From dcf76baefd448cdf2bda5fe87aa110b74ef8e23f Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Sun, 6 Dec 2020 21:54:46 -0500 Subject: [PATCH 17/18] Simplifed a regex with a split_at suggested by Markus --- crates/datis-core/src/extract.rs | 34 +++++++++++--------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index b95480b..fa3a7cb 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -128,14 +128,11 @@ pub fn extract_carrier_station_config(config: &str) -> Option { let mut tts: Option = None; let mut info_ltr_override = None; - let rex_option = RegexBuilder::new(r"([^ ]*) (.*)") - .case_insensitive(true) - .build() - .unwrap(); for token in config.split(",").skip(1) { - let caps = rex_option.captures(token.trim()).unwrap(); - let option_key = caps.get(1).unwrap().as_str(); - let option_value = caps.get(2).map_or("", |m| m.as_str()); + let token = token.trim(); + let (option_key, option_value) = token.split_at(token.find(' ').unwrap_or(token.len())); + let option_key = option_key.trim(); + let option_value = option_value.trim(); match option_key { "VOICE" => { @@ -188,15 +185,11 @@ pub fn extract_custom_broadcast_config(config: &str) -> Option let mut tts: Option = None; if options.is_some() { - let rex_option = RegexBuilder::new(r"([^ ]*) (.*)") - .case_insensitive(true) - .build() - .unwrap(); - for token in options.unwrap().as_str().split(",").skip(1) { - let caps = rex_option.captures(token.trim()).unwrap(); - let option_key = caps.get(1).unwrap().as_str(); - let option_value = caps.get(2).map_or("", |m| m.as_str()); + let token = token.trim(); + let (option_key, option_value) = token.split_at(token.find(' ').unwrap_or(token.len())); + let option_key = option_key.trim(); + let option_value = option_value.trim(); match option_key { "VOICE" => { @@ -238,14 +231,11 @@ pub fn extract_weather_station_config(config: &str) -> Option = None; - let rex_option = RegexBuilder::new(r"([^ ]*) (.*)") - .case_insensitive(true) - .build() - .unwrap(); for token in config.split(",").skip(1) { - let caps = rex_option.captures(token.trim()).unwrap(); - let option_key = caps.get(1).unwrap().as_str(); - let option_value = caps.get(2).map_or("", |m| m.as_str()); + let token = token.trim(); + let (option_key, option_value) = token.split_at(token.find(' ').unwrap_or(token.len())); + let option_key = option_key.trim(); + let option_value = option_value.trim(); match option_key { "VOICE" => { From b74695a4a4d6fcda30296ad537c11dc80895db8e Mon Sep 17 00:00:00 2001 From: Talbot McInnis Date: Sun, 20 Dec 2020 19:50:57 -0500 Subject: [PATCH 18/18] Fix type in unit test test_complete_garbge --- crates/datis-core/src/extract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/datis-core/src/extract.rs b/crates/datis-core/src/extract.rs index fa3a7cb..b2ea620 100644 --- a/crates/datis-core/src/extract.rs +++ b/crates/datis-core/src/extract.rs @@ -528,7 +528,7 @@ mod test { } #[test] - fn test_complete_garbge() { + fn test_complete_garbage() { assert_eq!( extract_atis_station_config("not an atis station at all"), None