@jpetit/toolkit 3.0.4 → 3.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/package.json +11 -6
  2. package/toolkit/index.ts +18 -1
  3. package/.prettierignore +0 -11
  4. package/.prettierrc.json +0 -9
  5. package/.vscode/settings.json +0 -26
  6. package/assets.zip +0 -0
  7. package/eslint.config.mjs +0 -31
  8. package/lib/ai.ts +0 -138
  9. package/lib/assets.ts +0 -31
  10. package/lib/cleaner.ts +0 -58
  11. package/lib/compilers/_frompython.ts +0 -388
  12. package/lib/compilers/base.ts +0 -97
  13. package/lib/compilers/gcc.ts +0 -47
  14. package/lib/compilers/gxx.ts +0 -47
  15. package/lib/compilers/index.ts +0 -61
  16. package/lib/compilers/python3.ts +0 -67
  17. package/lib/data.ts +0 -19
  18. package/lib/doctor.ts +0 -104
  19. package/lib/generate.ts +0 -333
  20. package/lib/maker.ts +0 -535
  21. package/lib/settings.ts +0 -42
  22. package/lib/tui.ts +0 -69
  23. package/lib/utils.ts +0 -83
  24. package/problems/maxim2.pbm/Main.java +0 -13
  25. package/problems/maxim2.pbm/distillation.yml +0 -7
  26. package/problems/maxim2.pbm/distilled-01.inp +0 -1
  27. package/problems/maxim2.pbm/distilled-02.inp +0 -1
  28. package/problems/maxim2.pbm/distilled-03.inp +0 -1
  29. package/problems/maxim2.pbm/distiller.yml +0 -2
  30. package/problems/maxim2.pbm/generate-inputs.py +0 -9
  31. package/problems/maxim2.pbm/handler.yml +0 -2
  32. package/problems/maxim2.pbm/ma-1.inp +0 -1
  33. package/problems/maxim2.pbm/ma-2.inp +0 -1
  34. package/problems/maxim2.pbm/ma-3.inp +0 -1
  35. package/problems/maxim2.pbm/ma-4.inp +0 -1
  36. package/problems/maxim2.pbm/ma-5.inp +0 -1
  37. package/problems/maxim2.pbm/per-doubles.inp +0 -1
  38. package/problems/maxim2.pbm/problem.ca.html +0 -11
  39. package/problems/maxim2.pbm/problem.ca.md +0 -19
  40. package/problems/maxim2.pbm/problem.ca.tex +0 -17
  41. package/problems/maxim2.pbm/problem.ca.txt +0 -19
  42. package/problems/maxim2.pbm/problem.ca.yml +0 -3
  43. package/problems/maxim2.pbm/problem.en.html +0 -11
  44. package/problems/maxim2.pbm/problem.en.md +0 -19
  45. package/problems/maxim2.pbm/problem.en.tex +0 -16
  46. package/problems/maxim2.pbm/problem.en.txt +0 -19
  47. package/problems/maxim2.pbm/problem.en.yml +0 -4
  48. package/problems/maxim2.pbm/sample-1.inp +0 -1
  49. package/problems/maxim2.pbm/sample-2.inp +0 -1
  50. package/problems/maxim2.pbm/sample-3.inp +0 -1
  51. package/problems/maxim2.pbm/solution.c +0 -12
  52. package/problems/maxim2.pbm/solution.cc +0 -13
  53. package/problems/maxim2.pbm/solution.java +0 -13
  54. package/problems/maxim2.pbm/solution.pas +0 -9
  55. package/problems/maxim2.pbm/solution.py +0 -5
  56. package/problems/maxim2.pbm/tags.yml +0 -2
  57. package/problems/maxim2.pbm/test_-1_-1.inp +0 -1
  58. package/problems/maxim2.pbm/test_-1_-2.inp +0 -1
  59. package/problems/maxim2.pbm/test_-1_0.inp +0 -1
  60. package/problems/maxim2.pbm/test_-1_1.inp +0 -1
  61. package/problems/maxim2.pbm/test_-2_-1.inp +0 -1
  62. package/problems/maxim2.pbm/test_-2_-2.inp +0 -1
  63. package/problems/maxim2.pbm/test_-2_0.inp +0 -1
  64. package/problems/maxim2.pbm/test_-2_1.inp +0 -1
  65. package/problems/maxim2.pbm/test_0_-1.inp +0 -1
  66. package/problems/maxim2.pbm/test_0_-2.inp +0 -1
  67. package/problems/maxim2.pbm/test_0_0.inp +0 -1
  68. package/problems/maxim2.pbm/test_0_1.inp +0 -1
  69. package/problems/maxim2.pbm/test_1_-1.inp +0 -1
  70. package/problems/maxim2.pbm/test_1_-2.inp +0 -1
  71. package/problems/maxim2.pbm/test_1_0.inp +0 -1
  72. package/problems/maxim2.pbm/test_1_1.inp +0 -1
  73. package/test.ts +0 -3
  74. package/toolkit/ai.ts +0 -30
  75. package/toolkit/clean.ts +0 -19
  76. package/toolkit/compilers.ts +0 -29
  77. package/toolkit/create-jutge-ai.ts +0 -101
  78. package/toolkit/create-template.ts +0 -51
  79. package/toolkit/create-wizard.ts +0 -4
  80. package/toolkit/create.ts +0 -75
  81. package/toolkit/doctor.ts +0 -17
  82. package/toolkit/init.ts +0 -66
  83. package/toolkit/make.ts +0 -60
  84. package/toolkit/verify.ts +0 -19
  85. package/tsconfig.json +0 -38
  86. package/types/zip.d.ts +0 -4
