Browse Source

Integration with `tcgen`

Marcelo Fornet 6 years ago
parent
commit
9004bcb298
3 changed files with 55 additions and 33 deletions
  1. 14 1
      README.md
  2. 24 30
      src/core.ts
  3. 17 2
      src/gwen.ts

+ 14 - 1
README.md

@@ -7,7 +7,8 @@
 * Contest/Problem parsing. (Through [Competitive-Companion)](https://github.com/jmerle/competitive-companion) extension.)
 * Running solution against testcases automatically
 * Add custom testcases easily
-* Smart veredict reporting (OK, WA, RTE, TLE, CE)
+* Veredict reporting (OK, WA, RTE, TLE, CE)
+* Smart generator creation. Testcases generator is created using `tcgen` program synthesis tool by inspecting testcases.
 * Stressing solution against brute using a generator (Useful to find corner cases)
 * (WIP) Automatic generator creation from inputs/outputs structure
 
@@ -66,6 +67,18 @@ Parsing problems and contests is done via [Competitive-Companion](https://github
 
 I encourage everyone to read and change [all settings](#settings) before first use. Anyway, after updating `acmx.configuration.solutionPath` it should work good for C++ users.
 
+## How does stressing the solution work
+
+To stress the solution your code is compared to a correct code against a larga sample of testcases. In order to do that you should execute `ACMX: Upgrade` from the command pallete. Two files will be created.
+
+* `brute.cpp` This should be a correct solution. A code that is expected to report correct output. It doesn't matter if it's slow as long as you only check this program against small testcases.
+* `gen.py` Every time this code is executed is expected to print a random testcases.
+
+**AWESOME** `gen.py` is created automatically by inspecting testcases if you install [`tcgen`](https://github.com/mfornet/tcgen).
+To install `tcgen` just run:
+
+`pip install tcgen`
+
 ## Default template is awful, how can I change it
 
 Create a file with your template. In settings, set `acmx.configuration.templatePath` to the path to your template.

+ 24 - 30
src/core.ts

@@ -169,7 +169,11 @@ export function newArena(path: string){
         templatePath = join(SRC, 'static', 'template.cpp');
     }
 
-    copyFileSync(templatePath!, join(path, solFile()));
+    let solution = join(path, solFile());
+
+    if (!existsSync(solution)){
+        copyFileSync(templatePath!, join(path, solFile()));
+    }
 }
 
 export function removeExtension(name: string){
@@ -191,25 +195,23 @@ export function testcasesName(path: string){
             map( function(tcpath) { return removeExtension(tcpath); });
 }
 
-function testcases(path: string){
-    return testcasesName(path).map(function (name){
-        let inp_fd = openSync(join(path, TESTCASES, `${name}.in`), 'r');
-        let out_fd = openSync(join(path, TESTCASES, `${name}.out`), 'r');
+// function testcases(path: string){
+//     return testcasesName(path).map(function (name){
+//         let inp_fd = openSync(join(path, TESTCASES, `${name}.in`), 'r');
+//         let out_fd = openSync(join(path, TESTCASES, `${name}.out`), 'r');
 
-        // TODO: Don't create buffer from constructor. See warning:
-        // (node:17458) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
-        let inp_buffer = new Buffer(getMaxSizeInput());
-        let out_buffer = new Buffer(getMaxSizeInput());
+//         let inp_buffer = new Buffer(getMaxSizeInput());
+//         let out_buffer = new Buffer(getMaxSizeInput());
 
-        readSync(inp_fd, inp_buffer, 0, getMaxSizeInput(), 0);
-        readSync(out_fd, out_buffer, 0, getMaxSizeInput(), 0);
+//         readSync(inp_fd, inp_buffer, 0, getMaxSizeInput(), 0);
+//         readSync(out_fd, out_buffer, 0, getMaxSizeInput(), 0);
 
-        return [
-            inp_buffer.toString(),
-            out_buffer.toString()
-        ];
-    });
-}
+//         return [
+//             inp_buffer.toString(),
+//             out_buffer.toString()
+//         ];
+//     });
+// }
 
 export function upgradeArena(path: string) {
     let brute = join(path, 'brute.cpp');
@@ -222,18 +224,8 @@ export function upgradeArena(path: string) {
     let generator = join(path, 'gen.py');
 
     if (!existsSync(generator)){
-        // Create generator
-        let inputs: string[] = [];
-        let outputs: string[] = [];
-
-        testcases(path).forEach(function(testcases){
-            inputs.push(testcases[0]);
-            outputs.push(testcases[1]);
-        });
-
-        let generator_template = gwen.create(inputs, outputs);
-        let generator_fd = openSync(generator, 'w');
-        writeSync(generator_fd, generator_template);
+        // TODO: If generator already exist ask whether to overwrite or not.
+        gwen.create(path, generator);
     }
 }
 
@@ -312,11 +304,13 @@ export async function newContestFromId(path: string, site: SiteDescription, cont
  * @param timeout in miliseconds
  */
 export function timedRun(path: string, tcName: string, timeout: number){
-
     let tcInput = join(path, TESTCASES, `${tcName}.in`);
     let tcOutput = join(path, TESTCASES, `${tcName}.out`);
     let tcCurrent = join(path, TESTCASES, `${tcName}.real`);
 
+    // TODO: Don't create Buffer from constructor `new Buffer()`. See warning:
+    // (node:17458) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
+
     let inputFd = openSync(tcInput, 'r');
     let buffer = new Buffer(getMaxSizeInput());
     readSync(inputFd, buffer, 0, getMaxSizeInput(), 0);

+ 17 - 2
src/gwen.ts

@@ -1,3 +1,18 @@
-export function create(inputs: string[], outputs: string[]) {
-    return 'import random\nprint(random.randint(1, 100))\n';
+import { openSync, writeSync } from "fs";
+import { spawnSync } from "child_process";
+import { TESTCASES } from "./core";
+import { join } from "path";
+
+const DEFAULT = 'import random\n\nprint(random.randint(1, 100))\n';
+
+export function create(problemPath: string, outputPath: string) {
+    let tcPath = join(problemPath, TESTCASES)
+    let exitCode = spawnSync("python", ["-m", `tcgen`, "--path", `${tcPath}`, "--output", `${outputPath}`]);
+
+    console.log("exticode:", exitCode);
+
+    if (exitCode.status !== 0){
+        let generator_fd = openSync(outputPath, 'w');
+        writeSync(generator_fd, DEFAULT);
+    }
 }