flat 0.1.6

Project multi-dimensional data onto the **flat** textual plane.
Documentation
diff --git a/examples/iris.rs b/examples/iris.rs
index 2d894d9..3c964f5 100644
--- a/examples/iris.rs
+++ b/examples/iris.rs
@@ -2,44 +2,56 @@ use blarg::{derive::*, prelude::*, CommandLineParser, Parameter, Scalar, Switch}
 use flat::*;
 use ordered_float::OrderedFloat;
 use serde::Deserialize;
+use std::fmt::Formatter;
 
 fn main() {
-    let parameters = Parameters::blarg_parse();
-    let dataset: Vec<Flower> = serde_json::from_str(IRIS_JSON).unwrap();
+    // let parameters = Parameters::blarg_parse();
+    let json_data: Vec<FlowerJson> = serde_json::from_str(IRIS_JSON).unwrap();
+    bar_chart(true, json_data.as_slice());
+    bar_chart_breakdown(true, json_data.as_slice());
+    // let mut dataset = Dataset::builder(FlowerSchema);
+    //
+    // for flower in &json_data {
+    //     dataset.update(flower.into(), 1);
+    // }
+    //
+    // let sepal_view = SepalView { dataset: &dataset };
 
-    match parameters.widget {
-        Widget::BarChart => {
-            if parameters.breakdown {
-                bar_chart_breakdown(&parameters, dataset);
-            } else {
-                bar_chart(&parameters, dataset);
-            }
-        }
-        Widget::Histogram => {
-            if parameters.breakdown {
-                histogram_breakdown(&parameters, dataset);
-            } else {
-                histogram(&parameters, dataset);
-            }
-        }
-    }
+    // BarChart::new(&sepal_view).render(Render::default());
+
+    // match parameters.widget {
+    //     Widget::BarChart => {
+    //         if parameters.breakdown {
+    //             bar_chart_breakdown(&parameters, dataset);
+    //         } else {
+    //             bar_chart(&parameters, dataset);
+    //         }
+    //     }
+    //     Widget::Histogram => {
+    //         if parameters.breakdown {
+    //             histogram_breakdown(&parameters, dataset);
+    //         } else {
+    //             histogram(&parameters, dataset);
+    //         }
+    //     }
+    // }
 }
 
