From 8534cf91e299d44facb3c1d17ff82868814e5eee Mon Sep 17 00:00:00 2001 From: asofold Date: Mon, 3 Sep 2012 05:03:28 +0200 Subject: [PATCH] Generic rage. --- .../checks/chat/analysis/ds/PrefixTree.java | 68 +++++++++++-------- .../chat/analysis/ds/SimplePrefixTree.java | 39 +++++++++++ .../chat/analysis/engine/CompressedChars.java | 16 ++--- 3 files changed, 83 insertions(+), 40 deletions(-) create mode 100644 src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/SimplePrefixTree.java diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/PrefixTree.java b/src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/PrefixTree.java index 97d65092..153b96c4 100644 --- a/src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/PrefixTree.java +++ b/src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/PrefixTree.java @@ -5,6 +5,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.PrefixTree.LookupEntry; 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 * */ -public class PrefixTree>{ +public class PrefixTree, L extends LookupEntry>{ public static class Node{ public boolean isEnd = false; @@ -33,7 +34,7 @@ public class PrefixTree>{ if (node != null) return node; else if (factory == null) return null; else{ - node = factory.getNewNode(); + node = factory.newNode(); children.put(key, node); return node; } @@ -41,7 +42,7 @@ public class PrefixTree>{ } public static interface NodeFactory>{ - public N getNewNode(); + public N newNode(); } public static class LookupEntry>{ @@ -62,28 +63,20 @@ public class PrefixTree>{ } } - protected final NodeFactory factory; + public static interface LookupEntryFactory, L extends LookupEntry>{ + public L newLookupEntry(N node , N insertion, int depth, boolean hasPrefix); + } + + protected final NodeFactory nodeFactory; + + protected final LookupEntryFactory resultFactory; protected N root; - public PrefixTree(final Class clazz){ - this(new NodeFactory() { - @Override - public N getNewNode() { - try { - return clazz.newInstance(); - } catch (InstantiationException e) { - return null; - } catch (IllegalAccessException e) { - return null; - } - } - }); - } - - public PrefixTree(NodeFactory factory){ - this.factory = factory; - this.root = factory.getNewNode(); + public PrefixTree(NodeFactory nodeFactory, LookupEntryFactory resultFactory){ + this.nodeFactory = nodeFactory; + this.root = nodeFactory.newNode(); + this.resultFactory = resultFactory; } public LookupEntry lookup(K[] keys, final boolean create){ @@ -91,13 +84,12 @@ public class PrefixTree>{ } @SuppressWarnings("unchecked") - public LookupEntry lookup(final List keys, final boolean create){ + public L lookup(final List keys, final boolean create){ N insertion = root; - N node = null; int depth = 0; N current = root; boolean hasPrefix = false; - final NodeFactory factory = (NodeFactory) (create ? this.factory : null); + final NodeFactory factory = (NodeFactory) (create ? this.nodeFactory : null); for (final K key : keys){ final N child = (N) current.getChild(key, null); if (child == null){ @@ -108,12 +100,13 @@ public class PrefixTree>{ } } else{ - // Node already exists, set as insertion point. + // A node already exists, set as insertion point. insertion = current = child; depth ++; if (child.isEnd) hasPrefix = true; } } + N node = null; if (create){ node = current; current.isEnd = true; @@ -121,11 +114,30 @@ public class PrefixTree>{ else if (depth == keys.size()){ node = current; } - return new LookupEntry(node, insertion, depth, hasPrefix); + return resultFactory.newLookupEntry(node, insertion, depth, hasPrefix); } public void clear() { - root = factory.getNewNode(); + root = nodeFactory.newNode(); // TODO: maybe more unlinking ? } + + /** + * Factory method for a simple tree. + * @param keyType + * @return + */ + public static PrefixTree, LookupEntry>> newPrefixTree(){ + return new PrefixTree, LookupEntry>>(new NodeFactory>(){ + @Override + public final Node newNode() { + return new Node(); + } + }, new LookupEntryFactory, LookupEntry>>() { + @Override + public LookupEntry> newLookupEntry(Node node, Node insertion, int depth, boolean hasPrefix) { + return new LookupEntry>(node, insertion, depth, hasPrefix); + } + }); + } } diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/SimplePrefixTree.java b/src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/SimplePrefixTree.java new file mode 100644 index 00000000..f58293e6 --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/chat/analysis/ds/SimplePrefixTree.java @@ -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. + *
+ * Interesting: ctrl-shift-o (eclipse) is not idempotent. + * @author mc_dev + * + * @param + */ +public class SimplePrefixTree extends PrefixTree, SimpleLookupEntry> { + + public static class SimpleLookupEntry extends LookupEntry>{ + public SimpleLookupEntry(Node node, Node insertion, int depth, boolean hasPrefix) { + super(node, insertion, depth, hasPrefix); + } + } + + public SimplePrefixTree() { + super(new NodeFactory>(){ + @Override + public Node newNode() { + return new Node(); + } + }, new LookupEntryFactory, SimpleLookupEntry>(){ + @Override + public SimpleLookupEntry newLookupEntry( + Node node, Node insertion, + int depth, boolean hasPrefix) { + return new SimpleLookupEntry(node, insertion, depth, hasPrefix); + } + }); + + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/analysis/engine/CompressedChars.java b/src/fr/neatmonster/nocheatplus/checks/chat/analysis/engine/CompressedChars.java index 5152fa44..ec03420b 100644 --- a/src/fr/neatmonster/nocheatplus/checks/chat/analysis/engine/CompressedChars.java +++ b/src/fr/neatmonster/nocheatplus/checks/chat/analysis/engine/CompressedChars.java @@ -6,20 +6,12 @@ import java.util.List; import fr.neatmonster.nocheatplus.checks.chat.analysis.MessageLetterCount; 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.PrefixTree.LookupEntry; -import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.PrefixTree.Node; -import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.PrefixTree.NodeFactory; +import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.SimplePrefixTree; +import fr.neatmonster.nocheatplus.checks.chat.analysis.ds.SimplePrefixTree.SimpleLookupEntry; public class CompressedChars extends AbstractWordProcessor{ - protected final PrefixTree> tree = new PrefixTree>( - new NodeFactory>() { - @Override - public Node getNewNode() { - return new Node(); - } - }); + protected final SimplePrefixTree tree = new SimplePrefixTree(); protected final int maxAdd; @@ -72,7 +64,7 @@ public class CompressedChars extends AbstractWordProcessor{ private float getScore(List chars) { final int len = chars.size(); - LookupEntry> entry = tree.lookup(chars, true); + SimpleLookupEntry entry = tree.lookup(chars, true); float score = (float) (entry.depth*entry.depth) / (float) (len*len) ; if (entry.depth == chars.size()){ score += 0.2;