Browse Source

Merge pull request #38 from sdk2/master

change all files "iso-8859-1" to "UTF-8"
lama0206 8 years ago
parent
commit
3e06b60ebb

+ 1 - 1
jplag.frontend-utils/src/main/java/jplag/UnicodeReader.java

@@ -27,7 +27,7 @@ import java.io.Reader;
  * default is used if: BOM mark is not found and defaultEnc is NULL.<br />
  * default is used if: BOM mark is not found and defaultEnc is NULL.<br />
  * 
  * 
  * Usage pattern:<pre>
  * Usage pattern:<pre>
- * String defaultEnc = "ISO-8859-1"; // or NULL to use system default
+ * String defaultEnc = "UTF-8"; // or NULL to use system default
  * FileInputStream fis = new FileInputStream(file);
  * FileInputStream fis = new FileInputStream(file);
  * Reader in = new UnicodeReader(fis, defaultEnc);</pre>
  * Reader in = new UnicodeReader(fis, defaultEnc);</pre>
  */
  */

+ 1 - 1
jplag.frontend.csharp-1.2/src/main/java/jplag/csharp/Parser.java

@@ -72,7 +72,7 @@ public class Parser extends jplag.Parser implements CSharpTokenConstants {
 			FileInputStream fis = new FileInputStream(new File(dir, file));
 			FileInputStream fis = new FileInputStream(new File(dir, file));
 			currentFile = file;
 			currentFile = file;
 			// Create a scanner that reads from the input stream passed to us
 			// Create a scanner that reads from the input stream passed to us
-			CSharpLexer lexer = new CSharpLexer(new UnicodeReader(fis, "ISO-8859-1"));
+			CSharpLexer lexer = new CSharpLexer(new UnicodeReader(fis, "UTF-8"));
 			lexer.setFilename(file);
 			lexer.setFilename(file);
 			lexer.setTabSize(1);
 			lexer.setTabSize(1);
 
 

+ 2 - 2
jplag.frontend.java-1.5/src/main/javacc/Java1.5.jj

@@ -137,11 +137,11 @@ public class JavaParser implements JavaTokenConstants
         try {
         try {
             FileInputStream in = new FileInputStream(new File(dir,fileName));
             FileInputStream in = new FileInputStream(new File(dir,fileName));
             if (parser == null) {
             if (parser == null) {
-                JavaTabModCharStream charStream = new JavaTabModCharStream(new UnicodeReader(in, "ISO-8859-1"));
+                JavaTabModCharStream charStream = new JavaTabModCharStream(new UnicodeReader(in, "UTF-8"));
                 parser = new JavaParser(charStream);
                 parser = new JavaParser(charStream);
                 parser.charStream = charStream;
                 parser.charStream = charStream;
             } else {
             } else {
-                parser.charStream.ReInit(new UnicodeReader(in, "ISO-8859-1"));
+                parser.charStream.ReInit(new UnicodeReader(in, "UTF-8"));
                 parser.ReInit(parser.charStream);
                 parser.ReInit(parser.charStream);
             }
             }
             parser.parser2 = parserX;
             parser.parser2 = parserX;

+ 1 - 1
jplag.homepage/src/main/webapp/WEB-INF/web.xml

@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
+<?xml version="1.0" encoding="UTF-8"?>
 
 
 <!DOCTYPE web-app
 <!DOCTYPE web-app
     PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

+ 217 - 217
jplag/pom.xml

@@ -1,230 +1,230 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<artifactId>jplag</artifactId>
-	<version>2.11.9-SNAPSHOT</version>
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>jplag</artifactId>
+    <version>2.11.9-SNAPSHOT</version>
 
 
-	<parent>
-		<groupId>edu.kit.ipd.jplag</groupId>
-		<artifactId>parent</artifactId>
-		<version>0.3-SNAPSHOT</version>
-		<relativePath>../jplag.parent/pom.xml</relativePath>
-	</parent>
+    <parent>
+        <groupId>edu.kit.ipd.jplag</groupId>
+        <artifactId>parent</artifactId>
+        <version>0.3-SNAPSHOT</version>
+        <relativePath>../jplag.parent/pom.xml</relativePath>
+    </parent>
 
 
-	<repositories>
-		<repository>
-			<id>ipdNexus</id>
-			<name>Recaa Repository</name>
-			<url>http://bob.ipd.kit.edu/nexus/content/repositories/public/</url>
-		</repository>
-	</repositories>
+    <repositories>
+        <repository>
+            <id>ipdNexus</id>
+            <name>Recaa Repository</name>
+            <url>http://bob.ipd.kit.edu/nexus/content/repositories/public/</url>
+        </repository>
+    </repositories>
 
 
-	<build>
-		<resources>
-			<resource>
-				<directory>src/main/resources</directory>
-				<filtering>true</filtering>
-				<includes>
-					<include>jplag/version.properties</include>
-				</includes>
-			</resource>
-			<resource>
-				<directory>src/main/resources</directory>
-				<filtering>false</filtering>
-				<excludes>
-					<exclude>jplag/version.properties</exclude>
-				</excludes>
-			</resource>
-		</resources>
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>jplag/version.properties</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>false</filtering>
+                <excludes>
+                    <exclude>jplag/version.properties</exclude>
+                </excludes>
+            </resource>
+        </resources>
 
 
-		<plugins>
-			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>build-helper-maven-plugin</artifactId>
-				<version>1.7</version>
-				<executions>
-					<execution>
-						<id>add-antlr-source</id>
-						<phase>generate-sources</phase>
-						<goals>
-							<goal>add-source</goal>
-						</goals>
-						<configuration>
-							<sources>
-								<source>target/generated-sources/antlr</source>
-								<source>target/generated-sources/javacc</source>
-							</sources>
-						</configuration>
-					</execution>
-				</executions>
-			</plugin>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <version>1.7</version>
+                <executions>
+                    <execution>
+                        <id>add-antlr-source</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>target/generated-sources/antlr</source>
+                                <source>target/generated-sources/javacc</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
 
 
-			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>javacc-maven-plugin</artifactId>
-				<!-- If you need javacc version 3.2 (as did the original jplag) use plugin 
-					version 2.0; plugin version 2.6 uses javacc version 5.0 -->
-				<version>2.6</version>
-				<configuration>
-					<debugParser>false</debugParser>
-					<isStatic>false</isStatic>
-					<!-- we need this since the old plugin does not read the package from 
-						the grammar; as of 2.4 the plugin does that on its own <packageName>jplag.filter</packageName> -->
-				</configuration>
-				<executions>
-					<execution>
-						<id>javacc</id>
-						<goals>
-							<goal>javacc</goal>
-						</goals>
-					</execution>
-				</executions>
-			</plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>javacc-maven-plugin</artifactId>
+                <!-- If you need javacc version 3.2 (as did the original jplag) use plugin
+                    version 2.0; plugin version 2.6 uses javacc version 5.0 -->
+                <version>2.6</version>
+                <configuration>
+                    <debugParser>false</debugParser>
+                    <isStatic>false</isStatic>
+                    <!-- we need this since the old plugin does not read the package from
+                        the grammar; as of 2.4 the plugin does that on its own <packageName>jplag.filter</packageName> -->
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>javacc</id>
+                        <goals>
+                            <goal>javacc</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
 
 
-			<plugin>
-				<artifactId>maven-jar-plugin</artifactId>
-				<configuration>
-					<archive>
-						<manifest>
-							<mainClass>jplag.JPlag</mainClass>
-							<packageName>jplag</packageName>
-						</manifest>
-					</archive>
-				</configuration>
-			</plugin>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <mainClass>jplag.JPlag</mainClass>
+                            <packageName>jplag</packageName>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
 
 
-			<plugin>
-				<artifactId>maven-assembly-plugin</artifactId>
-				<version>2.4</version>
-				<configuration>
-					<descriptorRefs>
-						<descriptorRef>jar-with-dependencies</descriptorRef>
-					</descriptorRefs>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <version>2.4</version>
+                <configuration>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
 
 
-					<archive>
-						<manifest>
-							<mainClass>jplag.JPlag</mainClass>
-							<packageName>jplag</packageName>
-						</manifest>
-					</archive>
-				</configuration>
-			</plugin>
+                    <archive>
+                        <manifest>
+                            <mainClass>jplag.JPlag</mainClass>
+                            <packageName>jplag</packageName>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
 
 
-			<plugin>
-				<groupId>com.github.wvengen</groupId>
-				<artifactId>proguard-maven-plugin</artifactId>
-				<version>2.0.11</version>
-				<!-- executions>
-					<execution>
-						<phase>package</phase>
-						<goals>
-							<goal>proguard</goal>
-						</goals>
-					</execution>
-				</executions-->
-				<configuration>
-					<proguardVersion>4.8</proguardVersion>
-					<options>
-						<option>-allowaccessmodification</option>
-						<option>-keep public class * extends java.applet.Applet { *; }</option>
-					</options>
-					<libs>
-						<lib>${java.home}/lib/rt.jar</lib>
-					</libs>
-				</configuration>
-				<dependencies>
-				<dependency>
-					<groupId>net.sf.proguard</groupId>
-					<artifactId>proguard-base</artifactId>
-					<version>4.9</version>
-					<scope>runtime</scope>
-					</dependency>
-				</dependencies>
-			</plugin>
+            <plugin>
+                <groupId>com.github.wvengen</groupId>
+                <artifactId>proguard-maven-plugin</artifactId>
+                <version>2.0.11</version>
+                <!-- executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>proguard</goal>
+                        </goals>
+                    </execution>
+                </executions-->
+                <configuration>
+                    <proguardVersion>4.8</proguardVersion>
+                    <options>
+                        <option>-allowaccessmodification</option>
+                        <option>-keep public class * extends java.applet.Applet { *; }</option>
+                    </options>
+                    <libs>
+                        <lib>${java.home}/lib/rt.jar</lib>
+                    </libs>
+                </configuration>
+                <dependencies>
+                    <dependency>
+                        <groupId>net.sf.proguard</groupId>
+                        <artifactId>proguard-base</artifactId>
+                        <version>4.9</version>
+                        <scope>runtime</scope>
+                    </dependency>
+                </dependencies>
+            </plugin>
 
 
-		</plugins>
-		<pluginManagement>
-			<plugins>
-				<!--This plugin's configuration is used to store Eclipse m2e settings 
-					only. It has no influence on the Maven build itself. -->
-				<plugin>
-					<groupId>org.eclipse.m2e</groupId>
-					<artifactId>lifecycle-mapping</artifactId>
-					<version>1.0.0</version>
-					<configuration>
-						<lifecycleMappingMetadata>
-							<pluginExecutions>
-								<pluginExecution>
-									<pluginExecutionFilter>
-										<groupId>
-											org.codehaus.mojo
-										</groupId>
-										<artifactId>
-											javacc-maven-plugin
-										</artifactId>
-										<versionRange>
-											[2.0],[2.6]
-										</versionRange>
-										<goals>
-											<goal>javacc</goal>
-										</goals>
-									</pluginExecutionFilter>
-									<action>
-										<ignore></ignore>
-									</action>
-								</pluginExecution>
-							</pluginExecutions>
-						</lifecycleMappingMetadata>
-					</configuration>
-				</plugin>
-			</plugins>
-		</pluginManagement>
-	</build>
+        </plugins>
+        <pluginManagement>
+            <plugins>
+                <!--This plugin's configuration is used to store Eclipse m2e settings
+                    only. It has no influence on the Maven build itself. -->
+                <plugin>
+                    <groupId>org.eclipse.m2e</groupId>
+                    <artifactId>lifecycle-mapping</artifactId>
+                    <version>1.0.0</version>
+                    <configuration>
+                        <lifecycleMappingMetadata>
+                            <pluginExecutions>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>
+                                            org.codehaus.mojo
+                                        </groupId>
+                                        <artifactId>
+                                            javacc-maven-plugin
+                                        </artifactId>
+                                        <versionRange>
+                                            [2.0],[2.6]
+                                        </versionRange>
+                                        <goals>
+                                            <goal>javacc</goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore></ignore>
+                                    </action>
+                                </pluginExecution>
+                            </pluginExecutions>
+                        </lifecycleMappingMetadata>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
 
 
-	<dependencies>
-		<dependency>
-			<groupId>edu.kit.ipd.jplag</groupId>
-			<artifactId>frontend-utils</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>edu.kit.ipd.jplag</groupId>
-			<artifactId>java-1.1exp</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>edu.kit.ipd.jplag</groupId>
-			<artifactId>utils</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>edu.kit.ipd.jplag</groupId>
-			<artifactId>text</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>edu.kit.ipd.jplag</groupId>
-			<artifactId>java-1.5</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>edu.kit.ipd.jplag</groupId>
-			<artifactId>java-1.7</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>edu.kit.ipd.jplag</groupId>
-			<artifactId>python-3</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>edu.kit.ipd.jplag</groupId>
-			<artifactId>csharp-1.2</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>edu.kit.ipd.jplag</groupId>
-			<artifactId>cpp</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>edu.kit.ipd.jplag</groupId>
-			<artifactId>scheme</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>edu.kit.ipd.jplag</groupId>
-			<artifactId>chars</artifactId>
-		</dependency>
-	</dependencies>
+    <dependencies>
+        <dependency>
+            <groupId>edu.kit.ipd.jplag</groupId>
+            <artifactId>frontend-utils</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>edu.kit.ipd.jplag</groupId>
+            <artifactId>java-1.1exp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>edu.kit.ipd.jplag</groupId>
+            <artifactId>utils</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>edu.kit.ipd.jplag</groupId>
+            <artifactId>text</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>edu.kit.ipd.jplag</groupId>
+            <artifactId>java-1.5</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>edu.kit.ipd.jplag</groupId>
+            <artifactId>java-1.7</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>edu.kit.ipd.jplag</groupId>
+            <artifactId>python-3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>edu.kit.ipd.jplag</groupId>
+            <artifactId>csharp-1.2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>edu.kit.ipd.jplag</groupId>
+            <artifactId>cpp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>edu.kit.ipd.jplag</groupId>
+            <artifactId>scheme</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>edu.kit.ipd.jplag</groupId>
+            <artifactId>chars</artifactId>
+        </dependency>
+    </dependencies>
 </project>
 </project>

+ 1 - 1
jplag/src/main/java/jplag/HTMLFile.java

@@ -10,7 +10,7 @@ public class HTMLFile extends PrintWriter {
   /* This static method has to be used to instanciate HTMLFile objects. */
   /* This static method has to be used to instanciate HTMLFile objects. */
   public static HTMLFile createHTMLFile(File f) throws IOException {
   public static HTMLFile createHTMLFile(File f) throws IOException {
     BufferedCounter new_bc = new BufferedCounter(
     BufferedCounter new_bc = new BufferedCounter(
-        new OutputStreamWriter(new FileOutputStream(f), "ISO-8859-1"));
+        new OutputStreamWriter(new FileOutputStream(f), "UTF-8"));
     HTMLFile htmlfile = new HTMLFile(new_bc);
     HTMLFile htmlfile = new HTMLFile(new_bc);
     htmlfile.bc = new_bc;
     htmlfile.bc = new_bc;
 //      if (Program.verbose_details)
 //      if (Program.verbose_details)

+ 1 - 1
jplag/src/main/java/jplag/JPlag.java

@@ -17,7 +17,7 @@ public class JPlag {
             }
             }
             catch(ExitException ex) {
             catch(ExitException ex) {
                 System.out.println("Error: "+ex.getReport());
                 System.out.println("Error: "+ex.getReport());
-		System.exit(1);
+                System.exit(1);
             }
             }
 		}
 		}
 	}
 	}

+ 1413 - 1409
jplag/src/main/java/jplag/Program.java

@@ -29,1417 +29,1421 @@ import jplagUtils.PropertiesLoader;
 
 
 /*
 /*
  * This class coordinates the whole program flow.
  * This class coordinates the whole program flow.
- * The revision history can be found on https://svn.ipd.kit.edu/trac/jplag/wiki/JPlag/History 
+ * The revision history can be found on https://svn.ipd.kit.edu/trac/jplag/wiki/JPlag/History
  *
  *
  */
  */
 
 
 public class Program implements ProgramI {
 public class Program implements ProgramI {
-	private static final Properties versionProps = PropertiesLoader.loadProps("jplag/version.properties");
-	public static final String name = "JPlag" + versionProps.getProperty("version", "devel");
-	public static final String name_long = "JPlag (Version " + versionProps.getProperty("version", "devel") + ")";
-
-	public DateFormat dateFormat;
-	public DateFormat dateTimeFormat;
-
-	public String currentSubmissionName = "<Unknown submission>";
-	public Vector<String> errorVector = new Vector<String>();
-
-	public void addError(String errorMsg) {
-		errorVector.add("[" + currentSubmissionName + "]\n" + errorMsg);
-		print(errorMsg, null);
-	}
-
-	public void print(String normal, String lng) {
-		if (options.verbose_parser) {
-			if (lng != null)
-				myWrite(lng);
-			else if (normal != null)
-				myWrite(normal);
-		}
-		if (options.verbose_quiet)
-			return;
-		try {
-			if (normal != null) {
-				System.out.print(normal);
-			}
-
-			if (lng != null) {
-				if (options.verbose_long)
-					System.out.print(lng);
-			}
-		} catch (Throwable e) {
-			System.out.println(e.getMessage());
-		}
-	}
-
-	private Submission basecodeSubmission = null;
-
-	// Used Objects of anothers jplag.Classes ,they muss be just one time
-	// instantiate
-	public Clusters clusters = null;
-
-	private int errors = 0;
-	private String invalidSubmissionNames = null;
-
-	private HashSet<String> excluded = null;
-
-	protected GSTiling gSTiling = new GSTiling(this);
-
-	private Hashtable<String, AllBasecodeMatches> htBasecodeMatches = new Hashtable<String, AllBasecodeMatches>(30);
-
-	private Vector<String> included = null;
-
-	// experiment end
-
-	private jplag.options.Options options;
-
-	public Report report;
-
-	public Messages msg;
-
-	private Runtime runtime = Runtime.getRuntime();
-
-	private Vector<Submission> submissions;
-
-	private FileWriter writer = null;
-
-	public Program(Options options) throws jplag.ExitException {
-		this.options = options;
-		this.options.initializeSecondStep(this);
-		if (this.options.language == null)
-			throw new ExitException("Language not initialized!", ExitException.BAD_LANGUAGE_ERROR);
-
-		msg = new Messages(this.options.getCountryTag());
-
-		if (this.options.getCountryTag().equals("de")) {
-			dateFormat = new SimpleDateFormat("dd.MM.yyyy");
-			dateTimeFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss 'GMT'");
-		} else {
-			dateFormat = new SimpleDateFormat("yyyy-MM-dd");
-			dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss 'GMT'");
-		}
-		dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
-		dateTimeFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
-
-		report = new Report(this, get_language());
-	}
-
-	/**
-	 * All submission with no errors are counted. (unsure if this is still
-	 * necessary.)
-	 */
-	protected int validSubmissions() {
-		if (submissions == null)
-			return 0;
-		int size = 0;
-		for (int i = submissions.size() - 1; i >= 0; i--) {
-			if (!submissions.elementAt(i).errors)
-				size++;
-		}
-		return size;
-	}
-
-	/**
-	 * Like the validSubmissions(), but this time all the submissions are
-	 * returned as a string, separated by "separator".
-	 */
-	protected String allValidSubmissions(String separator) {
-		String res = "";
-		int size = submissions.size();
-		boolean firsterr = true;
-		for (int i = 0; i < size; i++) {
-			Submission subm = submissions.elementAt(i);
-			if (!subm.errors) {
-				res += ((!firsterr) ? separator : "") + subm.name;
-				firsterr = false;
-			}
-		}
-		return res;
-	}
-
-	/**
-	 * Returns a " - " separated list of invalid submission names
-	 */
-	protected String allInvalidSubmissions() {
-		return invalidSubmissionNames;
-	}
-
-	public void closeWriter() {
-		try {
-			if (writer != null)
-				writer.close();
-		} catch (IOException ex) {
-			ex.printStackTrace();
-		}
-		writer = null;
-	}
-
-	private void throwNotEnoughSubmissions() throws jplag.ExitException {
-		StringBuilder errorStr = new StringBuilder();
-		for (String str : errorVector) {
-			errorStr.append(str);
-			errorStr.append('\n');
-		}
-
-		throw new ExitException("Not enough valid submissions! (only " + validSubmissions() + " "
-				+ (validSubmissions() != 1 ? "are" : "is") + " valid):\n" + errorStr.toString(), ExitException.NOT_ENOUGH_SUBMISSIONS_ERROR);
-	}
-
-	private void throwBadBasecodeSubmission() throws jplag.ExitException {
-		StringBuilder errorStr = new StringBuilder();
-		for (String str : errorVector) {
-			errorStr.append(str);
-			errorStr.append('\n');
-		}
-
-		throw new ExitException("Bad basecode submission:\n" + errorStr.toString());
-	}
-
-	// COMPARE
-
-	/**
-	 * Now the actual comparison: All submissions are compared pairwise.
-	 */
-	private void compare() throws jplag.ExitException {
-		int size = submissions.size();
-
-		SortedVector<AllMatches> avgmatches, maxmatches;
-		int[] dist = new int[10];
-
-		// Result vector
-		avgmatches = new SortedVector<AllMatches>(new AllMatches.AvgComparator());
-		maxmatches = new SortedVector<AllMatches>(new AllMatches.MaxComparator());
-
-		long msec;
-
-		AllBasecodeMatches bcmatch;
-		Submission s1, s2;
-
-		options.setState(Options.COMPARING);
-		options.setProgress(0);
-
-		if (this.options.useBasecode) {
-			//			print("\nComparing with Basecode:\n", validSubmissions()
-			//					+ " submissions");
-			int countBC = 0;
-			// System.out.println("BC size: "+basecodeSubmission.size());
-			msec = System.currentTimeMillis();
-			for (int i = 0; i < (size); i++) {
-				s1 = submissions.elementAt(i);
-				// System.out.println("basecode recognition for: "+s1.name);
-				bcmatch = this.gSTiling.compareWithBasecode(s1, basecodeSubmission);
-				htBasecodeMatches.put(s1.name, bcmatch);
-				this.gSTiling.resetBaseSubmission(basecodeSubmission);
-				countBC++;
-				options.setProgress(countBC * 100 / size);
-			}
-			long timebc = System.currentTimeMillis() - msec;
-			print("\n\n", "\nTime for comparing with Basecode: " + ((timebc / 3600000 > 0) ? (timebc / 3600000) + " h " : "")
-					+ ((timebc / 60000 > 0) ? ((timebc / 60000) % 60000) + " min " : "") + (timebc / 1000 % 60) + " sec\n"
-					+ "Time per basecode comparison: " + (timebc / size) + " msec\n\n");
-		}
-
-		//		print("\nComparing:\n", validSubmissions() + " submissions");
-
-		int totalcomps = (size - 1) * size / 2;
-		int i, j, anz = 0, count = 0;
-		AllMatches match;
-
-		options.setProgress(0);
-		msec = System.currentTimeMillis();
-
-		for (i = 0; i < (size - 1); i++) {
-			s1 = submissions.elementAt(i);
-			if (s1.struct == null) {
-				count += (size - i - 1);
-				continue;
-			}
-
-			for (j = (i + 1); j < size; j++) {
-				s2 = submissions.elementAt(j);
-				if (s2.struct == null) {
-					count++;
-					continue;
-				}
-
-				match = this.gSTiling.compare(s1, s2);
-
-				anz++;
-
-				System.out.println("Comparing " + s1.name + "-" + s2.name + ": " + match.percent());
-
-				// histogram:
-				if (options.useBasecode) {
-					match.bcmatchesA = htBasecodeMatches.get(match.subA.name);
-					match.bcmatchesB = htBasecodeMatches.get(match.subB.name);
-				}
-
-				registerMatch(match, dist, avgmatches, maxmatches, null, i, j);
-				count++;
-				options.setProgress(count * 100 / totalcomps);
-			}
-		}
-		options.setProgress(100);
-		long time = System.currentTimeMillis() - msec;
-
-		print("\n", "Total time for comparing submissions: " + ((time / 3600000 > 0) ? (time / 3600000) + " h " : "")
-				+ ((time / 60000 > 0) ? ((time / 60000) % 60000) + " min " : "") + (time / 1000 % 60) + " sec\n" + "Time per comparison: "
-				+ (time / anz) + " msec\n");
-
-		Cluster cluster = null;
-		if (options.clustering)
-			cluster = this.clusters.calculateClustering(submissions);
-
-		writeResults(dist, avgmatches, maxmatches, null, cluster);
-	}
-
-	/**
-	 * Revision compare mode: Compare each submission only with its next
-	 * submission.
-	 */
-	private void revisionCompare() throws jplag.ExitException {
-		int size = submissions.size();
-
-		SortedVector<AllMatches> avgmatches, maxmatches, minmatches;
-		int[] dist = new int[10];
-
-		// Result vector
-		avgmatches = new SortedVector<AllMatches>(new AllMatches.AvgReversedComparator());
-		maxmatches = new SortedVector<AllMatches>(new AllMatches.MaxReversedComparator());
-		minmatches = new SortedVector<AllMatches>(new AllMatches.MinReversedComparator());
-
-		long msec;
-
-		AllBasecodeMatches bcmatch;
-		Submission s1, s2;
-
-		options.setState(Options.COMPARING);
-		options.setProgress(0);
-
-		if (options.useBasecode) {
-			msec = System.currentTimeMillis();
-			for (int i = 0; i < size; i++) {
-				s1 = submissions.elementAt(i);
-				bcmatch = gSTiling.compareWithBasecode(s1, basecodeSubmission);
-				htBasecodeMatches.put(s1.name, bcmatch);
-				gSTiling.resetBaseSubmission(basecodeSubmission);
-				options.setProgress((i + 1) * 100 / size);
-			}
-			long timebc = System.currentTimeMillis() - msec;
-			print("\n\n", "\nTime for comparing with Basecode: " + ((timebc / 3600000 > 0) ? (timebc / 3600000) + " h " : "")
-					+ ((timebc / 60000 > 0) ? ((timebc / 60000) % 60000) + " min " : "") + (timebc / 1000 % 60) + " sec\n"
-					+ "Time per basecode comparison: " + (timebc / size) + " msec\n\n");
-		}
-
-		int totalcomps = size - 1;
-		int anz = 0, count = 0;
-		AllMatches match;
-
-		options.setProgress(0);
-		msec = System.currentTimeMillis();
-
-		s1loop: for (int i = 0; i < size - 1;) {
-			s1 = submissions.elementAt(i);
-			if (s1.struct == null) {
-				count++;
-				continue;
-			}
-
-			// Find next valid submission
-			int j = i;
-			do {
-				j++;
-				if (j >= size)
-					break s1loop; // no more comparison pairs available
-				s2 = submissions.elementAt(j);
-			} while (s2.struct == null);
-
-			match = this.gSTiling.compare(s1, s2);
-
-			anz++;
-
-			/*
-			 * System.out.println("Comparing "+s1.name+"-"+s2.name+": "+
-			 * match.percent());
-			 */
-			// histogram:
-			if (options.useBasecode) {
-				match.bcmatchesA = htBasecodeMatches.get(match.subA.name);
-				match.bcmatchesB = htBasecodeMatches.get(match.subB.name);
-			}
-
-			registerMatch(match, dist, avgmatches, maxmatches, minmatches, i, j);
-			count++;
-			options.setProgress(count * 100 / totalcomps);
-
-			i = j;
-		}
-		options.setProgress(100);
-		long time = System.currentTimeMillis() - msec;
-
-		print("\n", "Total time for comparing submissions: " + ((time / 3600000 > 0) ? (time / 3600000) + " h " : "")
-				+ ((time / 60000 > 0) ? ((time / 60000) % 60000) + " min " : "") + (time / 1000 % 60) + " sec\n" + "Time per comparison: "
-				+ (time / anz) + " msec\n");
-
-		Cluster cluster = null;
-		if (options.clustering)
-			cluster = this.clusters.calculateClustering(submissions);
-
-		writeResults(dist, avgmatches, maxmatches, minmatches, cluster);
-	}
-
-	private void createSubmissions() throws jplag.ExitException {
-		submissions = new Vector<Submission>();
-		File f = new File(options.root_dir);
-		if (f == null || !f.isDirectory()) {
-			throw new jplag.ExitException("\"" + options.root_dir + "\" is not a directory!");
-		}
-		String[] list = null;
-		try {
-			list = f.list();
-		} catch (SecurityException e) {
-			throw new jplag.ExitException("Unable to retrieve directory: " + options.root_dir + " Cause : " + e.toString());
-		}
-		Arrays.sort(list);
-
-		for (int i = 0; i < list.length; i++) {
-			File subm_dir = new File(f, list[i]);
-			if (!subm_dir.isDirectory()) {
-				if (options.sub_dir != null)
-					continue;
-
-				boolean ok = false;
-				String name = subm_dir.getName();
-				for (int j = 0; j < options.suffixes.length; j++)
-					if (name.endsWith(options.suffixes[j])) {
-						ok = true;
-						break;
-					}
-
-				if (!ok)
-					continue;
-
-				submissions.addElement(new Submission(name, f, this, get_language()));
-				continue;
-			}
-			if (options.exp && excludeFile(subm_dir.toString())) { // EXPERIMENT
-				// !!
-				System.err.println("excluded: " + subm_dir);
-				continue;
-			}
-
-			File file_dir = ((options.sub_dir == null) ? // - S option
-			subm_dir
-					: new File(subm_dir, options.sub_dir));
-			if (file_dir.isDirectory()) {
-				if (options.basecode.equals(subm_dir.getName())) {
-					basecodeSubmission = new Submission(subm_dir.getName(), file_dir, options.read_subdirs, this, get_language());
-				} else {
-					submissions.addElement(new Submission(subm_dir.getName(), file_dir, options.read_subdirs, this, get_language())); // -s
-				}
-			} else
-				throw new ExitException("Cannot find directory: " + file_dir.toString());
-		}
-	}
-
-	/**
-	 * THIS IS FOR THE EMPIRICAL STUDY
-	 */
-	private void createSubmissionsExp() throws jplag.ExitException {
-		// ES IST SICHER, DASS EIN INCLUDE-FILE ANGEGEBEN WURDE!
-		readIncludeFile();
-		submissions = new Vector<Submission>();
-		File f = new File(options.root_dir);
-		if (f == null || !f.isDirectory()) {
-			throw new jplag.ExitException(options.root_dir + " is not a directory!");
-		}
-		String[] list = new String[included.size()];
-		included.copyInto(list);
-		for (int i = 0; i < list.length; i++) {
-			File subm_dir = new File(f, list[i]);
-			if (subm_dir == null || !subm_dir.isDirectory())
-				continue;
-			if (options.exp && excludeFile(subm_dir.toString())) { // EXPERIMENT
-				// !!
-				System.err.println("excluded: " + subm_dir);
-				continue;
-			}
-			File file_dir = ((options.sub_dir == null) ? // - S option
-			subm_dir
-					: new File(subm_dir, options.sub_dir));
-			if (file_dir != null && file_dir.isDirectory())
-				submissions.addElement(new Submission(subm_dir.getName(), file_dir, options.read_subdirs, this, this.get_language())); // -s
-			else if (options.sub_dir == null) {
-				throw new jplag.ExitException(options.root_dir + " is not a directory!");
-			}
-		}
-	}
-
-	/**
-	 * Check if a file is excluded or not
-	 */
-	protected boolean excludeFile(String file) {
-		if (excluded == null)
-			return false;
-		Iterator<String> iter = excluded.iterator();
-		while (iter.hasNext())
-			if (file.endsWith(iter.next()))
-				return true;
-		return false;
-	}
-
-	// EXPERIMENT !!!!! special compare routine!
-	private void expCompare() throws jplag.ExitException {
-		int size = validSubmissions();
-		int[] similarity = new int[(size * size - size) / 2];
-
-		int anzSub = submissions.size();
-		int i, j, count = 0;
-		Submission s1, s2;
-		AllMatches match;
-		long msec = System.currentTimeMillis();
-		for (i = 0; i < (anzSub - 1); i++) {
-			s1 = submissions.elementAt(i);
-			if (s1.struct == null)
-				continue;
-			for (j = (i + 1); j < anzSub; j++) {
-				s2 = submissions.elementAt(j);
-				if (s2.struct == null)
-					continue;
-
-				match = this.gSTiling.compare(s1, s2);
-				similarity[count++] = (int) match.percent();
-			}
-		}
-		long time = System.currentTimeMillis() - msec;
-		// output
-		System.out.print(options.root_dir + " ");
-		System.out.print(options.min_token_match + " ");
-		System.out.print(options.filtername + " ");
-		System.out.print((time) + " ");
-		for (i = 0; i < similarity.length; i++)
-			System.out.print(similarity[i] + " ");
-		System.out.println();
-	}
-
-	/**
-	 * This is the special external comparison routine
-	 */
-	private void externalCompare() throws jplag.ExitException {
-		int size = submissions.size();
-		// Progress progress;
-		// Result vector
-		SortedVector<AllMatches> avgmatches = new SortedVector<AllMatches>(new AllMatches.AvgComparator());
-		SortedVector<AllMatches> maxmatches = new SortedVector<AllMatches>(new AllMatches.MaxComparator());
-		int[] dist = new int[10];
-
-		print("Comparing: " + size + " submissions\n", null);
-		options.setState(Options.COMPARING);
-		options.setProgress(0);
-		long totalComparisons = (size * (size - 1)) / 2, count = 0, comparisons = 0;
-		int index = 0;
-		AllMatches match;
-		Submission s1, s2;
-		long remain;
-		String totalTimeStr, remainTime;
-
-		print("Checking memory size...\n", null);
-		// First try to load as many submissions as possible
-		index = fillMemory(0, size);
-
-		long startTime;
-		long totalTime = 0;
-		int startA = 0;
-		int endA = index / 2;
-		int startB = endA + 1;
-		int endB = index;
-		int i, j;
-		//		long progStart;
-
-		do {
-			// compare A to A
-			startTime = System.currentTimeMillis();
-			print("Comparing block A (" + startA + "-" + endA + ") to block A\n", null);
-			//progStart = (endA - startA + 1) * (endA - startA) / 2;
-			//      progress = new Progress(progStart > 0 ? progStart : 1, this);
-			//progStart = count;
-			for (i = startA; i <= endA; i++) {
-				//        progress.set(count - progStart);
-				options.setProgress((int) (count * 100 / totalComparisons));
-				s1 = submissions.elementAt(i);
-				if (s1.struct == null) {
-					count += (endA - i);
-					continue;
-				}
-				for (j = (i + 1); j <= endA; j++) {
-					s2 = submissions.elementAt(j);
-					if (s2.struct == null) {
-						count++;
-						continue;
-					}
-
-					match = this.gSTiling.compare(s1, s2);
-					registerMatch(match, dist, avgmatches, maxmatches, null, i, j);
-					comparisons++;
-					count++;
-				}
-			}
-			//      progress.set(count - progStart);
-			options.setProgress((int) (count * 100 / totalComparisons));
-			print("\n", null);
-			totalTime += System.currentTimeMillis() - startTime;
-
-			// Are we finished?
-			if (startA == startB)
-				break;
-
-			do {
-				totalTimeStr = "" + ((totalTime / 3600000 > 0) ? (totalTime / 3600000) + " h " : "")
-						+ ((totalTime / 60000 > 0) ? ((totalTime / 60000) % 60) + " min " : "") + (totalTime / 1000 % 60) + " sec";
-				if (comparisons != 0)
-					remain = totalTime * (totalComparisons - count) / comparisons;
-				else
-					remain = 0;
-				remainTime = "" + ((remain / 3600000 > 0) ? (remain / 3600000) + " h " : "")
-						+ ((remain / 60000 > 0) ? ((remain / 60000) % 60) + " min " : "") + (remain / 1000 % 60) + " sec";
-
-				print("Progress: " + (100 * count) / totalComparisons + "%\nTime used for comparisons: " + totalTimeStr
-						+ "\nRemaining time (estimate): " + remainTime + "\n", null);
-
-				// compare A to B
-				startTime = System.currentTimeMillis();
-				print("Comparing block A (" + startA + "-" + endA + ") to block B (" + startB + "-" + endB + ")\n", null);
-				//progStart = (endA - startA + 1) * (endB - startB + 1);
-				//        progress = new Progress(progStart > 0 ? progStart : 1, this);
-				//progStart = count;
-				for (i = startB; i <= endB; i++) {
-					//          progress.set(count - progStart);
-					options.setProgress((int) (count * 100 / totalComparisons));
-					s1 = submissions.elementAt(i);
-					if (s1.struct == null) {
-						count += (endA - startA + 1);
-						continue;
-					}
-					for (j = startA; j <= endA; j++) {
-						s2 = submissions.elementAt(j);
-						if (s2.struct == null) {
-							count++;
-							continue;
-						}
-
-						match = this.gSTiling.compare(s1, s2);
-						registerMatch(match, dist, avgmatches, maxmatches, null, i, j);
-						comparisons++;
-						count++;
-					}
-					s1.struct = null; // remove B
-				}
-				//        progress.set(count - progStart);
-				options.setProgress((int) (count * 100 / totalComparisons));
-				print("\n", null);
-				totalTime += System.currentTimeMillis() - startTime;
-
-				if (endB == size - 1) {
-					totalTimeStr = "" + ((totalTime / 3600000 > 0) ? (totalTime / 3600000) + " h " : "")
-							+ ((totalTime / 60000 > 0) ? ((totalTime / 60000) % 60) + " min " : "") + (totalTime / 1000 % 60) + " sec";
-					remain = totalTime * (totalComparisons - count) / comparisons;
-					remainTime = "" + ((remain / 3600000 > 0) ? (remain / 3600000) + " h " : "")
-							+ ((remain / 60000 > 0) ? ((remain / 60000) % 60) + " min " : "") + (remain / 1000 % 60) + " sec";
-
-					print("Progress: " + (100 * count) / totalComparisons + "%\nTime used for comparisons: " + totalTimeStr
-							+ "\nRemaining time (estimate): " + remainTime + "\n", null);
-					break;
-				}
-
-				// Remove B -> already done...
-				// for (i=startB; i<=endB; i++)
-				// ((Submission)submissions.elementAt(i)).struct = null;
-				runtime.runFinalization();
-				runtime.gc();
-				Thread.yield();
-				// Try to find the next B
-				print("Finding next B\n", null);
-
-				index = fillMemory(endB + 1, size);
-
-				startB = endB + 1;
-				endB = index;
-
-			} while (true);
-
-			// Remove A
-			for (i = startA; i <= endA; i++)
-				submissions.elementAt(i).struct = null;
-			runtime.runFinalization();
-			runtime.gc();
-			Thread.yield();
-			print("Find next A.\n", null);
-			// First try to load as many submissions as possible
-
-			index = fillMemory(endA + 1, size);
-
-			if (index != size - 1) {
-				startA = endA + 1;
-				endA = startA + (index - startA + 1) / 2;
-				startB = endA + 1;
-				endB = index;
-			} else {
-				startA = startB; // last block
-				endA = endB = index;
-			}
-		} while (true);
-
-		totalTime += System.currentTimeMillis() - startTime;
-		totalTimeStr = "" + ((totalTime / 3600000 > 0) ? (totalTime / 3600000) + " h " : "")
-				+ ((totalTime / 60000 > 0) ? ((totalTime / 60000) % 60000) + " min " : "") + (totalTime / 1000 % 60) + " sec";
-
-		print("Total comparison time: " + totalTimeStr + "\nComparisons: " + count + "/" + comparisons + "/" + totalComparisons + "\n",
-				null);
-
-		// free remaining memory
-		for (i = startA; i <= endA; i++)
-			submissions.elementAt(i).struct = null;
-		runtime.runFinalization();
-		runtime.gc();
-		Thread.yield();
-
-		// System.out.println("Matrix:\n"+ similarity);
-		Cluster cluster = null;
-		if (options.clustering)
-			cluster = this.clusters.calculateClustering(submissions);
-
-		writeResults(dist, avgmatches, maxmatches, null, cluster);
-	}
-
-	private int fillMemory(int from, int size) {
-		Submission sub = null;
-		int index = from;
-
-		runtime.runFinalization();
-		runtime.gc();
-		Thread.yield();
-		long freeBefore = runtime.freeMemory();
-		try {
-			for (; index < size; index++) {
-				sub = submissions.elementAt(index);
-				sub.struct = new Structure();
-				if (!sub.struct.load(new File("temp", sub.dir.getName() + sub.name)))
-					sub.struct = null;
-			}
-		} catch (java.lang.OutOfMemoryError e) {
-			sub.struct = null;
-			print("Memory overflow after loading " + (index - from + 1) + " submissions.\n", null);
-		}
-		if (index >= size)
-			index = size - 1;
-
-		if (freeBefore / runtime.freeMemory() <= 2)
-			return index;
-		for (int i = (index - from) / 2; i > 0; i--) {
-			submissions.elementAt(index--).struct = null;
-		}
-		runtime.runFinalization();
-		runtime.gc();
-		Thread.yield();
-
-		// make sure we freed half of the "available" memory.
-		long free;
-		while (freeBefore / (free = runtime.freeMemory()) > 2) {
-			submissions.elementAt(index--).struct = null;
-			runtime.runFinalization();
-			runtime.gc();
-			Thread.yield();
-		}
-		print(free / 1024 / 1024 + "MByte freed. Current index: " + index + "\n", null);
-
-		return index;
-	}
-
-	public String get_basecode() {
-		return this.options.basecode;
-	}
-
-	public int get_clusterType() {
-		return this.options.clusterType;
-	}
-
-	public String get_commandLine() {
-		return this.options.commandLine;
-	}
-
-	public String getCountryTag() {
-		return options.getCountryTag();
-	}
-
-	/*
-	 * Distribution: Program given away to:
-	 * 
-	 * 0: Server version
-	 * 
-	 * 1: David Klausner 2: Ronald Kostoff 3: Bob Carlson 4: Neville Newman
-	 */
-
-	public int get_distri() {
-		return 0;
-	}
-
-	public File get_jplagResult() {
-		return new File(options.result_dir);
-
-	}
-
-	public Language get_language() {
-		return this.options.language;
-	}
-
-	public int get_min_token_match() {
-		return this.options.min_token_match;
-	}
-
-	public String get_title() {
-		return this.options.title;
-	}
-
-	public String get_original_dir() {
-		return this.options.original_dir;
-	}
-
-	public String get_result_dir() {
-		return this.options.result_dir;
-	}
-
-	public String get_root_dir() {
-		return this.options.root_dir;
-	}
-
-	public SimilarityMatrix get_similarity() {
-		return this.options.similarity;
-	}
-
-	public String get_sub_dir() {
-		return this.options.sub_dir;
-	}
-
-	public String[] get_suffixes() {
-		return this.options.suffixes;
-	}
-
-	public int[] get_themewords() {
-		return this.options.themewords;
-	}
-
-	public float[] get_threshold() {
-		return this.options.threshold;
-	}
-
-	public int getErrors() {
-		return errors;
-	}
-
-	public void hash_distribution() {
-		int[] dist = new int[20];
-		int count = 0;
-		Enumeration<Submission> enum1 = submissions.elements();
-
-		while (enum1.hasMoreElements()) {
-			Structure struct = enum1.nextElement().struct;
-			if (struct != null) {
-				struct.table.count_dist(dist);
-				count++;
-			}
-		}
-
-		System.out.println("Count: " + count);
-		for (int i = 0; i < dist.length; i++)
-			System.out.println(i + "\t" + dist[i]);
-	}
-
-	private void makeTempDir() throws jplag.ExitException {
-		print(null, "Creating temporary dir.\n");
-		File f = new File("temp");
-		if (!f.exists()) {
-			if (!f.mkdirs()) {
-				throw new jplag.ExitException("Cannot create temporary directory!");
-			}
-		}
-		if (!f.isDirectory()) {
-			throw new ExitException("'temp' is not a directory!");
-		}
-		if (!f.canWrite()) {
-			throw new ExitException("Cannot write directory: 'temp'");
-		}
-	}
-
-	private void myWrite(String str) {
-		if (writer != null) {
-			try {
-				writer.write(str);
-			} catch (IOException e) {
-				e.printStackTrace();
-			}
-		} else
-			System.out.print(str);
-	}
-
-	// PARSE
-	/*
-	 * Compiles all "submissions"
-	 */
-	private void parseAll() throws jplag.ExitException {
-		if (submissions == null) {
-			System.out.println("  Nothing to parse!");
-			return;
-		}
-		// lets go:)
-		int count = 0;
-		int totalcount = submissions.size();
-		options.setState(Options.PARSING);
-		options.setProgress(0);
-		long msec = System.currentTimeMillis();
-		Iterator<Submission> iter = submissions.iterator();
-
-		if (options.externalSearch)
-			makeTempDir();
-		int invalid = 0;
-		while (iter.hasNext()) {
-			boolean ok = true;
-			boolean removed = false;
-			Submission subm = iter.next();
-			print(null, "------ Parsing submission: " + subm.name + "\n");
-			currentSubmissionName = subm.name;
-			options.setProgress(count * 100 / totalcount);
-			if (!(ok = subm.parse()))
-				errors++;
-
-			if (options.exp && options.filter != null)
-				subm.struct = options.filter.filter(subm.struct); // EXPERIMENT
-			count++;
-			if (subm.struct != null && subm.size() < options.min_token_match) {
-				print(null, "Submission contains fewer tokens than minimum match " + "length allows!\n");
-				subm.struct = null;
-				invalid++;
-				removed = true;
-			}
-			if (options.externalSearch) {
-				if (subm.struct != null) {
-					this.gSTiling.create_hashes(subm.struct, options.min_token_match, false);
-					subm.struct.save(new File("temp", subm.dir.getName() + subm.name));
-					subm.struct = null;
-				}
-			}
-			if (!options.externalSearch && subm.struct == null) {
-				invalidSubmissionNames = (invalidSubmissionNames == null) ? subm.name : invalidSubmissionNames + " - " + subm.name;
-				iter.remove();
-			}
-			if (ok && !removed)
-				print(null, "OK\n");
-			else
-				print(null, "ERROR -> Submission removed\n");
-		}
-
-		options.setProgress(100);
-		print("\n" + (count - errors - invalid) + " submissions parsed successfully!\n" + errors + " parser error"
-				+ (errors != 1 ? "s!\n" : "!\n"), null);
-		if (invalid != 0) {
-			print(null, invalid
-					+ ((invalid == 1) ? " submission is not valid because it contains" : " submissions are not valid because they contain")
-					+ " fewer tokens\nthan minimum match length allows.\n");
-		}
-		long time = System.currentTimeMillis() - msec;
-		print("\n\n", "\nTotal time for parsing: " + ((time / 3600000 > 0) ? (time / 3600000) + " h " : "")
-				+ ((time / 60000 > 0) ? ((time / 60000) % 60000) + " min " : "") + (time / 1000 % 60) + " sec\n"
-				+ "Time per parsed submission: " + (count > 0 ? (time / count) : "n/a") + " msec\n\n");
-	}
-
-	private void parseBasecodeSubmission() throws jplag.ExitException {
-		Submission subm = basecodeSubmission;
-		if (subm == null) {
-			options.useBasecode = false;
-			return;
-		}
-		long msec = System.currentTimeMillis();
-		print("----- Parsing basecode submission: " + subm.name + "\n", null);
-
-		// lets go:
-		if (options.externalSearch)
-			makeTempDir();
-
-		if (!subm.parse())
-			throwBadBasecodeSubmission();
-
-		if (options.exp && options.filter != null)
-			subm.struct = options.filter.filter(subm.struct); // EXPERIMENT
-
-		if (subm.struct != null && subm.size() < options.min_token_match)
-			throw new ExitException("Basecode submission contains fewer tokens " + "than minimum match length allows!\n");
-
-		if (options.useBasecode)
-			gSTiling.create_hashes(subm.struct, options.min_token_match, true);
-		if (options.externalSearch) {
-			if (subm.struct != null) {
-				gSTiling.create_hashes(subm.struct, options.min_token_match, false);
-				subm.struct.save(new File("temp", subm.dir.getName() + subm.name));
-				subm.struct = null;
-			}
-		}
-
-		print("\nBasecode submission parsed!\n", null);
-		long time = System.currentTimeMillis() - msec;
-		print("\n", "\nTime for parsing Basecode: " + ((time / 3600000 > 0) ? (time / 3600000) + " h " : "")
-				+ ((time / 60000 > 0) ? ((time / 60000) % 60000) + " min " : "") + (time / 1000 % 60) + " sec\n");
-	}
-
-	// Excluded files:
-
-	/*
-	 * If an exclusion file is given, it is read in and all stings are saved in
-	 * the set "excluded".
-	 */
-	private void readExclusionFile() {
-		if (options.exclude_file == null)
-			return;
-		excluded = new HashSet<String>();
-
-		try {
-			BufferedReader in = new BufferedReader(new FileReader(options.exclude_file));
-			String line;
-			while ((line = in.readLine()) != null) {
-				excluded.add(line.trim());
-			}
-			in.close();
-		} catch (FileNotFoundException e) {
-			System.out.println("Exclusion file not found: " + options.exclude_file);
-		} catch (IOException e) {
-		}
-		print(null, "Excluded files:\n");
-		if (options.verbose_long) {
-			Iterator<String> iter = excluded.iterator();
-			while (iter.hasNext()) {
-				print(null, "  " + iter.next() + "\n");
-			}
-		}
-	}
-
-	/*
-	 * If an include file is given, read it in and store all the strings in
-	 * "included".
-	 */
-	private void readIncludeFile() {
-		if (options.include_file == null)
-			return;
-		included = new Vector<String>();
-		try {
-			BufferedReader in = new BufferedReader(new FileReader(options.include_file));
-			String line;
-			while ((line = in.readLine()) != null) {
-				included.addElement(line.trim());
-			}
-			in.close();
-		} catch (FileNotFoundException e) {
-			System.out.println("Include file not found: " + options.include_file);
-		} catch (IOException e) {
-		}
-		print(null, "Included dirs:\n");
-		if (options.verbose_long) {
-			Enumeration<String> enum1 = included.elements();
-			while (enum1.hasMoreElements())
-				print(null, "  " + enum1.nextElement() + "\n");
-		}
-	}
-
-	private void registerMatch(AllMatches match, int[] dist, SortedVector<AllMatches> avgmatches, SortedVector<AllMatches> maxmatches,
-			SortedVector<AllMatches> minmatches, int a, int b) {
-		float avgpercent = match.percent();
-		float maxpercent = match.percentMaxAB();
-		float minpercent = match.percentMinAB();
-
-		dist[((((int) avgpercent) / 10) == 10) ? 9 : (((int) avgpercent) / 10)]++;
-		if (!options.store_percent) {
-			if ((avgmatches.size() < options.store_matches || avgpercent > avgmatches.lastElement().percent()) && avgpercent > 0) {
-				avgmatches.insert(match);
-				if (avgmatches.size() > options.store_matches)
-					avgmatches.removeElementAt(options.store_matches);
-			}
-			if (maxmatches != null && (maxmatches.size() < options.store_matches || maxpercent > maxmatches.lastElement().percent())
-					&& maxpercent > 0) {
-				maxmatches.insert(match);
-				if (maxmatches.size() > options.store_matches)
-					maxmatches.removeElementAt(options.store_matches);
-			}
-			if (minmatches != null && (minmatches.size() < options.store_matches || minpercent > minmatches.lastElement().percent())
-					&& minpercent > 0) {
-				minmatches.insert(match);
-				if (minmatches.size() > options.store_matches)
-					minmatches.removeElementAt(options.store_matches);
-			}
-		} else { // store_percent
-			if (avgpercent > options.store_matches) {
-				avgmatches.insert(match);
-				if (avgmatches.size() > Options.MAX_RESULT_PAIRS)
-					avgmatches.removeElementAt(Options.MAX_RESULT_PAIRS);
-			}
-
-			if (maxmatches != null && maxpercent > options.store_matches) {
-				maxmatches.insert(match);
-				if (maxmatches.size() > Options.MAX_RESULT_PAIRS)
-					maxmatches.removeElementAt(Options.MAX_RESULT_PAIRS);
-			}
-
-			if (minmatches != null && minpercent > options.store_matches) {
-				minmatches.insert(match);
-				if (minmatches.size() > Options.MAX_RESULT_PAIRS)
-					minmatches.removeElementAt(Options.MAX_RESULT_PAIRS);
-			}
-		}
-		if (options.clustering)
-			options.similarity.setSimilarity(a, b, avgpercent);
-	}
-
-	private String toUTF8(String str) {
-		byte[] utf8 = null;
-		try {
-			utf8 = str.getBytes("UTF-8");
-		} catch (UnsupportedEncodingException e) {
-		}
-		return new String(utf8);
-	}
-
-	/** *************************** */
-	/* THE MAIN PROCEDURE */
-	/** *************************** */
-	public void run() throws jplag.ExitException {
-		if (options.output_file != null) {
-			try {
-				writer = new FileWriter(new File(options.output_file));
-				writer.write(name_long + "\n");
-				writer.write(dateTimeFormat.format(new Date()) + "\n\n");
-			} catch (IOException ex) {
-				System.out.println("Unable to open or write to log file: " + options.output_file);
-				throw new ExitException("Unable to create log file!");
-			}
-		} else
-			print(null, name_long + "\n\n");
-		print(null, "Language: " + options.language.name() + "\n\n");
-		if (options.original_dir == null)
-			print(null, "Root-dir: " + options.root_dir + "\n"); // server
-		// this file contains all files names which are excluded
-		readExclusionFile();
-		if (options.include_file == null) {
-			createSubmissions();
-			System.out.println(submissions.size() + " submissions");
-		} else
-			createSubmissionsExp();
-
-		if (!options.skipParse) {
-			try {
-				parseAll();
-				System.gc();
-				parseBasecodeSubmission();
-			} catch (OutOfMemoryError e) {
-				submissions = null;
-				System.gc();
-				System.out.println("[" + new Date() + "] OutOfMemoryError " + "during parsing of submission \"" + currentSubmissionName
-						+ "\"");
-				throw new ExitException("Out of memory during parsing of submission \"" + currentSubmissionName + "\"");
-			} catch (ExitException e) {
-				throw e;
-			} catch (Throwable e) {
-				System.out.println("[" + new Date() + "] Unknown exception " + "during parsing of submission \"" + currentSubmissionName
-						+ "\"");
-				e.printStackTrace();
-				throw new ExitException("Unknown exception during parsing of " + "submission \"" + currentSubmissionName + "\"");
-			}
-		} else
-			print("Skipping parsing...\n", null);
-
-		if (validSubmissions() < 2) {
-			throwNotEnoughSubmissions();
-		}
-		errorVector = null; // errorVector is not needed anymore
-
-		if (options.clustering) {
-			clusters = new Clusters(this);
-			options.similarity = new SimilarityMatrix(submissions.size());
-		}
-		System.gc();
-		if (options.exp) { // EXPERIMENT
-			expCompare();
-		} else if (options.externalSearch) {
-			try {
-				externalCompare();
-			} catch (OutOfMemoryError e) {
-				e.printStackTrace();
-			}
-		} else {
-			if (options.compare > 0)
-				specialCompare(); // compare every submission to x others
-			else {
-				switch (options.comparisonMode) {
-				case Options.COMPMODE_NORMAL:
-					compare();
-					break;
-
-				case Options.COMPMODE_REVISION:
-					revisionCompare();
-					break;
-
-				default:
-					throw new ExitException("Illegal comparison mode: \"" + options.comparisonMode + "\"");
-				}
-			}
-		}
-		closeWriter();
-
-		String str = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>";
-		str += "<jplag_infos>\n";
-		str += "<infos \n";
-
-		String sp = "\"";
-		str += " title = " + sp + toUTF8(options.getTitle()) + sp;
-		str += " source = " + sp + (get_original_dir() != null ? toUTF8(get_original_dir()) : "") + sp;
-		str += " n_of_programs = " + sp + submissions.size() + sp;
-		str += " errors = " + sp + get_language().errorsCount() + sp;
-		str += " path_to_files = " + sp + toUTF8((options.sub_dir != null) ? options.sub_dir : "") + sp;
-		str += " basecode_dir = " + sp + toUTF8((options.basecode != null) ? options.basecode : "") + sp;
-		str += " read_subdirs = " + sp + this.options.read_subdirs + sp;
-		str += " clustertype = " + sp + this.options.getClusterTyp() + sp;
-		str += " store_matches = " + sp + this.options.store_matches + ((this.options.store_percent) ? "%" : "") + sp;
-		String suf = "";
-		for (int s = 0; s < this.options.suffixes.length; s++)
-			suf += "," + this.options.suffixes[s];
-		str += " suffixes = " + sp + suf.substring(1) + sp;
-		str += " language_name = " + sp + this.options.languageName + sp;
-		str += " comparison_mode = " + sp + this.options.comparisonMode + sp;
-		str += " country_tag = " + sp + this.options.getCountryTag() + sp;
-		str += " min_token = " + sp + this.options.min_token_match + sp;
-		str += " date = " + sp + System.currentTimeMillis() + sp;
-
-		str += "/>\n";
-		str += "</jplag_infos>";
-
-		try {
-			FileWriter fw = new FileWriter(new File(this.options.result_dir + File.separator + "result.xml"));
-			fw.write(str);
-			fw.close();
-		} catch (IOException ex) {
-			System.out.println("Unable to create result.xml");
-		}
-	}
-
-	public void set_result_dir(String result_dir) {
-		this.options.result_dir = result_dir;
-	}
-
-	/*
-	 * Now the special comparison:
-	 */
-	private void specialCompare() throws jplag.ExitException {
-		File root = new File(options.result_dir);
-		HTMLFile f = this.report.openHTMLFile(root, "index.html");
-		this.report.copyFixedFiles(root);
-
-		this.report.writeIndexBegin(f, "Special Search Results"); // start HTML
-		f.println("<P><A NAME=\"matches\"><H4>Matches:</H4><P>");
-
-		int size = submissions.size();
-		int matchIndex = 0;
-
-		print("Comparing: ", validSubmissions() + " submissions");
-		print("\n(Writing results at the same time.)\n", null);
-
-		options.setState(Options.COMPARING);
-		options.setProgress(0);
-		int totalcomps = size * size;
-		int i, j, anz = 0, count = 0;
-		AllMatches match;
-		Submission s1, s2;
-		long msec = System.currentTimeMillis();
-		for (i = 0; i < (size - 1); i++) {
-			// Result vector
-			SortedVector<AllMatches> matches = new SortedVector<AllMatches>(new AllMatches.AvgComparator());
-
-			s1 = submissions.elementAt(i);
-			if (s1.struct == null) {
-				count += (size - 1);
-				continue;
-			}
-			for (j = 0; j < size; j++) {
-				s2 = submissions.elementAt(j);
-				if ((i == j) || (s2.struct == null)) {
-					count++;
-					continue;
-				}
-
-				match = this.gSTiling.compare(s1, s2);
-				anz++;
-
-				float percent = match.percent();
-
-				if ((matches.size() < options.compare || matches.size() == 0 || match.moreThan(matches.lastElement().percent()))
-						&& match.moreThan(0)) {
-					matches.insert(match);
-					if (matches.size() > options.compare)
-						matches.removeElementAt(options.compare);
-				}
-
-				if (options.clustering)
-					options.similarity.setSimilarity(i, j, percent);
-
-				count++;
-				options.setProgress(count * 100 / totalcomps);
-			}
-
-			// now output matches:
-			f.println("<TABLE CELLPADDING=3 CELLSPACING=2>");
-			boolean once = true;
-			for (Iterator<AllMatches> iter = matches.iterator(); iter.hasNext();) {
-				match = iter.next();
-				if (once) {
-					f.println("<TR><TD BGCOLOR=" + this.report.color(match.percent(), 128, 192, 128, 192, 255, 255) + ">" + s1.name
-							+ "<TD WIDTH=\"10\">-&gt;");
-					once = false;
-				}
-
-				int other = (match.subName(0).equals(s1.name) ? 1 : 0);
-				f.println(" <TD BGCOLOR=" + this.report.color(match.percent(), 128, 192, 128, 192, 255, 255)
-						+ " ALIGN=center><A HREF=\"match" + matchIndex + ".html\">" + match.subName(other) + "</A><BR><FONT COLOR=\""
-						+ this.report.color(match.percent(), 0, 255, 0, 0, 0, 0) + "\"><B>(" + match.roundedPercent() + "%)</B></FONT>");
-				this.report.writeMatch(root, matchIndex++, match);
-			}
-			f.println("</TR>");
-		}
-		f.println("</TABLE><P>\n");
-		f.println("<!---->");
-		this.report.writeIndexEnd(f);
-		f.close();
-
-		options.setProgress(100);
-		long time = System.currentTimeMillis() - msec;
-		print("\n", "Total time: " + ((time / 3600000 > 0) ? (time / 3600000) + " h " : "")
-				+ ((time / 60000 > 0) ? ((time / 60000) % 60000) + " min " : "") + (time / 1000 % 60) + " sec\n" + "Time per comparison: "
-				+ (time / anz) + " msec\n");
-
-	}
-
-	// DEBUG !!!
-	public void token_distribution() {
-		int[] count = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-				0, 0, 0 }; // to
-		// count
-		// the
-		// distribution
-
-		Enumeration<Submission> enum1 = submissions.elements();
-
-		while (enum1.hasMoreElements()) {
-			Structure struct = enum1.nextElement().struct;
-			if (struct != null)
-				for (int i = struct.size() - 1; i >= 0; i--)
-					count[struct.tokens[i].type]++;
-		}
-
-		int tot = 0;
-		for (int i = 0; i < 0; i++) { // !!!!!!!!!!!!!!!
-			int c = count[i];
-			tot += c;
-			// System.out.println(Token.type2string(i)+"\t"+c);
-		}
-		System.out.println((tot > 999 ? "" : (tot > 99 ? " " : (tot > 9 ? "  " : "   "))) + tot);
-	}
-
-	public boolean use_clustering() {
-		return this.options.clustering;
-	}
-
-	public boolean use_debugParser() {
-		return this.options.debugParser;
-	}
-
-	public boolean use_diff_report() {
-		return this.options.diff_report;
-	}
-
-	public boolean use_externalSearch() {
-		return this.options.externalSearch;
-	}
-
-	public boolean use_verbose_details() {
-		return this.options.verbose_details;
-	}
-
-	public boolean use_verbose_long() {
-		return this.options.verbose_long;
-	}
-
-	public boolean use_verbose_parser() {
-		return this.options.verbose_parser;
-	}
-
-	public boolean use_verbose_quiet() {
-		return this.options.verbose_quiet;
-	}
-
-	public boolean useBasecode() {
-		return this.options.useBasecode;
-	}
-
-	// RESULT
-
-	/*
-	 * Erst wird die Existenz des Ergebnis-Verzeichnisses sichergestellt, dann
-	 * wird die Erstellung der Dateien durch die Klasse "Report" erledigt.
-	 */
-	private void writeResults(int[] dist, SortedVector<AllMatches> avgmatches, SortedVector<AllMatches> maxmatches,
-			SortedVector<AllMatches> minmatches, Cluster clustering) throws jplag.ExitException {
-		options.setState(Options.GENERATING_RESULT_FILES);
-		options.setProgress(0);
-		if (options.original_dir == null)
-			print("Writing results to: " + options.result_dir + "\n", null);
-		File f = new File(options.result_dir);
-		if (!f.exists())
-			if (!f.mkdirs()) {
-				throw new jplag.ExitException("Cannot create directory!");
-			}
-		if (!f.isDirectory()) {
-			throw new jplag.ExitException(options.result_dir + " is not a directory!");
-		}
-		if (!f.canWrite()) {
-			throw new jplag.ExitException("Cannot write directory: " + options.result_dir);
-		}
-
-		this.report.write(f, dist, avgmatches, maxmatches, minmatches, clustering, options);
-
-		if (options.externalSearch)
-			writeTextResult(f, avgmatches);
-	}
-
-	private void writeTextResult(File dir, SortedVector<AllMatches> matches) {
-		Iterator<AllMatches> iter = matches.iterator();
-
-		print("Writing special 'matches.txt' file\n", null);
-
-		try {
-			File f = new File(dir, "matches.txt");
-			PrintWriter writer = new PrintWriter(new FileWriter(f));
-
-			while (iter.hasNext()) {
-				AllMatches match = iter.next();
-
-				String file1, file2, tmp;
-				file1 = match.subA.name;
-				file2 = match.subB.name;
-
-				if (file1.compareTo(file2) > 0) {
-					tmp = file2;
-					file2 = file1;
-					file1 = tmp;
-				}
-
-				writer.println(file1 + "\t" + file2 + "\t" + match.percent());
-			}
-			writer.close();
-		} catch (IOException e) {
-			print("IOException while writing file\n", null);
-		}
-	}
+    private static final Properties versionProps = PropertiesLoader.loadProps("jplag/version.properties");
+    public static final String name = "JPlag" + versionProps.getProperty("version", "devel");
+    public static final String name_long = "JPlag (Version " + versionProps.getProperty("version", "devel") + ")";
+
+    public DateFormat dateFormat;
+    public DateFormat dateTimeFormat;
+
+    public String currentSubmissionName = "<Unknown submission>";
+    public Vector<String> errorVector = new Vector<String>();
+
+    public void addError(String errorMsg) {
+        errorVector.add("[" + currentSubmissionName + "]\n" + errorMsg);
+        print(errorMsg, null);
+    }
+
+    public void print(String normal, String lng) {
+        if (options.verbose_parser) {
+            if (lng != null)
+                myWrite(lng);
+            else if (normal != null)
+                myWrite(normal);
+        }
+        if (options.verbose_quiet)
+            return;
+        try {
+            if (normal != null) {
+                System.out.print(normal);
+            }
+
+            if (lng != null) {
+                if (options.verbose_long)
+                    System.out.print(lng);
+            }
+        } catch (Throwable e) {
+            System.out.println(e.getMessage());
+        }
+    }
+
+    private Submission basecodeSubmission = null;
+
+    // Used Objects of anothers jplag.Classes ,they muss be just one time
+    // instantiate
+    public Clusters clusters = null;
+
+    private int errors = 0;
+    private String invalidSubmissionNames = null;
+
+    private HashSet<String> excluded = null;
+
+    protected GSTiling gSTiling = new GSTiling(this);
+
+    private Hashtable<String, AllBasecodeMatches> htBasecodeMatches = new Hashtable<String, AllBasecodeMatches>(30);
+
+    private Vector<String> included = null;
+
+    // experiment end
+
+    private jplag.options.Options options;
+
+    public Report report;
+
+    public Messages msg;
+
+    private Runtime runtime = Runtime.getRuntime();
+
+    private Vector<Submission> submissions;
+
+    private FileWriter writer = null;
+
+    public Program(Options options) throws jplag.ExitException {
+        this.options = options;
+        this.options.initializeSecondStep(this);
+        if (this.options.language == null)
+            throw new ExitException("Language not initialized!", ExitException.BAD_LANGUAGE_ERROR);
+
+        msg = new Messages(this.options.getCountryTag());
+
+        if (this.options.getCountryTag().equals("de")) {
+            dateFormat = new SimpleDateFormat("dd.MM.yyyy");
+            dateTimeFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss 'GMT'");
+        } else {
+            dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+            dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss 'GMT'");
+        }
+        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
+        dateTimeFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
+
+        report = new Report(this, get_language());
+    }
+
+    /**
+     * All submission with no errors are counted. (unsure if this is still
+     * necessary.)
+     */
+    protected int validSubmissions() {
+        if (submissions == null)
+            return 0;
+        int size = 0;
+        for (int i = submissions.size() - 1; i >= 0; i--) {
+            if (!submissions.elementAt(i).errors)
+                size++;
+        }
+        return size;
+    }
+
+    /**
+     * Like the validSubmissions(), but this time all the submissions are
+     * returned as a string, separated by "separator".
+     */
+    protected String allValidSubmissions(String separator) {
+        String res = "";
+        int size = submissions.size();
+        boolean firsterr = true;
+        for (int i = 0; i < size; i++) {
+            Submission subm = submissions.elementAt(i);
+            if (!subm.errors) {
+                res += ((!firsterr) ? separator : "") + subm.name;
+                firsterr = false;
+            }
+        }
+        return res;
+    }
+
+    /**
+     * Returns a " - " separated list of invalid submission names
+     */
+    protected String allInvalidSubmissions() {
+        return invalidSubmissionNames;
+    }
+
+    public void closeWriter() {
+        try {
+            if (writer != null)
+                writer.close();
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        }
+        writer = null;
+    }
+
+    private void throwNotEnoughSubmissions() throws jplag.ExitException {
+        StringBuilder errorStr = new StringBuilder();
+        for (String str : errorVector) {
+            errorStr.append(str);
+            errorStr.append('\n');
+        }
+
+        throw new ExitException("Not enough valid submissions! (only " + validSubmissions() + " "
+                + (validSubmissions() != 1 ? "are" : "is") + " valid):\n" + errorStr.toString(), ExitException.NOT_ENOUGH_SUBMISSIONS_ERROR);
+    }
+
+    private void throwBadBasecodeSubmission() throws jplag.ExitException {
+        StringBuilder errorStr = new StringBuilder();
+        for (String str : errorVector) {
+            errorStr.append(str);
+            errorStr.append('\n');
+        }
+
+        throw new ExitException("Bad basecode submission:\n" + errorStr.toString());
+    }
+
+    // COMPARE
+
+    /**
+     * Now the actual comparison: All submissions are compared pairwise.
+     */
+    private void compare() throws jplag.ExitException {
+        int size = submissions.size();
+
+        SortedVector<AllMatches> avgmatches, maxmatches;
+        int[] dist = new int[10];
+
+        // Result vector
+        avgmatches = new SortedVector<AllMatches>(new AllMatches.AvgComparator());
+        maxmatches = new SortedVector<AllMatches>(new AllMatches.MaxComparator());
+
+        long msec;
+
+        AllBasecodeMatches bcmatch;
+        Submission s1, s2;
+
+        options.setState(Options.COMPARING);
+        options.setProgress(0);
+
+        if (this.options.useBasecode) {
+            //			print("\nComparing with Basecode:\n", validSubmissions()
+            //					+ " submissions");
+            int countBC = 0;
+            // System.out.println("BC size: "+basecodeSubmission.size());
+            msec = System.currentTimeMillis();
+            for (int i = 0; i < (size); i++) {
+                s1 = submissions.elementAt(i);
+                // System.out.println("basecode recognition for: "+s1.name);
+                bcmatch = this.gSTiling.compareWithBasecode(s1, basecodeSubmission);
+                htBasecodeMatches.put(s1.name, bcmatch);
+                this.gSTiling.resetBaseSubmission(basecodeSubmission);
+                countBC++;
+                options.setProgress(countBC * 100 / size);
+            }
+            long timebc = System.currentTimeMillis() - msec;
+            print("\n\n", "\nTime for comparing with Basecode: " + ((timebc / 3600000 > 0) ? (timebc / 3600000) + " h " : "")
+                    + ((timebc / 60000 > 0) ? ((timebc / 60000) % 60000) + " min " : "") + (timebc / 1000 % 60) + " sec\n"
+                    + "Time per basecode comparison: " + (timebc / size) + " msec\n\n");
+        }
+
+        //		print("\nComparing:\n", validSubmissions() + " submissions");
+
+        int totalcomps = (size - 1) * size / 2;
+        int i, j, anz = 0, count = 0;
+        AllMatches match;
+
+        options.setProgress(0);
+        msec = System.currentTimeMillis();
+
+        for (i = 0; i < (size - 1); i++) {
+            s1 = submissions.elementAt(i);
+            if (s1.struct == null) {
+                count += (size - i - 1);
+                continue;
+            }
+
+            for (j = (i + 1); j < size; j++) {
+                s2 = submissions.elementAt(j);
+                if (s2.struct == null) {
+                    count++;
+                    continue;
+                }
+
+                match = this.gSTiling.compare(s1, s2);
+
+                anz++;
+
+                System.out.println("Comparing " + s1.name + "-" + s2.name + ": " + match.percent());
+
+                // histogram:
+                if (options.useBasecode) {
+                    match.bcmatchesA = htBasecodeMatches.get(match.subA.name);
+                    match.bcmatchesB = htBasecodeMatches.get(match.subB.name);
+                }
+
+                registerMatch(match, dist, avgmatches, maxmatches, null, i, j);
+                count++;
+                options.setProgress(count * 100 / totalcomps);
+            }
+        }
+        options.setProgress(100);
+        long time = System.currentTimeMillis() - msec;
+
+        print("\n", "Total time for comparing submissions: " + ((time / 3600000 > 0) ? (time / 3600000) + " h " : "")
+                + ((time / 60000 > 0) ? ((time / 60000) % 60000) + " min " : "") + (time / 1000 % 60) + " sec\n" + "Time per comparison: "
+                + (time / anz) + " msec\n");
+
+        Cluster cluster = null;
+        if (options.clustering)
+            cluster = this.clusters.calculateClustering(submissions);
+
+        writeResults(dist, avgmatches, maxmatches, null, cluster);
+    }
+
+    /**
+     * Revision compare mode: Compare each submission only with its next
+     * submission.
+     */
+    private void revisionCompare() throws jplag.ExitException {
+        int size = submissions.size();
+
+        SortedVector<AllMatches> avgmatches, maxmatches, minmatches;
+        int[] dist = new int[10];
+
+        // Result vector
+        avgmatches = new SortedVector<AllMatches>(new AllMatches.AvgReversedComparator());
+        maxmatches = new SortedVector<AllMatches>(new AllMatches.MaxReversedComparator());
+        minmatches = new SortedVector<AllMatches>(new AllMatches.MinReversedComparator());
+
+        long msec;
+
+        AllBasecodeMatches bcmatch;
+        Submission s1, s2;
+
+        options.setState(Options.COMPARING);
+        options.setProgress(0);
+
+        if (options.useBasecode) {
+            msec = System.currentTimeMillis();
+            for (int i = 0; i < size; i++) {
+                s1 = submissions.elementAt(i);
+                bcmatch = gSTiling.compareWithBasecode(s1, basecodeSubmission);
+                htBasecodeMatches.put(s1.name, bcmatch);
+                gSTiling.resetBaseSubmission(basecodeSubmission);
+                options.setProgress((i + 1) * 100 / size);
+            }
+            long timebc = System.currentTimeMillis() - msec;
+            print("\n\n", "\nTime for comparing with Basecode: " + ((timebc / 3600000 > 0) ? (timebc / 3600000) + " h " : "")
+                    + ((timebc / 60000 > 0) ? ((timebc / 60000) % 60000) + " min " : "") + (timebc / 1000 % 60) + " sec\n"
+                    + "Time per basecode comparison: " + (timebc / size) + " msec\n\n");
+        }
+
+        int totalcomps = size - 1;
+        int anz = 0, count = 0;
+        AllMatches match;
+
+        options.setProgress(0);
+        msec = System.currentTimeMillis();
+
+        s1loop:
+        for (int i = 0; i < size - 1; ) {
+            s1 = submissions.elementAt(i);
+            if (s1.struct == null) {
+                count++;
+                continue;
+            }
+
+            // Find next valid submission
+            int j = i;
+            do {
+                j++;
+                if (j >= size)
+                    break s1loop; // no more comparison pairs available
+                s2 = submissions.elementAt(j);
+            } while (s2.struct == null);
+
+            match = this.gSTiling.compare(s1, s2);
+
+            anz++;
+
+            /*
+             * System.out.println("Comparing "+s1.name+"-"+s2.name+": "+
+             * match.percent());
+             */
+            // histogram:
+            if (options.useBasecode) {
+                match.bcmatchesA = htBasecodeMatches.get(match.subA.name);
+                match.bcmatchesB = htBasecodeMatches.get(match.subB.name);
+            }
+
+            registerMatch(match, dist, avgmatches, maxmatches, minmatches, i, j);
+            count++;
+            options.setProgress(count * 100 / totalcomps);
+
+            i = j;
+        }
+        options.setProgress(100);
+        long time = System.currentTimeMillis() - msec;
+
+        print("\n", "Total time for comparing submissions: " + ((time / 3600000 > 0) ? (time / 3600000) + " h " : "")
+                + ((time / 60000 > 0) ? ((time / 60000) % 60000) + " min " : "") + (time / 1000 % 60) + " sec\n" + "Time per comparison: "
+                + (time / anz) + " msec\n");
+
+        Cluster cluster = null;
+        if (options.clustering)
+            cluster = this.clusters.calculateClustering(submissions);
+
+        writeResults(dist, avgmatches, maxmatches, minmatches, cluster);
+    }
+
+    private void createSubmissions() throws jplag.ExitException {
+        submissions = new Vector<Submission>();
+        File f = new File(options.root_dir);
+        if (f == null || !f.isDirectory()) {
+            throw new jplag.ExitException("\"" + options.root_dir + "\" is not a directory!");
+        }
+        String[] list = null;
+        try {
+            list = f.list();
+        } catch (SecurityException e) {
+            throw new jplag.ExitException("Unable to retrieve directory: " + options.root_dir + " Cause : " + e.toString());
+        }
+        Arrays.sort(list);
+
+        for (int i = 0; i < list.length; i++) {
+            File subm_dir = new File(f, list[i]);
+            if (!subm_dir.isDirectory()) {
+                if (options.sub_dir != null)
+                    continue;
+
+                boolean ok = false;
+                String name = subm_dir.getName();
+                for (int j = 0; j < options.suffixes.length; j++)
+                    if (name.endsWith(options.suffixes[j])) {
+                        ok = true;
+                        break;
+                    }
+
+                if (!ok)
+                    continue;
+
+                submissions.addElement(new Submission(name, f, this, get_language()));
+                continue;
+            }
+            if (options.exp && excludeFile(subm_dir.toString())) { // EXPERIMENT
+                // !!
+                System.err.println("excluded: " + subm_dir);
+                continue;
+            }
+
+            File file_dir = ((options.sub_dir == null) ? // - S option
+                    subm_dir
+                    : new File(subm_dir, options.sub_dir));
+            if (file_dir.isDirectory()) {
+                if (options.basecode.equals(subm_dir.getName())) {
+                    basecodeSubmission = new Submission(subm_dir.getName(), file_dir, options.read_subdirs, this, get_language());
+                } else {
+                    submissions.addElement(new Submission(subm_dir.getName(), file_dir, options.read_subdirs, this, get_language())); // -s
+                }
+            } else
+                throw new ExitException("Cannot find directory: " + file_dir.toString());
+        }
+    }
+
+    /**
+     * THIS IS FOR THE EMPIRICAL STUDY
+     */
+    private void createSubmissionsExp() throws jplag.ExitException {
+        // ES IST SICHER, DASS EIN INCLUDE-FILE ANGEGEBEN WURDE!
+        readIncludeFile();
+        submissions = new Vector<Submission>();
+        File f = new File(options.root_dir);
+        if (f == null || !f.isDirectory()) {
+            throw new jplag.ExitException(options.root_dir + " is not a directory!");
+        }
+        String[] list = new String[included.size()];
+        included.copyInto(list);
+        for (int i = 0; i < list.length; i++) {
+            File subm_dir = new File(f, list[i]);
+            if (subm_dir == null || !subm_dir.isDirectory())
+                continue;
+            if (options.exp && excludeFile(subm_dir.toString())) { // EXPERIMENT
+                // !!
+                System.err.println("excluded: " + subm_dir);
+                continue;
+            }
+            File file_dir = ((options.sub_dir == null) ? // - S option
+                    subm_dir
+                    : new File(subm_dir, options.sub_dir));
+            if (file_dir != null && file_dir.isDirectory())
+                submissions.addElement(new Submission(subm_dir.getName(), file_dir, options.read_subdirs, this, this.get_language())); // -s
+            else if (options.sub_dir == null) {
+                throw new jplag.ExitException(options.root_dir + " is not a directory!");
+            }
+        }
+    }
+
+    /**
+     * Check if a file is excluded or not
+     */
+    protected boolean excludeFile(String file) {
+        if (excluded == null)
+            return false;
+        Iterator<String> iter = excluded.iterator();
+        while (iter.hasNext())
+            if (file.endsWith(iter.next()))
+                return true;
+        return false;
+    }
+
+    // EXPERIMENT !!!!! special compare routine!
+    private void expCompare() throws jplag.ExitException {
+        int size = validSubmissions();
+        int[] similarity = new int[(size * size - size) / 2];
+
+        int anzSub = submissions.size();
+        int i, j, count = 0;
+        Submission s1, s2;
+        AllMatches match;
+        long msec = System.currentTimeMillis();
+        for (i = 0; i < (anzSub - 1); i++) {
+            s1 = submissions.elementAt(i);
+            if (s1.struct == null)
+                continue;
+            for (j = (i + 1); j < anzSub; j++) {
+                s2 = submissions.elementAt(j);
+                if (s2.struct == null)
+                    continue;
+
+                match = this.gSTiling.compare(s1, s2);
+                similarity[count++] = (int) match.percent();
+            }
+        }
+        long time = System.currentTimeMillis() - msec;
+        // output
+        System.out.print(options.root_dir + " ");
+        System.out.print(options.min_token_match + " ");
+        System.out.print(options.filtername + " ");
+        System.out.print((time) + " ");
+        for (i = 0; i < similarity.length; i++)
+            System.out.print(similarity[i] + " ");
+        System.out.println();
+    }
+
+    /**
+     * This is the special external comparison routine
+     */
+    private void externalCompare() throws jplag.ExitException {
+        int size = submissions.size();
+        // Progress progress;
+        // Result vector
+        SortedVector<AllMatches> avgmatches = new SortedVector<AllMatches>(new AllMatches.AvgComparator());
+        SortedVector<AllMatches> maxmatches = new SortedVector<AllMatches>(new AllMatches.MaxComparator());
+        int[] dist = new int[10];
+
+        print("Comparing: " + size + " submissions\n", null);
+        options.setState(Options.COMPARING);
+        options.setProgress(0);
+        long totalComparisons = (size * (size - 1)) / 2, count = 0, comparisons = 0;
+        int index = 0;
+        AllMatches match;
+        Submission s1, s2;
+        long remain;
+        String totalTimeStr, remainTime;
+
+        print("Checking memory size...\n", null);
+        // First try to load as many submissions as possible
+        index = fillMemory(0, size);
+
+        long startTime;
+        long totalTime = 0;
+        int startA = 0;
+        int endA = index / 2;
+        int startB = endA + 1;
+        int endB = index;
+        int i, j;
+        //		long progStart;
+
+        do {
+            // compare A to A
+            startTime = System.currentTimeMillis();
+            print("Comparing block A (" + startA + "-" + endA + ") to block A\n", null);
+            //progStart = (endA - startA + 1) * (endA - startA) / 2;
+            //      progress = new Progress(progStart > 0 ? progStart : 1, this);
+            //progStart = count;
+            for (i = startA; i <= endA; i++) {
+                //        progress.set(count - progStart);
+                options.setProgress((int) (count * 100 / totalComparisons));
+                s1 = submissions.elementAt(i);
+                if (s1.struct == null) {
+                    count += (endA - i);
+                    continue;
+                }
+                for (j = (i + 1); j <= endA; j++) {
+                    s2 = submissions.elementAt(j);
+                    if (s2.struct == null) {
+                        count++;
+                        continue;
+                    }
+
+                    match = this.gSTiling.compare(s1, s2);
+                    registerMatch(match, dist, avgmatches, maxmatches, null, i, j);
+                    comparisons++;
+                    count++;
+                }
+            }
+            //      progress.set(count - progStart);
+            options.setProgress((int) (count * 100 / totalComparisons));
+            print("\n", null);
+            totalTime += System.currentTimeMillis() - startTime;
+
+            // Are we finished?
+            if (startA == startB)
+                break;
+
+            do {
+                totalTimeStr = "" + ((totalTime / 3600000 > 0) ? (totalTime / 3600000) + " h " : "")
+                        + ((totalTime / 60000 > 0) ? ((totalTime / 60000) % 60) + " min " : "") + (totalTime / 1000 % 60) + " sec";
+                if (comparisons != 0)
+                    remain = totalTime * (totalComparisons - count) / comparisons;
+                else
+                    remain = 0;
+                remainTime = "" + ((remain / 3600000 > 0) ? (remain / 3600000) + " h " : "")
+                        + ((remain / 60000 > 0) ? ((remain / 60000) % 60) + " min " : "") + (remain / 1000 % 60) + " sec";
+
+                print("Progress: " + (100 * count) / totalComparisons + "%\nTime used for comparisons: " + totalTimeStr
+                        + "\nRemaining time (estimate): " + remainTime + "\n", null);
+
+                // compare A to B
+                startTime = System.currentTimeMillis();
+                print("Comparing block A (" + startA + "-" + endA + ") to block B (" + startB + "-" + endB + ")\n", null);
+                //progStart = (endA - startA + 1) * (endB - startB + 1);
+                //        progress = new Progress(progStart > 0 ? progStart : 1, this);
+                //progStart = count;
+                for (i = startB; i <= endB; i++) {
+                    //          progress.set(count - progStart);
+                    options.setProgress((int) (count * 100 / totalComparisons));
+                    s1 = submissions.elementAt(i);
+                    if (s1.struct == null) {
+                        count += (endA - startA + 1);
+                        continue;
+                    }
+                    for (j = startA; j <= endA; j++) {
+                        s2 = submissions.elementAt(j);
+                        if (s2.struct == null) {
+                            count++;
+                            continue;
+                        }
+
+                        match = this.gSTiling.compare(s1, s2);
+                        registerMatch(match, dist, avgmatches, maxmatches, null, i, j);
+                        comparisons++;
+                        count++;
+                    }
+                    s1.struct = null; // remove B
+                }
+                //        progress.set(count - progStart);
+                options.setProgress((int) (count * 100 / totalComparisons));
+                print("\n", null);
+                totalTime += System.currentTimeMillis() - startTime;
+
+                if (endB == size - 1) {
+                    totalTimeStr = "" + ((totalTime / 3600000 > 0) ? (totalTime / 3600000) + " h " : "")
+                            + ((totalTime / 60000 > 0) ? ((totalTime / 60000) % 60) + " min " : "") + (totalTime / 1000 % 60) + " sec";
+                    remain = totalTime * (totalComparisons - count) / comparisons;
+                    remainTime = "" + ((remain / 3600000 > 0) ? (remain / 3600000) + " h " : "")
+                            + ((remain / 60000 > 0) ? ((remain / 60000) % 60) + " min " : "") + (remain / 1000 % 60) + " sec";
+
+                    print("Progress: " + (100 * count) / totalComparisons + "%\nTime used for comparisons: " + totalTimeStr
+                            + "\nRemaining time (estimate): " + remainTime + "\n", null);
+                    break;
+                }
+
+                // Remove B -> already done...
+                // for (i=startB; i<=endB; i++)
+                // ((Submission)submissions.elementAt(i)).struct = null;
+                runtime.runFinalization();
+                runtime.gc();
+                Thread.yield();
+                // Try to find the next B
+                print("Finding next B\n", null);
+
+                index = fillMemory(endB + 1, size);
+
+                startB = endB + 1;
+                endB = index;
+
+            } while (true);
+
+            // Remove A
+            for (i = startA; i <= endA; i++)
+                submissions.elementAt(i).struct = null;
+            runtime.runFinalization();
+            runtime.gc();
+            Thread.yield();
+            print("Find next A.\n", null);
+            // First try to load as many submissions as possible
+
+            index = fillMemory(endA + 1, size);
+
+            if (index != size - 1) {
+                startA = endA + 1;
+                endA = startA + (index - startA + 1) / 2;
+                startB = endA + 1;
+                endB = index;
+            } else {
+                startA = startB; // last block
+                endA = endB = index;
+            }
+        } while (true);
+
+        totalTime += System.currentTimeMillis() - startTime;
+        totalTimeStr = "" + ((totalTime / 3600000 > 0) ? (totalTime / 3600000) + " h " : "")
+                + ((totalTime / 60000 > 0) ? ((totalTime / 60000) % 60000) + " min " : "") + (totalTime / 1000 % 60) + " sec";
+
+        print("Total comparison time: " + totalTimeStr + "\nComparisons: " + count + "/" + comparisons + "/" + totalComparisons + "\n",
+                null);
+
+        // free remaining memory
+        for (i = startA; i <= endA; i++)
+            submissions.elementAt(i).struct = null;
+        runtime.runFinalization();
+        runtime.gc();
+        Thread.yield();
+
+        // System.out.println("Matrix:\n"+ similarity);
+        Cluster cluster = null;
+        if (options.clustering)
+            cluster = this.clusters.calculateClustering(submissions);
+
+        writeResults(dist, avgmatches, maxmatches, null, cluster);
+    }
+
+    private int fillMemory(int from, int size) {
+        Submission sub = null;
+        int index = from;
+
+        runtime.runFinalization();
+        runtime.gc();
+        Thread.yield();
+        long freeBefore = runtime.freeMemory();
+        try {
+            for (; index < size; index++) {
+                sub = submissions.elementAt(index);
+                sub.struct = new Structure();
+                if (!sub.struct.load(new File("temp", sub.dir.getName() + sub.name)))
+                    sub.struct = null;
+            }
+        } catch (java.lang.OutOfMemoryError e) {
+            sub.struct = null;
+            print("Memory overflow after loading " + (index - from + 1) + " submissions.\n", null);
+        }
+        if (index >= size)
+            index = size - 1;
+
+        if (freeBefore / runtime.freeMemory() <= 2)
+            return index;
+        for (int i = (index - from) / 2; i > 0; i--) {
+            submissions.elementAt(index--).struct = null;
+        }
+        runtime.runFinalization();
+        runtime.gc();
+        Thread.yield();
+
+        // make sure we freed half of the "available" memory.
+        long free;
+        while (freeBefore / (free = runtime.freeMemory()) > 2) {
+            submissions.elementAt(index--).struct = null;
+            runtime.runFinalization();
+            runtime.gc();
+            Thread.yield();
+        }
+        print(free / 1024 / 1024 + "MByte freed. Current index: " + index + "\n", null);
+
+        return index;
+    }
+
+    public String get_basecode() {
+        return this.options.basecode;
+    }
+
+    public int get_clusterType() {
+        return this.options.clusterType;
+    }
+
+    public String get_commandLine() {
+        return this.options.commandLine;
+    }
+
+    public String getCountryTag() {
+        return options.getCountryTag();
+    }
+
+    /*
+     * Distribution: Program given away to:
+     *
+     * 0: Server version
+     *
+     * 1: David Klausner 2: Ronald Kostoff 3: Bob Carlson 4: Neville Newman
+     */
+
+    public int get_distri() {
+        return 0;
+    }
+
+    public File get_jplagResult() {
+        return new File(options.result_dir);
+
+    }
+
+    public Language get_language() {
+        return this.options.language;
+    }
+
+    public int get_min_token_match() {
+        return this.options.min_token_match;
+    }
+
+    public String get_title() {
+        return this.options.title;
+    }
+
+    public String get_original_dir() {
+        return this.options.original_dir;
+    }
+
+    public String get_result_dir() {
+        return this.options.result_dir;
+    }
+
+    public String get_root_dir() {
+        return this.options.root_dir;
+    }
+
+    public SimilarityMatrix get_similarity() {
+        return this.options.similarity;
+    }
+
+    public String get_sub_dir() {
+        return this.options.sub_dir;
+    }
+
+    public String[] get_suffixes() {
+        return this.options.suffixes;
+    }
+
+    public int[] get_themewords() {
+        return this.options.themewords;
+    }
+
+    public float[] get_threshold() {
+        return this.options.threshold;
+    }
+
+    public int getErrors() {
+        return errors;
+    }
+
+    public void hash_distribution() {
+        int[] dist = new int[20];
+        int count = 0;
+        Enumeration<Submission> enum1 = submissions.elements();
+
+        while (enum1.hasMoreElements()) {
+            Structure struct = enum1.nextElement().struct;
+            if (struct != null) {
+                struct.table.count_dist(dist);
+                count++;
+            }
+        }
+
+        System.out.println("Count: " + count);
+        for (int i = 0; i < dist.length; i++)
+            System.out.println(i + "\t" + dist[i]);
+    }
+
+    private void makeTempDir() throws jplag.ExitException {
+        print(null, "Creating temporary dir.\n");
+        File f = new File("temp");
+        if (!f.exists()) {
+            if (!f.mkdirs()) {
+                throw new jplag.ExitException("Cannot create temporary directory!");
+            }
+        }
+        if (!f.isDirectory()) {
+            throw new ExitException("'temp' is not a directory!");
+        }
+        if (!f.canWrite()) {
+            throw new ExitException("Cannot write directory: 'temp'");
+        }
+    }
+
+    private void myWrite(String str) {
+        if (writer != null) {
+            try {
+                writer.write(str);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        } else
+            System.out.print(str);
+    }
+
+    // PARSE
+    /*
+     * Compiles all "submissions"
+     */
+    private void parseAll() throws jplag.ExitException {
+        if (submissions == null) {
+            System.out.println("  Nothing to parse!");
+            return;
+        }
+        // lets go:)
+        int count = 0;
+        int totalcount = submissions.size();
+        options.setState(Options.PARSING);
+        options.setProgress(0);
+        long msec = System.currentTimeMillis();
+        Iterator<Submission> iter = submissions.iterator();
+
+        if (options.externalSearch)
+            makeTempDir();
+        int invalid = 0;
+        while (iter.hasNext()) {
+            boolean ok = true;
+            boolean removed = false;
+            Submission subm = iter.next();
+            print(null, "------ Parsing submission: " + subm.name + "\n");
+            currentSubmissionName = subm.name;
+            options.setProgress(count * 100 / totalcount);
+            if (!(ok = subm.parse()))
+                errors++;
+
+            if (options.exp && options.filter != null)
+                subm.struct = options.filter.filter(subm.struct); // EXPERIMENT
+            count++;
+            if (subm.struct != null && subm.size() < options.min_token_match) {
+                print(null, "Submission contains fewer tokens than minimum match " + "length allows!\n");
+                subm.struct = null;
+                invalid++;
+                removed = true;
+            }
+            if (options.externalSearch) {
+                if (subm.struct != null) {
+                    this.gSTiling.create_hashes(subm.struct, options.min_token_match, false);
+                    subm.struct.save(new File("temp", subm.dir.getName() + subm.name));
+                    subm.struct = null;
+                }
+            }
+            if (!options.externalSearch && subm.struct == null) {
+                invalidSubmissionNames = (invalidSubmissionNames == null) ? subm.name : invalidSubmissionNames + " - " + subm.name;
+                iter.remove();
+            }
+            if (ok && !removed)
+                print(null, "OK\n");
+            else
+                print(null, "ERROR -> Submission removed\n");
+        }
+
+        options.setProgress(100);
+        print("\n" + (count - errors - invalid) + " submissions parsed successfully!\n" + errors + " parser error"
+                + (errors != 1 ? "s!\n" : "!\n"), null);
+        if (invalid != 0) {
+            print(null, invalid
+                    + ((invalid == 1) ? " submission is not valid because it contains" : " submissions are not valid because they contain")
+                    + " fewer tokens\nthan minimum match length allows.\n");
+        }
+        long time = System.currentTimeMillis() - msec;
+        print("\n\n", "\nTotal time for parsing: " + ((time / 3600000 > 0) ? (time / 3600000) + " h " : "")
+                + ((time / 60000 > 0) ? ((time / 60000) % 60000) + " min " : "") + (time / 1000 % 60) + " sec\n"
+                + "Time per parsed submission: " + (count > 0 ? (time / count) : "n/a") + " msec\n\n");
+    }
+
+    private void parseBasecodeSubmission() throws jplag.ExitException {
+        Submission subm = basecodeSubmission;
+        if (subm == null) {
+            options.useBasecode = false;
+            return;
+        }
+        long msec = System.currentTimeMillis();
+        print("----- Parsing basecode submission: " + subm.name + "\n", null);
+
+        // lets go:
+        if (options.externalSearch)
+            makeTempDir();
+
+        if (!subm.parse())
+            throwBadBasecodeSubmission();
+
+        if (options.exp && options.filter != null)
+            subm.struct = options.filter.filter(subm.struct); // EXPERIMENT
+
+        if (subm.struct != null && subm.size() < options.min_token_match)
+            throw new ExitException("Basecode submission contains fewer tokens " + "than minimum match length allows!\n");
+
+        if (options.useBasecode)
+            gSTiling.create_hashes(subm.struct, options.min_token_match, true);
+        if (options.externalSearch) {
+            if (subm.struct != null) {
+                gSTiling.create_hashes(subm.struct, options.min_token_match, false);
+                subm.struct.save(new File("temp", subm.dir.getName() + subm.name));
+                subm.struct = null;
+            }
+        }
+
+        print("\nBasecode submission parsed!\n", null);
+        long time = System.currentTimeMillis() - msec;
+        print("\n", "\nTime for parsing Basecode: " + ((time / 3600000 > 0) ? (time / 3600000) + " h " : "")
+                + ((time / 60000 > 0) ? ((time / 60000) % 60000) + " min " : "") + (time / 1000 % 60) + " sec\n");
+    }
+
+    // Excluded files:
+
+    /*
+     * If an exclusion file is given, it is read in and all stings are saved in
+     * the set "excluded".
+     */
+    private void readExclusionFile() {
+        if (options.exclude_file == null)
+            return;
+        excluded = new HashSet<String>();
+
+        try {
+            BufferedReader in = new BufferedReader(new FileReader(options.exclude_file));
+            String line;
+            while ((line = in.readLine()) != null) {
+                excluded.add(line.trim());
+            }
+            in.close();
+        } catch (FileNotFoundException e) {
+            System.out.println("Exclusion file not found: " + options.exclude_file);
+        } catch (IOException e) {
+        }
+        print(null, "Excluded files:\n");
+        if (options.verbose_long) {
+            Iterator<String> iter = excluded.iterator();
+            while (iter.hasNext()) {
+                print(null, "  " + iter.next() + "\n");
+            }
+        }
+    }
+
+    /*
+     * If an include file is given, read it in and store all the strings in
+     * "included".
+     */
+    private void readIncludeFile() {
+        if (options.include_file == null)
+            return;
+        included = new Vector<String>();
+        try {
+            BufferedReader in = new BufferedReader(new FileReader(options.include_file));
+            String line;
+            while ((line = in.readLine()) != null) {
+                included.addElement(line.trim());
+            }
+            in.close();
+        } catch (FileNotFoundException e) {
+            System.out.println("Include file not found: " + options.include_file);
+        } catch (IOException e) {
+        }
+        print(null, "Included dirs:\n");
+        if (options.verbose_long) {
+            Enumeration<String> enum1 = included.elements();
+            while (enum1.hasMoreElements())
+                print(null, "  " + enum1.nextElement() + "\n");
+        }
+    }
+
+    private void registerMatch(AllMatches match, int[] dist, SortedVector<AllMatches> avgmatches, SortedVector<AllMatches> maxmatches,
+                               SortedVector<AllMatches> minmatches, int a, int b) {
+        float avgpercent = match.percent();
+        float maxpercent = match.percentMaxAB();
+        float minpercent = match.percentMinAB();
+
+        dist[((((int) avgpercent) / 10) == 10) ? 9 : (((int) avgpercent) / 10)]++;
+        if (!options.store_percent) {
+            if ((avgmatches.size() < options.store_matches || avgpercent > avgmatches.lastElement().percent()) && avgpercent > 0) {
+                avgmatches.insert(match);
+                if (avgmatches.size() > options.store_matches)
+                    avgmatches.removeElementAt(options.store_matches);
+            }
+            if (maxmatches != null && (maxmatches.size() < options.store_matches || maxpercent > maxmatches.lastElement().percent())
+                    && maxpercent > 0) {
+                maxmatches.insert(match);
+                if (maxmatches.size() > options.store_matches)
+                    maxmatches.removeElementAt(options.store_matches);
+            }
+            if (minmatches != null && (minmatches.size() < options.store_matches || minpercent > minmatches.lastElement().percent())
+                    && minpercent > 0) {
+                minmatches.insert(match);
+                if (minmatches.size() > options.store_matches)
+                    minmatches.removeElementAt(options.store_matches);
+            }
+        } else { // store_percent
+            if (avgpercent > options.store_matches) {
+                avgmatches.insert(match);
+                if (avgmatches.size() > Options.MAX_RESULT_PAIRS)
+                    avgmatches.removeElementAt(Options.MAX_RESULT_PAIRS);
+            }
+
+            if (maxmatches != null && maxpercent > options.store_matches) {
+                maxmatches.insert(match);
+                if (maxmatches.size() > Options.MAX_RESULT_PAIRS)
+                    maxmatches.removeElementAt(Options.MAX_RESULT_PAIRS);
+            }
+
+            if (minmatches != null && minpercent > options.store_matches) {
+                minmatches.insert(match);
+                if (minmatches.size() > Options.MAX_RESULT_PAIRS)
+                    minmatches.removeElementAt(Options.MAX_RESULT_PAIRS);
+            }
+        }
+        if (options.clustering)
+            options.similarity.setSimilarity(a, b, avgpercent);
+    }
+
+    private String toUTF8(String str) {
+        byte[] utf8 = null;
+        try {
+            utf8 = str.getBytes("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+        }
+        return new String(utf8);
+    }
+
+    /** *************************** */
+    /* THE MAIN PROCEDURE */
+
+    /**
+     * **************************
+     */
+    public void run() throws jplag.ExitException {
+        if (options.output_file != null) {
+            try {
+                writer = new FileWriter(new File(options.output_file));
+                writer.write(name_long + "\n");
+                writer.write(dateTimeFormat.format(new Date()) + "\n\n");
+            } catch (IOException ex) {
+                System.out.println("Unable to open or write to log file: " + options.output_file);
+                throw new ExitException("Unable to create log file!");
+            }
+        } else
+            print(null, name_long + "\n\n");
+        print(null, "Language: " + options.language.name() + "\n\n");
+        if (options.original_dir == null)
+            print(null, "Root-dir: " + options.root_dir + "\n"); // server
+        // this file contains all files names which are excluded
+        readExclusionFile();
+        if (options.include_file == null) {
+            createSubmissions();
+            System.out.println(submissions.size() + " submissions");
+        } else
+            createSubmissionsExp();
+
+        if (!options.skipParse) {
+            try {
+                parseAll();
+                System.gc();
+                parseBasecodeSubmission();
+            } catch (OutOfMemoryError e) {
+                submissions = null;
+                System.gc();
+                System.out.println("[" + new Date() + "] OutOfMemoryError " + "during parsing of submission \"" + currentSubmissionName
+                        + "\"");
+                throw new ExitException("Out of memory during parsing of submission \"" + currentSubmissionName + "\"");
+            } catch (ExitException e) {
+                throw e;
+            } catch (Throwable e) {
+                System.out.println("[" + new Date() + "] Unknown exception " + "during parsing of submission \"" + currentSubmissionName
+                        + "\"");
+                e.printStackTrace();
+                throw new ExitException("Unknown exception during parsing of " + "submission \"" + currentSubmissionName + "\"");
+            }
+        } else
+            print("Skipping parsing...\n", null);
+
+        if (validSubmissions() < 2) {
+            throwNotEnoughSubmissions();
+        }
+        errorVector = null; // errorVector is not needed anymore
+
+        if (options.clustering) {
+            clusters = new Clusters(this);
+            options.similarity = new SimilarityMatrix(submissions.size());
+        }
+        System.gc();
+        if (options.exp) { // EXPERIMENT
+            expCompare();
+        } else if (options.externalSearch) {
+            try {
+                externalCompare();
+            } catch (OutOfMemoryError e) {
+                e.printStackTrace();
+            }
+        } else {
+            if (options.compare > 0)
+                specialCompare(); // compare every submission to x others
+            else {
+                switch (options.comparisonMode) {
+                    case Options.COMPMODE_NORMAL:
+                        compare();
+                        break;
+
+                    case Options.COMPMODE_REVISION:
+                        revisionCompare();
+                        break;
+
+                    default:
+                        throw new ExitException("Illegal comparison mode: \"" + options.comparisonMode + "\"");
+                }
+            }
+        }
+        closeWriter();
+
+        String str = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>";
+        str += "<jplag_infos>\n";
+        str += "<infos \n";
+
+        String sp = "\"";
+        str += " title = " + sp + toUTF8(options.getTitle()) + sp;
+        str += " source = " + sp + (get_original_dir() != null ? toUTF8(get_original_dir()) : "") + sp;
+        str += " n_of_programs = " + sp + submissions.size() + sp;
+        str += " errors = " + sp + get_language().errorsCount() + sp;
+        str += " path_to_files = " + sp + toUTF8((options.sub_dir != null) ? options.sub_dir : "") + sp;
+        str += " basecode_dir = " + sp + toUTF8((options.basecode != null) ? options.basecode : "") + sp;
+        str += " read_subdirs = " + sp + this.options.read_subdirs + sp;
+        str += " clustertype = " + sp + this.options.getClusterTyp() + sp;
+        str += " store_matches = " + sp + this.options.store_matches + ((this.options.store_percent) ? "%" : "") + sp;
+        String suf = "";
+        for (int s = 0; s < this.options.suffixes.length; s++)
+            suf += "," + this.options.suffixes[s];
+        str += " suffixes = " + sp + suf.substring(1) + sp;
+        str += " language_name = " + sp + this.options.languageName + sp;
+        str += " comparison_mode = " + sp + this.options.comparisonMode + sp;
+        str += " country_tag = " + sp + this.options.getCountryTag() + sp;
+        str += " min_token = " + sp + this.options.min_token_match + sp;
+        str += " date = " + sp + System.currentTimeMillis() + sp;
+
+        str += "/>\n";
+        str += "</jplag_infos>";
+
+        try {
+            FileWriter fw = new FileWriter(new File(this.options.result_dir + File.separator + "result.xml"));
+            fw.write(str);
+            fw.close();
+        } catch (IOException ex) {
+            System.out.println("Unable to create result.xml");
+        }
+    }
+
+    public void set_result_dir(String result_dir) {
+        this.options.result_dir = result_dir;
+    }
+
+    /*
+     * Now the special comparison:
+     */
+    private void specialCompare() throws jplag.ExitException {
+        File root = new File(options.result_dir);
+        HTMLFile f = this.report.openHTMLFile(root, "index.html");
+        this.report.copyFixedFiles(root);
+
+        this.report.writeIndexBegin(f, "Special Search Results"); // start HTML
+        f.println("<P><A NAME=\"matches\"><H4>Matches:</H4><P>");
+
+        int size = submissions.size();
+        int matchIndex = 0;
+
+        print("Comparing: ", validSubmissions() + " submissions");
+        print("\n(Writing results at the same time.)\n", null);
+
+        options.setState(Options.COMPARING);
+        options.setProgress(0);
+        int totalcomps = size * size;
+        int i, j, anz = 0, count = 0;
+        AllMatches match;
+        Submission s1, s2;
+        long msec = System.currentTimeMillis();
+        for (i = 0; i < (size - 1); i++) {
+            // Result vector
+            SortedVector<AllMatches> matches = new SortedVector<AllMatches>(new AllMatches.AvgComparator());
+
+            s1 = submissions.elementAt(i);
+            if (s1.struct == null) {
+                count += (size - 1);
+                continue;
+            }
+            for (j = 0; j < size; j++) {
+                s2 = submissions.elementAt(j);
+                if ((i == j) || (s2.struct == null)) {
+                    count++;
+                    continue;
+                }
+
+                match = this.gSTiling.compare(s1, s2);
+                anz++;
+
+                float percent = match.percent();
+
+                if ((matches.size() < options.compare || matches.size() == 0 || match.moreThan(matches.lastElement().percent()))
+                        && match.moreThan(0)) {
+                    matches.insert(match);
+                    if (matches.size() > options.compare)
+                        matches.removeElementAt(options.compare);
+                }
+
+                if (options.clustering)
+                    options.similarity.setSimilarity(i, j, percent);
+
+                count++;
+                options.setProgress(count * 100 / totalcomps);
+            }
+
+            // now output matches:
+            f.println("<TABLE CELLPADDING=3 CELLSPACING=2>");
+            boolean once = true;
+            for (Iterator<AllMatches> iter = matches.iterator(); iter.hasNext(); ) {
+                match = iter.next();
+                if (once) {
+                    f.println("<TR><TD BGCOLOR=" + this.report.color(match.percent(), 128, 192, 128, 192, 255, 255) + ">" + s1.name
+                            + "<TD WIDTH=\"10\">-&gt;");
+                    once = false;
+                }
+
+                int other = (match.subName(0).equals(s1.name) ? 1 : 0);
+                f.println(" <TD BGCOLOR=" + this.report.color(match.percent(), 128, 192, 128, 192, 255, 255)
+                        + " ALIGN=center><A HREF=\"match" + matchIndex + ".html\">" + match.subName(other) + "</A><BR><FONT COLOR=\""
+                        + this.report.color(match.percent(), 0, 255, 0, 0, 0, 0) + "\"><B>(" + match.roundedPercent() + "%)</B></FONT>");
+                this.report.writeMatch(root, matchIndex++, match);
+            }
+            f.println("</TR>");
+        }
+        f.println("</TABLE><P>\n");
+        f.println("<!---->");
+        this.report.writeIndexEnd(f);
+        f.close();
+
+        options.setProgress(100);
+        long time = System.currentTimeMillis() - msec;
+        print("\n", "Total time: " + ((time / 3600000 > 0) ? (time / 3600000) + " h " : "")
+                + ((time / 60000 > 0) ? ((time / 60000) % 60000) + " min " : "") + (time / 1000 % 60) + " sec\n" + "Time per comparison: "
+                + (time / anz) + " msec\n");
+
+    }
+
+    // DEBUG !!!
+    public void token_distribution() {
+        int[] count = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0}; // to
+        // count
+        // the
+        // distribution
+
+        Enumeration<Submission> enum1 = submissions.elements();
+
+        while (enum1.hasMoreElements()) {
+            Structure struct = enum1.nextElement().struct;
+            if (struct != null)
+                for (int i = struct.size() - 1; i >= 0; i--)
+                    count[struct.tokens[i].type]++;
+        }
+
+        int tot = 0;
+        for (int i = 0; i < 0; i++) { // !!!!!!!!!!!!!!!
+            int c = count[i];
+            tot += c;
+            // System.out.println(Token.type2string(i)+"\t"+c);
+        }
+        System.out.println((tot > 999 ? "" : (tot > 99 ? " " : (tot > 9 ? "  " : "   "))) + tot);
+    }
+
+    public boolean use_clustering() {
+        return this.options.clustering;
+    }
+
+    public boolean use_debugParser() {
+        return this.options.debugParser;
+    }
+
+    public boolean use_diff_report() {
+        return this.options.diff_report;
+    }
+
+    public boolean use_externalSearch() {
+        return this.options.externalSearch;
+    }
+
+    public boolean use_verbose_details() {
+        return this.options.verbose_details;
+    }
+
+    public boolean use_verbose_long() {
+        return this.options.verbose_long;
+    }
+
+    public boolean use_verbose_parser() {
+        return this.options.verbose_parser;
+    }
+
+    public boolean use_verbose_quiet() {
+        return this.options.verbose_quiet;
+    }
+
+    public boolean useBasecode() {
+        return this.options.useBasecode;
+    }
+
+    // RESULT
+
+    /*
+     * Erst wird die Existenz des Ergebnis-Verzeichnisses sichergestellt, dann
+     * wird die Erstellung der Dateien durch die Klasse "Report" erledigt.
+     */
+    private void writeResults(int[] dist, SortedVector<AllMatches> avgmatches, SortedVector<AllMatches> maxmatches,
+                              SortedVector<AllMatches> minmatches, Cluster clustering) throws jplag.ExitException {
+        options.setState(Options.GENERATING_RESULT_FILES);
+        options.setProgress(0);
+        if (options.original_dir == null)
+            print("Writing results to: " + options.result_dir + "\n", null);
+        File f = new File(options.result_dir);
+        if (!f.exists())
+            if (!f.mkdirs()) {
+                throw new jplag.ExitException("Cannot create directory!");
+            }
+        if (!f.isDirectory()) {
+            throw new jplag.ExitException(options.result_dir + " is not a directory!");
+        }
+        if (!f.canWrite()) {
+            throw new jplag.ExitException("Cannot write directory: " + options.result_dir);
+        }
+
+        this.report.write(f, dist, avgmatches, maxmatches, minmatches, clustering, options);
+
+        if (options.externalSearch)
+            writeTextResult(f, avgmatches);
+    }
+
+    private void writeTextResult(File dir, SortedVector<AllMatches> matches) {
+        Iterator<AllMatches> iter = matches.iterator();
+
+        print("Writing special 'matches.txt' file\n", null);
+
+        try {
+            File f = new File(dir, "matches.txt");
+            PrintWriter writer = new PrintWriter(new FileWriter(f));
+
+            while (iter.hasNext()) {
+                AllMatches match = iter.next();
+
+                String file1, file2, tmp;
+                file1 = match.subA.name;
+                file2 = match.subB.name;
+
+                if (file1.compareTo(file2) > 0) {
+                    tmp = file2;
+                    file2 = file1;
+                    file1 = tmp;
+                }
+
+                writer.println(file1 + "\t" + file2 + "\t" + match.percent());
+            }
+            writer.close();
+        } catch (IOException e) {
+            print("IOException while writing file\n", null);
+        }
+    }
 }
 }

+ 2 - 2
jplag/src/main/java/jplag/Report.java

@@ -98,14 +98,14 @@ public class Report implements TokenConstants {
 	public void writeHTMLHeader(HTMLFile file, String title) {
 	public void writeHTMLHeader(HTMLFile file, String title) {
 		file.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
 		file.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
 		file.println("<HTML><HEAD><TITLE>" + title + "</TITLE>");
 		file.println("<HTML><HEAD><TITLE>" + title + "</TITLE>");
-		file.println("<META http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">");
+		file.println("<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
 		file.println("</HEAD>");
 		file.println("</HEAD>");
 	}
 	}
 
 
 	public void writeHTMLHeaderWithScript(HTMLFile file, String title) {
 	public void writeHTMLHeaderWithScript(HTMLFile file, String title) {
 		file.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
 		file.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
 		file.println("<HTML>\n<HEAD>\n <TITLE>" + title + "</TITLE>");
 		file.println("<HTML>\n<HEAD>\n <TITLE>" + title + "</TITLE>");
-		file.println("<META http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">");
+		file.println("<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
 		file.println("  <script type=\"text/javascript\">\n  <!--");
 		file.println("  <script type=\"text/javascript\">\n  <!--");
 		file.println("   function ZweiFrames(URL1,F1,URL2,F2)\n   {");
 		file.println("   function ZweiFrames(URL1,F1,URL2,F2)\n   {");
 		file.println("    parent.frames[F1].location.href=URL1;");
 		file.println("    parent.frames[F1].location.href=URL1;");

+ 8 - 2
jplag/src/main/java/jplag/Submission.java

@@ -8,6 +8,7 @@ import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.FileReader;
 import java.io.FilenameFilter;
 import java.io.FilenameFilter;
 import java.io.IOException;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.net.URL;
 import java.net.URL;
 import java.text.DecimalFormat;
 import java.text.DecimalFormat;
 import java.util.Vector;
 import java.util.Vector;
@@ -81,7 +82,7 @@ public class Submission implements Comparable<Submission> {
 			return;
 			return;
 		if (readSubDirs) {
 		if (readSubDirs) {
 			String[] dirs = aktDir.list();
 			String[] dirs = aktDir.list();
-			if (subDir != "")
+			if (!subDir.equals(""))
 				for (int i = 0; i < dirs.length; i++)
 				for (int i = 0; i < dirs.length; i++)
 					lookupDir(dir, subDir + File.separator + dirs[i]);
 					lookupDir(dir, subDir + File.separator + dirs[i]);
 			else
 			else
@@ -214,7 +215,10 @@ public class Submission implements Comparable<Submission> {
 		for (int i = 0; i < files.length; i++) {
 		for (int i = 0; i < files.length; i++) {
 			text.removeAllElements();
 			text.removeAllElements();
 			try {
 			try {
-				BufferedReader in = new BufferedReader(new FileReader(new File(dir, files[i])));
+				/* file encoding = "UTF-8" */
+				FileInputStream fileInputStream = new FileInputStream(new File(dir, files[i]));
+				InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
+				BufferedReader in = new BufferedReader(inputStreamReader);
 				while ((help = in.readLine()) != null) {
 				while ((help = in.readLine()) != null) {
 					help = help.replaceAll("&", "&amp;");
 					help = help.replaceAll("&", "&amp;");
 					help = help.replaceAll("<", "&lt;");
 					help = help.replaceAll("<", "&lt;");
@@ -223,6 +227,8 @@ public class Submission implements Comparable<Submission> {
 					text.addElement(help);
 					text.addElement(help);
 				}
 				}
 				in.close();
 				in.close();
+				inputStreamReader.close();
+				fileInputStream.close();
 			} catch (FileNotFoundException e) {
 			} catch (FileNotFoundException e) {
 				System.out.println("File not found: " + ((new File(dir, files[i])).toString()));
 				System.out.println("File not found: " + ((new File(dir, files[i])).toString()));
 			} catch (IOException e) {
 			} catch (IOException e) {

+ 8 - 8
jplag/src/main/resources/jplag/data/help-de.html

@@ -1,6 +1,6 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <HTML><HEAD><TITLE>Wie man die Ergebnisse liest</TITLE>
 <HTML><HEAD><TITLE>Wie man die Ergebnisse liest</TITLE>
-<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
 </HEAD>
 </HEAD>
 
 
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
@@ -11,19 +11,19 @@
 
 
 <p>Das Fenster ist in vier Teile unterteilt:
 <p>Das Fenster ist in vier Teile unterteilt:
 
 
-<p>Die beiden unteren Teile enthalten die Programme, wobei ähnliche Abschnitte
+<p>Die beiden unteren Teile enthalten die Programme, wobei ähnliche Abschnitte
 mit der selben Farbe markiert sind und durch <img src="forward.gif"
 mit der selben Farbe markiert sind und durch <img src="forward.gif"
-alt="Vorwärts"> oder <img src="back.gif" alt="Rückwärts"> auf die jeweilige
+alt="Vorwärts"> oder <img src="back.gif" alt="Rückwärts"> auf die jeweilige
 Stelle im anderen Programm verwiesen wird. Klickt man auf diese Bilder,
 Stelle im anderen Programm verwiesen wird. Klickt man auf diese Bilder,
 springen die anderen Ansichten zu den entsprechenden Stellen.<br>
 springen die anderen Ansichten zu den entsprechenden Stellen.<br>
-Wurde zu einem Block kein ähnlicher Abschnitt im anderen Programm gefunden, so
+Wurde zu einem Block kein ähnlicher Abschnitt im anderen Programm gefunden, so
 wird dieser Block schwarz dargestellt. 
 wird dieser Block schwarz dargestellt. 
 
 
-<p>Der linke obere Teil zeigt die prozentuale Ähnlichkeit zwischen den beiden
+<p>Der linke obere Teil zeigt die prozentuale Ähnlichkeit zwischen den beiden
 Programmen und bietet Verweise zur Index-Seite und zu dieser Hilfe-Seite an.
 Programmen und bietet Verweise zur Index-Seite und zu dieser Hilfe-Seite an.
 
 
-<p>Zuletzt enthält der rechte obere Teil eine Tabelle aller Abschnitte, zu denen
-ähnliche Abschnitte gefunden wurden. Dabei hat die Tabelle folgendes Format:
+<p>Zuletzt enthält der rechte obere Teil eine Tabelle aller Abschnitte, zu denen
+ähnliche Abschnitte gefunden wurden. Dabei hat die Tabelle folgendes Format:
 
 
 <p><TABLE BORDER="1" CELLSPACING="0" BGCOLOR="#d0d0d0">
 <p><TABLE BORDER="1" CELLSPACING="0" BGCOLOR="#d0d0d0">
 <TR><TH><TH>Programm_1 (??%)<TH>Programm_2 (??%)<TH>Meta-Zeichen
 <TR><TH><TH>Programm_1 (??%)<TH>Programm_2 (??%)<TH>Meta-Zeichen
@@ -36,7 +36,7 @@ Programmen und bietet Verweise zur Index-Seite und zu dieser Hilfe-Seite an.
 </TABLE>
 </TABLE>
 
 
 <p>Jede Zeile gibt einen Bereich von Dateizeilen an, die als gleich zu
 <p>Jede Zeile gibt einen Bereich von Dateizeilen an, die als gleich zu
-betrachten sind, zusammen mit der Größe der Abschnitte in Meta-Zeichen.
+betrachten sind, zusammen mit der Größe der Abschnitte in Meta-Zeichen.
 Die Dateinamen sind wiederum Verweise auf die entsprechenden
 Die Dateinamen sind wiederum Verweise auf die entsprechenden
 Stellen in beiden Programmen, die in der Farbe des kleinen Rechtecks dargestellt
 Stellen in beiden Programmen, die in der Farbe des kleinen Rechtecks dargestellt
 werden.
 werden.

+ 1 - 1
jplag/src/main/resources/jplag/data/help-en.html

@@ -1,6 +1,6 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <HTML><HEAD><TITLE>How to read the results</TITLE>
 <HTML><HEAD><TITLE>How to read the results</TITLE>
-<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
 </HEAD>
 </HEAD>
 
 
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">

+ 14 - 14
jplag/src/main/resources/jplag/data/help-es.html

@@ -1,33 +1,33 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<HTML><HEAD><TITLE>Cómo leer los resultados</TITLE>
-<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<HTML><HEAD><TITLE>Cómo leer los resultados</TITLE>
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
 </HEAD>
 </HEAD>
 
 
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
 
 
 <center><IMG SRC="logo.gif" ALT="JPlag" BORDER="0"></center>
 <center><IMG SRC="logo.gif" ALT="JPlag" BORDER="0"></center>
 
 
-<h1>Cómo leer los resultados</h1>
+<h1>Cómo leer los resultados</h1>
 
 
 <p>La ventana se encuentra dividida en cuatro marcos:
 <p>La ventana se encuentra dividida en cuatro marcos:
 
 
 <p>Los dos marcos grandes en el fondo contienen las solicitudes en las
 <p>Los dos marcos grandes en el fondo contienen las solicitudes en las
- cuales los parrafos similares están marcados con el mismo color. El texto 
-negro significa que no se encontró ninguna parte que coincidiese con la 
-otra solicitud. Además, cada parrafo tiene asociado <img src="forward.gif" alt="Adelante"> o
-<img src="back.gif" alt="Atrás">. Pulsar sobre estos iconos lleva el foco en el 
+ cuales los parrafos similares están marcados con el mismo color. El texto 
+negro significa que no se encontró ninguna parte que coincidiese con la 
+otra solicitud. Además, cada parrafo tiene asociado <img src="forward.gif" alt="Adelante"> o
+<img src="back.gif" alt="Atrás">. Pulsar sobre estos iconos lleva el foco en el 
 otro marco del programa al pasaje que coincida realiza un scroll en la tabla
 otro marco del programa al pasaje que coincida realiza un scroll en la tabla
-a lo alto de la otra posición.
+a lo alto de la otra posición.
 
 
 <p>El marco izquierdo en la parte superior muestra el porcentaje de la 
 <p>El marco izquierdo en la parte superior muestra el porcentaje de la 
 semejanza entre los dos programas y proporciona links al inicio 
 semejanza entre los dos programas y proporciona links al inicio 
-y a la página estás leyendo ahora.
+y a la página estás leyendo ahora.
 
 
 <p>El marco de la derecha contiene una tabla de todos los pasajes que
 <p>El marco de la derecha contiene una tabla de todos los pasajes que
 coinciden. La tabla tiene el siguiente formato:
 coinciden. La tabla tiene el siguiente formato:
 
 
 <p><TABLE BORDER="1" CELLSPACING="0" BGCOLOR="#d0d0d0">
 <p><TABLE BORDER="1" CELLSPACING="0" BGCOLOR="#d0d0d0">
-<TR><TH><TH>Solicitud1 (??%)<TH>Solicitud2 (??%)<TH>Símbolos
+<TR><TH><TH>Solicitud1 (??%)<TH>Solicitud2 (??%)<TH>Símbolos
 <TR><TD BGCOLOR="#c00000"><FONT COLOR="#c00000">-</FONT><TD>
 <TR><TD BGCOLOR="#c00000"><FONT COLOR="#c00000">-</FONT><TD>
 <A HREF="">archivo1 (1-8)</a><TD><A HREF="">archivo2 (1-10)</A>
 <A HREF="">archivo1 (1-8)</a><TD><A HREF="">archivo2 (1-10)</A>
 <TD ALIGN=center><FONT COLOR="#b00000">23</FONT>
 <TD ALIGN=center><FONT COLOR="#b00000">23</FONT>
@@ -36,13 +36,13 @@ coinciden. La tabla tiene el siguiente formato:
 <TD ALIGN=center><FONT COLOR="#600000">11</FONT>
 <TD ALIGN=center><FONT COLOR="#600000">11</FONT>
 </TABLE>
 </TABLE>
 
 
-<p>Cada línea proporciona un rango de números de línea del archivo1 y 
-el archivo2 que son consideradas iguales, junto con el tamaño del 
-pasaje en símbolos.
+<p>Cada línea proporciona un rango de números de línea del archivo1 y 
+el archivo2 que son consideradas iguales, junto con el tamaño del 
+pasaje en símbolos.
 
 
 Los nombres de archivos son hyperlinks al parrafo apropiado en ambos programas.
 Los nombres de archivos son hyperlinks al parrafo apropiado en ambos programas.
 
 
-El parrafo tiene el color del rectángulo pequeño en el borde izquierdo de la fila.
+El parrafo tiene el color del rectángulo pequeño en el borde izquierdo de la fila.
 
 
 <p><a href="index.html">INDICE</a>
 <p><a href="index.html">INDICE</a>
 <p>
 <p>

+ 1 - 1
jplag/src/main/resources/jplag/data/help-fr.html

@@ -1,6 +1,6 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <HTML><HEAD><TITLE>How to read the results</TITLE>
 <HTML><HEAD><TITLE>How to read the results</TITLE>
-<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
 </HEAD>
 </HEAD>
 
 
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">

+ 1 - 1
jplag/src/main/resources/jplag/data/help-pt.html

@@ -1,6 +1,6 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <HTML><HEAD><TITLE>How to read the results</TITLE>
 <HTML><HEAD><TITLE>How to read the results</TITLE>
-<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
 </HEAD>
 </HEAD>
 
 
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">

+ 13 - 13
jplag/src/main/resources/jplag/data/help-ptbr.html

@@ -3,7 +3,7 @@
 <head>
 <head>
   <title>Como ler os resultados</title>
   <title>Como ler os resultados</title>
   <meta http-equiv="Content-Type"
   <meta http-equiv="Content-Type"
- content="text/html; charset=iso-8859-1">
+ content="text/html; charset=UTF-8">
 </head>
 </head>
 <body bgcolor="#ffffff" link="#000088" text="#000000" vlink="#000000">
 <body bgcolor="#ffffff" link="#000088" text="#000000" vlink="#000000">
 <center><img src="logo.gif" alt="JPlag" border="0"></center>
 <center><img src="logo.gif" alt="JPlag" border="0"></center>
@@ -14,19 +14,19 @@
 trechos similares est&atilde;o marcados com a mesma cor. Texto preto
 trechos similares est&atilde;o marcados com a mesma cor. Texto preto
 significa que n&atilde;o foi encontrado algum trecho equivalente em
 significa que n&atilde;o foi encontrado algum trecho equivalente em
 outro arquivo submetido.<br>
 outro arquivo submetido.<br>
-&nbsp; Todo trecho com alguma equivalência encontrada
+&nbsp; Todo trecho com alguma equivalência encontrada
 tem um <img src="forward.gif" alt="Forward">
 tem um <img src="forward.gif" alt="Forward">
 ou
 ou
 <img src="back.gif" alt="Backward"> associado. Clicando nesses icones, o 
 <img src="back.gif" alt="Backward"> associado. Clicando nesses icones, o 
-foco vai para outro bloco com o trecho equivalente já na posição apropriada.
+foco vai para outro bloco com o trecho equivalente já na posição apropriada.
 </p>
 </p>
 <p>O bloco da esquerda mostra a porcentagem de similaridade entre
 <p>O bloco da esquerda mostra a porcentagem de similaridade entre
-dois programas e possui links para a página inicial e para o código  
-que você estava vendo.
+dois programas e possui links para a página inicial e para o código  
+que você estava vendo.
 
 
 </p>
 </p>
 <p>
 <p>
-O bloco da direita contém uma tabela de todos os trechos equivalentes encontrados.
+O bloco da direita contém uma tabela de todos os trechos equivalentes encontrados.
 A tabela tem o seguinte formato:
 A tabela tem o seguinte formato:
 </p>
 </p>
 <p>
 <p>
@@ -35,9 +35,9 @@ A tabela tem o seguinte formato:
     <tr>
     <tr>
       <th><br>
       <th><br>
       </th>
       </th>
-      <th>Submissão1 (??%)</th>
-      <th>Submissão2 (??%)</th>
-      <th>Marcação
+      <th>Submissão1 (??%)</th>
+      <th>Submissão2 (??%)</th>
+      <th>Marcação
       </th>
       </th>
     </tr>
     </tr>
     <tr>
     <tr>
@@ -59,11 +59,11 @@ A tabela tem o seguinte formato:
   </tbody>
   </tbody>
 </table>
 </table>
 </p>
 </p>
-<p> Cada coluna mostra uma sequência de números de linhas do arquivo1 e arquivo 2 que
-são consideradas equivalentes, juntamente com o tamanho do trecho em
-marcações. Os nomes dos arquivos são um hiperlink para o trecho apropriado em 
+<p> Cada coluna mostra uma sequência de números de linhas do arquivo1 e arquivo 2 que
+são consideradas equivalentes, juntamente com o tamanho do trecho em
+marcações. Os nomes dos arquivos são um hiperlink para o trecho apropriado em 
 ambos os programas.
 ambos os programas.
-O trecho tem a cor de um pequeno retângulo na fronteira esquerda da coluna.
+O trecho tem a cor de um pequeno retângulo na fronteira esquerda da coluna.
 </p>
 </p>
 <p><a href="index.html">INDEX</a>
 <p><a href="index.html">INDEX</a>
 </p>
 </p>

+ 1 - 1
jplag/src/main/resources/jplag/data/help-sim-de.html

@@ -1,6 +1,6 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <HTML><HEAD><TITLE>Match ranking</TITLE>
 <HTML><HEAD><TITLE>Match ranking</TITLE>
-<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
 </HEAD>
 </HEAD>
 
 
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">

+ 1 - 1
jplag/src/main/resources/jplag/data/help-sim-en.html

@@ -1,6 +1,6 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <HTML><HEAD><TITLE>Match ranking</TITLE>
 <HTML><HEAD><TITLE>Match ranking</TITLE>
-<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
 </HEAD>
 </HEAD>
 
 
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">

+ 8 - 8
jplag/src/main/resources/jplag/data/help-sim-es.html

@@ -1,6 +1,6 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <HTML><HEAD><TITLE>Ranking de Coincidencias</TITLE>
 <HTML><HEAD><TITLE>Ranking de Coincidencias</TITLE>
-<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
 </HEAD>
 </HEAD>
 
 
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
@@ -11,23 +11,23 @@
 
 
 <p>JPlag compara los programas intentando cubrir uno de los programas 
 <p>JPlag compara los programas intentando cubrir uno de los programas 
 con secuencias (preferiblemente grandes) del otro programa. La cobertura 
 con secuencias (preferiblemente grandes) del otro programa. La cobertura 
-de un programa se define como la proporción del código de fuente frente 
-al tamaño total del código de fuente.</p>
+de un programa se define como la proporción del código de fuente frente 
+al tamaño total del código de fuente.</p>
 
 
 <h4>Rango de coincidencias por semejanza media</h4>
 <h4>Rango de coincidencias por semejanza media</h4>
 
 
 <p>La semejanza media se define como la media de la cobertura de 
 <p>La semejanza media se define como la media de la cobertura de 
 ambos programas.<br/>
 ambos programas.<br/>
 
 
-Esta es la semejanza por defecto que funciona en la mayoría de los casos: Las 
+Esta es la semejanza por defecto que funciona en la mayoría de los casos: Las 
 coincidencias con una alta semajanza media indica que esos programas funcionan 
 coincidencias con una alta semajanza media indica que esos programas funcionan 
 de una forma muy similar.</b>
 de una forma muy similar.</b>
 
 
-<h4>Rango de coincidencias por semjanza máxima</h4>
+<h4>Rango de coincidencias por semjanza máxima</h4>
 
 
-<p>La semejanza máxima se define como la mayor de ambas coberturas del programa.<br/>
-Este ranking es especialmente útil en programas que son muy diferentes en tamaño. Esto 
-se puede manifestar cuando se introducen grandes porciones de código dentro de uno de ellos 
+<p>La semejanza máxima se define como la mayor de ambas coberturas del programa.<br/>
+Este ranking es especialmente útil en programas que son muy diferentes en tamaño. Esto 
+se puede manifestar cuando se introducen grandes porciones de código dentro de uno de ellos 
 para que no se distinga respecto al programa plagiado.</p>
 para que no se distinga respecto al programa plagiado.</p>
 
 
 <p><a href="index.html">INDEX</a></p>
 <p><a href="index.html">INDEX</a></p>

+ 1 - 1
jplag/src/main/resources/jplag/data/help-sim-fr.html

@@ -1,6 +1,6 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <HTML><HEAD><TITLE>Match ranking</TITLE>
 <HTML><HEAD><TITLE>Match ranking</TITLE>
-<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
 </HEAD>
 </HEAD>
 
 
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">

+ 1 - 1
jplag/src/main/resources/jplag/data/help-sim-pt.html

@@ -1,6 +1,6 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <HTML><HEAD><TITLE>Match ranking</TITLE>
 <HTML><HEAD><TITLE>Match ranking</TITLE>
-<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
 </HEAD>
 </HEAD>
 
 
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">

+ 11 - 11
jplag/src/main/resources/jplag/data/help-sim-ptbr.html

@@ -1,33 +1,33 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <HTML><HEAD><TITLE>Match ranking</TITLE>
 <HTML><HEAD><TITLE>Match ranking</TITLE>
-<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
 </HEAD>
 </HEAD>
 
 
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
 <BODY BGCOLOR="#ffffff" LINK="#000088" VLINK="#000000" TEXT="#000000">
 
 
 <center><IMG SRC="logo.gif" ALT="JPlag" BORDER="0"></center>
 <center><IMG SRC="logo.gif" ALT="JPlag" BORDER="0"></center>
 
 
-<h1>Ranking de Equivalências</h1>
+<h1>Ranking de Equivalências</h1>
 
 
 <p> JPlag compara programas tentando cobrir um dos programas com trechos 
 <p> JPlag compara programas tentando cobrir um dos programas com trechos 
 (preferencialmente grandes) de outros programs. A cobertura de um programa
 (preferencialmente grandes) de outros programs. A cobertura de um programa
-é definida como a razão do código fonte coberto com seu tamanho total.
+é definida como a razão do código fonte coberto com seu tamanho total.
 </p>
 </p>
 
 
-<h4>Ranking de equivalências pela similaridade média</h4>
+<h4>Ranking de equivalências pela similaridade média</h4>
 
 
-<p>A similaridade média é definida como a média das coberturas de ambos os programas.<br/>
-Essa é a similaridade padrão que funciona na maioria dos casos: Equivalências com
+<p>A similaridade média é definida como a média das coberturas de ambos os programas.<br/>
+Essa é a similaridade padrão que funciona na maioria dos casos: Equivalências com
 uma similaridade alta indica que os programas funcionam de uma maneira muito
 uma similaridade alta indica que os programas funcionam de uma maneira muito
 semelhante.</b>
 semelhante.</b>
 
 
-<h4>Ranking de equivalências pela similaridade máxima</h4>
+<h4>Ranking de equivalências pela similaridade máxima</h4>
 
 
-<p>A similaridade máxima é definida como a máxima similaridade da cobertura 
+<p>A similaridade máxima é definida como a máxima similaridade da cobertura 
 de ambos os programas.<br/>
 de ambos os programas.<br/>
-Esse ranking é especialmente útil quando programas são muito distintos 
-em tamanho. Isso pode acontecer quando partes inúteis de código são inseridas com o intuito
-de enganar um programa que busca plágios.</p>
+Esse ranking é especialmente útil quando programas são muito distintos 
+em tamanho. Isso pode acontecer quando partes inúteis de código são inseridas com o intuito
+de enganar um programa que busca plágios.</p>
 
 
 <p><a href="index.html">INDEX</a></p>
 <p><a href="index.html">INDEX</a></p>
 <p/>
 <p/>