2009-07-26 12:54:24 -04:00
|
|
|
|
2011-09-22 01:03:46 -04:00
|
|
|
package net.sourceforge.filebot.ui.rename;
|
2009-07-26 12:54:24 -04:00
|
|
|
|
|
|
|
|
2009-08-10 07:46:24 -04:00
|
|
|
import static net.sourceforge.filebot.hash.VerificationUtilities.*;
|
|
|
|
|
2009-07-26 12:54:24 -04:00
|
|
|
import java.io.File;
|
2010-11-09 03:04:12 -05:00
|
|
|
import java.util.Arrays;
|
2009-07-26 12:54:24 -04:00
|
|
|
import java.util.Collection;
|
2010-11-09 03:04:12 -05:00
|
|
|
import java.util.Collections;
|
2009-07-26 12:54:24 -04:00
|
|
|
|
2010-10-24 12:33:38 -04:00
|
|
|
import net.sourceforge.filebot.similarity.DateMetric;
|
|
|
|
import net.sourceforge.filebot.similarity.FileSizeMetric;
|
2009-07-26 12:54:24 -04:00
|
|
|
import net.sourceforge.filebot.similarity.NameSimilarityMetric;
|
|
|
|
import net.sourceforge.filebot.similarity.NumericSimilarityMetric;
|
2010-10-24 12:33:38 -04:00
|
|
|
import net.sourceforge.filebot.similarity.SeasonEpisodeMetric;
|
2009-07-26 12:54:24 -04:00
|
|
|
import net.sourceforge.filebot.similarity.SimilarityMetric;
|
|
|
|
import net.sourceforge.filebot.similarity.SeasonEpisodeMatcher.SxE;
|
2011-09-09 10:50:01 -04:00
|
|
|
import net.sourceforge.filebot.vfs.AbstractFile;
|
2010-10-24 12:33:38 -04:00
|
|
|
import net.sourceforge.filebot.web.Date;
|
2009-07-26 12:54:24 -04:00
|
|
|
import net.sourceforge.filebot.web.Episode;
|
|
|
|
import net.sourceforge.tuned.FileUtilities;
|
|
|
|
|
|
|
|
|
2010-10-24 12:33:38 -04:00
|
|
|
public enum MatchSimilarityMetric implements SimilarityMetric {
|
2009-07-26 12:54:24 -04:00
|
|
|
|
|
|
|
// Match by file length (only works when matching torrents or files)
|
2010-10-24 12:33:38 -04:00
|
|
|
FileSize(new FileSizeMetric() {
|
2009-07-26 12:54:24 -04:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public float getSimilarity(Object o1, Object o2) {
|
2010-11-09 03:04:12 -05:00
|
|
|
// order of arguments is logically irrelevant, but we might be able to save us a call to File.length() which is quite costly
|
2009-07-26 12:54:24 -04:00
|
|
|
return o1 instanceof File ? super.getSimilarity(o2, o1) : super.getSimilarity(o1, o2);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected long getLength(Object object) {
|
|
|
|
if (object instanceof AbstractFile) {
|
|
|
|
return ((AbstractFile) object).getLength();
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.getLength(object);
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
|
2010-10-24 12:33:38 -04:00
|
|
|
// Match by season/episode and airdate combined
|
|
|
|
EpisodeIdentifier(new SimilarityMetric() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public float getSimilarity(Object o1, Object o2) {
|
2010-11-09 03:04:12 -05:00
|
|
|
float sxeSimilarity = SeasonEpisode.getSimilarity(o1, o2);
|
|
|
|
|
|
|
|
// break if SxE is a perfect match already
|
|
|
|
if (sxeSimilarity >= 1)
|
|
|
|
return sxeSimilarity;
|
|
|
|
|
|
|
|
return Math.max(sxeSimilarity, AirDate.getSimilarity(o1, o2));
|
2010-10-24 12:33:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
}),
|
|
|
|
|
2009-07-26 12:54:24 -04:00
|
|
|
// Match by season / episode numbers
|
2010-10-24 12:33:38 -04:00
|
|
|
SeasonEpisode(new SeasonEpisodeMetric() {
|
2009-07-26 12:54:24 -04:00
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Collection<SxE> parse(Object object) {
|
|
|
|
if (object instanceof Episode) {
|
|
|
|
Episode episode = (Episode) object;
|
|
|
|
|
2010-11-09 03:04:12 -05:00
|
|
|
// get SxE from episode, both SxE for season/episode numbering and SxE for absolute episode numbering
|
|
|
|
SxE seasonEpisode = new SxE(episode.getSeason(), episode.getEpisode());
|
|
|
|
SxE absoluteEpisode = new SxE(null, episode.getAbsolute());
|
|
|
|
|
|
|
|
return seasonEpisode.equals(absoluteEpisode) ? Collections.singleton(absoluteEpisode) : Arrays.asList(seasonEpisode, absoluteEpisode);
|
2010-10-24 12:33:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
2009-07-26 12:54:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return super.parse(object);
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
|
|
|
|
// Match by generic name similarity
|
|
|
|
Name(new NameSimilarityMetric() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public float getSimilarity(Object o1, Object o2) {
|
|
|
|
// normalize absolute similarity to similarity rank (10 ranks in total),
|
|
|
|
// so we are less likely to fall for false positives in this pass, and move on to the next one
|
|
|
|
return (float) (Math.floor(super.getSimilarity(o1, o2) * 10) / 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected String normalize(Object object) {
|
|
|
|
// simplify file name, if possible
|
|
|
|
return super.normalize(normalizeFile(object));
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
|
|
|
|
// Match by generic numeric similarity
|
|
|
|
Numeric(new NumericSimilarityMetric() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected String normalize(Object object) {
|
|
|
|
// simplify file name, if possible
|
|
|
|
return super.normalize(normalizeFile(object));
|
|
|
|
}
|
2011-10-17 23:58:03 -04:00
|
|
|
}),
|
|
|
|
|
|
|
|
StrictEpisodeIdentifier(new SimilarityMetric() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public float getSimilarity(Object o1, Object o2) {
|
|
|
|
// strict SxE metric, don't allow in-between values
|
|
|
|
return EpisodeIdentifier.getSimilarity(o1, o2) >= 1 ? 1 : 0;
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
|
|
|
|
StrictName(new SimilarityMetric() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public float getSimilarity(Object o1, Object o2) {
|
|
|
|
return (float) (Math.floor(Name.getSimilarity(o1, o2) * 2) / 2);
|
|
|
|
}
|
2009-07-26 12:54:24 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
// inner metric
|
|
|
|
private final SimilarityMetric metric;
|
|
|
|
|
|
|
|
|
|
|
|
private MatchSimilarityMetric(SimilarityMetric metric) {
|
|
|
|
this.metric = metric;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public float getSimilarity(Object o1, Object o2) {
|
|
|
|
return metric.getSimilarity(o1, o2);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected static String normalizeFile(Object object) {
|
|
|
|
String name = object.toString();
|
|
|
|
|
|
|
|
// use name without extension
|
|
|
|
if (object instanceof File) {
|
|
|
|
name = FileUtilities.getName((File) object);
|
|
|
|
} else if (object instanceof AbstractFile) {
|
|
|
|
name = FileUtilities.getNameWithoutExtension(((AbstractFile) object).getName());
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove embedded checksum from name, if any
|
2009-08-10 07:46:24 -04:00
|
|
|
return removeEmbeddedChecksum(name);
|
2009-07-26 12:54:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static SimilarityMetric[] defaultSequence() {
|
|
|
|
// 1. pass: match by file length (fast, but only works when matching torrents or files)
|
|
|
|
// 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
|
2010-10-24 12:33:38 -04:00
|
|
|
return new SimilarityMetric[] { FileSize, EpisodeIdentifier, Name, Numeric };
|
2009-07-26 12:54:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|