* support for matching date based tv shows (that don't have SxE)

This commit is contained in:
Reinhard Pointner 2010-10-24 16:33:38 +00:00
parent 92765d5b93
commit 07b675eb93
9 changed files with 177 additions and 19 deletions

View File

@ -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;
}
}
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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();

View File

@ -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 };
}
}

View File

@ -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());

View File

@ -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);
}
}

View File

@ -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

View File

@ -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 {
}