# 行の先頭以外の r, rx, ry を受け入れるか ## 結論 受け入れる。位置を問わず、そのキー以降に適用する。rx, ry は座標を (rx, ry) に戻してから x, y を加える (KLE本家のコードから行頭チェックだけを外したときの挙動と同じ)。 決め手は Remap が読めること。ユーザーの判断: 「Remapで扱えるものを拒否したくない」。 | 案 | 取り込める基板 | 既存の解釈への影響 | 出力への影響 | | --- | --- | --- | --- | | 本家に合わせて拒否 | 1505件中1504件 | なし | なし | | **r だけ受け入れ** | 1505件 | なし | なし | | **r, rx, ry とも受け入れ(採用)** | 1505件 | なし | なし | 3案とも出力は変わらない。本家の serialize はクラスターが変わると必ず行を割るので、 r, rx, ry は常に行頭にしか出ない。寛容化しても非互換なJSONを生む側には回らない。 ## 実データ コーパス1505件(KLE本家プリセット12 + samples 9 + the-via/keyboards 1484)で、 行の先頭以外の r, rx, ry を持つのは `owlab/spring/spring.json` の1件だけ。内訳は r が15回、rx/ry は0回。 spring は Alice系。物理行ごとに配列を1つ書き、行の途中で r を 0 → 12 → -12 → 0 と切り替えている。 行頭チェックを外して読むと素直に開く(67キー、左右±12度のスプレイ + 回転なしの外側2列)。 ``` 0,3 x=3.25 r=0 0,4 x=4.44 r=12 0,8 x=8.72 r=-12 0,12 x=12.85 r=0 1,2 x=2.50 r=0 1,3 x=3.70 r=12 1,7 x=8.48 r=-12 1,11 x=12.60 r=0 ``` ## 寛容化が既存の解釈を変えないこと 本家 serial.js の該当箇所は throw だけで、意味づけは残りの行が決めている。 ```js if(key.r != null) { if(k!=0) {deserializeError(...)} current.rotation_angle = key.r; } if(key.rx != null) { if(k!=0) {deserializeError(...)} current.rotation_x = cluster.x = key.rx; extend(current, cluster); } ``` throw を3つ消したパーサーと本家で全1505件を読み比べ、本家が読めた1504件は**キー配列が完全一致**。 変わるのは今エラーになる1件だけ。 ## 他のツールの受け入れ | ツール | 行の途中の r/rx/ry | 根拠 | | --- | --- | --- | | KLE本家 `serial.js` | 拒否 | `'r' can only be used on the first key in a row` | | kle-serial (ijprest, TS移植) | 拒否 | 同じチェックを移植 | | Vial `kle_serial.py` | 拒否 | `k != 0 and ("r" in item or ...)` | | kicad-kbplacer | 拒否 | 同じチェックあり | | VIA `@the-via/reader` | 許容 | reduceで位置チェックなし | | Remap `KeyboardModel.ts` | 許容 | `Current.setOp()` に位置チェックなし | | QMK `kle2xy.py` | 無関係 | r/rx/ry を読まない(回転を捨てる) | Remap の `Current` を位置計算だけ移植して、throw を外した本家と突き合わせた。行の途中の r、 行の途中の rx/ry、途中で r=0 に戻す、spring 全体、いずれも一致する。VIA reader はコードを読んだだけで、 `cursor.y = ry` としか書いていないため rx/ry の扱いは本家と違う可能性がある(spring は rx=ry=0 なので影響なし)。 同じ突き合わせをコーパス全件でやると19件が不一致になるが、いずれも行頭側の ry の解釈やラベルなしキーの扱いで、 今回の話とは別件。簡易移植での比較なので Remap 本体で再現したわけでもない。追っていない。 ## 取り込んで書き戻す spring を寛容パーサーで読み、PHY経由で本家の serialize に通すと、5行 → 26行のJSONになる。 本家の deserialize が読め、配置も元と一致した。寛容化は本家で開けないファイルの修復経路になる。