diff --git a/src/lib.rs b/src/lib.rs index 8c8a0b4..4f12b0c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -324,6 +324,16 @@ pub struct Movie { } impl Movie { + fn min_bit_rate(&self) -> Option { + if self.files.is_empty() { + None + } else { + Some(self.files.iter().fold(usize::max_value(), |acc, (_, cmd)| { + std::cmp::min(acc, cmd.bit_rate) + })) + } + } + fn min_resolution(&self) -> Option { if self.files.is_empty() { None @@ -371,8 +381,8 @@ impl Movies { let mut dupes = Vec::new(); for (_parent, mut movies) in movie_counter.into_iter() { if movies.len() > 1 { - // Sort, smallest movie first. - movies.sort_by(|a, b| a.min_resolution().cmp(&b.min_resolution())); + // Sort, lowest bit_rate movie first + movies.sort_by(|a, b| a.min_bit_rate().cmp(&b.min_bit_rate())); // Flip order, we care about the largest. movies.reverse(); // Take the largest image, return the rest for removal. diff --git a/src/movielibrary_test.rs b/src/movielibrary_test.rs index 3929d61..f784a8c 100644 --- a/src/movielibrary_test.rs +++ b/src/movielibrary_test.rs @@ -49,7 +49,7 @@ fn test_simple_library() { ); } -fn build_tuple(path: &str, res: R) -> (String, CompactMetadata) +fn build_tuple(path: &str, res: R, bit_rate: usize) -> (String, CompactMetadata) where R: Into, { @@ -58,7 +58,7 @@ where path.to_string(), CompactMetadata { filename: format!("./{}", path), - bit_rate: 1, + bit_rate, duration: 1.0, format_name: "test_format".to_string(), size: 1, @@ -72,14 +72,14 @@ where ) } -fn build_movie(paths: Vec<(&str, R)>) -> Movie +fn build_movie(paths: Vec<(&str, R, usize)>) -> Movie where R: Into, { Movie { files: paths .into_iter() - .map(|(path, res)| build_tuple(path, res)) + .map(|(path, res, bit_rate)| build_tuple(path, res, bit_rate)) .collect(), } } @@ -89,26 +89,32 @@ fn build_complex_metadata() -> HashMap { build_tuple( "One Movie With Year (2019)/abcdef123456789.mkv", (1920, 1080), + 1, ), build_tuple( "One Movie With Two Parts (2019)/abcdef123456789 part 1.mkv", (1280, 720), + 1, ), build_tuple( "One Movie With Two Parts (2019)/abcdef123456789 part 2.mkv", (1280, 720), + 1, ), build_tuple( "Two Movies With Multi Parts (2019)/abcdef123456789 part 1.mkv", (1280, 720), + 1000, ), build_tuple( "Two Movies With Multi Parts (2019)/abcdef123456789 part 2.mkv", (1280, 720), + 1000, ), build_tuple( "Two Movies With Multi Parts (2019)/somethingelse.mkv", (1920, 1080), + 5000, ), ] .into_iter() @@ -121,30 +127,36 @@ fn build_complex_movies() -> Movies { build_movie(vec![( "One Movie With Year (2019)/abcdef123456789.mkv", (1920, 1080), + 1, )]), build_movie(vec![ ( "One Movie With Two Parts (2019)/abcdef123456789 part 1.mkv", (1280, 720), + 1, ), ( "One Movie With Two Parts (2019)/abcdef123456789 part 2.mkv", (1280, 720), + 1, ), ]), build_movie(vec![ ( "Two Movies With Multi Parts (2019)/abcdef123456789 part 1.mkv", (1280, 720), + 1000, ), ( "Two Movies With Multi Parts (2019)/abcdef123456789 part 2.mkv", (1280, 720), + 1000, ), ]), build_movie(vec![( "Two Movies With Multi Parts (2019)/somethingelse.mkv", (1920, 1080), + 5000, )]), ], }; @@ -192,15 +204,18 @@ fn test_duplicate_candidates() -> Result<(), Box> { build_movie(vec![( "Two Movies With Multi Parts (2019)/somethingelse.mkv", (1920, 1080), + 5000, )]), vec![build_movie(vec![ ( "Two Movies With Multi Parts (2019)/abcdef123456789 part 1.mkv", (1280, 720), + 1000, ), ( "Two Movies With Multi Parts (2019)/abcdef123456789 part 2.mkv", (1280, 720), + 1000, ), ])], )]; @@ -215,10 +230,12 @@ fn test_fullmetal() -> Result<(), Box> { build_movie(vec![( "Full Metal Jacket (1987)/Full Metal Jacket.mp4", (1280, 720), + 2581935, )]), build_movie(vec![( "Full Metal Jacket (1987)/1776f8e2fb614a6fb77a66cde601bb45.mkv", (1920, 1080), + 5719802, )]), ], }; @@ -235,10 +252,53 @@ fn test_fullmetal() -> Result<(), Box> { build_movie(vec![( "Full Metal Jacket (1987)/1776f8e2fb614a6fb77a66cde601bb45.mkv", (1920, 1080), + 5719802, )]), vec![build_movie(vec![( "Full Metal Jacket (1987)/Full Metal Jacket.mp4", (1280, 720), + 2581935, + )])], + )]; + validate_duplicates(got, want); + Ok(()) +} + +#[test] +fn test_keep_lower_res_higher_bit_rate() -> Result<(), Box> { + let mut movies = Movies { + movies: vec![ + build_movie(vec![( + "X Men The Last Stand (2006)/X.Men.The.Last.Stand.2006.1080p.BluRay.x264.DTS-ES.PRoDJi.mkv", + (1920, 800), + 11349705, + )]), + build_movie(vec![( + "X Men The Last Stand (2006)/948f08a4ba784626ac13de77b77559dd.mkv", + (1920, 1080), + 6574160, + )]), + ], + }; + movies.movies.sort_by(|a, b| { + a.files + .first() + .unwrap() + .0 + .partial_cmp(&b.files.first().unwrap().0) + .unwrap() + }); + let got = movies.duplicate_candidates(); + let want = vec![( + build_movie(vec![( + "X Men The Last Stand (2006)/X.Men.The.Last.Stand.2006.1080p.BluRay.x264.DTS-ES.PRoDJi.mkv", + (1920, 800), + 11349705, + )]), + vec![build_movie(vec![( + "X Men The Last Stand (2006)/948f08a4ba784626ac13de77b77559dd.mkv", + (1920, 1080), + 6574160, )])], )]; validate_duplicates(got, want);