# たりない観察 v39.18.3 ## 実績システム 実績定義は `js/achievement_catalog.js` を唯一のカタログとして管理します。表示名、説明、カテゴリ、未解除時の公開設定、同期可能な進捗条件、累積上限は、クライアントと `achievement_api.php` が同じカタログから読み取ります。 累積進捗の正規データは端末・タブ別の増加台帳です。表示用 `progress` に同じ累積値を重複保存しません。旧形式の重複カウンターと `synced` 一覧は読込時だけ移行し、現行形式では保存しません。 「敵の敵は味方」は実績画面の「生態」カテゴリに掲載されます。 ## ローカル保存 実績状態とサーバー資格情報は、通常保存、予備保存、同一タブ保存、IndexedDBへ世代付きで保存します。起動時は同じ世代の状態を追加方向に統合し、明示的な実績リセット時だけ世代を進めます。 v39.18.3は、v39.18.0以前の実績保存、旧ワールド実績メタデータ、実績スペルv9・v10、旧バイナリセーブを読み込めます。旧データは現行形式へ正規化され、新規保存には廃止済みフィールドを書きません。 ## サーバー同期 同期プロトコルはv5です。 - 解除状態と途中進捗を追加型で統合 - 同じ端末台帳の再送を重複加算しない - リセット要求の再送を無害化 - 古いサーバーバックアップから新しいローカル世代を復旧 - 古い端末からリセット前の状態を復活させない - プレイヤーIDと所有秘密鍵を耐久保存から復旧 共有達成率は、サーバーがゲームシミュレーションを再実行した検証値ではなく、クライアント端末の報告値です。UIとAPIでは「端末報告ベース」と明示します。 ## 旧サーバーデータの自動移行 データディレクトリ、またはアプリ直下の `.achievement_data` に旧コンパクト形式の `state.json`(スキーマ4)がある場合、最初のAPI要求時に現行形式へ自動移行します。環境変数で新保存先を指定した場合や、v39.18.1が空の現行保存先を先に作成済みの場合も検出します。 - 原本は `legacy-backup/` へSHA-256付きで保存 - 旧プレイヤーIDから決定的なUUIDを生成 - プレイヤー数、解除実績、解除時刻、実績別集計を移行 - 旧データに存在しない途中進捗は0から開始 - `legacy-v4-migration.json` に完了件数を記録 - 中断時は次のAPI要求で冪等に再開 - 切替中にコピー元の旧 `state.json` が更新された場合も、内容ハッシュを再確認して追加方向で再取込 - ファイルサイズとmtimeが同じ更新もSHA-256比較で検出 旧ブラウザーに22文字のプレイヤーIDが残っている場合、クライアントはUUIDへ上書きする前に専用領域へ退避し、初回セッションで一度だけ新しい所有秘密鍵へ引き継ぎます。引継ぎ済みの旧IDを別の秘密鍵で再取得することはできません。 旧版から直接v39.18.3へ更新したブラウザーは自動引継ぎできます。v39.18.1を既に起動して旧22文字IDがブラウザーから失われている場合、サーバーデータだけから端末との本人対応を再構成することはできません。解除履歴と共有集計自体は正常に移行されます。 ## 実績APIの保存先 本番環境では、PHP実行ユーザーが書き込める非公開ディレクトリを用意し、環境変数 `TARINAI_ACHIEVEMENT_DATA_DIR` に絶対パスを設定してください。未設定時は、HTTP公開ディレクトリ外の安定したユーザーデータ領域を使用します。 ## PHP組み込みサーバーでの起動 PHP組み込みサーバーは `.htaccess` を解釈しません。旧 `.achievement_data/state.json` には引継ぎ用IDが含まれるため、必ず同梱のルーターを使用してください。 ```sh ./start_server.sh 8000 ``` Windowsでは `start_server.bat 8000` を使用します。本番環境では引き続き `TARINAI_ACHIEVEMENT_DATA_DIR` をHTTP公開ディレクトリ外へ設定してください。