diff --git a/crunchy-cli-core/src/archive/filter.rs b/crunchy-cli-core/src/archive/filter.rs index 514b540..b181ae6 100644 --- a/crunchy-cli-core/src/archive/filter.rs +++ b/crunchy-cli-core/src/archive/filter.rs @@ -18,6 +18,7 @@ pub(crate) struct ArchiveFilter { archive: Archive, season_episode_count: HashMap>, season_subtitles_missing: Vec, + season_sorting: Vec, visited: Visited, } @@ -28,6 +29,7 @@ impl ArchiveFilter { archive, season_episode_count: HashMap::new(), season_subtitles_missing: vec![], + season_sorting: vec![], visited: Visited::None, } } @@ -129,6 +131,7 @@ impl Filter for ArchiveFilter { let mut episodes = vec![]; for season in seasons { + self.season_sorting.push(season.id.clone()); let season_locale = season .audio_locales .get(0) @@ -296,15 +299,24 @@ impl Filter for ArchiveFilter { let mut single_format_collection = SingleFormatCollection::new(); - let mut sorted: BTreeMap<(u32, String), Self::T> = BTreeMap::new(); + let mut pre_sorted: BTreeMap<(String, String), Self::T> = BTreeMap::new(); for data in flatten_input { - sorted - .entry((data.season_number, data.sequence_number.to_string())) + pre_sorted + .entry((data.season_id.clone(), data.sequence_number.to_string())) .or_insert(vec![]) .push(data) } - for data in sorted.into_values() { + let mut sorted: Vec<((String, String), Self::T)> = pre_sorted.into_iter().collect(); + sorted.sort_by(|((a, _), _), ((b, _), _)| { + self.season_sorting + .iter() + .position(|p| p == a) + .unwrap() + .cmp(&self.season_sorting.iter().position(|p| p == b).unwrap()) + }); + + for (_, data) in sorted { single_format_collection.add_single_formats(data) } diff --git a/crunchy-cli-core/src/utils/format.rs b/crunchy-cli-core/src/utils/format.rs index ca7df94..c67386d 100644 --- a/crunchy-cli-core/src/utils/format.rs +++ b/crunchy-cli-core/src/utils/format.rs @@ -173,8 +173,42 @@ impl PartialEq for SingleFormatCollectionEpisodeKey { } impl Eq for SingleFormatCollectionEpisodeKey {} +struct SingleFormatCollectionSeasonKey((u32, String)); + +impl PartialOrd for SingleFormatCollectionSeasonKey { + fn partial_cmp(&self, other: &Self) -> Option { + let mut cmp = self.0 .0.partial_cmp(&other.0 .0); + if let Some(ordering) = cmp { + if matches!(ordering, Ordering::Equal) && self.0 .1 != other.0 .1 { + // first come first serve + cmp = Some(Ordering::Greater) + } + } + cmp + } +} +impl Ord for SingleFormatCollectionSeasonKey { + fn cmp(&self, other: &Self) -> Ordering { + let mut cmp = self.0 .0.cmp(&other.0 .0); + if matches!(cmp, Ordering::Equal) && self.0 .1 != other.0 .1 { + // first come first serve + cmp = Ordering::Greater + } + cmp + } +} +impl PartialEq for SingleFormatCollectionSeasonKey { + fn eq(&self, other: &Self) -> bool { + self.0.eq(&other.0) + } +} +impl Eq for SingleFormatCollectionSeasonKey {} + pub struct SingleFormatCollection( - BTreeMap>>, + BTreeMap< + SingleFormatCollectionSeasonKey, + BTreeMap>, + >, ); impl SingleFormatCollection { @@ -189,7 +223,10 @@ impl SingleFormatCollection { pub fn add_single_formats(&mut self, single_formats: Vec) { let format = single_formats.first().unwrap(); self.0 - .entry(format.season_number) + .entry(SingleFormatCollectionSeasonKey(( + format.season_number, + format.season_id.clone(), + ))) .or_insert(BTreeMap::new()) .insert( SingleFormatCollectionEpisodeKey(format.sequence_number), @@ -199,18 +236,13 @@ impl SingleFormatCollection { pub fn full_visual_output(&self) { debug!("Series has {} seasons", self.0.len()); - for (season_number, episodes) in &self.0 { + for (season_key, episodes) in &self.0 { + let first_episode = episodes.first_key_value().unwrap().1.first().unwrap(); info!( - "{} Season {}", - episodes - .first_key_value() - .unwrap() - .1 - .first() - .unwrap() - .series_name - .clone(), - season_number + "{} Season {} ({})", + first_episode.series_name.clone(), + season_key.0 .0, + first_episode.season_title.clone(), ); for (i, (_, formats)) in episodes.iter().enumerate() { let format = formats.first().unwrap();