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
49 changes: 45 additions & 4 deletions docs/dev-notes/2026-09-09/task-title-index-change-impact/done.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# 完了分(PR0 / PR1 / PR1.5)— 意思決定の要約
# 完了分(PR0 / PR1 / PR1.5 / PR2)— 意思決定の要約

**状態**: PR0 完了(#4212)・PR1 完了(#4217)・PR1.5 完了(#4219)。全体像は [plan.md](./plan.md)、根拠データは [investigation.md](./investigation.md)。
**状態**: PR0 完了(#4212)・PR1 完了(#4217)・PR1.5 完了(#4219)・PR2 は staging に反映(#4220、本番は未反映)。全体像は [plan.md](./plan.md)、根拠データは [investigation.md](./investigation.md)。

コードと git の履歴から読み取れない判断と事実だけを残す。変更したファイルや関数は #4212 / #4217 と `471ad20c` の差分を見る。PR1.5 は [末尾](#pr15--aoj-api-の移転に追従する4028)。
コードと git の履歴から読み取れない判断と事実だけを残す。変更したファイルや関数は #4212 / #4217 / #4219 / #4220 の差分を見る。PR1.5 は [こちら](#pr15--aoj-api-の移転に追従する4028)、PR2 は [こちら](#pr2--jag-合宿系と-jag-模擬地区を問題記号にする4030)。

## 何をしたか

Expand Down Expand Up @@ -76,4 +76,45 @@ PR2 以降の計画には含めていない。
### 残っている確認

- ~~コンテナを再ビルドした後、ローカルの管理画面で AOJ から取得できること~~ — 2026-10-24 にメンテナが確認した
- ~~staging(Vercel)での取り込み~~ — 2026-10-24 にメンテナが JAG REGIONAL を取り込み、16 / 158 になった([plan-pr2.md](./plan-pr2.md#範囲))。こちらの取得ツールが新しいホストに `ECONNREFUSED` で拒まれたことから送信元の制限を心配していたが、Vercel からは問題なく取得できた
- ~~staging(Vercel)での取り込み~~ — 2026-10-24 にメンテナが JAG REGIONAL を取り込み、16 / 158 になった([PR2](#pr2--jag-合宿系と-jag-模擬地区を問題記号にする4030) の前提)。こちらの取得ツールが新しいホストに `ECONNREFUSED` で拒まれたことから送信元の制限を心配していたが、Vercel からは問題なく取得できた

---

## PR2 — JAG 合宿系と JAG 模擬地区を問題記号にする(#4030)

### 何をしたか

- JAG 合宿系(夏 / 冬 / 春、50 コンテスト / 467 問)と JAG 模擬地区(16 / 158)の `task_table_index` を、問題 ID から問題記号にした。合宿系の title から、前に付いていた `<問題 ID>. ` を外した。移行 SQL は `prisma/migrations/20261025000719_update_aoj_jag_task_table_index/`
- seed に、本番だけにあった模擬地区 158 問を足した(grade は本番のまま。3355 の title は trim)
- 管理画面の取り込みで、JAG は全 round(模擬国内 / 模擬地区)で記号を付けるようにした
- 記号の対応表は、メンテナのスプレッドシートを書き写した照合スクリプトで作った(`git show c605d3bd:docs/dev-notes/2026-09-09/task-title-index-change-impact/generate_aoj_jag_problem_letters.ts`)

### 決定と理由

| 決定 | 理由 |
| ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 基本ルールで振り、8 コンテストはコンテストの全行を上書きする(45 行) | 8 コンテストは先頭や途中の問題が AOJ に無く、基本ルールでは記号がずれる。正しい記号は、メンテナのスプレッドシートの位置(欠けた問題を飛ばした位置)で決まる。全行を上書きするのは、1 つのコンテストに 2 つの規則を混ぜないため |
| 各ステップの更新件数を DO ブロックで検査し、想定外なら RAISE する | UPDATE は対象が 0 件でもエラーにならない。想定値は、空の DB(`prisma migrate reset`)の 0、模擬地区の無い開発 DB の 467 / 32 / 467、staging・本番の 625 / 45 / 467 |
| 件数は固定値のまま。模擬地区が一部だけの DB では RAISE し、エラー文で「全部取り込むか、全部消す」と案内する | 本番で範囲の誤りを止める力を保つため。模擬地区だけ実際の件数に合わせる案は、範囲の誤りを見逃しやすくなるので採らなかった |
| 順位はコンテストの全行で付け、更新は問題 ID のままの行だけにする | 後から記号付きで入る行(PR2.1)が先にあっても触らないため。順位を付ける側でも絞ると、記号の行と問題 ID の行が混ざったコンテストで A から振り直してしまう(Codex の指摘) |
| title から外すのは「自分の `task_id` + `. `」で始まるものだけ | `^[0-9]+\. ` で外すと、番号で始まる本来の title まで削りうる |
| 範囲は `contest_id` の接頭辞(`^JAG(Summer\|Winter\|Spring\|Regional)`)で絞る | `AOJ_JAG` には PR1 で記号にした模擬国内も含まれる |
| 取り込みでは補正しない(M14) | 8 コンテストは本番・staging・seed のすべてにあり、取り込みは既存の問題を skip する。Codex も「取り込みで補正すべき」と指摘したが、同じ理由で採らなかった |
| seed の検査は、補正した 8 コンテストを literal で、title を「問題名(`name`)と同じ」で見る | 補正の正しさは基本ルールの関数では検査できない。title は「問題 ID が前に付いていない」だけだと、空や別の問題の title にすり替わっても通る(Codex の指摘) |
| 前後に空白のある title(本番 46 件、3355 の末尾のタブを含む)は直さない | 表示では空白が潰れ、完全一致で比べるコードも無い。取り込みが trim するので再発もしない([plan.md](./plan.md#スコープ外)) |

### 検証で分かったこと

- **staging の準備**: staging には当初、模擬地区が 2 コンテスト / 16 問しか無く、件数チェックで RAISE するところだった。PR1.5 の後に staging で取り込み、PR を開く前に本番と同じ状態(模擬地区 16 / 158、合宿系 50 / 467、index はすべて問題 ID、title の問題 ID は合宿系だけ)であることを確かめた
- **seed の模擬地区**: 本番から取り出した 158 問は、AOJ の fixture(2026-05 記録)と問題 ID・コンテスト・名前がすべて一致した
- **照合**: スプレッドシートの書き写し(66 コンテスト)と 625 問の title が、記号の位置ですべて一致した。補正は 8 コンテスト / 45 行(事前の目視どおり)。わざと誤りを入れたコピー 5 種類(欠けた記号を外す、順番の入れ替え、途中の title の誤り、欠けた数の不足、切れた title の前半の誤り)はすべて検出された
- **ローカルでの移行**: 管理画面で模擬地区を取り込み、本番と同じ状態にしてから確かめた。`SELECT` のプレビューは 625 行すべてで照合の結果と一致し、適用後もプレビューと 625 / 625 で一致した。範囲外の AOJ(PCK、大学系、PR1 の範囲)は変わらない。`EXPLAIN` は CTE 側の Seq Scan 1 回と、`task_task_id_key` の Index Scan を使う Nested Loop
- **Codex の指摘の再現**: 記号の行と問題 ID の行が混ざったコンテストを読み取り専用で再現すると、直す前の SQL は A から振り直し、直した後は B, C, D と正しく振った。ローカルは移行前のスナップショットに戻し、直した移行を適用し直した(625 / 625)
- **テストの検出力**: 6 つの変異をすべて検出した(JAG の記号を PRELIM だけ / ICPC だけにする、補正した記号を基本ルールに戻す、基本ルールのコンテストで A・B を入れ替える、title に問題 ID を付け直す、模擬地区の記号を問題 ID に戻す)。title のテストは、空の title・別の問題の title・問題 ID の付け直しも検出する
- **Codex の他の指摘**: 「`task_id` だけで結合している」は、`task_id` が schema で `@unique` なので該当しない

### 残っている確認

- ~~staging~~ — #4220 で反映した(2026-10-25)。移行の後に Vercel のデプロイが走るので、件数チェックも通っている
- 本番(`main` への昇格後)で、移行が通ること
- 問題一覧の出典欄の表示(例: `JAG 夏合宿 2024 Day3 - H(AOJ)`)
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ PR0 / PR1 だけに関わる調査(出典欄の呼び出し元、テストの

# 1. PR2 の照合(2026-10-24)

メンテナのスプレッドシート(スクリーンショット 16 枚、行 2〜1025。上が新しい)と、本番の問題一覧の JAG 模擬地区(スクリーンショット 10 枚、158 問)を目視で突き合わせた。**目視による暫定の結果**であり、確定は [plan-pr2.md](./plan-pr2.md#2-2-照合) のスクリプトで行う。
メンテナのスプレッドシート(スクリーンショット 16 枚、行 2〜1025。上が新しい)と、本番の問題一覧の JAG 模擬地区(スクリーンショット 10 枚、158 問)を目視で突き合わせた。目視の結果で、PR2 の照合スクリプト(書き写したスプレッドシートとの機械的な照合)でも同じ結果になった([done.md](./done.md#pr2--jag-合宿系と-jag-模擬地区を問題記号にする4030))。

スプレッドシートで折りたたまれた行(40–50 ほか 19 か所)は JAG 模擬国内だけで、合宿系・模擬地区は含まない(メンテナに確認済み)。

Expand Down Expand Up @@ -228,7 +228,7 @@ AtCoder 側(`AOJ_*` 以外)で title が `${task_table_index}. ` で始ま

## PR2 の範囲の本番と staging(2026-10-24)

本番と staging で範囲の状態を集計した結果(SQL は [plan-pr2.md](./plan-pr2.md#確かめ方))。
本番と staging で範囲の状態を集計した結果(SQL は `git show 7c68cef6:docs/dev-notes/2026-09-09/task-title-index-change-impact/plan-pr2.md` の「確かめ方」)。

| 範囲 | 本番 | staging | index が問題 ID のまま | title が問題 ID 付き |
| -------- | -------- | ------------------------------- | ---------------------- | -------------------- |
Expand All @@ -238,7 +238,7 @@ AtCoder 側(`AOJ_*` 以外)で title が `${task_table_index}. ` で始ま
| Winter | 10 / 87 | 10 / 87 | 全行 | 全行 |

- staging には当初、模擬地区が 2 コンテスト / 16 問しか無かった。PR1.5(#4219)の後に staging で取り込み、本番と同じ 16 / 158 にそろえた(2026-10-24)
- 本番の模擬地区 158 問([plan-pr2.md](./plan-pr2.md#2-1-seed-に模擬地区を足す) の SQL で取り出したもの)は、AOJ の一覧のスクリーンショットと問題名・問題 ID がすべて一致した。grade が付いているのは 6 問
- 本番の模擬地区 158 問(本番から取り出したもの)は、AOJ の一覧のスクリーンショットと問題名・問題 ID がすべて一致した。grade が付いているのは 6 問
- 本番の 3355 の title の末尾にタブがある(`Most distant point from the stations\t`)。前後に空白のある title はほかにもある(下記)

## 前後に空白のある title
Expand Down
Loading
Loading