Legality of Cannabis by U.S. Jurisdiction

Content deleted Content added
Pathoschild (talk | contribs)
Designed header infobox per Titoxd's request on IRC
Titoxd (talk | contribs)
→‎PurgeContribs.java: bug resolved, increase version to 3.40 ^_^
Line 451: Line 451:
* @author Titoxd
* @author Titoxd
* @program HTML -> ContribFile converter for Flcelloguy's Tool
* @program HTML -> ContribFile converter for Flcelloguy's Tool
* @version 3.32; released January 15, 2006
* @version 3.40; released January 28, 2006
* @see [[User:Flcelloguy/Tool]]
* @see [[User:Flcelloguy/Tool]]
* @docRoot http://en.wikipedia.org/wiki/User:Titoxd/Flcelloguy's_Tool
* @docRoot http://en.wikipedia.org/wiki/User:Titoxd/Flcelloguy's_Tool
* @copyright Permission is granted to distribute freely, provided attribution is granted.
* @copyright Permission is granted to distribute freely, provided attribution is granted.
*/
*/

import java.io.IOException;
import java.io.IOException;
import java.util.StringTokenizer;
import java.util.StringTokenizer;
Line 564: Line 565:
while (endLoop == false);
while (endLoop == false);


/**** Process edit summaries ****/
/**** flush the StringTokenizer ****/
if (token.hasMoreTokens() == true)
StringBuilder tokenDump = new StringBuilder();
String dump;
if (token.hasMoreTokens() == true) //
{
{
do
dummy = token.nextToken(); // read whether it is <span or <strong>
if (dummy.compareTo("<span") == 0) // <span: there is an edit summary
{
{
String dummySummary = token.nextToken();
tokenDump.append(token.nextToken());
tokenDump.append(' ');
String midSummary = dummySummary.substring(17);
} while (token.hasMoreTokens()==true);
String endSummary = null;
tokenDump.trimToSize();
StringBuilder summ = new StringBuilder();
dump = tokenDump.toString();
if (midSummary.endsWith("</span>")== true) //one-word edit summary (will only trigger when there's no section editing)
{
autoSummary = null;
summ.append(midSummary);
}
else
{
if (midSummary.compareTo("<span") == 0) // autosummary
{
do
{
endSummary = token.nextToken(); // read until "-</span>" is reached
if (endSummary.startsWith("href") == true)
{
String summaries[] = endSummary.split("#", 2);
if (sectionParsed == false)
{
autoSummary = summaries[1];
sectionParsed = true;
}
}
}
while (endSummary.compareTo("-</span>") != 0);
}
else
{
endSummary = midSummary;
summ.append(endSummary);
}
endLoop = false;
do
{
summ.append(" ");
endSummary = token.nextToken(); // read edit summary for processing
summ.append(endSummary);
summ.trimToSize();
if (summ.length() > 7)
{
if (summ.substring(summ.length() - 7).compareTo(
"</span>") == 0) endLoop = true;
}
}
while (endLoop == false);
}
editSummary = summ.toString().substring(0, summ.length() - 8);
}
}
}
else //not top edit, no edit summary

if (token.hasMoreTokens() == true)
{
{
dump = null;
dummy = token.nextToken(); // read whether <strong> is present
}
if (dummy.compareTo("<strong>") == 0) // top edit)
/**** Top edit? ****/
if (dump != null && dump.contains("<strong> (top)</strong>") == true)
{
{
token.nextToken(); // get rid of (top)</strong>"
newestEdit = true;
newestEdit = true;
dump = dump.substring(0,dump.indexOf("<strong> (top)</strong>")); //truncate to remove rollback links and other garbage
dump = dump.trim();
}
}
else newestEdit = false;
/**** Process edit summary ****/
String[] summaries = ParseSummary(dump);
autoSummary = summaries[0];
editSummary = summaries[1];
Contrib contrib = new Contrib(timeStamp, pageName, minorEdit,
editSummary, autoSummary, newestEdit);
return contrib;
}
/**
* @param dump
* @return String[2] array, String[0] is the auto summary, String[1] is the manual summary
*/
private static String[] ParseSummary(String dump)
{
/****Check that there is an edit summary to begin with ****/
String[] summaryArray = new String[2];
boolean sectionParsed = false;
if (dump == null | dump=="")
{
summaryArray[0]=null;
summaryArray[1]=null;
}
}
else
else
// edit is not the most recent edit to page
{
{
if (dump.indexOf("<span class=\"autocomment\">") != -1) //autocomment present
newestEdit = false;
{
String autoSummary = dump.substring(dump.indexOf("<span class=\"autocomment\">"),dump.indexOf("</span>")+7);
String summaries[] = autoSummary.split("#", 2);
if (sectionParsed == false)
{
summaryArray[0] = summaries[1];
sectionParsed = true;
}
summaryArray[1]= dump.substring(0,dump.indexOf(autoSummary));
summaryArray[1] = summaryArray[1].concat(dump.substring(dump.indexOf(autoSummary)+ autoSummary.length()).trim());
summaryArray[0] = summaryArray[0].substring(0,summaryArray[0].lastIndexOf("<"));
summaryArray[0] = summaryArray[0].substring(summaryArray[0].lastIndexOf(">")+1);
if (summaryArray[0].endsWith(" -")== true)
{
summaryArray[0] = summaryArray[0].substring(0,summaryArray[0].length()-1);
}
}
else
{
if (dump != "") summaryArray[1] = dump;
}
if (summaryArray[0]=="") summaryArray[0]=null;
if (summaryArray[1]=="") summaryArray[1]=null; //so the edge cases don't trigger exceptions
if (summaryArray[1] != null)
{
if (summaryArray[1].length() != 0)
{
summaryArray[1] = summaryArray[1].substring(summaryArray[1].indexOf(">")+1,summaryArray[1].lastIndexOf("<"));
summaryArray[1] = summaryArray[1].trim();
}
}
if (summaryArray[0] != null) summaryArray[0] = summaryArray[0].trim();
}
}
return summaryArray;
Contrib contrib = new Contrib(timeStamp, pageName, minorEdit,
editSummary, autoSummary, newestEdit);
return contrib;
}
}
}</nowiki></pre>
}</nowiki></pre>



