Refactory code into library module

main
mat ess 2023-04-17 19:24:39 -04:00
parent 07b18044de
commit cc949e07f3
2 changed files with 132 additions and 130 deletions

128
src/library.rs Normal file
View File

@ -0,0 +1,128 @@
use nanoserde::DeJson;
use std::{
collections::{HashMap, HashSet},
hash::Hash,
};
#[derive(Debug, Clone)]
pub struct Library {
artists: HashSet<Artist>,
}
impl Library {
pub fn new(json: HashMap<String, Vec<Song>>) -> Self {
let artists = json
.into_iter()
.map(|(name, catalog)| Artist {
name,
catalog: catalog.into_iter().collect(),
})
.collect();
Library { artists }
}
pub fn find_covers(&self) -> HashSet<&Song> {
let names = self
.artists
.iter()
.map(|artist| artist.name.clone())
.collect::<HashSet<_>>();
self.artists
.iter()
.fold(HashSet::new(), |mut covers, artist| {
covers.extend(artist.covered_songs());
covers
})
.into_iter()
.filter(|song| names.contains(&song.composer))
.collect()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
struct Artist {
name: String,
catalog: HashSet<Song>,
}
impl Hash for Artist {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
impl Artist {
fn covered_songs(&self) -> HashSet<&Song> {
self.catalog
.iter()
.filter(|song| song.composer != self.name)
.collect()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, DeJson)]
pub struct Song {
pub title: String,
pub performer: String,
pub composer: String,
}
#[cfg(test)]
mod tests {
use super::*;
fn bmbmbm() -> Song {
Song {
title: "bmbmbm".to_string(),
performer: "black midi".to_string(),
composer: "black midi".to_string(),
}
}
fn love_story(performer: &str) -> Song {
Song {
title: "Love Story".to_string(),
performer: performer.to_string(),
composer: "Taylor Swift".to_string(),
}
}
fn schizoid_man() -> Song {
Song {
title: "21st Century Schizoid Man".to_string(),
performer: "black midi".to_string(),
composer: "Greg Lake, Ian McDonald, Michael Giles, Peter Sinfield & Robert Fripp"
.to_string(),
}
}
fn bm() -> Artist {
Artist {
name: "black midi".to_string(),
catalog: HashSet::from([bmbmbm(), love_story("black midi"), schizoid_man()]),
}
}
fn ts() -> Artist {
Artist {
name: "Taylor Swift".to_string(),
catalog: HashSet::from([love_story("Taylor Swift")]),
}
}
fn library() -> Library {
Library {
artists: HashSet::from([bm(), ts()]),
}
}
#[test]
fn test_covered_songs() {
assert!(bm().covered_songs() == HashSet::from([&love_story("black midi"), &schizoid_man()]))
}
#[test]
fn test_find_covers() {
assert!(library().find_covers() == HashSet::from([&love_story("black midi")]))
}
}

View File

@ -1,9 +1,8 @@
use nanoserde::DeJson; use nanoserde::DeJson;
use std::{ use std::{collections::HashMap, env, fs};
collections::{HashMap, HashSet},
env, fs, mod library;
hash::Hash, use crate::library::{Library, Song};
};
fn main() { fn main() {
let file_path = env::args() let file_path = env::args()
@ -21,128 +20,3 @@ fn main() {
) )
} }
} }
#[derive(Debug, Clone)]
struct Library {
artists: HashSet<Artist>,
}
impl Library {
fn new(json: HashMap<String, Vec<Song>>) -> Self {
let artists = json
.into_iter()
.map(|(name, catalog)| Artist {
name,
catalog: catalog.into_iter().collect(),
})
.collect();
Library { artists }
}
}
impl Library {
fn find_covers(&self) -> HashSet<&Song> {
let names = self
.artists
.iter()
.map(|artist| artist.name.clone())
.collect::<HashSet<_>>();
self.artists
.iter()
.fold(HashSet::new(), |mut covers, artist| {
covers.extend(artist.covered_songs());
covers
})
.into_iter()
.filter(|song| names.contains(&song.composer))
.collect()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
struct Artist {
name: String,
catalog: HashSet<Song>,
}
impl Hash for Artist {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
impl Artist {
fn covered_songs(&self) -> HashSet<&Song> {
self.catalog
.iter()
.filter(|song| song.composer != self.name)
.collect()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, DeJson)]
struct Song {
title: String,
performer: String,
composer: String,
}
#[cfg(test)]
mod tests {
use super::*;
fn bmbmbm() -> Song {
Song {
title: "bmbmbm".to_string(),
performer: "black midi".to_string(),
composer: "black midi".to_string(),
}
}
fn love_story(performer: &str) -> Song {
Song {
title: "Love Story".to_string(),
performer: performer.to_string(),
composer: "Taylor Swift".to_string(),
}
}
fn schizoid_man() -> Song {
Song {
title: "21st Century Schizoid Man".to_string(),
performer: "black midi".to_string(),
composer: "Greg Lake, Ian McDonald, Michael Giles, Peter Sinfield & Robert Fripp"
.to_string(),
}
}
fn bm() -> Artist {
Artist {
name: "black midi".to_string(),
catalog: HashSet::from([bmbmbm(), love_story("black midi"), schizoid_man()]),
}
}
fn ts() -> Artist {
Artist {
name: "Taylor Swift".to_string(),
catalog: HashSet::from([love_story("Taylor Swift")]),
}
}
fn library() -> Library {
Library {
artists: HashSet::from([bm(), ts()]),
}
}
#[test]
fn test_covered_songs() {
assert!(bm().covered_songs() == HashSet::from([&love_story("black midi"), &schizoid_man()]))
}
#[test]
fn test_find_covers() {
assert!(library().find_covers() == HashSet::from([&love_story("black midi")]))
}
}