feat: context, not config
This commit is contained in:
parent
a0171ee81e
commit
9e84d57b8a
15 changed files with 209 additions and 328 deletions
|
|
@ -203,17 +203,22 @@ local function format_output(exec_result, expected_file, is_debug)
|
|||
return table.concat(output_lines, '') .. '\n' .. table.concat(metadata_lines, '\n')
|
||||
end
|
||||
|
||||
---@param ctx ProblemContext
|
||||
---@param contest_config ContestConfig
|
||||
---@param is_debug? boolean
|
||||
---@return {success: boolean, output: string?}
|
||||
function M.compile_problem(ctx, contest_config, is_debug)
|
||||
function M.compile_problem(contest_config, is_debug)
|
||||
vim.validate({
|
||||
ctx = { ctx, 'table' },
|
||||
contest_config = { contest_config, 'table' },
|
||||
})
|
||||
|
||||
local language = get_language_from_file(ctx.source_file, contest_config)
|
||||
local state = require('cp.state')
|
||||
local source_file = state.get_source_file()
|
||||
if not source_file then
|
||||
logger.log('No source file found', vim.log.levels.ERROR)
|
||||
return { success = false, output = 'No source file found' }
|
||||
end
|
||||
|
||||
local language = get_language_from_file(source_file, contest_config)
|
||||
local language_config = contest_config[language]
|
||||
|
||||
if not language_config then
|
||||
|
|
@ -221,9 +226,10 @@ function M.compile_problem(ctx, contest_config, is_debug)
|
|||
return { success = false, output = 'No configuration for language: ' .. language }
|
||||
end
|
||||
|
||||
local binary_file = state.get_binary_file()
|
||||
local substitutions = {
|
||||
source = ctx.source_file,
|
||||
binary = ctx.binary_file,
|
||||
source = source_file,
|
||||
binary = binary_file,
|
||||
version = tostring(language_config.version),
|
||||
}
|
||||
|
||||
|
|
@ -244,26 +250,35 @@ function M.compile_problem(ctx, contest_config, is_debug)
|
|||
return { success = true, output = nil }
|
||||
end
|
||||
|
||||
function M.run_problem(ctx, contest_config, is_debug)
|
||||
function M.run_problem(contest_config, is_debug)
|
||||
vim.validate({
|
||||
ctx = { ctx, 'table' },
|
||||
contest_config = { contest_config, 'table' },
|
||||
is_debug = { is_debug, 'boolean' },
|
||||
})
|
||||
|
||||
vim.system({ 'mkdir', '-p', 'build', 'io' }):wait()
|
||||
local state = require('cp.state')
|
||||
local source_file = state.get_source_file()
|
||||
local output_file = state.get_output_file()
|
||||
|
||||
local language = get_language_from_file(ctx.source_file, contest_config)
|
||||
local language_config = contest_config[language]
|
||||
|
||||
if not language_config then
|
||||
vim.fn.writefile({ 'Error: No configuration for language: ' .. language }, ctx.output_file)
|
||||
if not source_file or not output_file then
|
||||
logger.log('Missing required file paths', vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
vim.system({ 'mkdir', '-p', 'build', 'io' }):wait()
|
||||
|
||||
local language = get_language_from_file(source_file, contest_config)
|
||||
local language_config = contest_config[language]
|
||||
|
||||
if not language_config then
|
||||
vim.fn.writefile({ 'Error: No configuration for language: ' .. language }, output_file)
|
||||
return
|
||||
end
|
||||
|
||||
local binary_file = state.get_binary_file()
|
||||
local substitutions = {
|
||||
source = ctx.source_file,
|
||||
binary = ctx.binary_file,
|
||||
source = source_file,
|
||||
binary = binary_file,
|
||||
version = tostring(language_config.version),
|
||||
}
|
||||
|
||||
|
|
@ -271,26 +286,31 @@ function M.run_problem(ctx, contest_config, is_debug)
|
|||
if compile_cmd then
|
||||
local compile_result = M.compile_generic(language_config, substitutions)
|
||||
if compile_result.code ~= 0 then
|
||||
vim.fn.writefile({ compile_result.stderr }, ctx.output_file)
|
||||
vim.fn.writefile({ compile_result.stderr }, output_file)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local input_file = state.get_input_file()
|
||||
local input_data = ''
|
||||
if vim.fn.filereadable(ctx.input_file) == 1 then
|
||||
input_data = table.concat(vim.fn.readfile(ctx.input_file), '\n') .. '\n'
|
||||
if input_file and vim.fn.filereadable(input_file) == 1 then
|
||||
input_data = table.concat(vim.fn.readfile(input_file), '\n') .. '\n'
|
||||
end
|
||||
|
||||
local cache = require('cp.cache')
|
||||
cache.load()
|
||||
local timeout_ms, _ = cache.get_constraints(ctx.contest, ctx.contest_id, ctx.problem_id)
|
||||
local platform = state.get_platform()
|
||||
local contest_id = state.get_contest_id()
|
||||
local problem_id = state.get_problem_id()
|
||||
local timeout_ms, _ = cache.get_constraints(platform, contest_id, problem_id)
|
||||
timeout_ms = timeout_ms or 2000
|
||||
|
||||
local run_cmd = build_command(language_config.test, language_config.executable, substitutions)
|
||||
local exec_result = execute_command(run_cmd, input_data, timeout_ms)
|
||||
local formatted_output = format_output(exec_result, ctx.expected_file, is_debug)
|
||||
local expected_file = state.get_expected_file()
|
||||
local formatted_output = format_output(exec_result, expected_file, is_debug)
|
||||
|
||||
local output_buf = vim.fn.bufnr(ctx.output_file)
|
||||
local output_buf = vim.fn.bufnr(output_file)
|
||||
if output_buf ~= -1 then
|
||||
local was_modifiable = vim.api.nvim_get_option_value('modifiable', { buf = output_buf })
|
||||
local was_readonly = vim.api.nvim_get_option_value('readonly', { buf = output_buf })
|
||||
|
|
@ -303,7 +323,7 @@ function M.run_problem(ctx, contest_config, is_debug)
|
|||
vim.cmd.write()
|
||||
end)
|
||||
else
|
||||
vim.fn.writefile(vim.split(formatted_output, '\n'), ctx.output_file)
|
||||
vim.fn.writefile(vim.split(formatted_output, '\n'), output_file)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -130,12 +130,22 @@ local function load_constraints_from_cache(platform, contest_id, problem_id)
|
|||
return nil
|
||||
end
|
||||
|
||||
---@param ctx ProblemContext
|
||||
---@param contest_config ContestConfig
|
||||
---@param test_case TestCase
|
||||
---@return table
|
||||
local function run_single_test_case(ctx, contest_config, cp_config, test_case)
|
||||
local language = vim.fn.fnamemodify(ctx.source_file, ':e')
|
||||
local function run_single_test_case(contest_config, cp_config, test_case)
|
||||
local state = require('cp.state')
|
||||
local source_file = state.get_source_file()
|
||||
if not source_file then
|
||||
return {
|
||||
status = 'fail',
|
||||
actual = '',
|
||||
error = 'No source file found',
|
||||
time_ms = 0,
|
||||
}
|
||||
end
|
||||
|
||||
local language = vim.fn.fnamemodify(source_file, ':e')
|
||||
local language_name = constants.filetype_to_language[language] or contest_config.default_language
|
||||
local language_config = contest_config[language_name]
|
||||
|
||||
|
|
@ -168,13 +178,14 @@ local function run_single_test_case(ctx, contest_config, cp_config, test_case)
|
|||
return cmd
|
||||
end
|
||||
|
||||
local binary_file = state.get_binary_file()
|
||||
local substitutions = {
|
||||
source = ctx.source_file,
|
||||
binary = ctx.binary_file,
|
||||
source = source_file,
|
||||
binary = binary_file,
|
||||
version = tostring(language_config.version or ''),
|
||||
}
|
||||
|
||||
if language_config.compile and vim.fn.filereadable(ctx.binary_file) == 0 then
|
||||
if language_config.compile and vim.fn.filereadable(binary_file) == 0 then
|
||||
logger.log('binary not found, compiling first...')
|
||||
local compile_cmd = substitute_template(language_config.compile, substitutions)
|
||||
local redirected_cmd = vim.deepcopy(compile_cmd)
|
||||
|
|
@ -282,10 +293,9 @@ local function run_single_test_case(ctx, contest_config, cp_config, test_case)
|
|||
}
|
||||
end
|
||||
|
||||
---@param ctx ProblemContext
|
||||
---@param state table
|
||||
---@return boolean
|
||||
function M.load_test_cases(ctx, state)
|
||||
function M.load_test_cases(state)
|
||||
local test_cases = parse_test_cases_from_cache(
|
||||
state.get_platform() or '',
|
||||
state.get_contest_id() or '',
|
||||
|
|
@ -293,7 +303,9 @@ function M.load_test_cases(ctx, state)
|
|||
)
|
||||
|
||||
if #test_cases == 0 then
|
||||
test_cases = parse_test_cases_from_files(ctx.input_file, ctx.expected_file)
|
||||
local input_file = state.get_input_file()
|
||||
local expected_file = state.get_expected_file()
|
||||
test_cases = parse_test_cases_from_files(input_file, expected_file)
|
||||
end
|
||||
|
||||
run_panel_state.test_cases = test_cases
|
||||
|
|
@ -315,11 +327,10 @@ function M.load_test_cases(ctx, state)
|
|||
return #test_cases > 0
|
||||
end
|
||||
|
||||
---@param ctx ProblemContext
|
||||
---@param contest_config ContestConfig
|
||||
---@param index number
|
||||
---@return boolean
|
||||
function M.run_test_case(ctx, contest_config, cp_config, index)
|
||||
function M.run_test_case(contest_config, cp_config, index)
|
||||
local test_case = run_panel_state.test_cases[index]
|
||||
if not test_case then
|
||||
return false
|
||||
|
|
@ -327,7 +338,7 @@ function M.run_test_case(ctx, contest_config, cp_config, index)
|
|||
|
||||
test_case.status = 'running'
|
||||
|
||||
local result = run_single_test_case(ctx, contest_config, cp_config, test_case)
|
||||
local result = run_single_test_case(contest_config, cp_config, test_case)
|
||||
|
||||
test_case.status = result.status
|
||||
test_case.actual = result.actual
|
||||
|
|
@ -343,13 +354,13 @@ function M.run_test_case(ctx, contest_config, cp_config, index)
|
|||
return true
|
||||
end
|
||||
|
||||
---@param ctx ProblemContext
|
||||
---@param contest_config ContestConfig
|
||||
---@param cp_config cp.Config
|
||||
---@return TestCase[]
|
||||
function M.run_all_test_cases(ctx, contest_config, cp_config)
|
||||
function M.run_all_test_cases(contest_config, cp_config)
|
||||
local results = {}
|
||||
for i, _ in ipairs(run_panel_state.test_cases) do
|
||||
M.run_test_case(ctx, contest_config, cp_config, i)
|
||||
M.run_test_case(contest_config, cp_config, i)
|
||||
table.insert(results, run_panel_state.test_cases[i])
|
||||
end
|
||||
return results
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue