fix: complete language version IDs for all platforms (#350)

## Problem

`LANGUAGE_VERSIONS` only covered cpp and python. Several platform IDs
were wrong — CodeChef used `C++ 17`/`Python 3` (correct: `C++`/`PYTH
3`), USACO listed nonexistent c++20/c++23 options, and CSES only had
C++17.

## Solution

Verify every platform's submit page and update all language ID tables.
Add java and rust entries where supported, fix incorrect CodeChef and
USACO IDs, and expand CSES `CSES_LANGUAGES` dict with
C++11/C++20/PyPy3/Java/Rust variants.
This commit is contained in:
Barrett Ruth 2026-03-06 19:28:06 -05:00 committed by GitHub
parent 2776aaeb21
commit 425a8f36e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 64 additions and 34 deletions

View file

@ -1056,13 +1056,13 @@ Set {version} globally or per-platform:
<
Available versions per platform ~
Platform cpp python
AtCoder c++23 python3
Codeforces c++17/20/23 python3, pypy3
CSES c++17 python3
Kattis c++17/20/23 python3
USACO c++17/20/23 python3
CodeChef c++17 python3
Platform cpp python java rust
AtCoder c++20/23 python3, pypy3 java rust
Codeforces c++17/20/23 python3, pypy3 - -
CSES c++11/17/20 python3, pypy3 java rust2018/2021
Kattis c++17/20/23 python3 java rust
USACO c++11/17 python3 java -
CodeChef c++20 python3, pypy3 java rust
Using a raw platform ID ~

View file

@ -74,21 +74,39 @@ M.signal_codes = {
}
M.LANGUAGE_VERSIONS = {
atcoder = { cpp = { ['c++23'] = '6017' }, python = { python3 = '6082' } },
atcoder = {
cpp = { ['c++20'] = '6054', ['c++23'] = '6017' },
python = { python3 = '6082', pypy3 = '6083' },
java = { java = '6056' },
rust = { rust = '6088' },
},
codeforces = {
cpp = { ['c++17'] = '54', ['c++20'] = '89', ['c++23'] = '91' },
python = { python3 = '31', pypy3 = '70' },
},
cses = { cpp = { ['c++17'] = 'C++17' }, python = { python3 = 'Python3' } },
cses = {
cpp = { ['c++11'] = 'C++11', ['c++17'] = 'C++17', ['c++20'] = 'C++20' },
python = { python3 = 'Python3', pypy3 = 'PyPy3' },
java = { java = 'Java' },
rust = { rust2018 = 'Rust2018', rust2021 = 'Rust2021' },
},
kattis = {
cpp = { ['c++17'] = 'C++', ['c++20'] = 'C++', ['c++23'] = 'C++' },
python = { python3 = 'Python 3' },
java = { java = 'Java' },
rust = { rust = 'Rust' },
},
usaco = {
cpp = { ['c++17'] = 'cpp', ['c++20'] = 'cpp', ['c++23'] = 'cpp' },
cpp = { ['c++11'] = 'cpp', ['c++17'] = 'cpp' },
python = { python3 = 'python' },
java = { java = 'java' },
},
codechef = {
cpp = { ['c++20'] = 'C++' },
python = { python3 = 'PYTH 3', pypy3 = 'PYPY3' },
java = { java = 'JAVA' },
rust = { rust = 'rust' },
},
codechef = { cpp = { ['c++17'] = 'C++ 17' }, python = { python3 = 'Python 3' } },
}
M.DEFAULT_VERSIONS = { cpp = 'c++20', python = 'python3' }

View file

@ -31,13 +31,25 @@ HEADERS = {
CONNECTIONS = 8
CSES_LANGUAGES: dict[str, dict[str, str]] = {
"C++11": {"name": "C++", "option": "C++11"},
"C++17": {"name": "C++", "option": "C++17"},
"Python3": {"name": "Python", "option": "CPython3"},
"C++20": {"name": "C++", "option": "C++20"},
"Python3": {"name": "Python3", "option": "CPython3"},
"PyPy3": {"name": "Python3", "option": "PyPy3"},
"Java": {"name": "Java", "option": "Java"},
"Rust2018": {"name": "Rust", "option": "2018"},
"Rust2021": {"name": "Rust", "option": "2021"},
}
EXTENSIONS: dict[str, str] = {
"C++11": "cpp",
"C++17": "cpp",
"C++20": "cpp",
"Python3": "py",
"PyPy3": "py",
"Java": "java",
"Rust2018": "rs",
"Rust2021": "rs",
}

View file

@ -2,6 +2,8 @@ LANGUAGE_IDS = {
"atcoder": {
"cpp": "6017",
"python": "6082",
"java": "6056",
"rust": "6088",
},
"codeforces": {
"cpp": "89",
@ -10,18 +12,25 @@ LANGUAGE_IDS = {
"cses": {
"cpp": "C++17",
"python": "Python3",
"java": "Java",
"rust": "Rust2021",
},
"usaco": {
"cpp": "cpp",
"python": "python",
"java": "java",
},
"kattis": {
"cpp": "C++",
"python": "Python 3",
"java": "Java",
"rust": "Rust",
},
"codechef": {
"cpp": "C++ 17",
"python": "Python 3",
"cpp": "C++",
"python": "PYTH 3",
"java": "JAVA",
"rust": "rust",
},
}

View file

@ -1,6 +1,6 @@
import pytest
from scrapers.language_ids import LANGUAGE_IDS, get_language_id
from scrapers.language_ids import LANGUAGE_IDS
from scrapers.models import (
ContestListResult,
MetadataResult,
@ -140,26 +140,17 @@ def test_scraper_metadata_error(run_scraper_offline, scraper, contest_id):
assert objs[-1].get("error")
EXPECTED_PLATFORMS = {"atcoder", "codeforces", "cses", "usaco", "kattis", "codechef"}
EXPECTED_LANGUAGES = {"cpp", "python"}
def test_language_ids_coverage():
assert set(LANGUAGE_IDS.keys()) == EXPECTED_PLATFORMS
expected_platforms = {
"atcoder",
"codeforces",
"cses",
"usaco",
"kattis",
"codechef",
}
assert set(LANGUAGE_IDS.keys()) == expected_platforms
for platform, langs in LANGUAGE_IDS.items():
assert set(langs.keys()) == EXPECTED_LANGUAGES, f"{platform} missing languages"
assert {"cpp", "python"} <= set(langs.keys()), f"{platform} missing cpp/python"
for lang, lid in langs.items():
assert isinstance(lid, str) and lid, f"{platform}/{lang} empty ID"
@pytest.mark.parametrize("platform", EXPECTED_PLATFORMS)
@pytest.mark.parametrize("language", EXPECTED_LANGUAGES)
def test_get_language_id(platform, language):
result = get_language_id(platform, language)
assert result is not None, f"No ID for {platform}/{language}"
assert result == LANGUAGE_IDS[platform][language]
def test_get_language_id_unknown():
assert get_language_id("nonexistent", "cpp") is None
assert get_language_id("codeforces", "rust") is None