-fn bar_chart(parameters: &Parameters, dataset: Vec<Flower>) {
+fn bar_chart(verbose: bool, json_data: &[FlowerJson]) {
     let schema = Schemas::one("Species", "Petal Length");
     let mut builder = Dataset::builder(schema);
 
-    for flower in dataset {
+    for flower in json_data {
         builder.update((flower.species.clone(),), flower.petal_length);
     }
 
     let view = builder.view();
     let flat = BarChart::new(&view).render(Render {
         aggregate: Aggregate::Average,
-        show_aggregate: parameters.verbose,
+        show_aggregate: verbose,
         widget_config: {
             BarChartConfig {
-                show_aggregate: parameters.verbose,
+                show_aggregate: verbose,
                 ..BarChartConfig::default()
             }
         },
@@ -50,11 +62,11 @@ fn bar_chart(parameters: &Parameters, dataset: Vec<Flower>) {
     println!("{flat}");
 }
 
-fn bar_chart_breakdown(parameters: &Parameters, dataset: Vec<Flower>) {
-    let schema = Schemas::two("Attribute", "Species", "moot");
+fn bar_chart_breakdown(verbose: bool, json_data: &[FlowerJson]) {
+    let schema = Schemas::two("Attribute", "Species", "Value");
     let mut builder = Dataset::builder(schema);
 
-    for flower in dataset {
+    for flower in json_data {
         builder.update(
             ("sepal_length", flower.species.clone()),
             flower.sepal_length,
@@ -67,13 +79,13 @@ fn bar_chart_breakdown(parameters: &Parameters, dataset: Vec<Flower>) {
         builder.update(("petal_width", flower.species.clone()), flower.petal_width);
     }
 
-    let view = builder.view_breakdown2();
+    let view = builder.view();
     let flat = BarChart::new(&view).render(Render {
         aggregate: Aggregate::Average,
-        show_aggregate: parameters.verbose,
+        show_aggregate: verbose,
         widget_config: {
             BarChartConfig {
-                show_aggregate: parameters.verbose,
+                show_aggregate: verbose,
                 ..BarChartConfig::default()
             }
         },
@@ -82,45 +94,61 @@ fn bar_chart_breakdown(parameters: &Parameters, dataset: Vec<Flower>) {
     println!("Shows the relative attribute values of flowers in the dataset, broken down by their species.");
     println!();
     println!("{flat}");
-}
-
-fn histogram(parameters: &Parameters, dataset: Vec<Flower>) {
-    let schema = Schemas::one("Petal Length", "Flower Count");
-    let mut builder = Dataset::builder(schema);
-
-    for flower in dataset {
-        builder.update((flower.petal_length,), 1);
-    }
-
-    let view = builder.view();
-    let flat = Histogram::new(&view, 10).render(Render {
-        aggregate: Aggregate::Sum,
-        show_aggregate: parameters.verbose,
-        ..Render::default()
-    });
-    println!("Shows the relative count of flowers in the dataset, organized into bins based off their petal length.");
-    println!();
-    println!("{flat}");
-}
-
-fn histogram_breakdown(parameters: &Parameters, dataset: Vec<Flower>) {
-    let schema = Schemas::two("Petal Length", "Petal Widths", "moot");
-    let mut builder = Dataset::builder(schema);
-
-    for flower in dataset {
-        builder.update((flower.petal_length, OrderedFloat(flower.petal_width)), 1);
-    }
 
     let view = builder.view_breakdown2();
-    let flat = Histogram::new(&view, 10).render(Render {
-        aggregate: Aggregate::Sum,
-        show_aggregate: parameters.verbose,
+    let flat = BarChart::new(&view).render(Render {
+        aggregate: Aggregate::Average,
+        show_aggregate: verbose,
+        widget_config: {
+            BarChartConfig {
+                show_aggregate: verbose,
+                ..BarChartConfig::default()
+            }
+        },
         ..Render::default()
     });
-    println!("Shows the relative count of flowers in the dataset, broken down by their petal widths, organized into bins based off their petal length.");
+    println!("Shows the relative attribute values of flowers in the dataset, broken down by their species.");
     println!();
     println!("{flat}");
 }
+//
+// fn histogram(parameters: &Parameters, dataset: Vec<Flower>) {
+//     let schema = Schemas::one("Petal Length", "Flower Count");
+//     let mut builder = Dataset::builder(schema);
+//
+//     for flower in dataset {
+//         builder.update((flower.petal_length,), 1);
+//     }
+//
+//     let view = builder.view();
+//     let flat = Histogram::new(&view, 10).render(Render {
+//         aggregate: Aggregate::Sum,
+//         show_aggregate: parameters.verbose,
+//         ..Render::default()
+//     });
+//     println!("Shows the relative count of flowers in the dataset, organized into bins based off their petal length.");
+//     println!();
+//     println!("{flat}");
+// }
+//
+// fn histogram_breakdown(parameters: &Parameters, dataset: Vec<Flower>) {
+//     let schema = Schemas::two("Petal Length", "Petal Widths", "moot");
+//     let mut builder = Dataset::builder(schema);
+//
+//     for flower in dataset {
+//         builder.update((flower.petal_length, OrderedFloat(flower.petal_width)), 1);
+//     }
+//
+//     let view = builder.view_breakdown2();
+//     let flat = Histogram::new(&view, 10).render(Render {
+//         aggregate: Aggregate::Sum,
+//         show_aggregate: parameters.verbose,
+//         ..Render::default()
+//     });
+//     println!("Shows the relative count of flowers in the dataset, broken down by their petal widths, organized into bins based off their petal length.");
+//     println!();
+//     println!("{flat}");
+// }
 
 #[derive(BlargChoices, PartialEq)]
 enum Widget {
@@ -166,13 +194,136 @@ struct Parameters {
     breakdown: bool,
 }
 
-#[derive(Debug, Deserialize)]
+// #[derive(Debug, Clone)]
+#[derive(Debug, Clone)]
+struct SepalLength(f64);
+
+impl std::fmt::Display for SepalLength {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", minimal_precision_string(self.0))
+    }
+}
+
+#[derive(Debug, Clone)]
+struct SepalWidth(f64);
+
+impl std::fmt::Display for SepalWidth {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", minimal_precision_string(self.0))
+    }
+}
+
+#[derive(Debug, Clone)]
+struct PetalLength(f64);
+
+impl std::fmt::Display for PetalLength {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", minimal_precision_string(self.0))
+    }
+}
+
+#[derive(Debug, Clone)]
+struct PetalWidth(f64);
+
+impl std::fmt::Display for PetalWidth {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}", minimal_precision_string(self.0))
+    }
+}
+
+#[derive(Debug, Clone)]
+// #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 struct Flower {
+    species: String,
+    sepal_length: SepalLength,
+    sepal_width: SepalWidth,
+    petal_length: PetalLength,
+    petal_width: PetalWidth,
+}
+
+#[derive(Debug, Deserialize)]
+struct FlowerJson {
+    species: String,
     sepal_length: f64,
     sepal_width: f64,
     petal_length: f64,
     petal_width: f64,
-    species: String,
+}
+
+impl From<&FlowerJson> for Flower {
+    fn from(value: &FlowerJson) -> Self {
+        Self {
+            species: value.species.clone(),
+            sepal_length: SepalLength(value.sepal_length),
+            sepal_width: SepalWidth(value.sepal_width),
+            petal_length: PetalLength(value.petal_length),
+            petal_width: PetalWidth(value.petal_width),
+        }
+    }
+}
+
+impl Dimensions for Flower {
+    fn as_strings(&self) -> Vec<String> {
+        vec![
+            self.species.clone(),
+            self.sepal_length.0.to_string(),
+            self.sepal_width.0.to_string(),
+            self.petal_length.0.to_string(),
+            self.petal_width.0.to_string(),
+        ]
+    }
+
+    fn len(&self) -> usize {
+        5
+    }
+}
+
+struct FlowerSchema;
+
+impl Schema for FlowerSchema {
+    type Dimensions = Flower;
+}
+
+struct SepalView<'a> {
+    dataset: &'a Dataset<FlowerSchema>,
+}
+
+impl<'a> View<FlowerSchema> for SepalView<'a> {
+    type Dimensions = Flower;
+    type PrimaryDimension = (SepalLength, SepalWidth);
+    type BreakdownDimension = Nothing;
+    type SortDimensions = (SepalLength, SepalWidth);
+
+    fn dataset(&self) -> &Dataset<FlowerSchema> {
+        &self.dataset
+    }
+
+    fn primary_dim(&self, dims: &<FlowerSchema as Schema>::Dimensions) -> Self::PrimaryDimension {
+        (dims.sepal_length.clone(), dims.sepal_width.clone())
+    }
+
+    fn breakdown_dim(
+        &self,
+        dims: &<FlowerSchema as Schema>::Dimensions,
+    ) -> Self::BreakdownDimension {
+        Nothing
+    }
+
+    fn sort_dims(&self, dims: &<FlowerSchema as Schema>::Dimensions) -> Self::SortDimensions {
+        (dims.sepal_length.clone(), dims.sepal_width.clone())
+    }
+
+    fn headers(&self) -> Vec<String> {
+        vec!["Sepal Length".to_string(), "Sepal Width".to_string()]
+    }
+
+    fn data_header(&self) -> String {
+        "abc".to_string()
+    }
+
+    fn is_breakdown(&self) -> bool {
+        false
+    }
 }
 
 const IRIS_JSON: &str = r#"[