From 70fd7817176222991ace7906ecfd633c9b3eb272 Mon Sep 17 00:00:00 2001 From: Charles McGarvey Date: Thu, 11 Nov 2010 22:23:36 -0700 Subject: [PATCH] improved C++ driver template fixes #3 --- src/com/dogcows/Editor.java | 115 ++++++++----- .../dogcows/{Utilities.java => Utility.java} | 7 +- src/com/dogcows/VimCoder.java | 26 +-- src/com/dogcows/resources/C++Driver | 152 ++++++++++++------ src/com/dogcows/resources/C++Template | 2 +- src/com/dogcows/resources/C++Test | 1 - 6 files changed, 199 insertions(+), 104 deletions(-) rename src/com/dogcows/{Utilities.java => Utility.java} (92%) delete mode 100644 src/com/dogcows/resources/C++Test diff --git a/src/com/dogcows/Editor.java b/src/com/dogcows/Editor.java index dda5481..ddb7ccf 100644 --- a/src/com/dogcows/Editor.java +++ b/src/com/dogcows/Editor.java @@ -7,8 +7,7 @@ import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import com.topcoder.client.contestant.ProblemComponentModel; import com.topcoder.shared.language.Language; @@ -24,7 +23,6 @@ public class Editor { private String id; private String name; - private File sourceFile; private File directory; @@ -44,8 +42,8 @@ public class Editor Language language, Renderer renderer) throws IOException { - this.id = String.valueOf(component.getProblem().getProblemID()); - this.name = component.getClassName(); + this.id = String.valueOf(component.getProblem().getProblemID()); + this.name = component.getClassName(); File topDir = new File(System.getProperty("user.home"), ".vimcoder"); if (!topDir.isDirectory()) @@ -63,13 +61,18 @@ public class Editor String ext = languageExtension.get(lang); HashMap terms = new HashMap(); - terms.put("RETURNTYPE", component.getReturnType().getDescriptor(language)); - terms.put("CLASSNAME", component.getClassName()); + terms.put("RETURNTYPE", component.getReturnType().getDescriptor(language).replaceAll("\\s+", "")); + terms.put("CLASSNAME", name); terms.put("METHODNAME", component.getMethodName()); terms.put("METHODPARAMS", getMethodParams(component.getParamTypes(), component.getParamNames(), language)); - terms.put("METHODPARAMNAMES", Utilities.join(component.getParamNames(), ", ")); + terms.put("METHODPARAMNAMES", Utility.join(component.getParamNames(), ", ")); + terms.put("METHODPARAMSTREAMIN", Utility.join(component.getParamNames(), " >> ")); + terms.put("METHODPARAMSTREAMOUT", Utility.join(component.getParamNames(), " << ")); + terms.put("METHODPARAMDECLARES", getMethodParamDeclarations(component.getParamTypes(), + component.getParamNames(), + language)); File problemFile = new File(directory, "Problem.html"); if (!problemFile.canRead()) @@ -85,36 +88,41 @@ public class Editor writer.close(); } - sourceFile = new File(directory, terms.get("CLASSNAME") + "." + ext); + sourceFile = new File(directory, name + "." + ext); if (!sourceFile.canRead()) { - String text = Utilities.expandTemplate(Utilities.readResource(lang + "Template"), + String text = Utility.expandTemplate(Utility.readResource(lang + "Template"), terms); FileWriter writer = new FileWriter(sourceFile); writer.write(text); writer.close(); } - File driverFile = new File(directory, "driver" + "." + ext); - if (!driverFile.canRead()) + File testcaseFile = new File(directory, "testcases.txt"); + if (!testcaseFile.canRead()) { - StringBuilder testCases = new StringBuilder(); + StringBuilder text = new StringBuilder(); if (component.hasTestCases()) { - HashMap testTerms = new HashMap(); - testTerms.putAll(terms); - String template = Utilities.readResource(lang + "Test"); for (TestCase testCase : component.getTestCases()) { - testTerms.put("TESTOUTPUT", "\"" + Utilities.quote(testCase.getOutput()) + "\""); - testTerms.put("TESTINPUTS", Utilities.join(testCase.getInput(), ", ")); - testCases.append(Utilities.expandTemplate(template, testTerms)); + text.append(testCase.getOutput() + System.getProperty("line.separator")); + for (String input : testCase.getInput()) + { + text.append(input + System.getProperty("line.separator")); + } } } - terms.put("TESTCASES", testCases.toString()); - - String text = Utilities.expandTemplate(Utilities.readResource(lang + "Driver"), - terms); + FileWriter writer = new FileWriter(testcaseFile); + writer.write(text.toString()); + writer.close(); + } + + File driverFile = new File(directory, "driver." + ext); + if (!driverFile.canRead()) + { + String text = Utility.expandTemplate(Utility.readResource(lang + "Driver"), + terms); FileWriter writer = new FileWriter(driverFile); writer.write(text); writer.close(); @@ -122,15 +130,15 @@ public class Editor File makeFile = new File(directory, "Makefile"); { - String text = Utilities.expandTemplate(Utilities.readResource(lang + "Makefile"), + String text = Utility.expandTemplate(Utility.readResource(lang + "Makefile"), terms); FileWriter writer = new FileWriter(makeFile); writer.write(text); writer.close(); } } - - public void setSource(String source) throws IOException + + public void setSource(String source) throws Exception { FileWriter writer = new FileWriter(new File(directory, name)); writer.write(source); @@ -140,40 +148,63 @@ public class Editor public String getSource() throws IOException { - return Utilities.readFile(sourceFile) + "\n// Edited by " + VimCoder.version + "\n// " + VimCoder.website + "\n\n"; + return Utility.readFile(sourceFile) + "\n// Edited by " + VimCoder.version + "\n// " + VimCoder.website + "\n\n"; } - private boolean doVimCommand(String command, String argument) + private void doVimCommand(String command, String argument) throws Exception { String[] arguments = {argument}; - return doVimCommand(command, arguments); + doVimCommand(command, arguments); } - private boolean doVimCommand(String command, String[] arguments) + private void doVimCommand(String command, String[] arguments) throws Exception { - try + String[] exec = {"gvim", "--servername", "VimCoder" + id, + command}; + exec = Utility.concat(exec, arguments); + Process child = Runtime.getRuntime().exec(exec, null, directory); + + long expire = System.currentTimeMillis() + 500; + while (System.currentTimeMillis() < expire) { - String[] exec = {"gvim", "--servername", "VimCoder" + id, - command}; - exec = Utilities.concat(exec, arguments); - Runtime.getRuntime().exec(exec, null, directory); + try + { + int exitCode = child.exitValue(); + if (exitCode != 0) throw new Exception("Vim process returned exit code " + exitCode + "."); + break; + } + catch (IllegalThreadStateException exception) + { + } + Thread.yield(); } - catch (IOException exception) + } + + private String getMethodParams(DataType[] types, + String[] names, + Language language) + { + StringBuilder text = new StringBuilder(); + + text.append(types[0].getDescriptor(language).replaceAll("\\s+", "") + " " + names[0]); + for (int i = 1; i < names.length; ++i) { - System.out.println("Failed to launch external vim process. :-("); + text.append(", " + types[i].getDescriptor(language).replaceAll("\\s+", "") + " " + names[i]); } - return false; + + return text.toString(); } - private String getMethodParams(DataType[] types, String[] names, Language language) + private String getMethodParamDeclarations (DataType[] types, + String[] names, + Language language) { StringBuilder text = new StringBuilder(); - text.append(types[0].getDescriptor(language) + " " + names[0]); - for (int i = 1; i < names.length; ++i) + for (int i = 0; i < names.length; ++i) { - text.append(", " + types[i].getDescriptor(language) + " " + names[i]); + text.append(types[i].getDescriptor(language).replaceAll("\\s+", "") + "\t" + names[i] + ";" + System.getProperty("line.separator")); } return text.toString(); diff --git a/src/com/dogcows/Utilities.java b/src/com/dogcows/Utility.java similarity index 92% rename from src/com/dogcows/Utilities.java rename to src/com/dogcows/Utility.java index 7dddd1f..9b4c7cc 100644 --- a/src/com/dogcows/Utilities.java +++ b/src/com/dogcows/Utility.java @@ -9,7 +9,7 @@ import java.util.Map; * @author Charles McGarvey * */ -public abstract class Utilities +public abstract class Utility { public static T[] concat(T[] a, T[] b) @@ -61,7 +61,7 @@ public abstract class Utilities { StringBuilder text = new StringBuilder(); - InputStream stream = Utilities.class.getResourceAsStream("resources/" + path); + InputStream stream = Utility.class.getResourceAsStream("resources/" + path); if (stream != null) { try @@ -88,8 +88,9 @@ public abstract class Utilities for (String key : terms.keySet()) { text = text.replaceAll("\\$" + key + "\\$", - Utilities.quote(terms.get(key))); + Utility.quote(terms.get(key))); } return text; } } + diff --git a/src/com/dogcows/VimCoder.java b/src/com/dogcows/VimCoder.java index 5f69aaa..1fb9bab 100644 --- a/src/com/dogcows/VimCoder.java +++ b/src/com/dogcows/VimCoder.java @@ -48,6 +48,7 @@ public class VimCoder public void startUsing() { + System.out.println("startUsing"); Runnable task = new Runnable() { public void run() @@ -67,39 +68,43 @@ public class VimCoder public void stopUsing() { + System.out.println("stopUsing"); editor = null; } public JPanel getEditorPanel() { + System.out.println("getEditorPanel"); return panel; } - public String getSource() throws IOException + public String getSource() throws Exception { + System.out.println("getSource"); try { String source = editor.getSource(); logInfo("Source code uploaded to server."); return source; } - catch (IOException exception) + catch (Exception exception) { - logError("Failed to open source file for reading."); + logError("Failed to get source code: " + exception.getLocalizedMessage()); throw exception; } } public void setSource(String source) { + System.out.println("setSource: " + source); try { editor.setSource(source); logInfo("Source code downloaded from server."); } - catch (IOException exception) + catch (Exception exception) { - logError("Failed to save the source given by the server."); + logError("Failed to save the source given by the server: " + exception.getLocalizedMessage()); return; } } @@ -108,13 +113,14 @@ public class VimCoder Language language, Renderer renderer) { + System.out.println("setProblemComponent"); try { editor = new Editor(component, language, renderer); } - catch (IOException exception) + catch (Exception exception) { - logError("An error occured while loading the problem."); + logError("An error occured while loading the problem: " + exception.getLocalizedMessage()); } } @@ -141,17 +147,17 @@ public class VimCoder private void logInfo(String what) { - log(" INFO: " + what + "\n"); + log(" INFO: " + what + System.getProperty("line.separator")); } private void logWarning(String what) { - log(" WARN: " + what + "\n"); + log(" WARN: " + what + System.getProperty("line.separator")); } private void logError(String what) { - log("ERROR: " + what + "\n"); + log("ERROR: " + what + System.getProperty("line.separator")); } diff --git a/src/com/dogcows/resources/C++Driver b/src/com/dogcows/resources/C++Driver index 9f25901..718ced4 100644 --- a/src/com/dogcows/resources/C++Driver +++ b/src/com/dogcows/resources/C++Driver @@ -1,14 +1,18 @@ #include "$CLASSNAME$.cc" +#include +#include #include #include +#include #include +#include -static bool __exit_on_fail = false; -static int __pass = 0; -static int __fail = 0; -static double __time = 0.0; +using namespace std; + + +static double __time = 0.0; static void __timer_start() { @@ -26,77 +30,131 @@ static double __timer_stop() return __time - start; } -template -std::string __encode(const T& in) -{ - std::ostringstream s; - s << in; - return s.str(); -} -std::string __encode(const std::string& in) +std::ostream& operator << (std::ostream& out, const std::string& str) { - std::ostringstream s; - s << '"' << in << '"'; - return s.str(); + out << '"' << str.c_str() << '"'; + return out; } template -std::string __join(const std::vector& in, const std::string& glue) +std::ostream& operator << (std::ostream& out, const std::vector& vec) { - if (in.size() == 0) return ""; - std::ostringstream s; - s << __encode(in[0]); - for (size_t i = 1; i < in.size(); ++i) s << glue << __encode(in[i]); - return s.str(); + out << '{'; + if (0 < vec.size()) + { + out << vec[0]; + for (size_t i = 1; i < vec.size(); ++i) out << ", " << vec[i]; + } + out << '}'; + return out; } -template -std::string __encode(const std::vector& in) +std::istream& operator >> (std::istream& in, std::string& str) { - std::ostringstream s; - s << "{ " << __join(in, ", ") << " }"; - return s.str(); + while (in.good() && std::isspace(in.peek())) in.get(); + + int c; + if (in.good() && (c = in.get()) == '"') + { + std::ostringstream s; + while (in.good() && (c = in.get()) != '"') + { + s.put(char(c)); + } + str = s.str(); + } + else + { + in.putback(c); + } + + return in; } -void __do_test(const std::string& expected, $METHODPARAMS$) +template +std::istream& operator >> (std::istream& in, std::vector& vec) { - static int testNum = 0; - std::cout << "----------------------------------------" << std::endl - << "Test " << testNum++ << ": "; + while (in.good() && std::isspace(in.peek())) in.get(); - __timer_start(); - - $CLASSNAME$ object; - $RETURNTYPE$ ret = object.$METHODNAME$($METHODPARAMNAMES$); - - double t = __timer_stop(); - - std::string actual = __encode(ret); - if (actual == expected) + int c; + if (in.good() && (c = in.get()) == '{') { - std::cout << "[PASS] in " << t << " seconds." << std::endl; - ++__pass; + while (in.good() && std::isspace(in.peek())) in.get(); + T t; + vec.clear(); + while (in.good() && (c = in.get()) != '}') + { + if (c != ',') in.putback(c); + in >> t; + vec.push_back(t); + while (in.good() && std::isspace(in.peek())) in.get(); + } + } else { - std::cout << "[FAIL] in " << t << " seconds." << std::endl - << " Actual: " << actual << std::endl - << " Expected: " << expected << std::endl; - ++__fail; - if (__exit_on_fail) exit(1); + in.putback(c); } + + return in; } + int main(int argc, char* argv[]) { + bool __exit_on_fail = false; + int __pass = 0; + int __fail = 0; + if (1 < argc) __exit_on_fail = true; + + std::ifstream __in("testcases.txt"); + for(;;) + { + $RETURNTYPE$ __expected; + $METHODPARAMDECLARES$ + __in >> __expected >> $METHODPARAMSTREAMIN$; + if (!__in.good()) break; + + std::cout << "----------------------------------------" << std::endl + << "Test " << (__pass + __fail) << ": "; + std::cout.flush(); + + __timer_start(); + + $CLASSNAME$ object; + $RETURNTYPE$ __actual = object.$METHODNAME$($METHODPARAMNAMES$); + + double __t = __timer_stop(); + + if (__actual == __expected) + { + std::cout << "[PASS] in " << __t << " seconds." << std::endl; + ++__pass; + } + else + { + std::cout << "[FAIL] in " << __t << " seconds." << std::endl + << "-> Input: " << $METHODPARAMSTREAMOUT$ << std::endl + << " Actual: " << __actual << std::endl + << " Expected: " << __expected << std::endl; + ++__fail; + if (__exit_on_fail) exit(1); + } + } -$TESTCASES$ std::cout << "========================================" << std::endl << " Total Pass: " << __pass << std::endl << " Total Fail: " << __fail << std::endl; + if (__fail == 0) + { + std::cout << std::endl << "Nice! " + << "Don't forget to compile remotely before submitting." + << std::endl; + } + return __fail; } diff --git a/src/com/dogcows/resources/C++Template b/src/com/dogcows/resources/C++Template index 7cd56b2..f287af4 100644 --- a/src/com/dogcows/resources/C++Template +++ b/src/com/dogcows/resources/C++Template @@ -36,7 +36,7 @@ class $CLASSNAME$ public: $RETURNTYPE$ $METHODNAME$($METHODPARAMS$) { - + return $RETURNTYPE$(); } }; diff --git a/src/com/dogcows/resources/C++Test b/src/com/dogcows/resources/C++Test deleted file mode 100644 index 4316d38..0000000 --- a/src/com/dogcows/resources/C++Test +++ /dev/null @@ -1 +0,0 @@ - __do_test($TESTOUTPUT$, $TESTINPUTS$); -- 2.45.2