extension.ts 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. 'use strict';
  2. import * as vscode from 'vscode';
  3. import { existsSync, writeFileSync, readdirSync } from 'fs';
  4. import { join, extname } from 'path';
  5. import { SITES } from './conn';
  6. import { newContestFromId, testSolution, veredictName, stressSolution, upgradeArena, newProblemFromId, removeExtension } from './core';
  7. import { Veredict } from './types';
  8. import { currentProblem } from './core';
  9. const TESTCASES = 'testcases';
  10. function quickPickSites() {
  11. let sites: any[] = [];
  12. SITES.forEach(value => {
  13. sites.push({
  14. "label" : value.name,
  15. "target" : value.name,
  16. "description" : value.description,
  17. });
  18. });
  19. return sites;
  20. }
  21. // Create a new problem
  22. async function addProblem() {
  23. if (vscode.workspace.workspaceFolders === undefined) {
  24. vscode.window.showErrorMessage("Open the folder that will contain the problem.");
  25. return;
  26. }
  27. let path = vscode.workspace.workspaceFolders[0].uri.path;
  28. let site_info = await vscode.window.showQuickPick(quickPickSites(), { placeHolder: 'Select contest site' });
  29. if (site_info === undefined){
  30. vscode.window.showErrorMessage("Site not provided.");
  31. return;
  32. }
  33. let site = site_info.target;
  34. // TODO: 006
  35. let id = await vscode.window.showInputBox({placeHolder: "Problem ID"});
  36. if (id === undefined){
  37. vscode.window.showErrorMessage("Problem ID not provided.");
  38. return;
  39. }
  40. path = join(path, `${id}`);
  41. await newProblemFromId(path, site, id);
  42. await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(path));
  43. // TODO: 007
  44. // Just want to run two commands below
  45. // await vscode.commands.executeCommand("vscode.open", vscode.Uri.file("sol.cpp"));
  46. // vscode.window.showInformationMessage(`Add problem ${site}/${id} at ${path}`);
  47. }
  48. async function addContest() {
  49. if (vscode.workspace.workspaceFolders === undefined) {
  50. vscode.window.showErrorMessage("Open the folder that will contain the contest.");
  51. return;
  52. }
  53. let path = vscode.workspace.workspaceFolders[0].uri.path;
  54. let site_info = await vscode.window.showQuickPick(quickPickSites(), { placeHolder: 'Select contest site' });
  55. if (site_info === undefined){
  56. vscode.window.showErrorMessage("Site not provided.");
  57. return;
  58. }
  59. let site = site_info.target;
  60. let id = undefined;
  61. if (site === "personal"){
  62. let name= await vscode.window.showInputBox({placeHolder: "Contest Name"});
  63. if (name === undefined){
  64. vscode.window.showErrorMessage("Name not provided.");
  65. return;
  66. }
  67. path = join(path, name);
  68. let probCountStr = await vscode.window.showInputBox({placeHolder: "Number of problems"});
  69. if (name === undefined){
  70. vscode.window.showErrorMessage("Number of problems not provided.");
  71. return;
  72. }
  73. id = probCountStr!;
  74. }
  75. else{
  76. // TODO: 008
  77. id = await vscode.window.showInputBox({placeHolder: "Contest ID"});
  78. if (id === undefined){
  79. vscode.window.showErrorMessage("Contest ID not provided.");
  80. return;
  81. }
  82. path = join(path, `${id}`);
  83. }
  84. await newContestFromId(path, site, id);
  85. vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(path));
  86. }
  87. async function debugTestcase(path: string, tcId: string){
  88. // Change editor layout to show failing test
  89. await vscode.commands.executeCommand("vscode.setEditorLayout", { orientation: 0, groups: [{ groups: [{}], size: 0.5 }, { groups: [{}, {}, {}], size: 0.5 }] });
  90. let sol = join(path, `sol.cpp`);
  91. let inp = join(path, TESTCASES, `${tcId}.in`);
  92. let out = join(path, TESTCASES, `${tcId}.out`);
  93. let cur = join(path, TESTCASES, `${tcId}.real`);
  94. await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(sol), vscode.ViewColumn.One);
  95. await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(inp), vscode.ViewColumn.Two);
  96. await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(out), vscode.ViewColumn.Three);
  97. // This file might not exist!
  98. if (existsSync(cur)){
  99. await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(cur), vscode.ViewColumn.Four);
  100. }
  101. }
  102. async function runSolution(){
  103. let path = currentProblem();
  104. if (path === undefined){
  105. vscode.window.showErrorMessage("No active problem");
  106. return;
  107. }
  108. let result = testSolution(path);
  109. if (result.status === Veredict.OK){
  110. vscode.window.showInformationMessage(`OK. Time ${result.maxTime!}ms`);
  111. }
  112. else{
  113. vscode.window.showErrorMessage(`${veredictName(result.status)} on test ${result.failTcId}`);
  114. debugTestcase(path, result.failTcId!);
  115. }
  116. }
  117. async function openTestcase() {
  118. let path = currentProblem();
  119. if (path === undefined){
  120. vscode.window.showErrorMessage("No active problem");
  121. return;
  122. }
  123. let tcs: any[] = [];
  124. // Read testcases
  125. readdirSync(join(path, TESTCASES)).
  126. filter( function (tcpath) {
  127. return extname(tcpath) === '.in';}).
  128. map( function(tcpath) {
  129. let name = removeExtension(tcpath);
  130. tcs.push({
  131. 'label' : name,
  132. 'target' : name,
  133. });
  134. });
  135. let tc = await vscode.window.showQuickPick(tcs, { placeHolder: 'Select testcase' });
  136. if (tc !== undefined){
  137. let inp = join(path, TESTCASES, `${tc.target}.in`);
  138. let out = join(path, TESTCASES, `${tc.target}.out`);
  139. await vscode.commands.executeCommand("vscode.setEditorLayout", { orientation: 0, groups: [{}, {}]});
  140. await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(inp), vscode.ViewColumn.One);
  141. await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(out), vscode.ViewColumn.Two);
  142. }
  143. }
  144. async function addTestcase() {
  145. let path = currentProblem();
  146. if (path === undefined){
  147. vscode.window.showErrorMessage("No active problem");
  148. return;
  149. }
  150. let index = 0;
  151. while (existsSync(join(path, TESTCASES, `${index}.hand.in`))){
  152. index += 1;
  153. }
  154. let inp = join(path, TESTCASES, `${index}.hand.in`);
  155. let out = join(path, TESTCASES, `${index}.hand.out`);
  156. writeFileSync(inp, "");
  157. writeFileSync(out, "");
  158. await vscode.commands.executeCommand("vscode.setEditorLayout", { orientation: 0, groups: [{}, {}]});
  159. await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(inp), vscode.ViewColumn.One);
  160. await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(out), vscode.ViewColumn.Two);
  161. }
  162. async function coding() {
  163. let path = currentProblem();
  164. if (path === undefined){
  165. vscode.window.showErrorMessage("No active problem");
  166. return;
  167. }
  168. await vscode.commands.executeCommand("vscode.setEditorLayout", { groups: [{}]});
  169. let sol = join(path, `sol.cpp`);
  170. await vscode.commands.executeCommand("vscode.open", vscode.Uri.file(sol), vscode.ViewColumn.One);
  171. }
  172. async function stress(){
  173. let path = currentProblem();
  174. if (path === undefined){
  175. vscode.window.showErrorMessage("No active problem");
  176. return;
  177. }
  178. let result = stressSolution(path);
  179. if (result.status === Veredict.OK){
  180. vscode.window.showInformationMessage(`OK. Time ${result.maxTime!}ms`);
  181. }
  182. else{
  183. vscode.window.showErrorMessage(`${veredictName(result.status)} on test ${result.failTcId}`);
  184. debugTestcase(path, result.failTcId!);
  185. }
  186. }
  187. async function upgrade(){
  188. let path = currentProblem();
  189. if (path === undefined){
  190. vscode.window.showErrorMessage("No active problem");
  191. return;
  192. }
  193. upgradeArena(path);
  194. }
  195. async function debugTest(){
  196. // let contest = await parseContest("1081");
  197. console.log("HEY");
  198. // await parseProblem("1081-E");
  199. }
  200. // this method is called when your extension is activated
  201. // your extension is activated the very first time the command is executed
  202. export function activate(context: vscode.ExtensionContext) {
  203. let addProblemCommand = vscode.commands.registerCommand('extension.addProblem', addProblem);
  204. let addContestCommand = vscode.commands.registerCommand('extension.addContest', addContest);
  205. let runSolutionCommand = vscode.commands.registerCommand('extension.runSolution', runSolution);
  206. let openTestcaseCommand = vscode.commands.registerCommand('extension.openTestcase', openTestcase);
  207. let addTestcaseCommand = vscode.commands.registerCommand('extension.addTestcase', addTestcase);
  208. let codingCommand = vscode.commands.registerCommand('extension.coding', coding);
  209. let stressCommand = vscode.commands.registerCommand('extension.stress', stress);
  210. let upgradeCommand = vscode.commands.registerCommand('extension.upgrade', upgrade);
  211. let debugTestCommand = vscode.commands.registerCommand('extension.debugTest', debugTest);
  212. context.subscriptions.push(addProblemCommand);
  213. context.subscriptions.push(addContestCommand);
  214. context.subscriptions.push(runSolutionCommand);
  215. context.subscriptions.push(openTestcaseCommand);
  216. context.subscriptions.push(addTestcaseCommand);
  217. context.subscriptions.push(codingCommand);
  218. context.subscriptions.push(stressCommand);
  219. context.subscriptions.push(upgradeCommand);
  220. context.subscriptions.push(debugTestCommand);
  221. }
  222. // this method is called when your extension is deactivated
  223. export function deactivate() {
  224. }