diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..b58b603
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,5 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..77ad396
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/javascript-test-compat.iml b/.idea/javascript-test-compat.iml
new file mode 100644
index 0000000..0c8867d
--- /dev/null
+++ b/.idea/javascript-test-compat.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..d5f83ec
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/package.json b/package.json
index d5722be..ff196fb 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
},
"devDependencies": {
"@types/chai": "^4.2.11",
+ "@types/node": "^18.6.4",
"chai": "^4.2.0",
"husky": "^4.2.5",
"prettier": "^2.0.5",
@@ -26,5 +27,6 @@
"hooks": {
"pre-commit": "pretty-quick --staged"
}
- }
+ },
+ "dependencies": {}
}
diff --git a/src/antiSpoilers.ts b/src/antiSpoilers.ts
new file mode 100644
index 0000000..b93def5
--- /dev/null
+++ b/src/antiSpoilers.ts
@@ -0,0 +1,64 @@
+import * as assertions from "./assertions";
+import { ExecException } from "child_process";
+
+const fs = require("fs").promises;
+const util = require("util");
+const childProcess = require("child_process");
+const performance = require("perf_hooks").performance;
+
+export const assertLag = async function assertLag(
+ callback: (...args: any) => any,
+ timeout = 4000,
+ message = "Test failed: algorithm too fast"
+) {
+ const userSolution = await fs.readFile("/home/codewarrior/solution.txt");
+ const patchedSolution = `${userSolution};
+ (${callback.toString()})();
+ `;
+ let fileIdentifier = 0;
+ let fileName;
+ while (true) {
+ try {
+ fileName = `/home/codewarrior/_lagtest${fileIdentifier}.js`;
+ await fs.writeFile(fileName, patchedSolution);
+ } catch (e) {
+ fileIdentifier++;
+ continue;
+ }
+ break;
+ }
+
+ const startTime = performance.now();
+ const lagTester = childProcess.exec(
+ `node ${fileName}`,
+ (error: ExecException | null) => {
+ if (error === null) {
+ lagTester.emit("passed");
+ } else {
+ lagTester.emit("failed");
+ }
+ }
+ );
+
+ const lagResult = await new Promise((resolve) => {
+ let interval = setInterval(() => {
+ const endTime = performance.now();
+ if (endTime - startTime >= timeout) {
+ clearInterval(interval);
+ lagTester.kill();
+ }
+ }, 200);
+
+ lagTester.on("passed", () => {
+ clearInterval(interval);
+ resolve(false);
+ });
+
+ lagTester.on("failed", () => {
+ clearInterval(interval);
+ resolve(true);
+ });
+ });
+
+ assertions.expect(lagResult, message);
+};
diff --git a/yarn.lock b/yarn.lock
index b2ab29a..8d0fe8f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -38,6 +38,11 @@
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
+"@types/node@^18.6.4":
+ version "18.6.4"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.6.4.tgz#fd26723a8a3f8f46729812a7f9b4fc2d1608ed39"
+ integrity sha512-I4BD3L+6AWiUobfxZ49DlU43gtI+FTHSv9pE2Zekg6KjMpre4ByusaljW3vYSLJrvQ1ck1hUaeVu8HVlY3vzHg==
+
"@types/parse-json@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"