Bladeren bron

Optim: compressed resolver

Febbweiss 8 jaren geleden
bovenliggende
commit
dbfa1892ee

+ 11 - 0
pom.xml

@@ -11,6 +11,17 @@
 			<artifactId>commons-cli</artifactId>
 			<version>1.4</version>
 		</dependency>
+		<dependency>
+		    <groupId>com.fasterxml.jackson.core</groupId>
+		    <artifactId>jackson-core</artifactId>
+		    <version>2.9.1</version>
+		</dependency>
+		<dependency>
+		    <groupId>com.fasterxml.jackson.core</groupId>
+		    <artifactId>jackson-databind</artifactId>
+		    <version>2.9.1</version>
+		</dependency>
+		
 		<!-- Unit testing -->
 		<dependency>
 			<groupId>junit</groupId>

+ 12 - 49
src/main/java/fr/pavnay/scrabble/DictionaryBuilder.java

@@ -3,14 +3,9 @@ package fr.pavnay.scrabble;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 public class DictionaryBuilder {
@@ -58,7 +53,7 @@ public class DictionaryBuilder {
 	public static Enigma generateEnigma(String language, int minLength, int maxLength) {
 		Resolver resolver;
 		try {
-			resolver = loadResolver(language);
+			resolver = ScrabbleUtils.loadResolver(language);
 		} catch (Exception e) {
 			e.printStackTrace();
 			return null;
@@ -66,51 +61,19 @@ public class DictionaryBuilder {
 		return resolver.generateEnigma(minLength, maxLength);
 	}
 
-	public static void generateResolver(String language) throws IOException {
-		File file = new File(
-				"C:/Users/viaduc105.smallbusiness/Documents/workspace-sts/SocialArena/resources/" + language);
-		if (!file.exists()) {
-			System.out.println("No dictionary for " + language);
-			return;
-		}
-		Resolver resolver = generateResolver(new Resolver(), file, 3, 7);
-		resolver.computeStatistics();
-
-		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
-				new File("C:/Users/viaduc105.smallbusiness/Documents/workspace-sts/SocialArena/resources/resolver/"
-						+ language)));
-		oos.writeObject(resolver);
-		oos.flush();
-		oos.close();
-	}
-
-	public static void loadResolvers() throws IOException, ClassNotFoundException {
-		List<String> languages = ScrabbleUtils.loadLanguages();
-		for (String language : languages) {
-			long t1 = System.currentTimeMillis();
-			loadResolver(language);
-			System.out.println("Resolver in " + language + " loaded in " + (System.currentTimeMillis() - t1) + "ms.");
-		}
-	}
 
-	private static Resolver loadResolver(String language)
-			throws FileNotFoundException, IOException, ClassNotFoundException {
-		Resolver resolver = (Resolver) resolvers.get(language);
-		if (resolver == null) {
-			long t1 = System.currentTimeMillis();
-			String path = DictionaryBuilder.class.getResource("/resolvers/" + language).getPath();
-			File file = new File(path);
-			if (!file.exists()) {
-				System.out.println("No resolver for " + language);
-				return null;
+	public static void main(String[] args) throws Exception {
+		for( String language : new String[] {"english", "french"} ) {
+			long avg = 0;
+			for( int i = 0; i < 100; i++) {
+				resolvers.clear();
+				long t1 = System.currentTimeMillis();
+				ScrabbleUtils.loadResolver(language);
+				long t2 = System.currentTimeMillis() - t1;
+				avg += t2;
 			}
-			ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
-			resolver = (Resolver) ois.readObject();
-			ois.close();
-
-			resolvers.put(language, resolver);
-			System.out.println("Resolver in " + language + " loaded in " + (System.currentTimeMillis() - t1) + "ms.");
+			System.out.println(language + " : " + (avg/100));
 		}
-		return resolver;
 	}
+	
 }

+ 3 - 6
src/main/java/fr/pavnay/scrabble/Main.java

@@ -1,9 +1,7 @@
 package fr.pavnay.scrabble;
 
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.ObjectOutputStream;
 import java.util.List;
 
 import org.apache.commons.cli.CommandLine;
@@ -70,16 +68,15 @@ public class Main {
 	    try {
 		    Resolver resolver = DictionaryBuilder.generateResolver(new Resolver(), file, min, max);
 		    resolver.computeStatistics();
+		    resolver.displayStatistics();
 		    
-		    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("src/main/resources/resolvers/" + language)));
-		    oos.writeObject(resolver);
-		    oos.flush();
-		    oos.close();
+		    ScrabbleUtils.writeResolver(resolver, language);
 	    } catch( IOException e) {
 	    	System.err.println(e.getMessage());
 	    }
 	}
 	
+	
 	private static void getEnigma(CommandLine line) {
 		final String language = line.getOptionValue("lang", "");
 		final int min = Integer.parseInt(line.getOptionValue("min", "3"));

+ 7 - 66
src/main/java/fr/pavnay/scrabble/Node.java

@@ -1,73 +1,14 @@
 package fr.pavnay.scrabble;
 
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 
-public class Node implements Serializable {
-	private static final long serialVersionUID = 3539215265338287172L;
-	private Node[] nodes = new Node[26];
-	private List<String> words;
-	private String parent;
+public interface Node extends Serializable {
+	
+	public void addWord(String word);
+	public List<String> getWords();
+	public Node getNode(char character);
+	public Object getNodes();
+	public int getWordsCount();
 
-	public Node(String parent) {
-		this.parent = parent;
-	}
-
-	public void addWord(String word) {
-		if (this.words == null) {
-			this.words = new ArrayList<String>();
-		}
-		if (!this.words.contains(word)) {
-			this.words.add(word);
-		}
-	}
-
-	public List<String> getWords() {
-		if (this.words == null) {
-			return null;
-		}
-		Collections.sort(this.words);
-		return this.words;
-	}
-
-	public Node getNode(char character) {
-		Node node = this.nodes[(character - 'a')];
-		if (node == null) {
-			node = new Node(this.parent + character);
-			this.nodes[(character - 'a')] = node;
-		}
-		return node;
-	}
-
-	public int getWordsCount() {
-		int total = 0;
-		for (int i = 0; i < 26; i++) {
-			Node current = this.nodes[i];
-			if (current != null) {
-				total += current.getWordsCount();
-			}
-			if (this.words != null) {
-				total += this.words.size();
-			}
-		}
-		return total;
-	}
-
-	public String toString() {
-		StringBuilder sb = new StringBuilder("Parent " + this.parent);
-		if (this.words != null) {
-			sb.append(this.words.toString());
-		} else {
-			sb.append('-');
-		}
-		for (int i = 0; i < 26; i++) {
-			Node current = this.nodes[i];
-			if (current != null) {
-				sb.append(current);
-			}
-		}
-		return sb.toString();
-	}
 }

+ 10 - 9
src/main/java/fr/pavnay/scrabble/Resolver.java

@@ -8,20 +8,20 @@ import java.util.List;
 import java.util.Map;
 import java.util.Random;
 
+import fr.pavnay.scrabble.impl.HashNodeImpl;
+
 public class Resolver implements Serializable {
-	private static final long serialVersionUID = 8267126995323709570L;
-	private Node[] nodes = new Node[26];
+	
+	private static final long serialVersionUID = 3424195161013074975L;
+	
+	public Node nodes = new HashNodeImpl();
 	private float[] statistics = new float[26];
 	private float totalCharacter = 0.0F;
 
 	public Node getNode(char character) {
-		Node node = this.nodes[(character - 'a')];
+		Node node = nodes.getNode(character);
 		this.statistics[(character - 'a')] += 1.0F;
 		this.totalCharacter += 1.0F;
-		if (node == null) {
-			node = new Node(Character.toString(character));
-			this.nodes[(character - 'a')] = node;
-		}
 		return node;
 	}
 
@@ -132,7 +132,7 @@ public class Resolver implements Serializable {
 
 		int setSize = letters.length;
 		if (size == setSize) {
-			Node currentNode = this.nodes[(sortLetters[0] - 'a')];
+			Node currentNode = nodes.getNode(sortLetters[0]);
 			if (currentNode == null) {
 				return null;
 			}
@@ -175,7 +175,8 @@ public class Resolver implements Serializable {
 	public int countWords() {
 		int total = 0;
 		for (int i = 0; i < 26; i++) {
-			Node current = this.nodes[i];
+//			Node current = this.nodes[i];
+			Node current = nodes.getNode((char)(i + 'a'));
 			if (current != null) {
 				total += current.getWordsCount();
 			}

+ 93 - 0
src/main/java/fr/pavnay/scrabble/ScrabbleUtils.java

@@ -1,9 +1,24 @@
 package fr.pavnay.scrabble;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.net.URL;
 import java.util.Arrays;
 import java.util.List;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+import fr.pavnay.scrabble.impl.HashNodeImpl;
+import fr.pavnay.scrabble.serializer.NodeSerializer;
 
 public class ScrabbleUtils {
 	
@@ -14,4 +29,82 @@ public class ScrabbleUtils {
 		return Arrays.asList(files);
 	}
 	
+	public static Resolver loadResolver(String language) {
+		long t1 = System.currentTimeMillis();
+		String path = DictionaryBuilder.class.getResource("/resolvers/" + language).getPath();
+		File file = new File(path);
+		if (!file.exists()) {
+			System.out.println("No resolver for " + language);
+			return null;
+		}
+		
+		Resolver resolver = null;
+		
+		try {
+			ObjectMapper mapper = getObjectMapper();
+			resolver = mapper.readerFor(Resolver.class).readValue(loadFile(file) );
+		} catch(IOException ioe) {
+			
+		}
+		System.out.println("Resolver in " + language + " loaded in " + (System.currentTimeMillis() - t1) + "ms.");
+		return resolver;
+	}
+	
+	public static boolean writeResolver(Resolver resolver, String language) {
+		ObjectMapper mapper = getObjectMapper();
+	    
+		try {
+		    String serialized = mapper.writeValueAsString(resolver);
+		    writeFile(serialized.getBytes(), language);
+		}catch(IOException e) {
+			return false;
+		}
+		
+	    return true;
+	}
+	
+	private static void writeFile(byte[] content, String language) throws IOException {
+
+	    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+
+        GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
+        gzipOutputStream.write(content);
+        gzipOutputStream.close();
+        
+        FileOutputStream out = new FileOutputStream( "src/main/resources/resolvers/" + language );
+        out.write(byteArrayOutputStream.toByteArray());
+	    out.flush();
+	    out.close();
+	}
+
+	
+	private static InputStream loadFile(File file) throws IOException {
+		FileInputStream fis = new FileInputStream(file);
+	    ByteArrayOutputStream out = new ByteArrayOutputStream();
+	    byte[] buffer = new byte[1024];
+	    int count = 0;
+	    while ((count = fis.read(buffer))!=-1){                  
+            out.write(buffer, 0, count);
+        }      
+	    byte[] b = out.toByteArray();
+	    fis.close();
+	    
+	    return new GZIPInputStream(new ByteArrayInputStream(b));
+	}
+	
+	private static ObjectMapper getObjectMapper() {
+		ObjectMapper mapper = new ObjectMapper();
+		
+		SimpleModule module = new SimpleModule();
+
+		SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver();
+		resolver.addMapping(Node.class, HashNodeImpl.class);
+
+		module.setAbstractTypes(resolver);
+		module.addSerializer(Node.class, new NodeSerializer());
+		mapper.registerModule(module);
+		
+		return mapper;
+	}
+	
 }

+ 81 - 0
src/main/java/fr/pavnay/scrabble/impl/HashNodeImpl.java

@@ -0,0 +1,81 @@
+package fr.pavnay.scrabble.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import fr.pavnay.scrabble.Node;
+
+public class HashNodeImpl implements Node {
+	
+	private static final long serialVersionUID = 4221818951064573126L;
+	
+	private Map<Character,Node> nodes = new HashMap<Character, Node>();
+	private List<String> words;
+	private String parent;
+
+	public HashNodeImpl() {
+	}
+	
+	public HashNodeImpl(String parent) {
+		this.parent = parent;
+	}
+
+	public void addWord(String word) {
+		if (this.words == null) {
+			this.words = new ArrayList<String>();
+		}
+		if (!this.words.contains(word)) {
+			this.words.add(word);
+		}
+	}
+
+	public List<String> getWords() {
+		if (this.words == null) {
+			return null;
+		}
+		Collections.sort(this.words);
+		return this.words;
+	}
+
+	public Map<Character, Node> getNodes() {
+		return nodes;
+	}
+	
+	public Node getNode(char character) {
+		Node node = this.nodes.get(character);
+		if (node == null) {
+			node = new HashNodeImpl(this.parent + character);
+			nodes.put(character, node);
+		}
+		return node;
+	}
+
+	public int getWordsCount() {
+		int total = 0;
+		
+		for(Map.Entry<Character, Node> node : nodes.entrySet()) {
+			total += node.getValue().getWordsCount();
+		}
+		if (this.words != null) {
+			total += this.words.size();
+		}
+		
+		return total;
+	}
+
+	public String toString() {
+		StringBuilder sb = new StringBuilder("Parent " + this.parent);
+		if (this.words != null) {
+			sb.append(this.words.toString());
+		} else {
+			sb.append('-');
+		}
+		for(Map.Entry<Character, Node> node : nodes.entrySet()) {
+			sb.append(node.getValue());
+		}
+		return sb.toString();
+	}
+}

+ 81 - 0
src/main/java/fr/pavnay/scrabble/impl/NodeImpl.java

@@ -0,0 +1,81 @@
+package fr.pavnay.scrabble.impl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import fr.pavnay.scrabble.Node;
+
+public class NodeImpl implements Node {
+	private static final long serialVersionUID = 6637351994367583747L;
+
+	public Node[] nodes = new Node[26];
+	public List<String> words;
+	private String parent;
+	
+	public NodeImpl() {}
+
+	public NodeImpl(String parent) {
+		this.parent = parent;
+	}
+
+	public void addWord(String word) {
+		if (this.words == null) {
+			this.words = new ArrayList<String>();
+		}
+		if (!this.words.contains(word)) {
+			this.words.add(word);
+		}
+	}
+
+	public List<String> getWords() {
+		if (this.words == null) {
+			return null;
+		}
+		Collections.sort(this.words);
+		return this.words;
+	}
+
+	public Node[] getNodes() {
+		return this.nodes;
+	}
+	
+	public Node getNode(char character) {
+		Node node = this.nodes[(character - 'a')];
+		if (node == null) {
+			node = new NodeImpl(this.parent + character);
+			this.nodes[(character - 'a')] = node;
+		}
+		return node;
+	}
+
+	public int getWordsCount() {
+		int total = 0;
+		for (int i = 0; i < 26; i++) {
+			Node current = this.nodes[i];
+			if (current != null) {
+				total += current.getWordsCount();
+			}
+			if (this.words != null) {
+				total += this.words.size();
+			}
+		}
+		return total;
+	}
+
+	public String toString() {
+		StringBuilder sb = new StringBuilder("Parent " + this.parent);
+		if (this.words != null) {
+			sb.append(this.words.toString());
+		} else {
+			sb.append('-');
+		}
+		for (int i = 0; i < 26; i++) {
+			Node current = this.nodes[i];
+			if (current != null) {
+				sb.append(current);
+			}
+		}
+		return sb.toString();
+	}
+}

+ 29 - 0
src/main/java/fr/pavnay/scrabble/serializer/NodeSerializer.java

@@ -0,0 +1,29 @@
+package fr.pavnay.scrabble.serializer;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+import fr.pavnay.scrabble.Node;
+
+public class NodeSerializer extends StdSerializer<Node> {
+	private static final long serialVersionUID = -5136242177329213286L;
+
+	public NodeSerializer() {
+        this(null);
+    }
+   
+    public NodeSerializer(Class<Node> t) {
+        super(t);
+    }
+
+	@Override
+	public void serialize(Node node, JsonGenerator generator, SerializerProvider provider) throws IOException {
+		generator.writeStartObject();
+		generator.writeObjectField("nodes", node.getNodes());
+		generator.writeObjectField("words", node.getWords());
+		generator.writeEndObject();
+	}
+}

BIN
src/main/resources/resolvers/english


BIN
src/main/resources/resolvers/french