Improve coherent attribute updater

This commit is contained in:
RatzzFatzz
2025-12-15 18:13:32 +01:00
parent a51922968e
commit d3248e646b
9 changed files with 96 additions and 65 deletions

View File

@@ -32,7 +32,6 @@ public class FileFilter {
return false;
}
ResultStatistic.getInstance().total();
if (!hasMatchingPattern(pathName)
|| !isNewer(pathName)
|| isExcluded(pathName, new HashSet<>(excluded))) {

View File

@@ -8,13 +8,13 @@ import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
public class AttributeProcessor {
public class AttributeChangeProcessor {
private final SubtitleTrackComparator subtitleTrackComparator;
private final Set<String> commentaryKeywords;
private final Set<String> hearingImpairedKeywords;
private final Set<String> forcedKeywords;
public AttributeProcessor(String[] preferredSubtitles, Set<String> forcedKeywords, Set<String> commentaryKeywords, Set<String> hearingImpairedKeywords) {
public AttributeChangeProcessor(String[] preferredSubtitles, Set<String> forcedKeywords, Set<String> commentaryKeywords, Set<String> hearingImpairedKeywords) {
this.subtitleTrackComparator = new SubtitleTrackComparator(preferredSubtitles);
this.commentaryKeywords = commentaryKeywords;
this.hearingImpairedKeywords = hearingImpairedKeywords;

View File

@@ -22,7 +22,7 @@ public abstract class AttributeUpdater {
protected final InputConfig config;
protected final FileProcessor fileProcessor;
protected final AttributeProcessor attributeProcessor;
protected final AttributeChangeProcessor attributeChangeProcessor;
protected final ResultStatistic statistic = ResultStatistic.getInstance();
private final ExecutorService executor;
@@ -30,7 +30,7 @@ public abstract class AttributeUpdater {
public AttributeUpdater(InputConfig config, FileProcessor fileProcessor) {
this.config = config;
this.fileProcessor = fileProcessor;
this.attributeProcessor = new AttributeProcessor(config.getPreferredSubtitles().toArray(new String[0]), config.getForcedKeywords(), config.getCommentaryKeywords(), config.getHearingImpaired());
this.attributeChangeProcessor = new AttributeChangeProcessor(config.getPreferredSubtitles().toArray(new String[0]), config.getForcedKeywords(), config.getCommentaryKeywords(), config.getHearingImpaired());
this.executor = Executors.newFixedThreadPool(config.getThreads());
}

View File

@@ -34,47 +34,66 @@ public class CoherentAttributeUpdater extends SingleFileAttributeUpdater {
List<File> files = fileProcessor.loadFiles(rootDir.getPath());
Set<FileInfo> matchedFiles = new HashSet<>(files.size() * 2);
AttributeConfig matchedConfig = null;
for (AttributeConfig config: config.getAttributeConfig()) {
for (File file: files) {
FileInfo fileInfo = fileProcessor.readAttributes(file);
fileInfo.resetChanges();
fileInfo.setMatchedConfig(null);
AttributeConfig matchedConfig = findMatch(config, matchedFiles, files);
if (fileInfo.getTracks().isEmpty()) {
log.warn("No attributes found for file {}", file);
statistic.failure();
break;
}
attributeProcessor.findDefaultMatchAndApplyChanges(fileInfo, config);
if (matchedConfig == null) matchedConfig = fileInfo.getMatchedConfig();
matchedFiles.add(fileInfo);
if (matchedConfig != fileInfo.getMatchedConfig()) {
matchedConfig = null;
break;
}
if (matchedConfig == null) continue;
if (matchedFiles.size() != files.size()) {
log.warn("Skip applying changes: Found coherent match, but matched count is different than file count (matched: {}, files: {}, dir: {})",
matchedFiles.size(), files.size(), rootDir.getPath());
}
if (matchedConfig != null) break;
}
if (matchedConfig != null) {
matchedFiles.forEach(fileInfo -> {
attributeProcessor.findForcedTracksAndApplyChanges(fileInfo, config.isOverwriteForced());
attributeProcessor.findCommentaryTracksAndApplyChanges(fileInfo);
attributeProcessor.findHearingImpairedTracksAndApplyChanges(fileInfo);
attributeChangeProcessor.findForcedTracksAndApplyChanges(fileInfo, this.config.isOverwriteForced());
attributeChangeProcessor.findCommentaryTracksAndApplyChanges(fileInfo);
attributeChangeProcessor.findHearingImpairedTracksAndApplyChanges(fileInfo);
checkStatusAndUpdate(fileInfo);
});
} else {
log.info("No coherent match found, trying to find coherent match in child directories: {}", rootDir.getPath());
matchedFiles.forEach(fileInfo -> {
fileInfo.resetChanges();
fileInfo.setMatchedConfig(null);
});
for (File dir: fileProcessor.loadDirectory(rootDir.getPath(), 1)) this.process(dir);
return; // match was found and process must be stopped
}
// Couldn't match any config at current level. Resetting changes and trying to one level deeper
matchedFiles.forEach(fileInfo -> {
fileInfo.resetChanges();
fileInfo.setMatchedConfig(null);
});
if (config.isForceCoherent()) {
log.info("No coherent match found, aborting: {}", rootDir.getPath());
statistic.increaseNoSuitableConfigFoundBy(files.size()); // TODO: should matchedFiles count as already fit config?
return;
}
log.info("No coherent match found, trying to find coherent match in child directories: {}", rootDir.getPath());
for (File dir: fileProcessor.loadDirectory(rootDir.getPath(), 1)) this.process(dir);
}
private AttributeConfig findMatch(AttributeConfig config, Set<FileInfo> matchedFiles, List<File> files) {
AttributeConfig matchedConfig = null;
matchedFiles.clear();
for (File file: files) {
FileInfo fileInfo = fileProcessor.readAttributes(file);
fileInfo.resetChanges();
fileInfo.setMatchedConfig(null);
if (fileInfo.getTracks().isEmpty()) {
log.warn("No attributes found for file {}", file);
statistic.failure();
break;
}
attributeChangeProcessor.findDefaultMatchAndApplyChanges(fileInfo, config);
if (matchedConfig == null) matchedConfig = fileInfo.getMatchedConfig();
if (matchedConfig == null || matchedConfig != fileInfo.getMatchedConfig()) {
matchedConfig = null;
break;
}
matchedFiles.add(fileInfo);
}
return matchedConfig;
}
}

View File

@@ -29,10 +29,10 @@ public class SingleFileAttributeUpdater extends AttributeUpdater {
return;
}
attributeProcessor.findDefaultMatchAndApplyChanges(fileInfo, config.getAttributeConfig());
attributeProcessor.findForcedTracksAndApplyChanges(fileInfo, config.isOverwriteForced());
attributeProcessor.findCommentaryTracksAndApplyChanges(fileInfo);
attributeProcessor.findHearingImpairedTracksAndApplyChanges(fileInfo);
attributeChangeProcessor.findDefaultMatchAndApplyChanges(fileInfo, config.getAttributeConfig());
attributeChangeProcessor.findForcedTracksAndApplyChanges(fileInfo, config.isOverwriteForced());
attributeChangeProcessor.findCommentaryTracksAndApplyChanges(fileInfo);
attributeChangeProcessor.findHearingImpairedTracksAndApplyChanges(fileInfo);
checkStatusAndUpdate(fileInfo);
}

View File

@@ -46,9 +46,9 @@ public class InputConfig implements CommandLine.IVersionProvider {
private int threads;
@Min(0)
@Option(names = {"-c", "--coherent"}, description = "try to match all files in dir of depth with the same attribute config")
@Option(names = {"-c", "--coherent"}, description = "try to match all files in dir of depth with the same attribute config. Attempting increasing deeper levels until match is found (worst case applying config on single file basis)")
private Integer coherent;
@Option(names = {"-cf", "--force-coherent"}, description = "changes are only applied if it's a coherent match")
@Option(names = {"-cf", "--force-coherent"}, description = "only applies changes if a coherent match was found for the specifically entered depth")
private boolean forceCoherent;
@Option(names = {"-n", "--only-new-file"}, description = "sets filter-date to last successful execution (overwrites input of filter-date)")

View File

@@ -17,7 +17,6 @@ public class ResultStatistic {
"└─ Failed: %s%n" +
"Runtime: %s";
private static ResultStatistic instance;
private int total = 0;
private int excluded = 0;
private int shouldChange = 0;
@@ -43,12 +42,8 @@ public class ResultStatistic {
return instance;
}
public void increaseTotalBy(int amount) {
total += amount;
}
public synchronized void total() {
total++;
public int total() {
return shouldChange + noSuitableConfigFound + alreadyFits + failed;
}
public void increaseExcludedBy(int amount) {
@@ -75,6 +70,10 @@ public class ResultStatistic {
noSuitableConfigFound++;
}
public synchronized void increaseNoSuitableConfigFoundBy(int amount) {
noSuitableConfigFound += amount;
}
public synchronized void alreadyFits() {
alreadyFits++;
}
@@ -114,13 +113,13 @@ public class ResultStatistic {
}
public String prettyPrint() {
return String.format(result, total, excluded, shouldChange, failedChanging, successfullyChanged,
return String.format(result, total(), excluded, shouldChange, failedChanging, successfullyChanged,
noSuitableConfigFound, alreadyFits, failed, formatTimer());
}
@Override
public String toString() {
return "ResultStatistic: " + "total=" + total +
return "ResultStatistic: " + "total=" + total() +
", excluded=" + excluded +
", shouldChange=" + shouldChange +
" (failedChanging=" + failedChanging +
@@ -130,4 +129,5 @@ public class ResultStatistic {
", failed=" + failed +
", runtime=" + formatTimer();
}
}