反射便 教材 QA / 2026-10-05 UTC

対象
01_aim.py / 02_velocity.py / 03_sweep.py / 04_reflect.py / 05_remaining.py
Python 3.12.14 / Linux / 実Pyxel 2.9.9（既存環境を使用。インストール操作なし）
対象環境の最低要件はPython3.11以上。Python3.11実機の再試験は未実施。

1. 純粋モデル + 入力/描画スタブ
原作比較あり: 19テスト全件合格。qa/test_results.txt。
単独配布構成: 19テスト中18合格、原作比較1件だけ想定どおりスキップ。
qa/test_results_standalone.txt。
テスト実行は-B付き。原作は読み取りimportのみで、原作横へbytecodeを書かない。

確認したこと:
- 全段階の一度だけ発射、初期状態、R、R+Space同時押し
- 実入力と同じcontrol経由で-45度からUP×23更新、Space、終端へ到達
- 96px/秒と秒の積、角度→速度、異常なangle/dtの拒否
- 終端後の位置・時刻・軌跡の凍結、05のP中の停止とRでの解除
- 薄い壁の掃引、遠い壁より手前の壁、受取優先/壁優先の比較
- 壁と受取の同着およびEPS以内、角のX法線優先、壁番号順、小数9桁丸め
- 移動量ゼロ、平行線分、円への接線接触
- 反射速度長の保存、法線成分の符号反転、法線の符号を反転しても同じ結果
- 2枚目の鏡で停止、同じ刻み内の二度接触、6秒終了
- 0.5秒の大きな刻みで04のy=18.01と05のy=44.01
- 最終成功のdt=1/30・1/120・1/240で配達点の一致
- 全段階のUI状態・ASCIIテキスト・12描画後の保存をスタブで確認
- lessons.jsonの抜粋が実際の該当ソースに存在すること

2. 原作との宣言した比較範囲
原作011のmodel.pyにあるLEVELS[1]（B「塀の向こう」）と05を比較。
75角度（-180〜180を5度刻みの73角度、追加-50.75/-50.8）×3刻み幅。
合計225試射の毎更新について、pos、vel、status、bounces、used、age、traceが一致。
原作A/C、原作UI、あらゆる実数入力、入力デバイスやプラットフォームの同等性を
主張するものではない。完全な数学的証明でもない。
実行時はREFLECTION_ORIGINAL_DIRを原作011フォルダーへ指定した。
原作自体はこの教材に同梱しない。原作ソースのSHA-256はsource_provenance.json。

3. 実Pyxelのヘッドレス描画
5本それぞれで初期状態と到達点を実行し、12回の描画後にPNGへ保存。
全10プロセス正常終了、全PNGは768×720。各段階は他の段階をimportしない。
再現用スクリプト: qa/render_all.py。
コマンド形式:
python -B 03_sweep.py --headless-smoke --screenshot qa/03_sweep_initial.png
python -B 03_sweep.py --headless-smoke --demo-checkpoint --screenshot qa/03_sweep_outcome.png

初期画面5枚: 発射なし、ANGLE -45.00、TIME 0、反射0。
到達点（モデルの自動入力で-50.75度を発射してから実描画）:
01: aimed、位置(32,96)、時間0、反射0
02: outside、位置(110.45546,-0.02469)、約1.29167秒、反射0
03: wall、位置(95.72867,18)、約1.05秒、反射0
04: delivered、位置(155.88305,91.63528)、約2.04167秒、反射1
05: delivered、位置(155.88305,91.63528)、約2.04167秒、反射1
04と05が同じ表示時間でも、余り時間処理の実装が同じという意味ではない。
差は大きい刻みの数値テストで明示した。

4. 画像確認
最終ソースから再生成した初期5枚と到達点5枚を画像ビューアで全件確認した。
タイトル、キー案内、ANGLE/TIME/BOUNCES、始点、塀、受取口が読める。
03の上鏡接触印とラベルの重なりを見つけ、ラベルを左へ移して全10枚を再生成。
再確認で03は接触×が明瞭、04/05は折り返し軌跡と受取チェックが明瞭。
02の中心は画面外へ出るため終端の×は上部ヘッダー外へ隠れる。
場外の軌跡、STOP表示、TIMEで結果を読み取れる。これは未衝突段階の意図した結果。
この画像確認はアシスタントによる画像検査であり、人の実機プレイではない。

5. 限界と環境ログ
実描画である。Pyxelスタブが描いたPNGではない。
到達点は合成入力・モデル自動進行後の静止画であり、人の操作記録ではない。
ネイティブOSのウィンドウ/キーボード/閉じる操作、macOS/Windows実機、
ブラウザー、音声、実時間動画、人による学習効果や面白さは未検証。
ヘッドレス環境の音声デバイス初期化警告はrender_log.txtに保存。
音声を使わない教材で、描画・保存・終了は成功した。音声が動くとは主張しない。
Sites、公開、原作やサイトcheckoutへの変更は行っていない。

6. 配布前整合性
UTF-8指定で本文を読み書き。requirements.txtはpyxel==2.9.9。
MIT原文の全文を各段階冒頭へコメントとして保持し、LICENSEも同梱。
Noto由来字形を教材へ同梱しない。UI文字はASCII。
README.txtのZIPルート/.venvコマンド、段階到達点、近似、省略範囲を記載。
lessons.jsonの5エントリー、lesson_meta.json、4本の隣接diffを生成。
最終ファイル一覧のSHA-256はsha256_manifest.json。引き渡し後は凍結する。
