Browse Source

add settings

Marcelo Fornet 6 years ago
parent
commit
f7b172ed7c
4 changed files with 89 additions and 30 deletions
  1. 25 0
      package.json
  2. 43 19
      src/core.ts
  3. 4 4
      src/test/extension.test.ts
  4. 17 7
      todo.md

+ 25 - 0
package.json

@@ -29,6 +29,31 @@
     ],
     "main": "./out/extension",
     "contributes": {
+        "configuration": [
+			{
+				"title": "acmX",
+				"properties": {
+					"acmx.run.timeLimit": {
+						"type": "number",
+						"default": 2,
+						"description": "Maximum time limit in seconds to run the program on each test case.",
+						"scope": "resource"
+                    },
+					"acmx.execution.compileCpp": {
+                        "type": "string",
+						"default": "g++ -std=c++11 $PROGRAM -o $OUTPUT",
+						"description": "Command to compile the program. Refer to the code as $PROGRAM, and output file as $OUTPUT.",
+						"scope": "resource"
+					},
+					"acmx.execution.pythonPath": {
+                        "type": "string",
+						"default": "/usr/bin/python3",
+						"description": "Path to python executable.",
+						"scope": "resource"
+					}
+				}
+            }
+        ],
         "commands": [
             {
                 "command": "extension.addProblem",

+ 43 - 19
src/core.ts

@@ -9,10 +9,19 @@ import { TestcaseResult, Veredict, SolutionResult, Problem, Contest, SiteDescrip
 export const TESTCASES = 'testcases';
 export const ATTIC = 'attic';
 const SRC = dirname(__filename);
-const TESTCASE_TIMEOUT = 1000;
 
-// TODO: 001
-const MAX_SIZE_INPUT = 1024;
+export function getTimeout(){
+    let timeout: number|undefined = vscode.workspace.getConfiguration('acmx.run').get('timeLimit');
+    timeout = timeout! * 1000;
+    return timeout;
+}
+
+/**
+ * Can only handle testcases of at most 512MB
+ */
+function getMaxSizeInput(){
+    return 512 * 1024;
+}
 
 function isProblemFolder(path: string) {
     return  existsSync(join(path, 'sol.cpp')) &&
@@ -128,11 +137,11 @@ function testcases(path: string){
         let inp_fd = openSync(join(path, TESTCASES, `${name}.in`), 'r');
         let out_fd = openSync(join(path, TESTCASES, `${name}.out`), 'r');
 
-        let inp_buffer = new Buffer(MAX_SIZE_INPUT);
-        let out_buffer = new Buffer(MAX_SIZE_INPUT);
+        let inp_buffer = new Buffer(getMaxSizeInput());
+        let out_buffer = new Buffer(getMaxSizeInput());
 
-        readSync(inp_fd, inp_buffer, 0, MAX_SIZE_INPUT, 0);
-        readSync(out_fd, out_buffer, 0, MAX_SIZE_INPUT, 0);
+        readSync(inp_fd, inp_buffer, 0, getMaxSizeInput(), 0);
+        readSync(out_fd, out_buffer, 0, getMaxSizeInput(), 0);
 
         return [
             inp_buffer.toString(),
@@ -208,14 +217,21 @@ export async function newContestFromId(path: string, site: SiteDescription, cont
     newContest(path, contest);
 }
 
-export function timedRun(path: string, tcName: string, timeout = TESTCASE_TIMEOUT){
+/**
+ *
+ * @param path
+ * @param tcName
+ * @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`);
 
     let inputFd = openSync(tcInput, 'r');
-    let buffer = new Buffer(MAX_SIZE_INPUT);
-    readSync(inputFd, buffer, 0, MAX_SIZE_INPUT, 0);
+    let buffer = new Buffer(getMaxSizeInput());
+    readSync(inputFd, buffer, 0, getMaxSizeInput(), 0);
     let tcData = buffer.toString();
     closeSync(inputFd);
 
@@ -256,8 +272,17 @@ export function timedRun(path: string, tcName: string, timeout = TESTCASE_TIMEOU
 }
 
 export function compileCode(pathCode: string, pathOutput: string){
-    // TODO: 002
-    return child_process.spawnSync("g++", ["-std=c++11", `${pathCode}`, "-o", `${pathOutput}`]);
+    let instruction: string | undefined = vscode.workspace.getConfiguration('acmx.execution').get('compileCpp');
+    let splitedInstruction = instruction!.split(' ');
+
+    for (let i = 0; i < splitedInstruction.length; ++i){
+        splitedInstruction[i] = splitedInstruction[i].replace('$PROGRAM', pathCode).replace('$OUTPUT', pathOutput);
+    }
+
+    let program = splitedInstruction[0];
+    let args = splitedInstruction.slice(1);
+
+    return child_process.spawnSync(program, args);
 }
 
 export function testSolution(path: string){
@@ -294,7 +319,7 @@ export function testSolution(path: string){
     testcasesId.forEach(tcId => {
         // Run while there none have failed already
         if (fail === undefined){
-            let tcResult = timedRun(path, tcId);
+            let tcResult = timedRun(path, tcId, getTimeout());
 
             if (tcResult.status !== Veredict.OK){
                 fail = new SolutionResult(tcResult.status, tcId);
@@ -312,7 +337,6 @@ export function testSolution(path: string){
             }
         }
 
-        // TODO: 003
         return new SolutionResult(Veredict.OK, undefined, maxTime);
     }
     else{
@@ -321,8 +345,8 @@ export function testSolution(path: string){
 }
 
 function generateTestcase(path: string){
-    // TODO: 004
-    let genResult = child_process.spawnSync("python3", [join(path, ATTIC, 'gen.py')]);
+    let python: string | undefined = vscode.workspace.getConfiguration('acmx.execution').get('pythonPath');
+    let genResult = child_process.spawnSync(python!, [join(path, ATTIC, 'gen.py')]);
 
     let currentFd = openSync(join(path, TESTCASES, 'gen.in'), 'w');
     writeSync(currentFd, genResult.stdout);
@@ -362,8 +386,8 @@ export function stressSolution(path: string, times: number = 10){
 
         // Generate output testcase from brute.cpp
         let inputFd = openSync(join(path, TESTCASES, 'gen.in'), 'r');
-        let buffer = new Buffer(MAX_SIZE_INPUT);
-        readSync(inputFd, buffer, 0, MAX_SIZE_INPUT, 0);
+        let buffer = new Buffer(getMaxSizeInput());
+        readSync(inputFd, buffer, 0, getMaxSizeInput(), 0);
         let tcData = buffer.toString();
         closeSync(inputFd);
 
@@ -379,7 +403,7 @@ export function stressSolution(path: string, times: number = 10){
         closeSync(currentFd);
 
         // Check sol.cpp report same result than brute.cpp
-        let result = timedRun(path, 'gen');
+        let result = timedRun(path, 'gen', getTimeout());
 
         if (result.status !== Veredict.OK){
             return new SolutionResult(result.status, 'gen');

+ 4 - 4
src/test/extension.test.ts

@@ -6,7 +6,7 @@
 // The module 'assert' provides assertion methods from node
 import * as assert from 'assert';
 import { dirname, join } from 'path';
-import { timedRun, testcasesName, testSolution, newArena, ATTIC, TESTCASES, upgradeArena, stressSolution, newProblemFromId, newContestFromId } from '../core';
+import { timedRun, testcasesName, testSolution, newArena, ATTIC, TESTCASES, upgradeArena, stressSolution, newProblemFromId, newContestFromId, getTimeout } from '../core';
 import { TestcaseResult, Veredict } from '../types';
 import { rmdirSync, existsSync, readdirSync, unlinkSync, openSync, writeSync, closeSync } from 'fs';
 import { getSite } from '../conn';
@@ -144,7 +144,7 @@ suite("Extension Tests", function () {
         let exampleContest = join(ARENA, 'exampleContest');
         let problem = join(exampleContest, 'A');
         let testcaseId = '0';
-        let result: TestcaseResult = timedRun(problem, testcaseId);
+        let result: TestcaseResult = timedRun(problem, testcaseId, getTimeout());
         assert.equal(result.status, Veredict.OK);
     });
 
@@ -152,7 +152,7 @@ suite("Extension Tests", function () {
         let exampleContest = join(ARENA, 'exampleContest');
         let problem = join(exampleContest, 'B');
         let testcaseId = '0';
-        let result: TestcaseResult = timedRun(problem, testcaseId);
+        let result: TestcaseResult = timedRun(problem, testcaseId, getTimeout());
         assert.equal(result.status, Veredict.WA);
     });
 
@@ -160,7 +160,7 @@ suite("Extension Tests", function () {
         let exampleContest = join(ARENA, 'exampleContest');
         let problem = join(exampleContest, 'C');
         let testcaseId = '0';
-        let result: TestcaseResult = timedRun(problem, testcaseId);
+        let result: TestcaseResult = timedRun(problem, testcaseId, getTimeout());
         assert.equal(result.status, Veredict.RTE);
     });
 

+ 17 - 7
todo.md

@@ -1,17 +1,27 @@
 # List of TODO
 
 * **IMPORTANT** Add How to Use (in the README.) How to add own template etc...
-* **IMPORTANT** Create custom settings. Add (TimeLimit, Checker)
 * **WOW** Use this tool: [caide-cpp-inliner](https://github.com/slycelote/caide-cpp-inliner).  Suggestion from jcg
 * When a new view is activated (after run or view:code) close all open tabs. (also (maybe) collapse everything not related to the problem)
 * Allow programming in other languages than c++
-* Figure out something for interactive problems.
 * Allow stopping a running program (such as sol.cpp/brute.cpp/gen.py/etc...)
-* Allow custom checker easily
-* Add several checkers and try to infer which is the correct!
 
-* [001](/src/core.ts): Revisit this constant. Show specific error to know when this is an issue. Add in settings
-* [002](/src/core.ts): Avoid this hardcoded line. Use personalized compile line. increase stack by default. This involve allowing different languages
-* [004](/src/core.ts): Make crossplatform call. Solution: Configure path to python in global settings
 * [005](/src/core.ts): Restrict brute in time, and capture errors
 * [007](/src/extension.ts): How can I have access to new proccess created using `openFolder`?
+
+## Settings
+
+Global settings
+
+* [x] Time Limit
+* [ ] Template file
+* [X] Line to execute C++ (Upgrade this line, by increasing stack and making optimizations by default)
+* [X] Line to execute Python
+
+Particular settings (per problem)
+
+* [ ] Checker
+  * [ ] Allow custom checker implemented with testlib.
+  * [ ] Try to figure out correct checker.
+* [ ] Allow multiple solutions. (Don't check on this case. Try to figure out if this is the case)
+* [ ] Is interactive (Don't check on this case. Try to figure out if this is the case)