Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .claude/skills/add-contest-table-provider/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ Step 0 (seed check) is already done. Confirm the following before touching code:
> Skip when an existing ContestType already covers this contest family (e.g. `AOJ_JAG` for JAG Prelim).

- [ ] Add to `prisma/schema.prisma` ContestType enum → `pnpm exec prisma generate`
- [ ] Add to `ContestType` in `src/lib/types/contest.ts` (same position as schema)
- [ ] Add to `ContestType` in `src/lib/contests/types/contest.ts` (same position as schema)
- [ ] `pnpm check` — confirm error resolved

## Layer 3 — Contest utilities (TDD)

### Tests first

- [ ] Add exports to `src/test/lib/utils/test_cases/contest_type.ts` and `contest_name_labels.ts`
- [ ] Add 3 `describe` blocks to `src/test/lib/utils/contest.test.ts`: classify / priority / name label
- [ ] `pnpm test:unit src/test/lib/utils/contest.test.ts` — **RED**
- [ ] Add exports to `src/lib/contests/fixtures/contest_type.ts` and `contest_name_labels.ts`
- [ ] Add 3 `describe` blocks to `src/lib/contests/utils/contest.test.ts`: classify / priority / name label
- [ ] `pnpm test:unit src/lib/contests/utils/contest.test.ts` — **RED**

### Implement

Expand Down
1 change: 1 addition & 0 deletions docs/guides/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ src/lib/
├── clients/ # 外部 API クライアント(AtCoder Problems, AOJ)
├── components/ # 共通 UI コンポーネント(GradeLabel, TaskGradeList, TaskList, FormWrapper 等)
├── constants/ # アプリ定数
├── contests/ # コンテスト分類・ラベル生成・優先度(types/, utils/, fixtures/)
├── server/ # サーバー専用の共有インフラ
│ ├── database.ts # Prisma クライアント(14+ サービスが依存)
│ ├── tasks/ # cache.ts など複数 feature 共有のサーバ処理
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/how-to-add-contest-table-provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

## 事前確認

- [ ] `ContestType`(`src/lib/types/contest.ts`)— 既存で対応できるか?複数 contest_id を統一表示するなら複合型
- [ ] `classifyContest()`(`src/lib/utils/contest.ts`)— 新 contest_id に正しい ContestType を返すか
- [ ] `ContestType`(`src/lib/contests/types/contest.ts`)— 既存で対応できるか?複数 contest_id を統一表示するなら複合型
- [ ] `classifyContest()`(`src/lib/contests/utils/contest.ts`)— 新 contest_id に正しい ContestType を返すか
- [ ] `prisma/tasks.ts` にデータが存在するか(複合型は `prisma/contest_task_pairs.ts` も)
- [ ] 実装パターン判定(後述4パターン)
- [ ] JOI: 2026 年より `joi{YYYY}ho` → `joi{YYYY}sf`。regex は `(ho|sf)` 対応済み
Expand Down
2 changes: 1 addition & 1 deletion prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { hashPassword } from '../src/features/auth/server/password';
import { getTaskGrade } from '../src/lib/types/task';
import type { PlacementCreate } from '../src/features/workbooks/types/workbook_placement';

import { classifyContest } from '../src/lib/utils/contest';
import { classifyContest } from '../src/lib/contests/utils/contest';

import { users, USER_PASSWORD_FOR_SEED } from './users';
import { tasks } from './tasks';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ContestType } from '$lib/types/contest';
import type { ContestType } from '$lib/contests/types/contest';
import type { TaskResults, TaskResult } from '$lib/types/task';

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResult, TaskResults } from '$lib/types/task';

import {
Expand Down
2 changes: 1 addition & 1 deletion src/features/tasks/utils/contest-table/abc_providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
} from '$features/tasks/types/contest-table/contest_table_provider';
import type { TaskResult } from '$lib/types/task';

import { classifyContest, getContestNameLabel } from '$lib/utils/contest';
import { classifyContest, getContestNameLabel } from '$lib/contests/utils/contest';

import { ContestTableProviderBase, parseContestRound } from './contest_table_provider_base';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResults } from '$lib/types/task';

import { ABSProvider } from './abs_provider';
Expand Down
2 changes: 1 addition & 1 deletion src/features/tasks/utils/contest-table/abs_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
} from '$features/tasks/types/contest-table/contest_table_provider';
import type { TaskResult } from '$lib/types/task';

import { classifyContest } from '$lib/utils/contest';
import { classifyContest } from '$lib/contests/utils/contest';

import { ContestTableProviderBase } from './contest_table_provider_base';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResults } from '$lib/types/task';

