ADDED   TZTesterSp/ContestApplet.jar
Index: TZTesterSp/ContestApplet.jar
==================================================================
--- TZTesterSp/ContestApplet.jar
+++ TZTesterSp/ContestApplet.jar
cannot compute difference between binary files

ADDED   TZTesterSp/Makefile
Index: TZTesterSp/Makefile
==================================================================
--- TZTesterSp/Makefile
+++ TZTesterSp/Makefile
@@ -0,0 +1,11 @@
+TZTester.jar: tangentz/TZTester.class
+	jar cvf TZTester.jar tangentz/TZTester.class
+
+install: TZTester.jar
+	cp TZTester.jar ../workspace/arena_plugin
+
+clean:
+	rm -f TZTester.jar tangentz/TZTester.class
+
+tangentz/TZTester.class: tangentz/TZTester.java
+	javac -classpath ContestApplet.jar tangentz/TZTester.java

ADDED   TZTesterSp/tangentz/TZTester.java
Index: TZTesterSp/tangentz/TZTester.java
==================================================================
--- TZTesterSp/tangentz/TZTester.java
+++ TZTesterSp/tangentz/TZTester.java
@@ -0,0 +1,295 @@
+package tangentz;
+import java.util.HashMap;
+import java.util.Map;
+import com.topcoder.client.contestant.ProblemComponentModel;
+import com.topcoder.shared.language.Language;
+import com.topcoder.shared.problem.*;
+
+
+/**
+ * @author TangentZ
+ *
+ * This tester class is for C++ only.  It is based on PopsProcessor which is written for Java.
+ * It reads in all the given examples for a problem and generates the equivalent C++ code
+ * to test all the cases.  The accumulated running time is 8 seconds, but it is easy to
+ * selectively run a specific case only.
+ *
+ * This tester will define three tags that can be embedded within PopsEdit/FileEdit code template:
+ *	$WRITERCODE$ - place holder for writer code - will be blank if none found
+ *	$PROBLEM$ - place holder for problem description as plain text
+ *	// $RUNTEST$ - place holder for where to put the code that starts the test
+ *	$TESTCODE$ - place holder for where to put the test code
+ */
+public class TZTester
+{
+	// Map used to store my tags
+	private HashMap<String,String> m_Tags = new HashMap<String,String>();
+
+	// Constants
+	private static final String k_WRITERCODE = "$WRITERCODE$";
+	private static final String k_PROBLEM    = "$PROBLEM$";
+	private static final String k_RUNTEST    = "$RUNTEST$";
+	private static final String k_TESTCODE   = "$TESTCODE$";
+	private static final String k_VERSION    = "\n// Powered by TZTester 1.01 [25-Feb-2003] : <cafelier&naoya_t>-custom";
+
+	// Cut tags
+	private static final String k_BEGINCUT   = "// BEGIN CUT HERE";
+	private static final String k_ENDCUT	 = "// END CUT HERE";
+
+	// Problem-related variables
+	private ProblemComponentModel m_Problem   = null;
+	private Language			  m_Language  = null;
+	
+	/**
+	 * PreProcess the source code
+	 * 
+	 * First determines if it is saved code, writer code, or nothing and stores it in $WRITERCODE$ tag
+	 * Secondly builds a main method with default test cases
+	 */
+	public String preProcess(String Source, ProblemComponentModel Problem, Language Lang, Renderer Render)
+	{
+		// Set defaults for the tags in case we exit out early
+		m_Tags.put(k_WRITERCODE, "");
+		m_Tags.put(k_PROBLEM,    "");
+		m_Tags.put(k_RUNTEST,    "// *** WARNING *** $RUNTEST$ is not supported by this customized TZTester.");
+		m_Tags.put(k_TESTCODE,   "");
+
+		// If there is source and the source is NOT equal to the default solution, return it
+		if( Source.length()>0 && !Source.equals(Problem.getDefaultSolution()) )
+			return Source;
+
+		// Check to see if the component has any signature 
+		if( !Problem.hasSignature() )
+		{
+			m_Tags.put(k_TESTCODE, "// *** WARNING *** Problem has no signature defined for it");
+			return "";
+		}
+		
+		// Get the test cases
+		TestCase[] TestCases = Problem.getTestCases();
+
+		// Check to see if test cases are defined
+		if( TestCases==null || TestCases.length==0 )
+		{
+			m_Tags.put(k_TESTCODE, "// *** WARNING *** No test cases defined for this problem");
+			return "";
+		}
+
+		// Re-initialize the tags
+		m_Tags.clear();
+		m_Tags.put(k_WRITERCODE, Problem.getDefaultSolution());
+		try { m_Tags.put(k_PROBLEM, Render.toHTML(m_Language)); } catch (Exception Ex) { }
+
+		m_Problem  = Problem;
+		m_Language = Lang;
+
+		// Generate the test cases
+		generate_test_code();
+		return "";
+	}
+
+	/**
+	 * This method will cut the test methods above out
+	 */
+	public String postProcess(String Source, Language Lang)
+	{
+		// Insert a version string
+		return Source + k_VERSION;
+	}
+
+	/**
+	 * This method will return my tags.  This method is ALWAYS called after preProcess()
+	 * 
+	 * @return a map of my tags
+	 */
+	public Map getUserDefinedTags()
+	{
+		return m_Tags;
+	}
+
+	/**
+	 * This method will generate the code for the test cases.
+	 */
+	private void generate_test_code()
+	{
+		DataType[] ParamTypes = m_Problem.getParamTypes();
+		DataType ReturnType   = m_Problem.getReturnType();
+		TestCase[] Cases	  = m_Problem.getTestCases();
+		StringBuffer Code = new StringBuffer();
+
+		// <<thanks to naoya_t>> Generate the timer function
+		Code.append("#include <ctime>\n");
+		Code.append("double start_time; string timer()\n");
+		Code.append(" { ostringstream os; os << \" (\" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << \" msec)\"; return os.str(); }\n");
+
+		// Generate the vector output function
+		Code.append("template<typename T> ostream& operator<<(ostream& os, const vector<T>& v)\n");
+		Code.append(" { os << \"{ \";\n");
+		Code.append("   for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it)\n");
+		Code.append("   os << \'\\\"\' << *it << \'\\\"\' << (it+1==v.end() ? \"\" : \", \"); os << \" }\"; return os; }\n");
+
+		// Generate the verification function
+		generate_verification_code(Code, ReturnType);
+
+		// <<modified by cafelier>> : new test code template
+		Code.append("#define CASE(N) {cerr << \"Test Case #\" << N << \"...\" << flush; start_time=clock();\n");
+		Code.append("#define END	 ");
+		generate_verifier_call(Code, ParamTypes, ReturnType, Cases[0]);
+		Code.append("}\n");
+		Code.append("int main(){\n\n");
+
+		// Generate the individual test cases
+		for(int i=0; i<Cases.length; ++i)
+			generate_test_case(i, Code, ParamTypes, ReturnType, Cases[i]);
+		for(int i=0; i<2; ++i)
+			generate_blank_test_case(Cases.length+i, Code, ParamTypes, ReturnType, Cases[0]);
+		Code.append("\n}\n");
+
+		// Insert the cut tags
+		Code.insert(0, k_BEGINCUT+"\n");
+		Code.append(k_ENDCUT);
+
+		// Replace $TESTCODE$
+		m_Tags.put(k_TESTCODE, Code.toString());
+	}
+
+	/**
+	 * This method will generate the code for verifying test cases.
+	 */
+	private void generate_verification_code(StringBuffer Code, DataType ReturnType)
+	{
+		String TypeString = ReturnType.getDescriptor(m_Language);
+
+		// <<modified by cafelier>> : new test code template
+		Code.append("void verify_case(const " + TypeString + "& Expected, const " + TypeString + "& Received) {\n");
+
+		// Print "PASSED" or "FAILED" based on the result
+		// <<modified by naoya_t>> : double precision
+		if (TypeString.equals("double")) {
+			Code.append(" bool ok = (abs(Expected - Received) < 1e-9);\n");
+		} else if (TypeString.equals("vector <double>")) {
+			// <<modified by cafelier>> : vector<double> !!!
+			Code.append(" bool ok = true;\n");
+			Code.append(" for(int i=0; i<Expected.size(); ++i)\n");
+			Code.append("   if( abs(Expected[i]-Received[i]) >= 1e-9 )\n");
+			Code.append("     ok = false;\n");
+		} else {
+			Code.append(" bool ok = (Expected == Received);\n");
+		}
+		Code.append(" if(ok) cerr << \"PASSED\" << timer() << endl; ");
+		Code.append(" else { cerr << \"FAILED\" << timer() << endl;\n ");
+
+		if (ReturnType.getDimension() == 0)
+		{
+			Code.append("cerr << \"\\to: \\\"\" << Expected << \'\\\"\' << endl ");
+			Code.append("<< \"\\tx: \\\"\" << Received << \'\\\"\' << endl; }");
+		}
+		else
+		{
+			Code.append("cerr << \"\\to: \" << Expected << endl ");
+			Code.append("<< \"\\tx: \" << Received << endl; }");
+		}
+
+		Code.append(" }\n");
+	}
+
+	/**
+	 * This method will generate the code for one test case.
+	 */
+	private void generate_test_case(int Index, StringBuffer Code, DataType[] ParamTypes, DataType ReturnType, TestCase Case)
+	{
+		String[] Inputs = Case.getInput();
+		String Output = Case.getOutput();
+		String Desc = ReturnType.getDescription();
+
+		/*
+		 * Generate code for setting up individual test cases
+		 * and calling the method with these parameters.
+		*/
+
+		// <<modified by cafelier>> : new test code template
+		Code.append("CASE("+Index+")\n");
+
+		// Generate each input variable separately
+		for (int I = 0; I < Inputs.length; ++I) {
+			Code.append("\t");
+			generate_parameter(I, Code, ParamTypes[I], Inputs[I]);
+			Code.append("\n");
+		}
+
+		// Generate the output variable as the last variable
+		Code.append("\t");
+		generate_parameter(-1, Code, ReturnType, Output);
+		Code.append("\n");
+		Code.append("END\n");
+	}
+
+	private void generate_blank_test_case(int Index, StringBuffer Code, DataType[] ParamTypes, DataType ReturnType, TestCase Case)
+	{
+		String[] Inputs = Case.getInput();
+		String Output = Case.getOutput();
+		String Desc = ReturnType.getDescription();
+
+		Code.append("CASE("+Index+")\n");
+		for (int I = 0; I < Inputs.length; ++I) {
+			Code.append("\t");
+			generate_parameter(I, Code, ParamTypes[I], "");
+			Code.append("\n");
+		}
+		Code.append("\t");
+		generate_parameter(-1, Code, ReturnType, "");
+		Code.append("\n");
+		Code.append("END\n");
+	}
+
+	private void generate_verifier_call(StringBuffer Code, DataType[] ParamTypes, DataType ReturnType, TestCase Case)
+	{
+		String[] Inputs = Case.getInput();
+		String Output = Case.getOutput();
+		String Desc = ReturnType.getDescription();
+
+		Code.append("verify_case(_, "
+		  + m_Problem.getClassName() + "()." + m_Problem.getMethodName() + "(");
+		for(int i=0; i<Inputs.length; ++i)
+		{
+			Code.append( m_Problem.getParamNames()[i] );
+			if( i < Inputs.length-1 )
+				Code.append(", ");
+		}
+		Code.append("));");
+	}
+
+	/**
+	 * This method will generate the required parameter as a unique variable.
+	 */
+	private void generate_parameter(int Index, StringBuffer Code, DataType ParamType, String Input)
+	{
+		// <<modified by cafelier>> : named parameters
+		String Name = (Index==-1 ? "_" : m_Problem.getParamNames()[Index]);
+
+		String Desc = ParamType.getBaseName();
+
+		if (ParamType.getDimension() == 0)
+		{
+			// Just a scalar value, simply initialize it at declaration (long integers need an 'L' tagged on)
+			if (Desc.equals("long") || Desc.equals("Long"))
+				Code.append(ParamType.getDescriptor(m_Language) + " " + Name + " = " + Input + "LL; ");
+			else
+				Code.append(ParamType.getDescriptor(m_Language) + " " + Name + " = " + Input + "; ");
+		}
+		else
+		{
+			  // <<modified by cafelier>> : empty array
+			  if( Input.matches("^[\\s\\{\\}]+$") )
+			  {
+				Code.append(ParamType.getDescriptor(m_Language) + " " + Name + "; ");
+			  }
+			  else
+			  {
+				// Arrays need to be converted to vector<type> before passing
+				Code.append(ParamType.getBaseName().toLowerCase() + " " + Name + "_[] = " + Input + ";\n\t");
+				Code.append("  "+ParamType.getDescriptor(m_Language) + " " + Name + "(" + Name + "_, " + Name + "_+sizeof("+Name+"_)/sizeof(*"+Name+"_)); ");
+			  }
+		}
+	}
+}