Skip to content

Commit

Permalink
Merge pull request #121 from searleser97/develop
Browse files Browse the repository at this point in the history
merge develop into master
  • Loading branch information
searleser97 authored Feb 21, 2025
2 parents 487da36 + 54819ed commit 139990e
Show file tree
Hide file tree
Showing 30 changed files with 596 additions and 220 deletions.
100 changes: 0 additions & 100 deletions README.md

This file was deleted.

1 change: 1 addition & 0 deletions README.md
20 changes: 15 additions & 5 deletions app/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# cpbooster · [![GPLv3 license](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://github.com/searleser97/cpbooster/blob/master/LICENSE) [![npm version](https://badge.fury.io/js/cpbooster.svg#)](https://badge.fury.io/js/cpbooster) ![npm](https://img.shields.io/npm/dt/cpbooster)

### Competitive Programming Booster 🡲 https://searleser97.github.io/cpbooster/
### Link to Website 🡲 https://searleser97.github.io/cpbooster/

## About

Expand Down Expand Up @@ -53,6 +53,8 @@

1. Flat File Structure. See [Why Flat File Structure](https://searleser97.github.io/cpbooster/docs/clone/#why-flat-file-structure)

1. Supports any programming language.

## How to Contribute

1. Fork this repository and clone it locally: `git clone https://github.com/{yourUsername}/cpbooster`
Expand All @@ -71,14 +73,22 @@
- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
- [prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)

## Future updates
## Future Updates (work not started yet, you can contribute by coding any of these features)

- add `--here` option to `cpb clone` to clone testcases in current directory
- Add Memory Limit Exceeded Veredict (using `gnu-time` as `/usr/bin/time -f '%M' ./program`, can't use `ps` due to lack of precision.
See https://stackoverflow.com/a/131346/13079132)
- Add the possibility to test interactive problems
- Add the possibility to test current file using test cases of another file (test --as \<filename>)
- Add Stress tests (using brute force solution and tests generator)
- Add the possibility to test current file using test cases of another file (test --as \<filename> or `cpb test <sourcefile> --with \<testcases_filename>`)
- Add the possibility to debug current file using test cases of another file (test --as \<filename> -d)
- Add support for Java
- Fully support windows CMD.
- Add Stress tests (using brute force solution and tests generator)
- Add support for `NODE_ENV` in compile/debug command for debugging purposes.
- Refactor `DebugOne` and `DebugWithUserInput` functions.
- Open editor in created file right after executing `cpb create <filename>.<ext>`
- Add option per file type/language to not prepend the `// time-limit: xxx` comment on top of a file of specific type/language.
- Solve TODOs in code.


## Final Notes

Expand Down
4 changes: 2 additions & 2 deletions app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "cpbooster",
"author": "searleser97",
"version": "2.6.4",
"version": "2.6.5",
"description": "cpbooster is a cross-platform CLI tool designed to boost competitive programmer's speed during contests by automating various routine tasks",
"homepage": "https://github.com/searleser97/cpbooster",
"repository": "github:searleser97/cpbooster",
Expand Down
41 changes: 30 additions & 11 deletions app/src/Clone/CCServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import { exit } from "process";
import { spawn, spawnSync } from "child_process";
import Util from "../Utils/Util";
import SourceFileCreator from "../Create/SourceFileCreator";
import * as os from "os";
import { getEditorCommand } from "./EditorCommandBuilder";
import chalk from "chalk";
import Tester from "../Test/TesterFactory/Tester";
Expand All @@ -34,6 +33,8 @@ import Tester from "../Test/TesterFactory/Tester";
export default class CCServer {
app = express();
contestName = "NO_NAME";
contestPath = "";
platform = "NO_PLATFORM";
config: Config;
isActive = false;
lastRequestTime = process.hrtime();
Expand All @@ -47,16 +48,33 @@ export default class CCServer {
const problemData: ProblemData = request.body;
problemData.name = Util.normalizeFileName(problemData.name);
problemData.group = Util.normalizeFileName(problemData.group);

this.contestName = problemData.group;
this.contestPath = Util.getContestPath(this.contestName, this.config);
if (!fs.existsSync(this.contestPath)) fs.mkdirSync(this.contestPath, { recursive: true });
const FilesPathNoExtension = `${Path.join(this.contestPath, problemData.name)}`;
if (this.config.createContestPlatformDirectory) {
let [platform, contestName] = problemData.group.split("-").map((str) => str.trim());
this.platform = platform;
// removes platform name from contest name
contestName = contestName.replace(new RegExp(this.platform, 'g'), "");
contestName = Util.normalizeFileName(contestName);
// removes extra dots
this.contestName = contestName.replace(/\./g, "");
} else {
problemData.group = Util.normalizeFileName(problemData.group);
this.contestName = problemData.group;
}

const contestPath = config.cloneInCurrentDir
? this.contestName
: Path.join(config.contestsDirectory, problemData.group);
: this.config.createContestPlatformDirectory
? Path.join(this.config.contestsDirectory, this.platform, this.contestName)
: Path.join(this.config.contestsDirectory, problemData.group);
if (!fs.existsSync(contestPath)) fs.mkdirSync(contestPath, { recursive: true });
const FilesPathNoExtension = `${Path.join(contestPath, problemData.name)}`;
const extension = `.${config.preferredLang}`;
const filePath = `${FilesPathNoExtension}${extension}`;
SourceFileCreator.create(filePath, config, problemData.timeLimit, problemData.url);
SourceFileCreator.create(filePath, config, false, problemData.timeLimit, problemData.url);
problemData.tests.forEach((testcase, idx) => {
fs.writeFileSync(Tester.getInputPath(filePath, idx + 1), testcase.input);
fs.writeFileSync(Tester.getAnswerPath(filePath, idx + 1), testcase.output);
Expand All @@ -82,22 +100,23 @@ export default class CCServer {
const interval = setInterval(() => {
if (!this.isActive) return;
const elapsedTime = process.hrtime(this.lastRequestTime)[0];
const isWindows = os.type() === "Windows_NT" || os.release().includes("Microsoft");
const tolerance = isWindows ? 10 : 1;
const tolerance = Util.isWindows() ? 4 : 1;
if (elapsedTime >= tolerance) {
if (serverRef) serverRef.close();
clearInterval(interval);
const contestPath = this.config.cloneInCurrentDir
? this.contestName
: Path.join(this.config.contestsDirectory, this.contestName);
: this.config.createContestPlatformDirectory
? Path.join(this.config.contestsDirectory, this.platform, this.contestName)
: Path.join(this.config.contestsDirectory, this.contestName);
console.log("\n\t DONE!\n");
console.log(`The path to your contest folder is: "${contestPath}"`);
console.log(`The path to your contest folder is: "${this.contestPath}"`);
console.log("\n\tHappy Coding!\n");
const command = getEditorCommand(this.config.editor, contestPath);
const command = getEditorCommand(this.config.editor, this.contestPath);
if (command) {
const newTerminalExec = spawn(command, { shell: true, detached: true, stdio: "ignore" });
newTerminalExec.unref();
if (this.config.closeAfterClone && !isWindows) {
if (this.config.closeAfterClone && !Util.isWindows()) {
const execution = spawnSync("ps", ["-o", "ppid=", "-p", `${process.ppid}`]);
const grandParentPid = parseInt(execution.stdout.toString().trim());
if (!Number.isNaN(grandParentPid)) {
Expand All @@ -116,4 +135,4 @@ export default class CCServer {
}
}, 100);
}
}
}
2 changes: 2 additions & 0 deletions app/src/Clone/EditorCommandBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export function getEditorCommand(terminalName: string, contestPath: string): str
return `kitty --directory "${contestPath}"`;
case "vscode":
return `code "${contestPath}"`;
case "neovide":
return `neovide "${contestPath}"`;
default:
return `${terminalName} "${contestPath}"`;
}
Expand Down
24 changes: 23 additions & 1 deletion app/src/Config/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,14 @@ export default class Config {
closeAfterClone: boolean;
showStatusPageOnSubmit: boolean;
useUserDefaultBrowser: boolean;
createContestPlatformDirectory: boolean;
// preferred language extension
preferredLang: string;
hideTestCaseInput: boolean;
maxLinesToShowFromInput: number;
cloneInCurrentDir: boolean;
groupContestsByJudge: boolean;
executableFileExtension: string;
// config for language extension
languages: Record<string, LangConfig | undefined>;

Expand All @@ -52,18 +55,25 @@ export default class Config {
this.closeAfterClone = false;
this.showStatusPageOnSubmit = true;
this.useUserDefaultBrowser = true;
this.createContestPlatformDirectory = true;
this.preferredLang = "cpp";
this.hideTestCaseInput = false;
this.maxLinesToShowFromInput = 50;
this.cloneInCurrentDir = false;
this.groupContestsByJudge = false;
this.executableFileExtension = "exe";
this.languages = {
cpp: {
template: "",
command: "g++ -std=gnu++17 -O2",
debugCommand: "g++ -std=gnu++17 -DDEBUG -Wshadow -Wall",
aliases: {
codeforces: "54",
atcoder: "4003",
ucup: "C++23",
qoj: "C++23",
universaloj: "C++20",
tlx: "C++20",
atcoder: "5001",
omegaup: "cpp17-gcc",
szkopul: "C++",
yandex: "gcc7_3"
Expand All @@ -77,6 +87,10 @@ export default class Config {
debugCommand: "python3 -O",
aliases: {
codeforces: "31",
ucup: "Python3",
qoj: "Python3",
universaloj: "Python3",
tlx: "PyPy 3",
atcoder: "4006",
omegaup: "py3",
szkopul: "Python"
Expand All @@ -91,6 +105,10 @@ export default class Config {
runCommand: "java",
aliases: {
codeforces: "36",
ucup: "Java11",
qoj: "Java11",
universaloj: "Java17",
tlx: "Java 11",
atcoder: "4005"
},
type: "mixed",
Expand Down Expand Up @@ -136,6 +154,9 @@ export default class Config {
debugCommand: "rustc",
aliases: {
codeforces: "49",
ucup: "Rust",
qoj: "Rust",
tlx: "Rust 2021",
atcoder: "4050"
},
type: "compiled",
Expand All @@ -147,6 +168,7 @@ export default class Config {
debugCommand: "go build",
aliases: {
codeforces: "32",
tlx: "Go",
atcoder: "4026"
},
type: "compiled",
Expand Down
9 changes: 2 additions & 7 deletions app/src/Config/Types/LangAliases.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,2 @@
export type LangAliases = {
codeforces?: string;
atcoder?: string;
omegaup?: string;
szkopul?: string;
yandex?: string;
};
import { OnlineJudgeName } from "./OnlineJudgeName";
export type LangAliases = { [K in OnlineJudgeName]?: string };
11 changes: 11 additions & 0 deletions app/src/Config/Types/OnlineJudgeName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export enum OnlineJudgeName {
codeforces = "codeforces",
universaloj = "universaloj",
qoj = "qoj",
ucup = "ucup",
tlx = "tlx",
atcoder = "atcoder",
omegaup = "omegaup",
szkopul = "szkopul",
yandex = "yandex"
}
Loading

0 comments on commit 139990e

Please sign in to comment.