use crate::sketchbook::ids::{DatasetId, ObservationId, VarId};
use crate::sketchbook::observations::{Dataset, DatasetIterator, Observation, ObservationManager};
use std::collections::{HashMap, HashSet};
use std::str::FromStr;
impl ObservationManager {
pub fn new_empty() -> ObservationManager {
ObservationManager {
datasets: HashMap::new(),
}
}
pub fn from_datasets(datasets: Vec<(&str, Dataset)>) -> Result<ObservationManager, String> {
let mut manager = ObservationManager::new_empty();
let prop_id_set = datasets.iter().map(|pair| pair.0).collect::<HashSet<_>>();
if prop_id_set.len() != datasets.len() {
return Err(format!("Datasets {:?} contain duplicate IDs.", datasets));
}
for (id, dataset) in datasets {
let dataset_id = DatasetId::new(id)?;
manager.datasets.insert(dataset_id, dataset);
}
Ok(manager)
}
}
impl ObservationManager {
pub fn add_dataset(&mut self, id: DatasetId, dataset: Dataset) -> Result<(), String> {
self.assert_no_dataset(&id)?;
self.datasets.insert(id, dataset);
Ok(())
}
pub fn add_dataset_by_str(&mut self, id: &str, dataset: Dataset) -> Result<(), String> {
let dataset_id = DatasetId::new(id)?;
self.add_dataset(dataset_id, dataset)
}
pub fn add_multiple_datasets(
&mut self,
id_name_pairs: Vec<(&str, Dataset)>,
) -> Result<(), String> {
for (id, _) in &id_name_pairs {
let dataset_id = DatasetId::new(id)?;
self.assert_no_dataset(&dataset_id)?;
}
for (id, name) in id_name_pairs {
self.add_dataset_by_str(id, name)?;
}
Ok(())
}
pub fn swap_dataset_content(
&mut self,
id: &DatasetId,
new_content: Dataset,
) -> Result<(), String> {
self.assert_valid_dataset(id)?;
self.datasets.insert(id.clone(), new_content);
Ok(())
}
pub fn swap_dataset_content_by_str(
&mut self,
id: &str,
new_content: Dataset,
) -> Result<(), String> {
let dataset_id = DatasetId::new(id)?;
self.swap_dataset_content(&dataset_id, new_content)
}
pub fn set_dataset_name(&mut self, id: &DatasetId, name: &str) -> Result<(), String> {
self.assert_valid_dataset(id)?;
let dataset = self.datasets.get_mut(id).unwrap();
dataset.set_name(name)?;
Ok(())
}
pub fn set_dataset_name_by_str(&mut self, id: &str, name: &str) -> Result<(), String> {
let dataset_id = DatasetId::new(id)?;
self.set_dataset_name(&dataset_id, name)
}
pub fn set_dataset_annot(&mut self, id: &DatasetId, annot: &str) -> Result<(), String> {
self.assert_valid_dataset(id)?;
let dataset = self.datasets.get_mut(id).unwrap();
dataset.set_annotation(annot);
Ok(())
}
pub fn set_dataset_annot_by_str(&mut self, id: &str, annot: &str) -> Result<(), String> {
let dataset_id = DatasetId::new(id)?;
self.set_dataset_annot(&dataset_id, annot)
}
pub fn set_dataset_id(
&mut self,
original_id: &DatasetId,
new_id: DatasetId,
) -> Result<(), String> {
self.assert_valid_dataset(original_id)?;
self.assert_no_dataset(&new_id)?;
if let Some(dataset) = self.datasets.remove(original_id) {
self.datasets.insert(new_id.clone(), dataset);
} else {
panic!("Error when modifying dataset's id in the dataset map.");
}
Ok(())
}
pub fn set_dataset_id_by_str(&mut self, original_id: &str, new_id: &str) -> Result<(), String> {
let original_id = DatasetId::new(original_id)?;
let new_id = DatasetId::new(new_id)?;
self.set_dataset_id(&original_id, new_id)
}
pub fn set_var_id(
&mut self,
dataset_id: &DatasetId,
original_id: &VarId,
new_id: VarId,
) -> Result<(), String> {
self.assert_valid_dataset(dataset_id)?;
self.datasets
.get_mut(dataset_id)
.unwrap()
.set_var_id(original_id, new_id)
}
pub fn set_var_id_by_str(
&mut self,
dataset_id: &str,
original_id: &str,
new_id: &str,
) -> Result<(), String> {
let dataset_id = DatasetId::new(dataset_id)?;
let original_id = VarId::new(original_id)?;
let new_id = VarId::new(new_id)?;
self.set_var_id(&dataset_id, &original_id, new_id)
}
pub fn set_all_variables(
&mut self,
dataset_id: &DatasetId,
new_variables_list: Vec<VarId>,
) -> Result<(), String> {
self.assert_valid_dataset(dataset_id)?;
self.datasets
.get_mut(dataset_id)
.unwrap()
.set_all_variables(new_variables_list)
}
pub fn set_all_variables_by_str(
&mut self,
dataset_id: &str,
new_variables_list: Vec<&str>,
) -> Result<(), String> {
let dataset_id = DatasetId::new(dataset_id)?;
self.assert_valid_dataset(&dataset_id)?;
self.datasets
.get_mut(&dataset_id)
.unwrap()
.set_all_variables_by_str(new_variables_list)
}
pub fn remove_var(&mut self, dataset_id: &DatasetId, var_id: &VarId) -> Result<(), String> {
self.assert_valid_dataset(dataset_id)?;
self.datasets
.get_mut(dataset_id)
.unwrap()
.remove_var(var_id)
}
pub fn remove_var_by_str(&mut self, dataset_id: &str, id: &str) -> Result<(), String> {
let dataset_id = DatasetId::new(dataset_id)?;
let var_id = VarId::new(id)?;
self.remove_var(&dataset_id, &var_id)
}
pub fn add_var(&mut self, dataset_id: &DatasetId, var_id: VarId) -> Result<(), String> {
self.assert_valid_dataset(dataset_id)?;
let new_var_idx = self.get_dataset(dataset_id)?.num_variables();
self.datasets
.get_mut(dataset_id)
.unwrap()
.add_var_default(var_id, new_var_idx)
}
pub fn add_var_by_str(&mut self, dataset_id: &str, id: &str) -> Result<(), String> {
let dataset_id = DatasetId::new(dataset_id)?;
let var_id = VarId::new(id)?;
self.add_var(&dataset_id, var_id)
}
pub fn remove_dataset(&mut self, id: &DatasetId) -> Result<(), String> {
self.assert_valid_dataset(id)?;
if self.datasets.remove(id).is_none() {
panic!("Error when removing dataset {id} from the dataset map.")
}
Ok(())
}
pub fn remove_dataset_by_str(&mut self, id: &str) -> Result<(), String> {
let dataset_id = DatasetId::new(id)?;
self.remove_dataset(&dataset_id)
}
}
impl ObservationManager {
pub fn num_datasets(&self) -> usize {
self.datasets.len()
}
pub fn is_valid_dataset_id(&self, id: &DatasetId) -> bool {
self.datasets.contains_key(id)
}
pub fn get_dataset_id(&self, id: &str) -> Result<DatasetId, String> {
let dataset_id = DatasetId::from_str(id)?;
if self.is_valid_dataset_id(&dataset_id) {
return Ok(dataset_id);
}
Err(format!("Dataset with ID {id} does not exist."))
}
pub fn get_dataset(&self, id: &DatasetId) -> Result<&Dataset, String> {
let dataset = self
.datasets
.get(id)
.ok_or(format!("Dataset with ID {id} does not exist."))?;
Ok(dataset)
}
pub fn get_dataset_by_str(&self, id: &str) -> Result<&Dataset, String> {
let dataset_id = DatasetId::new(id)?;
self.get_dataset(&dataset_id)
}
pub fn get_obs_id(&self, dataset_id: &str, obs_id: &str) -> Result<ObservationId, String> {
let dataset = self.get_dataset_by_str(dataset_id)?;
dataset.get_obs_id_by_str(obs_id)
}
pub fn get_obs(
&self,
dataset_id: &DatasetId,
obs_id: &ObservationId,
) -> Result<&Observation, String> {
let dataset = self.get_dataset(dataset_id)?;
dataset.get_obs(obs_id)
}
pub fn get_obs_by_str(&self, dataset_id: &str, obs_id: &str) -> Result<&Observation, String> {
let dataset_id = DatasetId::new(dataset_id)?;
let obs_id = ObservationId::new(obs_id)?;
self.get_obs(&dataset_id, &obs_id)
}
pub fn datasets(&self) -> DatasetIterator {
self.datasets.iter()
}
fn assert_no_dataset(&self, id: &DatasetId) -> Result<(), String> {
if self.is_valid_dataset_id(id) {
Err(format!("Dataset with id {id} already exists."))
} else {
Ok(())
}
}
fn assert_valid_dataset(&self, id: &DatasetId) -> Result<(), String> {
if self.is_valid_dataset_id(id) {
Ok(())
} else {
Err(format!("Dataset with id {id} does not exist."))
}
}
}
#[cfg(test)]
mod tests {
use crate::sketchbook::observations::{Dataset, Observation, ObservationManager};
#[test]
fn test_new_manager() {
let manager = ObservationManager::new_empty();
assert_eq!(manager.num_datasets(), 0);
let d1 = Dataset::new("d1", vec![], vec!["a", "b"]).unwrap();
let d2 = Dataset::new("d2", vec![], vec!["a", "c"]).unwrap();
let dataset_list = vec![("d1", d1.clone()), ("d2", d2.clone())];
let manager = ObservationManager::from_datasets(dataset_list).unwrap();
assert_eq!(manager.num_datasets(), 2);
let dataset_list = vec![("d", d1.clone()), ("d", d2.clone())];
assert!(ObservationManager::from_datasets(dataset_list).is_err());
}
#[test]
fn test_manipulate_datasets() {
let o1 = Observation::try_from_str("*", "o").unwrap();
let o2 = Observation::try_from_str("0", "p").unwrap();
let d1 = Dataset::new("d1", vec![o1, o2], vec!["a"]).unwrap();
let d2 = Dataset::new("d2", vec![], vec!["a", "c"]).unwrap();
let dataset_list = vec![("d1", d1.clone()), ("d2", d2.clone())];
let mut manager = ObservationManager::from_datasets(dataset_list).unwrap();
assert_eq!(manager.num_datasets(), 2);
let d3 = Dataset::new("d3", vec![], vec!["a", "c"]).unwrap();
manager.add_dataset_by_str("d3", d3.clone()).unwrap();
assert_eq!(manager.num_datasets(), 3);
let d3 = Dataset::new("d3", vec![], vec!["a", "c"]).unwrap();
assert!(manager.add_multiple_datasets(vec![("d3", d3)]).is_err());
assert_eq!(manager.num_datasets(), 3);
manager.remove_dataset_by_str("d2").unwrap();
assert_eq!(manager.num_datasets(), 2);
assert!(manager.remove_dataset_by_str("d2").is_err());
assert_eq!(manager.num_datasets(), 2);
}
#[test]
fn test_edit_dataset() {
let o1 = Observation::try_from_str("*1", "o").unwrap();
let o2 = Observation::try_from_str("00", "p").unwrap();
let d1 = Dataset::new("d1", vec![o1, o2], vec!["a", "b"]).unwrap();
let dataset_list = vec![("dataset1", d1.clone())];
let mut manager = ObservationManager::from_datasets(dataset_list).unwrap();
manager.set_dataset_id_by_str("dataset1", "d1").unwrap();
assert!(manager.get_dataset_id("dataset1").is_err());
assert!(manager.get_dataset_id("d1").is_ok());
let new_dataset = Dataset::new("d1", vec![], vec!["a", "b"]).unwrap();
manager
.swap_dataset_content_by_str("d1", new_dataset.clone())
.unwrap();
let d1 = manager.get_dataset_id("d1").unwrap();
assert_eq!(manager.get_dataset(&d1).unwrap(), &new_dataset);
}
}