Skip to content

feat: fetch and display Codeforces problem statements in ProblemWorkspace#49

Merged
enlorik merged 1 commit into
mainfrom
copilot/add-codeforces-problem-fetch
May 13, 2026
Merged

feat: fetch and display Codeforces problem statements in ProblemWorkspace#49
enlorik merged 1 commit into
mainfrom
copilot/add-codeforces-problem-fetch

Conversation

Copilot AI commented May 11, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR lets HDD display a Codeforces problem statement directly inside the app, without requiring the user to visit the Codeforces website.

Changes

Backend (server.js, cfStatementParser.js)

  • Added GET /api/cf/problem/:contestId/:index/statement route
    • Validates contestId (numeric) and index (alphanumeric, e.g. A, C1)
    • Fetches the public Codeforces problem page server-side via HTTPS
    • Returns structured JSON only — no raw HTML is ever forwarded to the browser
  • Added cfStatementParser.js helper that isolates all cheerio-based HTML parsing
    • Returns: title, timeLimit, memoryLimit, statement, inputSpecification, outputSpecification, samples[]

Frontend (src/services/cfStatement.js, ProblemWorkspace.jsx, ProblemWorkspace.css)

  • Added src/services/cfStatement.js — thin fetch wrapper for the new endpoint
  • Updated ProblemWorkspace.jsx:
    • Fetches statement on mount (keyed to contestId/index)
    • Shows loading state while fetching
    • Shows clear error state with fallback link on failure
    • Displays statement panel: title, time/memory limits, problem body, input/output specs, sample tests
    • Kotlin editor and local draft persistence are unchanged
  • Updated ProblemWorkspace.css with styles for limits strip, statement body, section headings, and samples grid

Config

  • Updated vite.config.js to proxy /api/ to the Express dev server (port 3000) so the new route works in npm run dev
  • Updated eslint.config.js to apply Node globals to cfStatementParser.js and its test file

Tests (cfStatementParser.test.js)

  • 11 unit tests covering title, time/memory limits, statement body, I/O specs, sample parsing, multi-paragraph body, multi-line sample input, missing statement page, and full return shape
  • No live Codeforces requests — all tests use mocked HTML fixtures
  • All 19 tests (8 existing + 11 new) pass

Out of scope (per problem statement)

  • Code execution
  • Login / authentication
  • Direct submission
  • Kotlin library injection
  • Solve counts, standings, popularity

Validation

  • npm test — 19/19 tests pass ✅
  • npm run lint — clean ✅
  • npm run build — success ✅

- Install cheerio for server-side HTML parsing
- Add cfStatementParser.js with parseCFProblemStatement() helper
- Add GET /api/cf/problem/:contestId/:index/statement route to server.js
- Add cfStatementParser.test.js with 11 unit tests (mocked HTML fixtures)
- Add src/services/cfStatement.js frontend fetch service
- Update ProblemWorkspace.jsx with statement panel, loading/error states
- Update ProblemWorkspace.css with statement panel styles
- Update eslint.config.js for node globals on new server files
- Update vite.config.js with /api proxy for dev server

Agent-Logs-Url: https://github.com/enlorik/HDD/sessions/ba819bfd-a6b0-4a90-8ea5-965d62ff0a58

Co-authored-by: enlorik <99548776+enlorik@users.noreply.github.com>
Copilot AI requested a review from enlorik May 11, 2026 13:51
@enlorik
enlorik marked this pull request as ready for review May 13, 2026 11:28
Copilot AI review requested due to automatic review settings May 13, 2026 11:28
@enlorik
enlorik merged commit 3aae1c5 into main May 13, 2026
2 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds end-to-end support for fetching and rendering Codeforces problem statements inside HDD’s ProblemWorkspace, using a server-side HTML fetch + parser to return structured plain-text JSON to the React UI.

Changes:

  • Backend: added /api/cf/problem/:contestId/:index/statement to fetch the Codeforces problem page and parse it into JSON via a new cfStatementParser.js.
  • Frontend: added a statement fetch service and updated ProblemWorkspace to display loading/error states, limits, statement sections, and samples.
  • Tooling: added Vite dev proxy for /api, updated ESLint config for Node globals, and added unit tests for the parser.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
vite.config.js Proxies /api to the Express server in dev for the new endpoint.
src/services/cfStatement.js Adds a frontend fetch wrapper for the statement endpoint.
src/components/ProblemWorkspace.jsx Fetches and renders the parsed statement (loading/error/ok states).
src/components/ProblemWorkspace.css Styles the new statement panel and sample layout.
server.js Adds the new statement route that fetches Codeforces HTML and returns parsed JSON.
package.json Adds cheerio dependency used for server-side parsing.
package-lock.json Locks cheerio and its transitive dependencies.
eslint.config.js Applies Node globals to the new parser and its tests.
cfStatementParser.test.js Adds unit tests for parsing title/limits/body/specs/samples from fixtures.
cfStatementParser.js Implements the cheerio-based HTML-to-plain-text parser.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread package.json
Comment on lines 14 to 17
"dependencies": {
"cheerio": "^1.2.0",
"express": "^5.2.1",
"react": "^19.2.0",
Comment thread server.js
Comment on lines +82 to +94
let rawHtml = '';

const request = https.get(options, (cfRes) => {
if (cfRes.statusCode !== 200) {
res.status(502).json({ error: `Codeforces returned HTTP ${cfRes.statusCode}` });
cfRes.resume();
return;
}

cfRes.setEncoding('utf-8');
cfRes.on('data', chunk => { rawHtml += chunk; });
cfRes.on('end', () => {
const parsed = parseCFProblemStatement(rawHtml);
Comment thread cfStatementParser.js
Comment on lines +11 to +15
/**
* Replace block-level children and <br> tags with newlines, then return the
* trimmed text content of an element. This preserves paragraph breaks without
* leaking any HTML tags to the caller.
*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants