use std::cmp::Ordering; use std::collections::HashSet; // As an artist, I can add artwork and attach it to a product // As an artist, I can enter detailed information about a product // As an artist, I can store a product for later recall by me or connoisseurs. // As a connoisseur, I can search the gallery for artwork matching given keywords and see products // containing that artwork // As a connoisseur, I can select one or many products and submit them in a job to an artist // As an artist, I can select individual products to be featured, and rank first in default fetch lists // As an artist, I can select individual products to be featured, and rank first in search results // As an artist, I can select entire categories to be featured, and rank first in search results // As an artist, I can select entire categories to be featured, and rank first in default fetch // lists // Sellable artwork, artowrk with a price attached to it. Prices are in cents to do comparisons to // other products without fractions. Has a quantity to indicate stock. Can be // featured in order to appear higher in connoisseur search results. #[derive(Debug, Clone)] struct Product { artwork: Artwork, cents: u64, quantity: u64, featured: bool, } impl PartialEq for Product { fn eq(&self, other: &Self) -> bool { self.cents == other.cents } } impl PartialOrd for Product { fn partial_cmp(&self, other: &Self) -> Option { self.cents.partial_cmp(&other.cents) } } impl Product { fn dollars(&self) -> f64 { self.cents as f64 / 100.0 } } #[derive(Debug, Clone)] struct Artwork { name: String, description: String, category: Vec, tags: HashSet, } struct Customer {} trait Artist { fn create_art(gallery: G) -> Result<(), ()>; } struct Sort { highest_price: bool, lowest_price: bool, highest_quantity: bool, lowest_quantity: bool, atoz: bool, ztoa: bool, oldest: bool, newest: bool, featured: bool, } struct Filter { search_term: HashSet, category: Vec, sort: Sort, } trait Gallery { fn store(artwork: Artwork) -> Result<(), ()>; fn search(filter: Filter, sort: Sort) -> Result<(), ()>; } struct MockGallery {} impl Gallery for MockGallery { fn store(_artwork: Artwork) -> Result<(), ()> { Ok(()) } fn search(_search: Filter, _sort: Sort) -> Result<(), ()> { Ok(()) } } struct Job {} fn add_two(a: usize, b: usize) -> usize { a + b } #[cfg(test)] mod tests { use super::*; #[test] fn add() { assert_eq!(4, add_two(2, 2)); } #[test] fn dollars() { let product = Product { artwork: Artwork { tags: HashSet::new(), category: vec![], name: "".into(), description: "".into(), }, cents: 1000, quantity: 0, featured: false, }; assert_eq!(10.00, product.dollars()); let product = Product { artwork: Artwork { tags: HashSet::new(), category: vec![], name: "".into(), description: "".into(), }, cents: 1234, quantity: 0, featured: false, }; assert_eq!(12.34, product.dollars()); } #[test] fn price_check() { let artwork = Artwork { tags: HashSet::new(), category: vec![], name: "".into(), description: "".into(), }; let product1 = Product { artwork: artwork.clone(), cents: 1000, quantity: 0, featured: false, }; let mut product2 = Product { artwork, cents: 1000, quantity: 0, featured: false, }; assert_eq!(product1, product2); product2.cents = 1234; assert_ne!(product1, product2); assert!(product1 < product2); } }