YAE43L6AF2HPQYJZDQGFYGFEV7722SUMAXXMP2ZQZMPE7VC6EWKAC PK7JY27R55PZON4SPFLJBX66IAE47SXBRAGDHXM4SN6TKZXO5LMAC SPSFTMLRZE2R4EBAAQKWBUZDRYZ36S2VFTBIJRE6XS7JMKELV4AQC GQVS55HIQLU7KPJNRMF57QUM4EATSWFQRCS7ZEJMJPUXFX2NHSYAC TTR5IFSG25VNBQ2F2FNOLUMTEIHVBHFOEXYB2ZWEHWOURUV4GJMQC SAHJYVNBUBBIUBI4ZMAXK4QJFOT54M5UA3W2HQMTNDSP3GGCRX7QC 2CCG6KUP6VL2Q7WQKLVNIPPGZWHSWIOWETRCS3APZTV4WSF5GLWAC XI5ALEH6NPTQWB6O62QV62EP4H3K7WSNTHCOGT3LZIIU6I2YDGIQC 4QOTH75I2VINLY52J75OR3E3B5CN5ITHJGOAKQYXI6PH3XLJ6DBQC XPXYFEZMZJSF2GOFG5HTCMLVHINNVRYIVWV7KJ6A7A3PG3CM2TGAC PQKGZNQGSRWMV3D6AUUBH3JUICKXXKDV4OLLDUM3YP5ESORBYKLAC 5B2HBV3JTNBNJYEJ4BXFQDEP2D552SBJFPY6STKSK7SPFZYSTCFAC BB2T6X3XK3Y4JFOMBGKTFVL6BZ5NOGBTPSCK4ADRSZQLQKQHESLAC EHEK63WARL6PGYZMCSOH53JXOYPHNGWZO4QP5RKODPIQJ53IWDDQC E2T2A74YPYLDPT2FCBLRJSJTDND2D5EDDRSXJZCUOQVEEIVCM2MAC TSY4YBBZ4AEW2JTEI4AS5FGTTUZR5WE3TENDHVIOWWY6V2DRT7ZQC GUXZCEWWPBCHXO26JVWZ74CTSDFDDO775YR7FKY7UGVZCA7GCSYAC 2SABVMY3A2RZDF3KJXZSMJ2UQ4Q5EW422G4DVBJRKK26S2ESGVQAC 4MG5JFXTKAE3SOVKGGNKEUTNCKOWEBHTGKVZHJWLWE3PTZTQKHPAC UUD3CJZLSTAVLMIXIWE4CHN5HQSFM6K3DCPWECJMKGXDOROK4G4AC DataSpec,DataType,DateRange,data_from_file,MonthlyDate,
// DataSpec,DataType,// DateRange,// data_from_file,// MonthlyDate,
// --- 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>);
pub struct UIData(pub BTreeMap<(Country, usize), String>);
/// 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;
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);
/// A UI plot. `UIGraphicJson` can be serialized to JSON.pub struct UIGraphicJson {country: Country,title: String,lines: Vec<UILineJson>,
#[derive(Debug, Serialize)]pub struct GraphicJson {country: Country,index: usize,lines: Vec<LineJson>,sized: Option<FixedScale>,
/// A line in a UI plot. `UILineJson` can be serialized to JSON.pub struct UILineJson {data: RegularTimeSeries<2>,
#[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>,
/// ```/// 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>);
impl Spec {
impl UISpec {
/// 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())})}
// Convert UISpec into UIJson.pub (crate) fn into_json(&self,data_spec: &DataSpec,root_path: &str) -> Result<UIJson, Error>{
pub fn into_json(&self, root_path: &str) -> Result<Json, Error> {
fn try_into(self) -> Result<UISpec, Self::Error> {Ok(UISpec(self.vec_at("ui_spec::ui_graphic")?))}}
// GraphicJson builderlet mut graphic_json = GraphicJson {country: *country,index: *index,lines: Vec::new(),sized: None,};
/// ```/// 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>,}
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(),))},};
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 {
let rts = x_rts.zip_one_one(y_rts);
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,
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);
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")?,}
Spec(self.vec_at("ui_spec::ui_graphic")?)
/// 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,
pub struct GraphicSpec {pub country: Country,pub index: usize,pub seriess: BTreeMap<SeriesId, SeriesSpec>,pub lines: Vec<LineSpec>,
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)?;
fn try_into(self) -> Result<GraphicSpec, Self::Error> {
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}
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);
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")?,
GraphicSpec {country: self.value("graphic::country")?,index: self.value("graphic::index")?,seriess,lines: self.vec_at("graphic::line")?,
/// ```/// time_series:/// data_type: u/// series: AUSURAMS_a/// transform: ident/// ```pub struct UITimeSeriesSpec {data_type: DataType,series_id: SeriesId,transform1: Transform1,
pub struct LineSpec {x: SeriesId,y: SeriesId,
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> {
impl<'a> TryInto<LineSpec> for KeyTreeRef<'a> {
UITimeSeriesSpec {data_type: self.value("time_series::data_type")?,series_id: self.value("time_series::series")?,transform1: self.value("time_series::transform1")?,
LineSpec {x: self.value("line::x")?,y: self.value("line::y")?,
// 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),// )// }
/// 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>,}
// /// 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()// )// )},// };
// 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!(),// }// }
}/// 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>,