123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- 'use strict';
- import * as vscode from 'vscode';
- import { existsSync, writeFileSync, readdirSync, copyFileSync } from 'fs';
- import { join, extname } from 'path';
- import { SITES, getSite } from './conn';
- import { newContestFromId, testSolution, veredictName, stressSolution, upgradeArena, newProblemFromId, removeExtension, solFile, initAcmX, currentProblem, compileCode, ATTIC, SRC } from './core';
- import { Veredict, SiteDescription } from './types';
- import { startCompetitiveCompanionService } from './companion';
- import { hideTerminals } from './terminal';
- const TESTCASES = 'testcases';
- function quickPickSites() {
- let sites: any[] = [];
- SITES.forEach(value => {
- sites.push({
- "label" : value.name,
- "target" : value.name,
- "description" : value.description,
- });
- });
- return sites;
- }
- // Create a new problem
- async function addProblem() {
- let site_info = await vscode.window.showQuickPick(quickPickSites(), { placeHolder: 'Select contest site' });
- if (site_info === undefined){
- vscode.window.showErrorMessage("Site not provided.");
- return;
- }
- let site: SiteDescription = getSite(site_info.target);
- let id = await vscode.window.showInputBox({placeHolder: site.problemIdPlaceholder});
- if (id === undefined){
- vscode.window.showErrorMessage("Problem ID not provided.");
- return;
- }
- let path: string | undefined = vscode.workspace.getConfiguration('acmx.configuration', null).get('solutionPath');
- path = join(path!, site.name, 'single');
- let problemPath = await newProblemFromId(path, site, id);
- await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(problemPath));
- // TODO: 007
- // Just want to run two commands below
- // await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(solFile()));
- // vscode.window.showInformationMessage(`Add problem ${site}/${id} at ${path}`);
- }
- async function addContest() {
- let path: string | undefined = vscode.workspace.getConfiguration('acmx.configuration', null).get('solutionPath');
- let site_info = await vscode.window.showQuickPick(quickPickSites(), { placeHolder: 'Select contest site' });
- if (site_info === undefined){
- vscode.window.showErrorMessage("Site not provided.");
- return;
- }
- let site = getSite(site_info.target);
- let id = undefined;
- if (site.name === "empty"){
- let name= await vscode.window.showInputBox({placeHolder: site.contestIdPlaceholder});
- if (name === undefined){
- vscode.window.showErrorMessage("Name not provided.");
- return;
- }
- let probCountStr = await vscode.window.showInputBox({placeHolder: "Number of problems"});
- if (name === undefined){
- vscode.window.showErrorMessage("Number of problems not provided.");
- return;
- }
- id = name + '-' + probCountStr!;
- }
- else{
- id = await vscode.window.showInputBox({placeHolder: site.contestIdPlaceholder});
- if (id === undefined){
- vscode.window.showErrorMessage("Contest ID not provided.");
- return;
- }
- }
- let contestPath = await newContestFromId(path!, site, id);
- vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(contestPath));
- }
- async function debugTestcase(path: string, tcId: string){
- // Change editor layout to show failing test
- await vscode.commands.executeCommand("vscode.setEditorLayout", { orientation: 0, groups: [{ groups: [{}], size: 0.5 }, { groups: [{}, {}, {}], size: 0.5 }] });
- let sol = join(path, solFile());
- let inp = join(path, TESTCASES, `${tcId}.in`);
- let out = join(path, TESTCASES, `${tcId}.out`);
- let cur = join(path, TESTCASES, `${tcId}.real`);
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(sol), vscode.ViewColumn.One);
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(inp), vscode.ViewColumn.Two);
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(out), vscode.ViewColumn.Three);
- // This file might not exist!
- if (existsSync(cur)){
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(cur), vscode.ViewColumn.Four);
- }
- }
- async function runSolution(){
- let path = currentProblem();
- if (path === undefined){
- vscode.window.showErrorMessage("No active problem");
- return;
- }
- let result = testSolution(path);
- if (result.status === Veredict.OK){
- vscode.window.showInformationMessage(`OK. Time ${result.maxTime!}ms`);
- }
- else if (result.status === Veredict.NO_TESTCASES){
- vscode.window.showErrorMessage(`No testcases.`);
- }
- else{
- vscode.window.showErrorMessage(`${veredictName(result.status)} on test ${result.failTcId}`);
- debugTestcase(path, result.failTcId!);
- }
- }
- async function compile(){
- let path = currentProblem();
- if (path === undefined){
- vscode.window.showErrorMessage("No active problem");
- return;
- }
- let sol = join(path, solFile());
- let out = join(path, ATTIC, 'sol');
- if (!existsSync(sol)){
- throw new Error("Open a coding environment first.");
- }
- // Compile solution
- let xresult = compileCode(sol, out);
- if (xresult.status !== 0){
- throw new Error(`Compilation Error. ${sol}`);
- }
- else{
- vscode.window.showInformationMessage("Compilation successfully.");
- }
- }
- async function openTestcase() {
- let path = currentProblem();
- if (path === undefined){
- vscode.window.showErrorMessage("No active problem");
- return;
- }
- let tcs: any[] = [];
- // Read testcases
- readdirSync(join(path, TESTCASES)).
- filter( function (tcpath) {
- return extname(tcpath) === '.in';}).
- map( function(tcpath) {
- let name = removeExtension(tcpath);
- tcs.push({
- 'label' : name,
- 'target' : name,
- });
- });
- let tc = await vscode.window.showQuickPick(tcs, { placeHolder: 'Select testcase' });
- if (tc !== undefined){
- let inp = join(path, TESTCASES, `${tc.target}.in`);
- let out = join(path, TESTCASES, `${tc.target}.out`);
- await vscode.commands.executeCommand("vscode.setEditorLayout", { orientation: 0, groups: [{}, {}]});
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(inp), vscode.ViewColumn.One);
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(out), vscode.ViewColumn.Two);
- }
- }
- async function addTestcase() {
- let path = currentProblem();
- if (path === undefined){
- vscode.window.showErrorMessage("No active problem");
- return;
- }
- let index = 0;
- while (existsSync(join(path, TESTCASES, `${index}.hand.in`))){
- index += 1;
- }
- let inp = join(path, TESTCASES, `${index}.hand.in`);
- let out = join(path, TESTCASES, `${index}.hand.out`);
- writeFileSync(inp, "");
- writeFileSync(out, "");
- await vscode.commands.executeCommand("vscode.setEditorLayout", { orientation: 0, groups: [{}, {}]});
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(inp), vscode.ViewColumn.One);
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(out), vscode.ViewColumn.Two);
- }
- async function coding() {
- hideTerminals();
- let path = currentProblem();
- if (path === undefined){
- vscode.window.showErrorMessage("No active problem");
- return;
- }
- await vscode.commands.executeCommand("vscode.setEditorLayout", { groups: [{}]});
- let sol = join(path, solFile());
- await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(sol), vscode.ViewColumn.One);
- }
- async function stress(){
- let path = currentProblem();
- if (path === undefined){
- vscode.window.showErrorMessage("No active problem");
- return;
- }
- let stressTimes: number | undefined = vscode.workspace.getConfiguration('acmx.stress', null).get('times');
- // Use default
- if (stressTimes === undefined){
- stressTimes = 10;
- }
- let result = stressSolution(path, stressTimes);
- if (result.status === Veredict.OK){
- vscode.window.showInformationMessage(`OK. Time ${result.maxTime!}ms`);
- }
- else{
- vscode.window.showErrorMessage(`${veredictName(result.status)} on test ${result.failTcId}`);
- debugTestcase(path, result.failTcId!);
- }
- }
- async function upgrade(){
- let path = currentProblem();
- if (path === undefined){
- vscode.window.showErrorMessage("No active problem");
- return;
- }
- upgradeArena(path);
- }
- function fileList(dir: string): string[]{
- return readdirSync(dir).reduce((list: string[], file: string) => {
- return list.concat([file]);
- }, []);
- }
- async function setChecker(){
- let path = currentProblem();
- if (path === undefined){
- vscode.window.showErrorMessage("No active problem");
- return;
- }
- let all_checkers_plain = fileList(join(SRC, 'static', 'checkers'))
- .filter((name: string) => name !== 'testlib.h')
- .map((name: string) => name.slice(0, name.length - 4));
- let all_checkers = all_checkers_plain.map((value: string) => {
- return {
- 'label' : value,
- 'target' : value + '.cpp'
- };
- });
- let checker_info = await vscode.window.showQuickPick(all_checkers, { placeHolder: 'Select custom checker.' });
- if (checker_info === undefined){
- vscode.window.showErrorMessage("Checker not provided.");
- return;
- }
- let checker = checker_info.target;
- let checker_path = join(SRC, 'static', 'checkers', checker);
- let checker_dest = join(path, ATTIC, 'checker.cpp');
- copyFileSync(checker_path, checker_dest);
- }
- async function debugTest(){
- console.log("no bugs :O");
- }
- // TODO: Make all the code async.
- // this method is called when your extension is activated
- // your extension is activated the very first time the command is executed
- export function activate(context: vscode.ExtensionContext) {
- initAcmX();
- startCompetitiveCompanionService();
- let addProblemCommand = vscode.commands.registerCommand('acmx.addProblem', addProblem);
- let addContestCommand = vscode.commands.registerCommand('acmx.addContest', addContest);
- let runSolutionCommand = vscode.commands.registerCommand('acmx.runSolution', runSolution);
- let openTestcaseCommand = vscode.commands.registerCommand('acmx.openTestcase', openTestcase);
- let addTestcaseCommand = vscode.commands.registerCommand('acmx.addTestcase', addTestcase);
- let codingCommand = vscode.commands.registerCommand('acmx.coding', coding);
- let stressCommand = vscode.commands.registerCommand('acmx.stress', stress);
- let upgradeCommand = vscode.commands.registerCommand('acmx.upgrade', upgrade);
- let compileCommand = vscode.commands.registerCommand('acmx.compile', compile);
- let setCheckerCommand = vscode.commands.registerCommand('acmx.setChecker', setChecker);
- let debugTestCommand = vscode.commands.registerCommand('acmx.debugTest', debugTest);
- context.subscriptions.push(addProblemCommand);
- context.subscriptions.push(addContestCommand);
- context.subscriptions.push(runSolutionCommand);
- context.subscriptions.push(openTestcaseCommand);
- context.subscriptions.push(addTestcaseCommand);
- context.subscriptions.push(codingCommand);
- context.subscriptions.push(stressCommand);
- context.subscriptions.push(upgradeCommand);
- context.subscriptions.push(compileCommand);
- context.subscriptions.push(setCheckerCommand);
- context.subscriptions.push(debugTestCommand);
- }
- // this method is called when your extension is deactivated
- export function deactivate() {
- }
|