Browse Source

String-Ähnlichkeit durch Jaccard-Distanz ersetzt

master
Yannic Link 3 years ago
parent
commit
b5e9480edc
2 changed files with 17 additions and 42 deletions
  1. +1
    -0
      app/build.gradle
  2. +16
    -42
      app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/PlayCommand.java

+ 1
- 0
app/build.gradle View File

@ -30,6 +30,7 @@ dependencies {
implementation 'com.sedmelluq:lavaplayer:1.3.73' implementation 'com.sedmelluq:lavaplayer:1.3.73'
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.0' implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.0'
implementation 'org.apache.commons:commons-text:1.9'
implementation "net.dean.jraw:JRAW:1.1.0" implementation "net.dean.jraw:JRAW:1.1.0"


+ 16
- 42
app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/PlayCommand.java View File

@ -5,14 +5,14 @@ import de.yannicpunktdee.yoshibot.command.YoshiCommandContext;
import de.yannicpunktdee.yoshibot.main.YoshiBot; import de.yannicpunktdee.yoshibot.main.YoshiBot;
import de.yannicpunktdee.yoshibot.utils.Resources; import de.yannicpunktdee.yoshibot.utils.Resources;
import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.VoiceChannel; import net.dv8tion.jda.api.entities.VoiceChannel;
import org.apache.commons.text.similarity.JaccardDistance;
import java.awt.Color; import java.awt.Color;
import java.io.File; import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -44,6 +44,11 @@ public class PlayCommand extends YoshiCommand {
sendCustomMessage(eb.build()); sendCustomMessage(eb.build());
} else if (context.containsArgument("name")) { } else if (context.containsArgument("name")) {
String requestedFile = getBestMatch(context.getArgument("name"), getAllFiles()); String requestedFile = getBestMatch(context.getArgument("name"), getAllFiles());
if(requestedFile == null){
sendErrorMessage(String.format("Konnte keine Audiodatei namens '%s.opus' finden!",
context.getArgument("name")));
return false;
}
File file = new File(Resources.getPathToAudioFile(requestedFile)); File file = new File(Resources.getPathToAudioFile(requestedFile));
if (!file.isFile()) { if (!file.isFile()) {
sendErrorMessage(String.format("Konnte keine Audiodatei namens '%s.opus' finden!", sendErrorMessage(String.format("Konnte keine Audiodatei namens '%s.opus' finden!",
@ -68,48 +73,17 @@ public class PlayCommand extends YoshiCommand {
} }
private String getBestMatch(String word, List<String> choices) { private String getBestMatch(String word, List<String> choices) {
Map<String, Double> hammingDists =
choices.parallelStream()
.collect(Collectors.toMap(file -> file,
file -> (double) maximalMatchingChars(file, word) /
Math.max(file.length(),
word.length())));
return hammingDists.keySet().stream()
.max((file1, file2) -> (int) Math.signum(hammingDists.get(file1) - hammingDists.get(file2)))
.orElse(choices.get(0));
}
private int maximalMatchingChars(String word1, String word2) {
int maxMatches = 0;
int combinedSize = word1.length() + word2.length() - 1;
char[] word1Chars = new char[combinedSize], word2Chars = new char[combinedSize];
for (int i = 0; i < combinedSize; i++) {
if (i < word2.length()) {
word2Chars[i] = word2.charAt(i);
} else {
word2Chars[i] = '&';
double bestScore = 1.0;
String bestMatching = null;
for(String file : choices){
double score = (new JaccardDistance()).apply(word, file);
if(score < bestScore){
bestScore = score;
bestMatching = file;
} }
} }
for (int i = 0; i < combinedSize; i++) {
for (int j = 0; j < combinedSize; j++) {
if (i <= j && j < i + word1.length()) {
word1Chars[j] = word1.charAt(j - i);
} else {
word1Chars[j] = '$';
}
}
maxMatches = Math.max(getMatchingChars(word1Chars, word2Chars), maxMatches);
}
return maxMatches;
}
private int getMatchingChars(char[] word1, char[] word2) {
int dist = 0;
assert word1.length == word2.length;
for (int i = 0; i < word1.length; i++) {
dist += word1[i] == word2[i] ? 1 : 0;
}
return dist;
return bestMatching;
} }
private List<String> getAllFiles() { private List<String> getAllFiles() {


Loading…
Cancel
Save