Redo time-series spec.

[?]
CrEcTsRjb1hHQjHuumqRfqdbVV4X58iLEubi4noaDPFa
Jul 21, 2021, 12:43 AM
2CCG6KUP6VL2Q7WQKLVNIPPGZWHSWIOWETRCS3APZTV4WSF5GLWAC

Dependencies

  • [2] AZQVIGSM First record
  • [3] K4CH53V4 Added GPL2 license, included missing source files.
  • [4] GQVS55HI Finished generate_ts_spec() function.
  • [5] SPSFTMLR Completed loading ts_data from specification.
  • [6] 77SIQZ3E Separating out spec generation.
  • [7] A6ZAYJNB Debugging DataSelector
  • [8] 4MG5JFXT First record.
  • [9] JTX5OHWH Added USA CPI.
  • [10] YJXKWWM6 Added max() min() n GraphicJson and cleaned up serialization
  • [11] UKQAGL5F Checked ts_json toolchain.
  • [12] GUXZCEWW Added Country enum.
  • [13] XI5ALEH6 Take advantage of keytree FromStr functionality.
  • [14] TTR5IFSG Working on building generic TSSpec.
  • [15] UUD3CJZL Making error handling more comprehensive.
  • [16] 2SABVMY3 Finished into_json() functionality.
  • [17] 4QOTH75I Fixed UI specification code.
  • [18] LVMGQJGH Finished framework for checking series specifications with data.
  • [19] U4VCAFXQ Added data_type to TSSpec key.
  • [20] SAHJYVNB Removed checking functionality.

