├── .classpath ├── .gitignore ├── .project ├── BUILD ├── README ├── deploy ├── moj_instructions.txt ├── template.cpp └── template.java ├── deps ├── CodeProcessor.jar ├── ContestApplet.jar └── FileEdit.jar ├── package.sh ├── src └── moj │ ├── CPPHarnessGenerator.java │ ├── Common.java │ ├── ConfigurationDialog.java │ ├── ConstantFormatting.java │ ├── HarnessGenerator.java │ ├── JavaHarnessGenerator.java │ ├── LanguageAutoDetection.java │ ├── Preferences.java │ └── moj.java └── test └── moj ├── CPPParameterTest.java ├── JavaParameterTest.java └── mocks ├── DataTypeFactoryMock.java ├── PreferencesMock.java └── ProblemComponentModelMock.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .settings 2 | bin 3 | deploy/moj*.zip 4 | deploy/moj.jar 5 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | moj 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /BUILD: -------------------------------------------------------------------------------- 1 | The easiest way to build moj is to import the project into Eclipse 2 | (.classpath and .project files are provided). The script package.sh 3 | creates: 4 | - deploy/moj.jar (load this in the Arena) 5 | - deploy/moj.zip (suitable for distribution) 6 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Hello! 2 | 3 | moj is a plug-in for the TopCoder arena that helps you compete 4 | locally. When you open a problem, moj pulls the example test cases 5 | from the problem statement and adds test code to your source 6 | file. When you run your solution locally, it will be run on the 7 | examples. The test code will be stripped when you submit your solution 8 | in the Arena. 9 | 10 | moj supports C++ and Java. 11 | 12 | moj extends the functionality of TZTester. It requires CodeProcessor 13 | (v2.0 recommended) and FileEdit, both of which are bundled with 14 | moj. Improvements over TZTester are: 15 | 16 | 1. Output is prettier. Numbers are no longer surrounded by quotes. A 17 | small summary is output after the results for individual cases. If 18 | this summary does not appear, your program crashed while solving 19 | one of the cases. 20 | 21 | 2a. Doubles and arrays of doubles are compared correctly (with an 22 | absolute and relative tolerance of 1e-9). 23 | 24 | 2b. If the result is a double or array of doubles and your output is 25 | not exact, moj will display the relative error of your output. 26 | For example: 27 | 28 | Test Case #0... PASSED (relative error 5.44969e-014) 29 | Test Case #1... PASSED (relative error 5.68462e-012) 30 | Test Case #2... PASSED (relative error 4.05691e-008) 31 | Test Case #3... PASSED 32 | All 4 tests passed! 33 | 34 | The purpose of this feature is to alert you when your solution may 35 | be insufficiently precise. Test case 2 passes because the absolute 36 | error is small enough. However, it is a good indicator that your 37 | solution is not precise enough for systests. Indeed, modifying the 38 | code to use 80-bit floating-point variables changes the report to: 39 | 40 | Test Case #0... PASSED (relative error 2.88899e-015) 41 | Test Case #1... PASSED (relative error 3.82932e-015) 42 | Test Case #2... PASSED (relative error 4.63219e-012) 43 | Test Case #3... PASSED 44 | All 4 tests passed! 45 | 46 | 3. Restructured test harness. Adding custom cases is much easier. 47 | Placeholders are in place at the bottom of the test code, just 48 | scroll down and uncomment one of them. You may also add additional 49 | cases. 50 | 51 | 4. Java support. Through a hack (language auto-detection from source 52 | code, based on heuristics) you may switch between Java and C++ 53 | after opening a problem. 54 | 55 | 5. Timing per test case. 56 | 57 | 6. Visual C++ support. 58 | 59 | 60 | Setup: 61 | 62 | 1. Unzip the three .jar files in the moj package to a folder of your 63 | liking. 64 | 65 | 2. Launch the Arena. Open the "Options" menu and select "Editors". 66 | 67 | 3. Add CodeProcessor, with entry point codeprocessor.EntryPoint. Add 68 | codeprocessor.jar, moj.jar and fileedit.jar to the classpath. 69 | 70 | 4. In the "Editor preferences" window, select CodeProcessor then 71 | "Configure". Under "Editor EntryPoint" write fileedit.EntryPoint. 72 | Configure FileEdit. 73 | 74 | The most important part is to update the code template(s). Under 75 | the "Code Template" tab, select your language and paste in the code 76 | template. Included in the moj package are minimal code templates 77 | for C++ and Java. 78 | 79 | On the "General" tab I recommend turning off "Backup existing file 80 | then overwrite". 81 | 82 | 5. In the CodeProcessor configuration window, write moj.moj as the 83 | processor class and verify. If all is good, you'll get 4 "found" 84 | reports. Configure moj to your liking. 85 | 86 | 87 | For bug reports, suggestions and questions, please use the member 88 | contact feature at the TopCoder website or the forum thread. My handle 89 | is lovro. 90 | -------------------------------------------------------------------------------- /deploy/moj_instructions.txt: -------------------------------------------------------------------------------- 1 | moj 4.18 2 | ======== 3 | 4 | Hello! 5 | 6 | moj is a plug-in for the TopCoder arena that helps you compete 7 | locally. When you open a problem, moj pulls the example test cases 8 | from the problem statement and adds test code to your source 9 | file. When you run your solution locally, it will be run on the 10 | examples. The test code will be stripped when you submit your solution 11 | in the Arena. 12 | 13 | moj supports C++ and Java. 14 | 15 | moj extends the functionality of TZTester. It requires CodeProcessor 16 | (v2.0 recommended) and FileEdit, both of which are bundled with 17 | moj. Improvements over TZTester are: 18 | 19 | 1. Output is prettier. Numbers are no longer surrounded by quotes. A 20 | small summary is output after the results for individual cases. If 21 | this summary does not appear, your program crashed while solving 22 | one of the cases. 23 | 24 | 2a. Doubles and arrays of doubles are compared correctly (with an 25 | absolute and relative tolerance of 1e-9). 26 | 27 | 2b. If the result is a double or array of doubles and your output is 28 | not exact, moj will display the relative error of your output. 29 | For example: 30 | 31 | Test Case #0... PASSED (relative error 5.44969e-014) 32 | Test Case #1... PASSED (relative error 5.68462e-012) 33 | Test Case #2... PASSED (relative error 4.05691e-008) 34 | Test Case #3... PASSED 35 | All 4 tests passed! 36 | 37 | The purpose of this feature is to alert you when your solution may 38 | be insufficiently precise. Test case 2 passes because the absolute 39 | error is small enough. However, it is a good indicator that your 40 | solution is not precise enough for systests. Indeed, modifying the 41 | code to use 80-bit floating-point variables changes the report to: 42 | 43 | Test Case #0... PASSED (relative error 2.88899e-015) 44 | Test Case #1... PASSED (relative error 3.82932e-015) 45 | Test Case #2... PASSED (relative error 4.63219e-012) 46 | Test Case #3... PASSED 47 | All 4 tests passed! 48 | 49 | 3. Restructured test harness. Adding custom cases is much easier. 50 | Placeholders are in place at the bottom of the test code, just 51 | scroll down and uncomment one of them. You may also add additional 52 | cases. 53 | 54 | 4. Java support. Through a hack (language auto-detection from source 55 | code, based on heuristics) you may switch between Java and C++ 56 | after opening a problem. 57 | 58 | 5. Timing per test case. 59 | 60 | 6. Visual C++ support. 61 | 62 | 63 | Setup: 64 | 65 | 1. Unzip the three .jar files in the moj package to a folder of your 66 | liking. 67 | 68 | 2. Launch the Arena. Open the "Options" menu and select "Editors". 69 | 70 | 3. Add CodeProcessor, with entry point codeprocessor.EntryPoint. Add 71 | codeprocessor.jar, moj.jar and fileedit.jar to the classpath. 72 | 73 | 4. In the "Editor preferences" window, select CodeProcessor then 74 | "Configure". Under "Editor EntryPoint" write fileedit.EntryPoint. 75 | Configure FileEdit. 76 | 77 | The most important part is to update the code template(s). Under 78 | the "Code Template" tab, select your language and paste in the code 79 | template. Included in the moj package are minimal code templates 80 | for C++ and Java. 81 | 82 | On the "General" tab I recommend turning off "Backup existing file 83 | then overwrite". 84 | 85 | 5. In the CodeProcessor configuration window, write moj.moj as the 86 | processor class and verify. If all is good, you'll get 4 "found" 87 | reports. Configure moj to your liking. 88 | 89 | 90 | For bug reports, suggestions and questions, please use the member 91 | contact feature at the TopCoder website or the forum thread. My handle 92 | is lovro. 93 | -------------------------------------------------------------------------------- /deploy/template.cpp: -------------------------------------------------------------------------------- 1 | // Paste me into the FileEdit configuration dialog 2 | 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | class $CLASSNAME$ { 8 | public: 9 | $RC$ $METHODNAME$( $METHODPARMS$ ) { 10 | 11 | } 12 | }; 13 | 14 | $BEGINCUT$ 15 | $TESTCODE$ 16 | 17 | $DEFAULTMAIN$ 18 | $ENDCUT$ 19 | -------------------------------------------------------------------------------- /deploy/template.java: -------------------------------------------------------------------------------- 1 | // Paste me into the FileEdit configuration dialog 2 | 3 | public class $CLASSNAME$ { 4 | public $RC$ $METHODNAME$($METHODPARMS$) { 5 | 6 | } 7 | 8 | 9 | $BEGINCUT$ 10 | $DEFAULTMAIN$ 11 | $ENDCUT$ 12 | } 13 | 14 | $BEGINCUT$ 15 | $TESTCODE$ 16 | $ENDCUT$ 17 | -------------------------------------------------------------------------------- /deps/CodeProcessor.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lovrop/topcoder-moj/793a56d8e21d821000f9293bc3e0dc8f7d940895/deps/CodeProcessor.jar -------------------------------------------------------------------------------- /deps/ContestApplet.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lovrop/topcoder-moj/793a56d8e21d821000f9293bc3e0dc8f7d940895/deps/ContestApplet.jar -------------------------------------------------------------------------------- /deps/FileEdit.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lovrop/topcoder-moj/793a56d8e21d821000f9293bc3e0dc8f7d940895/deps/FileEdit.jar -------------------------------------------------------------------------------- /package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd $(dirname $0) 4 | 5 | VERSION=$(egrep -o 'Powered by moj [0-9][0-9a-zA-Z.]+' src/moj/moj.java | egrep -o '[0-9][0-9a-zA-Z.]+') 6 | echo "Version is $VERSION." 7 | 8 | echo "Creating jar..." 9 | rm -f deploy/moj.jar 10 | cd bin 11 | jar cf ../deploy/moj.jar moj/*.class 12 | cd .. 13 | 14 | rm -f deploy/moj_instructions.txt 15 | echo "moj $VERSION" >> deploy/moj_instructions.txt 16 | echo "moj $VERSION" | sed -e 's/./=/g' >> deploy/moj_instructions.txt 17 | echo >> deploy/moj_instructions.txt 18 | cat README >> deploy/moj_instructions.txt 19 | 20 | echo "Creating zip..." 21 | target=deploy/moj_$VERSION.zip 22 | rm -f $target 23 | zip -j $target deploy/moj.jar deps/CodeProcessor.jar deps/FileEdit.jar deploy/moj_instructions.txt deploy/template.cpp deploy/template.java 24 | 25 | echo "Done." 26 | -------------------------------------------------------------------------------- /src/moj/CPPHarnessGenerator.java: -------------------------------------------------------------------------------- 1 | package moj; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Set; 5 | import java.util.TreeSet; 6 | import java.util.regex.Pattern; 7 | 8 | import com.topcoder.client.contestant.ProblemComponentModel; 9 | import com.topcoder.shared.language.Language; 10 | import com.topcoder.shared.problem.*; 11 | 12 | public class CPPHarnessGenerator implements HarnessGenerator { 13 | final ProblemComponentModel m_problem; 14 | final Language m_lang; 15 | 16 | final Preferences m_pref; 17 | final String m_targetCompiler; 18 | 19 | static class TestCodeGenerationState { 20 | public Set headers = new TreeSet(); 21 | public ArrayList lines = new ArrayList(); 22 | 23 | public void add(String line) { 24 | lines.add(line); 25 | } 26 | 27 | public void addHeader(String header) { 28 | headers.add(header); 29 | } 30 | } 31 | 32 | public CPPHarnessGenerator(ProblemComponentModel problem, Language lang, Preferences pref) { 33 | m_problem = problem; 34 | m_lang = lang; 35 | m_pref = pref; 36 | m_targetCompiler = pref.getTargetCompiler(); 37 | } 38 | 39 | public String generateDefaultMain() { 40 | return 41 | "#include \n" + 42 | "int main(int argc, char *argv[]) {\n" + 43 | "\tif (argc == 1) {\n" + 44 | "\t\tmoj_harness::run_test();\n" + 45 | "\t} else {\n" + 46 | "\t\tfor (int i=1; i= 100) break;"); 84 | code.add(" continue;"); 85 | code.add(" }"); 86 | code.add(" correct += x;"); 87 | code.add(" ++total;"); 88 | code.add(" }"); 89 | code.add(" "); 90 | code.add(" if (total == 0) {"); 91 | code.add(" std::cerr << \"No test cases run.\" << std::endl;"); 92 | code.add(" } else if (correct < total) {"); 93 | code.add(" std::cerr << \"Some cases FAILED (passed \" << correct << \" of \" << total << \").\" << std::endl;"); 94 | code.add(" } else {"); 95 | code.add(" std::cerr << \"All \" << total << \" tests passed!\" << std::endl;"); 96 | code.add(" }"); 97 | code.add(" }"); 98 | code.add(" "); 99 | } 100 | 101 | void generateOutputComparison(TestCodeGenerationState code) { 102 | DataType returnType = m_problem.getReturnType(); 103 | if (returnType.getBaseName().equals("double")) { 104 | code.addHeader("algorithm"); // min, max 105 | code.addHeader("cmath"); // isinf, isnan, fabs 106 | String isinf, isnan; 107 | if (m_targetCompiler.equals(Preferences.TARGETCOMPILER_VC)) { 108 | isinf = "!_finite"; 109 | isnan = "_isnan"; 110 | } else if (m_targetCompiler.equals(Preferences.TARGETCOMPILER_GCC11)) { 111 | isinf = "std::isinf"; 112 | isnan = "std::isnan"; 113 | } else { 114 | isinf = "isinf"; 115 | isnan = "isnan"; 116 | } 117 | 118 | code.add(" static const double MAX_DOUBLE_ERROR = 1e-9;"); 119 | code.add(" static bool topcoder_fequ(double expected, double result) {"); 120 | code.add(" if (" + isnan + "(expected)) {"); 121 | code.add(" return " + isnan + "(result);"); 122 | code.add(" } else if (" + isinf + "(expected)) {"); 123 | code.add(" if (expected > 0) {"); 124 | code.add(" return result > 0 && " + isinf + "(result);"); 125 | code.add(" } else {"); 126 | code.add(" return result < 0 && " + isinf + "(result);"); 127 | code.add(" }"); 128 | code.add(" } else if (" + isnan + "(result) || " + isinf + "(result)) {"); 129 | code.add(" return false;"); 130 | code.add(" } else if (std::fabs(result - expected) < MAX_DOUBLE_ERROR) {"); 131 | code.add(" return true;"); 132 | code.add(" } else {"); 133 | code.add(" double mmin = std::min(expected * (1.0 - MAX_DOUBLE_ERROR), expected * (1.0 + MAX_DOUBLE_ERROR));"); 134 | code.add(" double mmax = std::max(expected * (1.0 - MAX_DOUBLE_ERROR), expected * (1.0 + MAX_DOUBLE_ERROR));"); 135 | code.add(" return result > mmin && result < mmax;"); 136 | code.add(" }"); 137 | code.add(" }"); 138 | code.add(" double moj_relative_error(double expected, double result) {"); 139 | code.add(" if (" + isnan + "(expected) || " + isinf + "(expected) || " + isnan + "(result) || " + isinf + "(result) || expected == 0) {"); 140 | code.add(" return 0;"); 141 | code.add(" }"); 142 | code.add(" return std::fabs(result-expected) / std::fabs(expected);"); 143 | code.add(" }"); 144 | if (returnType.getDimension() > 0) { 145 | code.addHeader("vector"); 146 | code.add(" static bool topcoder_fequ(const vector &a, const vector &b) { if (a.size() != b.size()) return false; for (size_t i=0; i &expected, const vector &result) { double ret = 0.0; for (size_t i=0; i 0) { 156 | code.addHeader("vector"); 157 | code.add(" template std::ostream& operator<<(std::ostream &os, const vector &v) { os << \"{\"; for (typename vector::const_iterator vi=v.begin(); vi!=v.end(); ++vi) { if (vi != v.begin()) os << \",\"; os << \" \" << *vi; } os << \" }\"; return os; }"); 158 | if (returnType.getBaseName().equals("String")) { 159 | code.addHeader("string"); 160 | code.add(" template<> std::ostream& operator<<(std::ostream &os, const vector &v) { os << \"{\"; for (vector::const_iterator vi=v.begin(); vi!=v.end(); ++vi) { if (vi != v.begin()) os << \",\"; os << \" \\\"\" << *vi << \"\\\"\"; } os << \" }\"; return os; }"); 161 | } 162 | code.add(""); 163 | } 164 | } 165 | 166 | void generateVerifyCase(TestCodeGenerationState code) { 167 | DataType returnType = m_problem.getReturnType(); 168 | String typeName = returnType.getDescriptor(m_lang); 169 | 170 | code.addHeader("cstdio"); 171 | code.addHeader("ctime"); 172 | code.addHeader("iostream"); 173 | code.addHeader("string"); 174 | code.addHeader("vector"); 175 | code.add(" int verify_case(int casenum, const " + typeName + " &expected, const " + typeName + " &received, std::clock_t elapsed) { "); 176 | code.add(" std::cerr << \"Example \" << casenum << \"... \"; "); 177 | code.add(" "); 178 | code.add(" string verdict;"); 179 | code.add(" vector info;"); 180 | code.add(" char buf[100];"); 181 | code.add(" "); 182 | code.add(" if (elapsed > CLOCKS_PER_SEC / 200) {"); 183 | code.add(" std::sprintf(buf, \"time %.2fs\", elapsed * (1.0/CLOCKS_PER_SEC));"); 184 | code.add(" info.push_back(buf);"); 185 | code.add(" }"); 186 | code.add(" "); 187 | 188 | // Print "PASSED" or "FAILED" based on the result 189 | if (returnType.getBaseName().equals("double")) { 190 | code.add(" if (topcoder_fequ(expected, received)) {"); 191 | code.add(" verdict = \"PASSED\";"); 192 | code.add(" double rerr = moj_relative_error(expected, received); "); 193 | code.add(" if (rerr > 0) {"); 194 | code.add(" std::sprintf(buf, \"relative error %.3e\", rerr);"); 195 | code.add(" info.push_back(buf);"); 196 | code.add(" }"); 197 | } else { 198 | code.add(" if (expected == received) {"); 199 | code.add(" verdict = \"PASSED\";"); 200 | } 201 | code.add(" } else {"); 202 | code.add(" verdict = \"FAILED\";"); 203 | code.add(" }"); 204 | code.add(" "); 205 | code.add(" std::cerr << verdict;"); 206 | code.add(" if (!info.empty()) {"); 207 | code.add(" std::cerr << \" (\";"); 208 | code.add(" for (size_t i=0; i 0) std::cerr << \", \";"); 210 | code.add(" std::cerr << info[i];"); 211 | code.add(" }"); 212 | code.add(" std::cerr << \")\";"); 213 | code.add(" }"); 214 | code.add(" std::cerr << std::endl;"); 215 | code.add(" "); 216 | 217 | code.add(" if (verdict == \"FAILED\") {"); 218 | if (returnType.getBaseName().equals("String") && returnType.getDimension() == 0) { 219 | code.add(" std::cerr << \" Expected: \\\"\" << expected << \"\\\"\" << std::endl; "); 220 | code.add(" std::cerr << \" Received: \\\"\" << received << \"\\\"\" << std::endl; "); 221 | } else { 222 | code.add(" std::cerr << \" Expected: \" << expected << std::endl; "); 223 | code.add(" std::cerr << \" Received: \" << received << std::endl; "); 224 | } 225 | code.add(" }"); 226 | code.add(" "); 227 | code.add(" return verdict == \"PASSED\";"); 228 | code.add(" }"); 229 | code.add(""); 230 | } 231 | 232 | static boolean representsEmptyArray(String s) { 233 | return s.replaceAll("\\s+", "").equals("{}"); 234 | } 235 | 236 | void generateParameter(TestCodeGenerationState code, DataType paramType, String name, String contents, boolean isPlaceholder) { 237 | if (isPlaceholder) { 238 | contents = ""; 239 | } 240 | 241 | String baseName = paramType.getBaseName(); 242 | boolean isLong = baseName.equals("long"); 243 | String typeName = ""; 244 | if (paramType.getDimension() == 0) { 245 | // Scalar 246 | typeName = paramType.getDescriptor(m_lang) + " " + name; 247 | if (isLong) { 248 | contents = ConstantFormatting.formatLongForCPP(contents); 249 | } 250 | } else { 251 | typeName = (isLong ? "long long" : baseName.toLowerCase()) + " " + name + "[]"; 252 | 253 | if (!isPlaceholder) { 254 | if (m_targetCompiler.equals(Preferences.TARGETCOMPILER_VC) && 255 | representsEmptyArray(contents)) { 256 | typeName = "// " + typeName; 257 | contents = "empty, commented out for VC++"; 258 | } else if (isLong) { 259 | // Vector of longs, add LL to constants 260 | contents = ConstantFormatting.formatLongArrayForCPP(contents); 261 | } 262 | } 263 | } 264 | 265 | while (typeName.length() < 25) { 266 | typeName = typeName + " "; 267 | } 268 | 269 | if (!baseName.equals("String")) { 270 | // Compress spaces in non-strings 271 | contents = contents.replaceAll("\\s+", " "); 272 | } 273 | 274 | code.add(" " + typeName + " = " + contents + ";"); 275 | } 276 | 277 | String vectorize(DataType type, String name, String contents, boolean isPlaceholder) { 278 | if (type.getDimension() == 0) { 279 | return name; 280 | } else { 281 | if (!isPlaceholder && 282 | m_targetCompiler.equals(Preferences.TARGETCOMPILER_VC) && 283 | representsEmptyArray(contents)) { 284 | // Visual C++ empty array hack 285 | return type.getDescriptor(m_lang) + "()"; 286 | } 287 | 288 | return type.getDescriptor(m_lang) + "(" + name + ", " + name + " + (sizeof " + name + " / sizeof " + name + "[0]))"; 289 | } 290 | } 291 | 292 | void generateTestCase(TestCodeGenerationState code, int index, TestCase testCase, boolean isPlaceholder) { 293 | DataType[] paramTypes = m_problem.getParamTypes(); 294 | String[] paramNames = m_problem.getParamNames(); 295 | DataType returnType = m_problem.getReturnType(); 296 | 297 | String[] inputs = testCase.getInput(); 298 | String output = testCase.getOutput(); 299 | 300 | /* 301 | * Generate code for setting up individual test cases 302 | * and calling the method with these parameters. 303 | */ 304 | // Generate each input variable separately 305 | for (int i = 0; i < inputs.length; ++i) { 306 | generateParameter(code, paramTypes[i], paramNames[i], inputs[i], isPlaceholder); 307 | } 308 | 309 | // Generate the output variable as the last variable 310 | generateParameter(code, returnType, "expected__", output, isPlaceholder); 311 | 312 | code.add(""); 313 | code.add(" std::clock_t start__ = std::clock();"); 314 | 315 | // Generate the function call 316 | StringBuffer call = new StringBuffer(); 317 | call.append(returnType.getDescriptor(m_lang) + " received__"); 318 | while (call.length() < 25) { 319 | call.append(' '); 320 | } 321 | call.append(" = " + m_problem.getClassName() + "()." + m_problem.getMethodName() + "("); 322 | for (int i = 0; i < inputs.length; ++i) { 323 | call.append(vectorize(paramTypes[i], paramNames[i], inputs[i], isPlaceholder)); 324 | if (i < inputs.length-1) { 325 | call.append(", "); 326 | } 327 | } 328 | call.append(");"); 329 | code.add(" " + call); 330 | 331 | code.add(" return verify_case(casenum__, " + vectorize(returnType, "expected__", output, isPlaceholder) + ", received__, clock()-start__);"); 332 | } 333 | 334 | void generateRunTestCase(TestCodeGenerationState code) { 335 | TestCase[] testCases = m_problem.getTestCases(); 336 | 337 | code.add(" int run_test_case(int casenum__) {"); 338 | code.add(" switch (casenum__) {"); 339 | // Generate the individual test cases 340 | int totalCases = testCases.length + m_pref.getNumPlaceholders(); 341 | for (int i = 0; i < totalCases; ++i) { 342 | if (i == testCases.length) { 343 | code.add(""); 344 | code.add(" // custom cases"); 345 | code.add(""); 346 | } 347 | code.add((i >= testCases.length ? "/*" : "") + " case " + i + ": {"); 348 | generateTestCase(code, i, testCases[i < testCases.length ? i : 0], i >= testCases.length); 349 | code.add(" }" + (i >= testCases.length ? "*/" : "")); 350 | } 351 | 352 | // next 353 | code.add(" default:"); 354 | code.add(" return -1;"); 355 | code.add(" }"); 356 | code.add(" }"); 357 | } 358 | 359 | public String generateTestCode() { 360 | TestCodeGenerationState code = new TestCodeGenerationState(); 361 | 362 | generateNamespaceStart(code); 363 | generateRunTest(code); 364 | 365 | generateOutputComparison(code); 366 | generateFormatResult(code); 367 | generateVerifyCase(code); 368 | generateRunTestCase(code); 369 | code.add("}"); 370 | 371 | StringBuilder sb = new StringBuilder(); 372 | for (String header : code.headers) { 373 | sb.append("#include <"); 374 | sb.append(header); 375 | sb.append(">\n"); 376 | } 377 | for (String s : code.lines) { 378 | sb.append(s); 379 | sb.append('\n'); 380 | } 381 | String ret = sb.toString(); 382 | ret = Pattern.compile("^ ", Pattern.MULTILINE).matcher(ret).replaceAll("\t\t\t\t\t"); 383 | ret = Pattern.compile("^ " , Pattern.MULTILINE).matcher(ret).replaceAll("\t\t\t\t"); 384 | ret = Pattern.compile("^ " , Pattern.MULTILINE).matcher(ret).replaceAll("\t\t\t"); 385 | ret = Pattern.compile("^ " , Pattern.MULTILINE).matcher(ret).replaceAll("\t\t"); 386 | ret = Pattern.compile("^ " , Pattern.MULTILINE).matcher(ret).replaceAll("\t"); 387 | return ret; 388 | } 389 | } 390 | -------------------------------------------------------------------------------- /src/moj/Common.java: -------------------------------------------------------------------------------- 1 | package moj; 2 | 3 | import java.awt.*; 4 | import java.awt.event.FocusAdapter; 5 | import java.awt.event.FocusEvent; 6 | 7 | import javax.swing.*; 8 | import javax.swing.border.Border; 9 | import javax.swing.text.JTextComponent; 10 | 11 | class Common { 12 | public static final Color FG_COLOR = Color.white; 13 | public static final Color BG_COLOR = Color.black; 14 | public static final Color WPB_COLOR = Color.decode("0x333333"); 15 | public static final Color TF_COLOR = Color.white; 16 | public static final Color TB_COLOR = Color.black; 17 | public static final Color HF_COLOR = Color.white; 18 | public static final Color HB_COLOR = Color.decode("0x003300"); 19 | public final static Font DEFAULTFONT = new Font("SansSerif", Font.PLAIN, 12); 20 | public final static Box createHorizontalBox(Component[] a) { 21 | return Common.createHorizontalBox(a, true); 22 | } 23 | public final static Box createHorizontalBox(Component[] a, boolean endGlue) { 24 | Box temp = Box.createHorizontalBox(); 25 | if (a.length == 0) 26 | return temp; 27 | // Add all but the last one 28 | for (int x = 0; x < a.length - 1; x++) { 29 | temp.add(a[x]); 30 | temp.add(Box.createHorizontalStrut(5)); 31 | } 32 | // Add the last one 33 | temp.add(a[a.length - 1]); 34 | if (endGlue) 35 | temp.add(Box.createHorizontalGlue()); 36 | return temp; 37 | } 38 | 39 | public final static JTable createJTable() { 40 | JTable table = new JTable(); 41 | table.setBackground(Common.TB_COLOR); 42 | table.setForeground(Common.TF_COLOR); 43 | table.setSelectionBackground(Common.HB_COLOR); 44 | table.setSelectionForeground(Common.HF_COLOR); 45 | table.setShowGrid(false); 46 | return table; 47 | } 48 | public final static JLabel createJLabel(String text) { 49 | return Common.createJLabel(text, DEFAULTFONT); 50 | } 51 | public final static JLabel createJLabel(String text, Font font) { 52 | return Common.createJLabel(text, null, SwingConstants.LEFT, font); 53 | } 54 | public final static JLabel createJLabel(String text, Dimension size) { 55 | return Common.createJLabel(text, size, SwingConstants.LEFT, DEFAULTFONT); 56 | } 57 | public final static JLabel createJLabel( 58 | String text, 59 | Dimension size, 60 | int alignment) { 61 | return Common.createJLabel(text, size, alignment, DEFAULTFONT); 62 | } 63 | public final static JLabel createJLabel( 64 | String text, 65 | Dimension size, 66 | int alignment, 67 | Font font) { 68 | JLabel temp = new JLabel(text); 69 | temp.setForeground(Common.FG_COLOR); 70 | temp.setBackground(WPB_COLOR); 71 | temp.setFont(font); 72 | temp.setHorizontalAlignment(alignment); 73 | if (size != null) { 74 | temp.setMinimumSize(size); 75 | temp.setPreferredSize(size); 76 | temp.setMaximumSize(size); 77 | } 78 | return temp; 79 | } 80 | public final static JTextField createJTextField(int size, Dimension max) { 81 | return Common.createJTextField(size, max, DEFAULTFONT); 82 | } 83 | public final static JTextField createJTextField( 84 | int size, 85 | Dimension max, 86 | Font font) { 87 | JTextField temp = new JTextField(size); 88 | temp.setForeground(FG_COLOR); 89 | temp.setBackground(BG_COLOR); 90 | temp.setCaretColor(FG_COLOR); 91 | temp.setFont(font); 92 | temp.setBorder(BorderFactory.createLineBorder(FG_COLOR, 1)); 93 | temp.setMaximumSize(max); 94 | temp.addFocusListener(new Common.SelectAll(temp)); 95 | return temp; 96 | } 97 | public final static JScrollPane createJScrollPane(Component a) { 98 | return Common.createJScrollPane(a, null, null); 99 | } 100 | 101 | public final static JScrollPane createJScrollPane(Component a, Dimension size) { 102 | return Common.createJScrollPane(a, size, null); 103 | } 104 | 105 | public final static JScrollPane createJScrollPane(Component a, Dimension size, Border border) { 106 | 107 | JScrollPane temp = new JScrollPane(a); 108 | temp.setBackground(WPB_COLOR); 109 | temp.getViewport().setBackground(WPB_COLOR); 110 | if (size!=null) temp.getViewport().setPreferredSize(size); 111 | if (border!=null) temp.setBorder(border); 112 | 113 | return temp; 114 | } 115 | 116 | public final static void setDefaultAttributes(Container panel) { 117 | Common.setDefaultAttributes(panel, new BorderLayout()); 118 | } 119 | public final static void setDefaultAttributes( 120 | Container panel, 121 | LayoutManager layout) { 122 | panel.setLayout(layout); 123 | panel.setBackground(WPB_COLOR); 124 | } 125 | private static class SelectAll extends FocusAdapter { 126 | JTextComponent parent; 127 | public SelectAll(JTextComponent parent) { 128 | this.parent = parent; 129 | } 130 | public void focusGained(FocusEvent e) { 131 | parent.selectAll(); 132 | } 133 | } 134 | public final static JButton createJButton(String text) { 135 | return Common.createJButton(text, null, DEFAULTFONT); 136 | } 137 | public final static JButton createJButton(String text, Dimension size) { 138 | return Common.createJButton(text, size, DEFAULTFONT); 139 | } 140 | public final static JButton createJButton(String text, Font font) { 141 | return Common.createJButton(text, null, font); 142 | } 143 | public final static JButton createJButton( 144 | String text, 145 | Dimension size, 146 | Font font) { 147 | JButton temp = new JButton(text); 148 | temp.setFont(font); 149 | if (size != null) { 150 | temp.setMinimumSize(size); 151 | temp.setPreferredSize(size); 152 | temp.setMaximumSize(size); 153 | } 154 | return temp; 155 | } 156 | public static void showMessage(String title, String msg, Component comp) { 157 | JOptionPane.showMessageDialog( 158 | comp, 159 | msg, 160 | title, 161 | JOptionPane.INFORMATION_MESSAGE); 162 | } 163 | public static void showError(String title, String msg, Component comp) { 164 | JOptionPane.showMessageDialog( 165 | comp, 166 | msg, 167 | title, 168 | JOptionPane.INFORMATION_MESSAGE); 169 | } 170 | public static boolean confirm(String title, String msg, Component comp) { 171 | int choice = 172 | JOptionPane.showConfirmDialog( 173 | comp, 174 | msg, 175 | title, 176 | JOptionPane.YES_NO_OPTION, 177 | JOptionPane.WARNING_MESSAGE); 178 | if (choice == JOptionPane.YES_OPTION) { 179 | return (true); 180 | } 181 | return (false); 182 | } 183 | public static String input(String title, String msg, Component comp) { 184 | String value = 185 | JOptionPane.showInputDialog(comp, msg, title, JOptionPane.QUESTION_MESSAGE); 186 | return (value); 187 | } 188 | } 189 | /* @(#)Common.java */ -------------------------------------------------------------------------------- /src/moj/ConfigurationDialog.java: -------------------------------------------------------------------------------- 1 | package moj; 2 | 3 | import java.awt.*; 4 | import java.awt.event.*; 5 | import java.io.IOException; 6 | import java.util.Enumeration; 7 | 8 | import javax.swing.*; 9 | 10 | class ConfigurationDialog extends JDialog implements ActionListener { 11 | 12 | private static final long serialVersionUID = 6205878572134421087L; 13 | 14 | private Preferences pref; 15 | 16 | private ButtonGroup compilerButtonGroup = new ButtonGroup(); 17 | private JRadioButton gcc11RadioButton = new JRadioButton("GCC -std=c++11"); 18 | private JRadioButton gcc98RadioButton = new JRadioButton("Older GCC"); 19 | private JRadioButton vcRadioButton = new JRadioButton("Visual C++"); 20 | 21 | private JTextField placeholdersTextField = new JTextField(); 22 | 23 | private JCheckBox switchCheckBox = new JCheckBox(); 24 | private JCheckBox javaSupportCheckBox = new JCheckBox(); 25 | 26 | private JButton saveButton = new JButton("Save"); 27 | private JButton closeButton = new JButton("Close"); 28 | 29 | private WindowHandler windowHandler = new WindowHandler(); 30 | 31 | public ConfigurationDialog(Preferences pref) { 32 | 33 | super((JFrame)null, "moj configuration", true); 34 | 35 | this.pref = pref; 36 | setSize(new Dimension(600, 400)); 37 | 38 | // Configure the content pane 39 | Container contentPane = getContentPane(); 40 | contentPane.setLayout(new GridBagLayout()); 41 | contentPane.setForeground(Common.FG_COLOR); 42 | contentPane.setBackground(Common.WPB_COLOR); 43 | 44 | // Target compiler 45 | JLabel compilerLabel = new JLabel("Target compiler:"); 46 | compilerLabel.setForeground(Common.FG_COLOR); 47 | compilerLabel.setBackground(Common.WPB_COLOR); 48 | compilerLabel.setToolTipText("Select the compiler you will be using. moj needs to make adjustments to the testing code for it to compile under Visual C++."); 49 | 50 | compilerButtonGroup.add(gcc11RadioButton); 51 | compilerButtonGroup.add(gcc98RadioButton); 52 | compilerButtonGroup.add(vcRadioButton); 53 | 54 | String current_compiler = pref.getTargetCompiler(); 55 | if (current_compiler.equals(Preferences.TARGETCOMPILER_GCC11)) { 56 | gcc11RadioButton.setSelected(true); 57 | } else if (current_compiler.equals(Preferences.TARGETCOMPILER_GCC98)) { 58 | gcc98RadioButton.setSelected(true); 59 | } else { 60 | vcRadioButton.setSelected(true); 61 | } 62 | 63 | for (Enumeration eRadio=compilerButtonGroup.getElements(); eRadio.hasMoreElements(); ) { 64 | //Iterating over the Radio Buttons 65 | JRadioButton button = (JRadioButton)eRadio.nextElement(); 66 | button.setForeground(Common.FG_COLOR); 67 | button.setBackground(Common.WPB_COLOR); 68 | button.setText("" + button.getText() + ""); 69 | } 70 | 71 | // Test case placeholders 72 | JLabel placeholdersLabel = new JLabel("Test case placeholders:"); 73 | placeholdersLabel.setForeground(Common.FG_COLOR); 74 | placeholdersLabel.setBackground(Common.WPB_COLOR); 75 | placeholdersLabel.setToolTipText("Set the number of empty test case placeholders to be generated. You can use these to enter your own test cases while solving the problem."); 76 | placeholdersTextField.setText("" + pref.getNumPlaceholders()); 77 | 78 | // Language-switch workaround checkbox 79 | switchCheckBox.setText("Enable workaround for FileEdit language switching issue"); 80 | switchCheckBox.setForeground(Common.FG_COLOR); 81 | switchCheckBox.setBackground(Common.WPB_COLOR); 82 | switchCheckBox.setToolTipText("If checked, moj will try to allow you to switch between languages mid-contest."); 83 | switchCheckBox.setSelected(pref.getLanguageSwitchWorkaround()); 84 | 85 | // Java support checkbox 86 | javaSupportCheckBox.setText("Enable Java test code generation"); 87 | javaSupportCheckBox.setForeground(Common.FG_COLOR); 88 | javaSupportCheckBox.setBackground(Common.WPB_COLOR); 89 | javaSupportCheckBox.setToolTipText("Uncheck if you want to use a different plug-in to generate Java test code."); 90 | javaSupportCheckBox.setSelected(pref.getEnableJavaSupport()); 91 | 92 | contentPane.add(compilerLabel, new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(10,10,4,4),0,0)); 93 | contentPane.add(gcc11RadioButton, new GridBagConstraints(1,0,1,1,1,1,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(10,10,4,4),0,0)); 94 | contentPane.add(gcc98RadioButton, new GridBagConstraints(1,1,1,1,1,1,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(10,10,4,4),0,0)); 95 | contentPane.add(vcRadioButton, new GridBagConstraints(1,2,1,1,1,1,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(10,10,4,4),0,0)); 96 | contentPane.add(placeholdersLabel, new GridBagConstraints(0,3,1,1,1,1,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(10,10,4,4),0,0)); 97 | contentPane.add(placeholdersTextField, new GridBagConstraints(1,3,1,1,1,1,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(10,10,4,4),0,0)); 98 | contentPane.add(switchCheckBox, new GridBagConstraints(0,4,3,1,1,1,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(10,10,4,4),0,0)); 99 | contentPane.add(javaSupportCheckBox, new GridBagConstraints(0,5,3,1,1,1,GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(10,10,4,4),0,0)); 100 | contentPane.add(saveButton, new GridBagConstraints(1,6,1,1,0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10,10,10,10),0,0)); 101 | contentPane.add(closeButton, new GridBagConstraints(2,6,1,1,0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10,0,10,10),0,0)); 102 | 103 | // Add listeners 104 | saveButton.addActionListener(this); 105 | closeButton.addActionListener(this); 106 | 107 | // Set the close operations 108 | setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); 109 | addWindowListener(windowHandler); 110 | 111 | this.pack(); 112 | } 113 | 114 | public void actionPerformed(ActionEvent e) { 115 | Object src = e.getSource(); 116 | if (src == saveButton) { 117 | save(); 118 | } else if (src == closeButton) { 119 | windowHandler.windowClosing(new WindowEvent(this, WindowEvent.WINDOW_CLOSING)); 120 | } 121 | } 122 | 123 | private String getSelectedCompiler() { 124 | return 125 | gcc11RadioButton.isSelected() ? Preferences.TARGETCOMPILER_GCC11 : 126 | gcc98RadioButton.isSelected() ? Preferences.TARGETCOMPILER_GCC98 : 127 | Preferences.TARGETCOMPILER_VC; 128 | } 129 | 130 | public boolean save() { 131 | // Parse 132 | int numPlaceholders; 133 | try { 134 | numPlaceholders = Integer.valueOf(placeholdersTextField.getText()); 135 | } catch(NumberFormatException e) { 136 | Common.showError("Parse error", "\"" + placeholdersTextField.getText() + "\" is not a valid integer.", null); 137 | return false; 138 | } 139 | 140 | if (numPlaceholders < 0 || numPlaceholders > 50) { 141 | Common.showError("Parse error", "The number of placeholders must be between 0 and 50.", null); 142 | return false; 143 | } 144 | 145 | // Write out the preferences 146 | try { 147 | pref.setTargetCompiler(getSelectedCompiler()); 148 | pref.setNumPlaceholders(numPlaceholders); 149 | pref.save(); 150 | Common.showMessage("Save", "Preferences were saved successfully", null); 151 | return true; 152 | } catch (IOException e) { 153 | Common.showError("Error saving preferences", e.toString(), null); 154 | return false; 155 | } 156 | 157 | } 158 | 159 | private class WindowHandler extends WindowAdapter { 160 | public void windowClosing(WindowEvent e) { 161 | 162 | // Find out if anything has save's pending 163 | boolean savePending=false; 164 | 165 | savePending = 166 | !getSelectedCompiler().equals(pref.getTargetCompiler()) 167 | || !placeholdersTextField.getText().equals("" + pref.getNumPlaceholders()) 168 | || switchCheckBox.isSelected() != pref.getLanguageSwitchWorkaround() 169 | || javaSupportCheckBox.isSelected() != pref.getEnableJavaSupport(); 170 | 171 | // If so... 172 | if (savePending) { 173 | 174 | // Should we save? 175 | if (Common.confirm("Save Pending", "Changes are pending. Do you want to save before closing?", null)) { 176 | // Try to save 177 | if (!save()) return; 178 | } 179 | } 180 | // Close the window 181 | dispose(); 182 | } 183 | } 184 | 185 | public static void main(String[] args) { 186 | new ConfigurationDialog(null).setVisible(true); 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /src/moj/ConstantFormatting.java: -------------------------------------------------------------------------------- 1 | package moj; 2 | 3 | class ConstantFormatting { 4 | public static String formatLongForCPP(String str) { 5 | return formatSingleLong(str, "LL"); 6 | } 7 | 8 | public static String formatLongArrayForCPP(String str) { 9 | return formatLongArray(str, "LL"); 10 | } 11 | 12 | public static String formatLongForJava(String str) { 13 | return formatSingleLong(str, "L"); 14 | } 15 | 16 | public static String formatLongArrayForJava(String str) { 17 | return formatLongArray(str, "L"); 18 | } 19 | 20 | private static String formatSingleLong(String str, String suffix) { 21 | if (str.trim().equals("")) { 22 | return ""; 23 | } 24 | long value = Long.valueOf(str); 25 | if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) { 26 | str += suffix; 27 | } 28 | return str; 29 | } 30 | 31 | private static String formatLongArray(String str, String suffix) { 32 | // Vector of longs, add LL to constants 33 | String[] tokens = str.split("[^0-9-]"); 34 | StringBuffer fixed = new StringBuffer(); 35 | boolean first = true; 36 | for (String token : tokens) { 37 | if (token.isEmpty()) { 38 | continue; 39 | } 40 | if (!first) { 41 | fixed.append(", "); 42 | } 43 | first = false; 44 | fixed.append(formatSingleLong(token, suffix)); 45 | } 46 | return "{" + fixed.toString() + "}"; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/moj/HarnessGenerator.java: -------------------------------------------------------------------------------- 1 | package moj; 2 | 3 | public interface HarnessGenerator { 4 | String generateTestCode(); 5 | String generateDefaultMain(); 6 | String generateRunTest(); 7 | } 8 | -------------------------------------------------------------------------------- /src/moj/JavaHarnessGenerator.java: -------------------------------------------------------------------------------- 1 | package moj; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.regex.Pattern; 7 | 8 | import com.topcoder.client.contestant.ProblemComponentModel; 9 | import com.topcoder.shared.language.Language; 10 | import com.topcoder.shared.problem.*; 11 | 12 | public class JavaHarnessGenerator implements HarnessGenerator { 13 | final ProblemComponentModel m_problem; 14 | final Language m_lang; 15 | final Preferences m_pref; 16 | 17 | public JavaHarnessGenerator(ProblemComponentModel problem, Language lang, Preferences pref) { 18 | m_problem = problem; 19 | m_lang = lang; 20 | m_pref = pref; 21 | } 22 | 23 | public String generateDefaultMain() { 24 | return 25 | "public static void main(String[] args) {\n" + 26 | "\t\tif (args.length == 0) {\n" + 27 | "\t\t\t" + m_problem.getClassName() + "Harness.run_test(-1);\n" + 28 | "\t\t} else {\n" + 29 | "\t\t\tfor (int i=0; i code) { 40 | code.add("class " + m_problem.getClassName() + "Harness {"); 41 | } 42 | 43 | void generateRunTest(ArrayList code) { 44 | code.add(" public static void run_test(int casenum) {"); 45 | 46 | code.add(" if (casenum != -1) {"); 47 | code.add(" if (runTestCase(casenum) == -1)"); 48 | code.add(" System.err.println(\"Illegal input! Test case \" + casenum + \" does not exist.\");"); 49 | code.add(" return;"); 50 | code.add(" }"); 51 | code.add(" "); 52 | code.add(" int correct = 0, total = 0;"); 53 | code.add(" for (int i=0;; ++i) {"); 54 | code.add(" int x = runTestCase(i);"); 55 | code.add(" if (x == -1) {"); 56 | code.add(" if (i >= 100) break;"); 57 | code.add(" continue;"); 58 | code.add(" }"); 59 | code.add(" correct += x;"); 60 | code.add(" ++total;"); 61 | code.add(" }"); 62 | code.add(" "); 63 | code.add(" if (total == 0) {"); 64 | code.add(" System.err.println(\"No test cases run.\");"); 65 | code.add(" } else if (correct < total) {"); 66 | code.add(" System.err.println(\"Some cases FAILED (passed \" + correct + \" of \" + total + \").\");"); 67 | code.add(" } else {"); 68 | code.add(" System.err.println(\"All \" + total + \" tests passed!\");"); 69 | code.add(" }"); 70 | code.add(" }"); 71 | code.add(" "); 72 | } 73 | 74 | void generateOutputComparison(ArrayList code) { 75 | DataType returnType = m_problem.getReturnType(); 76 | if (returnType.getBaseName().equals("double")) { 77 | code.add(" static final double MAX_DOUBLE_ERROR = 1E-9;"); 78 | code.add(" static boolean compareOutput(double expected, double result){ if(Double.isNaN(expected)){ return Double.isNaN(result); }else if(Double.isInfinite(expected)){ if(expected > 0){ return result > 0 && Double.isInfinite(result); }else{ return result < 0 && Double.isInfinite(result); } }else if(Double.isNaN(result) || Double.isInfinite(result)){ return false; }else if(Math.abs(result - expected) < MAX_DOUBLE_ERROR){ return true; }else{ double min = Math.min(expected * (1.0 - MAX_DOUBLE_ERROR), expected * (1.0 + MAX_DOUBLE_ERROR)); double max = Math.max(expected * (1.0 - MAX_DOUBLE_ERROR), expected * (1.0 + MAX_DOUBLE_ERROR)); return result > min && result < max; } }"); 79 | code.add(" static double relativeError(double expected, double result) { if (Double.isNaN(expected) || Double.isInfinite(expected) || Double.isNaN(result) || Double.isInfinite(result) || expected == 0) return 0; return Math.abs(result-expected) / Math.abs(expected); }"); 80 | if (returnType.getDimension() > 0) { 81 | code.add(" static boolean compareOutput(double[] expected, double[] result) { if (expected.length != result.length) return false; for (int i=0; i 0) { 87 | code.add(" static boolean compareOutput(String[] expected, String[] result) { if (expected.length != result.length) return false; for (int i=0; i 0) { 94 | code.add(" static boolean compareOutput("+type+"[] expected, "+type+"[] result) { if (expected.length != result.length) return false; for (int i=0; i code) { 102 | DataType returnType = m_problem.getReturnType(); 103 | 104 | Map typeFormatMap = new HashMap(); 105 | typeFormatMap.put("int", "%d"); 106 | typeFormatMap.put("float", "%.10g"); 107 | typeFormatMap.put("char", "'%c'"); 108 | typeFormatMap.put("byte", "%d"); 109 | typeFormatMap.put("short", "%d"); 110 | typeFormatMap.put("long", "%d"); 111 | typeFormatMap.put("double", "%.10g"); 112 | typeFormatMap.put("String", "\\\"%s\\\""); 113 | typeFormatMap.put("boolean", "%b"); 114 | String formatString = typeFormatMap.get(returnType.getBaseName()); 115 | 116 | code.add(" static String formatResult(" + returnType.getDescriptor(m_lang) + " res) {"); 117 | if (returnType.getDimension() > 0) { 118 | code.add(" String ret = \"\";"); 119 | code.add(" ret += \"{\";"); 120 | code.add(" for (int i=0; i 0) ret += \",\";"); 122 | code.add(" ret += String.format(\" " + formatString + "\", res[i]);"); 123 | code.add(" }"); 124 | code.add(" ret += \" }\";"); 125 | code.add(" return ret;"); 126 | } else { 127 | code.add(" return String.format(\"" + formatString + "\", res);"); 128 | } 129 | 130 | code.add(" }"); 131 | code.add(" "); 132 | } 133 | 134 | void generateVerifyCase(ArrayList code) { 135 | DataType returnType = m_problem.getReturnType(); 136 | String typeName = returnType.getDescriptor(m_lang); 137 | 138 | code.add(" static int verifyCase(int casenum, " + typeName + " expected, " + typeName + " received) { "); 139 | code.add(" System.err.print(\"Example \" + casenum + \"... \");"); 140 | 141 | // Print "PASSED" or "FAILED" based on the result 142 | if (returnType.getBaseName().equals("double")) { 143 | code.add(" if (compareOutput(expected, received)) {"); 144 | code.add(" System.err.print(\"PASSED\");"); 145 | code.add(" double rerr = relativeError(expected, received);"); 146 | code.add(" if (rerr > 0) System.err.printf(\" (relative error %g)\", rerr);"); 147 | code.add(" System.err.println();"); 148 | code.add(" return 1;"); 149 | } else { 150 | code.add(" if (compareOutput(expected, received)) {"); 151 | code.add(" System.err.println(\"PASSED\");"); 152 | code.add(" return 1;"); 153 | } 154 | code.add(" } else {"); 155 | code.add(" System.err.println(\"FAILED\");"); 156 | 157 | code.add(" System.err.println(\" Expected: \" + formatResult(expected)); "); 158 | code.add(" System.err.println(\" Received: \" + formatResult(received)); "); 159 | 160 | code.add(" return 0;"); 161 | code.add(" }"); 162 | code.add(" }"); 163 | code.add(""); 164 | } 165 | 166 | void generateParameter(ArrayList code, DataType paramType, String name, String contents, boolean isPlaceholder) { 167 | if (isPlaceholder) 168 | contents = ""; 169 | 170 | String baseName = paramType.getBaseName(); 171 | boolean isLong = baseName.equals("long"); 172 | String typeName = paramType.getDescriptor(m_lang) + " " + name; 173 | if (isLong) { 174 | if (paramType.getDimension() == 0) { 175 | contents = ConstantFormatting.formatLongForJava(contents); 176 | } else { 177 | contents = ConstantFormatting.formatLongArrayForJava(contents); 178 | } 179 | } 180 | 181 | while (typeName.length() < 25) 182 | typeName = typeName + " "; 183 | 184 | if (!baseName.equals("String")) { 185 | // Compress spaces in non-strings 186 | contents = contents.replaceAll("\\s+", " "); 187 | } 188 | 189 | code.add(" " + typeName + " = " + contents + ";"); 190 | } 191 | 192 | void generateTestCase(ArrayList code, int index, TestCase testCase, boolean isPlaceholder) { 193 | DataType[] paramTypes = m_problem.getParamTypes(); 194 | String[] paramNames = m_problem.getParamNames(); 195 | DataType returnType = m_problem.getReturnType(); 196 | 197 | String[] inputs = testCase.getInput(); 198 | String output = testCase.getOutput(); 199 | 200 | /* 201 | * Generate code for setting up individual test cases 202 | * and calling the method with these parameters. 203 | */ 204 | // Generate each input variable separately 205 | for (int i = 0; i < inputs.length; ++i) { 206 | generateParameter(code, paramTypes[i], paramNames[i], inputs[i], isPlaceholder); 207 | } 208 | 209 | // Generate the output variable as the last variable 210 | generateParameter(code, returnType, "expected__", output, isPlaceholder); 211 | 212 | code.add(""); 213 | 214 | StringBuffer line = new StringBuffer(); 215 | line.append(" return verifyCase(casenum__, expected__, new " + m_problem.getClassName() + "()." + m_problem.getMethodName() + "("); 216 | 217 | // Generate the function call list 218 | for (int i = 0; i < inputs.length; ++i) { 219 | line.append(paramNames[i]); 220 | if (i < (inputs.length - 1)) 221 | line.append(", "); 222 | } 223 | 224 | line.append("));"); 225 | code.add(line.toString()); 226 | } 227 | 228 | void generateRunTestCase(ArrayList code) { 229 | TestCase[] testCases = m_problem.getTestCases(); 230 | 231 | code.add(" static int runTestCase(int casenum__) {"); 232 | code.add(" switch(casenum__) {"); 233 | // Generate the individual test cases 234 | for (int i = 0; i < testCases.length+m_pref.getNumPlaceholders(); ++i) { 235 | if (i == testCases.length) { 236 | code.add(""); 237 | code.add(" // custom cases"); 238 | code.add(""); 239 | } 240 | code.add((i >= testCases.length ? "/*" : "") + " case " + i + ": {"); 241 | generateTestCase(code, i, testCases[i < testCases.length ? i : 0], i >= testCases.length); 242 | code.add(" }" + (i >= testCases.length ? "*/" : "")); 243 | } 244 | 245 | // next 246 | code.add(" default:"); 247 | code.add(" return -1;"); 248 | code.add(" }"); 249 | code.add(" }"); 250 | } 251 | 252 | public String generateTestCode() { 253 | ArrayList code = new ArrayList(); 254 | 255 | generateNamespaceStart(code); 256 | generateRunTest(code); 257 | 258 | generateOutputComparison(code); 259 | generateFormatResult(code); 260 | generateVerifyCase(code); 261 | generateRunTestCase(code); 262 | code.add("}"); 263 | 264 | StringBuffer sb = new StringBuffer(); 265 | for (String s : code) { 266 | sb.append(s); 267 | sb.append('\n'); 268 | } 269 | String ret = sb.toString(); 270 | ret = Pattern.compile("^ ", Pattern.MULTILINE).matcher(ret).replaceAll("\t\t\t\t\t"); 271 | ret = Pattern.compile("^ " , Pattern.MULTILINE).matcher(ret).replaceAll("\t\t\t\t"); 272 | ret = Pattern.compile("^ " , Pattern.MULTILINE).matcher(ret).replaceAll("\t\t\t"); 273 | ret = Pattern.compile("^ " , Pattern.MULTILINE).matcher(ret).replaceAll("\t\t"); 274 | ret = Pattern.compile("^ " , Pattern.MULTILINE).matcher(ret).replaceAll("\t"); 275 | return ret; 276 | } 277 | } 278 | 279 | -------------------------------------------------------------------------------- /src/moj/LanguageAutoDetection.java: -------------------------------------------------------------------------------- 1 | package moj; 2 | 3 | import java.util.*; 4 | import java.util.regex.Pattern; 5 | 6 | public class LanguageAutoDetection { 7 | final static String[] CPLUSPLUS_MARKERS = { 8 | "#\\s*include", "#\\s*define", 9 | "private:", "public:", "protected:", 10 | "struct\\s", 11 | "using\\s+namespace", 12 | "template\\s*<", 13 | "inline\\s*", 14 | "vector\\s*<", 15 | "::", 16 | }; 17 | final static String[] JAVA_MARKERS = { 18 | "import\\s+java\\.", 19 | "public \\w", 20 | "String\\s*\\[\\]", "int\\s*\\[\\]", "long\\s*\\[\\]", 21 | "HashMap", "TreeMap" 22 | }; 23 | final static String[] CSHARP_MARKERS = { 24 | "using\\s+System", 25 | "string\\s*\\[\\]", 26 | "\\[,\\]", "\\[,,\\]", "\\[,,,\\]", "\\[,,,,\\]", 27 | }; 28 | 29 | 30 | static String filterComments(String source) { 31 | StringBuilder sb = new StringBuilder(); 32 | for (int i=0; i markers = new TreeMap(); 58 | 59 | markers.put("C++", CPLUSPLUS_MARKERS); 60 | markers.put("Java", JAVA_MARKERS); 61 | markers.put("C#", CSHARP_MARKERS); 62 | 63 | System.err.printf("moj language auto detection:"); 64 | 65 | int best = 0; 66 | String ret = "C++"; 67 | boolean first = true; 68 | 69 | for (String language : markers.keySet()) { 70 | int matched = 0, total = 0; 71 | 72 | for (String m : markers.get(language)) { 73 | if (Pattern.compile(m, Pattern.MULTILINE).matcher(source).find()) 74 | ++matched; 75 | ++total; 76 | } 77 | 78 | if (matched > best || 79 | matched == best && language.equals(candidate)) { 80 | best = matched; 81 | ret = language; 82 | } 83 | 84 | if (!first) System.err.printf(","); 85 | first = false; 86 | System.err.printf(" %s %d markers", language, matched); 87 | } 88 | 89 | System.err.printf("\n"); 90 | 91 | return ret.equals(candidate); 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/moj/Preferences.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Preferences.java 3 | * 4 | * Description: Preferences class for FileEdit 5 | * @author Tim "Pops" Roberts 6 | * @version 3.0 7 | */ 8 | 9 | package moj; 10 | import com.topcoder.client.contestApplet.common.LocalPreferences; 11 | 12 | public class Preferences { 13 | 14 | private static LocalPreferences pref = LocalPreferences.getInstance(); 15 | 16 | public final static String KEY_TARGETCOMPILER = "moj.config.targetcompiler"; 17 | public final static String KEY_NUMPLACEHOLDERS = "moj.config.numplaceholders"; 18 | public final static String KEY_LANGUAGESWITCHWORKAROUND = "moj.config.languageswitchworkaround"; 19 | public final static String KEY_ENABLEJAVASUPPORT = "moj.config.enablejavasupport"; 20 | 21 | public final static String TARGETCOMPILER_GCC11 = "GCC -std=c++11"; 22 | public final static String TARGETCOMPILER_GCC98 = "GCC (deprecated)"; 23 | public final static String TARGETCOMPILER_VC = "Visual C++"; 24 | public final static String TARGETCOMPILER_DEFAULT = TARGETCOMPILER_GCC11; 25 | 26 | public Preferences() { 27 | } 28 | 29 | public String getTargetCompiler() { 30 | String compiler = getStringProperty(KEY_TARGETCOMPILER, TARGETCOMPILER_DEFAULT); 31 | if (!compiler.equals(TARGETCOMPILER_GCC11) && 32 | !compiler.equals(TARGETCOMPILER_GCC98) && 33 | !compiler.equals(TARGETCOMPILER_VC)) { 34 | // Force any no-longer-supported settings to the current default 35 | compiler = TARGETCOMPILER_DEFAULT; 36 | } 37 | return compiler; 38 | } 39 | 40 | public void setTargetCompiler(String compiler) { 41 | pref.setProperty(KEY_TARGETCOMPILER, compiler); 42 | } 43 | 44 | public int getNumPlaceholders() { 45 | return getIntegerProperty(KEY_NUMPLACEHOLDERS, 3); 46 | } 47 | 48 | public void setNumPlaceholders(int numPlaceholders) { 49 | pref.setProperty(KEY_NUMPLACEHOLDERS, "" + numPlaceholders); 50 | } 51 | 52 | public boolean getEnableJavaSupport() { 53 | return getBooleanProperty(KEY_ENABLEJAVASUPPORT, true); 54 | } 55 | 56 | public void setEnableJavaSupport(boolean enabled) { 57 | pref.setProperty(KEY_ENABLEJAVASUPPORT, enabled ? "true" : "false"); 58 | } 59 | 60 | public boolean getLanguageSwitchWorkaround() { 61 | return getBooleanProperty(KEY_LANGUAGESWITCHWORKAROUND, true); 62 | } 63 | 64 | public void setLanguageSwitchWorkaround(boolean enabled) { 65 | pref.setProperty(KEY_LANGUAGESWITCHWORKAROUND, enabled ? "true" : "false"); 66 | } 67 | 68 | protected String getStringProperty(String key, String defaultValue) { 69 | String value = pref.getProperty(key); 70 | return value==null || value.equals("") ? defaultValue : value; 71 | } 72 | 73 | protected boolean getBooleanProperty(String key, boolean defaultValue) { 74 | String value = pref.getProperty(key); 75 | return value==null || value.equals("") ? defaultValue : value.equals("true"); 76 | } 77 | 78 | protected int getIntegerProperty(String key, int defaultValue) { 79 | String value = pref.getProperty(key); 80 | if(value==null || value.equals("")) return defaultValue; 81 | 82 | try { 83 | return Integer.parseInt(value); 84 | } catch (NumberFormatException e) { 85 | return defaultValue; 86 | } 87 | } 88 | 89 | public void save() throws java.io.IOException { 90 | pref.savePreferences(); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/moj/moj.java: -------------------------------------------------------------------------------- 1 | package moj; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.topcoder.client.contestant.ProblemComponentModel; 7 | import com.topcoder.shared.language.Language; 8 | import com.topcoder.shared.problem.*; 9 | 10 | public class moj { 11 | // Map used to store my tags 12 | private Map m_Tags = new HashMap(); 13 | 14 | // Constants 15 | private static final String k_TESTCODE = "$TESTCODE$"; 16 | private static final String k_DEFAULTMAIN = "$DEFAULTMAIN$"; 17 | private static final String k_RUNTEST = "$RUNTEST$"; 18 | private static final String k_VERSION = "\n// Powered by moj 4.18 [modified TZTester]"; 19 | 20 | // Preferences 21 | private Preferences pref = new Preferences(); 22 | 23 | public String preProcess(String source, ProblemComponentModel problem, Language lang, Renderer renderer) { 24 | // Set defaults for the tags in case we exit out early 25 | m_Tags.put(k_TESTCODE, ""); 26 | m_Tags.put(k_RUNTEST, ""); 27 | m_Tags.put(k_DEFAULTMAIN, ""); 28 | 29 | // If there is source and the language matches that in the actual code, return it 30 | if (source.length() > 0 && 31 | (!pref.getLanguageSwitchWorkaround() || LanguageAutoDetection.isMostLikely(source, lang.getName()))) { 32 | return source; 33 | } 34 | 35 | // See if we are needed at all and select the appropriate generator 36 | HarnessGenerator generator = null; 37 | if (lang.getName().equals("C++")) { 38 | generator = new CPPHarnessGenerator(problem, lang, pref); 39 | } else if (lang.getName().equals("Java")) { 40 | if (!pref.getEnableJavaSupport()) return ""; 41 | generator = new JavaHarnessGenerator(problem, lang, pref); 42 | } else { 43 | return ""; 44 | } 45 | 46 | // Re-initialize the tags 47 | m_Tags.clear(); 48 | 49 | // Get the test cases 50 | TestCase[] testCases = problem.getTestCases(); 51 | 52 | // Check to see if test cases are defined 53 | if ((testCases == null) || (testCases.length == 0)) { 54 | m_Tags.put(k_TESTCODE, "// *** moj WARNING *** No test cases defined for this problem"); 55 | return ""; 56 | } 57 | 58 | m_Tags.put(k_TESTCODE, generator.generateTestCode()); 59 | m_Tags.put(k_DEFAULTMAIN, generator.generateDefaultMain()); 60 | m_Tags.put(k_RUNTEST, generator.generateRunTest()); 61 | return ""; 62 | } 63 | 64 | public String postProcess(String source, Language lang) { 65 | return source + k_VERSION; 66 | } 67 | 68 | public Map getUserDefinedTags() { 69 | return m_Tags; 70 | } 71 | 72 | public void configure() { 73 | new ConfigurationDialog(pref).setVisible(true); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /test/moj/CPPParameterTest.java: -------------------------------------------------------------------------------- 1 | package moj; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import moj.CPPHarnessGenerator.TestCodeGenerationState; 9 | import moj.mocks.*; 10 | 11 | import org.junit.*; 12 | import org.junit.runner.RunWith; 13 | import org.junit.runners.Parameterized; 14 | import org.junit.runners.Parameterized.Parameters; 15 | 16 | import com.topcoder.shared.language.CPPLanguage; 17 | import com.topcoder.shared.problem.DataType; 18 | import com.topcoder.shared.problem.InvalidTypeException; 19 | 20 | @RunWith(Parameterized.class) 21 | public class CPPParameterTest { 22 | private String typename, value, expected; 23 | 24 | public CPPParameterTest(String typename, String varval, String expected) { 25 | this.typename = typename; 26 | this.value = varval; 27 | this.expected = expected; 28 | } 29 | 30 | CPPHarnessGenerator generator; 31 | TestCodeGenerationState code; 32 | 33 | @Before public void setUp() { 34 | generator = new CPPHarnessGenerator( 35 | new ProblemComponentModelMock(), 36 | CPPLanguage.CPP_LANGUAGE, 37 | new PreferencesMock() 38 | ); 39 | code = new TestCodeGenerationState(); 40 | } 41 | 42 | static String compressSpaceBeforeEquals(String str) { 43 | return str.replaceFirst("\\s*=", " =").trim(); 44 | } 45 | 46 | @Parameters 47 | public static List data() { 48 | Object[][] data = new Object[][] { 49 | {"int", "-2147483648", "int var = -2147483648;"}, 50 | 51 | {"String", "\"test string\"", "string var = \"test string\";"}, 52 | {"String", "\" multiple spaces \"", "string var = \" multiple spaces \";"}, 53 | {"String", "\" a = 3 \"", "string var = \" a = 3 \";"}, 54 | 55 | {"double", "1.345e08", "double var = 1.345e08;"}, 56 | 57 | {"long", "123", "long long var = 123;"}, 58 | {"long", "-9999999999", "long long var = -9999999999LL;"}, 59 | {"long", "2147483648", "long long var = 2147483648LL;"}, 60 | 61 | {"int[]", "{-2147483648, 2147483647, 0, -1, 555}", "int var[] = {-2147483648, 2147483647, 0, -1, 555};"}, 62 | {"int[]", "{}", "int var[] = {};"}, 63 | 64 | {"String[]", "{\"a\",\n \"\",\n \"test test\"}", "string var[] = {\"a\",\n \"\",\n \"test test\"};"}, 65 | {"String[]", "{\"spaces space\", \"a a\"}", "string var[] = {\"spaces space\", \"a a\"};"}, 66 | 67 | {"double[]", "{ 1e9, -3.e-012, -4, 5 }", "double var[] = { 1e9, -3.e-012, -4, 5 };"}, 68 | 69 | {"long[]", "{ 0, -1, 1, 2147483648,\n-2147483649, 9223372036854775807, -9223372036854775808}", "long long var[] = {0, -1, 1, 2147483648LL, -2147483649LL, 9223372036854775807LL, -9223372036854775808LL};"}, 70 | }; 71 | return Arrays.asList(data); 72 | } 73 | 74 | @Test public void test() throws InvalidTypeException { 75 | DataType dt = DataTypeFactoryMock.getDataType(this.typename); 76 | generator.generateParameter(code, dt, "var", this.value, false); 77 | String result = compressSpaceBeforeEquals(code.lines.get(0).toString()); 78 | assertEquals(this.expected, result); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /test/moj/JavaParameterTest.java: -------------------------------------------------------------------------------- 1 | package moj; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | import moj.mocks.*; 10 | 11 | import org.junit.*; 12 | import org.junit.runner.RunWith; 13 | import org.junit.runners.Parameterized; 14 | import org.junit.runners.Parameterized.Parameters; 15 | 16 | import com.topcoder.shared.language.JavaLanguage; 17 | import com.topcoder.shared.problem.DataType; 18 | import com.topcoder.shared.problem.InvalidTypeException; 19 | 20 | @RunWith(Parameterized.class) 21 | public class JavaParameterTest { 22 | private String typename, value, expected; 23 | 24 | public JavaParameterTest(String typename, String varval, String expected) { 25 | this.typename = typename; 26 | this.value = varval; 27 | this.expected = expected; 28 | } 29 | 30 | JavaHarnessGenerator generator; 31 | ArrayList code; 32 | 33 | @Before public void setUp() { 34 | generator = new JavaHarnessGenerator( 35 | new ProblemComponentModelMock(), 36 | JavaLanguage.JAVA_LANGUAGE, 37 | new PreferencesMock() 38 | ); 39 | code = new ArrayList(); 40 | } 41 | 42 | static String compressSpaceBeforeEquals(String str) { 43 | return str.replaceFirst("\\s*=", " =").trim(); 44 | } 45 | 46 | @Parameters 47 | public static List data() { 48 | Object[][] data = new Object[][] { 49 | {"int", "-2147483648", "int var = -2147483648;"}, 50 | 51 | {"String", "\"test string\"", "String var = \"test string\";"}, 52 | {"String", "\" multiple spaces \"", "String var = \" multiple spaces \";"}, 53 | {"String", "\" a = 3 \"", "String var = \" a = 3 \";"}, 54 | 55 | {"double", "1.345e08", "double var = 1.345e08;"}, 56 | 57 | {"long", "123", "long var = 123;"}, 58 | {"long", "-9999999999", "long var = -9999999999L;"}, 59 | {"long", "2147483648", "long var = 2147483648L;"}, 60 | 61 | {"int[]", "{-2147483648, 2147483647, 0, -1, 555}", "int[] var = {-2147483648, 2147483647, 0, -1, 555};"}, 62 | {"int[]", "{}", "int[] var = {};"}, 63 | 64 | {"String[]", "{\"a\",\n \"\",\n \"test test\"}", "String[] var = {\"a\",\n \"\",\n \"test test\"};"}, 65 | {"String[]", "{\"spaces space\", \"a a\"}", "String[] var = {\"spaces space\", \"a a\"};"}, 66 | 67 | {"double[]", "{ 1e9, -3.e-012, -4, 5 }", "double[] var = { 1e9, -3.e-012, -4, 5 };"}, 68 | 69 | {"long[]", "{ 0, -1, 1, 2147483648,\n-2147483649, 9223372036854775807, -9223372036854775808}", "long[] var = {0, -1, 1, 2147483648L, -2147483649L, 9223372036854775807L, -9223372036854775808L};"}, 70 | }; 71 | return Arrays.asList(data); 72 | } 73 | 74 | @Test public void test() throws InvalidTypeException { 75 | DataType dt = DataTypeFactoryMock.getDataType(this.typename); 76 | generator.generateParameter(code, dt, "var", this.value, false); 77 | String result = compressSpaceBeforeEquals(code.get(0).toString()); 78 | assertEquals(this.expected, result); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /test/moj/mocks/DataTypeFactoryMock.java: -------------------------------------------------------------------------------- 1 | package moj.mocks; 2 | 3 | import java.util.HashMap; 4 | 5 | import com.topcoder.shared.language.CPPLanguage; 6 | import com.topcoder.shared.language.JavaLanguage; 7 | import com.topcoder.shared.problem.DataType; 8 | import com.topcoder.shared.problem.InvalidTypeException; 9 | 10 | public class DataTypeFactoryMock { 11 | static public DataType getDataType(String description) throws InvalidTypeException { 12 | int id = 0; 13 | HashMap typeMapping = new HashMap(); 14 | int cpp = CPPLanguage.CPP_LANGUAGE.getId(); 15 | int java = JavaLanguage.JAVA_LANGUAGE.getId(); 16 | 17 | typeMapping.put(java, description); 18 | if (description.equals("int")) { 19 | id = 1; 20 | typeMapping.put(cpp, "int"); 21 | } else if (description.equals("int[]")) { 22 | id = 2; 23 | typeMapping.put(cpp, "vector"); 24 | } else if (description.equals("String")) { 25 | id = 3; 26 | typeMapping.put(cpp, "string"); 27 | } else if (description.equals("String[]")) { 28 | id = 4; 29 | typeMapping.put(cpp, "vector"); 30 | } else if (description.equals("double")) { 31 | id = 5; 32 | typeMapping.put(cpp, "double"); 33 | } else if (description.equals("double[]")) { 34 | id = 6; 35 | typeMapping.put(cpp, "vector"); 36 | } else if (description.equals("long")) { 37 | id = 7; 38 | typeMapping.put(cpp, "long long"); 39 | } else if (description.equals("long[]")) { 40 | id = 8; 41 | typeMapping.put(cpp, "vector"); 42 | } else { 43 | throw new InvalidTypeException("invalid base type \"" + description + "\""); 44 | } 45 | return new DataType(id, description, typeMapping); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /test/moj/mocks/PreferencesMock.java: -------------------------------------------------------------------------------- 1 | package moj.mocks; 2 | 3 | public class PreferencesMock extends moj.Preferences { 4 | @Override 5 | protected String getStringProperty(String key, String defaultValue) { 6 | return defaultValue; 7 | } 8 | 9 | @Override 10 | protected boolean getBooleanProperty(String key, boolean defaultValue) { 11 | return defaultValue; 12 | } 13 | 14 | @Override 15 | protected int getIntegerProperty(String key, int defaultValue) { 16 | return defaultValue; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/moj/mocks/ProblemComponentModelMock.java: -------------------------------------------------------------------------------- 1 | package moj.mocks; 2 | 3 | import com.topcoder.client.contestant.ProblemComponentModel; 4 | import com.topcoder.client.contestant.ProblemModel; 5 | import com.topcoder.netCommon.contestantMessages.response.data.ComponentChallengeData; 6 | import com.topcoder.shared.problem.DataType; 7 | import com.topcoder.shared.problem.ProblemComponent; 8 | import com.topcoder.shared.problem.TestCase; 9 | 10 | public class ProblemComponentModelMock implements ProblemComponentModel { 11 | 12 | public String getClassName() { 13 | return "ProblemComponentModelMock"; 14 | } 15 | 16 | public ProblemComponent getComponent() { 17 | return null; 18 | } 19 | 20 | public ComponentChallengeData getComponentChallengeData() { 21 | return null; 22 | } 23 | 24 | public Integer getComponentTypeID() { 25 | return null; 26 | } 27 | 28 | public String getDefaultSolution() { 29 | return null; 30 | } 31 | 32 | public Long getID() { 33 | return null; 34 | } 35 | 36 | public String getMethodName() { 37 | return "mockMethod"; 38 | } 39 | 40 | public String[] getParamNames() { 41 | return new String[]{}; 42 | } 43 | 44 | public DataType[] getParamTypes() { 45 | return new DataType[]{}; 46 | } 47 | 48 | public Double getPoints() { 49 | return null; 50 | } 51 | 52 | public ProblemModel getProblem() { 53 | return null; 54 | } 55 | 56 | public DataType getReturnType() { 57 | return null; 58 | } 59 | 60 | public TestCase[] getTestCases() { 61 | return null; 62 | } 63 | 64 | public boolean hasTestCases() { 65 | return false; 66 | } 67 | 68 | } 69 | --------------------------------------------------------------------------------