import { ACLPracticeProvider, ACLBeginnerProvider, ACLProvider } from './acl_providers';
Expand Down
2 changes: 1 addition & 1 deletion src/features/tasks/utils/contest-table/acl_providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
} from '$features/tasks/types/contest-table/contest_table_provider';
import type { TaskResult } from '$lib/types/task';

import { classifyContest } from '$lib/utils/contest';
import { classifyContest } from '$lib/contests/utils/contest';

import { ContestTableProviderBase } from './contest_table_provider_base';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResults } from '$lib/types/task';

import { AGC001OnwardsProvider } from './agc_provider';
Expand Down
2 changes: 1 addition & 1 deletion src/features/tasks/utils/contest-table/agc_provider.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type ContestTableMetaData } from '$features/tasks/types/contest-table/contest_table_provider';
import type { TaskResult } from '$lib/types/task';

import { classifyContest, getContestNameLabel } from '$lib/utils/contest';
import { classifyContest, getContestNameLabel } from '$lib/contests/utils/contest';

import { ContestTableProviderBase, parseContestRound } from './contest_table_provider_base';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect, beforeEach, afterEach } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResults } from '$lib/types/task';

import { AOJ_LABEL_OVERRIDES } from './aoj_labels';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResult, TaskResults } from '$lib/types/task';
import {
type ContestTableMetaData,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResults } from '$lib/types/task';

import { JagPrelimProvider } from './aoj_jag_providers';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResult, TaskResults } from '$lib/types/task';
import {
type ContestTableMetaData,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResult, TaskResults } from '$lib/types/task';

import {
Expand Down
2 changes: 1 addition & 1 deletion src/features/tasks/utils/contest-table/arc_providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
} from '$features/tasks/types/contest-table/contest_table_provider';
import type { TaskResult } from '$lib/types/task';

import { classifyContest, getContestNameLabel } from '$lib/utils/contest';
import { classifyContest, getContestNameLabel } from '$lib/contests/utils/contest';

import { ContestTableProviderBase, parseContestRound } from './contest_table_provider_base';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResults } from '$lib/types/task';

import { AWCRangeProvider, AWCSpecialContestProvider } from './awc_provider';
Expand Down
4 changes: 2 additions & 2 deletions src/features/tasks/utils/contest-table/awc_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import {
type ContestTableMetaData,
type ContestTableDisplayConfig,
} from '$features/tasks/types/contest-table/contest_table_provider';
import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResult } from '$lib/types/task';

import { classifyContest, getContestNameLabel } from '$lib/utils/contest';
import { classifyContest, getContestNameLabel } from '$lib/contests/utils/contest';

import { ContestTableProviderBase, parseContestRound } from './contest_table_provider_base';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResults } from '$lib/types/task';

import { ABCLikeProvider } from './axc_like_provider';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
} from '$features/tasks/types/contest-table/contest_table_provider';
import type { TaskResult } from '$lib/types/task';

import { classifyContest } from '$lib/utils/contest';
import { classifyContest } from '$lib/contests/utils/contest';

import { ContestTableProviderBase } from './contest_table_provider_base';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';

import { ABSProvider } from './contest_table_provider';
import { taskResultsForABS } from '$features/tasks/fixtures/contest-table/contest_table_provider';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
type ContestTableDisplayConfig,
type ProviderKey,
} from '$features/tasks/types/contest-table/contest_table_provider';
import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResults, TaskResult } from '$lib/types/task';

import { getTaskTableHeaderName } from '$lib/utils/task';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';

import {
ABSProvider,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type ContestTablesMetaData } from '$features/tasks/types/contest-table/contest_table_provider';
import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';

import { ContestTableProviderBase } from './contest_table_provider_base';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';

import { TESSOKU_SECTIONS } from '$features/tasks/types/contest-table/contest_table_provider';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';

import { ABSProvider } from './abs_provider';
import {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResults } from '$lib/types/task';

import { EDPCProvider, TDPCProvider, NDPCProvider } from './dp_providers';
Expand Down
2 changes: 1 addition & 1 deletion src/features/tasks/utils/contest-table/dp_providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
} from '$features/tasks/types/contest-table/contest_table_provider';
import type { TaskResult } from '$lib/types/task';

import { classifyContest } from '$lib/utils/contest';
import { classifyContest } from '$lib/contests/utils/contest';

import { ContestTableProviderBase } from './contest_table_provider_base';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResults } from '$lib/types/task';

