Skip to content

Commit 6dd1bf5

Browse files
Merge pull request #28 from EmmanuelDodoo/feature/numeric_scale
Feature/numeric scale
2 parents b04fcb9 + a643c46 commit 6dd1bf5

File tree

6 files changed

+872
-485
lines changed

6 files changed

+872
-485
lines changed

src/models/bar.rs

Lines changed: 44 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,22 @@
1-
use std::{
2-
collections::HashSet,
3-
fmt::{self, Debug},
4-
hash::Hash,
5-
};
1+
use std::fmt::{self, Debug};
62

73
use super::{Point, Scale};
8-
use crate::repr::Data;
94

105
#[derive(Clone, Debug, PartialEq)]
11-
pub struct Bar<X = Data, Y = Data> {
6+
pub struct Bar {
127
pub label: Option<String>,
13-
pub point: Point<X, Y>,
8+
pub point: Point,
149
}
1510

16-
impl<X, Y> Bar<X, Y> {
17-
pub fn new(label: impl Into<String>, point: impl Into<Point<X, Y>>) -> Self {
11+
impl Bar {
12+
pub fn new(label: impl Into<String>, point: impl Into<Point>) -> Self {
1813
Self {
1914
point: point.into(),
2015
label: Some(label.into()),
2116
}
2217
}
2318

24-
pub fn from_point(point: impl Into<Point<X, Y>>) -> Self {
19+
pub fn from_point(point: impl Into<Point>) -> Self {
2520
Self {
2621
point: point.into(),
2722
label: None,
@@ -35,36 +30,19 @@ impl<X, Y> Bar<X, Y> {
3530
}
3631

3732
#[derive(Clone, Debug, PartialEq)]
38-
pub struct BarChart<X = Data, Y = Data>
39-
where
40-
X: Clone + Debug,
41-
Y: Clone + Debug,
42-
{
43-
pub bars: Vec<Bar<X, Y>>,
33+
pub struct BarChart {
34+
pub bars: Vec<Bar>,
4435
pub x_label: Option<String>,
4536
pub y_label: Option<String>,
46-
pub x_scale: Scale<X>,
47-
pub y_scale: Scale<Y>,
37+
pub x_scale: Scale,
38+
pub y_scale: Scale,
4839
}
4940

5041
#[allow(dead_code)]
51-
impl<X, Y> BarChart<X, Y>
52-
where
53-
X: Eq + Clone + Hash + PartialOrd + ToString + Debug,
54-
Y: Eq + Clone + Hash + PartialOrd + ToString + Debug,
55-
{
56-
pub fn new(
57-
bars: Vec<Bar<X, Y>>,
58-
x_scale: Scale<X>,
59-
y_scale: Scale<Y>,
60-
) -> Result<Self, BarChartError> {
61-
match &x_scale {
62-
Scale::List(scale) => Self::assert_list_scales_x(scale, &bars)?,
63-
};
64-
65-
match &y_scale {
66-
Scale::List(scale) => Self::assert_list_scales_y(scale, &bars)?,
67-
};
42+
impl BarChart {
43+
pub fn new(bars: Vec<Bar>, x_scale: Scale, y_scale: Scale) -> Result<Self, BarChartError> {
44+
Self::assert_x_scale(&x_scale, &bars)?;
45+
Self::assert_y_scale(&y_scale, &bars)?;
6846

6947
Ok(Self {
7048
x_scale,
@@ -75,64 +53,24 @@ where
7553
})
7654
}
7755

78-
fn assert_list_scales_y(lst: &[Y], bars: &[Bar<X, Y>]) -> Result<(), BarChartError> {
79-
// Duplicate check and removal
80-
let mut lst: Vec<Y> = lst.to_vec();
81-
let set: HashSet<Y> = lst.drain(..).collect();
82-
83-
// Check if all points are on scale.
84-
let mut invalid: Option<Y> = None;
85-
let valid = bars.iter().fold(true, |acc, curr| {
86-
if !acc {
87-
return acc;
56+
fn assert_x_scale(scale: &Scale, bars: &[Bar]) -> Result<(), BarChartError> {
57+
for x in bars.iter().map(|bar| &bar.point.x) {
58+
if !scale.contains(x) {
59+
return Err(BarChartError::OutOfRange("X".into(), x.to_string()));
8860
}
89-
90-
if !set.contains(&curr.point.y) {
91-
invalid = Some(curr.point.y.clone());
92-
false
93-
} else {
94-
true
95-
}
96-
});
97-
98-
if valid {
99-
Ok(())
100-
} else {
101-
Err(BarChartError::OutOfRange(
102-
"Y".into(),
103-
invalid.unwrap().to_string(),
104-
))
10561
}
106-
}
107-
108-
fn assert_list_scales_x(lst: &[X], bars: &[Bar<X, Y>]) -> Result<(), BarChartError> {
109-
// Duplicate check and removal
110-
let mut lst: Vec<X> = lst.to_vec();
111-
let set: HashSet<X> = lst.drain(..).collect();
11262

113-
let mut invalid: Option<X> = None;
114-
115-
let valid = bars.iter().fold(true, |acc, curr| {
116-
if !acc {
117-
return acc;
118-
}
63+
Ok(())
64+
}
11965

120-
if !set.contains(&curr.point.x) {
121-
invalid = Some(curr.point.x.clone());
122-
false
123-
} else {
124-
true
66+
fn assert_y_scale(scale: &Scale, bars: &[Bar]) -> Result<(), BarChartError> {
67+
for y in bars.iter().map(|bar| &bar.point.y) {
68+
if !scale.contains(y) {
69+
return Err(BarChartError::OutOfRange("Y".into(), y.to_string()));
12570
}
126-
});
127-
128-
if valid {
129-
Ok(())
130-
} else {
131-
Err(BarChartError::OutOfRange(
132-
"X".into(),
133-
invalid.unwrap().to_string(),
134-
))
13571
}
72+
73+
Ok(())
13674
}
13775

13876
pub fn x_label(mut self, label: impl Into<String>) -> Self {
@@ -169,49 +107,56 @@ impl std::error::Error for BarChartError {}
169107

170108
#[cfg(test)]
171109
mod barchart_tests {
110+
use super::super::ScaleKind;
172111
use super::*;
112+
use crate::repr::Data;
173113

174-
fn create_barchart<'a>() -> BarChart<usize, &'a str> {
114+
fn create_barchart() -> BarChart {
175115
let p1 = vec!["one", "two", "three", "four", "five"];
176116
let p2 = [1, 2, 3, 4, 5];
177117

178118
let bars = p2
179119
.into_iter()
180120
.zip(p1.into_iter())
181-
.map(|point| Bar::from_point(point))
121+
.map(|point| Bar::from_point((Data::Integer(point.0), Data::Text(point.1.to_string()))))
182122
.collect();
183123

184-
let x_scale: Scale<usize> = {
124+
let x_scale = {
185125
let rng = 0..60;
186126

187-
Scale::List(rng.collect())
127+
Scale::new(rng, ScaleKind::Integer)
128+
};
129+
let y_scale = {
130+
let values = vec!["one", "two", "three", "four", "five"];
131+
132+
Scale::new(values, ScaleKind::Text)
188133
};
189-
let y_scale: Scale<&str> = Scale::List(vec!["one", "two", "three", "four", "five"]);
190134

191135
match BarChart::new(bars, x_scale, y_scale) {
192136
Ok(bar) => bar.x_label("Number").y_label("Language"),
193137
Err(e) => panic!("{}", e),
194138
}
195139
}
196140

197-
fn out_of_range() -> Result<BarChart<isize, isize>, BarChartError> {
141+
fn out_of_range() -> Result<BarChart, BarChartError> {
198142
let xs = [1, 5, 6, 11, 15];
199143
let ys = [4, 5, 6, 7, 8];
200144

201145
let bars = xs
202146
.into_iter()
203147
.zip(ys.into_iter())
204-
.map(|point| Bar::from_point(point))
148+
.map(|point| Bar::from_point((Data::Integer(point.0), Data::Integer(point.1))))
205149
.collect();
206150

207-
let x_scale: Scale<isize> = {
151+
let x_scale = {
208152
let rng = -5..11;
209153

210-
Scale::List(rng.collect())
154+
Scale::new(rng, ScaleKind::Integer)
211155
};
212-
let y_scale: Scale<isize> = {
156+
let y_scale = {
213157
let rng = 2..10;
214-
Scale::List(rng.collect())
158+
159+
Scale::new(rng, ScaleKind::Integer)
215160
};
216161

217162
BarChart::new(bars, x_scale, y_scale)

0 commit comments

Comments
 (0)