use log::trace;
use super::span::{MatchSpan, Property};
pub fn resolve_conflicts(matches: &mut Vec<MatchSpan>) {
if matches.len() < 2 {
return;
}
matches.sort_by(|a, b| {
a.start
.cmp(&b.start)
.then(b.priority.cmp(&a.priority))
.then(b.len().cmp(&a.len()))
});
let mut keep = vec![true; matches.len()];
for i in 0..matches.len() {
if !keep[i] {
continue;
}
for j in (i + 1)..matches.len() {
if !keep[j] {
continue;
}
if matches[i].property != matches[j].property {
continue;
}
if (matches[i].property == Property::Other
|| matches[i].property == Property::Episode
|| matches[i].property == Property::AbsoluteEpisode
|| matches[i].property == Property::Season
|| matches[i].property == Property::Language
|| matches[i].property == Property::SubtitleLanguage
|| matches[i].property == Property::Disc)
&& matches[i].value != matches[j].value
&& matches[i].start == matches[j].start
&& matches[i].end == matches[j].end
{
continue;
}
if matches[i].overlaps(&matches[j]) {
if matches[j].priority > matches[i].priority {
trace!(
"conflict: dropping {:?}={} (pri={}) in favour of {:?}={} (pri={})",
matches[i].property,
matches[i].value,
matches[i].priority,
matches[j].property,
matches[j].value,
matches[j].priority
);
keep[i] = false;
break;
}
trace!(
"conflict: dropping {:?}={} (pri={}) in favour of {:?}={} (pri={})",
matches[j].property,
matches[j].value,
matches[j].priority,
matches[i].property,
matches[i].value,
matches[i].priority
);
keep[j] = false;
}
}
}
let mut idx = 0;
matches.retain(|_| {
let k = keep[idx];
idx += 1;
k
});
}
#[cfg(test)]
mod tests {
use super::*;
use crate::matcher::span::Property;
#[test]
fn test_no_conflict() {
let mut matches = vec![
MatchSpan::new(0, 5, Property::Title, "Hello"),
MatchSpan::new(6, 10, Property::Year, "2020"),
];
resolve_conflicts(&mut matches);
assert_eq!(matches.len(), 2);
}
#[test]
fn test_overlap_keeps_higher_priority() {
let mut matches = vec![
MatchSpan::new(0, 5, Property::Source, "web").with_priority(0),
MatchSpan::new(2, 7, Property::Source, "other").with_priority(-1),
];
resolve_conflicts(&mut matches);
assert_eq!(matches.len(), 1);
assert_eq!(matches[0].value, "web");
}
#[test]
fn test_overlap_keeps_longer_at_same_priority() {
let mut matches = vec![
MatchSpan::new(0, 3, Property::VideoCodec, "264"),
MatchSpan::new(0, 5, Property::VideoCodec, "x264"),
];
resolve_conflicts(&mut matches);
assert_eq!(matches.len(), 1);
assert_eq!(matches[0].value, "x264");
}
}