#![allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum StudioElement {
Floor,
Wall,
Ceiling,
Prop,
}
impl StudioElement {
#[must_use]
pub fn is_physical(&self) -> bool {
matches!(self, Self::Floor | Self::Wall | Self::Ceiling)
}
}
#[derive(Debug, Clone)]
pub struct PlacedElement {
pub element: StudioElement,
pub name: String,
pub position: Option<(f32, f32, f32)>,
}
impl PlacedElement {
#[must_use]
pub fn new(element: StudioElement, name: impl Into<String>) -> Self {
Self {
element,
name: name.into(),
position: None,
}
}
#[must_use]
pub fn at(mut self, x: f32, y: f32, z: f32) -> Self {
self.position = Some((x, y, z));
self
}
}
#[derive(Debug, Default)]
pub struct VirtualStudio {
elements: Vec<PlacedElement>,
tracking_enabled: bool,
}
impl VirtualStudio {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with_tracking(tracking_enabled: bool) -> Self {
Self {
elements: Vec::new(),
tracking_enabled,
}
}
pub fn add_element(&mut self, element: PlacedElement) {
self.elements.push(element);
}
#[must_use]
pub fn element_count(&self) -> usize {
self.elements.len()
}
#[must_use]
pub fn has_tracking(&self) -> bool {
self.tracking_enabled
}
pub fn set_tracking(&mut self, enabled: bool) {
self.tracking_enabled = enabled;
}
#[must_use]
pub fn elements(&self) -> &[PlacedElement] {
&self.elements
}
#[must_use]
pub fn elements_of_type(&self, element_type: StudioElement) -> Vec<&PlacedElement> {
self.elements
.iter()
.filter(|e| e.element == element_type)
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_floor_is_physical() {
assert!(StudioElement::Floor.is_physical());
}
#[test]
fn test_wall_is_physical() {
assert!(StudioElement::Wall.is_physical());
}
#[test]
fn test_ceiling_is_physical() {
assert!(StudioElement::Ceiling.is_physical());
}
#[test]
fn test_prop_is_not_physical() {
assert!(!StudioElement::Prop.is_physical());
}
#[test]
fn test_placed_element_no_position() {
let el = PlacedElement::new(StudioElement::Floor, "Main floor");
assert!(el.position.is_none());
assert_eq!(el.name, "Main floor");
}
#[test]
fn test_placed_element_with_position() {
let el = PlacedElement::new(StudioElement::Wall, "Back wall").at(0.0, 2.0, -5.0);
assert_eq!(el.position, Some((0.0, 2.0, -5.0)));
}
#[test]
fn test_studio_default_no_tracking() {
let studio = VirtualStudio::new();
assert!(!studio.has_tracking());
}
#[test]
fn test_studio_with_tracking() {
let studio = VirtualStudio::with_tracking(true);
assert!(studio.has_tracking());
}
#[test]
fn test_studio_set_tracking() {
let mut studio = VirtualStudio::new();
studio.set_tracking(true);
assert!(studio.has_tracking());
}
#[test]
fn test_studio_add_and_count() {
let mut studio = VirtualStudio::new();
assert_eq!(studio.element_count(), 0);
studio.add_element(PlacedElement::new(StudioElement::Floor, "Floor"));
studio.add_element(PlacedElement::new(StudioElement::Wall, "Wall A"));
assert_eq!(studio.element_count(), 2);
}
#[test]
fn test_elements_of_type_filter() {
let mut studio = VirtualStudio::new();
studio.add_element(PlacedElement::new(StudioElement::Floor, "Floor"));
studio.add_element(PlacedElement::new(StudioElement::Prop, "Chair"));
studio.add_element(PlacedElement::new(StudioElement::Prop, "Desk"));
let props = studio.elements_of_type(StudioElement::Prop);
assert_eq!(props.len(), 2);
}
#[test]
fn test_elements_of_type_empty_result() {
let mut studio = VirtualStudio::new();
studio.add_element(PlacedElement::new(StudioElement::Floor, "Floor"));
let ceilings = studio.elements_of_type(StudioElement::Ceiling);
assert!(ceilings.is_empty());
}
#[test]
fn test_elements_accessor_length() {
let mut studio = VirtualStudio::new();
studio.add_element(PlacedElement::new(StudioElement::Ceiling, "Ceiling"));
assert_eq!(studio.elements().len(), 1);
}
}