Skip to content

Commit c291fa1

Browse files
authored
Merge pull request #2775 from AtCoder-NoviSteps/#2346
feat: Enable to register tasks shared across multiple contests (#2346)
2 parents e9fe02a + 03b2f47 commit c291fa1

File tree

10 files changed

+3489
-53
lines changed

10 files changed

+3489
-53
lines changed

docs/dev-notes/2025-10-26/impact-analysis/future_tasks.md

Lines changed: 483 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
# Phase 1: 直接的な依存関係の調査結果
2+
3+
調査日: 2025-10-26
4+
5+
対象: `getTaskResults()``getTasksWithTagIds()` の呼び出し元と `Map<string, TaskResult>` の利用箇所
6+
7+
---
8+
9+
## 1. 起点となる関数の呼び出し元
10+
11+
### 1.1 getTaskResults() - 呼び出し元
12+
13+
| ファイル | 行番号 | コンテキスト |
14+
| --------------------------------------------- | ------ | --------------------------------------------------------------------------------------- |
15+
| `src/routes/problems/+page.server.ts` | 26 | `taskResults: (await crud.getTaskResults(session?.user.userId)) as TaskResults,` |
16+
| `src/routes/users/[username]/+page.server.ts` | 33 | `const taskResultsMap = await taskResultService.getTaskResultsOnlyResultExists(...)` |
17+
| `src/routes/workbooks/+page.server.ts` | 39 | `const taskResultsByTaskId = await taskResultsCrud.getTaskResultsOnlyResultExists(...)` |
18+
19+
### 1.2 getTasksWithTagIds() - 呼び出し元
20+
21+
| ファイル | 行番号 | コンテキスト |
22+
| ------------------------------------- | ------ | -------------------------------------------------------------------------------------------- |
23+
| `src/routes/problems/+page.server.ts` | 20 | `taskResults: (await crud.getTasksWithTagIds(tagIds, session?.user.userId)) as TaskResults,` |
24+
25+
**修正が必要な理由**:
26+
27+
- `relateTasksAndAnswers()` を使用(削除対象)
28+
- ContestTaskPair に非対応(タグフィルタ後のタスクで同一 taskId 複数 contestId に対応していない)
29+
- `/problems?tags=...` ページで複数コンテストの同じ問題が表示されない
30+
31+
**修正方法**:
32+
33+
- `getMergedTasksMap(filteredTasks)` に タグフィルタ後のタスク配列を渡す
34+
- ヘルパー関数 `createTaskResults()` で統一マージ
35+
- 詳細は [`report.md` Section 3.2](report.md#32-サービス層gettagswithtaskids新規追加対象) を参照
36+
37+
---
38+
39+
## 1.3 その他の関連関数
40+
41+
| 関数名 | ファイル | 状態 | 備考 |
42+
| --------------------------- | ---------------------------------- | -------- | --------------------------------------------------------------------- |
43+
| `createTaskResults()` | `src/lib/services/task_results.ts` | 新規追加 | ヘルパー関数。`getTaskResults()``getTasksWithTagIds()` で共通使用 |
44+
| `getMergedTasksMap(tasks?)` | `src/lib/services/tasks.ts` | 拡張必要 | `tasks` パラメータを optional に拡張 |
45+
46+
---
47+
48+
## 2. Map<string, TaskResult> 利用箇所一覧
49+
50+
### 2.1 型定義
51+
52+
| ファイル | 行番号 | 用途 |
53+
| --------------------------------------------------- | ---------- | ------------------------------------------------------------------------- |
54+
| `src/lib/types/contest_task_pair.ts` | 25 | `TaskResultMapByContestTaskPairKey = Map<ContestTaskPairKey, TaskResult>` |
55+
| `src/test/lib/utils/test_cases/account_transfer.ts` | 16, 96, 98 | テスト用サンプルデータ |
56+
| `src/lib/utils/account_transfer.ts` | 16, 69 | アカウント転送用ユーティリティの型定義 |
57+
58+
### 2.2 サービス層での生成・操作
59+
60+
| ファイル | 行番号 | 関数名 | 説明 |
61+
| ---------------------------------- | ------- | ---------------------------------- | ------------------------------------------------------------------- |
62+
| `src/lib/services/tasks.ts` | 41-65 | `getMergedTasksMap(tasks?)` |**新規拡張**: ContestTaskPair マップ。tasks パラメータで DI 対応 |
63+
| `src/lib/services/task_results.ts` | - | `createTaskResults()` |**新規追加**: Task 配列を answers とマージ。統一ポイント |
64+
| `src/lib/services/task_results.ts` | 88, 96 | `transferAnswers()` | ソースユーザ・宛先ユーザの回答を Map として取得 |
65+
| `src/lib/services/task_results.ts` | 154-179 | `getTaskResultsOnlyResultExists()` | 回答ありのみ返すメソッド(Map 可能) |
66+
| `src/lib/services/task_results.ts` | 190-231 | `getTaskResultsByTaskId()` | 指定タスク ID のみ返すメソッド(workbooks 用) |
67+
68+
### 2.3 コンポーネント層での利用
69+
70+
| ファイル | 行番号 | 用途 | キー参照方法 |
71+
| ------------------------------------------------------- | ------- | ------------------------------- | --------------------------------- |
72+
| `src/lib/components/TaskTables/TaskTable.svelte` | 126-132 | TaskResults 配列から Map へ変換 | `taskResult.task_id` をキー |
73+
| `src/lib/components/TaskTables/TaskTable.svelte` | 146-152 | Map での検索・インデックス操作 | `.get(taskId)` 直接参照 |
74+
| `src/lib/components/TaskGradeList.svelte` | 18-55 | 成績別に Map 作成 | `.get(taskGrade)` で グループ分け |
75+
| `src/lib/components/WorkBooks/WorkBookBaseTable.svelte` | 33 | props 型として使用 | - |
76+
| `src/lib/components/WorkBooks/WorkBookList.svelte` | 23-88 | workbook 別の TaskResults 集約 | `.get(workbookType)` でグループ化 |
77+
| `src/lib/components/WorkBook/WorkBookForm.svelte` | 46 | タスク情報参照 | `.get(taskId)` 直接参照 |
78+
79+
### 2.4 ページ層での利用
80+
81+
| ファイル | 行番号 | 用途 |
82+
| ----------------------------------------------------- | --------- | ----------------------------------------------- |
83+
| `src/routes/problems/+page.server.ts` | 4, 20, 26 | TaskResults を props として渡す(形式は Array) |
84+
| `src/routes/problems/[slug]/+page.server.ts` | 16, 31 | 単一タスク結果の取得・更新 |
85+
| `src/routes/workbooks/+page.svelte` | 70 | Map 形式で受け取り |
86+
| `src/routes/workbooks/[slug]/+page.server.ts` | 27 | Map 形式で返却 |
87+
| `src/routes/workbooks/[slug]/+page.svelte` | 44 | `.get(taskId)` で参照 |
88+
| `src/routes/(admin)/account_transfer/+page.server.ts` | 62 | `copyTaskResults()` でユーザ間転送 |
89+
90+
---
91+
92+
## 3. taskId をキーとした直接 Map アクセス
93+
94+
### 3.1 アクセスパターン一覧
95+
96+
| ファイル | 行番号 | パターン | 説明 |
97+
| ------------------------------------------------------------ | ------ | ------------------------------------------- | ---------------------------- |
98+
| `src/lib/services/task_results.ts` | 213 | `tasksMap.get(taskId)` | Task マップからタスク取得 |
99+
| `src/lib/services/task_results.ts` | 220 | `answersMap.get(taskId)` | 回答マップから回答取得 |
100+
| `src/lib/services/task_results.ts` | 223 | `taskResultsMap.set(taskId, taskResult)` | 結果マップに結果を登録 |
101+
| `src/lib/components/WorkBookTasks/WorkBookTasksTable.svelte` | 133 | `tasksMapByIds.get(taskId)` | コンポーネント内でタスク参照 |
102+
| `src/lib/components/TaskTables/TaskTable.svelte` | 152 | `taskIndicesMap().get(updatedTask.task_id)` | インデックスマップから参照 |
103+
| `src/routes/workbooks/[slug]/+page.svelte` | 44 | `taskResults?.get(taskId)` | ページ内で結果参照 |
104+
105+
---
106+
107+
## 4. task_results サービス層の全体像
108+
109+
### 4.1 他からインポートされる関数一覧
110+
111+
```text
112+
src/routes/problems/+page.server.ts
113+
├─ getTaskResults()
114+
├─ getTasksWithTagIds()
115+
└─ updateTaskResult()
116+
117+
src/routes/problems/[slug]/+page.server.ts
118+
├─ getTaskResult()
119+
└─ updateTaskResult()
120+
121+
src/routes/users/[username]/+page.server.ts
122+
└─ getTaskResultsOnlyResultExists()
123+
124+
src/routes/workbooks/+page.server.ts
125+
└─ getTaskResultsOnlyResultExists()
126+
127+
src/routes/workbooks/[slug]/+page.server.ts
128+
└─ getTaskResultsByTaskId()
129+
130+
src/routes/(admin)/account_transfer/+page.server.ts
131+
└─ copyTaskResults()
132+
```
133+
134+
### 4.2 内部関数一覧
135+
136+
- `relateTasksAndAnswers()` - TaskResults 生成の中核
137+
- `createDefaultTaskResult()` - デフォルト TaskResult 作成
138+
- `transferAnswers()` - アカウント転送時の回答転送
139+
- `mergeTaskAndAnswer()` - Task と Answer を統合
140+
141+
---
142+
143+
## 5. リスク区分
144+
145+
### 高リスク(必須修正)
146+
147+
- **`src/lib/services/task_results.ts`**
148+
- `getTaskResultsByTaskId()` - 直接 `taskId` をキーに利用(213, 220, 223 行)
149+
- `getTaskResultsOnlyResultExists()` - `taskId` を直接キーに登録(173 行)
150+
- `relateTasksAndAnswers()` - 配列返却用だが内部では taskId を利用
151+
152+
- **`src/routes/problems/+page.server.ts`**
153+
- `getTaskResults()``getTasksWithTagIds()` の戻り値型が `TaskResults` (Array)
154+
- しかし新構造では `Map<contestId:taskId, Task>` が必要
155+
156+
### 中リスク(間接的な影響)
157+
158+
- **`src/lib/components/TaskTables/TaskTable.svelte`**
159+
- TaskResults 配列を Map に変換(127行)
160+
- キーが taskId なので、新構造対応が必要
161+
162+
- **`src/routes/workbooks/[slug]/+page.svelte`**
163+
- 既に Map 型で受け取り `.get(taskId)` で参照(44行)
164+
- キー構造の変更が必要
165+
166+
### 低リスク(読み取りのみ)
167+
168+
- `src/routes/problems/[slug]/+page.server.ts`
169+
- 単一タスク参照なので、現在の構造でも対応可能かもしれない
170+
171+
---
172+
173+
## 6. 推奨される修正優先順序
174+
175+
1. **Phase 2**: サービス層(`src/lib/services/task_results.ts`)を修正
176+
- `getTaskResultsByTaskId()` - キー形式を変更
177+
- `getTaskResultsOnlyResultExists()` - キー形式を変更
178+
- ヘルパー関数を新構造対応に改修
179+
180+
2. **Phase 3**: ページサーバー層(`src/routes/*/+page.server.ts`)を修正
181+
- `/problems` ページ:戻り値型の見直し
182+
- `/workbooks` ページ:キー形式の一貫性確認
183+
184+
3. **Phase 4**: コンポーネント層(`src/lib/components/*`)を修正
185+
- TaskTable での Map 変換処理
186+
- workbooks での参照処理
187+
188+
4. **Phase 5**: ユーティリティ層(`src/lib/utils/account_transfer.ts`)を修正
189+
- アカウント転送の型・ロジック調整
190+
191+
---
192+
193+
## 7. 既知の新しい型定義
194+
195+
| 型名 | ファイル | 説明 |
196+
| ----------------------------------- | ------------------------------------ | ----------------------------- |
197+
| `TaskResultMapByContestTaskPairKey` | `src/lib/types/contest_task_pair.ts` | 新しいキー形式用の Map 型 |
198+
| `ContestTaskPairKey` | `src/lib/types/contest_task_pair.ts` | `contestId:taskId` 形式のキー |
199+
200+
---
201+
202+
## 8. 次のステップ(Phase 2 候補)
203+
204+
- [ ] `src/lib/services/tasks.ts``getMergedTasksMap()` 実装内容確認
205+
- [ ] ContestTaskPair テーブルの実装内容確認
206+
- [ ] `/problems` ページの現在の TaskResults 返却形式を詳細確認
207+
- [ ] `/workbooks` との互換性要件の最終確認

0 commit comments

Comments
 (0)