diff --git a/src/fr/inria/moex/classapp/Classification.java b/src/fr/inria/moex/classapp/Classification.java
index 578e92de5f1dbd71db6a77c65b39a385abed5054..c975000506209f9124be0986e413d24857bd38b9 100644
--- a/src/fr/inria/moex/classapp/Classification.java
+++ b/src/fr/inria/moex/classapp/Classification.java
@@ -52,12 +52,15 @@ import java.util.Vector;
 import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.Iterator;
+import java.util.Deque;
+import java.util.ArrayDeque;
 
 import java.io.PrintStream;
 import java.io.BufferedOutputStream;
 import java.io.FileOutputStream;
 import java.io.File;
 import java.io.ByteArrayOutputStream;
+import java.io.StringReader;
 import java.io.UnsupportedEncodingException;
 //import static java.nio.charset.StandardCharsets.UTF_8;
 import java.nio.charset.StandardCharsets;
@@ -110,44 +113,59 @@ public class Classification implements Iterable<Classification> {
 		}
 	}
 
-	/*
+	//************ THIS WAS HIDDEN AND MUST BE DISCLOSED
+	
 	public Classification( String specif ) {
-		if ( !specif.equals( "()" ) ) {
-			// get the feature, set it 
-			subTree = new Classification[NBVALUES];
-			// read the subtree and put in the place
-		}
+		read( specif );
+		fillPatterns();
+		// This puts the lists of cards in leaves: this is necessary for the game
+		fillLeaves();
 	}
 
-	// May not need to be static if call from above?
-	public static Classification read( String specif ) {
-		Classification result;
+	/**
+	 * Call it from an empty Classification
+	 * It will create it
+	 * specifications S=()|(lbl S S S)
+	 *
+	 */
+	public void read( String specif ) {
 		try { 
 			StringReader reader = new StringReader( specif );
+			Deque<Classification> stack = new ArrayDeque<Classification>();
+			stack.push( this );
 			int c;
 			while((c = reader.read()) != -1) {
 				switch ( c ) {
-				case '(':					
+				case '(':
+					Classification current = stack.pop();
 					while((c = reader.read()) != -1) { if ( c != ' ' && c != '\t' ) break; }
-					if ( c == ')' )	result = new Classification(); break;
-					String ff = (Char)c;
-					while((c = reader.read()) != -1) { if ( c != ' ' && c != '\t' && c != '(' ) ff += (Char)c; }
+					// Just an empty classification
+					if ( c == ')' ) break; // result = new Classification();
+					// There is a fork
+					String ff = ""+(char)c;
+					while((c = reader.read()) != -1 && c != ' ' && c != '\t' && c != '('  && c != ')' ) ff += (char)c;
 					// Analyse ff
-					result = new Classification( ff );
-					result.subTree = new Classification[NBVALUES];
-					// Go ahead...		
-				case ' ': ; break;
-				case '\t': ; break;
+					if ( ff.equals( "COLOR" ) ) current.feature = Feature.COLOR;
+					else if ( ff.equals( "SHAPE" ) ) current.feature = Feature.SHAPE;
+					else if ( ff.equals( "FILLING" ) ) current.feature = Feature.FILLING;
+					else if ( ff.equals( "NUMBER" ) ) current.feature = Feature.NUMBER;
+					else throw new Exception( "Unrecognised feature: "+ff );
+					current.subTree = new Classification[NBVALUES];
+					for ( int i=0; i < NBVALUES; i++ ) {
+						current.subTree[i] = new Classification();
+						stack.push( current.subTree[i] );
+					}
+					// Go ahead...
+					break;
+				case ' ': break;
+				case '\t': break;
 				case ')': ; break;
 				}
 			}
 		} catch ( Exception ex ) { 
-            System.out.println(ex); 
+            System.out.println( ex ); 
 		}
-		fillPatterns();
-		// This puts the lists of cards in leaves: this is necessary for the game
-		fillLeaves();		
-		}*/
+	}
 
 	// JE2024: Taken can be replaced by pattern
 	public Classification( int level, int forks, boolean[] taken, boolean exact ) {
@@ -213,14 +231,12 @@ public class Classification implements Iterable<Classification> {
 		return true;
 	}
 
-	// JE2024: Taken can be replaced by pattern
 	public int[] classPattern( int color, int shape, int filling, int number ) {
 		pattern = new int[4];
-		// Should be indexed by Feature.XX
-		pattern[0] = color;
-		pattern[1] = shape;
-		pattern[2] = filling;
-		pattern[3] = number;
+		pattern[Feature.COLOR.ordinal()] = color;
+		pattern[Feature.SHAPE.ordinal()] = shape;
+		pattern[Feature.FILLING.ordinal()] = filling;
+		pattern[Feature.NUMBER.ordinal()] = number;
 		return pattern;
 	}
 	
@@ -250,11 +266,10 @@ public class Classification implements Iterable<Classification> {
 	private void fillLeafFromPattern() {
 		cards = new CardSet(); 
 		// Fill it
-		// Should be indexed by Feature.XX
-		int color = pattern[0];
-		int shape = pattern[1];
-		int filling = pattern[2];
-		int number = pattern[3];
+		int color = pattern[Feature.COLOR.ordinal()];
+		int shape = pattern[Feature.SHAPE.ordinal()];
+		int filling = pattern[Feature.FILLING.ordinal()];
+		int number = pattern[Feature.NUMBER.ordinal()];
 		int[] vcolor, vshape, vfill, vnumber;
 		//int[] pcolor = (color==-1)?{0,1,2}:{color};
 		if ( color == -1 ) { vcolor = new int[] {0,1,2}; } else { vcolor = new int[] {color}; }
@@ -378,7 +393,7 @@ public class Classification implements Iterable<Classification> {
 			}
 		}
 		for ( Classification cl2: classif2 ) nbClasses++;
-    	return (2*nbCommon)/nbClasses;
+    	return (double)(2*nbCommon)/(double)nbClasses;
     }
 	
 	public int nbForks() {