import { FPS24Provider } from './fps24_provider';
Expand Down
2 changes: 1 addition & 1 deletion src/features/tasks/utils/contest-table/fps24_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
} from '$features/tasks/types/contest-table/contest_table_provider';
import type { TaskResult } from '$lib/types/task';

import { classifyContest } from '$lib/utils/contest';
import { classifyContest } from '$lib/contests/utils/contest';

import { ContestTableProviderBase } from './contest_table_provider_base';

Expand Down
4 changes: 2 additions & 2 deletions src/features/tasks/utils/contest-table/joi_providers.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResults } from '$lib/types/task';

import {
Expand Down Expand Up @@ -81,7 +81,7 @@ describe('JOIFirstQualRoundProvider', () => {
test('expects to handle invalid contest IDs gracefully', () => {
const provider = new JOIFirstQualRoundProvider(ContestType.JOI);

expect(provider.getContestRoundLabel('invalid-id')).toBe('INVALID-ID'); // See: getContestNameLabel() in src/lib/utils/contest.ts
expect(provider.getContestRoundLabel('invalid-id')).toBe('INVALID-ID'); // See: getContestNameLabel() in src/lib/contests/utils/contest.ts
expect(provider.getContestRoundLabel('joi2024yo1d')).toBe('2024d'); // 'd' doesn't match valid round (a|b|c)
});

Expand Down
4 changes: 2 additions & 2 deletions src/features/tasks/utils/contest-table/joi_providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import {
JOI_SECOND_QUAL_ROUND_SECTIONS,
JOI_FINAL_ROUND_SECTIONS,
} from '$features/tasks/types/contest-table/contest_table_provider';
import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResult } from '$lib/types/task';

import { classifyContest, getContestNameLabel } from '$lib/utils/contest';
import { classifyContest, getContestNameLabel } from '$lib/contests/utils/contest';

import { ContestTableProviderBase } from './contest_table_provider_base';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResults } from '$lib/types/task';

import { MathAndAlgorithmProvider } from './math_and_algorithm_provider';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
} from '$features/tasks/types/contest-table/contest_table_provider';
import type { TaskResult } from '$lib/types/task';

import { classifyContest } from '$lib/utils/contest';
import { classifyContest } from '$lib/contests/utils/contest';

import { ContestTableProviderBase } from './contest_table_provider_base';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResults } from '$lib/types/task';

import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import {
type ContestTableDisplayConfig,
TESSOKU_SECTIONS,
} from '$features/tasks/types/contest-table/contest_table_provider';
import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResult } from '$lib/types/task';

import { classifyContest } from '$lib/utils/contest';
import { classifyContest } from '$lib/contests/utils/contest';

import { ContestTableProviderBase } from './contest_table_provider_base';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'vitest';

import { ContestType } from '$lib/types/contest';
import { ContestType } from '$lib/contests/types/contest';
import type { TaskResults } from '$lib/types/task';

import { Typical90Provider } from './typical90_provider';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
} from '$features/tasks/types/contest-table/contest_table_provider';
import type { TaskResult } from '$lib/types/task';

import { classifyContest } from '$lib/utils/contest';
import { classifyContest } from '$lib/contests/utils/contest';

import { ContestTableProviderBase } from './contest_table_provider_base';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import GradeLabel from '$lib/components/GradeLabel.svelte';
import ExternalLinkWrapper from '$lib/components/ExternalLinkWrapper.svelte';

import { addContestNameToTaskIndex } from '$lib/utils/contest';
import { addContestNameToTaskIndex } from '$lib/contests/utils/contest';
import { getTaskUrl, removeTaskIndexFromTitle } from '$lib/utils/task';

import type {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/clients/aizu_online_judge/clients.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Cache } from '$lib/clients/cache';

import { AojCoursesApiClient, AojChallengesApiClient } from './clients';

import type { ContestsForImport } from '$lib/types/contest';
import type { ContestsForImport } from '$lib/contests/types/contest';
import type { TasksForImport } from '$lib/types/task';
import type { AOJCourseAPI, AOJChallengeContestAPI, AOJTaskAPIs } from './types';

Expand Down
2 changes: 1 addition & 1 deletion src/lib/clients/aizu_online_judge/clients.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { HttpRequestClient } from '$lib/clients/http_client';
import { ContestTaskCache } from '$lib/clients/cache_strategy';
import { getCachedOrFetchContests, getCachedOrFetchTasks } from '$lib/clients/contest_task_fetcher';

import type { ContestsForImport } from '$lib/types/contest';
import type { ContestsForImport } from '$lib/contests/types/contest';
import type { TasksForImport } from '$lib/types/task';

import type {
Expand Down
Loading
Loading