Skip to content

Commit

Permalink
Script for Cycle1_PartC direct download
Browse files Browse the repository at this point in the history
  • Loading branch information
nothuman2718 committed Feb 7, 2024
1 parent 14fbe5f commit eda41a5
Show file tree
Hide file tree
Showing 90 changed files with 799 additions and 195 deletions.
Binary file removed Assignments/Cycle 1_Part A.pdf
Binary file not shown.
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
## Here you can find the script directly

This is just another branch of the main repository. This branch is created to provide the script directly to the students who are not familiar with git and github. This is just a simple way to provide the script directly to the students. If you are familiar with git and github then you can head to the main repository and clone the repository and use the script from there. [Main Repository](https://github.com/nothuman2718/DSALab.git).

### Automated Script evaluation similar to lab.

- Similar to lab you can only run script in the Linux environment amd also in macOS (macOS is built on top of a UNIX-like OS). So for running in windows you can install bash from this command. Windows Subsystem For Linux.

```
wsl --install
```

- Read this [Article](https://www.geeksforgeeks.org/how-to-run-bash-script-in-linux/) on how to use bash.
- Only Prerequisite is to have Node installed on your machine.[Please refer documentation](https://nodejs.org/en/docs).
- There many ways install node. One way is through Linux package manager **_apt_**.

```bash
sudo apt install nodejs
```

### Benefits of this Script.

- When your test cases gets failed there will be a directory created with WrongOutputs in the same directory as the script file which contains the failed testcase data which itself contains input to that specific test case and output which your code generated and the expected output and link to the explanation of the failed testcase.

- On successful run of your testcase you can see the total time taken to run that specific test case and memory it took in bytes.

- There will be an ScriptReport file. Which provides total report of the script.

- To avoid confusion, We implimented this script in a way that it will only run the script which is in the same directory as the script similar to lab.

- For example if you want to run script for Cycle1PartA then download the zip folder of git repository .Head to Scripts directory which contains the specific script for Cycle1PartA and test cases for each question .
- Keep your CFilesFolder in the Script directory.

### To run the script file just type the following command in the terminal.(for Q1 similarly for other questions same as lab).

```bash
node evaluate.js q1
```

### Things to notice.

- Beaware of infinte loops that can crash your system. We are not responsible for that.If that happens immediately restart the system or use this linux command to know the status of your processors and can kill the instruction running on your processors.

```
htop
```

- Running of all script files doesn't mean that your code is correct. It just means that your code is passing all the test cases which we included in the script file.

### Maintainers

- VLM Lokesh [Mail](mailto:[email protected])
- Devineni Sriram [Mail](mailto:[email protected])
- Varshini Pandiri [Mail](mailto:[email protected])
- Geetha Meenakshi [Mail](mailto:[email protected])

### Motivation behind this repository.

- "Lift others, lift yourself – that's the way we learn and grow."
219 changes: 219 additions & 0 deletions Script-Cycle1PartC/Cycle1_PartC/evaluate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
const fs = require('fs');
const path = require('path');
const execSync = require('child_process').execSync;
const { spawnSync } = require('child_process');

function validateNames(folderName, fileName) {
// Regular expression for the folder name
const folderRegex = /^ASSGC\d_[A-Z]_B\d{2}\d{4}CS_CS\d{2}_[A-Z]+$/;

// Regular expression for the file name
const fileRegex = /^ASSGC\d_[A-Z]_B\d{2}\d{4}CS_CS\d{2}_[A-Z]+_\d\.c$/;

// Test the folder name
if (!folderRegex.test(folderName)) {
return false;
}

// Test the file name
if (!fileRegex.test(fileName)) {
return false;
}

return true;
}

function main() {
let qn = process.argv[2];
let contentInDir = fs.readdirSync(__dirname);
let cFilesFolder;
for (let f of contentInDir) {
if (f.startsWith("ASSG")) {
const stats = fs.lstatSync(f);
if (stats.isDirectory()) {
cFilesFolder = f;
break;
}
}
}
if (cFilesFolder == undefined) {
console.error("No C files folder found");
process.exit(1);
}

let Wrong = path.join(__dirname, 'WrongOutputs' + qn);
let Correct = path.join(__dirname, 'CorrectOutputs' + qn);
let ScriptReport = path.join(__dirname, 'ScriptReport.txt');
fs.writeFileSync(ScriptReport, "");
//After every run it will delete the previous files and create new files.
if (fs.existsSync(Wrong)) {
fs.rmdirSync(Wrong, { recursive: true });
}
fs.mkdirSync(Wrong);
if (fs.existsSync(Correct)) {
fs.rmdirSync(Correct, { recursive: true });
}
fs.mkdirSync(Correct);

//Check if the folder exists
try {
fs.accessSync(qn);
} catch (err) {
console.error("Wrong Question Folder");
fs.appendFileSync(ScriptReport, "Wrong Question Folder\n");
process.exit(1);
}


let cFiles = fs.readdirSync(cFilesFolder);

//it will work for only q0-q9.(Max 10 questions)
let cFile = cFiles.find(f => f.endsWith(".c") && f[f.length - 3] === qn[qn.length - 1]);
let result = validateNames(cFilesFolder, cFile);
if (result) {
console.log("\x1b[33m\x1b[1mValid folder and file names\x1b[0m\n");
fs.appendFileSync(ScriptReport, "Valid folder and file names\n");
}
else {
console.log("\x1b[91mInvalid folder or file names. Rename according to instructions given in the pdf.\n\x1b[0m");
console.log("\x1b[91mBut our script will try to evaluate your code. If not worked, please rename and try again.\x1b[0m\n");
fs.appendFileSync(ScriptReport, "Invalid folder or file names. Please do remember to keep the folder in this dir or if it is preesent with wrong name then rename the folder and file names as per the instructions given in the pdf.");
fs.appendFileSync(ScriptReport, "But our script will try to evaluate your code. If not worked, please rename and try again.\n");
}
console.log("File : " + cFile);
fs.appendFileSync(ScriptReport, "File : " + cFile + "\n");

let pgmName = path.join(cFilesFolder, cFile);
try {
execSync(`gcc ${pgmName} -lm`);
} catch (err) {
console.error("\n\nCompilation Error!!!!.\n\n Not Compiled");
fs.appendFileSync(ScriptReport, "Compilation Error!!!!.\n\n Not Compiled\n");
process.exit(1);
}

let noOfTestCases = fs.readdirSync(qn).length / 2;
let correct = [];
let wrong = [];
let noofInfinteLoops = 0;
for (let f of fs.readdirSync(qn)) {
let infinity = false;
if (f.endsWith(".txt") && f.startsWith("in")) {
let inputfile = path.join(qn, f);
fs.copyFileSync(inputfile, "input.txt");
if (!fs.readFileSync('input.txt', 'utf8')) {
console.log("Input file is empty");
fs.appendFileSync(ScriptReport, "Input file is empty\n");
process.exit(1);
}

try {
let start = Date.now();
let child = spawnSync('sh', ['-c', './a.out <input.txt >output.txt'], { timeout: 2000 });

if (child.error || child.signal === 'SIGTERM') {
infinity = true;
noofInfinteLoops++;

console.log("Might be an infinite loop . Please debug before running again");
console.error('The process was killed because it did not finish within 2000 ms \n');
console.log("Adjust time accordingly if 1000ms is not enough on line: 103 in evaluate.js\n\n");
console.error('\x1b[31m%s\x1b[0m', "Infinite loop may cause your system breakdown or crash. So please restart your system before executing script again.\n\n");
fs.appendFileSync(ScriptReport, "Might be an infinite loop . Please debug before running again\n");
fs.appendFileSync(ScriptReport, 'The process was killed because it did not finish within 2000 ms \n');
fs.appendFileSync(ScriptReport, "Adjust time accordingly if 1000ms is not enough on line: 103 in evaluate.js\n\n");
fs.appendFileSync(ScriptReport, "Infinite loop may cause your system breakdown or crash. So please restart your system before executing script again.\n\n");
}

let end = Date.now();
let duration = end - start;
console.log(`Execution time: \x1b[34m${duration} ms\x1b[0m`);
fs.appendFileSync(ScriptReport, `Execution time: ${duration} ms\n`);

let stats = fs.statSync("output.txt");
let fileSizeInBytes = stats.size;
console.log(`File size: \x1b[34m${fileSizeInBytes} Bytes\x1b[0m`);
fs.appendFileSync(ScriptReport, `File size: ${fileSizeInBytes} Bytes\n`);

if (fileSizeInBytes > 500 * 1024) {
console.log("Output file is too large. Consider deleting it.");
fs.appendFileSync(ScriptReport, "Output file is too large. Consider deleting it.\n");
}
} catch (err) {
console.error(`Execution error for testcase #${f[f.length - 5]}: ${err}`);
fs.appendFileSync(ScriptReport, `Execution error for testcase #${f[f.length - 5]}: ${err}\n`);
process.exit(1);
}
//valid input file names are {in}+{randomtext}+{number}.txt
let [testCaseNumber] = f.match(/\d+/g).map(Number);
let correctOutput = fs.readFileSync(path.join(qn, `out${testCaseNumber}.txt`), 'utf8').trim();
let yourOutput = fs.readFileSync("output.txt", 'utf8').trim();

let proctxt = yourOutput.split('\n').map(line => line.trim()).join('\n');
let cotxt = correctOutput.split('\n').map(line => line.trim()).join('\n');

if (cotxt === proctxt) {
console.log(`\x1b[32m\tTestcase #${testCaseNumber}: Correct\x1b[0m\n\n`); // Green for correct
fs.appendFileSync(ScriptReport, `Testcase #${testCaseNumber}: Correct\n\n`);
correct.push(testCaseNumber);
let inputContent = fs.readFileSync("input.txt", "utf8");
fs.appendFileSync(path.join(Correct, `TestCase-${testCaseNumber}.txt`), "Input:\n" + inputContent + "\n");
fs.appendFileSync(path.join(Correct, `TestCase-${testCaseNumber}.txt`), "\nYour Output:\n");
fs.appendFileSync(path.join(Correct, `TestCase-${testCaseNumber}.txt`), proctxt + "\n");
fs.appendFileSync(path.join(Correct, `TestCase-${testCaseNumber}.txt`), "\n\nExpected Output:\n");
fs.appendFileSync(path.join(Correct, `TestCase-${testCaseNumber}.txt`), cotxt);


let content = fs.readFileSync(path.join(Correct, `TestCase-${testCaseNumber}.txt`), "utf8");
fs.appendFileSync(ScriptReport, content);

} else {
if (infinity) {
console.log(`\x1b[31m\tTestcase #${testCaseNumber}: Wrong (Might be an infinite loop)\x1b[0m\n\n`); // Red for wrong
fs.appendFileSync(ScriptReport, `Testcase #${testCaseNumber}: Wrong (Might be an infinite loop)\n\n`);
}
else {
console.log(`\x1b[31m\tTestcase #${testCaseNumber}: Wrong\x1b[0m\n\n`); // Red for wrong
fs.appendFileSync(ScriptReport, `Testcase #${testCaseNumber}: Wrong\n\n`);
}

wrong.push(testCaseNumber);
if (noofInfinteLoops > 1) {
console.error('\x1b[31m%s\x1b[0m', "Already 2 infinite loops are detected in these test cases. Please restart the computer and debug again or you can use htop command please refer the documentation\n\n");
fs.appendFileSync(ScriptReport, "Already 2 infinite loops are detected in these test cases. Please restart the computer and debug again or you can use htop command please refer the documentation\n\n");
fs.appendFileSync(ScriptReport, "Sorry to say but your two processors are using 100% because two infinte loops are running. So please restart your system and debug again or stop the process using htop command.Please google it .\n\n")
process.exit(1);
}
let inputContent = fs.readFileSync("input.txt", "utf8");
fs.appendFileSync(path.join(Wrong, `TestCase-${testCaseNumber}.txt`), "Input:\n" + inputContent + "\n");
fs.appendFileSync(path.join(Wrong, `TestCase-${testCaseNumber}.txt`), "\nYour Output:\n");
fs.appendFileSync(path.join(Wrong, `TestCase-${testCaseNumber}.txt`), proctxt + "\n");
fs.appendFileSync(path.join(Wrong, `TestCase-${testCaseNumber}.txt`), "\n\nExpected Output:\n");
fs.appendFileSync(path.join(Wrong, `TestCase-${testCaseNumber}.txt`), cotxt);
fs.appendFileSync(path.join(Wrong, `TestCase-${testCaseNumber}.txt`), "\n\nExplanation Link(Hold Ctrl and Click)\n");
let content = fs.readFileSync(path.join(Wrong, `TestCase-${testCaseNumber}.txt`), "utf8");
fs.appendFileSync(path.join(Wrong, `TestCase-${testCaseNumber}.txt`), `https://github.com/nothuman2718/DSALab/blob/main/TestCases/Cycle1_PartC/Q${qn[1]}.md/#test-case-${testCaseNumber}`);
fs.appendFileSync(ScriptReport, content);
}
}
}

correct.sort();
wrong.sort();

console.log(`\nCORRECT : \x1b[32m${correct.join(' ')}\x1b[0m`);
fs.appendFileSync(ScriptReport, `CORRECT : ${correct.join(' ')}\n`);
console.log(`WRONG : \x1b[31m${wrong.join(' ')}\x1b[0m`);
fs.appendFileSync(ScriptReport, `WRONG : ${wrong.join(' ')}\n\n`);
console.log(`\n\tPassed \x1b[34m${correct.length} / ${noOfTestCases}\x1b[0m\n`);
fs.appendFileSync(ScriptReport, `\n\tPassed ${correct.length} / ${noOfTestCases}\n`);
//Clean a.out and output.txt and input.txt
if (fs.existsSync("a.out"))
execSync("rm a.out");
if (fs.existsSync("output.txt"))
execSync("rm output.txt");
if (fs.existsSync("input.txt"))
execSync("rm input.txt");
}

main();
5 changes: 5 additions & 0 deletions Script-Cycle1PartC/Cycle1_PartC/q1/in1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
0 0
u A B
i A B
s A B
e
10 changes: 10 additions & 0 deletions Script-Cycle1PartC/Cycle1_PartC/q1/in10.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
7 15
2 3 6 9 3 6 7
3 6 3 4 5 3 6 8 1 1 2 9 9 8 3
u A B
u B A
i A B
i B A
s A B
s B A
e
10 changes: 10 additions & 0 deletions Script-Cycle1PartC/Cycle1_PartC/q1/in2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
2 9
1 1
1 1 1 1 1 1 1 1 1
u A B
u B A
i A B
i B A
s A B
s B A
e
10 changes: 10 additions & 0 deletions Script-Cycle1PartC/Cycle1_PartC/q1/in3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
8 8
16 23 37 48 92 54 63 94
16 23 48 37 54 92 94 63
u A B
u B A
i A B
i B A
s A B
s B A
e
7 changes: 7 additions & 0 deletions Script-Cycle1PartC/Cycle1_PartC/q1/in4.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
5 0
1 2 3 4 5
u A B
s A B
s B A
i A B
e
7 changes: 7 additions & 0 deletions Script-Cycle1PartC/Cycle1_PartC/q1/in5.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
1 1
10
20
i A B
s A B
u A B
e
9 changes: 9 additions & 0 deletions Script-Cycle1PartC/Cycle1_PartC/q1/in6.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
5 5
100 50 75 25 10
25 30 40 50 60
i A B
s A B
u B A
s B A
u A B
e
8 changes: 8 additions & 0 deletions Script-Cycle1PartC/Cycle1_PartC/q1/in7.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
2 6
4 7
8 3 5 7 0 4
u A B
s A B
s B A
i B A
e
10 changes: 10 additions & 0 deletions Script-Cycle1PartC/Cycle1_PartC/q1/in8.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
2 3
89 90
1 2 3
u A B
u B A
i A B
i B A
s A B
s B A
e
10 changes: 10 additions & 0 deletions Script-Cycle1PartC/Cycle1_PartC/q1/in9.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
8 6
1 2 3 4 5 6 7 8
6 7 8 3 2 1
u A B
u B A
i A B
i B A
s A B
s B A
e
3 changes: 3 additions & 0 deletions Script-Cycle1PartC/Cycle1_PartC/q1/out1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-1
-1
-1
6 changes: 6 additions & 0 deletions Script-Cycle1PartC/Cycle1_PartC/q1/out10.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
2 3 6 9 7 4 5 8 1
3 6 4 5 8 1 2 9 7
2 3 6 9
3 6 2 9
7
4 5 8 1
Loading

0 comments on commit eda41a5

Please sign in to comment.