Updated to 2.1.5 (not too much manual changes).

This commit is contained in:
CoderMarido 2018-09-11 20:48:19 +02:00
parent e53a078364
commit 42b5665214
10 changed files with 291 additions and 305 deletions

View File

@ -40,6 +40,9 @@ import nl.marido.deluxeheads.economy.ItemEconomy;
import nl.marido.deluxeheads.economy.NoEconomy;
import nl.marido.deluxeheads.economy.PlayerPointsEconomy;
import nl.marido.deluxeheads.economy.VaultEconomy;
import nl.marido.deluxeheads.handlers.HeadNamer;
import nl.marido.deluxeheads.handlers.LegacyIDs;
import nl.marido.deluxeheads.handlers.UpdateChecker;
import nl.marido.deluxeheads.menu.ui.InventoryMenu;
import nl.marido.deluxeheads.oldmenu.ClickInventory;
import nl.marido.deluxeheads.util.Clock;
@ -110,12 +113,12 @@ public class DeluxeHeads extends JavaPlugin implements Listener {
String currentVersion = UpdateChecker.getCurrentVersion();
String latestVersion = UpdateChecker.getLatestVersion();
if (!UpdateChecker.isNewerVersion(latestVersion)) {
String newversion = Lang.Updater.newVersion().getSingle();
String newversion = Lang.Updater.newVersion().toString();
newversion = newversion.replaceAll("%version%", currentVersion);
severe(newversion);
return;
}
String oldversion = Lang.Updater.oldVersion().getSingle();
String oldversion = Lang.Updater.oldVersion().toString();
oldversion = oldversion.replaceAll("%version%", currentVersion);
warning(oldversion);
} catch (IOException e) {

View File

@ -1,296 +0,0 @@
package nl.marido.deluxeheads;
import java.util.*;
import nl.marido.deluxeheads.cache.CacheHead;
import nl.marido.deluxeheads.util.Checks;
public final class Search {
private Query query;
private Query reusableQuery;
private double threshold;
private int[][] editDis;
private int editDisDim1;
private int editDisDim2;
private List<Substring> substrings = new ArrayList<>();
private Search(String query, double threshold) {
this.query = new Query(query, toWords(query));
this.substrings = new ArrayList<>();
this.reusableQuery = new Query("", null);
this.threshold = threshold;
getReusableArray(query.length() + 1, 38);
}
private int[][] getReusableArray(int dim1, int dim2) {
if(dim1 <= editDisDim1 && dim2 <= editDisDim2)
return editDis;
dim1 = Math.max(dim1, editDisDim1);
dim2 = Math.max(dim2, editDisDim2);
editDis = new int[dim1][dim2];
editDisDim1 = dim1;
editDisDim2 = dim2;
return editDis;
}
private void appendSubstring(int index, String string, int start, int end) {
if(index < substrings.size()) {
substrings.get(index).reuse(string, start, end);
} else {
substrings.add(new Substring(string, start, end));
}
}
public List<Substring> toWords(String string) {
int len = string.length();
int wordCount = 0;
int lastSplit = 0;
boolean inWord = false;
for(int index = 0; index < len; ++index) {
char ch = string.charAt(index);
if(ch == ' ') {
if(inWord) {
appendSubstring(wordCount, string, lastSplit, index);
wordCount += 1;
lastSplit = index + 1;
}
inWord = false;
} else {
inWord = true;
}
}
if(inWord) {
appendSubstring(wordCount, string, lastSplit, len);
wordCount += 1;
}
return substrings.subList(0, wordCount);
}
public Query reuseQuery(String string) {
return reusableQuery.reuse(string, toWords(string));
}
public List<CacheHead> checkAll(Iterable<CacheHead> heads) {
List<Match> matches = new ArrayList<>();
for(CacheHead head : heads) {
double relevance = calculateRelevance(query, head);
if(relevance <= threshold)
continue;
matches.add(new Match(head, relevance));
}
Collections.sort(matches);
List<CacheHead> results = new ArrayList<>();
for(Match match : matches) {
results.add(match.subject);
}
return results;
}
private double calculateRelevance(Query query, CacheHead head) {
double relevance = calculateRelevance(query, reuseQuery(head.getName()));
for(String tag : head.getTags()) {
relevance = Math.max(relevance, 0.8 * calculateRelevance(query, reuseQuery(tag)));
}
return relevance;
}
private double calculateRelevance(Query query, Query subject) {
double similarity = calcSimilarity(query.string, subject.string);
double wordSimilarity = 0d;
double aggregate = 0d;
int count = 0;
for(Substring queryWord : query.words) {
double querySimilarity = 0d;
for(Substring subjectWord : subject.words) {
querySimilarity = Math.max(querySimilarity, calcSimilarity(queryWord, subjectWord));
}
aggregate += querySimilarity;
count += 1;
wordSimilarity = Math.max(wordSimilarity, querySimilarity);
}
if(count > 0) {
wordSimilarity = 0.9d * wordSimilarity + 0.1d * (aggregate / count);
}
return Math.max(similarity, wordSimilarity);
}
private double calcSimilarity(Substring query, Substring subject) {
int len1 = query.length();
int len2 = subject.length();
// len1+1, len2+1, because finally return dp[len1][len2]
int[][] dp = getReusableArray(len1 + 1, len2 + 1);
for (int i = 0; i <= len1; i++) {
dp[i][0] = i;
}
for (int j = 0; j <= len2; j++) {
dp[0][j] = j;
}
//iterate though, and check last char
for (int i = 0; i < len1; i++) {
char c1 = query.charAt(i);
for (int j = 0; j < len2; j++) {
char c2 = subject.charAt(j);
//if last two chars equal
if (c1 == c2) {
//update dp value for +1 length
dp[i + 1][j + 1] = dp[i][j];
} else {
int replace = dp[i][j] + 1;
int insert = dp[i][j + 1] + 1;
int delete = dp[i + 1][j] + 1;
int min = replace > insert ? insert : replace;
min = delete > min ? min : delete;
dp[i + 1][j + 1] = min;
}
}
}
int editDistance = dp[len1][len2];
if(editDistance == 0)
return 1;
return 0.75d * (double) (query.length() - editDistance) / (double) query.length();
}
private final static class Match implements Comparable<Match> {
public final CacheHead subject;
public final double relevance;
private Match(CacheHead subject, double relevance) {
this.subject = subject;
this.relevance = relevance;
}
@Override
public int compareTo(Match other) {
return Double.compare(other.relevance, relevance);
}
}
private final class Query {
public Substring string;
public List<Substring> words;
public Query(String string, List<Substring> words) {
this.string = new Substring(string);
this.words = words;
}
public Query reuse(String string, List<Substring> words) {
this.string.reuse(string);
this.words = words;
return this;
}
}
private static class Substring {
public String string;
public int start;
public int end;
public Substring(String string) {
this(string, 0, string.length());
}
public Substring(String string, int start, int end) {
reuse(string, start, end);
}
public Substring reuse(String string) {
return reuse(string, 0, string.length());
}
public Substring reuse(String string, int start, int end) {
Checks.ensureNonNull(string, "string");
this.string = string;
this.moveTo(start, end);
return this;
}
public void moveTo(int start, int end) {
Checks.ensureTrue(start >= 0, "start must be >= 0");
Checks.ensureTrue(end >= start, "end must be >= start");
Checks.ensureTrue(end <= string.length(), "end must be <= to the length of string");
this.start = start;
this.end = end;
}
public char charAt(int index) {
if(index < 0)
throw new IndexOutOfBoundsException("index cannot be negative");
if(index >= length())
throw new IndexOutOfBoundsException("index must be less than the strings length");
char ch = string.charAt(start + index);
return (char) (ch >= 'A' && ch <= 'Z' ? ch + ('a' - 'A') : ch);
}
public int length() {
return end - start;
}
@Override
public String toString() {
return string.substring(start, end);
}
}
/**
* Search over the list of heads and find all heads with a relevance above a certain threshold.
* Will simplify the query string in an attempt to improve matches.
*
* @param query The search term.
* @param heads The heads we are checking for matches.
* @param threshold The threshold relevance that a head must have to be matched.
* @return All heads sorted by relevance that have a relevance greater than the threshold.
*/
public static List<CacheHead> searchHeads(String query, Iterable<CacheHead> heads, double threshold) {
return new Search(query, threshold).checkAll(heads);
}
}

View File

@ -22,7 +22,7 @@ import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import nl.marido.deluxeheads.DeluxeHeads;
import nl.marido.deluxeheads.Search;
import nl.marido.deluxeheads.handlers.Search;
import nl.marido.deluxeheads.util.Checks;
import nl.marido.deluxeheads.util.IOUtils;

View File

@ -1,4 +1,4 @@
package nl.marido.deluxeheads;
package nl.marido.deluxeheads.handlers;
import java.util.ArrayList;
import java.util.List;
@ -27,6 +27,7 @@ import org.bukkit.plugin.RegisteredListener;
import com.mojang.authlib.GameProfile;
import net.sothatsit.blockstore.BlockStoreApi;
import nl.marido.deluxeheads.DeluxeHeads;
import nl.marido.deluxeheads.cache.CacheHead;
import nl.marido.deluxeheads.volatilecode.ItemNBT;
import nl.marido.deluxeheads.volatilecode.Items;

View File

@ -1,4 +1,4 @@
package nl.marido.deluxeheads;
package nl.marido.deluxeheads.handlers;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@ -14,6 +14,7 @@ import java.util.Map;
import org.bukkit.Material;
import nl.marido.deluxeheads.DeluxeHeads;
import nl.marido.deluxeheads.util.Checks;
public class LegacyIDs {

View File

@ -1,10 +1,11 @@
package nl.marido.deluxeheads;
package nl.marido.deluxeheads.handlers;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.scheduler.BukkitRunnable;
import nl.marido.deluxeheads.DeluxeHeads;
import nl.marido.deluxeheads.api.DeluxeHeadsAPI.Head;
public class LiveHead {

View File

@ -0,0 +1,274 @@
package nl.marido.deluxeheads.handlers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import nl.marido.deluxeheads.cache.CacheHead;
import nl.marido.deluxeheads.util.Checks;
public final class Search {
private Query query;
private Query reusableQuery;
private double threshold;
private int[][] editDis;
private int editDisDim1;
private int editDisDim2;
private List<Substring> substrings = new ArrayList<>();
private Search(String query, double threshold) {
this.query = new Query(query, toWords(query));
this.substrings = new ArrayList<>();
this.reusableQuery = new Query("", null);
this.threshold = threshold;
getReusableArray(query.length() + 1, 38);
}
private int[][] getReusableArray(int dim1, int dim2) {
if (dim1 <= editDisDim1 && dim2 <= editDisDim2)
return editDis;
dim1 = Math.max(dim1, editDisDim1);
dim2 = Math.max(dim2, editDisDim2);
editDis = new int[dim1][dim2];
editDisDim1 = dim1;
editDisDim2 = dim2;
return editDis;
}
private void appendSubstring(int index, String string, int start, int end) {
if (index < substrings.size()) {
substrings.get(index).reuse(string, start, end);
} else {
substrings.add(new Substring(string, start, end));
}
}
public List<Substring> toWords(String string) {
int len = string.length();
int wordCount = 0;
int lastSplit = 0;
boolean inWord = false;
for (int index = 0; index < len; ++index) {
char ch = string.charAt(index);
if (ch == ' ') {
if (inWord) {
appendSubstring(wordCount, string, lastSplit, index);
wordCount += 1;
lastSplit = index + 1;
}
inWord = false;
} else {
inWord = true;
}
}
if (inWord) {
appendSubstring(wordCount, string, lastSplit, len);
wordCount += 1;
}
return substrings.subList(0, wordCount);
}
public Query reuseQuery(String string) {
return reusableQuery.reuse(string, toWords(string));
}
public List<CacheHead> checkAll(Iterable<CacheHead> heads) {
List<Match> matches = new ArrayList<>();
for (CacheHead head : heads) {
double relevance = calculateRelevance(query, head);
if (relevance <= threshold)
continue;
matches.add(new Match(head, relevance));
}
Collections.sort(matches);
List<CacheHead> results = new ArrayList<>();
for (Match match : matches) {
results.add(match.subject);
}
return results;
}
private double calculateRelevance(Query query, CacheHead head) {
double relevance = calculateRelevance(query, reuseQuery(head.getName()));
for (String tag : head.getTags()) {
relevance = Math.max(relevance, 0.8 * calculateRelevance(query, reuseQuery(tag)));
}
return relevance;
}
private double calculateRelevance(Query query, Query subject) {
double similarity = calcSimilarity(query.string, subject.string);
double wordSimilarity = 0d;
double aggregate = 0d;
int count = 0;
for (Substring queryWord : query.words) {
double querySimilarity = 0d;
for (Substring subjectWord : subject.words) {
querySimilarity = Math.max(querySimilarity, calcSimilarity(queryWord, subjectWord));
}
aggregate += querySimilarity;
count += 1;
wordSimilarity = Math.max(wordSimilarity, querySimilarity);
}
if (count > 0) {
wordSimilarity = 0.9d * wordSimilarity + 0.1d * (aggregate / count);
}
return Math.max(similarity, wordSimilarity);
}
private double calcSimilarity(Substring query, Substring subject) {
int len1 = query.length();
int len2 = subject.length();
int[][] dp = getReusableArray(len1 + 1, len2 + 1);
for (int i = 0; i <= len1; i++) {
dp[i][0] = i;
}
for (int j = 0; j <= len2; j++) {
dp[0][j] = j;
}
for (int i = 0; i < len1; i++) {
char c1 = query.charAt(i);
for (int j = 0; j < len2; j++) {
char c2 = subject.charAt(j);
if (c1 == c2) {
dp[i + 1][j + 1] = dp[i][j];
} else {
int replace = dp[i][j] + 1;
int insert = dp[i][j + 1] + 1;
int delete = dp[i + 1][j] + 1;
int min = replace > insert ? insert : replace;
min = delete > min ? min : delete;
dp[i + 1][j + 1] = min;
}
}
}
int editDistance = dp[len1][len2];
if (editDistance == 0)
return 1;
return 0.75d * (double) (query.length() - editDistance) / (double) query.length();
}
private final static class Match implements Comparable<Match> {
public final CacheHead subject;
public final double relevance;
private Match(CacheHead subject, double relevance) {
this.subject = subject;
this.relevance = relevance;
}
@Override
public int compareTo(Match other) {
return Double.compare(other.relevance, relevance);
}
}
private final class Query {
public Substring string;
public List<Substring> words;
public Query(String string, List<Substring> words) {
this.string = new Substring(string);
this.words = words;
}
public Query reuse(String string, List<Substring> words) {
this.string.reuse(string);
this.words = words;
return this;
}
}
private static class Substring {
public String string;
public int start;
public int end;
public Substring(String string) {
this(string, 0, string.length());
}
public Substring(String string, int start, int end) {
reuse(string, start, end);
}
public Substring reuse(String string) {
return reuse(string, 0, string.length());
}
public Substring reuse(String string, int start, int end) {
Checks.ensureNonNull(string, "string");
this.string = string;
this.moveTo(start, end);
return this;
}
public void moveTo(int start, int end) {
Checks.ensureTrue(start >= 0, "start must be >= 0");
Checks.ensureTrue(end >= start, "end must be >= start");
Checks.ensureTrue(end <= string.length(), "end must be <= to the length of string");
this.start = start;
this.end = end;
}
public char charAt(int index) {
if (index < 0)
throw new IndexOutOfBoundsException("index cannot be negative");
if (index >= length())
throw new IndexOutOfBoundsException("index must be less than the strings length");
char ch = string.charAt(start + index);
return (char) (ch >= 'A' && ch <= 'Z' ? ch + ('a' - 'A') : ch);
}
public int length() {
return end - start;
}
@Override
public String toString() {
return string.substring(start, end);
}
}
/**
* Search over the list of heads and find all heads with a relevance above a certain threshold.
* Will simplify the query string in an attempt to improve matches.
*
* @param query The search term.
* @param heads The heads we are checking for matches.
* @param threshold The threshold relevance that a head must have to be matched.
* @return All heads sorted by relevance that have a relevance greater than the threshold.
*/
public static List<CacheHead> searchHeads(String query, Iterable<CacheHead> heads, double threshold) {
return new Search(query, threshold).checkAll(heads);
}
}

View File

@ -1,4 +1,4 @@
package nl.marido.deluxeheads;
package nl.marido.deluxeheads.handlers;
import java.io.BufferedReader;
import java.io.IOException;
@ -6,9 +6,11 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import nl.marido.deluxeheads.DeluxeHeads;
public class UpdateChecker {
private static final String versionURL = "https://api.spigotmc.org/legacy/update.php?resource=13402";
private static String versionURL = "https://api.spigotmc.org/legacy/update.php?resource=13402";
public static String getCurrentVersion() {
return DeluxeHeads.getInstance().getDescription().getVersion();

View File

@ -2,7 +2,7 @@ main: nl.marido.deluxeheads.DeluxeHeads
author: Marido
name: DeluxeHeads
description: Enhance your server with over 17,000 awesome unique heads with amazing features.
version: 2.1.4
version: 2.1.5
api-version: 1.13
softdepend: [Vault, PlayerPoints, BlockStore]
loadbefore: [DeluxeMenus]