2016-06-02 20:14:09 +02:00
|
|
|
/*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2013-01-20 04:18:08 +01:00
|
|
|
package fr.neatmonster.nocheatplus.utilities;
|
|
|
|
|
|
|
|
import java.text.DecimalFormat;
|
|
|
|
import java.text.DecimalFormatSymbols;
|
[BLEEDING][BREAKING][INSTABLE] Swiftly throw in permission caching.
Benefits:
* Improves performance, where permission lookup has major impact, with
timeout based lookup, static permissions (skip permission check
entirely), and world/offline based invalidation. (Once fully
implemented.)
* Hopefully more efficient: use Bukkit Permission for faster defaults.
* (Allows control over how which permission is to be
updated/invalidated, which is useful per se.)
Risks:
* Complex changes yield bugs.
* Other plugins depending on NCP might break.
* Cache incoherence might happen (permissions are changed dynamically +-
unintended malconfiguration, or in case of bugs).
* (Endless loops certainly have all been fixed.)
Breaking:
* Lots of more or less internal API has been changed or removed: Check,
CheckType, CheckUtils, TickTask, ...
* Permission checking behavior has been altered.
Rough points:
* Implement a permission cache within PlayerData.
* Remove the player tasks and permission updates in favour of handling
those within DataManager and PlayerData.
* Adjust everything else to it (partly TBD).
* Updating sets of permissions (e.g. for CHAT) is done more lazily now,
i.e. one per 10 ticks). An actual permission check would still yield an
update next tick (asynchronous).
* Fixed/extended random spots (DualCollection, MiniListener registration
support, StringUtil).
Missing:
* Basic implementation
* Cleanup after logout (stages: 1. non-essential like permissions,
2. unrecoverable like set-back location, 3. complete data removal).
* Coverage
* Might have missed spots.
* NoCheatPlus.nameSetPerms should be replaced by caching + default
config for world-wise updating.
* Command permissions are always checked. At least for players,
cache based lookup should get implemented.
* More unit tests.
* Extended configurability: Per-world settings/policies.
* Efficiency
* Not all parts of the implementation are 100%/optimal yet.
2018-01-28 18:52:51 +01:00
|
|
|
import java.util.ArrayList;
|
2015-11-15 05:27:46 +01:00
|
|
|
import java.util.Arrays;
|
2013-01-20 04:18:08 +01:00
|
|
|
import java.util.Collection;
|
2016-03-03 20:11:46 +01:00
|
|
|
import java.util.Iterator;
|
2013-02-20 21:18:16 +01:00
|
|
|
import java.util.List;
|
2013-01-20 04:18:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* String utility methods (working with or returning strings).
|
[BLEEDING][BREAKING][INSTABLE] Swiftly throw in permission caching.
Benefits:
* Improves performance, where permission lookup has major impact, with
timeout based lookup, static permissions (skip permission check
entirely), and world/offline based invalidation. (Once fully
implemented.)
* Hopefully more efficient: use Bukkit Permission for faster defaults.
* (Allows control over how which permission is to be
updated/invalidated, which is useful per se.)
Risks:
* Complex changes yield bugs.
* Other plugins depending on NCP might break.
* Cache incoherence might happen (permissions are changed dynamically +-
unintended malconfiguration, or in case of bugs).
* (Endless loops certainly have all been fixed.)
Breaking:
* Lots of more or less internal API has been changed or removed: Check,
CheckType, CheckUtils, TickTask, ...
* Permission checking behavior has been altered.
Rough points:
* Implement a permission cache within PlayerData.
* Remove the player tasks and permission updates in favour of handling
those within DataManager and PlayerData.
* Adjust everything else to it (partly TBD).
* Updating sets of permissions (e.g. for CHAT) is done more lazily now,
i.e. one per 10 ticks). An actual permission check would still yield an
update next tick (asynchronous).
* Fixed/extended random spots (DualCollection, MiniListener registration
support, StringUtil).
Missing:
* Basic implementation
* Cleanup after logout (stages: 1. non-essential like permissions,
2. unrecoverable like set-back location, 3. complete data removal).
* Coverage
* Might have missed spots.
* NoCheatPlus.nameSetPerms should be replaced by caching + default
config for world-wise updating.
* Command permissions are always checked. At least for players,
cache based lookup should get implemented.
* More unit tests.
* Extended configurability: Per-world settings/policies.
* Efficiency
* Not all parts of the implementation are 100%/optimal yet.
2018-01-28 18:52:51 +01:00
|
|
|
* @author asofold
|
2013-01-20 04:18:08 +01:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
public class StringUtil {
|
2014-11-11 15:31:56 +01:00
|
|
|
|
|
|
|
/** Decimal format for "#.###" */
|
|
|
|
public static final DecimalFormat fdec3 = new DecimalFormat();
|
|
|
|
/** Decimal format for "#.#" */
|
|
|
|
public static final DecimalFormat fdec1 = new DecimalFormat();
|
|
|
|
|
|
|
|
static {
|
|
|
|
// 3 digits.
|
|
|
|
DecimalFormatSymbols sym = fdec3.getDecimalFormatSymbols();
|
|
|
|
sym.setDecimalSeparator('.');
|
|
|
|
fdec3.setDecimalFormatSymbols(sym);
|
|
|
|
fdec3.setMaximumFractionDigits(3);
|
|
|
|
fdec3.setMinimumIntegerDigits(1);
|
|
|
|
// 1 digit.
|
|
|
|
sym = fdec1.getDecimalFormatSymbols();
|
|
|
|
sym.setDecimalSeparator('.');
|
|
|
|
fdec1.setDecimalFormatSymbols(sym);
|
|
|
|
fdec1.setMaximumFractionDigits(1);
|
|
|
|
fdec1.setMinimumIntegerDigits(1);
|
|
|
|
}
|
|
|
|
|
[BLEEDING][BREAKING][INSTABLE] Swiftly throw in permission caching.
Benefits:
* Improves performance, where permission lookup has major impact, with
timeout based lookup, static permissions (skip permission check
entirely), and world/offline based invalidation. (Once fully
implemented.)
* Hopefully more efficient: use Bukkit Permission for faster defaults.
* (Allows control over how which permission is to be
updated/invalidated, which is useful per se.)
Risks:
* Complex changes yield bugs.
* Other plugins depending on NCP might break.
* Cache incoherence might happen (permissions are changed dynamically +-
unintended malconfiguration, or in case of bugs).
* (Endless loops certainly have all been fixed.)
Breaking:
* Lots of more or less internal API has been changed or removed: Check,
CheckType, CheckUtils, TickTask, ...
* Permission checking behavior has been altered.
Rough points:
* Implement a permission cache within PlayerData.
* Remove the player tasks and permission updates in favour of handling
those within DataManager and PlayerData.
* Adjust everything else to it (partly TBD).
* Updating sets of permissions (e.g. for CHAT) is done more lazily now,
i.e. one per 10 ticks). An actual permission check would still yield an
update next tick (asynchronous).
* Fixed/extended random spots (DualCollection, MiniListener registration
support, StringUtil).
Missing:
* Basic implementation
* Cleanup after logout (stages: 1. non-essential like permissions,
2. unrecoverable like set-back location, 3. complete data removal).
* Coverage
* Might have missed spots.
* NoCheatPlus.nameSetPerms should be replaced by caching + default
config for world-wise updating.
* Command permissions are always checked. At least for players,
cache based lookup should get implemented.
* More unit tests.
* Extended configurability: Per-world settings/policies.
* Efficiency
* Not all parts of the implementation are 100%/optimal yet.
2018-01-28 18:52:51 +01:00
|
|
|
/**
|
|
|
|
* List by boxing.
|
|
|
|
* @param chars
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public static List<Character> characterList(char...chars) {
|
|
|
|
final List<Character> res = new ArrayList<Character>(chars.length);
|
|
|
|
for (int i = 0; i < chars.length; i++) {
|
|
|
|
res.add(chars[i]);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2015-11-15 05:27:46 +01:00
|
|
|
/**
|
|
|
|
* Join parts with link, starting from startIndex.
|
|
|
|
* @param input
|
|
|
|
* @param startIndex
|
|
|
|
* @param link
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public static <O extends Object> String join(O[] input, int startIndex, String link) {
|
|
|
|
return join(Arrays.copyOfRange(input, startIndex, input.length), link);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Join parts with link.
|
|
|
|
*
|
|
|
|
* @param input
|
|
|
|
* @param link
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public static <O extends Object> String join(O[] input, String link) {
|
|
|
|
return join(Arrays.asList(input), link);
|
|
|
|
}
|
|
|
|
|
2017-04-26 14:25:37 +02:00
|
|
|
public static String join(Iterator<? extends Object> iterator, String link) {
|
2016-03-03 20:11:46 +01:00
|
|
|
final StringBuilder builder = new StringBuilder(1024);
|
|
|
|
boolean first = true;
|
|
|
|
while (iterator.hasNext()) {
|
|
|
|
final Object obj = iterator.next();
|
|
|
|
if (!first) {
|
|
|
|
builder.append(link);
|
|
|
|
}
|
|
|
|
builder.append(obj.toString());
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
return builder.toString();
|
|
|
|
}
|
|
|
|
|
2014-11-11 15:31:56 +01:00
|
|
|
/**
|
|
|
|
* Join parts with link.
|
|
|
|
*
|
|
|
|
* @param input
|
|
|
|
* @param link
|
|
|
|
* @return
|
|
|
|
*/
|
2017-04-26 14:25:37 +02:00
|
|
|
public static String join(final Collection<? extends Object> input, final String link)
|
|
|
|
{
|
|
|
|
return join(input, link, new StringBuilder(Math.max(300, input.size() * 10))).toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add joined parts with link.
|
|
|
|
*
|
|
|
|
* @param input
|
|
|
|
* @param link
|
|
|
|
* @return The given StringBuilder for chaining.
|
|
|
|
*/
|
|
|
|
public static StringBuilder join(final Collection<? extends Object> input, final String link,
|
|
|
|
final StringBuilder builder)
|
2014-11-11 15:31:56 +01:00
|
|
|
{
|
|
|
|
boolean first = true;
|
|
|
|
for (final Object obj : input) {
|
2016-03-03 20:11:46 +01:00
|
|
|
if (!first) {
|
|
|
|
builder.append(link);
|
|
|
|
}
|
2014-11-11 15:31:56 +01:00
|
|
|
builder.append(obj.toString());
|
|
|
|
first = false;
|
|
|
|
}
|
2017-04-26 14:25:37 +02:00
|
|
|
return builder;
|
2014-11-11 15:31:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Split input by all characters given (convenience method).
|
[BLEEDING][BREAKING][INSTABLE] Swiftly throw in permission caching.
Benefits:
* Improves performance, where permission lookup has major impact, with
timeout based lookup, static permissions (skip permission check
entirely), and world/offline based invalidation. (Once fully
implemented.)
* Hopefully more efficient: use Bukkit Permission for faster defaults.
* (Allows control over how which permission is to be
updated/invalidated, which is useful per se.)
Risks:
* Complex changes yield bugs.
* Other plugins depending on NCP might break.
* Cache incoherence might happen (permissions are changed dynamically +-
unintended malconfiguration, or in case of bugs).
* (Endless loops certainly have all been fixed.)
Breaking:
* Lots of more or less internal API has been changed or removed: Check,
CheckType, CheckUtils, TickTask, ...
* Permission checking behavior has been altered.
Rough points:
* Implement a permission cache within PlayerData.
* Remove the player tasks and permission updates in favour of handling
those within DataManager and PlayerData.
* Adjust everything else to it (partly TBD).
* Updating sets of permissions (e.g. for CHAT) is done more lazily now,
i.e. one per 10 ticks). An actual permission check would still yield an
update next tick (asynchronous).
* Fixed/extended random spots (DualCollection, MiniListener registration
support, StringUtil).
Missing:
* Basic implementation
* Cleanup after logout (stages: 1. non-essential like permissions,
2. unrecoverable like set-back location, 3. complete data removal).
* Coverage
* Might have missed spots.
* NoCheatPlus.nameSetPerms should be replaced by caching + default
config for world-wise updating.
* Command permissions are always checked. At least for players,
cache based lookup should get implemented.
* More unit tests.
* Extended configurability: Per-world settings/policies.
* Efficiency
* Not all parts of the implementation are 100%/optimal yet.
2018-01-28 18:52:51 +01:00
|
|
|
*
|
2014-11-11 15:31:56 +01:00
|
|
|
* @param input
|
|
|
|
* @param chars
|
[BLEEDING][BREAKING][INSTABLE] Swiftly throw in permission caching.
Benefits:
* Improves performance, where permission lookup has major impact, with
timeout based lookup, static permissions (skip permission check
entirely), and world/offline based invalidation. (Once fully
implemented.)
* Hopefully more efficient: use Bukkit Permission for faster defaults.
* (Allows control over how which permission is to be
updated/invalidated, which is useful per se.)
Risks:
* Complex changes yield bugs.
* Other plugins depending on NCP might break.
* Cache incoherence might happen (permissions are changed dynamically +-
unintended malconfiguration, or in case of bugs).
* (Endless loops certainly have all been fixed.)
Breaking:
* Lots of more or less internal API has been changed or removed: Check,
CheckType, CheckUtils, TickTask, ...
* Permission checking behavior has been altered.
Rough points:
* Implement a permission cache within PlayerData.
* Remove the player tasks and permission updates in favour of handling
those within DataManager and PlayerData.
* Adjust everything else to it (partly TBD).
* Updating sets of permissions (e.g. for CHAT) is done more lazily now,
i.e. one per 10 ticks). An actual permission check would still yield an
update next tick (asynchronous).
* Fixed/extended random spots (DualCollection, MiniListener registration
support, StringUtil).
Missing:
* Basic implementation
* Cleanup after logout (stages: 1. non-essential like permissions,
2. unrecoverable like set-back location, 3. complete data removal).
* Coverage
* Might have missed spots.
* NoCheatPlus.nameSetPerms should be replaced by caching + default
config for world-wise updating.
* Command permissions are always checked. At least for players,
cache based lookup should get implemented.
* More unit tests.
* Extended configurability: Per-world settings/policies.
* Efficiency
* Not all parts of the implementation are 100%/optimal yet.
2018-01-28 18:52:51 +01:00
|
|
|
* @return An (Array)List with the results.
|
2014-11-11 15:31:56 +01:00
|
|
|
*/
|
|
|
|
public static List<String> split(String input, Character... chars){
|
[BLEEDING][BREAKING][INSTABLE] Swiftly throw in permission caching.
Benefits:
* Improves performance, where permission lookup has major impact, with
timeout based lookup, static permissions (skip permission check
entirely), and world/offline based invalidation. (Once fully
implemented.)
* Hopefully more efficient: use Bukkit Permission for faster defaults.
* (Allows control over how which permission is to be
updated/invalidated, which is useful per se.)
Risks:
* Complex changes yield bugs.
* Other plugins depending on NCP might break.
* Cache incoherence might happen (permissions are changed dynamically +-
unintended malconfiguration, or in case of bugs).
* (Endless loops certainly have all been fixed.)
Breaking:
* Lots of more or less internal API has been changed or removed: Check,
CheckType, CheckUtils, TickTask, ...
* Permission checking behavior has been altered.
Rough points:
* Implement a permission cache within PlayerData.
* Remove the player tasks and permission updates in favour of handling
those within DataManager and PlayerData.
* Adjust everything else to it (partly TBD).
* Updating sets of permissions (e.g. for CHAT) is done more lazily now,
i.e. one per 10 ticks). An actual permission check would still yield an
update next tick (asynchronous).
* Fixed/extended random spots (DualCollection, MiniListener registration
support, StringUtil).
Missing:
* Basic implementation
* Cleanup after logout (stages: 1. non-essential like permissions,
2. unrecoverable like set-back location, 3. complete data removal).
* Coverage
* Might have missed spots.
* NoCheatPlus.nameSetPerms should be replaced by caching + default
config for world-wise updating.
* Command permissions are always checked. At least for players,
cache based lookup should get implemented.
* More unit tests.
* Extended configurability: Per-world settings/policies.
* Efficiency
* Not all parts of the implementation are 100%/optimal yet.
2018-01-28 18:52:51 +01:00
|
|
|
return split(input, Arrays.asList(chars));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Split input by all characters given (convenience method).
|
|
|
|
*
|
|
|
|
* @param input
|
|
|
|
* @param chars
|
|
|
|
* @return An (Array)List with the results.
|
|
|
|
*/
|
|
|
|
public static List<String> splitChars(String input, char... chars){
|
|
|
|
return split(input, characterList(chars));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Split input by all characters given (convenience method).
|
|
|
|
*
|
|
|
|
* @param input
|
|
|
|
* @param chars
|
|
|
|
* @return An (Array)List with the results.
|
|
|
|
*/
|
|
|
|
public static List<String> split(String input, Collection<Character> chars){
|
|
|
|
// TODO: Construct one regular expression to do the entire job!?
|
|
|
|
List<String> out = new ArrayList<String>();
|
2014-11-11 15:31:56 +01:00
|
|
|
out.add(input);
|
[BLEEDING][BREAKING][INSTABLE] Swiftly throw in permission caching.
Benefits:
* Improves performance, where permission lookup has major impact, with
timeout based lookup, static permissions (skip permission check
entirely), and world/offline based invalidation. (Once fully
implemented.)
* Hopefully more efficient: use Bukkit Permission for faster defaults.
* (Allows control over how which permission is to be
updated/invalidated, which is useful per se.)
Risks:
* Complex changes yield bugs.
* Other plugins depending on NCP might break.
* Cache incoherence might happen (permissions are changed dynamically +-
unintended malconfiguration, or in case of bugs).
* (Endless loops certainly have all been fixed.)
Breaking:
* Lots of more or less internal API has been changed or removed: Check,
CheckType, CheckUtils, TickTask, ...
* Permission checking behavior has been altered.
Rough points:
* Implement a permission cache within PlayerData.
* Remove the player tasks and permission updates in favour of handling
those within DataManager and PlayerData.
* Adjust everything else to it (partly TBD).
* Updating sets of permissions (e.g. for CHAT) is done more lazily now,
i.e. one per 10 ticks). An actual permission check would still yield an
update next tick (asynchronous).
* Fixed/extended random spots (DualCollection, MiniListener registration
support, StringUtil).
Missing:
* Basic implementation
* Cleanup after logout (stages: 1. non-essential like permissions,
2. unrecoverable like set-back location, 3. complete data removal).
* Coverage
* Might have missed spots.
* NoCheatPlus.nameSetPerms should be replaced by caching + default
config for world-wise updating.
* Command permissions are always checked. At least for players,
cache based lookup should get implemented.
* More unit tests.
* Extended configurability: Per-world settings/policies.
* Efficiency
* Not all parts of the implementation are 100%/optimal yet.
2018-01-28 18:52:51 +01:00
|
|
|
List<String> queue = new ArrayList<String>();
|
2014-11-11 15:31:56 +01:00
|
|
|
for (final char c : chars){
|
|
|
|
String hex = Integer.toHexString((int) c);
|
|
|
|
switch (hex.length()){
|
2015-11-15 05:27:46 +01:00
|
|
|
case 1:
|
|
|
|
hex = "000" + hex;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
hex = "00" + hex;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
hex = "0" + hex;
|
2014-11-11 15:31:56 +01:00
|
|
|
}
|
|
|
|
for (final String s : out){
|
|
|
|
final String[] split = s.split("\\u" + hex);
|
|
|
|
for (final String _s : split){
|
|
|
|
queue.add(_s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
List<String> temp = out;
|
|
|
|
out = queue;
|
|
|
|
queue = temp;
|
|
|
|
queue.clear();
|
|
|
|
}
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
[BLEEDING][BREAKING][INSTABLE] Swiftly throw in permission caching.
Benefits:
* Improves performance, where permission lookup has major impact, with
timeout based lookup, static permissions (skip permission check
entirely), and world/offline based invalidation. (Once fully
implemented.)
* Hopefully more efficient: use Bukkit Permission for faster defaults.
* (Allows control over how which permission is to be
updated/invalidated, which is useful per se.)
Risks:
* Complex changes yield bugs.
* Other plugins depending on NCP might break.
* Cache incoherence might happen (permissions are changed dynamically +-
unintended malconfiguration, or in case of bugs).
* (Endless loops certainly have all been fixed.)
Breaking:
* Lots of more or less internal API has been changed or removed: Check,
CheckType, CheckUtils, TickTask, ...
* Permission checking behavior has been altered.
Rough points:
* Implement a permission cache within PlayerData.
* Remove the player tasks and permission updates in favour of handling
those within DataManager and PlayerData.
* Adjust everything else to it (partly TBD).
* Updating sets of permissions (e.g. for CHAT) is done more lazily now,
i.e. one per 10 ticks). An actual permission check would still yield an
update next tick (asynchronous).
* Fixed/extended random spots (DualCollection, MiniListener registration
support, StringUtil).
Missing:
* Basic implementation
* Cleanup after logout (stages: 1. non-essential like permissions,
2. unrecoverable like set-back location, 3. complete data removal).
* Coverage
* Might have missed spots.
* NoCheatPlus.nameSetPerms should be replaced by caching + default
config for world-wise updating.
* Command permissions are always checked. At least for players,
cache based lookup should get implemented.
* More unit tests.
* Extended configurability: Per-world settings/policies.
* Efficiency
* Not all parts of the implementation are 100%/optimal yet.
2018-01-28 18:52:51 +01:00
|
|
|
/**
|
|
|
|
* Add non empty strings to an output (Array)List.
|
|
|
|
*
|
|
|
|
* @param input
|
|
|
|
* @param trim
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public static List<String> getNonEmpty(final List<String> input, boolean trim) {
|
|
|
|
final List<String> output = new ArrayList<String>();
|
|
|
|
for (String x : input) {
|
|
|
|
if (trim) {
|
|
|
|
x = x.trim();
|
|
|
|
}
|
|
|
|
if (!x.isEmpty()) {
|
|
|
|
output.add(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-11-11 15:31:56 +01:00
|
|
|
/**
|
|
|
|
* Return if the two Strings are similar based on the given threshold.
|
|
|
|
*
|
|
|
|
* @param s
|
|
|
|
* the first String, must not be null
|
|
|
|
* @param t
|
|
|
|
* the second String, must not be null
|
|
|
|
* @param threshold
|
|
|
|
* the minimum value of the correlation coefficient
|
|
|
|
* @return result true if the two Strings are similar, false otherwise
|
|
|
|
*/
|
|
|
|
public static boolean isSimilar(final String s, final String t, final float threshold)
|
|
|
|
{
|
|
|
|
return 1.0f - (float) levenshteinDistance(s, t) / Math.max(1.0, Math.max(s.length(), t.length())) > threshold;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find the Levenshtein distance between two Strings.
|
|
|
|
*
|
|
|
|
* This is the number of changes needed to change one String into another,
|
|
|
|
* where each change is a single character modification (deletion, insertion or substitution).
|
|
|
|
*
|
|
|
|
* @param s
|
|
|
|
* the first String, must not be null
|
|
|
|
* @param t
|
|
|
|
* the second String, must not be null
|
|
|
|
* @return result distance
|
|
|
|
*/
|
|
|
|
public static int levenshteinDistance(CharSequence s, CharSequence t) {
|
|
|
|
if (s == null || t == null) throw new IllegalArgumentException("Strings must not be null");
|
|
|
|
|
|
|
|
int n = s.length();
|
|
|
|
int m = t.length();
|
|
|
|
|
|
|
|
if (n == 0) return m;
|
|
|
|
else if (m == 0) return n;
|
|
|
|
|
|
|
|
if (n > m) {
|
|
|
|
final CharSequence tmp = s;
|
|
|
|
s = t;
|
|
|
|
t = tmp;
|
|
|
|
n = m;
|
|
|
|
m = t.length();
|
|
|
|
}
|
|
|
|
|
|
|
|
int p[] = new int[n + 1];
|
|
|
|
int d[] = new int[n + 1];
|
|
|
|
int _d[];
|
|
|
|
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
|
|
|
|
char t_j;
|
|
|
|
|
|
|
|
int cost;
|
|
|
|
|
|
|
|
for (i = 0; i <= n; i++)
|
|
|
|
p[i] = i;
|
|
|
|
|
|
|
|
for (j = 1; j <= m; j++) {
|
|
|
|
t_j = t.charAt(j - 1);
|
|
|
|
d[0] = j;
|
|
|
|
|
|
|
|
for (i = 1; i <= n; i++) {
|
|
|
|
cost = s.charAt(i - 1) == t_j ? 0 : 1;
|
|
|
|
d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost);
|
|
|
|
}
|
|
|
|
|
|
|
|
_d = p;
|
|
|
|
p = d;
|
|
|
|
d = _d;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p[n];
|
|
|
|
}
|
2014-12-17 18:33:16 +01:00
|
|
|
|
2014-11-11 20:25:28 +01:00
|
|
|
/**
|
|
|
|
* Just return the stack trace as new-line-separated string.
|
|
|
|
* @param t
|
|
|
|
* @param header Add a header about the exception itself, if set to true.
|
2014-11-12 19:50:36 +01:00
|
|
|
* @param trim If to make the output more compact in case of repetitions.
|
2014-11-11 20:25:28 +01:00
|
|
|
* @return
|
|
|
|
*/
|
2014-11-12 19:50:36 +01:00
|
|
|
public static final String stackTraceToString(final Throwable t, final boolean header, final boolean trim) {
|
2014-11-11 20:25:28 +01:00
|
|
|
// TODO: Consider to use System.getProperty("line.separator").
|
2014-11-12 19:50:36 +01:00
|
|
|
// TODO: Consider to add a trimDepth argument, for repetition of a sequence of elements.
|
2014-11-11 20:25:28 +01:00
|
|
|
final StringBuilder b = new StringBuilder(325);
|
|
|
|
if (header) {
|
|
|
|
b.append(t.toString()); // TODO: Check.
|
|
|
|
b.append("\n");
|
|
|
|
}
|
|
|
|
final StackTraceElement[] elements = t.getStackTrace();
|
2014-11-12 19:50:36 +01:00
|
|
|
StackTraceElement last = null; // Assume this is faster than operating on the strings.
|
|
|
|
int repetition = 0;
|
2014-11-11 20:25:28 +01:00
|
|
|
for (int i = 0; i < elements.length; i++) {
|
2014-11-12 19:50:36 +01:00
|
|
|
final StackTraceElement element = elements[i];
|
|
|
|
if (trim) {
|
|
|
|
if (element.equals(last)) {
|
|
|
|
repetition += 1;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
if (repetition > 0) {
|
|
|
|
if (header) {
|
|
|
|
b.append("\t");
|
|
|
|
}
|
|
|
|
b.append("(... repeated " + repetition + " times.)\n");
|
|
|
|
repetition = 0;
|
|
|
|
}
|
|
|
|
last = element;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (header) {
|
|
|
|
b.append("\t");
|
|
|
|
}
|
|
|
|
b.append(element);
|
2014-11-11 20:25:28 +01:00
|
|
|
b.append("\n");
|
|
|
|
}
|
2014-11-12 19:50:36 +01:00
|
|
|
if (repetition > 0) {
|
|
|
|
if (header) {
|
|
|
|
b.append("\t");
|
|
|
|
}
|
|
|
|
b.append("(... repeated " + repetition + " times.)\n");
|
|
|
|
}
|
2014-11-11 20:25:28 +01:00
|
|
|
return b.toString();
|
|
|
|
}
|
2014-12-17 18:33:16 +01:00
|
|
|
|
2014-11-11 20:25:28 +01:00
|
|
|
/**
|
2014-11-12 19:50:36 +01:00
|
|
|
* Convenience method for stackTraceToString(t).
|
2014-11-11 20:25:28 +01:00
|
|
|
* @param t
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public static final String throwableToString(final Throwable t) {
|
2014-11-12 19:50:36 +01:00
|
|
|
return stackTraceToString(t, true, true);
|
2014-11-11 20:25:28 +01:00
|
|
|
}
|
2014-12-17 18:33:16 +01:00
|
|
|
|
2014-11-12 19:50:36 +01:00
|
|
|
/**
|
|
|
|
* Count number of needles left in a dart board.
|
|
|
|
* @param dartBoard
|
|
|
|
* @param needles
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public static final int count(final String dartBoard, final char needles) {
|
|
|
|
int n = 0;
|
|
|
|
int index = 0;
|
|
|
|
while (index != -1) {
|
|
|
|
index = dartBoard.indexOf(needles, index);
|
|
|
|
if (index != -1) {
|
|
|
|
n ++;
|
|
|
|
index ++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
}
|
2014-11-11 15:31:56 +01:00
|
|
|
|
2014-12-17 18:33:16 +01:00
|
|
|
/**
|
|
|
|
* Get a version of a String with all leading whitespace removed.
|
|
|
|
*
|
|
|
|
* @param input
|
|
|
|
* @return String with leading whitespace removed. Returns the original
|
|
|
|
* reference, if there is no leading whitespace.
|
|
|
|
*/
|
|
|
|
public static final String leftTrim(final String input) {
|
|
|
|
if (input == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
final int len = input.length();
|
|
|
|
int beginIndex = 0;
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
if (Character.isWhitespace(input.charAt(i))) {
|
|
|
|
++beginIndex;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (beginIndex > 0) {
|
|
|
|
if (beginIndex >= len) {
|
|
|
|
return "";
|
|
|
|
} else {
|
|
|
|
return input.substring(beginIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-25 19:40:31 +01:00
|
|
|
/**
|
|
|
|
* Format to maximally 3 digits after the comma, always show the sign,
|
|
|
|
* unless equal.
|
|
|
|
*
|
|
|
|
* @param current
|
|
|
|
* @param previous
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public static String formatDiff(final double current, final double previous) {
|
|
|
|
return current == previous ? "0" : ((current > previous ? "+" : "-") + fdec3.format(Math.abs(current - previous)));
|
|
|
|
}
|
|
|
|
|
[BLEEDING][BREAKING][INSTABLE] Swiftly throw in permission caching.
Benefits:
* Improves performance, where permission lookup has major impact, with
timeout based lookup, static permissions (skip permission check
entirely), and world/offline based invalidation. (Once fully
implemented.)
* Hopefully more efficient: use Bukkit Permission for faster defaults.
* (Allows control over how which permission is to be
updated/invalidated, which is useful per se.)
Risks:
* Complex changes yield bugs.
* Other plugins depending on NCP might break.
* Cache incoherence might happen (permissions are changed dynamically +-
unintended malconfiguration, or in case of bugs).
* (Endless loops certainly have all been fixed.)
Breaking:
* Lots of more or less internal API has been changed or removed: Check,
CheckType, CheckUtils, TickTask, ...
* Permission checking behavior has been altered.
Rough points:
* Implement a permission cache within PlayerData.
* Remove the player tasks and permission updates in favour of handling
those within DataManager and PlayerData.
* Adjust everything else to it (partly TBD).
* Updating sets of permissions (e.g. for CHAT) is done more lazily now,
i.e. one per 10 ticks). An actual permission check would still yield an
update next tick (asynchronous).
* Fixed/extended random spots (DualCollection, MiniListener registration
support, StringUtil).
Missing:
* Basic implementation
* Cleanup after logout (stages: 1. non-essential like permissions,
2. unrecoverable like set-back location, 3. complete data removal).
* Coverage
* Might have missed spots.
* NoCheatPlus.nameSetPerms should be replaced by caching + default
config for world-wise updating.
* Command permissions are always checked. At least for players,
cache based lookup should get implemented.
* More unit tests.
* Extended configurability: Per-world settings/policies.
* Efficiency
* Not all parts of the implementation are 100%/optimal yet.
2018-01-28 18:52:51 +01:00
|
|
|
public static boolean startsWithAnyOf(final String input, final String... startsWith) {
|
|
|
|
for (int i = 0; i < startsWith.length; i++) {
|
|
|
|
if (input.startsWith(startsWith[i])) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean endsWithAnyOf(final String input, final String... endsWith) {
|
|
|
|
for (int i = 0; i < endsWith.length; i++) {
|
|
|
|
if (input.endsWith(endsWith[i])) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-08-18 22:23:21 +02:00
|
|
|
public static String reverse(final String input) {
|
|
|
|
return new StringBuilder(input).reverse().toString();
|
|
|
|
}
|
|
|
|
|
2013-01-20 04:18:08 +01:00
|
|
|
}
|