diff --git a/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/PlayCommand.java b/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/PlayCommand.java index c3ae429..3aeb2c8 100644 --- a/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/PlayCommand.java +++ b/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/PlayCommand.java @@ -5,12 +5,16 @@ import de.yannicpunktdee.yoshibot.command.YoshiCommandContext; import de.yannicpunktdee.yoshibot.main.YoshiBot; import de.yannicpunktdee.yoshibot.utils.Resources; import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.TextChannel; import net.dv8tion.jda.api.entities.VoiceChannel; -import java.awt.*; +import java.awt.Color; import java.io.File; import java.util.Arrays; +import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.stream.Collectors; public class PlayCommand extends YoshiCommand { @@ -31,18 +35,16 @@ public class PlayCommand extends YoshiCommand { if (download.isFile()) sendInfoMessage("Audio erfolgreich hinzugefügt."); else sendErrorMessage("Audio konnte nicht hinzugefügt werden."); } else if (context.containsArguments(new String[]{"list"})) { - File audioDirectory = new File(Resources.getAudioPath()); StringBuilder sb = new StringBuilder(); - Arrays.stream(audioDirectory.listFiles()).map(File::getName).filter(name -> name.endsWith(".opus")) - .map(name -> name.substring(0, name.lastIndexOf(".opus"))).sorted() - .forEach(name -> sb.append(name).append("\n")); + getAllFiles().forEach(name -> sb.append(name).append("\n")); EmbedBuilder eb = new EmbedBuilder(); eb.setTitle("Es sind folgende Audios verf\u00fcgbar:"); eb.setColor(Color.cyan); eb.setDescription(sb.toString()); sendCustomMessage(eb.build()); } else { - File file = new File(Resources.getPathToAudioFile(context.getArgument("name"))); + String requestedFile = getBestMatch(context.getArgument("name"), getAllFiles()); + File file = new File(Resources.getPathToAudioFile(requestedFile)); if (!file.isFile()) { sendErrorMessage(String.format("Konnte keine Audiodatei namens '%s.opus' finden!", context.getArgument("name"))); @@ -53,10 +55,63 @@ public class PlayCommand extends YoshiCommand { sendErrorMessage("Konnte keinen Audiochannel auswählen."); return false; } + context.getEvent().getMessage().getTextChannel().sendMessage("Spiele '" + requestedFile + "' in '" + vc.getName() + "' ab").queue(); YoshiBot.getInstance().playSound(file, vc); } return true; } + private String getBestMatch(String word, List choices) { + Map hammingDists = + choices.parallelStream() + .collect(Collectors.toMap(file -> file, + file -> maximalMatchingChars(file, word) * choices.size() + + file.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] = '&'; + } + } + 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; + } + + private List getAllFiles() { + File audioDirectory = new File(Resources.getAudioPath()); + return Arrays.stream(Objects.requireNonNull(audioDirectory.listFiles())) + .map(File::getName) + .filter(name -> name.endsWith(".opus")) + .map(name -> name.substring(0, name.lastIndexOf(".opus"))) + .sorted().collect(Collectors.toList()); + } }