Change contents

  • file move: tests (dxwrxwrx-r)tests (d--r------)
    [1.0]
    [2.8]
  • file move: test.rs (-xw-xw-x--)test.rs (----------)
    [2.8]
    [2.19]
  • file move: src (dxwrxwrx-r)src.AZQVIGSM6OJHM (d--r------)
    [1.0]
    [2.2628]
  • file move: response.rs (-xw-xw-x--)response.rs (----------)
    [2.2628]
    [2.2643]
  • file move: lib.rs (-xw-xw-x--)lib.rs (----------)
    [2.2628]
    [2.21264]
  • file move: src (dxwrxwrx-r)src (d--r------)
    [1.0]
    [4.6]
  • file move: ui.rs (-xw-xw-x--)ui.rs (----------)
    [4.6]
    [4.14]
  • edit in src/ui.rs at line 7
    [4.132][4.0:23]()
    use std::str::FromStr;
  • edit in src/ui.rs at line 19
    [4.378]
    [4.23]
    DateRange,
  • edit in src/ui.rs at line 24
    [4.429][4.24:25]()
  • edit in src/ui.rs at line 190
    [4.1712][4.1712:1713]()
  • replacement in src/ui.rs at line 222
    [4.3240][4.3240:3314]()
    let range = MonthlyDate::range(&self.start_date, &self.end_date);
    [4.3240]
    [4.3314]
    let range = DateRange::new(&self.start_date, &self.end_date);
  • replacement in src/ui.rs at line 227
    [4.3456][4.3456:3500]()
    xy_data.with_range(&range);
    [4.3456]
    [4.3500]
    xy_data.with_range(&range.0);
  • edit in src/ui.rs at line 253
    [4.3675][4.3675:3678](),[4.3678][4.3966:4050](),[4.4050][4.1930:1955](),[4.1930][4.1930:1955]()
    }
    /// Transforms from a TimeSeries<1> to another TimeSeries<1>.
    pub enum Transform1 {
    /// No-op
    Ident,
  • edit in src/ui.rs at line 255
    [4.4134][4.4051:4081](),[4.4081][4.1985:2007](),[4.1985][4.1985:2007]()
    impl FromStr for Transform1 {
    type Err = Error;
  • edit in src/ui.rs at line 256
    [4.4224][4.2008:2080](),[4.2080][4.4082:4128](),[4.4128][4.44:105](),[4.105][4.4171:4457](),[4.4171][4.4171:4457](),[4.4457][4.106:199](),[4.199][4.4843:4853](),[4.1010][4.4843:4853](),[4.2197][4.4843:4853](),[4.4500][4.4843:4853](),[4.4843][4.4843:4853](),[4.4870][4.4870:4876](),[4.5034][4.5034:5036](),[4.5392][4.5392:5393]()
    fn from_str(s: &str) -> Result<Self, Self::Err> {
    match s {
    "ident" => Ok(Transform1::Ident),
    _ => Err(parse_transform1(file!(), line!(), s)),
    }
    }
    }
    /// Transforms from two TimeSeries<1> to a TimeSeries<2>.
    pub enum Transform2 {
    ///
    Zip,
    }
    impl FromStr for Transform2 {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
    match s {
    "zip" => Ok(Transform2::Zip),
    _ => {
    Err(parse_transform2(file!(), line!(), s))
    },
    }
    }
    }
  • file move: ts.rs (-xw-xw-x--)ts.rs (----------)
    [4.6]
    [4.7119]
  • replacement in src/ts.rs at line 1
    [4.7119][4.1001:1022]()
    #![allow(dead_code)]
    [4.7119]
    [4.1022]
    // #![allow(dead_code)]
  • edit in src/ts.rs at line 8
    [4.7677]
    [4.7677]
    use std::str::FromStr;
  • edit in src/ts.rs at line 28
    [4.1092]
    [3.0]
    DateRange,
  • edit in src/ts.rs at line 37
    [3.54][4.1136:1733](),[4.117][4.1136:1733](),[4.1136][4.1136:1733](),[4.1733][4.7998:7999](),[4.7998][4.7998:7999](),[4.7999][4.1734:1989](),[4.1989][4.8099:8100](),[4.8099][4.8099:8100](),[4.8100][4.1990:2296](),[4.2296][4.0:17](),[4.626][4.0:17](),[4.17][4.2297:2346](),[4.666][4.8147:8148](),[4.2346][4.8147:8148](),[4.8147][4.8147:8148](),[4.8148][4.2347:2361](),[4.681][4.8166:8167](),[4.2361][4.8166:8167](),[4.8166][4.8166:8167](),[4.8167][4.2362:2550](),[4.738][4.8231:8238](),[4.2550][4.8231:8238](),[4.8231][4.8231:8238](),[4.8238][4.2551:2619](),[4.2619][4.8314:8320](),[4.8314][4.8314:8320](),[4.8320][4.787:788](),[4.788][4.2620:2954](),[4.2954][4.364:370](),[4.980][4.364:370](),[4.370][4.2955:2957](),[4.2957][4.370:371](),[4.370][4.370:371](),[4.371][4.2958:3037](),[4.3037][4.868:869](),[4.868][4.868:869](),[4.869][4.3038:3050](),[4.3050][4.344:345](),[4.869][4.344:345](),[4.345][4.3051:3114](),[4.3114][4.943:944](),[4.943][4.943:944](),[4.944][4.3115:3156](),[4.3156][4.5366:5367](),[4.1002][4.5366:5367](),[4.5367][4.3157:3192](),[4.3192][4.346:347](),[4.5367][4.346:347](),[4.347][4.3193:3576](),[4.3576][4.1154:1170](),[4.1154][4.1154:1170](),[4.1170][4.3577:3619](),[4.3619][4.1211:1221](),[4.1211][4.1211:1221](),[4.1221][4.3620:3805](),[4.1241][4.980:986](),[4.3805][4.980:986](),[4.980][4.980:986](),[4.986][4.8320:8323](),[4.2151][4.8320:8323](),[4.8320][4.8320:8323](),[4.8323][3.55:72](),[3.72][4.3834:4209](),[4.3834][4.3834:4209](),[4.1131][4.8557:8567](),[4.4209][4.8557:8567](),[4.8557][4.8557:8567](),[4.8578][4.8578:8584](),[4.8586][4.8586:8587](),[4.8587][4.4210:4316](),[4.4316][3.73:2012](),[4.1325][4.8825:8834](),[3.2012][4.8825:8834](),[4.4316][4.8825:8834](),[4.8825][4.8825:8834]()
    // --- Client-facing data-structures --------------------------------------------------------------
    /// `(DataType, Country)` key to lookup data or spec.
    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
    pub struct PageKey {
    ///
    pub country: Country,
    ///
    pub data_type: DataType,
    ///
    pub index: usize,
    }
    impl PageKey {
    /// Return a new `PageKey`.
    pub fn new(country: Country, data_type: DataType, index: usize) -> Self {
    PageKey { country, data_type, index }
    }
    }
    impl<'a> TryInto<PageKey> for KeyTreeRef<'a> {
    type Error = keytree::Error;
    fn try_into(self) -> Result<PageKey, Self::Error> {
    Ok(PageKey {
    index: self.value("key::index")?,
    data_type: self.value("key::data_type")?,
    country: self.value("key::country")?,
    })
    }
    }
    /// Represents a series of graphics to be plotted on one page. A `PageKey` is a combination of
    /// `Country` and `DataType`. It is served to the client as one chunk of JSON.
    // GraphicJson. Json holds the JSON serialization as a String. PageJson is the largest component
    // that is serializable into JSON.
    #[derive(Debug)]
    pub struct TSData(pub HashMap<PageKey, String>);
    impl TSData {
    /// Build time-series data from a time-series specification.
    pub fn from_spec(spec: &Spec, root_path: &str) -> Result<Self, Error> {
    spec
    .into_data(root_path)
    }
    pub (crate) fn new() -> TSData {
    TSData(HashMap::new())
    }
    pub (crate) fn insert(&mut self, key: &PageKey, value: String) {
    match self.0.get_mut(key) {
    Some(_) => {
    println!("Tried to insert page_key: {:?} twice.", key);
    panic!();
    },
    None => {
    self.0.insert(*key, value);
    },
    }
    }
    }
    /// Converts specification data into `TSData`.
    pub struct Json(Vec<PageJson>);
    impl Json {
    pub (crate) fn into_data(&self) -> Result<TSData, Error> {
    let mut ts_data = TSData::new();
    for page_json in &self.0 {
    let key = PageKey::new(
    page_json.country,
    page_json.data_type,
    page_json.index
    );
    let value = match serde_json::to_string(&page_json) {
    Ok(s) => s,
    Err(err) => {
    eprintln!("{}", err.to_string());
    panic!();
    },
    };
    ts_data.insert(&key, value);
    }
    Ok(ts_data)
    }
    pub (crate) fn new() -> Self {
    Json(Vec::new())
    }
    pub (crate) fn push(&mut self, page_json: PageJson) {
    self.0.push(page_json);
    }
    }
    #[derive(Debug)]
    /// Serializable into JSON data for a time-series HTML page.
    pub struct PageJson {
    country: Country,
    data_type: DataType,
    index: usize,
    graphics: Vec<GraphicJson>,
    }
    impl PageJson {
    pub (crate) fn new(country: Country, data_type: DataType, index: usize) -> Self {
    PageJson {
    country, data_type, index, graphics: Vec::new()
    }
    }
    pub (crate) fn push(&mut self, graphic_json: GraphicJson) {
    self.graphics.push(graphic_json);
    }
    pub (crate) fn max(&self) -> f32 {
    self.graphics.iter()
    .map(|graphic| graphic.max())
    .fold(f32::NEG_INFINITY, |a, b| a.max(b))
    }
    pub (crate) fn min(&self) -> f32 {
    self.graphics.iter()
    .map(|graphic| graphic.min())
    .fold(f32::INFINITY, |a, b| a.min(b))
    }
    pub (crate) fn first_date(&self) -> MonthlyDate {
    match self.graphics.iter()
    .map(|graphic| graphic.first_date().0)
    .min()
    {
    Some(date) => MonthlyDate(date),
    None => {
    // No data in series?
    eprintln!("Could not calculate first date.");
    panic!()
    },
    }
    }
    pub (crate) fn last_date(&self) -> MonthlyDate {
    match self.graphics.iter()
    .map(|graphic| graphic.last_date().0)
    .max()
    {
    Some(date) => MonthlyDate(date),
    None => {
    // No data in series?
    eprintln!("Could not calculate last date.");
    panic!()
    },
    }
    }
    }
    impl Serialize for PageJson {
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
    where
    S: Serializer,
    {
    let mut page_json = serializer.serialize_struct("Json", 6)?;
    page_json.serialize_field("country", &self.country)?;
    page_json.serialize_field("data_type", &self.data_type)?;
    page_json.serialize_field("index", &self.index)?;
    page_json.serialize_field("max", &self.max())?;
    page_json.serialize_field("min", &self.min())?;
    page_json.serialize_field("first_date", &self.first_date())?;
    page_json.serialize_field("last_date", &self.last_date())?;
    page_json.serialize_field("graphics", &self.graphics)?;
    page_json.serialize_field("height", &GRAPHIC_HEIGHT)?;
    page_json.end()
    }
    }
  • edit in src/ts.rs at line 38
    [3.2014][4.4317:4390](),[4.8834][4.4317:4390](),[4.4390][4.118:135](),[4.135][4.4418:4443](),[4.4418][4.4418:4443](),[4.4443][4.2247:2255](),[4.1723][4.2247:2255](),[4.2255][4.4444:4473](),[4.4473][4.2265:2273](),[4.5830][4.2265:2273](),[4.1782][4.2265:2273](),[4.2273][4.4474:4535](),[4.4535][4.8930:8933](),[4.8930][4.8930:8933](),[4.8933][4.4536:4670](),[4.4670][4.136:141](),[4.141][4.9110:9126](),[4.2463][4.9110:9126](),[4.4670][4.9110:9126](),[4.9110][4.9110:9126](),[4.9126][4.1964:1965](),[4.1965][4.4671:4811](),[4.4811][4.142:590](),[4.590][4.5981:5987](),[4.4811][4.5981:5987](),[4.5981][4.5981:5987](),[4.5987][4.591:592](),[4.592][3.2015:2863](),[3.2863][4.592:740](),[4.592][4.592:740](),[4.740][4.4812:4814](),[4.5987][4.4812:4814](),[4.4814][4.741:896](),[4.896][3.2864:2943](),[3.2943][4.1144:1145](),[4.1144][4.1144:1145](),[4.1225][4.1225:1471](),[4.1471][3.2944:3088](),[3.3088][4.1471:1508](),[4.1471][4.1471:1508]()
    /// GraphicJson is the largest component that is serializable into JSON.
    #[derive(Debug)]
    pub struct GraphicJson {
    ///
    pub height: Option<f32>,
    ///
    pub series: Vec<(RegularTimeSeries<1>, SeriesMetaData)>,
    }
    impl GraphicJson {
    pub (crate) fn new() -> Self {
    GraphicJson {
    height: None,
    series: Vec::new(),
    }
    }
    pub (crate) fn push(&mut self, time_series: RegularTimeSeries<1>, meta: SeriesMetaData) {
    self.series.push((time_series, meta))
    }
    /// Calculate the maximum value of all series in `Self`.
    pub (crate) fn max(&self) -> f32 {
    self.series.iter()
    .map(|(ts, _)| ts.max(0))
    .fold(f32::NEG_INFINITY, |a, b| a.max(b))
    }
    /// Calculate the minimum value of all series in `Self`.
    pub (crate) fn min(&self) -> f32 {
    self.series.iter()
    .map(|(ts, _)| ts.min(0))
    .fold(f32::INFINITY, |a, b| a.min(b))
    }
    /// Return first date in all series.
    pub (crate) fn first_date(&self) -> MonthlyDate {
    match self.series.iter()
    .map(|(ts, _)| ts.first_date())
    .min()
    {
    Some(date) => MonthlyDate(date),
    None => {
    // No data in series?
    eprintln!("Could not calculate first date.");
    panic!()
    }
    }
    }
    /// Return last date of in all series.
    pub (crate) fn last_date(&self) -> MonthlyDate {
    match self.series.iter()
    .map(|(ts, _)| ts.last_date())
    .max()
    {
    Some(date) => MonthlyDate(date),
    None => {
    // No data in series?
    eprintln!("Could not calculate first date.");
    panic!()
    }
    }
    }
    pub (crate) fn height(&self) -> f32 {
    match self.height {
    Some(h) => h,
    None => GRAPHIC_HEIGHT,
    }
    }
    }
    impl Serialize for GraphicJson {
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
    where
    S: Serializer,
    {
    let mut graphic_json = serializer.serialize_struct("GraphicJson", 6)?;
    graphic_json.serialize_field("height", &self.height())?;
    graphic_json.serialize_field("series", &self.series)?;
    graphic_json.serialize_field("max", &self.max())?;
    graphic_json.serialize_field("min", &self.min())?;
    graphic_json.serialize_field("first_date", &self.first_date())?;
    graphic_json.serialize_field("last_date", &self.last_date())?;
    graphic_json.end()
    }
    }
  • edit in src/ts.rs at line 58
    [4.5365][4.5365:6616]()
    // The Spec components do not map well to Json components.
    // 1. Json is not serializable - it is a HashMap which maps PageKeys to Strings to serve.
    // 2. PageJson does not exists. PageSpec.into_json creates a Vec<GraphicJson>.
    pub (crate) fn into_data(&self, root_path: &str) -> Result<TSData, Error> {
    let mut json = Json::new();
    for page_spec in &self.0 {
    let mut page_json = PageJson::new(
    page_spec.country,
    page_spec.data_type,
    page_spec.index,
    );
    for graphic_spec in &page_spec.graphics {
    let mut graphic_json = GraphicJson::new();
    for series_spec in &graphic_spec.seriess {
    let rts = data_from_file(
    page_spec.country,
    series_spec.data_type,
    series_spec.series_id.clone(),
    root_path,
    )?;
    let meta = meta_from_file(
    page_spec.country,
    series_spec.data_type,
    series_spec.series_id.clone(),
    root_path,
    );
  • edit in src/ts.rs at line 59
    [4.6617][4.6617:6784](),[4.2586][4.2092:2102](),[4.6025][4.2092:2102](),[4.6784][4.2092:2102](),[4.2092][4.2092:2102](),[4.2102][4.6785:6959](),[4.6959][4.2102:2108](),[4.2102][4.2102:2108](),[4.9128][4.9128:9129]()
    graphic_json.push(rts, meta);
    }
    page_json.push(graphic_json);
    }
    json.push(page_json);
    }
    // Now we have a Json datastructure which we can iterate over the pages, serialize, generate
    // keys, and build a TSData Hashmap.
    json.into_data()
    }
  • edit in src/ts.rs at line 119
    [4.8547]
    [4.8547]
    series: Vec<SeriesSpec>,
  • edit in src/ts.rs at line 130
    [4.8709]
    [4.8709]
    series: Vec<SeriesSpec>,
  • replacement in src/ts.rs at line 133
    [4.8762][4.8762:8819]()
    PageSpec { country, data_type, index, graphics }
    [4.8762]
    [4.2880]
    PageSpec { country, data_type, index, series, graphics }
  • edit in src/ts.rs at line 146
    [4.9164]
    [4.9164]
    series: self.vec_at("page::series")?,
  • edit in src/ts.rs at line 150
    [4.3483]
    [4.10298]
    }
    }
    /// Specifies what text a graphic displays.
    pub enum TextSpec {
    /// Specifies that graphic displays Links to series.
    Link,
    /// Specifies that graphics displays metadata.
    Meta,
    /// Specifies that graphics do not display text.
    None,
    }
    impl FromStr for TextSpec {
    type Err = Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
    match s {
    "link" => Ok(TextSpec::Link),
    "meta" => Ok(TextSpec::Meta),
    _ => Err(keytree_error(file!(), line!(), "Failed to parse to Text")),
    }
  • edit in src/ts.rs at line 186
    [4.9473]
    [4.9473]
    title: Option<String>,
  • replacement in src/ts.rs at line 188
    [4.9502][4.9502:9541]()
    seriess: Vec<self::SeriesSpec>,
    [4.9502]
    [4.9541]
    series_id: Vec<SeriesId>,
    fid: Vec<String>,
    text: TextSpec,
  • replacement in src/ts.rs at line 194
    [4.9563][4.9563:9598]()
    pub (crate) fn new() -> Self {
    [4.9563]
    [4.9598]
    pub (crate) fn empty() -> Self {
  • replacement in src/ts.rs at line 196
    [4.9620][4.9620:9679]()
    height: None,
    seriess: Vec::new(),
    [4.9620]
    [4.10698]
    title: None,
    height: None,
    series_id: Vec::new(),
    fid: Vec::new(),
    text: TextSpec::None,
  • replacement in src/ts.rs at line 204
    [4.9687][4.9687:9794](),[4.9794][4.10719:10725](),[4.10719][4.10719:10725]()
    pub (crate) fn push(&mut self, series_spec: self::SeriesSpec) {
    self.seriess.push(series_spec)
    }
    [4.9687]
    [4.10725]
    // pub (crate) fn push(
    // &mut self,
    // title: Option<Title>,
    // height: Option<f32>,
    // transform_spec: Vec<TransformSpec>)
    // {
    // let graph_spec = GraphSpec {
    // title,
    // height,
    // transform_spec,
    // };
    // self.seriess.push(series_spec)
    // }
  • replacement in src/ts.rs at line 224
    [4.10874][4.9911:10061]()
    GraphicSpec{
    height: self.opt_value("graphic::height")?,
    seriess: self.vec_at("graphic::series")?,
    [4.10874]
    [4.7030]
    GraphicSpec {
    title: self.opt_value("graphic::title")?,
    height: self.opt_value("graphic::height")?,
    series_id: self.vec_value("graphic::series_id")?,
    fid: self.vec_value("graphic::fid")?,
    text: self.value("graphic::text")?,
  • edit in src/ts.rs at line 243
    [4.7185]
    [4.10259]
    #[derive(Debug)]
  • edit in src/ts.rs at line 247
    [4.7271]
    [4.7271]
    date_range: DateRange,
    transforms: Vec<Transform>,
    fid: Option<FID>,
  • edit in src/ts.rs at line 253
    [4.10302]
    [4.10302]
  • replacement in src/ts.rs at line 255
    [4.10311][4.7327:7394](),[4.7327][4.7327:7394]()
    pub fn new(data_type: DataType, series_id: SeriesId) -> Self {
    [4.10311]
    [4.10312]
    pub fn new(
    data_type: DataType,
    series_id: SeriesId,
    date_range: DateRange,
    transforms: Vec<Transform>,
    fid: Option<FID>,
    ) -> Self {
  • edit in src/ts.rs at line 265
    [4.7463]
    [4.7463]
    date_range,
    transforms,
    fid,
  • edit in src/ts.rs at line 276
    [4.10447]
    [4.7629]
    let first_date = self.opt_value("series::first_date")?;
    let last_date = self.opt_value("series::last_date")?;
    let date_range = DateRange::new(&first_date, &last_date);
  • replacement in src/ts.rs at line 284
    [4.7641][4.10448:10472](),[4.10472][4.7668:7790](),[4.7668][4.7668:7790]()
    SeriesSpec{
    data_type: self.value("series::data_type")?,
    series_id: self.value("series::series_id")?,
    [4.7641]
    [4.11011]
    SeriesSpec {
    data_type: self.value("series::data_type")?,
    series_id: self.value("series::series_id")?,
    date_range,
    transforms: self.vec_value("series::transform")?,
    fid: self.opt_value("series::fid")?,
  • edit in src/ts.rs at line 293
    [4.8105]
    [4.8105]
    }
    // === Transforms ==================================================================================
    /// Transforms from a TimeSeries<1> to another TimeSeries<1>.
    #[derive(Debug)]
    pub enum Transform {
    ///
    ToMonthly,
    ///
    ToQuarterly,
    /// Year on year percentage change.
    YearOnYear,
  • edit in src/ts.rs at line 308
    [4.8108]
    [4.8108]
    impl FromStr for Transform {
    type Err = Error;
  • edit in src/ts.rs at line 311
    [4.8109]
    [4.8109]
    fn from_str(s: &str) -> Result<Self, Self::Err> {
    match s {
    "to_monthly" => Ok(Transform::ToMonthly),
    "to_quarterly" => Ok(Transform::ToQuarterly),
    "yoy" => Ok(Transform::YearOnYear),
    _ => Err(parse_transform1(file!(), line!(), s)),
    }
    }
    }
    /// SeriesIdentifierAfterTransform
    #[derive(Debug)]
    pub struct FID(String);
  • edit in src/ts.rs at line 325
    [4.8110]
    [4.11144]
    impl FID {
    pub (crate) fn new(series_id: &SeriesId, f: Vec<Transform>) -> Self {
    let mut s = format!(
    "{}_",
    series_id,
    );
    for transform in f {
    match transform {
    Transform::ToMonthly => { s.push('m') },
    Transform::ToQuarterly => { s.push('q') },
    Transform::YearOnYear => { s.push('y') },
    }
    }
    FID(s)
    }
    }
  • edit in src/ts.rs at line 342
    [4.11145]
    [4.10473]
    impl FromStr for FID {
    type Err = Error;
  • edit in src/ts.rs at line 345
    [4.10478]
    fn from_str(s: &str) -> Result<Self, Self::Err> {
    Ok(FID(String::from(s)))
    }
    }
  • file move: main.rs (-xw-xw-x--)main.rs (----------)
    [4.6]
    [4.10]
  • replacement in src/main.rs at line 18
    [4.1637][4.1637:1657]()
    use ui_data::ui::*;
    [4.1637]
    [4.72]
    // use ui_data::ui::*;
  • replacement in src/main.rs at line 56
    [4.11388][4.11388:11459]()
    let ts_spec = ts::Spec::from_file("ts_spec.keytree").unwrap();
    [4.11388]
    [4.11459]
    // let ts_spec = ts::Spec::from_file("ts_spec.keytree").unwrap();
  • replacement in src/main.rs at line 58
    [4.11468][4.11468:11539]()
    let ts_data = TSData::from_spec(&ts_spec, &root_dir).unwrap();
    [4.11468]
    [4.11539]
    // let ts_data = TSData::from_spec(&ts_spec, &root_dir).unwrap();
  • replacement in src/main.rs at line 60
    [4.11540][4.11540:11564]()
    dbg!(&ts_data);
    [4.11540]
    [4.11564]
    // dbg!(&ts_data);
  • file move: lib.rs (-xw-xw-x--)lib.rs (----------)
    [4.6]
    [4.16]
  • replacement in src/lib.rs at line 175
    [4.7834][4.2232:2244]()
    pub mod ui;
    [4.7834]
    [4.7835]
    // pub mod ui;
  • edit in src/lib.rs at line 201
    [4.12253][4.12253:12268]()
    DateRange,
  • edit in src/lib.rs at line 205
    [4.2378][4.2378:2403]()
    use crate::error::Error;
  • replacement in src/lib.rs at line 226
    [4.2488][3.6137:6158]()
    #[derive(Serialize)]
    [4.2488]
    [4.2488]
    #[derive(Clone, Serialize)]
  • edit in src/lib.rs at line 228
    [4.2538][4.10817:11168]()
    impl MonthlyDate {
    /// Create a time_series::DateRange.
    pub fn range(
    date_opt1: &Option<MonthlyDate>,
    date_opt2: &Option<MonthlyDate>) -> time_series::DateRange
    {
    time_series::DateRange::new(
    date_opt1.as_ref().map(|date| date.0),
    date_opt2.as_ref().map(|date| date.0),
    )
    }
    }
  • edit in src/lib.rs at line 239
    [3.6160]
    [3.6160]
    /// `DateRange` newtype.
    #[derive(Debug)]
    pub struct DateRange(time_series::DateRange);
  • edit in src/lib.rs at line 243
    [3.6161]
    [4.2868]
    impl DateRange {
  • edit in src/lib.rs at line 245
    [4.2869]
    [4.2869]
    /// Create a time_series::DateRange.
    pub fn new(
    first_date: &Option<MonthlyDate>,
    last_date: &Option<MonthlyDate>) -> DateRange
    {
    DateRange(
    time_series::DateRange::new(
    &first_date.clone().map(|d| d.0),
    &last_date.clone().map(|d| d.0),
    )
    )
    }
    ///
    pub fn first_date(&self) -> Option<MonthlyDate> {
    self.0.first_date().map(|date| MonthlyDate(date))
    }
    ///
    pub fn last_date(&self) -> Option<MonthlyDate> {
    self.0.last_date().map(|date| MonthlyDate(date))
    }
    }
  • replacement in src/lib.rs at line 449
    [4.4927][4.13604:13696]()
    /// Build a generic `Spec` from `Self`.
    pub fn generic_ts_spec(&self) -> ts::Spec {
    [4.4927]
    [4.5019]
    // /// Build a generic `Spec` from `Self`.
    // pub fn generic_ts_spec(&self) -> ts::Spec {
  • replacement in src/lib.rs at line 452
    [4.5020][4.13697:13740]()
    let mut ts_spec = ts::Spec::new();
    [4.5020]
    [4.5061]
    // let mut ts_spec = ts::Spec::new();
  • replacement in src/lib.rs at line 454
    [4.5062][4.5062:5132]()
    for ((data_type, country), series_specs) in self.map.iter() {
    [4.5062]
    [4.5132]
    // for ((data_type, country), series_specs) in self.map.iter() {
  • replacement in src/lib.rs at line 456
    [4.5133][4.13741:13803]()
    let mut ts_graphic_spec = ts::GraphicSpec::new();
    [4.5133]
    [4.5193]
    // let mut graphic_spec = ts::GraphicSpec::empty();
  • replacement in src/lib.rs at line 458
    [4.5194][4.5194:5240](),[4.5240][4.13804:13862](),[4.13862][4.5296:5477](),[4.5296][4.5296:5477]()
    for series_spec in series_specs {
    let ts_series_spec = ts::SeriesSpec::new(
    series_spec.data_type,
    series_spec.series_id.clone()
    );
    ts_graphic_spec.push(ts_series_spec);
    };
    [4.5194]
    [4.5477]
    // let series_id = series_spec.series_id;
    // let f = Vec::new();
    // for series_spec in series_specs {
    // let series_spec = ts::SeriesSpec::new(
    // series_spec.data_type,
    // series_id,
    // DateRange::new(&None, &None),
    // f,
    // FID::new(series_id, f),
    // );
    // graphic_spec.push(series_spec);
    // };
  • replacement in src/lib.rs at line 472
    [4.13864][4.13864:14041]()
    let ts_page_spec = ts::PageSpec::new(
    *country,
    *data_type,
    0,
    vec!(ts_graphic_spec),
    );
    [4.5478]
    [4.14041]
    // let page_spec = ts::PageSpec::new(
    // *country,
    // *data_type,
    // 0,
    // Vec::new(),
    // vec!(graphic_spec),
    // );
  • replacement in src/lib.rs at line 480
    [4.14042][4.5625:5698](),[4.5625][4.5625:5698]()
    ts_spec.push(ts_page_spec);
    }
    ts_spec
    }
    [4.14042]
    [4.5698]
    // spec.push(ts_page_spec);
    // }
    // spec
    // }
  • replacement in src/lib.rs at line 792
    [4.20935][4.20935:21000]()
    for date_point in rts.iter(DateRange::new(None, None)) {
    [4.20935]
    [4.21000]
    for date_point in rts.iter(DateRange::new(&None, &None).0) {
  • edit in src/lib.rs at line 1067
    [4.23902]
  • file move: fred.rs (-xw-xw-x--)fred.rs (----------)
    [4.6]
    [3.6172]
  • file move: error.rs (-xw-xw-x--)error.rs (----------)
    [4.6]
    [3.14566]
  • file move: LICENSE (-xw-xw-x--)LICENSE (----------)
    [1.0]
    [3.20270]
  • file move: Cargo.toml (-xw-xw-x--)Cargo.toml.AZQVIGSM6OJHM (----------)
    [1.0]
    [2.33361]
  • file move: Cargo.toml (-xw-xw-x--)Cargo.toml (----------)
    [1.0]
    [4.126]