「9種セット」の正体は御三家9商品だった:同じ商品なのに、決して一致しなかった
トレカダッシュ 開発の記録 / 2026年10月
iOS アプリ「トレカダッシュ」は、トレカの抽選・先着情報を集めて通知します。集めた情報に抜けがないか調べるため、他のまとめサイト(抽選図鑑、ポケチュー)の掲載と、自分のアプリの記事を突き合わせて数えています。10月7日に測ったところ、抜けの多くは、同じ商品なのに、決して一致しないという、小さな食い違いが原因でした。HANDOFF とコミットの記録で書きます。
このサイトには、トレカダッシュの作品ページはまだありません。ここに書くのは、開発の記録です。
測ったこと
「まとめサイトが紹介している抽選が、全部アプリに出ているか」を、読み取りだけで確かめました。
- 抽選図鑑:受付中 90 件のうち、アプリに表示されているのは 49 件(54%)。記事はあるのに非表示が 12 件、フィードに無いのが 29 件。
- ポケチュー:21 件のうち 18 件(86%)。
- X のまとめ投稿:72 時間で 606 投稿。記事に結び付いたのは 9 件。
非表示 12 件のうち 7 件は、行のほうが間違っていた
非表示だった 12 件を調べると、7 件は、まとめサイトの行が応募ページと違う商品を書いていました。ある系列の 4 店は「エネルギーカードセット」、別の 3 店は「拡張パック」と書いてあります。応募ページ(抽選の応募フォーム)と店の X を見ると、実際は「カードセット 9種セット 10,800円」でした。
アプリの「価格の関門」(商品の定価と出品価格が合わないものを弾く仕組み)は、これを正しく弾いていました。間違っていたのは関門ではなく、商品の取り違えのほうです。商品を付け替えて、表示に戻しました。
「9種セット」の正体
この「9種セット」は、ポケモンカードの 30th CELEBRATION のカードセットで、歴代 9 世代の御三家(3 匹)のセットが 9 商品あるものでした。カタログには、この 9 商品が、もともと正しい形で登録されていました。ところが、マーケットプレイスの出品や X の監視が新しい記事を作るたびに、3 匹のうち 1 匹だけの名前の、別の商品として登録されてしまうバグが、9 商品のうち複数で起きていました。たとえば「ヒノアラシ」だけの商品です。
同じ商品なのに、一致しない
突き合わせの仕組みには、商品名を比べるための「キー」を作る処理があります。ここに、左右非対称がありました。
- 相手側の「カードセット9種」は、末尾の「9種」を落として比べる。
- カタログ側の「カードセット 9種類セット」は、落とさない。
同じ商品なのに、決して一致しません。そのため、相手の名前は「エネルギーカードセット」や「拡張パック」といった別の商品に、誤って解決されていました。これが、取り違えの出どころでした。両方に同じ規則(「N 種」「N 種類」「セット」を落とす)を当て、さらに、数の指定がある名前は、部分一致で一つに決めないようにしました。カタログ全体で、キーの衝突が 0 であることも確かめています。
もう一つの穴:前回の記事が、次の回を止めていた
「フィードに無い」の主な原因は、別にありました。記事の ID が「まとめの URL + 店 + 商品」で作られていて、抽選の回が含まれていなかったのです。前回の期限切れの記事が、同じ店・同じ商品の新しい回の記事を作るのを止めていました(「同じ記事 ID が既にある」)。新しい回の締切が前回より 1 日超あとなら、日付を足した別の ID で作るようにしました。
結果
| カバー率 | 前 | 後 |
|---|---|---|
| 抽選図鑑(受付中 90 件) | 54%(49件) | 91%(82件) |
| ポケチュー | 86% | 90% |
残りは、応募ページが「商品各種」としか書いておらず商品を特定できないもの、店名の手がかりがページに無いもの、などです。「安全のため採用しない」と決めたものも含まれています。取りこぼしがゼロになったわけではありません。
分かったこと
正しく弾いた関門と、間違っていたデータは、別の問題。
- 弾いたものを疑う前に、弾かれた理由を見る。価格の関門は正しく動いていて、間違っていたのは商品の取り違えでした。
- 「一致しない」の原因が、比べ方の左右非対称のことがある。同じ商品が決して一致しないのは、データの汚れではなく、規則の食い違いでした。
- カバー率を数えないと、抜けは見えない。54% という数字が出て、はじめて、どこを直すかが決まりました。
この記事の数字は、HANDOFF(§272、§281)とコミット(2026年10月7日)の記録から取りました。
この話に出てくるもの
- 「減るはず」が、二度外れた — 同じアプリの、AI への問い合わせの記録
- JSONLを読んだら壊れた — 見た目では分からない食い違いの、別の記録
ほかの記録
- 「9種セット」を中身ごとに分けて、偽の商品が80個できていた — ポケモンカードの9種セットは1つの商品なのに、中身ごとに分けて、実在しない商品が80個できていた。入口を止め、親22件を戻し、子190件を外し、偽の商品を消した記録。
- 「重複は実質ゼロ」と数えたのに、監査は112組を出していた — 重複を統合する処理が、毎晩、先頭のジャンルの途中で時間切れになっていた。「ゼロ」と数えた自分の測り方が間違っていた。持ち回りに直して112組を0組にした記録。
- iOS アプリが固まって強制終了される(0x8BADF00D):SwiftUI の計算プロパティが毎回走っていた — 実機のログにあった 0x8BADF00D(watchdog)。951件の記事を、画面を描き直すたびにメインスレッドで数え直していた。原因の特定と、バックグラウンドで計算する形に直した記録。
コメント
感想や、記事の間違いの指摘は、ここへ。書くには、GitHub のアカウントが要ります。
押すと、giscus(giscus.app)と GitHub に接続します。押さなければ、接続しません。詳しくはあつかいに書いています。