* support for matching date based tv shows (that don't have SxE)
This commit is contained in:
parent
92765d5b93
commit
07b675eb93
|
@ -0,0 +1,89 @@
|
|||
|
||||
package net.sourceforge.filebot.similarity;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.MatchResult;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.sourceforge.filebot.web.Date;
|
||||
|
||||
|
||||
public class DateMetric implements SimilarityMetric {
|
||||
|
||||
private final DatePattern[] patterns;
|
||||
|
||||
|
||||
public DateMetric() {
|
||||
patterns = new DatePattern[2];
|
||||
|
||||
// match yyyy-mm-dd patterns like 2010-10-24, 2009/6/1, etc.
|
||||
patterns[0] = new DatePattern("(?<!\\p{Alnum})(\\d{4})[^\\p{Alnum}](\\d{1,2})[^\\p{Alnum}](\\d{1,2})(?!\\p{Alnum})", new int[] { 1, 2, 3 });
|
||||
|
||||
// match dd-mm-yyyy patterns like 1.1.2010, 01/06/2010, etc.
|
||||
patterns[1] = new DatePattern("(?<!\\p{Alnum})(\\d{1,2})[^\\p{Alnum}](\\d{1,2})[^\\p{Alnum}](\\d{4})(?!\\p{Alnum})", new int[] { 3, 2, 1 });
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public float getSimilarity(Object o1, Object o2) {
|
||||
Date d1 = parse(o1);
|
||||
Date d2 = parse(o2);
|
||||
|
||||
return d1 != null && d2 != null && d1.equals(d2) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
protected Date parse(Object object) {
|
||||
if (object instanceof File) {
|
||||
// parse file name
|
||||
object = ((File) object).getName();
|
||||
}
|
||||
|
||||
return match(object.toString());
|
||||
}
|
||||
|
||||
|
||||
protected Date match(CharSequence name) {
|
||||
for (DatePattern pattern : patterns) {
|
||||
Date match = pattern.match(name);
|
||||
|
||||
if (match != null) {
|
||||
return match;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected static class DatePattern {
|
||||
|
||||
protected final Pattern pattern;
|
||||
protected final int[] order;
|
||||
|
||||
|
||||
public DatePattern(String pattern, int[] order) {
|
||||
this.pattern = Pattern.compile(pattern);
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
|
||||
protected Date process(MatchResult match) {
|
||||
return new Date(Integer.parseInt(match.group(order[0])), Integer.parseInt(match.group(order[1])), Integer.parseInt(match.group(order[2])));
|
||||
}
|
||||
|
||||
|
||||
public Date match(CharSequence name) {
|
||||
Matcher matcher = pattern.matcher(name);
|
||||
|
||||
if (matcher.find()) {
|
||||
return process(matcher);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@ package net.sourceforge.filebot.similarity;
|
|||
import java.io.File;
|
||||
|
||||
|
||||
public class LengthEqualsMetric implements SimilarityMetric {
|
||||
public class FileSizeMetric implements SimilarityMetric {
|
||||
|
||||
@Override
|
||||
public float getSimilarity(Object o1, Object o2) {
|
|
@ -102,9 +102,9 @@ public class SeasonEpisodeMatcher {
|
|||
public final int episode;
|
||||
|
||||
|
||||
public SxE(int season, int episode) {
|
||||
this.season = season;
|
||||
this.episode = episode;
|
||||
public SxE(Integer season, Integer episode) {
|
||||
this.season = season != null ? season : UNDEFINED;
|
||||
this.episode = episode != null ? episode : UNDEFINED;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import java.util.Collection;
|
|||
import net.sourceforge.filebot.similarity.SeasonEpisodeMatcher.SxE;
|
||||
|
||||
|
||||
public class SeasonEpisodeSimilarityMetric implements SimilarityMetric {
|
||||
public class SeasonEpisodeMetric implements SimilarityMetric {
|
||||
|
||||
private final SeasonEpisodeMatcher seasonEpisodeMatcher = new SeasonEpisodeMatcher();
|
||||
|
|
@ -2,26 +2,28 @@
|
|||
package net.sourceforge.filebot.ui.panel.rename;
|
||||
|
||||
|
||||
import static java.util.Collections.*;
|
||||
import static net.sourceforge.filebot.hash.VerificationUtilities.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import net.sourceforge.filebot.similarity.LengthEqualsMetric;
|
||||
import net.sourceforge.filebot.similarity.DateMetric;
|
||||
import net.sourceforge.filebot.similarity.FileSizeMetric;
|
||||
import net.sourceforge.filebot.similarity.NameSimilarityMetric;
|
||||
import net.sourceforge.filebot.similarity.NumericSimilarityMetric;
|
||||
import net.sourceforge.filebot.similarity.SeasonEpisodeSimilarityMetric;
|
||||
import net.sourceforge.filebot.similarity.SeasonEpisodeMetric;
|
||||
import net.sourceforge.filebot.similarity.SimilarityMetric;
|
||||
import net.sourceforge.filebot.similarity.SeasonEpisodeMatcher.SxE;
|
||||
import net.sourceforge.filebot.web.Date;
|
||||
import net.sourceforge.filebot.web.Episode;
|
||||
import net.sourceforge.tuned.FileUtilities;
|
||||
|
||||
|
||||
enum MatchSimilarityMetric implements SimilarityMetric {
|
||||
public enum MatchSimilarityMetric implements SimilarityMetric {
|
||||
|
||||
// Match by file length (only works when matching torrents or files)
|
||||
Length(new LengthEqualsMetric() {
|
||||
FileSize(new FileSizeMetric() {
|
||||
|
||||
@Override
|
||||
public float getSimilarity(Object o1, Object o2) {
|
||||
|
@ -40,8 +42,18 @@ enum MatchSimilarityMetric implements SimilarityMetric {
|
|||
}
|
||||
}),
|
||||
|
||||
// Match by season/episode and airdate combined
|
||||
EpisodeIdentifier(new SimilarityMetric() {
|
||||
|
||||
@Override
|
||||
public float getSimilarity(Object o1, Object o2) {
|
||||
return SeasonEpisode.getSimilarity(o1, o2) + AirDate.getSimilarity(o1, o2);
|
||||
}
|
||||
|
||||
}),
|
||||
|
||||
// Match by season / episode numbers
|
||||
SeasonEpisode(new SeasonEpisodeSimilarityMetric() {
|
||||
SeasonEpisode(new SeasonEpisodeMetric() {
|
||||
|
||||
@Override
|
||||
protected Collection<SxE> parse(Object object) {
|
||||
|
@ -49,7 +61,23 @@ enum MatchSimilarityMetric implements SimilarityMetric {
|
|||
Episode episode = (Episode) object;
|
||||
|
||||
// create SxE from episode
|
||||
return Collections.singleton(new SxE(episode.getSeason(), episode.getEpisode()));
|
||||
return singleton(new SxE(episode.getSeason(), episode.getEpisode()));
|
||||
}
|
||||
|
||||
return super.parse(object);
|
||||
}
|
||||
}),
|
||||
|
||||
// Match episode airdate
|
||||
AirDate(new DateMetric() {
|
||||
|
||||
@Override
|
||||
protected Date parse(Object object) {
|
||||
if (object instanceof Episode) {
|
||||
Episode episode = (Episode) object;
|
||||
|
||||
// create SxE from episode
|
||||
return episode.airdate();
|
||||
}
|
||||
|
||||
return super.parse(object);
|
||||
|
@ -119,7 +147,7 @@ enum MatchSimilarityMetric implements SimilarityMetric {
|
|||
// 2. pass: match by season / episode numbers
|
||||
// 3. pass: match by generic name similarity (slow, but most matches will have been determined in second pass)
|
||||
// 4. pass: match by generic numeric similarity
|
||||
return new SimilarityMetric[] { Length, SeasonEpisode, Name, Numeric };
|
||||
return new SimilarityMetric[] { FileSize, EpisodeIdentifier, Name, Numeric };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import static java.util.Calendar.*;
|
|||
import java.io.Serializable;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
|
@ -48,6 +49,23 @@ public class Date implements Serializable {
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Date) {
|
||||
Date other = (Date) obj;
|
||||
return year == other.year && month == other.month && day == other.day;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(new Object[] { year, month, day });
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%04d-%02d-%02d", year, month, day);
|
||||
|
@ -55,7 +73,7 @@ public class Date implements Serializable {
|
|||
|
||||
|
||||
public String format(String pattern) {
|
||||
return new SimpleDateFormat(pattern).format(new GregorianCalendar(year, month, day).getTime());
|
||||
return new SimpleDateFormat(pattern).format(new GregorianCalendar(year, month - 1, day).getTime()); // Calendar months start at 0
|
||||
}
|
||||
|
||||
|
||||
|
@ -66,7 +84,7 @@ public class Date implements Serializable {
|
|||
try {
|
||||
Calendar date = new GregorianCalendar(Locale.ROOT);
|
||||
date.setTime(formatter.parse(string));
|
||||
return new Date(date.get(YEAR), date.get(MONTH) + 1, date.get(DAY_OF_MONTH));
|
||||
return new Date(date.get(YEAR), date.get(MONTH) + 1, date.get(DAY_OF_MONTH)); // Calendar months start at 0
|
||||
} catch (ParseException e) {
|
||||
// no result if date is invalid
|
||||
Logger.getLogger(Date.class.getName()).log(Level.WARNING, e.getMessage());
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
package net.sourceforge.filebot.similarity;
|
||||
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
public class DateMetricTest {
|
||||
|
||||
private static DateMetric metric = new DateMetric();
|
||||
|
||||
|
||||
@Test
|
||||
public void getSimilarity() {
|
||||
assertEquals(1, metric.getSimilarity("2008-02-10", "The Daily Show [10.2.2008] Lou Dobbs"), 0);
|
||||
assertEquals(0, metric.getSimilarity("2008-01-01", "The Daily Show [10.2.2008] Lou Dobbs"), 0);
|
||||
assertEquals(1, metric.getSimilarity("2008-04-03", "The Daily Show - 2008.04.03 - George Clooney"), 0);
|
||||
assertEquals(0, metric.getSimilarity("2008-01-01", "The Daily Show - 2008.04.03 - George Clooney"), 0);
|
||||
}
|
||||
|
||||
}
|
|
@ -7,11 +7,11 @@ import static org.junit.Assert.*;
|
|||
import org.junit.Test;
|
||||
|
||||
|
||||
public class SeasonEpisodeSimilarityMetricTest {
|
||||
|
||||
private static SeasonEpisodeSimilarityMetric metric = new SeasonEpisodeSimilarityMetric();
|
||||
public class SeasonEpisodeMetricTest {
|
||||
|
||||
private static SeasonEpisodeMetric metric = new SeasonEpisodeMetric();
|
||||
|
||||
|
||||
@Test
|
||||
public void getSimilarity() {
|
||||
// single pattern match, single episode match
|
|
@ -8,7 +8,7 @@ import org.junit.runners.Suite.SuiteClasses;
|
|||
|
||||
|
||||
@RunWith(Suite.class)
|
||||
@SuiteClasses( { SeriesNameMatcherTest.class, SeasonEpisodeMatcherTest.class, NameSimilarityMetricTest.class, NumericSimilarityMetricTest.class, SeasonEpisodeSimilarityMetricTest.class })
|
||||
@SuiteClasses( { SeriesNameMatcherTest.class, SeasonEpisodeMatcherTest.class, NameSimilarityMetricTest.class, NumericSimilarityMetricTest.class, SeasonEpisodeMetricTest.class })
|
||||
public class SimilarityTestSuite {
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue