diff --git a/docs/dev-notes/2026-03-01/add-aoj-course-to-contests/plan.md b/docs/dev-notes/2026-03-01/add-aoj-course-to-contests/plan.md new file mode 100644 index 000000000..7babb2e47 --- /dev/null +++ b/docs/dev-notes/2026-03-01/add-aoj-course-to-contests/plan.md @@ -0,0 +1,7 @@ +# AOJ コースへの DSL・CGL・NTL 追加 (Issue #3223) + +[Issue #3223](https://github.com/AtCoder-NoviSteps/AtCoderNoviSteps/issues/3223) で、AOJ の DSL (18問)・CGL (25問)・NTL (11問) を追加。`AOJ_COURSES` に3件追記するだけで、アーキテクチャ上の変更は不要。`AOJ_COURSES` を参照する関数はデータ駆動のため変更不要。 + +## 注意事項 + +AOJ の `/problems?size=N` は存在しない問題を返すことがある。現在の `id` 生成ロジックは `sha256(contest_id + task.title)` のため、タイトル重複時に `Task.id` 一意制約違反 (P2002) が発生する(CGL で確認)。根本対処は `task.id`(API のユニーク識別子)を使うこと。暫定対処として存在する問題のみインポート。 diff --git a/src/lib/utils/contest.ts b/src/lib/utils/contest.ts index 9df44b5b1..74319b8e1 100644 --- a/src/lib/utils/contest.ts +++ b/src/lib/utils/contest.ts @@ -225,6 +225,9 @@ export const AOJ_COURSES: ContestPrefix = { ITP2: 'プログラミング応用', DPL: '組み合わせ最適化', GRL: 'グラフ', + DSL: 'データ構造', + CGL: '計算幾何学', + NTL: '整数論', } as const; export function getPrefixForAojCourses() { diff --git a/src/test/lib/utils/test_cases/contest_name_and_task_index.ts b/src/test/lib/utils/test_cases/contest_name_and_task_index.ts index a07e6da9f..ef9e64046 100644 --- a/src/test/lib/utils/test_cases/contest_name_and_task_index.ts +++ b/src/test/lib/utils/test_cases/contest_name_and_task_index.ts @@ -593,6 +593,10 @@ export const agc = generateAgcTestCases( * - ALDS1: Algorithms and Data Structures I * - ITP2: Introduction to Programming II * - DPL: Discrete Optimization Problems + * - GRL: Graph Algorithms + * - DSL: Data Set and Queries + * - CGL: Computational Geometry + * - NTL: Number Theory */ const AOJ_COURSES_TEST_DATA = { ITP1: { @@ -615,6 +619,18 @@ const AOJ_COURSES_TEST_DATA = { contestId: 'GRL', tasks: ['1_A', '1_C', '6_B', '7_A'], }, + DSL: { + contestId: 'DSL', + tasks: ['1_A', '2_H'], + }, + CGL: { + contestId: 'CGL', + tasks: ['1_A', '7_I'], + }, + NTL: { + contestId: 'NTL', + tasks: ['1_A', '2_F'], + }, }; const generateAojCoursesTestCases = ( diff --git a/src/test/lib/utils/test_cases/contest_type.ts b/src/test/lib/utils/test_cases/contest_type.ts index 5299c13b9..d5b628350 100644 --- a/src/test/lib/utils/test_cases/contest_type.ts +++ b/src/test/lib/utils/test_cases/contest_type.ts @@ -508,6 +508,9 @@ const aojCoursesData = [ { name: 'AOJ Courses, ITP2', contestId: 'ITP2' }, { name: 'AOJ Courses, DPL', contestId: 'DPL' }, { name: 'AOJ Courses, GRL', contestId: 'GRL' }, + { name: 'AOJ Courses, DSL', contestId: 'DSL' }, + { name: 'AOJ Courses, CGL', contestId: 'CGL' }, + { name: 'AOJ Courses, NTL', contestId: 'NTL' }, ]; export const aojCourses = aojCoursesData.map(({ name, contestId }) => diff --git a/src/test/lib/utils/test_cases/task_url.ts b/src/test/lib/utils/test_cases/task_url.ts index a67f2d1c3..2cf596094 100644 --- a/src/test/lib/utils/test_cases/task_url.ts +++ b/src/test/lib/utils/test_cases/task_url.ts @@ -104,6 +104,18 @@ const courses = [ contestId: 'GRL', tasks: ['1_A', '1_C', '6_B', '7_A'], }, + { + contestId: 'DSL', + tasks: ['1_A', '1_B', '2_I', '5_B'], + }, + { + contestId: 'CGL', + tasks: ['1_A', '1_C', '7_I'], + }, + { + contestId: 'NTL', + tasks: ['1_A', '1_E', '2_F'], + }, ]; export const aojCourses = courses.flatMap((course) =>