From bcb46b7cd5cf826f7ee6004a618b0d1563a15f37 Mon Sep 17 00:00:00 2001 From: Marc Baloup Date: Sun, 3 Nov 2019 00:15:23 +0100 Subject: [PATCH] Add SQLWhereIn and LevenshteinDistance algorithm --- .../pandacube/util/LevenshteinDistance.java | 68 ++++++++ .../util/PlayerNameHistoryLookup.java | 145 ------------------ .../fr/pandacube/util/orm/SQLWhereIn.java | 34 ++++ 3 files changed, 102 insertions(+), 145 deletions(-) create mode 100644 src/main/java/fr/pandacube/util/LevenshteinDistance.java delete mode 100644 src/main/java/fr/pandacube/util/PlayerNameHistoryLookup.java create mode 100644 src/main/java/fr/pandacube/util/orm/SQLWhereIn.java diff --git a/src/main/java/fr/pandacube/util/LevenshteinDistance.java b/src/main/java/fr/pandacube/util/LevenshteinDistance.java new file mode 100644 index 0000000..a5566c3 --- /dev/null +++ b/src/main/java/fr/pandacube/util/LevenshteinDistance.java @@ -0,0 +1,68 @@ +package fr.pandacube.util; + +import java.util.Objects; +import java.util.function.ToIntBiFunction; + +public class LevenshteinDistance { + + private String initialList; + + private int elementAdditionScore; + private int elementDeletionScore; + + private ToIntBiFunction elementDistanceFunction; + + private int[] prev, curr; + + private int progress = 0; + + public LevenshteinDistance(String initList, String finList, int addScore, int delScore, ToIntBiFunction elemDistFn) { + initialList = initList == null ? "" : initList; + elementAdditionScore = addScore; + elementDeletionScore = delScore; + elementDistanceFunction = elemDistFn == null ? ((e1, e2) -> Objects.equals(e1, e2) ? 0 : 1) : elemDistFn; + + prev = new int[initialList.length() + 1]; + + curr = new int[initialList.length() + 1]; + for (int i = 0; i < curr.length; i++) + curr[i] = i * elementDeletionScore; + + add(finList); + } + + public LevenshteinDistance() { + this(null, null, 1, 1, null); + } + + public LevenshteinDistance(String initList) { + this(initList, null, 1, 1, null); + } + + public int getCurrentDistance() { + return curr[curr.length - 1]; + } + + public void add(String els) { + for (char el : els.toCharArray()) + add(el); + } + + public void add(char el) { + progress++; + // swap score arrays + int[] tmp = prev; prev = curr; curr = tmp; + + curr[0] = progress * elementAdditionScore; + + for (int i = 1; i < curr.length; i++) { + int S = prev[i - 1] + elementDistanceFunction.applyAsInt(initialList.charAt(i - 1), el); + int A = prev[i] + elementAdditionScore; + int D = curr[i - 1] + elementDeletionScore; + curr[i] = Math.min(S, Math.min(A, D)); + } + } + + + +} diff --git a/src/main/java/fr/pandacube/util/PlayerNameHistoryLookup.java b/src/main/java/fr/pandacube/util/PlayerNameHistoryLookup.java deleted file mode 100644 index a92e8a5..0000000 --- a/src/main/java/fr/pandacube/util/PlayerNameHistoryLookup.java +++ /dev/null @@ -1,145 +0,0 @@ -package fr.pandacube.util; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.Arrays; -import java.util.Date; -import java.util.UUID; - -import com.google.gson.Gson; -import com.google.gson.annotations.SerializedName; - -/** - * This class performs a name lookup for a player and gets back all the name - * changes of the player (if any). - *
- * https - * ://bukkit.org/threads/player-name-history-lookup.412679/ - * - * @since 25-3-2016 - * @author mine-care (AKA fillpant) - * - */ -public class PlayerNameHistoryLookup { - - /** - * The URL from Mojang API that provides the JSON String in response. - */ - private static final String LOOKUP_URL = "https://api.mojang.com/user/profiles/%s/names"; - - private static final Gson JSON_PARSER = new Gson(); - - /** - *

NOTE: Avoid running this method Synchronously with the main - * thread!It blocks while attempting to get a response from Mojang servers! - *

- * - * @param player The UUID of the player to be looked up. - * @return Returns an array of {@link PreviousPlayerNameEntry} objects, or - * null if the response couldn't be interpreted. - * @throws IOException {@link #getPlayerPreviousNames(String)} - */ - public static PreviousPlayerNameEntry[] getPlayerPreviousNames(UUID player) throws IOException { - return getPlayerPreviousNames(player.toString()); - } - - /** - *

NOTE: Avoid running this method Synchronously with the main - * thread! It blocks while attempting to get a response from Mojang servers! - *

- * Alternative method accepting an {@link OfflinePlayer} (and therefore - * {@link Player}) objects as parameter. - * - * @param uuid The UUID String to lookup - * @return Returns an array of {@link PreviousPlayerNameEntry} objects, or - * null if the response couldn't be interpreted. - * @throws IOException {@link #getRawJsonResponse(String)} - */ - public static PreviousPlayerNameEntry[] getPlayerPreviousNames(String uuid) throws IOException { - if (uuid == null || uuid.isEmpty()) return null; - uuid = uuid.replace("-", ""); - String response = getRawJsonResponse(new URL(String.format(LOOKUP_URL, uuid))); - PreviousPlayerNameEntry[] names = JSON_PARSER.fromJson(response, PreviousPlayerNameEntry[].class); - return names; - } - - /** - * This is a helper method used to read the response of Mojang's API - * webservers. - * - * @param u the URL to connect to - * @return a String with the data read. - * @throws IOException Inherited by {@link BufferedReader#readLine()}, - * {@link BufferedReader#close()}, {@link URL}, - * {@link HttpURLConnection#getInputStream()} - */ - private static String getRawJsonResponse(URL u) throws IOException { - HttpURLConnection con = (HttpURLConnection) u.openConnection(); - con.setDoInput(true); - con.setConnectTimeout(2000); - con.setReadTimeout(2000); - con.connect(); - BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); - String response = in.readLine(); - in.close(); - return response; - } - - /** - * This class represents the typical response expected by Mojang servers - * when requesting the name history of a player. - */ - public class PreviousPlayerNameEntry { - private String name; - @SerializedName("changedToAt") - private long changeTime; - - /** - * Gets the player name of this entry. - * - * @return The name of the player. - */ - public String getPlayerName() { - return name; - } - - /** - * Get the time of change of the name. - *
- * Note: This will return 0 if the name is the original (initial) - * name of the player! Make sure you check if it is 0 before handling! - *
- * Parsing 0 to a Date will result in the date "01/01/1970".
- * - * @return a timestamp in miliseconds that you can turn into a date or - * handle however you want :) - */ - public long getChangeTime() { - return changeTime; - } - - /** - * Check if this name is the name used to register the account (the - * initial/original name) - * - * @return a boolean, true if it is the the very first name of the - * player, otherwise false. - */ - public boolean isPlayersInitialName() { - return getChangeTime() == 0; - } - - @Override - public String toString() { - return "Name: " + name + " Date of change: " + new Date(changeTime).toString(); - } - } - - public static void main(String[] args) throws IOException { - System.out.println(Arrays.toString(getPlayerPreviousNames("a18d9b2c-e18f-4933-9e15-36452bc36857"))); - } - -} diff --git a/src/main/java/fr/pandacube/util/orm/SQLWhereIn.java b/src/main/java/fr/pandacube/util/orm/SQLWhereIn.java new file mode 100644 index 0000000..b541493 --- /dev/null +++ b/src/main/java/fr/pandacube/util/orm/SQLWhereIn.java @@ -0,0 +1,34 @@ +package fr.pandacube.util.orm; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.javatuples.Pair; + +public class SQLWhereIn extends SQLWhere { + + private SQLField field; + private Collection values; + + public SQLWhereIn(SQLField f, Collection v) { + if (f == null || v == null) + throw new IllegalArgumentException("All arguments for SQLWhereIn constructor can't be null"); + field = f; + values = v; + } + + @Override + public Pair> toSQL() throws ORMException { + List params = new ArrayList<>(); + for (Object v : values) + SQLElement.addValueToSQLObjectList(params, field, v); + + char[] questions = new char[values.size() == 0 ? 0 : (values.size() * 2 - 1)]; + for (int i = 0; i < questions.length; i++) + questions[i] = i % 2 == 0 ? '?' : ','; + + return new Pair<>("`" + field.getName() + "` IN (" + new String(questions) + ") ", params); + } + +}