Completed first try at UIData.

[?]
CrEcTsRjb1hHQjHuumqRfqdbVV4X58iLEubi4noaDPFa
Jul 24, 2021, 9:13 AM
YAE43L6AF2HPQYJZDQGFYGFEV7722SUMAXXMP2ZQZMPE7VC6EWKAC

Dependencies

  • [2] PK7JY27R Integrate date_range with transforms.
  • [3] GQVS55HI Finished generate_ts_spec() function.
  • [4] PQKGZNQG Added class field to GraphicJson.
  • [5] BB2T6X3X Improved documentation.
  • [6] UUD3CJZL Making error handling more comprehensive.
  • [7] 2SABVMY3 Finished into_json() functionality.
  • [8] SAHJYVNB Removed checking functionality.
  • [9] EHEK63WA Cleaning up ts.rs.
  • [10] 77SIQZ3E Separating out spec generation.
  • [11] TSY4YBBZ Changed ts Spec datastructures to new format.
  • [12] E2T2A74Y Added class field to GraphicSpec.
  • [13] K4CH53V4 Added GPL2 license, included missing source files.
  • [14] XPXYFEZM Finished code for building TSJson struct.
  • [15] 5B2HBV3J Completed first try at ts Json data-structure.
  • [16] XI5ALEH6 Take advantage of keytree FromStr functionality.
  • [17] SPSFTMLR Completed loading ts_data from specification.
  • [18] 4QOTH75I Fixed UI specification code.
  • [19] TTR5IFSG Working on building generic TSSpec.
  • [20] 2CCG6KUP Redo time-series spec.
  • [21] YJXKWWM6 Added max() min() n GraphicJson and cleaned up serialization
  • [*] GUXZCEWW Added Country enum.
  • [*] 4MG5JFXT First record.

