# KLE JSON 互換性設計 ## 双方向変換戦略 ### Beyond KLE → KLE JSON #### 1. フラット化プロセス ```typescript interface ConversionOptions { preserveIds: boolean; // IDを保持するか preserveClusterInfo: boolean; // クラスター情報を保持するか idEmbedMethod: 'metadata' | 'label' | 'comment'; } function convertToKLE(beyondKle: PHYLayer, options: ConversionOptions): KLELayout { const flatKeys = flattenElements(beyondKle.elements); return { name: beyondKle.metadata.name, keys: flatKeys.map(key => convertKey(key, options)) }; } function flattenElements(elements: Element[], parentTransform?: Transform): FlatKey[] { const result: FlatKey[] = []; for (const element of elements) { if (element.type === 'key') { const absolutePos = applyTransform(element.position, parentTransform); result.push({ ...element, absolutePosition: absolutePos, clusterPath: getClusterPath(element) }); } else if (element.type === 'cluster') { const clusterTransform = combineTransforms(parentTransform, element.position); result.push(...flattenElements(element.elements, clusterTransform)); } } return result; } ``` #### 2. ID保持方法の比較 | 方法 | メリット | デメリット | KLE互換性 | |------|----------|------------|-----------| | `_beyondkle` メタデータ | 構造化された情報保持 | KLEパーサーが無視する可能性 | △ | | ラベル9番目位置 | 確実に保存される | 表示されてしまう | ○ | | コメントフィールド | 非表示 | 標準的でない | △ | #### 3. 推奨アプローチ: ハイブリッド方式 ```json { "name": "Split Layout (Generated by Beyond KLE)", "_beyondkle": { "version": "1.0.0", "sourceFile": "layout.beyond.json", "conversionSettings": { "flattenClusters": true, "preserveRotations": true } }, "keys": [ { "x": 0, "y": 0, "w": 1, "h": 1, "t": "#000000\n\n\n\n\n\n\n\n\nk00", "_beyondkle": { "id": "k00", "clusterPath": ["left_half", "left_main"], "relativePosition": { "x": 0, "y": 0 }, "absolutePosition": { "x": 0, "y": 0 } } } ] } ``` ### KLE JSON → Beyond KLE #### 1. ID復元戦略 ```typescript function convertFromKLE(kleLayout: KLELayout): PHYLayer { // 1. メタデータからBeyond KLE情報を取得 const beyondKleInfo = kleLayout._beyondkle; if (beyondKleInfo?.sourceFile) { // 元のBeyond KLEファイルが指定されている場合 return reconstructFromSource(kleLayout, beyondKleInfo); } // 2. キーからIDとクラスター情報を抽出 const keys = kleLayout.keys.map(kleKey => { const id = extractId(kleKey); const clusterInfo = extractClusterInfo(kleKey); return { type: 'key' as const, id: id || generateId(kleKey), profile: 'default', position: { x: kleKey.x, y: kleKey.y }, size: { width: kleKey.w || 1, height: kleKey.h || 1 }, metadata: extractMetadata(kleKey) }; }); // 3. クラスター構造の再構築 return reconstructClusters(keys); } function extractId(kleKey: any): string | null { // 1. _beyondkle メタデータから if (kleKey._beyondkle?.id) return kleKey._beyondkle.id; // 2. ラベル9番目から if (kleKey.labels?.[8]) return kleKey.labels[8]; // 3. t文字列の解析 const tMatch = kleKey.t?.match(/\n([a-zA-Z0-9_]+)$/); if (tMatch) return tMatch[1]; return null; } ``` #### 2. クラスター再構築アルゴリズム ```typescript function reconstructClusters(flatKeys: Key[]): Element[] { // クラスター情報が保持されている場合 const clusteredKeys = groupByCluster(flatKeys); if (Object.keys(clusteredKeys).length > 1) { return Object.entries(clusteredKeys).map(([clusterName, keys]) => ({ type: 'cluster' as const, id: clusterName, name: clusterName, position: calculateClusterOrigin(keys), elements: keys.map(key => ({ ...key, position: makeRelativeToCluster(key.position, clusterOrigin) })) })); } // クラスター情報がない場合は自動推定 return autoDetectClusters(flatKeys); } function autoDetectClusters(keys: Key[]): Element[] { // 座標の近さとレイアウトパターンからクラスターを推定 // 1. 連続する矩形領域の検出 // 2. 回転角度の類似性 // 3. 一定の間隔での分離 const clusters = detectSpatialClusters(keys); if (clusters.length === 1) { // 単一クラスターの場合はフラットに return keys; } return clusters; } ``` ## 実装における考慮事項 ### 1. バージョン管理 ```json { "_beyondkle": { "version": "1.0.0", "generator": "beyond-kle-converter", "timestamp": "2025-11-09T12:00:00Z", "preservedData": { "clusters": true, "rotations": true, "profiles": false } } } ``` ### 2. 設定可能な変換オプション ```typescript interface ConversionSettings { // ID保持方法 idPreservation: 'metadata' | 'label' | 'both' | 'none'; // クラスター処理 clusterHandling: 'preserve' | 'flatten' | 'auto'; // 回転の処理 rotationHandling: 'preserve' | 'flatten'; // プロファイル情報 includeProfiles: boolean; // 互換性レベル compatibilityLevel: 'strict' | 'extended' | 'beyondkle'; } ``` ### 3. 往復変換の整合性保証 ```typescript // テストケース const originalBeyondKLE = loadBeyondKLE('test.beyond.json'); const kleJson = convertToKLE(originalBeyondKLE, settings); const reconstructed = convertFromKLE(kleJson); // 構造的等価性の検証 assert(structurallyEquivalent(originalBeyondKLE, reconstructed)); ``` ## ワークフロー例 ### 1. Beyond KLE → 外部ツール → Beyond KLE ```bash # Beyond KLE → KLE JSON (ID付き) beyond-kle export --format=kle --preserve-ids layout.beyond.json # 外部ツール(KLE等)で編集 # ... # KLE JSON → Beyond KLE (構造復元) beyond-kle import --format=kle --auto-cluster edited.kle.json ``` ### 2. 段階的移行 ```bash # 既存のKLE JSON → Beyond KLE beyond-kle import legacy.kle.json # Beyond KLE で編集・管理 # 必要に応じてKLE JSONで共有 beyond-kle export --format=kle-compatible project.beyond.json ``` この設計により、Beyond KLEの高度な機能を使いながらも、既存のKLEエコシステムとの互換性を保てると思いますが、いかがでしょうか?