use crate::types::{CategoryId, IndicatorId};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SeriesPreset {
pub category_id: CategoryId,
pub indicator_id: IndicatorId,
}
impl SeriesPreset {
#[must_use]
#[inline]
pub const fn new(category_id: CategoryId, indicator_id: IndicatorId) -> Self {
Self {
category_id,
indicator_id,
}
}
}
pub mod fx {
use super::SeriesPreset;
#[cfg(feature = "blocking")]
use crate::BlockingCbrClient;
use crate::models::CategoryNewItem;
use crate::types::{CategoryId, IndicatorId, MeasureId};
use crate::{CbrClient, CbrError};
const CATEGORY_SUBSTR: &str = "Номинальные курсы иностранных валют к рублю";
const MONTHLY_SUBSTR: &str = "ежемесячные данные";
const QUARTERLY_SUBSTR: &str = "ежеквартальные данные";
const INDICATOR_NOMINAL: &str = "Номинальный курс";
const INDICATOR_AVERAGE: &str = "Средний номинальный курс за период";
const INDICATOR_AVERAGE_YTD: &str = "Средний номинальный курс за период с начала года";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FxPeriodicity {
Monthly,
Quarterly,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FxMetric {
Nominal,
Average,
AverageYtd,
}
pub const USD_RUB_MONTHLY_NOMINAL: SeriesPreset =
SeriesPreset::new(CategoryId::new_const(33), IndicatorId::new_const(127));
pub const USD_RUB_MONTHLY_AVERAGE: SeriesPreset =
SeriesPreset::new(CategoryId::new_const(33), IndicatorId::new_const(128));
pub const USD_RUB_MONTHLY_AVERAGE_YTD: SeriesPreset =
SeriesPreset::new(CategoryId::new_const(33), IndicatorId::new_const(139));
pub const USD_RUB_QUARTERLY_NOMINAL: SeriesPreset =
SeriesPreset::new(CategoryId::new_const(35), IndicatorId::new_const(133));
pub const USD_RUB_QUARTERLY_AVERAGE: SeriesPreset =
SeriesPreset::new(CategoryId::new_const(35), IndicatorId::new_const(134));
pub const USD_RUB_QUARTERLY_AVERAGE_YTD: SeriesPreset =
SeriesPreset::new(CategoryId::new_const(35), IndicatorId::new_const(141));
pub const USD_TO_RUB_END_OF_PERIOD_MEASURE2_ID: MeasureId = MeasureId::new_const(98);
pub const EUR_TO_RUB_END_OF_PERIOD_MEASURE2_ID: MeasureId = MeasureId::new_const(99);
pub const CNY_TO_RUB_END_OF_PERIOD_MEASURE2_ID: MeasureId = MeasureId::new_const(100);
pub const USD_TO_RUB_AVERAGE_MEASURE2_ID: MeasureId = MeasureId::new_const(101);
pub const EUR_TO_RUB_AVERAGE_MEASURE2_ID: MeasureId = MeasureId::new_const(102);
pub const CNY_TO_RUB_AVERAGE_MEASURE2_ID: MeasureId = MeasureId::new_const(103);
pub async fn resolve_fx_series(
client: &CbrClient,
periodicity: FxPeriodicity,
metric: FxMetric,
) -> Result<Option<SeriesPreset>, CbrError> {
let response = client.category_new().await?;
Ok(find_fx_series(&response.category, periodicity, metric))
}
#[cfg(feature = "blocking")]
pub fn resolve_fx_series_blocking(
client: &BlockingCbrClient,
periodicity: FxPeriodicity,
metric: FxMetric,
) -> Result<Option<SeriesPreset>, CbrError> {
let response = client.category_new()?;
Ok(find_fx_series(&response.category, periodicity, metric))
}
fn periodicity_substr(periodicity: FxPeriodicity) -> &'static str {
match periodicity {
FxPeriodicity::Monthly => MONTHLY_SUBSTR,
FxPeriodicity::Quarterly => QUARTERLY_SUBSTR,
}
}
fn indicator_name(metric: FxMetric) -> &'static str {
match metric {
FxMetric::Nominal => INDICATOR_NOMINAL,
FxMetric::Average => INDICATOR_AVERAGE,
FxMetric::AverageYtd => INDICATOR_AVERAGE_YTD,
}
}
fn find_fx_series(
items: &[CategoryNewItem],
periodicity: FxPeriodicity,
metric: FxMetric,
) -> Option<SeriesPreset> {
let periodicity_substr = periodicity_substr(periodicity);
let indicator_name = indicator_name(metric);
items
.iter()
.find(|item| {
item.category_name.contains(CATEGORY_SUBSTR)
&& item.category_name.contains(periodicity_substr)
&& item.indicator_name == indicator_name
})
.map(|item| SeriesPreset::new(item.category_id, item.indicator_id))
}
}