A6ZAYJNBYFXPUTCHTQDGAWUZIYOXNO3IJBN73ZX6PEJ3T4NMNOGQC
SAHJYVNBUBBIUBI4ZMAXK4QJFOT54M5UA3W2HQMTNDSP3GGCRX7QC
4MG5JFXTKAE3SOVKGGNKEUTNCKOWEBHTGKVZHJWLWE3PTZTQKHPAC
LVMGQJGH34VSGZCB74IQEJIVFNJE6OPQQCF7IPS72NPVMIUFBV4AC
TTR5IFSG25VNBQ2F2FNOLUMTEIHVBHFOEXYB2ZWEHWOURUV4GJMQC
GQVS55HIQLU7KPJNRMF57QUM4EATSWFQRCS7ZEJMJPUXFX2NHSYAC
XI5ALEH6NPTQWB6O62QV62EP4H3K7WSNTHCOGT3LZIIU6I2YDGIQC
2SABVMY3A2RZDF3KJXZSMJ2UQ4Q5EW422G4DVBJRKK26S2ESGVQAC
U4VCAFXQNTKC7KWWE3B2JJMZMFRGLBOHSZIOXCE6EEXW7WE2Q5NAC
GUXZCEWWPBCHXO26JVWZ74CTSDFDDO775YR7FKY7UGVZCA7GCSYAC
5POF332LJEBGWEJUGI34P33Q4BQP7CAQNV5ODQT3PWG7FI7VNLOQC
77SIQZ3EGGV6KSECMLPDKQFGEC7CCFAPWGER7ZARQ5STDKJNU6GQC
use std::collections::{
BTreeMap,
HashMap,
};
use std::convert::TryInto;
use std::fs;
use serde::Serialize;
use time::OffsetDateTime;
use countries::Country;
use fred_api::{
Fred,
};
use keytree::{KeyTree, KeyTreeRef};
use keytree::serialize::{
IntoKeyTree,
KeyTreeString,
};
use time_series::{
RegularTimeSeries,
TimeSeries,
};
use crate::serve_ts::{
TSGraphicSpec,
TSPageSpec,
};
impl DataSpec {
/// Check for errors that might have occurred somewhere along the toolchain.
let mut builder = CheckedDataSpec(Vec::new());
}
builder
// This is a specification for CheckedData
/// ```
/// series:
/// data_type: u
/// country: United States
/// id: LRUNTTTTUSQ156S
/// ```
impl<'a> TryInto<CheckedDataSpec> for KeyTreeRef<'a> {
Ok(
)
}
}
impl IntoKeyTree for CheckedDataSpec {
fn keytree(&self) -> KeyTreeString {
let mut kt = KeyTreeString::new();
for series in &self.0 {
kt.push_keytree(1, series.keytree());
}
kt
}
}
/// `CheckedSourceSeries` is a code representation of the 'checked_data.keytree' specification file.
/// It acts as the gate-keeper to the data on disk.
pub struct CheckedSourceSeries {
impl IntoKeyTree for CheckedSourceSeries {
fn keytree(&self) -> KeyTreeString {
let mut kt = KeyTreeString::new();
kt.push_key(0, "series");
kt
}
}
impl<'a> TryInto<CheckedSourceSeries> for KeyTreeRef<'a> {
type Error = keytree::Error;
fn try_into(self) -> Result<CheckedSourceSeries, keytree::Error> {
Ok(
CheckedSourceSeries{
}
)
}
}
data_type: self.value("series::data_type")?,
country: self.value("series::country")?,
series_id: self.value("series::series_id")?,
drop_first: self.opt_value("series::drop_first")?,
let country: Country = self.value("series::country")?;
// let time_stamp = match date_str {
// Some(date_str) => {
// Some(OffsetDateTime::parse(date_str, "%Y %T").unwrap())
// },
// None => None,
// };
kt.push_value(1, "data_type", &self.data_type.to_string());
kt.push_value(1, "country", &self.country.to_string());
kt.push_value(1, "series_id", &self.series_id.to_string());
kt.push_opt_value(1, "drop_first", self.drop_first);
pub data_type: DataType,
///
pub country: Country,
///
///
}
pub drop_first: Option<usize>,
pub series_id: SeriesId,
///
kt.push_key(0, "page");
CheckedDataSpec(self.vec_at("seriess::series")?)
fn try_into(self) -> Result<CheckedDataSpec, Self::Error> {
type Error = keytree::Error;
pub struct CheckedDataSpec(pub Vec<CheckedSourceSeries>);
}
}
for series_spec in &self.0 {
let checked_series = CheckedSourceSeries {
data_type: series_spec.data_type,
country: series_spec.country,
series_id: series_spec.series_id.clone(),
drop_first: None,
};
builder.0.push(checked_series);
pub fn into_checked(&self) -> CheckedDataSpec {
TSSeriesSpec,
TSSpec,
PageKey,
use crate::build_spec::{
DataSpec,
};
use crate::error::*;
use crate::{
DataType,
SeriesId,
};
use std::str::FromStr;
//! Probably the most effective way to find stuff, is to search on tags and then filter on series
//! title, such as
//! ```
//! for item in Fred::tags_series("usa;interest")
//! .unwrap()
//! .series()
//! .has_phrase("Prime")
//! .iter()
//! {
//! println!("{}", item);
//! }
//! ```
//! The filters such as `has_phrase` are found in the `fred_api` crate.
//! The data series selector specification looks like
//! ## Step 2. Build a generic data specification.
//!
//! The results of Step 1 are integrated into algorithms in the `build_spec` module. These can then
//! be used to generate collections of series.
//!
//! These specifications are then edited by hand, and cannot be programatically regenerated after
//! editting. To modify the spec. programmatically, a newly generated `Keytree` string can be
//! manually appended.
//!
//! Example:
//! ```
//! println!("{}", generic_data_spec().keytree());
//! ```text
//! selectors:
//! series:
//! country: Australia,
//! data_type: u
//! tag: unemployment
//! none_of: Male
//! none_of: Female
//! none_of: 55-64
//! none_of: 25-54
//! none_of: 15-24
//! none_of: 20 to 24
//! none_of: Youth
//! none_of: Women
//! none_of: Teenagers
//! not_any_of: Rate
//!
//! series:
//! country: Austria,
//! data_type: u
//! tag: unemployment
//! none_of: Male
//! none_of: Female
//! none_of: 55-64
//! none_of: 25-54
//! none_of: 15-24
//! The structure of JSON which is served to the client is determined by `Serialize`-able data
//! structures. The top structure is `TSJson`. The `ts_spec.keytree` file specifies the graphics on
//! each page, and what data each graphic uses. The `ts_spec.keytree` file is deserialized into
//! `TSSpec`.
//! This step converts the specification in JSON data and meta-data that is served to the client.
//! The client Javascript then builds the graphics dynamically. Take both specifications and load
//! data from "/full/path/to/data".
//! The procedure is generally to read in the specification in `ts_spec.keytree`.
//! `data_spec.keytree` which specifies data available, and also acts as a gate-keeper for that
//! data.
//!
//! Then `TSSpec` uses `IndexedCheckedDataSpec` as an argument to be converted into `TSJson`.
//!
//!
//! We want to serve data to clients in a particular way depending on the client (time-series or
//! scatter plots). Each client-facing data-structure has its own specification. The two
//! specifications interact.
//! All JSON is generated at server startup into an immutable `HashMap` in memory.