@@ -1,388 +0,0 @@
1
- import { $ } from 'bun'
2
- import chalk from 'chalk'
3
- import { access, copyFile, mkdir, readFile, rename, rm, unlink, writeFile } from 'fs/promises'
4
-
5
- // Constants
6
- const MAX_COMPILATION_TIME = 30000 // 30 seconds in milliseconds
7
-
8
- // Custom Errors
9
- export class CompilationTooLongError extends Error {
10
- constructor() {
11
- super('Compilation time exceeded')
12
- this.name = 'CompilationTooLongError'
13
- }
14
- }
15
-
16
- export class ExecutionError extends Error {
17
- constructor(message: string) {
18
- super(message)
19
- this.name = 'ExecutionError'
20
- }
21
- }
22
-
23
- export class CompilationError extends Error {
24
- constructor(message: string) {
25
- super(message)
26
- this.name = 'CompilationError'
27
- }
28
- }
29
-
30
- interface CompilerInfo {
31
- compiler_id: string
32
- name: string
33
- language: string
34
- version: string
35
- flags1: string
36
- flags2: string
37
- extension: string
38
- type: string
39
- warning: string
40
- }
41
-
42
- interface Handler {
43
- source_modifier?: string
44
- [key: string]: any
45
- }
46
-
47
- const compilersList: Record<string, typeof Compiler> = {}
48
-
49
- function compiler(baseClass: typeof Compiler) {
50
- return function <T extends typeof Compiler>(derivedClass: T) {
51
- compilersList[derivedClass.name] = derivedClass
52
- return derivedClass
53
- }
54
- }
55
-
56
- export abstract class Compiler {
57
- protected handler: Handler
58
- protected _name: string
59
- static availableCompilers: string[] = []
60
-
61
- constructor(handler: Handler | null, name: string | null) {
62
- this.handler = handler || {}
63
- this._name = name || ''
64
- }
65
-
66
- abstract name(): string
67
- abstract type(): string
68
- abstract executable(): string
69
- abstract language(): string
70
- abstract version(): Promise<string>
71
- abstract flags1(): string
72
- abstract flags2(): string
73
- abstract extension(): string
74
- abstract compile(): Promise<boolean>
75
- abstract execute(tst: string, correct: boolean, iterations?: number): Promise<number>
76
-
77
- id(): string {
78
- return this.constructor.name.replace('Compiler_', '').replace('XX', '++')
79
- }
80
-
81
- warning(): string {
82
- return ''
83
- }
84
-
85
- async prepareExecution(ori: string): Promise<void> {
86
- // Override in subclasses if needed
87
- }
88
-
89
- protected async executeCompiler(cmd: string): Promise<void> {
90
- console.log(chalk.dim(cmd))
91
-
92
- return new Promise((resolve, reject) => {
93
- const startTime = Date.now()
94
- const proc = Bun.spawn(cmd.split(' '), {
95
- stdout: 'pipe',
96
- stderr: 'pipe',
97
- })
98
-
99
- let output = ''
100
- let hasError = false
101
-
102
- const timeout = setTimeout(() => {
103
- proc.kill()
104
- console.log(chalk.bold.red('Compilation time exceeded!'))
105
- reject(new CompilationTooLongError())
106
- }, MAX_COMPILATION_TIME)
107
-
108
- ;(async () => {
109
- try {
110
- const [stdout, stderr] = await Promise.all([
111
- new Response(proc.stdout).text(),
112
- new Response(proc.stderr).text(),
113
- ])
114
-
115
- output = stdout + stderr
116
- if (stderr.length > 0) {
117
- hasError = true
118
- }
119
-
120
- const exitCode = await proc.exited
121
- clearTimeout(timeout)
122
-
123
- if (exitCode !== 0 || hasError || output.length > 0) {
124
- if (output.length > 0) {
125
- console.log('\n' + output.trim() + '\n')
126
- }
127
- console.log(
128
- chalk.bold.red('Compilation error! ') +
129
- chalk.normal(`Please check ${this._name}.${this.extension()} and try again.`),
130
- )
131
- reject(new CompilationError('Compilation failed'))
132
- } else {
133
- resolve()
134
- }
135
- } catch (error) {
136
- clearTimeout(timeout)
137
- reject(error)
138
- }
139
- })()
140
- })
141
- }
142
-
143
- protected async getVersion(cmd: string, lineIndex: number): Promise<string> {
144
- try {
145
- const proc = Bun.spawn(cmd.split(' '), {
146
- stdout: 'pipe',
147
- stderr: 'pipe',
148
- })
149
-
150
- const stdout = await new Response(proc.stdout).text()
151
- const lines = stdout.split('\n')
152
- return lines[lineIndex]?.trim() || 'Unknown version'
153
- } catch {
154
- return 'not found'
155
- }
156
- }
157
-
158
- info(): CompilerInfo {
159
- return {
160
- compiler_id: this.id(),
161
- name: this._name,
162
- language: this.language(),
163
- version: '', // Will be populated asynchronously
164
- flags1: this.flags1(),
165
- flags2: this.flags2(),
166
- extension: this.extension(),
167
- type: this.type(),
168
- warning: this.warning(),
169
- }
170
- }
171
-
172
- protected async timeExecution(cmd: string, iterations: number = 1): Promise<number> {
173
- const start = Date.now()
174
- for (let i = 0; i < iterations; i++) {
175
- await $`sh -c ${cmd}`.quiet()
176
- }
177
- const end = Date.now()
178
- return (end - start) / iterations / 1000 // Return in seconds
179
- }
180
- }
181
-
182
- // Python3 Compiler
183
- export class Compiler_Python3 extends Compiler {
184
- name(): string {
185
- return 'Python3'
186
- }
187
-
188
- type(): string {
189
- return 'interpreter'
190
- }
191
-
192
- executable(): string {
193
- return `${this._name}.py`
194
- }
195
-
196
- language(): string {
197
- return 'Python'
198
- }
199
-
200
- async version(): Promise<string> {
201
- return await this.getVersion('python3 -V', 0)
202
- }
203
-
204
- flags1(): string {
205
- return ''
206
- }
207
-
208
- flags2(): string {
209
- return ''
210
- }
211
-
212
- extension(): string {
213
- return 'py'
214
- }
215
-
216
- private async genWrapper(): Promise<void> {
217
- await Util.writeFile(
218
- 'py3c.py',
219
- `#!/usr/bin/python3
220
-
221
- import py_compile, sys
222
-
223
- py_compile.compile(sys.argv[1])`,
224
- )
225
- }
226
-
227
- private async delWrapper(): Promise<void> {
228
- await Util.delFile('py3c.py')
229
- }
230
-
231
- async execute(tst: string, correct: boolean, iterations: number = 1): Promise<number> {
232
- let exec = this.executable()
233
-
234
- if (this.handler.source_modifier === 'no_main' || this.handler.source_modifier === 'structs') {
235
- await Util.copyFile(`${this._name}.py`, 'modified.py')
236
- const ori = await Util.readFile(`${this._name}.py`)
237
- const main = await Util.readFile('main.py')
238
- await Util.writeFile('modified.py', `${ori}\n${main}\n`)
239
- exec = 'modified.py'
240
- }
241
-
242
- const ext = correct ? 'cor' : 'py.out'
243
- const cmd = `python3 ${exec} < ${tst}.inp > ${tst}.${ext}`
244
-
245
- if (correct) {
246
- process.stdout.write(cmd)
247
- }
248
-
249
- const time = await this.timeExecution(cmd, iterations)
250
-
251
- await Util.delFile('modified.py')
252
- await Util.delDir('__pycache__')
253
-
254
- return time
255
- }
256
-
257
- async compile(): Promise<boolean> {
258
- if (this.handler.source_modifier === 'no_main' || this.handler.source_modifier === 'structs') {
259
- return await this.compileNoMain()
260
- } else {
261
- return await this.compileNormal()
262
- }
263
- }
264
-
265
- private async compileNormal(): Promise<boolean> {
266
- try {
267
- await this.genWrapper()
268
- const code = await Util.readFile(`${this._name}.py`)
269
- await Util.writeFile(`${this._name}.py`, code)
270
- await this.executeCompiler(`python3 py3c.py ${this._name}.py 1> /dev/null`)
271
- } catch (error) {
272
- if (error instanceof CompilationTooLongError) {
273
- console.log(chalk.bold.red('Compilation time exceeded!'))
274
- }
275
- return false
276
- } finally {
277
- await this.delWrapper()
278
- }
279
- return true
280
- }
281
-
282
- private async compileNoMain(): Promise<boolean> {
283
- if (!(await this.compileNormal())) {
284
- return false
285
- }
286
-
287
- await Util.copyFile(`${this._name}.py`, 'modified.py')
288
- const ori = await Util.readFile(`${this._name}.py`)
289
- const main = await Util.readFile('main.py')
290
- await Util.writeFile('modified.py', `${ori}\n${main}\n`)
291
-
292
- try {
293
- await this.genWrapper()
294
- await this.executeCompiler('python3 py3c.py modified.py 1> /dev/null')
295
- } catch (error) {
296
- if (error instanceof CompilationTooLongError) {
297
- console.log(chalk.bold.red('Compilation time exceeded!'))
298
- }
299
- return false
300
- } finally {
301
- await this.delWrapper()
302
- }
303
- return true
304
- }
305
- }
306
-
307
- // Compiler registry
308
- const COMPILERS = ['GCC', 'GXX', 'Python3']
309
-
310
- export function getCompiler(cpl: string, handler: Handler | null = null, name: string | null = null): Compiler {
311
- const compilerClass = cpl.replace('++', 'XX')
312
-
313
- switch (compilerClass) {
314
- case 'GCC':
315
- return new Compiler_GCC(handler, name)
316
- case 'GXX':
317
- return new Compiler_GXX(handler, name)
318
- case 'Python3':
319
- return new Compiler_Python3(handler, name)
320
- default:
321
- throw new Error(`Unknown compiler: ${cpl}`)
322
- }
323
- }
324
-
325
- export async function getCompilerExtensions(handlerCompiler: string): Promise<Record<string, string>> {
326
- const result: Record<string, string> = {}
327
-
328
- for (const compilerName of COMPILERS) {
329
- const compiler = getCompiler(compilerName)
330
- const ext = compiler.extension()
331
-
332
- if (compilerName === handlerCompiler) {
333
- result[ext] = compilerName
334
- } else if (!compilerName.includes('Run') && !(ext in result)) {
335
- result[ext] = compilerName
336
- }
337
- }
338
-
339
- return result
340
- }
341
-
342
- export async function getAvailableCompilers(): Promise<string[]> {
343
- const available: string[] = []
344
-
345
- for (const compilerName of COMPILERS) {
346
- const compiler = getCompiler(compilerName)
347
- const version = await compiler.version()
348
-
349
- if (!version.includes('not found')) {
350
- available.push(compilerName)
351
- }
352
- }
353
-
354
- return available
355
- }
356
-
357
- export async function printAvailableCompilers(): Promise<void> {
358
- const available = await getAvailableCompilers()
359
-
360
- if (available.length > 0) {
361
- process.stdout.write('Available compilers: ')
362
-
363
- for (let i = 0; i < available.length; i++) {
364
- process.stdout.write(available[i])
365
-
366
- if (i === available.length - 2) {
367
- process.stdout.write(' and ')
368
- } else if (i !== available.length - 1) {
369
- process.stdout.write(', ')
370
- }
371
- }
372
-
373
- console.log()
374
- }
375
- }
376
-
377
- export async function getCompilerInfo(): Promise<Record<string, CompilerInfo>> {
378
- const result: Record<string, CompilerInfo> = {}
379
-
380
- for (const compilerName of COMPILERS) {
381
- const compiler = getCompiler(compilerName)
382
- const info = compiler.info()
383
- info.version = await compiler.version()
384
- result[compilerName] = info
385
- }
386
-
387
- return result
388
- }
@@ -1,97 +0,0 @@
1
- import { rm, exists } from 'fs/promises'
2
- import { join, sep } from 'path'
3
- import * as tui from '@/lib/tui'
4
-
5
- export type CompilerInfo = {
6
- compiler_id: string
7
- name: string
8
- language: string
9
- version: string
10
- flags1: string
11
- flags2: string
12
- extension: string
13
- type: string
14
- warning: string
15
- }
16
-
17
- export abstract class Compiler {
18
- abstract id(): string
19
-
20
- abstract name(): string
21
-
22
- abstract type(): string
23
-
24
- abstract language(): string
25
-
26
- abstract version(): Promise<string>
27
-
28
- abstract flags1(): string
29
-
30
- abstract flags2(): string
31
-
32
- abstract extension(): string
33
-
34
- warning(): string {
35
- return ''
36
- }
37
-
38
- async available(): Promise<boolean> {
39
- const version = await this.version()
40
- return version !== 'not found'
41
- }
42
-
43
- async info(): Promise<CompilerInfo> {
44
- return {
45
- compiler_id: this.id(),
46
- name: this.name(),
47
- language: this.language(),
48
- version: await this.version(),
49
- flags1: this.flags1(),
50
- flags2: this.flags2(),
51
- extension: this.extension(),
52
- type: this.type(),
53
- warning: this.warning(),
54
- }
55
- }
56
-
57
- abstract compile(directory: string, sourcePath: string): Promise<void>
58
-
59
- // Default implementation of execute for compiled languages
60
- async execute(directory: string, inputPath: string, outputPath: string): Promise<void> {
61
- const executablePath = `solution.${this.extension()}.exe`
62
- if (!(await exists(join(directory, executablePath)))) {
63
- throw new Error(`Executable file ${executablePath} does not exist in directory ${directory}`)
64
- }
65
- // TODO: check in windows
66
- const relativeExecutablePath = `.${sep}${executablePath}` // force prepending ./ to make it work
67
- const fullInputPath = join(directory, inputPath)
68
- const fullOutputPath = join(directory, outputPath)
69
- await rm(fullOutputPath, { force: true })
70
- tui.command(`${relativeExecutablePath} < ${inputPath} > ${outputPath}`)
71
- const proc = Bun.spawn([relativeExecutablePath], {
72
- cwd: directory,
73
- stdin: Bun.file(fullInputPath),
74
- stdout: Bun.file(fullOutputPath),
75
- stderr: 'inherit',
76
- })
77
- await proc.exited
78
- const exitCode = proc.exitCode
79
-
80
- if (exitCode !== 0) throw new Error(`Execution failed for ${executablePath} with exit code ${exitCode}`)
81
- }
82
-
83
- protected async getVersion(cmd: string, lineIndex: number): Promise<string> {
84
- try {
85
- const proc = Bun.spawn(cmd.split(' '), {
86
- stdout: 'pipe',
87
- stderr: 'pipe',
88
- })
89
-
90
- const stdout = await new Response(proc.stdout).text()
91
- const lines = stdout.split('\n')
92
- return lines[lineIndex]?.trim() || 'Unknown version'
93
- } catch {
94
- return 'not found'
95
- }
96
- }
97
- }
@@ -1,47 +0,0 @@
1
- import * as tui from '@/lib/tui.js'
2
- import { Compiler } from './base'
3
- import { rm, exists } from 'fs/promises'
4
- import { join } from 'path'
5
-
6
- export class Compiler_GCC extends Compiler {
7
- id(): string {
8
- return 'GCC'
9
- }
10
-
11
- name(): string {
12
- return 'GNU C Compiler'
13
- }
14
-
15
- type(): string {
16
- return 'compiler'
17
- }
18
-
19
- language(): string {
20
- return 'C'
21
- }
22
-
23
- async version(): Promise<string> {
24
- return await this.getVersion('gcc --version', 0)
25
- }
26
-
27
- flags1(): string {
28
- return '-D_JUDGE_ -O2 -DNDEBUG -Wall -Wextra -Wno-sign-compare'
29
- }
30
-
31
- flags2(): string {
32
- return ''
33
- }
34
-
35
- extension(): string {
36
- return 'c'
37
- }
38
-
39
- async compile(directory: string, sourcePath: string): Promise<void> {
40
- const outputPath = sourcePath + '.exe'
41
- const fullOutputPath = join(directory, outputPath)
42
- await rm(fullOutputPath, { force: true })
43
- tui.command(`gcc ${this.flags1()} ${sourcePath} -o ${outputPath}`)
44
- await Bun.$`gcc ${this.flags1().split(' ')} ${sourcePath} -o ${outputPath}`.cwd(directory).nothrow()
45
- if (!(await exists(fullOutputPath))) throw new Error(`Compilation failed for ${sourcePath}`)
46
- }
47
- }
@@ -1,47 +0,0 @@
1
- import { rm, exists } from 'fs/promises'
2
- import { Compiler } from './base'
3
- import chalk from 'chalk'
4
- import { join } from 'path'
5
-
6
- export class Compiler_GXX extends Compiler {
7
- id(): string {
8
- return 'GXX'
9
- }
10
-
11
- name(): string {
12
- return 'GNU C++ Compiler'
13
- }
14
-
15
- type(): string {
16
- return 'compiler'
17
- }
18
-
19
- language(): string {
20
- return 'C++'
21
- }
22
-
23
- async version(): Promise<string> {
24
- return await this.getVersion('g++ --version', 0)
25
- }
26
-
27
- flags1(): string {
28
- return '-std=c++11 -D_JUDGE_ -O2 -DNDEBUG -Wall -Wextra -Wno-sign-compare -Wshadow'
29
- }
30
-
31
- flags2(): string {
32
- return '-std=c++11 -D_JUDGE_ -O2 -DNDEBUG -Wall -Wextra -Wno-sign-compare -Wshadow'
33
- }
34
-
35
- extension(): string {
36
- return 'cc'
37
- }
38
-
39
- async compile(directory: string, sourcePath: string): Promise<void> {
40
- const outputPath = sourcePath + '.exe'
41
- const fullOutputPath = join(directory, outputPath)
42
- await rm(fullOutputPath, { force: true })
43
- console.log(chalk.magenta(`❯ g++ ${this.flags1()} ${sourcePath} -o ${outputPath}`))
44
- await Bun.$`g++ ${this.flags1().split(' ')} ${sourcePath} -o ${outputPath}`.cwd(directory).nothrow()
45
- if (!(await exists(fullOutputPath))) throw new Error(`Compilation failed for ${sourcePath}`)
46
- }
47
- }
@@ -1,61 +0,0 @@
1
- import { Compiler, type CompilerInfo } from './base'
2
- import { Compiler_GCC } from './gcc'
3
- import { Compiler_GXX } from './gxx'
4
- import { Compiler_Python3 } from './python3'
5
-
6
- const compilersRegistryById: Record<string, new () => Compiler> = {
7
- C: Compiler_GCC,
8
- 'C++': Compiler_GXX,
9
- Python3: Compiler_Python3,
10
- }
11
-
12
- const compilersRegistryByExtension: Record<string, new () => Compiler> = {
13
- c: Compiler_GCC,
14
- cc: Compiler_GXX,
15
- py: Compiler_Python3,
16
- }
17
-
18
- export function getCompilerById(id: string): Compiler {
19
- const CompilerClass = compilersRegistryById[id]
20
- if (!CompilerClass) throw new Error(`Compiler '${id}' is not defined`)
21
- const compilerInstance = new CompilerClass()
22
- return compilerInstance
23
- }
24
-
25
- export function getCompilerByExtension(extension: string): Compiler {
26
- const CompilerClass = compilersRegistryByExtension[extension]
27
- if (!CompilerClass) throw new Error(`No compiler defined for extension '.${extension}'`)
28
- const compilerInstance = new CompilerClass()
29
- return compilerInstance
30
- }
31
-
32
- export async function getDefinedCompilerIds(): Promise<string[]> {
33
- await Bun.sleep(0) // to make function async
34
- return Object.keys(compilersRegistryById)
35
- }
36
-
37
- export async function getAvailableCompilers(): Promise<string[]> {
38
- const available: string[] = []
39
- for (const id of Object.keys(compilersRegistryById)) {
40
- const CompilerClass = compilersRegistryById[id]!
41
- const compilerInstance = new CompilerClass()
42
- if (await compilerInstance.available()) {
43
- available.push(id)
44
- }
45
- }
46
- return available
47
- }
48
-
49
- export async function getCompilerInfo(id: string): Promise<CompilerInfo> {
50
- const compilerInstance = getCompilerById(id)
51
- if (!compilerInstance) throw new Error(`Compiler '${id}' is not defined`)
52
- return await compilerInstance.info()
53
- }
54
-
55
- export async function getCompilersInfo(): Promise<Record<string, CompilerInfo>> {
56
- const infos: Record<string, CompilerInfo> = {}
57
- for (const id of Object.keys(compilersRegistryById)) {
58
- infos[id] = await getCompilerInfo(id)
59
- }
60
- return infos
61
- }
@@ -1,67 +0,0 @@
1
- import * as tui from '@/lib/tui.js'
2
- import { exists, rm } from 'fs/promises'
3
- import { join } from 'path'
4
- import { Compiler } from './base'
5
-
6
- export class Compiler_Python3 extends Compiler {
7
- id(): string {
8
- return 'Python3'
9
- }
10
-
11
- name(): string {
12
- return 'Python3'
13
- }
14
-
15
- type(): string {
16
- return 'interpreter'
17
- }
18
-
19
- language(): string {
20
- return 'Python'
21
- }
22
-
23
- async version(): Promise<string> {
24
- return await this.getVersion('python3 --version', 0)
25
- }
26
-
27
- flags1(): string {
28
- return ''
29
- }
30
-
31
- flags2(): string {
32
- return ''
33
- }
34
-
35
- extension(): string {
36
- return 'py'
37
- }
38
-
39
- async compile(directory: string, sourcePath: string): Promise<void> {
40
- tui.command(`python3 -m py_compile ${sourcePath}`)
41
- console.log('directory:', directory, 'sourcePath:', sourcePath)
42
- const { exitCode } = await Bun.$`python3 -m py_compile ${sourcePath}`.cwd(directory).nothrow()
43
- if (exitCode !== 0) throw new Error(`Compilation failed for ${sourcePath}`)
44
- }
45
-
46
- override async execute(directory: string, inputPath: string, outputPath: string): Promise<void> {
47
- const sourcePath = 'solution.py'
48
- if (!(await exists(join(directory, sourcePath)))) {
49
- throw new Error(`Source file ${sourcePath} does not exist in directory ${directory}`)
50
- }
51
- const fullInputPath = join(directory, inputPath)
52
- const fullOutputPath = join(directory, outputPath)
53
- await rm(fullOutputPath, { force: true })
54
- tui.command(`python3 ${sourcePath} < ${inputPath} > ${outputPath}`)
55
-
56
- const proc = Bun.spawn(['python3', sourcePath], {
57
- cwd: directory,
58
- stdin: Bun.file(fullInputPath),
59
- stdout: Bun.file(fullOutputPath),
60
- stderr: 'inherit',
61
- })
62
- await proc.exited
63
- const exitCode = proc.exitCode
64
-
65
- if (exitCode !== 0) throw new Error(`Execution failed for ${sourcePath}`)
66
- }
67
- }