feat: atcoder scraper update for :CP test

This commit is contained in:
Barrett Ruth 2025-09-15 18:31:26 -04:00
parent 0fb247f18b
commit c99cf8d4f0
5 changed files with 104 additions and 29 deletions

View file

@ -206,11 +206,24 @@ local function toggle_test_panel()
return
end
if state.platform == "codeforces" then
logger.log("test panel not yet supported for codeforces", vim.log.levels.ERROR)
return
end
local problem_id = get_current_problem()
if not problem_id then
return
end
local ctx = problem.create_context(state.platform, state.contest_id, state.problem_id, config)
local test_module = require("cp.test")
if not test_module.load_test_cases(ctx, state) then
logger.log("no test cases found", vim.log.levels.WARN)
return
end
state.saved_session = vim.fn.tempname()
vim.cmd(("mksession! %s"):format(state.saved_session))
@ -221,24 +234,59 @@ local function toggle_test_panel()
vim.bo.filetype = "cptest"
vim.bo.bufhidden = "wipe"
local test_lines = {
" 1 ✓ PASS 12ms",
" 2 ✗ FAIL 45ms",
"> 3 ✓ PASS 8ms",
" 4 ? PENDING",
"",
"── Test 3 ──",
"Input: │ Expected: │ Actual:",
"5 3 │ 8 │ 8",
"",
"j/k: navigate <space>: toggle <enter>: run q: quit",
}
local test_state = test_module.get_test_panel_state()
local test_lines = {}
for i, test_case in ipairs(test_state.test_cases) do
local status_icon = "?"
local status_text = "PENDING"
if test_case.status == "pass" then
status_icon = ""
status_text = "PASS"
elseif test_case.status == "fail" then
status_icon = ""
status_text = "FAIL"
end
local time_text = test_case.time_ms and string.format("%.0fms", test_case.time_ms) or ""
local prefix = i == test_state.current_index and "> " or " "
table.insert(test_lines, string.format("%s%d %s %s %s",
prefix, i, status_icon, status_text, time_text))
end
table.insert(test_lines, "")
local current_test = test_state.test_cases[test_state.current_index]
if current_test then
table.insert(test_lines, string.format("── Test %d ──", test_state.current_index))
table.insert(test_lines, "Input:")
for line in current_test.input:gmatch("[^\n]*") do
table.insert(test_lines, " " .. line)
end
table.insert(test_lines, "Expected:")
for line in current_test.expected:gmatch("[^\n]*") do
table.insert(test_lines, " " .. line)
end
if current_test.actual then
table.insert(test_lines, "Actual:")
for line in current_test.actual:gmatch("[^\n]*") do
table.insert(test_lines, " " .. line)
end
end
end
table.insert(test_lines, "")
table.insert(test_lines, "j/k: navigate <space>: toggle <enter>: run q: quit")
vim.api.nvim_buf_set_lines(test_buf, 0, -1, false, test_lines)
vim.bo.modifiable = false
state.test_panel_active = true
logger.log("test panel opened")
logger.log(string.format("test panel opened (%d test cases)", #test_state.test_cases))
end
---@param delta number 1 for next, -1 for prev

View file

@ -225,7 +225,13 @@ function M.scrape_problem(ctx)
return data
end
if data.test_cases and #data.test_cases > 0 then
if data.combined then
local combined_input = data.combined.input:gsub("\r", "")
local combined_output = data.combined.output:gsub("\r", "")
vim.fn.writefile(vim.split(combined_input, "\n", true), ctx.input_file)
vim.fn.writefile(vim.split(combined_output, "\n", true), ctx.expected_file)
elseif data.test_cases and #data.test_cases > 0 then
local combined_input = data.test_cases[1].input:gsub("\r", "")
local combined_output = data.test_cases[1].output:gsub("\r", "")

View file

@ -1,7 +1,24 @@
---@class TestCase
---@field index number
---@field input string
---@field expected string
---@field status "pending"|"pass"|"fail"|"running"
---@field actual string?
---@field time_ms number?
---@field error string?
---@class TestPanelState
---@field test_cases TestCase[]
---@field current_index number
---@field buffer number?
---@field namespace number?
---@field is_active boolean
---@field saved_layout table?
local M = {}
local logger = require("cp.log")
local execute = require("cp.execute")
---@type TestPanelState
local test_panel_state = {
test_cases = {},
current_index = 1,
@ -33,8 +50,10 @@ local function parse_test_cases_from_cache(platform, contest_id, problem_id)
end
local test_cases = {}
for i, test_case in ipairs(cached_test_cases) do
table.insert(test_cases, create_test_case(i, test_case.input, test_case.output))
local index = test_case.index or i
table.insert(test_cases, create_test_case(index, test_case.input, test_case.output))
end
return test_cases