Add SQLWhereIn and LevenshteinDistance algorithm

This commit is contained in:
Marc Baloup 2019-11-03 00:15:23 +01:00
parent 05d115cd19
commit bcb46b7cd5
3 changed files with 102 additions and 145 deletions

View File

@ -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<Character, Character> elementDistanceFunction;
private int[] prev, curr;
private int progress = 0;
public LevenshteinDistance(String initList, String finList, int addScore, int delScore, ToIntBiFunction<Character, Character> 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));
}
}
}

View File

@ -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).
* <br/>
* <a href="https://bukkit.org/threads/player-name-history-lookup.412679/">https
* ://bukkit.org/threads/player-name-history-lookup.412679/</a>
*
* @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();
/**
* <h1>NOTE: Avoid running this method <i>Synchronously</i> with the main
* thread!It blocks while attempting to get a response from Mojang servers!
* </h1>
*
* @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());
}
/**
* <h1>NOTE: Avoid running this method <i>Synchronously</i> with the main
* thread! It blocks while attempting to get a response from Mojang servers!
* </h1>
* 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.
* <br>
* <b>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!
* <br>
* Parsing 0 to a Date will result in the date "01/01/1970".</b>
*
* @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")));
}
}

View File

@ -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 <T> SQLWhereIn(SQLField<?, T> f, Collection<T> 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<String, List<Object>> toSQL() throws ORMException {
List<Object> 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);
}
}