const fs = require('fs'); const path = require('path'); const JSON_FILES = [ 'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.BusinessLogic.json', 'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.ImageProcessor.json', 'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.ScannerController.json', 'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.TransportManager.json', 'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.UIView.json' ]; // 1.優先 // team_task_classification 團隊分工覆寫 const PRIM_TAGS_TO_FIE = { // // ScannerController // 'ScannerController.acquisitionHandler': 'scan/acquisition.pas', // 'ScannerController.twainWrapper': 'scan/twain.pas', // // // ImageProcessor // 'ImageProcessor.transformer': 'img/transformer.pas', // 'ImageProcessor.converter': 'img/converter.pas', // 'ImageProcessor.anchorAnalyzer': 'img/anchor.pas', // 'ImageProcessor.payloadArchiver': 'img/imgArchiver.pas', '初始化與生命週期': 'CB_IMGPSScanImp.lfcycle.pas', 'API 呼叫相關': 'CB_IMGPSScanImp.api.pas', '轉換區(名稱/格式轉換)': 'CB_IMGPSScanImp.convert.pas', '案件管理(TreeView / 案件操作)': 'CB_IMGPSScanImp.caseMgr.pas', '清單管理': 'CB_IMGPSScanImp.listMgr.pas', '檔案操作': 'CB_IMGPSScanImp.fileOp.pas', '上傳前置資料產生': 'CB_IMGPSScanImp.prUpload.pas', '文件份數/頁數/查詢': 'CB_IMGPSScanImp.docq.pas', '自訂文件': 'CB_IMGPSScanImp.custdoc.pas', '舊案/異動件處理': 'CB_IMGPSScanImp.docmod.pas', '入庫文件/可見性': 'CB_IMGPSScanImp.inbound.pas', // '影像瀏覽/顯示': 'CB_IMGPSScanImp.image.pas', 'OMR 檢核': 'CB_IMGPSScanImp.omr.pas', '縮圖預覽(PreViewISB)': 'CB_IMGPSScanImp.preview.pas', '其他內部': 'CB_IMGPSScanImp.misc.pas', } // 2.若 1未定義到, 則從這裡分類 const TAGS_TO_FILE = { // ScannerController 'ScannerController.acquisitionHandler': 'scan/acquisition.pas', 'ScannerController.twainWrapper': 'scan/twain.pas', // ImageProcessor 'ImageProcessor.transformer': 'img/transformer.pas', 'ImageProcessor.converter': 'img/converter.pas', 'ImageProcessor.anchorAnalyzer': 'img/anchor.pas', 'ImageProcessor.payloadArchiver': 'img/imgArchiver.pas', // TransportManager 'TransportManager.apiClient': 'transp/apiClient.pas', 'TransportManager.fileTransfer': 'transp/fileClient.pas', 'TransportManager.certificateManager': 'transp/certManager.pas', 'TransportManager.payloadArchiver': 'transp/payloadArchiver.pas', // BusinessLogic 'BusinessLogic.systemInternal': 'bloc/sys.pas', 'BusinessLogic.configRepository': 'bloc/cfg.pas', 'BusinessLogic.ormRuleEngine': 'bloc/ormRuleEngine.pas', 'BusinessLogic.entityMapping': 'bloc/entityMapping.pas', 'BusinessLogic.fileManager': 'bloc/fileManager.pas', 'BusinessLogic.caseManager': 'bloc/caseManager.pas', 'BusinessLogic.entityModel': 'bloc/entityModel.pas', 'BusinessLogic.activeXWrapper': 'bloc/ocx.pas', // UIView 'UIView.statusMessenger': 'view/msger.pas', 'UIView.events': 'view/events.pas', 'UIView.i18n': 'view/i18n.pas', 'UIView.inputHandler': 'view/input.pas', 'UIView.configRepository': 'view/cfg.pas', 'UIView.treeView': 'view/treeView.pas', 'UIView.toolBar': 'view/toolBar.pas', 'UIView.imageScrollBox': 'view/isb.pas', 'UIView.popupMenu': 'view/popupMenu.pas', 'UIView.listView': 'view/listView.pas', 'UIView.scrollView': 'view/scrollView.pas', 'UIView.misc': 'view/misc.pas' }; const SRC_FILE = 'CB_IMGPSScanImp.pas.bk'; const DEST_FILE = 'CB_IMGPSScanImp.pas'; const OUTPUT_DEST = 'reassemble'; const REMAININGS_FILE = 'scripts/dist/scanimpl_annalysis.remainings.txt'; function getVisualWidth(str) { let width = 0; for (let i = 0; i < str.length; i++) { const code = str.charCodeAt(i); if (code >= 0x4e00 && code <= 0x9fff) { width += 2; } else { width += 1; } } return width; } function wrapText(text, limit, wrapIndent) { if (!text) return ""; // 處理 1. 2. 3. 這種標示點,先進行初步換行 // 尋找符合 "數字." 的模式,並在其前面加上換行符(如果不是在開頭的話) let formattedText = text.replace(/(\d+\.)/g, (match, p1, offset) => { return offset === 0 ? match : "\n" + match; }); const segments = formattedText.split('\n'); let resultLines = []; segments.forEach(segment => { let currentLine = ""; let currentLineWidth = 0; // 將 segment 依字元處理 for (let i = 0; i < segment.length; i++) { const char = segment[i]; const charWidth = getVisualWidth(char); if (currentLineWidth + charWidth > limit) { resultLines.push(currentLine); currentLine = char; currentLineWidth = charWidth; } else { currentLine += char; currentLineWidth += charWidth; } } if (currentLine) resultLines.push(currentLine); }); return resultLines.join("\n" + wrapIndent); } function getDocString(m) { const methodName = m.matcher.match(/^(procedure|function)\s+TCB_IMGPSScanX\.([\w\.]+)/i)?.[2] || m.matcher; const deps = (m.deps || []).join(', '); const wrappedDeps = wrapText(deps, 68, " "); const desc = m.description || ''; const wrappedDesc = wrapText(desc, 68, " "); return `{ ============================================================================== 方法名稱:${methodName} 引用相依:${wrappedDeps} 方法描述:${wrappedDesc} ============================================================================== }\n`; } function main() { console.log('Copying ' + SRC_FILE + ' to ' + DEST_FILE); fs.copyFileSync(SRC_FILE, DEST_FILE); const originalContent = fs.readFileSync(DEST_FILE, 'utf8'); const lines = originalContent.split(/\r?\n/); const allMethods = []; JSON_FILES.forEach(jsonFile => { if (!fs.existsSync(jsonFile)) return; const data = JSON.parse(fs.readFileSync(jsonFile, 'utf8')); data.forEach(m => { const lIndex = parseInt(m.lIndex); const rIndex = parseInt(m.rIndex); if (lIndex > 0 && rIndex > 0) { allMethods.push({ ...m, lIndex, rIndex }); } }); }); const lineToTargetFile = new Array(lines.length + 1).fill(null); const fileToMethods = {}; allMethods.forEach(m => { let targetFile = null; // team_task_classification 團隊分工覆寫 if (!targetFile) { for (const tag of m.tags) { if (PRIM_TAGS_TO_FIE[tag]) { targetFile = PRIM_TAGS_TO_FIE[tag]; break; } } } if (!targetFile) { for (const tag of m.tags) { if (TAGS_TO_FILE[tag]) { targetFile = TAGS_TO_FILE[tag]; break; } } } if (!targetFile) targetFile = 'view/misc.pas'; if (!fileToMethods[targetFile]) { fileToMethods[targetFile] = []; } fileToMethods[targetFile].push(m); for (let i = m.lIndex; i <= m.rIndex; i++) { if (i <= lines.length) { lineToTargetFile[i] = targetFile; } } }); // Create sub-files for (const targetFile in fileToMethods) { const methods = fileToMethods[targetFile]; methods.sort((a, b) => a.lIndex - b.lIndex); let subFileContent = ''; methods.forEach(m => { const methodLines = lines.slice(m.lIndex - 1, m.rIndex); subFileContent += getDocString(m) + methodLines.join('\n') + '\n\n'; }); const fullPath = path.join(OUTPUT_DEST, targetFile); fs.mkdirSync(path.dirname(fullPath), { recursive: true }); fs.writeFileSync(fullPath, subFileContent); console.log(`Saved ${methods.length} methods to ${fullPath}`); } // Rewrite main file and generate remainings const newMainLines = []; const remainingsLines = []; const includedFiles = new Set(); for (let i = 1; i <= lines.length; i++) { const targetFile = lineToTargetFile[i]; if (targetFile) { if (!includedFiles.has(targetFile)) { newMainLines.push(`{$I ${OUTPUT_DEST}/${targetFile}}`); includedFiles.add(targetFile); } } else { newMainLines.push(lines[i - 1]); remainingsLines.push(lines[i - 1]); } } const finalContent = newMainLines.join('\n'); fs.writeFileSync(DEST_FILE, finalContent); if (!fs.existsSync(path.dirname(REMAININGS_FILE))) { fs.mkdirSync(path.dirname(REMAININGS_FILE), { recursive: true }); } fs.writeFileSync(REMAININGS_FILE, remainingsLines.join('\n')); console.log('\n--- Content of ' + DEST_FILE + ' after disaggregation ---\n'); console.log(finalContent.substring(0, 1000) + '\n...'); console.log('\n--- End of Preview ---\n'); console.log('Remainings saved to: ' + REMAININGS_FILE); console.log('Done.'); } main();