Change contents

  • replacement in src/ui.rs at line 3
    [3.1][3.1:22]()
    #![allow(dead_code)]
    [3.1]
    [3.104]
    use std::collections::BTreeMap;
    use std::convert::TryInto;
    use std::fs;
  • replacement in src/ui.rs at line 7
    [3.105][3.0:31](),[3.31][3.105:132](),[3.105][3.105:132]()
    use std::collections::HashMap;
    use std::convert::TryInto;
    [3.105]
    [3.163]
    use serde::Serialize;
  • edit in src/ui.rs at line 11
    [3.228]
    [3.228]
    KeyTree,
  • replacement in src/ui.rs at line 19
    [3.364][3.8:22](),[3.22][3.364:378](),[3.364][3.364:378](),[3.378][3.138:153](),[3.153][3.23:43](),[3.378][3.23:43](),[3.43][3.0:17](),[3.378][3.0:17]()
    DataSpec,
    DataType,
    DateRange,
    data_from_file,
    MonthlyDate,
    [3.364]
    [3.17]
    // DataSpec,
    DataType,
    // DateRange,
    // data_from_file,
    // MonthlyDate,
  • edit in src/ui.rs at line 25
    [3.31]
    [3.426]
    SeriesJson,
    SeriesSpec,
    Transform,
  • replacement in src/ui.rs at line 31
    [3.54][3.54:140](),[3.140][3.135:307]()
    // --- JSON Serializers -------------------------------------------------------------
    /// The top-level datastructure, served as JSON, that specifies all the data required to build a UI
    /// plot.
    pub struct UIJson(HashMap<(Country, usize), UIGraphicJson>);
    [3.54]
    [3.140]
    pub struct UIData(pub BTreeMap<(Country, usize), String>);
  • replacement in src/ui.rs at line 33
    [3.141][3.308:322]()
    impl UIJson {
    [3.141]
    [3.199]
    #[derive(Debug, Serialize)]
    pub struct FixedScale {
    x_max: f32,
    x_min: f32,
    y_max: f32,
    y_min: f32,
    }
  • replacement in src/ui.rs at line 41
    [3.200][3.323:421]()
    /// Create an empty `UIJson`.
    pub fn new() -> Self {
    UIJson(HashMap::new())
    }
    [3.200]
    [3.421]
    pub struct Json(BTreeMap<(Country, usize), GraphicJson>);
  • replacement in src/ui.rs at line 43
    [3.422][3.422:744]()
    /// Insert a `UIGraphicJson` into `UIJson`. If the country already exists, increment the index
    /// in the key until a space is available.
    pub fn insert(&mut self, ui_graphic_json: UIGraphicJson) {
    let mut ix = 0;
    while self.0.get(&(ui_graphic_json.country, 0)).is_none() {
    ix += 1;
    [3.422]
    [3.744]
    impl Json {
    pub fn into_ui_data(&self) -> Result<UIData, Error> {
    let mut map: BTreeMap<(Country, usize), String> = BTreeMap::new();
    for (key, value) in self.0.iter() {
    let json = serde_json::to_string(&value)
    .map_err(|_| {
    failed_to_serialize_to_json(
    file!(),
    line!(),
    )
    })?;
    map.insert(*key, json);
  • replacement in src/ui.rs at line 57
    [3.754][3.754:831]()
    self.0.insert((ui_graphic_json.country, ix), ui_graphic_json);
    }
    [3.754]
    [3.831]
    Ok(UIData(map))
    }
  • replacement in src/ui.rs at line 61
    [3.834][3.834:988]()
    /// A UI plot. `UIGraphicJson` can be serialized to JSON.
    pub struct UIGraphicJson {
    country: Country,
    title: String,
    lines: Vec<UILineJson>,
    [3.834]
    [3.988]
    #[derive(Debug, Serialize)]
    pub struct GraphicJson {
    country: Country,
    index: usize,
    lines: Vec<LineJson>,
    sized: Option<FixedScale>,
  • replacement in src/ui.rs at line 69
    [3.235][3.991:1112]()
    /// A line in a UI plot. `UILineJson` can be serialized to JSON.
    pub struct UILineJson {
    data: RegularTimeSeries<2>,
    [3.235]
    [3.1112]
    #[derive(Debug, Serialize)]
    pub struct LineJson {
    x_series_id: SeriesId,
    y_series_id: SeriesId,
    rts: RegularTimeSeries<2>,
    x_transforms: Vec<Transform>,
    y_transforms: Vec<Transform>,
  • replacement in src/ui.rs at line 78
    [3.236][3.236:322]()
    // --- Specification ----------------------------------------------------------------
    [3.236]
    [3.474]
    pub struct Spec(Vec<GraphicSpec>);
  • replacement in src/ui.rs at line 80
    [3.475][3.475:491](),[3.491][3.1115:1349](),[3.1349][3.758:810](),[3.758][3.758:810](),[3.810][3.1350:1381](),[3.1381][3.810:818](),[3.810][3.810:818](),[3.818][3.73:112]()
    /// ```
    /// ui:
    /// country: Australia
    /// index: 0
    ///
    /// time_series:
    /// data_type: u
    /// series: AUSURAMS_a
    /// time_series:
    /// data_type: i
    /// series: _
    /// line:
    /// x: 0
    /// y: 1
    /// transform: indent
    /// ```
    pub struct UISpec(Vec<UIGraphicSpec>);
    [3.475]
    [3.1382]
    impl Spec {
  • replacement in src/ui.rs at line 82
    [3.1383][3.1383:1397]()
    impl UISpec {
    [3.1383]
    [3.1397]
    /// Read in ts specification from file.
    /// ```
    /// let ts_spec = ts::Spec::from_file("ui_spec.keytree");
    /// ```
    pub fn from_file(path: &str) -> Result<Self, Error> {
    let source_spec = match fs::read_to_string(path) {
    Ok(ss) => ss,
    Err(err) => { return Err(
    failed_to_read_file(
    file!(),
    line!(),
    &err.to_string()
    ))
    },
    };
    let kt = KeyTree::parse(&source_spec).unwrap();
    kt.to_ref().try_into().map_err(|err: keytree::error::Error| {
    keytree_error(file!(), line!(), &err.to_string())
    })
    }
  • replacement in src/ui.rs at line 103
    [3.1398][3.1398:1478](),[3.1478][3.23:53](),[3.53][3.1522:1572](),[3.1522][3.1522:1572](),[3.1572][3.54:60]()
    // Convert UISpec into UIJson.
    pub (crate) fn into_json(
    &self,
    data_spec: &DataSpec,
    root_path: &str) -> Result<UIJson, Error>
    {
    [3.1398]
    [3.60]
    pub fn into_json(&self, root_path: &str) -> Result<Json, Error> {
  • replacement in src/ui.rs at line 105
    [3.61][3.1579:1875](),[3.1579][3.1579:1875]()
    let mut ui_json = UIJson::new();
    for ui_graphic_spec in &self.0 {
    let ui_graphic_json = ui_graphic_spec.into_json(
    data_spec,
    root_path,
    )?;
    ui_json.insert(ui_graphic_json);
    }
    Ok(ui_json)
    }
    }
    [3.61]
    [3.879]
    let mut json = BTreeMap::new();
  • replacement in src/ui.rs at line 107
    [3.880][3.880:926](),[3.926][3.113:146]()
    impl<'a> TryInto<UISpec> for KeyTreeRef<'a> {
    type Error = keytree::Error;
    [3.880]
    [3.1070]
    for GraphicSpec {
    country,
    index,
    seriess,
    lines,
    } in &self.0 {
  • replacement in src/ui.rs at line 114
    [3.1071][3.147:214](),[3.214][3.323:379](),[3.379][3.267:277](),[3.267][3.267:277](),[3.277][3.1227:1235](),[3.1227][3.1227:1235]()
    fn try_into(self) -> Result<UISpec, Self::Error> {
    Ok(
    UISpec(self.vec_at("ui_spec::ui_graphic")?)
    )
    }
    }
    [3.1071]
    [3.1235]
    // GraphicJson builder
    let mut graphic_json = GraphicJson {
    country: *country,
    index: *index,
    lines: Vec::new(),
    sized: None,
    };
  • replacement in src/ui.rs at line 122
    [3.1236][3.278:907](),[3.907][3.1301:1303](),[3.1301][3.1301:1303]()
    /// ```
    /// ui_graphic:
    /// country: Australia
    /// index: 0
    ///
    /// time_series:
    /// data_type: u
    /// series: AUSURAMS_a
    /// transform: ident
    /// time_series:
    /// data_type: i
    /// series: _
    /// transform: ident
    /// line:
    /// x: 0
    /// y: 1
    /// ```
    pub struct UIGraphicSpec {
    ///
    pub country: Country,
    ///
    pub title: String,
    ///
    pub index: usize,
    ///
    pub time_series: Vec<UITimeSeriesSpec>,
    ///
    pub line: Vec<UILineSpec>,
    }
    [3.1236]
    [3.1303]
    for LineSpec {
    x,
    y,
    } in lines {
    let x_rts = match seriess.get(x) {
    Some(s) => s.read_data_with_transforms(*country, root_path)?,
    None => {
    return Err(failed_to_reference_series(
    file!(),
    line!(),
    &x.to_string(),
    ))
    },
    };
  • replacement in src/ui.rs at line 137
    [3.1304][3.1876:1897]()
    impl UIGraphicSpec {
    [3.1304]
    [3.1897]
    let y_rts = match seriess.get(y) {
    Some(series_json) => series_json.read_data_with_transforms(*country, root_path)?,
    None => {
    return Err(failed_to_reference_series(
    file!(),
    line!(),
    &y.to_string(),
    ))
    },
    };
  • replacement in src/ui.rs at line 148
    [3.1898][3.1898:1943](),[3.1943][3.62:92](),[3.92][3.1987:2120](),[3.1987][3.1987:2120]()
    pub (crate) fn into_json(
    &self,
    data_spec: &DataSpec,
    root_path: &str) -> Result<UIGraphicJson, Error>
    {
    let mut v = Vec::new();
    for line_spec in &self.line {
    [3.1898]
    [3.2120]
    let rts = x_rts.zip_one_one(y_rts);
  • replacement in src/ui.rs at line 150
    [3.2121][3.2121:2661]()
    let x_time_series_spec = &self.time_series[line_spec.x];
    let y_time_series_spec = &self.time_series[line_spec.y];
    let line_json = line_spec.into_json(
    data_spec,
    x_time_series_spec,
    y_time_series_spec,
    root_path,
    ).unwrap();
    v.push(line_json);
    }
    Ok(
    UIGraphicJson {
    country: self.country,
    title: self.title.clone(),
    lines: v,
    [3.2121]
    [3.2661]
    let line_json = LineJson {
    x_series_id: x.clone(),
    y_series_id: y.clone(),
    rts: rts,
    x_transforms: seriess.get(x).unwrap().transforms.clone(),
    y_transforms: seriess.get(y).unwrap().transforms.clone(),
    };
    graphic_json.lines.push(line_json);
  • replacement in src/ui.rs at line 160
    [3.2675][3.2675:2692]()
    )
    }
    [3.2675]
    [3.2692]
    json.insert((*country, *index), graphic_json);
    }
    Ok(Json(json))
    }
  • replacement in src/ui.rs at line 166
    [3.2695][3.908:961](),[3.1304][3.908:961]()
    impl<'a> TryInto<UIGraphicSpec> for KeyTreeRef<'a> {
    [3.2695]
    [3.961]
    impl<'a> TryInto<Spec> for KeyTreeRef<'a> {
  • replacement in src/ui.rs at line 169
    [3.1380][3.995:1057](),[3.1560][3.1560:1561]()
    fn try_into(self) -> Result<UIGraphicSpec, Self::Error> {
    [3.1380]
    [3.1561]
    fn try_into(self) -> Result<Spec, Self::Error> {
  • replacement in src/ui.rs at line 171
    [3.1573][3.1126:1154](),[3.1154][3.380:719](),[3.719][3.1680:1694](),[3.1438][3.1680:1694](),[3.1680][3.1680:1694]()
    UIGraphicSpec {
    country: self.value("ui_graphic::country")?,
    index: self.value("ui_graphic::index")?,
    title: self.value("ui_graphic::title")?,
    time_series: self.vec_at("ui_graphic::time_series")?,
    line: self.vec_at("ui_graphic::line")?,
    }
    [3.1573]
    [3.1694]
    Spec(self.vec_at("ui_spec::ui_graphic")?)
  • replacement in src/ui.rs at line 176
    [3.1942][3.1942:2013](),[3.2013][3.1439:1493](),[3.1493][3.2618:2774](),[3.2618][3.2618:2774](),[3.2774][3.2696:2742](),[3.754][3.2804:2841](),[3.2742][3.2804:2841](),[3.2804][3.2804:2841](),[3.2841][3.2743:2808]()
    /// An integer reference to a series, for x and y coordinates.
    /// ```
    /// line:
    /// x: 0
    /// y: 1
    /// ```
    /// For instance in this example, x refers to the first time-series AUSURAMS_a, and y refers to the
    /// second time-series.
    pub struct UILineSpec {
    x: usize,
    y: usize,
    start_date: Option<MonthlyDate>,
    end_date: Option<MonthlyDate>,
    transform2: Transform2,
    [3.1756]
    [3.2808]
    pub struct GraphicSpec {
    pub country: Country,
    pub index: usize,
    pub seriess: BTreeMap<SeriesId, SeriesSpec>,
    pub lines: Vec<LineSpec>,
  • replacement in src/ui.rs at line 183
    [3.2811][3.2811:2829]()
    impl UILineSpec {
    [3.2811]
    [3.2829]
    impl<'a> TryInto<GraphicSpec> for KeyTreeRef<'a> {
    type Error = keytree::Error;
  • replacement in src/ui.rs at line 186
    [3.2830][3.2830:2875](),[3.2875][3.93:118](),[3.118][3.2914:3120](),[3.2914][3.2914:3120]()
    pub (crate) fn into_json(
    &self,
    data: &DataSpec,
    x: &UITimeSeriesSpec,
    y: &UITimeSeriesSpec,
    root_path: &str) -> Result<UILineJson, Error>
    {
    x.assert_data_type(DataType::U)?;
    y.assert_data_type(DataType::Inf)?;
    [3.2830]
    [3.3120]
    fn try_into(self) -> Result<GraphicSpec, Self::Error> {
  • replacement in src/ui.rs at line 188
    [3.3121][3.3121:3240](),[3.3240][3.154:224](),[3.224][3.3314:3456](),[3.3314][3.3314:3456](),[3.3456][3.225:271](),[3.271][3.3500:3538](),[3.3500][3.3500:3538]()
    let x_data = x.time_series_data(data, root_path)?;
    let y_data = y.time_series_data(data, root_path)?;
    let range = DateRange::new(&self.start_date, &self.end_date);
    let xy_data = match self.transform2 {
    Transform2::Zip => {
    let mut xy_data = x_data.zip_one_one(y_data);
    xy_data.with_range(&range.0);
    xy_data
    }
    [3.3121]
    [3.3538]
    let v: Vec<SeriesSpec> = self.vec_at("graphic::series")?;
    let mut seriess = BTreeMap::new();
    for series_spec in v {
    seriess.insert(series_spec.series_id.clone(), series_spec);
  • edit in src/ui.rs at line 193
    [3.3549][3.3549:3647](),[3.3647][3.2876:2878](),[3.2876][3.2876:2878]()
    Ok(
    UILineJson {
    data: xy_data,
    }
    )
    }
    }
  • edit in src/ui.rs at line 194
    [3.2879][3.2879:2929](),[3.2929][3.1494:1527](),[3.1527][3.2953:2954](),[3.2953][3.2953:2954](),[3.2954][3.1528:1587]()
    impl<'a> TryInto<UILineSpec> for KeyTreeRef<'a> {
    type Error = keytree::Error;
    fn try_into(self) -> Result<UILineSpec, Self::Error> {
  • replacement in src/ui.rs at line 195
    [3.3456][3.3456:3481](),[3.3481][3.3648:3965]()
    UILineSpec {
    x: self.value("line::x")?,
    y: self.value("line::y")?,
    start_date: self.opt_value("line::start_date")?,
    end_date: self.opt_value("line::end_date")?,
    transform2: self.value("line::transform2")?,
    [3.3456]
    [3.3645]
    GraphicSpec {
    country: self.value("graphic::country")?,
    index: self.value("graphic::index")?,
    seriess,
    lines: self.vec_at("graphic::line")?,
  • replacement in src/ui.rs at line 205
    [3.2007][3.4223:4224](),[3.4223][3.4223:4224](),[3.5393][3.2198:2340](),[3.2414][3.2414:2440](),[3.2440][3.4501:4555]()
    /// ```
    /// time_series:
    /// data_type: u
    /// series: AUSURAMS_a
    /// transform: ident
    /// ```
    pub struct UITimeSeriesSpec {
    data_type: DataType,
    series_id: SeriesId,
    transform1: Transform1,
    [3.4134]
    [3.4555]
    pub struct LineSpec {
    x: SeriesId,
    y: SeriesId,
  • edit in src/ui.rs at line 209
    [3.4557][3.4557:4582]()
    impl UITimeSeriesSpec {
  • replacement in src/ui.rs at line 210
    [3.4583][3.4583:4747](),[3.4747][3.200:436](),[3.436][3.4836:4905](),[3.4836][3.4836:4905](),[3.4905][3.119:149](),[3.149][3.4944:5014](),[3.4944][3.4944:5014](),[3.5014][3.437:1000](),[3.268][3.5113:5119](),[3.1000][3.5113:5119](),[3.5113][3.5113:5119](),[3.2491][3.5415:5417](),[3.5119][3.5415:5417](),[3.5415][3.5415:5417](),[3.5558][3.5558:5559](),[3.5559][3.2492:2570](),[3.2596][3.2596:2660]()
    pub (crate) fn assert_data_type(&self, data_type: DataType) -> Result<(), Error> {
    if self.data_type == data_type {
    Ok(())
    } else {
    Err(
    data_type_mismatch(
    file!(),
    line!(),
    &self.data_type.to_string(),
    &data_type.to_string()
    )
    )
    }
    }
    pub (crate) fn time_series_data(
    &self,
    data_spec: &DataSpec,
    root_path: &str) -> Result<RegularTimeSeries<1>, Error>
    {
    let series_spec = match data_spec.get_series_spec(&self.series_id) {
    Some(series_spec) => series_spec,
    None => {
    return Err(
    series_id_not_in_dataspec(
    file!(),
    line!(),
    &self.series_id.to_string()
    )
    )
    },
    };
    data_from_file(
    series_spec.country,
    series_spec.data_type,
    series_spec.series_id,
    root_path
    )
    }
    }
    /// ```
    /// time_series:
    /// data_type: u
    /// series: AUSURAMS_a
    /// ```
    impl<'a> TryInto<UITimeSeriesSpec> for KeyTreeRef<'a> {
    [3.4583]
    [3.2660]
    impl<'a> TryInto<LineSpec> for KeyTreeRef<'a> {
  • replacement in src/ui.rs at line 213
    [3.5618][3.2694:2759]()
    fn try_into(self) -> Result<UITimeSeriesSpec, Self::Error> {
    [3.5618]
    [3.6923]
    fn try_into(self) -> Result<LineSpec, Self::Error> {
  • replacement in src/ui.rs at line 215
    [3.6935][3.3477:3508](),[3.3508][3.1011:1078](),[3.1078][3.5120:5252]()
    UITimeSeriesSpec {
    data_type: self.value("time_series::data_type")?,
    series_id: self.value("time_series::series")?,
    transform1: self.value("time_series::transform1")?,
    [3.6935]
    [3.7070]
    LineSpec {
    x: self.value("line::x")?,
    y: self.value("line::y")?,
  • edit in src/ui.rs at line 222
    [3.7102][3.7102:7103](),[3.7103][3.1352:1720](),[3.1720][3.7103:7104](),[3.4027][3.7103:7104](),[3.7103][3.7103:7104](),[3.7104][3.1721:1873](),[3.1873][3.4156:4157](),[3.4156][3.4156:4157]()
    // fn parse_date(s: &str) -> Result<MonthlyDate, keytree::Error> {
    // let year = s[..=4].parse::<usize>().map_err(|err| keytree::Error(Box::new(keytree::ErrorKind::User(err.to_string()))))?;
    // let month = s[5..].parse::<usize>().map_err(|err| keytree::Error(Box::new(keytree::ErrorKind::User(err.to_string()))))?;
    // Ok(MonthlyDate::ym(year, month))
    // }
    // #[test]
    // fn test_parse_date() {
    // let s = "1999-03";
    // assert!(
    // parse_date(s),
    // MonthlyDate(1999, 3),
    // )
    // }
  • replacement in src/ts.rs at line 15
    [3.7908][2.0:87]()
    use crate::{ DataType, DateRange, MonthlyDate, SeriesId, SeriesMetaData, SeriesSpec };
    [3.7908]
    [3.1114]
    use crate::{ DataType, DateRange, MonthlyDate, SeriesId, SeriesJson, SeriesMetaData, SeriesSpec };
  • edit in src/ts.rs at line 66
    [2.121][3.93:168](),[3.130][3.93:168](),[3.321][3.93:168](),[3.168][3.321:353](),[3.321][3.321:353]()
    // Title is displayed if Some otherwise no or default title displayed.
    title_opt: Option<String>,
  • edit in src/ts.rs at line 72
    [3.415][3.574:775](),[3.775][3.415:467](),[3.415][3.415:467](),[3.467][2.122:148](),[2.148][3.467:579](),[3.467][3.467:579](),[3.4915][3.4915:4916]()
    /// A component of `Json` that is a single data series. Series are referenced by graphics through an
    /// index, so that each series can be used multiple times, without being downloaded multiple times.
    #[derive(Debug, Serialize)]
    pub struct SeriesJson {
    series_id: SeriesId,
    rts: RegularTimeSeries<1>,
    meta: Option<SeriesMetaData>,
    transforms: Vec<Transform>,
    }
  • edit in src/ts.rs at line 124
    [3.464][3.464:553]()
    let mut m_series: BTreeMap<SeriesId, (usize, SeriesJson)> = BTreeMap::new();
  • edit in src/ts.rs at line 128
    [3.1230]
    [3.131]
    let mut m_series: BTreeMap<SeriesId, (usize, SeriesJson)> = BTreeMap::new();
  • edit in src/ts.rs at line 130
    [3.199][2.149:317](),[3.199][3.1308:1309](),[2.317][3.1308:1309](),[3.1308][3.1308:1309]()
    // if m_series.contains_key(series_id) {
    // println!("Duplicate series_id");
    // panic!()
    // };
  • replacement in src/ts.rs at line 139
    [3.1571][3.1571:1629]()
    //Build graphics from graphics specification.
    [3.1571]
    [3.603]
    // Build graphics from graphics specification.
  • edit in src/ts.rs at line 145
    [3.31][3.1134:1165](),[2.352][3.1134:1165](),[3.1134][3.1134:1165]()
    title_opt,
  • edit in src/ts.rs at line 148
    [3.1317][3.1317:1523]()
    // Construct GraphicJson
    let t_opt = match title_opt {
    Some(title_opt) => Some(title_opt.clone()),
    None => None,
    };
  • replacement in src/ts.rs at line 154
    [2.572][2.572:657]()
    Some(GraphicCategory::Collated) => GraphicCategory::Collated,
    [2.572]
    [2.657]
    Some(GraphicCategory::Collation) => GraphicCategory::Collation,
  • edit in src/ts.rs at line 172
    [2.1212]
    [3.795]
    // Sets the kind of text display under each graphic.
  • replacement in src/ts.rs at line 177
    [2.1353][2.1353:1427]()
    Some(GraphicCategory::Collated) => TextSpec::Link,
    [2.1353]
    [2.1427]
    Some(GraphicCategory::Collation) => TextSpec::Link,
  • edit in src/ts.rs at line 183
    [3.480][3.797:798]()
  • edit in src/ts.rs at line 185
    [3.838][3.1577:1617](),[2.1544][3.1577:1617](),[3.1577][3.1577:1617]()
    title_opt: t_opt,
  • edit in src/ts.rs at line 188
    [3.1736][3.1630:1694]()
    // Construct indices for series in GraphicJson
  • edit in src/ts.rs at line 189
    [3.1737][3.1695:1723]()
    // We have
  • edit in src/ts.rs at line 200
    [3.1826][3.1872:1905]()
    // dbg!(ix);
  • edit in src/ts.rs at line 207
    [3.2018][3.2018:2019](),[3.2019][3.1995:2012]()
  • replacement in src/ts.rs at line 430
    [3.643][3.643:657]()
    Collated,
    [3.643]
    [3.657]
    Collation,
  • replacement in src/ts.rs at line 444
    [3.949][2.1669:1727]()
    "collation" => Ok(GraphicCategory::Collated),
    [3.949]
    [2.1727]
    "collation" => Ok(GraphicCategory::Collation),
  • replacement in src/ts.rs at line 455
    [3.1348][2.1882:1937]()
    GraphicCategory::Collated => "collation",
    [3.1348]
    [2.1937]
    GraphicCategory::Collation => "collation",
  • edit in src/ts.rs at line 476
    [2.2092][2.2092:2132]()
    pub title_opt: Option<String>,
  • edit in src/ts.rs at line 492
    [3.1656][3.3602:3669](),[2.2336][3.3602:3669](),[3.1845][3.3602:3669]()
    title_opt: self.opt_value("graphic::title")?,
  • edit in src/ts.rs at line 507
    [3.1761][3.3809:3856](),[3.7063][3.3809:3856](),[3.3856][3.2332:2378](),[3.2332][3.2332:2378](),[3.2472][3.2472:2483]()
    if let Some(title) = &self.title_opt {
    kt.push_value(1, "title", title);
    }
  • edit in src/ts.rs at line 551
    [3.4285]
  • replacement in src/main.rs at line 56
    [3.11388][3.2893:2964]()
    let ts_spec = ts::Spec::from_file("ts_spec.keytree").unwrap();
    [3.11388]
    [3.2964]
    // let ts_spec = ts::Spec::from_file("ts_spec.keytree").unwrap();
  • replacement in src/main.rs at line 60
    [3.3012][3.1278:1349]()
    ts_spec.into_json(&root_dir).unwrap().into_ts_data().unwrap();
    [3.3012]
    [3.11459]
    // ts_spec.into_json(&root_dir).unwrap().into_ts_data().unwrap();
  • edit in src/main.rs at line 73
    [3.11846]
    [3.11846]
    // Step 5
  • edit in src/main.rs at line 76
    [3.11847]
    [3.11847]
    let ui_spec = ui::Spec::from_file("ui_spec.keytree").unwrap();
    // ui_spec.into_json(&root_dir).unwrap().into_ts_data().unwrap();
  • replacement in src/lib.rs at line 173
    [3.7834][3.4667:4682]()
    // pub mod ui;
    [3.7834]
    [3.7835]
    pub mod ui;
  • replacement in src/lib.rs at line 523
    [3.4990][2.3593:3696]()
    category_opt: Some(GraphicCategory::Collated),
    title_opt: None,
    [3.4990]
    [2.3696]
    category_opt: Some(GraphicCategory::Collation),
  • edit in src/lib.rs at line 547
    [2.3808][2.3808:3850]()
    title_opt: None,
  • edit in src/lib.rs at line 771
    [3.17681][3.17681:17682](),[3.17682][3.4001:4257](),[3.4257][3.1497:1498](),[3.1497][3.1497:1498](),[3.1498][3.4258:4595]()
    // /// Return `Self` given a `series_id`.
    // pub fn from_series_id(series_id: &str, root_path: &str) -> Result<Self, Error> {
    // let sid = SeriesId::from_str(series_id).unwrap();
    // let data_spec = DataSpec::from_file(root_path)?;
    // let key = match data_spec.reverse.get(&sid) {
    // Some(key) => key,
    // None => { return Err(
    // series_id_not_in_dataspec(
    // file!(),
    // line!(),
    // &series_id.to_string()
    // )
    // )},
    // };
  • edit in src/lib.rs at line 772
    [3.1681][3.4596:4994](),[3.4994][3.6800:6801](),[3.6800][3.6800:6801]()
    // match data_spec.map.get(&key) {
    // Some(series_specs) => {
    // Ok(
    // series_specs.iter()
    // .find(|series_spec| series_spec.series_id == sid)
    // .unwrap()
    // .clone()
    // )
    // },
    // None => unreachable!(),
    // }
    // }
  • replacement in src/lib.rs at line 777
    [3.5144][2.3925:3998]()
    let rts = self.read_data_without_transform(country, root_path)?;
    [3.5144]
    [3.6855]
    let mut rts = self.read_data_without_transform(country, root_path)?;
  • replacement in src/lib.rs at line 783
    [3.6961][3.6961:6991]()
    match transform {
    [3.6961]
    [3.6991]
    rts = match transform {
  • replacement in src/lib.rs at line 1143
    [2.4154][2.4154:4238]()
    let mut transforms: Vec<Transform> = self.vec_value("series::transforms")?;
    [2.4154]
    [2.4238]
    let mut transforms: Vec<Transform> = self.vec_value("series::transform")?;
  • edit in src/lib.rs at line 1246
    [3.15544]
    [3.15544]
    }
    /// A component of `Json` that is a single data series. Series are referenced by graphics through an
    /// index, so that each series can be used multiple times, without being downloaded multiple times.
    #[derive(Debug, Serialize)]
    pub struct SeriesJson {
    series_id: SeriesId,
    rts: RegularTimeSeries<1>,
    meta: Option<SeriesMetaData>,
    transforms: Vec<Transform>,