From c31360a772d8121cb970093247e944744da7d007 Mon Sep 17 00:00:00 2001 From: EwdErna Date: Mon, 21 Sep 2026 21:57:45 +0900 Subject: [PATCH] =?UTF-8?q?phy:=20=E8=A1=8C=E3=81=AE=E5=85=88=E9=A0=AD?= =?UTF-8?q?=E4=BB=A5=E5=A4=96=E3=81=AE=20r,=20rx,=20ry=20=E3=82=92?= =?UTF-8?q?=E5=8F=96=E3=82=8A=E8=BE=BC=E3=81=BF=E3=81=A7=E5=8F=97=E3=81=91?= =?UTF-8?q?=E5=85=A5=E3=82=8C=E3=82=8B(P-16=E8=A7=A3=E6=B6=88)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit KLE本家は拒否するが、VIAとRemapは読む。Remapで扱える基板を取り込めない 状態にしないため、位置を問わず受け入れる。本家のコードから行頭チェックを 外した挙動をそのまま採る。出力は従来どおり行頭にのみ置く。 Journal: journal/2026-09-21-kle-lenient-row.md Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01SSKcJLPAaPLchG4LXxk6cY --- PHYレイヤー.md | 12 ++--- journal/2026-09-21-kle-lenient-row.md | 66 +++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 journal/2026-09-21-kle-lenient-row.md diff --git a/PHYレイヤー.md b/PHYレイヤー.md index 1ebafde..51a77c8 100644 --- a/PHYレイヤー.md +++ b/PHYレイヤー.md @@ -334,6 +334,7 @@ const kleData = (ConfigObject | KeyLabel)[][] - ユニットサイズ(mm)、ビジュアルオフセット、クラスター構造、部品ノード、per-key LEDはKLE JSONに出力されない - バリアント構造はKLE JSONに出力しない。VariantGroupごとにバリアントを1つ選び、その配下だけを畳んで出力する - 部品グループ・スイッチの向きはKLE JSONに出力しない。sm, sb, st には取り込み時に保持した値をそのまま書き戻す +- r, rx, ry は行の先頭にのみ置く。KLE本家はそれ以外の位置に置かれたものを読まない - p, sm, sb, st は空文字に戻す指定がKLE側で無視される。値を持つキーと持たないキーが混在する配置は、 KLEで開いた時点で後続のキーに前の値が残る - KLEの `p` はキーキャップのプロファイル名(SA、DCSなど)であり、PHYのプロファイルとは対応させない @@ -348,7 +349,9 @@ const kleData = (ConfigObject | KeyLabel)[][] - 構造の復元は保証しない。KLE側での編集が大きいほど、クラスター構造は失われる - 配列の順番は照合に使わない。KLEは保存時にキーを「角度 → rx → ry → y → x」の順に並べ替えるため、順番は形状から決まる以上の情報を持たない -r, rx, ry を行の先頭以外に置いたKLE JSONが公開されている。KLE本家はこれを読み込まずエラーにする。 +r, rx, ry は行の先頭以外に置かれていても受け入れ、そのキー以降に適用する。 +rx, ry を持つキーでは、座標を (rx, ry) に戻してから x, y を加える。 +KLE本家はこの位置の r, rx, ry をエラーにするが、VIAとRemapは読む。Remapで扱える基板を取り込めない状態にしない。 KLEの rx, ry, r はキーの絶対配置 (x, y, rotation) に変換して取り込む。元の rx, ry は保持しない。 @@ -403,10 +406,3 @@ Beyond KLEはスイッチの品種を持たないため、対応づける先が - 位置づけ: 未解決の問い。数値入力以外に、原点をどこへ吸着させるか - 現状の認識: キーのローカル原点(左上角)・キー中心・境界矩形の角と中心が候補。相対グリッドとは別の機構になる - 格上げ条件: 原点移動を実装し、吸着なしで足りるか、足りない場合どの候補が要るかを確認する - -### P-16 KLE本家が拒否するJSONを取り込むか - -- 位置づけ: 未解決の問い。本文「KLE JSONの取り込み」が扱えていない -- 現状の認識: r, rx, ry を行の先頭以外に置いたJSONが公開されている(1505件中1件)。KLE本家はエラーにするが、 - VIAのパーサーは読める。本家に合わせて拒否するか、読めるものは読むかが未定 -- 格上げ条件: 取り込みの寛容さの方針をユーザーが決める diff --git a/journal/2026-09-21-kle-lenient-row.md b/journal/2026-09-21-kle-lenient-row.md new file mode 100644 index 0000000..3ed9ae3 --- /dev/null +++ b/journal/2026-09-21-kle-lenient-row.md @@ -0,0 +1,66 @@ +# 行の先頭以外の 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 が読め、配置も元と一致した。寛容化は本家で開けないファイルの修復経路になる。