forked from ChomeNS/chomens-bot-java
msuic custom instrumnet thing auto detect using levenshtein distance (worst code)
yes its so bad but it kinda owkrs it takes a while to load the shit though
This commit is contained in:
parent
b04eb16d4f
commit
b2d8aeb319
6 changed files with 7868 additions and 4 deletions
|
@ -1,12 +1,23 @@
|
|||
package land.chipmunk.chayapak.chomens_bot.song;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import land.chipmunk.chayapak.chomens_bot.Bot;
|
||||
import land.chipmunk.chayapak.chomens_bot.util.ComponentUtilities;
|
||||
import land.chipmunk.chayapak.chomens_bot.util.LevenshteinUtilities;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
// Author: hhhzzzsss
|
||||
public class NBSConverter implements Converter {
|
||||
|
@ -170,10 +181,48 @@ public class NBSConverter implements Converter {
|
|||
|
||||
NBSCustomInstrument customInstrument = customInstruments.get(index);
|
||||
|
||||
final Path path = Path.of(customInstrument.file);
|
||||
String name = path.getFileName().toString();
|
||||
if (name.endsWith(".ogg")) name = name.substring(0, name.length() - ".ogg".length()); // bad but OK
|
||||
if (name.contains("entity.firework.")) name = name.replace("entity.firework.", "entity.firework_rocket.");
|
||||
String name = customInstrument.name.replace("entity.firework.", "entity.firework_rocket.");
|
||||
|
||||
String file = Path.of(customInstrument.file).getFileName().toString();
|
||||
if (file.endsWith(".ogg")) file = file.substring(0, file.length() - ".ogg".length());
|
||||
file = file.replace("entity.firework.", "entity.firework_rocket.");
|
||||
|
||||
boolean replaced = false;
|
||||
|
||||
if (name.toLowerCase().contains("glass break") || name.toLowerCase().contains("glass broken")) {
|
||||
name = "block.glass.break";
|
||||
replaced = true;
|
||||
} else if (name.toLowerCase().contains("door close") || name.toLowerCase().contains("door open")) {
|
||||
name = "block.wooden_door.open";
|
||||
replaced = true;
|
||||
}
|
||||
|
||||
if (!sounds.contains(name) && !sounds.contains(file) && !replaced) {
|
||||
name = name
|
||||
.replaceAll("Eye.*Fill", "Eye of Ender attaches");
|
||||
|
||||
final List<String> outputTitles = LevenshteinUtilities.searchTitles(name, subtitles.values());
|
||||
|
||||
final String bestMatch = outputTitles.size() == 0 ? "" : outputTitles.get(0);
|
||||
|
||||
System.out.println("orig ins name: " + name);
|
||||
System.out.println("best match: " + bestMatch);
|
||||
|
||||
for (Map.Entry<String, String> entry : subtitles.entrySet()) {
|
||||
if (!entry.getValue().equals(bestMatch)) continue;
|
||||
|
||||
name = entry.getKey().substring("subtitles.".length());
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// final Path path = Path.of(customInstrument.file);
|
||||
// String name = path.getFileName().toString();
|
||||
// if (name.endsWith(".ogg")) name = name.substring(0, name.length() - ".ogg".length()); // bad but OK
|
||||
// name = name.replace("entity.firework.", "entity.firework_rocket.");
|
||||
//
|
||||
// System.out.println("after replaced " + name);
|
||||
|
||||
instrument = Instrument.of(name);
|
||||
key += customInstrument.pitch;
|
||||
|
@ -213,4 +262,30 @@ public class NBSConverter implements Converter {
|
|||
private static int getMilliTime(int tick, int tempo) {
|
||||
return 1000 * tick * 100 / tempo;
|
||||
}
|
||||
|
||||
private static final Map<String, String> subtitles = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (Map.Entry<String, String> entry : ComponentUtilities.englishLanguage.entrySet()) {
|
||||
if (!entry.getKey().startsWith("subtitles.")) continue;
|
||||
|
||||
subtitles.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> sounds = loadJsonStringArray("sounds.json");
|
||||
|
||||
private static List<String> loadJsonStringArray (String name) {
|
||||
List<String> list = new ArrayList<>();
|
||||
|
||||
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(name);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
JsonArray json = JsonParser.parseReader(reader).getAsJsonArray();
|
||||
|
||||
for (JsonElement entry : json) {
|
||||
list.add(entry.getAsString());
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ public class ComponentUtilities {
|
|||
|
||||
// component parsing
|
||||
public static final Map<String, String> language = loadJsonStringMap("language.json");
|
||||
public static final Map<String, String> englishLanguage = loadJsonStringMap("englishLanguage.json");
|
||||
private static final Map<String, String> voiceChatLanguage = loadJsonStringMap("voiceChatLanguage.json");
|
||||
private static final Map<String, String> keybinds = loadJsonStringMap("keybinds.json");
|
||||
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package land.chipmunk.chayapak.chomens_bot.util;
|
||||
|
||||
import com.google.common.collect.Ordering;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
// stolen from https://github.com/MeteorDevelopment/meteor-client/blob/master/src/main/java/meteordevelopment/meteorclient/utils/Utils.java#L253
|
||||
// and https://github.com/MeteorDevelopment/meteor-client/blob/master/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java#L170
|
||||
public class LevenshteinUtilities {
|
||||
public static List<String> searchTitles(String text, Collection<String> texts) {
|
||||
final Map<String, Integer> output = new ValueComparableMap<>(Ordering.natural());
|
||||
|
||||
for (String eachText : texts) {
|
||||
int score = searchLevenshteinDefault(text, eachText, false);
|
||||
output.put(eachText, output.getOrDefault(eachText, 0) + score);
|
||||
}
|
||||
|
||||
return output.keySet().stream().toList();
|
||||
}
|
||||
|
||||
public static int searchLevenshteinDefault(String text, String filter, boolean caseSensitive) {
|
||||
return levenshteinDistance(caseSensitive ? filter : filter.toLowerCase(), caseSensitive ? text : text.toLowerCase(), 1, 8, 8);
|
||||
}
|
||||
|
||||
public static int searchInWords(String text, String filter) {
|
||||
if (filter.isEmpty()) return 1;
|
||||
|
||||
int wordsFound = 0;
|
||||
text = text.toLowerCase();
|
||||
String[] words = filter.toLowerCase().split(" ");
|
||||
|
||||
for (String word : words) {
|
||||
if (!text.contains(word)) return 0;
|
||||
wordsFound += StringUtils.countMatches(text, word);
|
||||
}
|
||||
|
||||
return wordsFound;
|
||||
}
|
||||
|
||||
public static int levenshteinDistance(String from, String to, int insCost, int subCost, int delCost) {
|
||||
int textLength = from.length();
|
||||
int filterLength = to.length();
|
||||
|
||||
if (textLength == 0) return filterLength * insCost;
|
||||
if (filterLength == 0) return textLength * delCost;
|
||||
|
||||
// Populate matrix
|
||||
int[][] d = new int[textLength + 1][filterLength + 1];
|
||||
|
||||
for (int i = 0; i <= textLength; i++) {
|
||||
d[i][0] = i * delCost;
|
||||
}
|
||||
|
||||
for (int j = 0; j <= filterLength; j++) {
|
||||
d[0][j] = j * insCost;
|
||||
}
|
||||
|
||||
// Find best route
|
||||
for (int i = 1; i <= textLength; i++) {
|
||||
for (int j = 1; j <= filterLength; j++) {
|
||||
int sCost = d[i-1][j-1] + (from.charAt(i-1) == to.charAt(j-1) ? 0 : subCost);
|
||||
int dCost = d[i-1][j] + delCost;
|
||||
int iCost = d[i][j-1] + insCost;
|
||||
d[i][j] = Math.min(Math.min(dCost, iCost), sCost);
|
||||
}
|
||||
}
|
||||
|
||||
return d[textLength][filterLength];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package land.chipmunk.chayapak.chomens_bot.util;
|
||||
|
||||
|
||||
import com.google.common.collect.Ordering;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
// https://github.com/MeteorDevelopment/meteor-client/blob/master/src/main/java/meteordevelopment/meteorclient/utils/misc/ValueComparableMap.java
|
||||
public class ValueComparableMap<K extends Comparable<K>, V> extends TreeMap<K, V> {
|
||||
private final Map<K, V> valueMap;
|
||||
|
||||
public ValueComparableMap(final Ordering<? super V> partialValueOrdering) {
|
||||
this(partialValueOrdering, new HashMap<>());
|
||||
}
|
||||
|
||||
private ValueComparableMap(Ordering<? super V> partialValueOrdering, HashMap<K, V> valueMap) {
|
||||
super(partialValueOrdering.onResultOf(valueMap::get).compound(Comparator.naturalOrder()));
|
||||
this.valueMap = valueMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(K k, V v) {
|
||||
if (valueMap.containsKey(k)) remove(k);
|
||||
valueMap.put(k,v);
|
||||
return super.put(k, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return valueMap.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V getOrDefault(Object key, V defaultValue) {
|
||||
return containsKey(key) ? get(key) : defaultValue;
|
||||
}
|
||||
}
|
6219
src/main/resources/englishLanguage.json
Normal file
6219
src/main/resources/englishLanguage.json
Normal file
File diff suppressed because it is too large
Load diff
1456
src/main/resources/sounds.json
Normal file
1456
src/main/resources/sounds.json
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue