Sort the collection

This commit is contained in:
Wojciech Kozlowski 2023-05-14 18:59:06 +02:00
parent 847a6dcf9c
commit cc4e59a76e

View File

@ -39,8 +39,24 @@ pub struct Track {
pub quality: Quality, pub quality: Quality,
} }
impl PartialOrd for Track {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
let id = (&self.number, &self.title);
let other_id = (&other.number, &other.title);
id.partial_cmp(&other_id)
}
}
impl Ord for Track {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let id = (&self.number, &self.title);
let other_id = (&other.number, &other.title);
id.cmp(&other_id)
}
}
/// The album identifier. /// The album identifier.
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)] #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub struct AlbumId { pub struct AlbumId {
pub year: u32, pub year: u32,
pub title: String, pub title: String,
@ -53,8 +69,20 @@ pub struct Album {
pub tracks: Vec<Track>, pub tracks: Vec<Track>,
} }
impl PartialOrd for Album {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.id.partial_cmp(&other.id)
}
}
impl Ord for Album {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.id.cmp(&other.id)
}
}
/// The artist identifier. /// The artist identifier.
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)] #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ArtistId { pub struct ArtistId {
pub name: String, pub name: String,
} }
@ -66,6 +94,18 @@ pub struct Artist {
pub albums: Vec<Album>, pub albums: Vec<Album>,
} }
impl PartialOrd for Artist {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.id.partial_cmp(&other.id)
}
}
impl Ord for Artist {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.id.cmp(&other.id)
}
}
/// The collection type. Currently, a collection is a list of artists. /// The collection type. Currently, a collection is a list of artists.
pub type Collection = Vec<Artist>; pub type Collection = Vec<Artist>;
@ -122,6 +162,7 @@ impl<LIB: ILibrary, DB: IDatabase> MusicHoard<LIB, DB> {
pub fn rescan_library(&mut self) -> Result<(), Error> { pub fn rescan_library(&mut self) -> Result<(), Error> {
let items = self.library.list(&Query::new())?; let items = self.library.list(&Query::new())?;
self.collection = Self::items_to_artists(items); self.collection = Self::items_to_artists(items);
Self::sort(&mut self.collection);
Ok(()) Ok(())
} }
@ -134,6 +175,16 @@ impl<LIB: ILibrary, DB: IDatabase> MusicHoard<LIB, DB> {
&self.collection &self.collection
} }
fn sort(collection: &mut [Artist]) {
collection.sort_unstable();
for artist in collection.iter_mut() {
artist.albums.sort_unstable();
for album in artist.albums.iter_mut() {
album.tracks.sort_unstable();
}
}
}
fn items_to_artists(items: Vec<Item>) -> Vec<Artist> { fn items_to_artists(items: Vec<Item>) -> Vec<Artist> {
let mut artists: Vec<Artist> = vec![]; let mut artists: Vec<Artist> = vec![];
let mut album_ids = HashMap::<ArtistId, HashSet<AlbumId>>::new(); let mut album_ids = HashMap::<ArtistId, HashSet<AlbumId>>::new();
@ -287,23 +338,8 @@ mod tests {
let mut music_hoard = MusicHoard::new(library, database); let mut music_hoard = MusicHoard::new(library, database);
let mut expected = COLLECTION.to_owned();
// Putting the last track first will make the entire artist come first in the output.
expected.rotate_right(1);
// Same applies to that artists' albums.
expected[0].albums.rotate_right(1);
// Same applies to that album's tracks.
expected[0].albums[0].tracks.rotate_right(1);
// And the original first album's (now the first album of the second artist) tracks first
// track comes last as it will only get picked up at the end.
expected[1].albums[0].tracks.rotate_left(1);
music_hoard.rescan_library().unwrap(); music_hoard.rescan_library().unwrap();
assert_eq!(music_hoard.get_collection(), &expected); assert_eq!(music_hoard.get_collection(), &*COLLECTION);
} }
#[test] #[test]