use once_cell::sync::Lazy;
use std::sync::{Arc, RwLock};
use crate::space_weather::provider::SpaceWeatherProvider;
use crate::space_weather::static_provider::StaticSpaceWeatherProvider;
use crate::space_weather::types::{SpaceWeatherExtrapolation, SpaceWeatherType};
use crate::time::Epoch;
use crate::utils::BraheError;
#[cfg(test)]
use serial_test::serial;
static GLOBAL_SW: Lazy<Arc<RwLock<Box<dyn SpaceWeatherProvider + Sync + Send>>>> =
Lazy::new(|| Arc::new(RwLock::new(Box::new(StaticSpaceWeatherProvider::new()))));
pub fn set_global_space_weather_provider<T: SpaceWeatherProvider + Sync + Send + 'static>(
provider: T,
) {
*GLOBAL_SW.write().unwrap() = Box::new(provider);
}
pub fn get_global_kp(mjd: f64) -> Result<f64, BraheError> {
GLOBAL_SW.read().unwrap().get_kp(mjd)
}
pub fn get_global_kp_all(mjd: f64) -> Result<[f64; 8], BraheError> {
GLOBAL_SW.read().unwrap().get_kp_all(mjd)
}
pub fn get_global_kp_daily(mjd: f64) -> Result<f64, BraheError> {
GLOBAL_SW.read().unwrap().get_kp_daily(mjd)
}
pub fn get_global_ap(mjd: f64) -> Result<f64, BraheError> {
GLOBAL_SW.read().unwrap().get_ap(mjd)
}
pub fn get_global_ap_all(mjd: f64) -> Result<[f64; 8], BraheError> {
GLOBAL_SW.read().unwrap().get_ap_all(mjd)
}
pub fn get_global_ap_daily(mjd: f64) -> Result<f64, BraheError> {
GLOBAL_SW.read().unwrap().get_ap_daily(mjd)
}
pub fn get_global_f107_observed(mjd: f64) -> Result<f64, BraheError> {
GLOBAL_SW.read().unwrap().get_f107_observed(mjd)
}
pub fn get_global_f107_adjusted(mjd: f64) -> Result<f64, BraheError> {
GLOBAL_SW.read().unwrap().get_f107_adjusted(mjd)
}
pub fn get_global_f107_obs_avg81(mjd: f64) -> Result<f64, BraheError> {
GLOBAL_SW.read().unwrap().get_f107_obs_avg81(mjd)
}
pub fn get_global_f107_adj_avg81(mjd: f64) -> Result<f64, BraheError> {
GLOBAL_SW.read().unwrap().get_f107_adj_avg81(mjd)
}
pub fn get_global_sunspot_number(mjd: f64) -> Result<u32, BraheError> {
GLOBAL_SW.read().unwrap().get_sunspot_number(mjd)
}
pub fn get_global_sw_initialization() -> bool {
GLOBAL_SW.read().unwrap().is_initialized()
}
pub fn get_global_sw_len() -> usize {
GLOBAL_SW.read().unwrap().len()
}
pub fn get_global_sw_type() -> SpaceWeatherType {
GLOBAL_SW.read().unwrap().sw_type()
}
pub fn get_global_sw_extrapolation() -> SpaceWeatherExtrapolation {
GLOBAL_SW.read().unwrap().extrapolation()
}
pub fn get_global_sw_mjd_min() -> f64 {
GLOBAL_SW.read().unwrap().mjd_min()
}
pub fn get_global_sw_mjd_max() -> f64 {
GLOBAL_SW.read().unwrap().mjd_max()
}
pub fn get_global_sw_mjd_last_observed() -> f64 {
GLOBAL_SW.read().unwrap().mjd_last_observed()
}
pub fn get_global_sw_mjd_last_daily_predicted() -> f64 {
GLOBAL_SW.read().unwrap().mjd_last_daily_predicted()
}
pub fn get_global_sw_mjd_last_monthly_predicted() -> f64 {
GLOBAL_SW.read().unwrap().mjd_last_monthly_predicted()
}
pub fn get_global_last_kp(mjd: f64, n: usize) -> Result<Vec<f64>, BraheError> {
GLOBAL_SW.read().unwrap().get_last_kp(mjd, n)
}
pub fn get_global_last_ap(mjd: f64, n: usize) -> Result<Vec<f64>, BraheError> {
GLOBAL_SW.read().unwrap().get_last_ap(mjd, n)
}
pub fn get_global_last_daily_kp(mjd: f64, n: usize) -> Result<Vec<f64>, BraheError> {
GLOBAL_SW.read().unwrap().get_last_daily_kp(mjd, n)
}
pub fn get_global_last_daily_ap(mjd: f64, n: usize) -> Result<Vec<f64>, BraheError> {
GLOBAL_SW.read().unwrap().get_last_daily_ap(mjd, n)
}
pub fn get_global_last_f107(mjd: f64, n: usize) -> Result<Vec<f64>, BraheError> {
GLOBAL_SW.read().unwrap().get_last_f107(mjd, n)
}
pub fn get_global_last_kpap_epochs(mjd: f64, n: usize) -> Result<Vec<Epoch>, BraheError> {
GLOBAL_SW.read().unwrap().get_last_kpap_epochs(mjd, n)
}
pub fn get_global_last_daily_epochs(mjd: f64, n: usize) -> Result<Vec<Epoch>, BraheError> {
GLOBAL_SW.read().unwrap().get_last_daily_epochs(mjd, n)
}
pub fn initialize_sw() -> Result<(), BraheError> {
use crate::space_weather::caching_provider::CachingSpaceWeatherProvider;
let provider = CachingSpaceWeatherProvider::new(
None, 7 * 86400, false, SpaceWeatherExtrapolation::Hold,
)?;
set_global_space_weather_provider(provider);
Ok(())
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
#[serial]
mod tests {
use super::*;
use crate::utils::testing::setup_global_test_space_weather;
fn clear_test_global_sw() {
set_global_space_weather_provider(StaticSpaceWeatherProvider::new());
}
#[test]
#[serial]
fn test_set_global_sw_from_zero() {
clear_test_global_sw();
assert!(!get_global_sw_initialization());
let sw = StaticSpaceWeatherProvider::from_zero();
set_global_space_weather_provider(sw);
assert!(get_global_sw_initialization());
assert_eq!(get_global_sw_len(), 1);
assert_eq!(get_global_sw_type(), SpaceWeatherType::Static);
}
#[test]
#[serial]
fn test_set_global_sw_from_file() {
clear_test_global_sw();
assert!(!get_global_sw_initialization());
setup_global_test_space_weather();
assert!(get_global_sw_initialization());
assert!(get_global_sw_len() > 0);
assert_eq!(get_global_sw_type(), SpaceWeatherType::CssiSpaceWeather);
}
#[test]
#[serial]
fn test_get_global_kp() {
setup_global_test_space_weather();
let kp = get_global_kp(36114.0).unwrap();
assert!((0.0..=9.0).contains(&kp));
}
#[test]
#[serial]
fn test_get_global_ap() {
setup_global_test_space_weather();
let ap = get_global_ap_daily(36114.0).unwrap();
assert!((0.0..=400.0).contains(&ap));
}
#[test]
#[serial]
fn test_get_global_f107() {
setup_global_test_space_weather();
let f107 = get_global_f107_observed(36114.0).unwrap();
assert!(f107 > 0.0);
}
#[test]
#[serial]
fn test_get_global_sunspot() {
setup_global_test_space_weather();
let isn = get_global_sunspot_number(36114.0).unwrap();
assert!(isn < 500);
}
#[test]
#[serial]
fn test_get_global_sw_mjd_last_daily_predicted() {
setup_global_test_space_weather();
let mjd_last_daily = get_global_sw_mjd_last_daily_predicted();
assert!(mjd_last_daily >= get_global_sw_mjd_last_observed());
assert!(mjd_last_daily > 58849.0);
}
#[test]
#[serial]
fn test_get_global_sw_mjd_last_monthly_predicted() {
setup_global_test_space_weather();
let mjd_last_monthly = get_global_sw_mjd_last_monthly_predicted();
assert!(mjd_last_monthly >= get_global_sw_mjd_last_daily_predicted());
assert!(mjd_last_monthly > 58849.0);
}
#[test]
#[serial]
fn test_get_global_kp_all() {
setup_global_test_space_weather();
let kp_all = get_global_kp_all(36114.0).unwrap();
assert_eq!(kp_all.len(), 8);
for kp in kp_all.iter() {
assert!((0.0..=9.0).contains(kp));
}
}
#[test]
#[serial]
fn test_get_global_kp_daily() {
setup_global_test_space_weather();
let kp_daily = get_global_kp_daily(36114.0).unwrap();
assert!((0.0..=9.0).contains(&kp_daily));
}
#[test]
#[serial]
fn test_get_global_ap_3hourly() {
setup_global_test_space_weather();
let ap = get_global_ap(36114.0).unwrap();
assert!(ap >= 0.0);
}
#[test]
#[serial]
fn test_get_global_ap_all() {
setup_global_test_space_weather();
let ap_all = get_global_ap_all(36114.0).unwrap();
assert_eq!(ap_all.len(), 8);
for ap in ap_all.iter() {
assert!(*ap >= 0.0);
}
}
#[test]
#[serial]
fn test_get_global_f107_adjusted() {
setup_global_test_space_weather();
let f107_adj = get_global_f107_adjusted(36114.0).unwrap();
assert!(f107_adj >= 0.0);
}
#[test]
#[serial]
fn test_get_global_f107_obs_avg81() {
setup_global_test_space_weather();
let f107_avg = get_global_f107_obs_avg81(60000.0).unwrap();
assert!(f107_avg > 0.0);
}
#[test]
#[serial]
fn test_get_global_f107_adj_avg81() {
setup_global_test_space_weather();
let f107_avg = get_global_f107_adj_avg81(60000.0).unwrap();
assert!(f107_avg > 0.0);
}
#[test]
#[serial]
fn test_get_global_sw_extrapolation() {
setup_global_test_space_weather();
let extrapolation = get_global_sw_extrapolation();
assert_eq!(extrapolation, SpaceWeatherExtrapolation::Hold);
}
#[test]
#[serial]
fn test_get_global_sw_mjd_min() {
setup_global_test_space_weather();
let mjd_min = get_global_sw_mjd_min();
assert_eq!(mjd_min, 36112.0);
}
#[test]
#[serial]
fn test_get_global_sw_mjd_max() {
setup_global_test_space_weather();
let mjd_max = get_global_sw_mjd_max();
assert!(mjd_max > 60000.0);
}
#[test]
#[serial]
fn test_get_global_sw_mjd_last_observed() {
setup_global_test_space_weather();
let mjd_last_obs = get_global_sw_mjd_last_observed();
assert!(mjd_last_obs > 60000.0);
}
#[test]
#[serial]
fn test_get_global_last_kp() {
setup_global_test_space_weather();
let kp_values = get_global_last_kp(60000.0, 5).unwrap();
assert_eq!(kp_values.len(), 5);
for kp in &kp_values {
assert!((0.0..=9.0).contains(kp));
}
}
#[test]
#[serial]
fn test_get_global_last_ap() {
setup_global_test_space_weather();
let ap_values = get_global_last_ap(60000.0, 5).unwrap();
assert_eq!(ap_values.len(), 5);
for ap in &ap_values {
assert!(*ap >= 0.0);
}
}
#[test]
#[serial]
fn test_get_global_last_daily_kp() {
setup_global_test_space_weather();
let daily_kp = get_global_last_daily_kp(60000.0, 3).unwrap();
assert_eq!(daily_kp.len(), 3);
for kp in &daily_kp {
assert!((0.0..=9.0).contains(kp));
}
}
#[test]
#[serial]
fn test_get_global_last_daily_ap() {
setup_global_test_space_weather();
let daily_ap = get_global_last_daily_ap(60000.0, 3).unwrap();
assert_eq!(daily_ap.len(), 3);
for ap in &daily_ap {
assert!(*ap >= 0.0);
}
}
#[test]
#[serial]
fn test_get_global_last_f107() {
setup_global_test_space_weather();
let f107_values = get_global_last_f107(60000.0, 3).unwrap();
assert_eq!(f107_values.len(), 3);
for f107 in &f107_values {
assert!(*f107 > 0.0);
}
}
#[test]
#[serial]
fn test_get_global_last_kpap_epochs() {
setup_global_test_space_weather();
let epochs = get_global_last_kpap_epochs(60000.0, 5).unwrap();
assert_eq!(epochs.len(), 5);
for i in 0..epochs.len() - 1 {
assert!(epochs[i].mjd() < epochs[i + 1].mjd());
}
}
#[test]
#[serial]
fn test_get_global_last_daily_epochs() {
setup_global_test_space_weather();
let epochs = get_global_last_daily_epochs(60000.0, 3).unwrap();
assert_eq!(epochs.len(), 3);
for i in 0..epochs.len() - 1 {
assert!(epochs[i].mjd() < epochs[i + 1].mjd());
}
}
#[test]
#[serial]
fn test_initialize_sw() {
clear_test_global_sw();
assert!(!get_global_sw_initialization());
initialize_sw().unwrap();
assert!(get_global_sw_initialization());
assert_eq!(get_global_sw_type(), SpaceWeatherType::CssiSpaceWeather);
assert!(get_global_sw_len() > 0);
}
}