mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-11-02 08:40:01 +01:00
Generic rage.
This commit is contained in:
parent
167717609c
commit
8534cf91e2
@ -5,6 +5,7 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.PrefixTree.LookupEntry;
|
||||||
import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.PrefixTree.Node;
|
import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.PrefixTree.Node;
|
||||||
|
|
||||||
|
|
||||||
@ -14,7 +15,7 @@ import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.PrefixTree.Node;
|
|||||||
* @author mc_dev
|
* @author mc_dev
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class PrefixTree<K, N extends Node<K>>{
|
public class PrefixTree<K, N extends Node<K>, L extends LookupEntry<K, N>>{
|
||||||
|
|
||||||
public static class Node<K>{
|
public static class Node<K>{
|
||||||
public boolean isEnd = false;
|
public boolean isEnd = false;
|
||||||
@ -33,7 +34,7 @@ public class PrefixTree<K, N extends Node<K>>{
|
|||||||
if (node != null) return node;
|
if (node != null) return node;
|
||||||
else if (factory == null) return null;
|
else if (factory == null) return null;
|
||||||
else{
|
else{
|
||||||
node = factory.getNewNode();
|
node = factory.newNode();
|
||||||
children.put(key, node);
|
children.put(key, node);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@ -41,7 +42,7 @@ public class PrefixTree<K, N extends Node<K>>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static interface NodeFactory<K, N extends Node<K>>{
|
public static interface NodeFactory<K, N extends Node<K>>{
|
||||||
public N getNewNode();
|
public N newNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LookupEntry<K, N extends Node<K>>{
|
public static class LookupEntry<K, N extends Node<K>>{
|
||||||
@ -62,28 +63,20 @@ public class PrefixTree<K, N extends Node<K>>{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final NodeFactory<K, N> factory;
|
public static interface LookupEntryFactory<K, N extends Node<K>, L extends LookupEntry<K, N>>{
|
||||||
|
public L newLookupEntry(N node , N insertion, int depth, boolean hasPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final NodeFactory<K, N> nodeFactory;
|
||||||
|
|
||||||
|
protected final LookupEntryFactory<K, N, L> resultFactory;
|
||||||
|
|
||||||
protected N root;
|
protected N root;
|
||||||
|
|
||||||
public PrefixTree(final Class<N> clazz){
|
public PrefixTree(NodeFactory<K, N> nodeFactory, LookupEntryFactory<K, N, L> resultFactory){
|
||||||
this(new NodeFactory<K, N>() {
|
this.nodeFactory = nodeFactory;
|
||||||
@Override
|
this.root = nodeFactory.newNode();
|
||||||
public N getNewNode() {
|
this.resultFactory = resultFactory;
|
||||||
try {
|
|
||||||
return clazz.newInstance();
|
|
||||||
} catch (InstantiationException e) {
|
|
||||||
return null;
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public PrefixTree(NodeFactory<K, N> factory){
|
|
||||||
this.factory = factory;
|
|
||||||
this.root = factory.getNewNode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LookupEntry<K, N> lookup(K[] keys, final boolean create){
|
public LookupEntry<K, N> lookup(K[] keys, final boolean create){
|
||||||
@ -91,13 +84,12 @@ public class PrefixTree<K, N extends Node<K>>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public LookupEntry<K, N> lookup(final List<K> keys, final boolean create){
|
public L lookup(final List<K> keys, final boolean create){
|
||||||
N insertion = root;
|
N insertion = root;
|
||||||
N node = null;
|
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
N current = root;
|
N current = root;
|
||||||
boolean hasPrefix = false;
|
boolean hasPrefix = false;
|
||||||
final NodeFactory<K, N> factory = (NodeFactory<K, N>) (create ? this.factory : null);
|
final NodeFactory<K, N> factory = (NodeFactory<K, N>) (create ? this.nodeFactory : null);
|
||||||
for (final K key : keys){
|
for (final K key : keys){
|
||||||
final N child = (N) current.getChild(key, null);
|
final N child = (N) current.getChild(key, null);
|
||||||
if (child == null){
|
if (child == null){
|
||||||
@ -108,12 +100,13 @@ public class PrefixTree<K, N extends Node<K>>{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
// Node already exists, set as insertion point.
|
// A node already exists, set as insertion point.
|
||||||
insertion = current = child;
|
insertion = current = child;
|
||||||
depth ++;
|
depth ++;
|
||||||
if (child.isEnd) hasPrefix = true;
|
if (child.isEnd) hasPrefix = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
N node = null;
|
||||||
if (create){
|
if (create){
|
||||||
node = current;
|
node = current;
|
||||||
current.isEnd = true;
|
current.isEnd = true;
|
||||||
@ -121,11 +114,30 @@ public class PrefixTree<K, N extends Node<K>>{
|
|||||||
else if (depth == keys.size()){
|
else if (depth == keys.size()){
|
||||||
node = current;
|
node = current;
|
||||||
}
|
}
|
||||||
return new LookupEntry<K, N>(node, insertion, depth, hasPrefix);
|
return resultFactory.newLookupEntry(node, insertion, depth, hasPrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
root = factory.getNewNode();
|
root = nodeFactory.newNode();
|
||||||
// TODO: maybe more unlinking ?
|
// TODO: maybe more unlinking ?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method for a simple tree.
|
||||||
|
* @param keyType
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <K> PrefixTree<K, Node<K>, LookupEntry<K, Node<K>>> newPrefixTree(){
|
||||||
|
return new PrefixTree<K, Node<K>, LookupEntry<K, Node<K>>>(new NodeFactory<K, Node<K>>(){
|
||||||
|
@Override
|
||||||
|
public final Node<K> newNode() {
|
||||||
|
return new Node<K>();
|
||||||
|
}
|
||||||
|
}, new LookupEntryFactory<K, Node<K>, LookupEntry<K,Node<K>>>() {
|
||||||
|
@Override
|
||||||
|
public LookupEntry<K, Node<K>> newLookupEntry(Node<K> node, Node<K> insertion, int depth, boolean hasPrefix) {
|
||||||
|
return new LookupEntry<K, PrefixTree.Node<K>>(node, insertion, depth, hasPrefix);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package fr.neatmonster.nocheatplus.checks.chat.analysis.ds;
|
||||||
|
|
||||||
|
import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.PrefixTree.LookupEntry;
|
||||||
|
import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.PrefixTree.Node;
|
||||||
|
import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.SimplePrefixTree.SimpleLookupEntry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple prefix tree, for one given key type.
|
||||||
|
* <hr>
|
||||||
|
* Interesting: ctrl-shift-o (eclipse) is not idempotent.
|
||||||
|
* @author mc_dev
|
||||||
|
*
|
||||||
|
* @param <K>
|
||||||
|
*/
|
||||||
|
public class SimplePrefixTree<K> extends PrefixTree<K, Node<K>, SimpleLookupEntry<K>> {
|
||||||
|
|
||||||
|
public static class SimpleLookupEntry<K> extends LookupEntry<K, Node<K>>{
|
||||||
|
public SimpleLookupEntry(Node<K> node, Node<K> insertion, int depth, boolean hasPrefix) {
|
||||||
|
super(node, insertion, depth, hasPrefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimplePrefixTree() {
|
||||||
|
super(new NodeFactory<K, Node<K>>(){
|
||||||
|
@Override
|
||||||
|
public Node<K> newNode() {
|
||||||
|
return new Node<K>();
|
||||||
|
}
|
||||||
|
}, new LookupEntryFactory<K, Node<K>, SimpleLookupEntry<K>>(){
|
||||||
|
@Override
|
||||||
|
public SimpleLookupEntry<K> newLookupEntry(
|
||||||
|
Node<K> node, Node<K> insertion,
|
||||||
|
int depth, boolean hasPrefix) {
|
||||||
|
return new SimpleLookupEntry<K>(node, insertion, depth, hasPrefix);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -6,20 +6,12 @@ import java.util.List;
|
|||||||
|
|
||||||
import fr.neatmonster.nocheatplus.checks.chat.analysis.MessageLetterCount;
|
import fr.neatmonster.nocheatplus.checks.chat.analysis.MessageLetterCount;
|
||||||
import fr.neatmonster.nocheatplus.checks.chat.analysis.WordLetterCount;
|
import fr.neatmonster.nocheatplus.checks.chat.analysis.WordLetterCount;
|
||||||
import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.PrefixTree;
|
import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.SimplePrefixTree;
|
||||||
import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.PrefixTree.LookupEntry;
|
import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.SimplePrefixTree.SimpleLookupEntry;
|
||||||
import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.PrefixTree.Node;
|
|
||||||
import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.PrefixTree.NodeFactory;
|
|
||||||
|
|
||||||
public class CompressedChars extends AbstractWordProcessor{
|
public class CompressedChars extends AbstractWordProcessor{
|
||||||
|
|
||||||
protected final PrefixTree<Character, Node<Character>> tree = new PrefixTree<Character, Node<Character>>(
|
protected final SimplePrefixTree<Character> tree = new SimplePrefixTree<Character>();
|
||||||
new NodeFactory<Character, Node<Character>>() {
|
|
||||||
@Override
|
|
||||||
public Node<Character> getNewNode() {
|
|
||||||
return new Node<Character>();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
protected final int maxAdd;
|
protected final int maxAdd;
|
||||||
|
|
||||||
@ -72,7 +64,7 @@ public class CompressedChars extends AbstractWordProcessor{
|
|||||||
|
|
||||||
private float getScore(List<Character> chars) {
|
private float getScore(List<Character> chars) {
|
||||||
final int len = chars.size();
|
final int len = chars.size();
|
||||||
LookupEntry<Character, Node<Character>> entry = tree.lookup(chars, true);
|
SimpleLookupEntry<Character> entry = tree.lookup(chars, true);
|
||||||
float score = (float) (entry.depth*entry.depth) / (float) (len*len) ;
|
float score = (float) (entry.depth*entry.depth) / (float) (len*len) ;
|
||||||
if (entry.depth == chars.size()){
|
if (entry.depth == chars.size()){
|
||||||
score += 0.2;
|
score += 0.2;
|
||||||
|
Loading…
Reference in New Issue
Block a user