Revision as of 01:39, 29 January 2006

Attention users: We need your help to improve this tool. We're particularly looking for someone with Java knowledge or ideas for a good GUI. Feel free to make a feature request.
Sample UI of the tool, while running on Windows XP.

This is an extension of Flcelloguy's Tool which processes the HTML from a contribs file and parses it into a file readable by the tool. It is not finished, but the core is done, so I'm publishing it as v1.00.

Titoxd(?!? - did you read this?) 04:21, 8 December 2005 (UTC)[reply]

Compiling and executing the tool requires the JDK for Java 1.4.

Requirements

You must have a Java IDE and JDK (freeware available; see below). Thus, you must make two downloads - one from Sun Microsystems, which developed Java, and another from a Java run-time developement program. We recommend JCreator, BlueJ, or Eclipse.

Links

Capabilities

Current Capabilities

  • Count the number of edits
  • Break down count by project namespace
  • Count percentage and number of "minor" flag usage

Under development

  • Correct parsing of edit summaries (through PurgeContribs.java)
  • Adding support for direct analysis of Special:Contributions (beta version can process in 1,000-edit intervals) (done, will be available in 4.0)
  • Add "kill bit" functionality for turning off tool remotely when server load requires it (done, will be available in 4.0)

Future developments (see also Feature requests)

  • Merge the two pages (this page and User:Titoxd/Flcelloguy's Tool, perhaps under a WP:TOOLS subfile; rename to reflect that it's not "my" tool, but both my and Titoxd's tool
  • Test and release Titoxd's contributions, which parses from the source code, instead of copying and pasting contributions
    • Add more buttons to that, make more user friendly
  • Add more detailed statistics with the parsing of timestamps, etc. available in Titoxd's code
  • Better and more detailed instructions on how to download and use (perhaps a JAR?)
    • JAR file done, just needs hosting
  • Output to txt file for debugging (already done) and also to make copying results to the project easier
  • Add "First edit" date
  • Count percentage of edit summary usage
  • Attempt to make counting less crude by using a query

Known bugs

  • User UI is not completely user-friendly, needs improvements and suggestions
  • Need to create/update documentation to reflect move to WikiProject
  • Exceptions not handled sometimes, need to process correctly

Revisions

  • v1.00: Original version, parses contribs to HTML file
  • v1.01: Revision, split into a separate class, removed print command to system buffer (slowing down tool, only used for debugging)
  • v2.00: begun processing the raw HTML file, parsed date/time stamp and page name into a special "Contrib" class. Minor edits, edit summaries and most recent edits still to be implemented.
  • v2.10: Minor edits implemented, some code for edit summaries created (not operational yet).
  • v2.15: Contrib class parses namespaces.
  • v3.00: Merged my code with Flcelloguy's code.
  • v3.10: Removed 5,000-edit limit (the program now allows input from multiple sources) and added a basic Graphical user interface.
  • v3.20: Enhanced the GUI, output now sent to a window, not to console.
  • v3.30: Enabling parsing of edit summaries and automatic section-edit summaries.
  • v3.31: Bug fix in edit summary parsing: now processes one-word edit summaries correctly

Code

Stats.java (same file as Flcelloguy's tool, only updated)

/**
 * @author Flcelloguy et al.
 * @program Flcelloguy's Tool (Stats.java)
 * @version 3.32; released January 15, 2006
 * @see [[User:Flcelloguy/Tool]]
 * @docRoot code from http://en.wikipedia.org/wiki/User:Flcelloguy/Tool
 * @copyright Permission is granted to distribute freely, provided attribution is granted.
 * Capabilities: Count edits, break down by namespace, count minor edits and calculate percentage
 * Please leave this block in. 
 * Note: This new version does not require cut-and-pasting. Just go to http://en.wikipedia.org/w/index.php?title=Special:Contributions&target={{USERNAME}}&offset=0&limit=5000, where {{USERNAME}} is the name of the user you want to run a check on. 
 */
import javax.swing.JOptionPane;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

// import java.util.FileReader;

public class Stats
{
	private static StringBuilder console = new StringBuilder();
	private static int numEdits = 0;
	private static int minorEdits = 0;
	private static int Mainspace = 0;
	private static int Talk = 0;
	private static int User = 0;
	private static int User_talk = 0;
	private static int Wikipedia = 0;
	private static int Wikipedia_talk = 0;
	private static int Image = 0;
	private static int Image_talk = 0;
	private static int MediaWiki = 0;
	private static int MediaWiki_talk = 0;
	private static int Template = 0;
	private static int Template_talk = 0;
	private static int Help = 0;
	private static int Help_talk = 0;
	private static int Category = 0;
	private static int Category_talk = 0;
	private static int Portal = 0;
	private static int Portal_talk = 0;
	private static int Special = 0; // these two are listed at
									// [[Wikipedia:Namespace]],
	private static int Media = 0; // so I'm adding support for them, but I'm
									// not sure they are used.

	public static void reset()
	{
		console = new StringBuilder();
		numEdits = 0;
		minorEdits = 0;
		Mainspace = 0;
		Talk = 0;
		User = 0;
		User_talk = 0;
		Wikipedia = 0;
		Wikipedia_talk = 0;
		Image = 0;
		Image_talk = 0;
		MediaWiki = 0;
		MediaWiki_talk = 0;
		Template = 0;
		Template_talk = 0;
		Help = 0;
		Help_talk = 0;
		Category = 0;
		Category_talk = 0;
		Portal = 0;
		Portal_talk = 0;
		Special = 0; // these two are listed at [[Wikipedia:Namespace]],
		Media = 0; // so I'm adding support for them, but I'm not sure they are
					// used.

	}

	public static void main(String args[]) throws IOException
	{
		/**
		 * the GUI is too complex to screw up clean, crisp code like this, so
		 * I'm moving it to a separate class. --Titoxd
		 */
		MainGUI.main(null);
	}

	public static void mainSingle(String inFile$) throws IOException
	{
		if (inFile$ == null)
			inFile$ = JOptionPane.showInputDialog("Input file:", inFile$);

		JOptionPane
				.showMessageDialog(
						null,
						"Current status: \n "
								+ "Editcount only \n "
								+ "Coming soon: \n "
								+ "Breakdown by namespace \n Minor edits usage \n User friendly version \n Edit summary usage \n First edit date",
						"Information", JOptionPane.INFORMATION_MESSAGE);

		JOptionPane.showMessageDialog(null, "Number of edits: "
				+ editcount(inFile$), "Results",
				JOptionPane.INFORMATION_MESSAGE);
	}

	public static int editcount(String inFile$) throws IOException
	{
		System.out.println("Computing...");

		FileReader reader = new FileReader(inFile$);
		BufferedReader in = new BufferedReader(reader);

		// FileWriter writer = new FileWriter(outFile$); //for debugging
		// BufferedWriter out = new BufferedWriter(writer); //for debugging

		String inString = "";
		Contrib outContrib;
		boolean endContribs = false; // marks whether all the contributions
										// have been parsed

		inString = in.readLine(); // read from file and discard

		do
		{
			if ((inString.trim().compareTo("<ul>") == 0)
					&& (endContribs == false)) // until the <ul> tag is
												// reached,
			{
				do
				{
					inString = in.readLine(); // then start reading and
												// recording
					if ((inString.trim().compareTo("</ul>") != 0))
					{
						// System.out.println(inString.trim());
						outContrib = PurgeContribs.Parse(inString.trim());
						// System.out.println(outString.trim());

						AnalyzeContrib(outContrib);
						// out.newLine();
					}
					else
					{
						endContribs = true;
					}
				}
				while (endContribs != true);
			}
			inString = in.readLine(); // read from file and discard
		}
		while (inString != null);
		in.close();
		// out.close();

		// Prints out statistics
		System.out.println("-------------------");
		System.out.println("Breakdown by namespace:");
		if (Mainspace != 0)
		{
			console.append("Main (articles): " + Mainspace + "\n");
			System.out.println("Main (articles): " + Mainspace);
		}
		if (Talk != 0)
		{
			console.append("Article talk: " + Talk + "\n");
			System.out.println("Article talk: " + Talk);
		}
		if (User != 0)
		{
			console.append("User: " + User + "\n");
			System.out.println("User: " + User);
		}
		if (User_talk != 0)
		{
			console.append("User talk: " + User_talk + "\n");
			System.out.println("User talk: " + User_talk);
		}
		if (Wikipedia != 0)
		{
			console.append("Project: " + Wikipedia + "\n");
			System.out.println("Project: " + Wikipedia);
		}
		if (Wikipedia_talk != 0)
		{
			console.append("Project talk: " + Wikipedia_talk + "\n");
			System.out.println("Project talk: " + Wikipedia_talk);
		}
		if (Image != 0)
		{
			console.append("Image: " + Image + "\n");
			System.out.println("Image: " + Image);
		}
		if (Image_talk != 0)
		{
			console.append("Image talk: " + Image_talk + "\n");
			System.out.println("Image talk: " + Image_talk);
		}
		if (MediaWiki != 0)
		{
			console.append("MediaWiki: " + MediaWiki + "\n");
			System.out.println("MediaWiki: " + MediaWiki);
		}
		if (MediaWiki_talk != 0)
		{
			console.append("MediaWiki talk: " + MediaWiki_talk + "\n");
			System.out.println("MediaWiki talk: " + MediaWiki_talk);
		}
		if (Template != 0)
		{
			console.append("Template: " + Template + "\n");
			System.out.println("Template: " + Template);
		}
		if (Template_talk != 0)
		{
			console.append("Template talk: " + Template_talk + "\n");
			System.out.println("Template talk: " + Template_talk);
		}
		if (Help != 0)
		{
			console.append("Help: " + Help + "\n");
			System.out.println("Help: " + Help);
		}
		if (Help_talk != 0)
		{
			console.append("Help talk: " + Help_talk + "\n");
			System.out.println("Help talk: " + Help_talk);
		}
		if (Category != 0)
		{
			console.append("Category: " + Category + "\n");
			System.out.println("Category: " + Category);
		}
		if (Category_talk != 0)
		{
			console.append("Category talk: " + Category_talk + "\n");
			System.out.println("Category talk: " + Category_talk);
		}
		if (Portal != 0)
		{
			console.append("Portal: " + Portal + "\n");
			System.out.println("Portal: " + Portal);
		}
		if (Portal_talk != 0)
		{
			console.append("Portal talk: " + Portal_talk + "\n");
			System.out.println("Portal talk: " + Portal_talk);
		}
		if (Special != 0)
		{
			console.append("Special: " + Special + "\n");
			System.out.println("Special: " + Special);
		}
		if (Media != 0)
		{
			console.append("Media: " + Media + "\n");
			System.out.println("Media: " + Media);
		}

		System.out.println("-------------------");
		System.out.println("Overall statistics: ");
		System.out.println("Total edits: " + numEdits);
		console.append("-------------------" + "\n" + "Overall statistics:"
				+ "\n" + "Total edits: " + numEdits + "\n");
		System.out.println("Minor edits: " + minorEdits);
		console.append("Minor edits: " + minorEdits + "\n");
		System.out.println("Percentage of minor edits: "
				+ (int) (((double) minorEdits) / numEdits * 100.0) + "%  *");
		console.append("Percentage of minor edits: "
				+ (int) (((double) minorEdits) / numEdits * 100.0) + "%  *\n");
		System.out
				.println("* - percentage is always rounded down to nearest whole number percentage.");
		// console.append("* - percentage is always rounded down to nearest
		// whole number percentage.\n");
		System.out.println("Percent edit summary: Not available yet.");

		System.out.println("-------------------");
		console.append("-------------------\n");
		MainGUI.createTextFrame(console.toString());
		return numEdits;

	}

	private static void AnalyzeContrib(Contrib contrib)
	{
		if (contrib.minorEdit == true)
		{
			minorEdits++;
		}
		if (contrib.namespace.equals("Main")) Mainspace++;
		if (contrib.namespace.equals("Talk")) Talk++;
		if (contrib.namespace.equals("User")) User++;
		if (contrib.namespace.equals("User_talk")) User_talk++;
		if (contrib.namespace.equals("Wikipedia")) Wikipedia++;
		if (contrib.namespace.equals("Wikipedia_talk")) Wikipedia_talk++;
		if (contrib.namespace.equals("Image")) Image++;
		if (contrib.namespace.equals("Image_talk")) Image_talk++;
		if (contrib.namespace.equals("MediaWiki")) MediaWiki++;
		if (contrib.namespace.equals("MediaWiki_talk")) MediaWiki_talk++;
		if (contrib.namespace.equals("Template")) Template++;
		if (contrib.namespace.equals("Template_talk")) Template_talk++;
		if (contrib.namespace.equals("Help")) Help++;
		if (contrib.namespace.equals("Help_talk")) Help_talk++;
		if (contrib.namespace.equals("Category")) Category++;
		if (contrib.namespace.equals("Category_talk")) Category_talk++;
		if (contrib.namespace.equals("Portal")) Portal++;
		if (contrib.namespace.equals("Portal_talk")) Portal_talk++;
		if (contrib.namespace.equals("Special")) Special++;
		if (contrib.namespace.equals("Media")) Media++;

		numEdits++;
	}

	public static void mainMulti(String[] args) throws IOException
	{
		String outFile$ = null;
		String inFile$ = null;

		outFile$ = JOptionPane.showInputDialog(null,
				"Enter the filename of the output file:", outFile$,
				JOptionPane.QUESTION_MESSAGE);

		FileWriter writer = new FileWriter(outFile$);
		BufferedWriter out = new BufferedWriter(writer);

		out.write("<ul>", 0, "<ul>".length());
		out.newLine();

		inFile$ = JOptionPane.showInputDialog(null,
				"Enter the filename of the next contributions file:", inFile$,
				JOptionPane.QUESTION_MESSAGE);

		while (inFile$ != null)
		{
			FileReader reader = new FileReader(inFile$);
			BufferedReader in = new BufferedReader(reader);

			String inString = "";
			boolean endContribs = false; // marks whether all the
											// contributions have been parsed

			inString = in.readLine(); // read from file and discard

			do
			{
				if ((inString.trim().compareTo("<ul>") == 0)
						&& (endContribs == false)) // until the <ul> tag is
													// reached,
				{
					do
					{
						inString = in.readLine(); // then start reading and
													// recording
						if ((inString.trim().compareTo("</ul>") != 0))
						{
							out.write(inString.trim(), 0, inString.length());
							out.newLine();

							// System.out.println(inString.trim());
						}
						else
						{
							endContribs = true;
						}
					}
					while (endContribs != true);
				}
				inString = in.readLine(); // read from file and discard
			}
			while (inString != null);
			in.close();
			inFile$ = JOptionPane.showInputDialog(null,
					"Enter the filename of the next contributions file:",
					inFile$, JOptionPane.QUESTION_MESSAGE);
		}

		out.write("</ul>", 0, "</ul>".length());
		out.newLine();
		out.close();
		mainSingle(outFile$);
	}
}

PurgeContribs.java

/**
 * @author Titoxd
 * @program HTML -> ContribFile converter for Flcelloguy's Tool
 * @version 3.40; released January 28, 2006
 * @see [[User:Flcelloguy/Tool]]
 * @docRoot http://en.wikipedia.org/wiki/User:Titoxd/Flcelloguy's_Tool
 * @copyright Permission is granted to distribute freely, provided attribution is granted.
 */

import java.io.IOException;
import java.util.StringTokenizer;

public class PurgeContribs
{
	/**
	 * @param purgedLine
	 *            (input line in raw HTML, leading and trailing whitespace
	 *            removed)
	 * @return Contrib class object: for analysis
	 * @throws IOException
	 */
	public static Contrib Parse(String purgedLine) throws IOException
	{
		/**** Take out the <li> tags ****/
		String midString1;
		String timeStamp;
		String editSummary = null;
		String autoSummary = null;
		boolean minorEdit = false;
		boolean endLoop = false;
		boolean newestEdit = false;
		boolean sectionParsed = false;
		midString1 = purgedLine.substring(4, purgedLine.length() - 5);

		/**** Process the time stamp ****/
		StringTokenizer token;
		token = new StringTokenizer(midString1.trim());
		{
			String time = token.nextToken();
			String day = token.nextToken();
			String month = token.nextToken();
			String year = token.nextToken();
			timeStamp = time + " " + day + " " + month + " " + year;
		}

		/**** Process the page name ****/

		String dummy = token.nextToken(); // get rid of (<a
		String URL = token.nextToken();
		String pageName = URL.substring(25, URL.length() - 20);

		/**** Get rid of a few extra tokens ****/

		do
		{
			endLoop = false;
			dummy = token.nextToken();
			if (dummy.lastIndexOf('<') != -1)
			{
				if (dummy.substring(dummy.lastIndexOf('<'),
						dummy.lastIndexOf('<') + 3).compareTo("</a>") != 0)
					endLoop = true;
			}
		}
		while (endLoop == false);

		/**** Do the same with the diff link ****/
		dummy = token.nextToken(); // get rid of (<a
		String dummyURL = token.nextToken(); // this URL is not needed, so it is dummied out
		String dummyPageName = URL.substring(25, dummyURL.length() - 20); // ditto
		do
		{
			endLoop = false;
			dummy = token.nextToken();
			if (dummy.lastIndexOf('<') != -1)
			{
				if (dummy.substring(dummy.lastIndexOf('<'),
						dummy.lastIndexOf('<') + 3).compareTo("</a>") != 0)
					endLoop = true;
			}
		}
		while (endLoop == false);

		/**** Determine if edit is minor or not ****/
		dummy = token.nextToken(); // get rid of (<span
		dummy = token.nextToken(); // read the next token; it should be class="minor">m</span> if a minor edit
		if (dummy.compareTo("class=\"minor\">m</span>") == 0)
		{
			minorEdit = true;
			dummyPageName = null;
		}
		else
		{
			minorEdit = false;
			dummyPageName = dummy;
		}

		if (dummyPageName == null) // if it was a minor edit, advance token
									// cursor to match non-minor edits
		{
			dummy = token.nextToken(); // get rid of <a
			dummyPageName = token.nextToken();
		}

		do
		{
			endLoop = false;
			dummy = token.nextToken();
			if (dummy.lastIndexOf('<') != -1)
			{
				if (dummy.substring(dummy.lastIndexOf('<'),
						dummy.lastIndexOf('<') + 3).compareTo("</a>") != 0)
					endLoop = true;
			}
		}
		while (endLoop == false);

		/**** flush the StringTokenizer ****/
		
		StringBuilder tokenDump = new StringBuilder();
		String dump;
		if (token.hasMoreTokens() == true) // 
		{
			do
			{
				tokenDump.append(token.nextToken());
				tokenDump.append(' ');
			} while (token.hasMoreTokens()==true);
			tokenDump.trimToSize();
			dump = tokenDump.toString();
		}
		else	//not top edit, no edit summary
		{
			dump = null;	
		}
		
		/**** Top edit? ****/
		if (dump != null && dump.contains("<strong> (top)</strong>") == true)
			{
				newestEdit = true;
				dump = dump.substring(0,dump.indexOf("<strong> (top)</strong>")); //truncate to remove rollback links and other garbage 
				dump = dump.trim();		
			}
			else newestEdit = false;
		
		/**** Process edit summary ****/
		String[] summaries = ParseSummary(dump);
		autoSummary = summaries[0];
		editSummary = summaries[1];
		
		Contrib contrib = new Contrib(timeStamp, pageName, minorEdit,
				editSummary, autoSummary, newestEdit);
		return contrib;
	}
	
	/**
	 * @param dump
	 * @return String[2] array, String[0] is the auto summary, String[1] is the manual summary  
	 */
	private static String[] ParseSummary(String dump)
	{
		/****Check that there is an edit summary to begin with ****/
		String[] summaryArray = new String[2];
		boolean sectionParsed = false;
		if (dump == null | dump=="")
		{
			summaryArray[0]=null;
			summaryArray[1]=null;
		}
		else
		{
			if (dump.indexOf("<span class=\"autocomment\">") != -1)  //autocomment present
			{
				String autoSummary = dump.substring(dump.indexOf("<span class=\"autocomment\">"),dump.indexOf("</span>")+7); 
				String summaries[] = autoSummary.split("#", 2);
				if (sectionParsed == false)
				{
					summaryArray[0] = summaries[1];
					sectionParsed = true;
				}
				summaryArray[1]= dump.substring(0,dump.indexOf(autoSummary));
				summaryArray[1] = summaryArray[1].concat(dump.substring(dump.indexOf(autoSummary)+ autoSummary.length()).trim());
				summaryArray[0] = summaryArray[0].substring(0,summaryArray[0].lastIndexOf("<"));
				summaryArray[0] = summaryArray[0].substring(summaryArray[0].lastIndexOf(">")+1);
				if (summaryArray[0].endsWith(" -")== true)
				{
					summaryArray[0] = summaryArray[0].substring(0,summaryArray[0].length()-1);
				}
			}
			else
			{
				if (dump != "") summaryArray[1] = dump;
			}
			
			if (summaryArray[0]=="") summaryArray[0]=null;
			if (summaryArray[1]=="") summaryArray[1]=null; //so the edge cases don't trigger exceptions
			if (summaryArray[1] != null)
			{
				if (summaryArray[1].length() != 0)
				{
					summaryArray[1] = summaryArray[1].substring(summaryArray[1].indexOf(">")+1,summaryArray[1].lastIndexOf("<"));
					summaryArray[1] = summaryArray[1].trim();
				}
			}
			
			if (summaryArray[0] != null) summaryArray[0] = summaryArray[0].trim();
			
		}
		return summaryArray;
	}
	
}

Contrib.java

/**
 * @author Titoxd
 * @program Contribution class for Flcelloguy's Tool
 * @version 3.30; released January 15, 2006
 * @see [[User:Flcelloguy/Tool]]
 * @docRoot http://en.wikipedia.org/wiki/User:Titoxd/Flcelloguy's_Tool
 * @copyright Permission is granted to distribute freely, provided attribution is granted.
 */
public class Contrib
{

	public Contrib(String inStamp, String inName, boolean inMin, String inSummary, String inAuto, boolean inTop)
	{
		timeStamp = inStamp;
		pageName = inName;
		namespace = FindNameSpace(pageName);
		shortName = FindShortName(pageName);
		minorEdit = inMin;
		editSummary = inSummary;
		autoSummary = inAuto;
		topEdit = inTop;
		
	}

	private String FindNameSpace(String inName)
	{
		String[] nameArray=inName.split(":",2);
		if (nameArray[0].compareTo(inName)==0)
		{
			nameArray[0] = namespaceArray[0];
		}
		return nameArray[0];
	}
	
	private String FindShortName(String inName)
	{
		String name=null;
		if (inName.contains(":"))
		{
			String[] nameArray=inName.split(":",2);
			name = nameArray[1];
		}
		else
		{
			name = inName;
		}
		return name;
	}
	
	
	public String timeStamp;
	public String pageName;
	public String namespace;
	public String shortName;
	public boolean minorEdit;
	public String editSummary;
	public String autoSummary;
	public boolean topEdit;
	private static String[] namespaceArray = 		//list of namespaces from [[Wikipedia:Namespace]]
		{
		"Main", "Talk", "User", "User_talk", 
		"Wikipedia", "Wikipedia_talk", "Image", "Image_talk", "MediaWiki", "MediaWiki_talk", 
		"Template", "Template_talk", "Help", "Help_talk", "Category", "Category_talk", 
		"Portal", "Portal_talk", "Media", "Special",
		}; 

	
	public String toString()
	{
		String returnString = "Time: " + timeStamp + "\r" + 
			"Page: " + pageName + " (Namespace: " + namespace + "; Article: " + shortName + ")\r" + 
			"Minor edit: " + minorEdit + "\r" + 
			"Edit Summary: " + editSummary + "\r" +
			"Most recent edit: " + topEdit;
		return returnString;
	}
}

MainGUI.java

/**
 * @author Titoxd
 * @program Graphical User Interface shell for Flcelloguy's Tool
 * @version 3.30; released January 15, 2006
 * @see [[User:Flcelloguy/Tool]]
 * @docRoot http://en.wikipedia.org/wiki/User:Titoxd/Flcelloguy's_Tool
 * @copyright Permission is granted to distribute freely, provided attribution is granted.
 */
import javax.swing.JDesktopPane;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JMenuBar;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import java.awt.event.*;
import java.awt.*;

public class MainGUI extends JFrame
                               implements ActionListener {
	static JDesktopPane desktop;

    public MainGUI() {
        super("Flcelloguy's Tool");

        //Make the big window be indented 50 pixels from each edge
        //of the screen.
        int inset = 100;
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        setBounds(inset, inset,
                  screenSize.width  - inset*2,
                  screenSize.height - inset*2);

        //Set up the GUI.
        desktop = new JDesktopPane(); //a specialized layered pane
        createFrame(); //create first "window"
        setContentPane(desktop);
        setJMenuBar(createMenuBar());

        //Make dragging a little faster but perhaps uglier.
        desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
    }

    protected JMenuBar createMenuBar() {
        JMenuBar menuBar = new JMenuBar();

        //Set up the lone menu.
        JMenu menu = new JMenu("Document");
        menu.setMnemonic(KeyEvent.VK_D);
        menuBar.add(menu);

        //Set up the first menu item.
        JMenuItem menuItem = new JMenuItem("New Query");
        menuItem.setMnemonic(KeyEvent.VK_N);
        menuItem.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_N, ActionEvent.ALT_MASK));
        menuItem.setActionCommand("new");
        menuItem.addActionListener(this);
        menu.add(menuItem);

        //Set up the second menu item.
        menuItem = new JMenuItem("Quit");
        menuItem.setMnemonic(KeyEvent.VK_Q);
        menuItem.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_Q, ActionEvent.ALT_MASK));
        menuItem.setActionCommand("quit");
        menuItem.addActionListener(this);
        menu.add(menuItem);

        return menuBar;
    }

    //React to menu selections.
    public void actionPerformed(ActionEvent e) {
        if ("new".equals(e.getActionCommand())) { //new
            createFrame();
        } else { //quit
            quit();
        }
    }

    //Create a new internal frame.
    protected void createFrame() {
        QueryFrame frame = new QueryFrame();
        frame.setVisible(true);
        desktop.add(frame);
        try {
            frame.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {}
    }

    protected static void createTextFrame(String passedString) {
        ResultsFrame frame = new ResultsFrame(passedString);
        frame.setVisible(true);
        desktop.add(frame);
        try {
            frame.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {}
    }
    
    protected void quit() {
        System.exit(0);
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI()
    {
    	try 
   		{
        UIManager.setLookAndFeel(
        		UIManager.getSystemLookAndFeelClassName());
   		} catch (Exception e) { }

    	//Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);

        //Create and set up the window.
        MainGUI frame = new MainGUI();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Display the window.
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }


}

QueryFrame.java

/**
 * @author Titoxd
 * @program Query Graphical User Interface for Flcelloguy's Tool
 * @version 3.30; released January 15, 2006
 * @see [[User:Flcelloguy/Tool]]
 * @docRoot http://en.wikipedia.org/wiki/User:Titoxd/Flcelloguy's_Tool
 * @copyright Permission is granted to distribute freely, provided attribution is granted.
 */
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import java.awt.event.*;
import java.awt.*;
import java.io.IOException;

/* Used by MainGUI.java. */
public class QueryFrame extends JInternalFrame implements ActionListener 
{
    static int openFrameCount = 0;
    static final int xOffset = 30, yOffset = 30;

    private JLabel topLabel = new JLabel("Look at the online help: http://en.wikipedia.org/wiki/User:Flcelloguy/Tool/Help");
	private JLabel label = new JLabel("Flcelloguy's Tool: Statistics for editcounters.");
	private String[] phases = { "Single file (up to 5,000 edits)",
		"Multiple files (5000 edits or more)"};
	private JComboBox box = new JComboBox(phases);
	private JButton button = new JButton("Proceed");

    public QueryFrame() {
        super("New Query "+ (++openFrameCount), 
              true, //resizable
              true, //closable
              true, //maximizable
              true);//iconifiable

        //...Create the GUI and put it in the window...
        
        
        JPanel panel = (JPanel) createComponents(); 
		panel.setBorder(BorderFactory.createEmptyBorder(
                20, //top
                30, //left
                10, //bottom
                30) //right
                );
		getContentPane().add(panel);
		
        //...Then set the window size or call pack...
		pack();
		
        //Set the window's location.
        setLocation(xOffset*openFrameCount, yOffset*openFrameCount);
    }
	public Component createComponents()
	{
		label.setLabelFor(button);
		button.setMnemonic('i'); 
		button.addActionListener(this);
		
		box.setSelectedIndex(0);
		box.addActionListener(this);
		JPanel panel = new JPanel(new GridLayout(0,1));
		panel.add(topLabel);
		panel.add(box);
		panel.add(button);
		panel.add(label);
		
		return panel;
	}

	public void actionPerformed(ActionEvent event)
    {
		if ("comboBoxChanged".equals(event.getActionCommand()))
		{
			if (box.getSelectedItem().equals(phases[0])) label.setText("This method asks you to parse a single contributions file.");
			if (box.getSelectedItem().equals(phases[1])) label.setText("This method asks you for several contributions files to parse.");
		}
		if ("Proceed".equals(event.getActionCommand()))
		{
			if (box.getSelectedItem().equals(phases[0])) try
			{
				Stats.reset();
				Stats.mainSingle(null);
			}
			catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (box.getSelectedItem().equals(phases[1])) try
			{
				Stats.reset();
				Stats.mainMulti(null);
			}
			catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			dispose();
		}
    }

}

ResultsFrame.java

/**
 * @author Titoxd
 * @program Results Graphical User Interface for Flcelloguy's Tool
 * @version 3.30; released January 15, 2006
 * @see [[User:Flcelloguy/Tool]]
 * @docRoot http://en.wikipedia.org/wiki/User:Titoxd/Flcelloguy's_Tool
 * @copyright Permission is granted to distribute freely, provided attribution is granted.
 */
import javax.swing.BorderFactory;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import java.awt.*;

/* Used by MainGUI.java. */
public class ResultsFrame extends JInternalFrame
{
	private static final long serialVersionUID = -132302847428809365L;
	static int openFrameCount = 0;
    static final int xOffset = 30, yOffset = 30;
    private String consoleText=null;

    public ResultsFrame(String inText) {
        super("Query Results "+ (++openFrameCount), 
              true, //resizable
              true, //closable
              true, //maximizable
              true);//iconifiable

        //...Create the GUI and put it in the window...
        
        consoleText = inText;
        JPanel panel = (JPanel) createComponents(); 
		panel.setBorder(BorderFactory.createEmptyBorder(
                20, //top
                30, //left
                10, //bottom
                30) //right
                );
		getContentPane().add(panel);
		
        //...Then set the window size or call pack...
		pack();
		
        //Set the window's location.
        setLocation(xOffset*openFrameCount, yOffset*openFrameCount);
    }
	public Component createComponents()
	{
		//Create a text area.
        JTextArea textArea = new JTextArea(consoleText);
        textArea.setFont(new Font("Monospace", Font.PLAIN, 12));
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        JScrollPane areaScrollPane = new JScrollPane(textArea);
        areaScrollPane.setVerticalScrollBarPolicy(
                        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        areaScrollPane.setPreferredSize(new Dimension(250, 250));
        areaScrollPane.setBorder(
            BorderFactory.createCompoundBorder(
                BorderFactory.createCompoundBorder(
                                BorderFactory.createTitledBorder("WikiText"),
                                BorderFactory.createEmptyBorder(5,5,5,5)),
                areaScrollPane.getBorder()));

		
        JPanel panel = new JPanel(new GridLayout(0,1));
		panel.add(areaScrollPane);
		
		return panel;
	}


}