#!/usr/bin/env node const fs = require('fs'); const path = require('path'); const { SatLocLogParser } = require('./helpers/satloc_log_parser'); async function extractIds(filePath) { const relativePath = path.relative('./test-logs', filePath); console.log(`\n=== Processing: ${relativePath} ===`); try { const parser = new SatLocLogParser({ debugRecordTypes: [], outputAllRecords: false, verbose: false }); const result = await parser.parseFile(filePath); if (!result.success) { console.log(`ERROR: ${result.error}`); return; } let jobId = null; let aircraftId = null; let fileName = path.basename(filePath); // Extract jobId from record 120 (SWATHING_SETUP) const record120 = result.records.find(r => r.recordType === 120); if (record120) { jobId = record120.jobId || 'N/A'; } // Extract aircraftId from record 100 (SYSTEM_SETUP) const record100 = result.records.find(r => r.recordType === 100); if (record100) { aircraftId = record100.aircraftId || 'N/A'; } console.log(`File Name: ${fileName}`); console.log(`Job ID (from record 120): ${jobId || 'Not found'}`); console.log(`Aircraft ID (from record 100): ${aircraftId || 'Not found'}`); console.log(`Total records: ${result.records.length}`); } catch (error) { console.log(`ERROR processing ${filePath}: ${error.message}`); } } async function extractIdsQuiet(filePath) { try { const parser = new SatLocLogParser({ debugRecordTypes: [], outputAllRecords: false, verbose: false }); const result = await parser.parseFile(filePath); if (!result.success) { return null; } let jobId = null; let aircraftId = null; let fileName = path.basename(filePath); let relativePath = path.relative('./test-logs', filePath); // Extract jobId from record 120 (SWATHING_SETUP) const record120 = result.records.find(r => r.recordType === 120); if (record120) { jobId = record120.jobId || null; } // Extract aircraftId from record 100 (SYSTEM_SETUP) const record100 = result.records.find(r => r.recordType === 100); if (record100) { aircraftId = record100.aircraftId || null; } return { fileName, relativePath, jobId, aircraftId, totalRecords: result.records.length, filePath }; } catch (error) { return null; } } function findSatLocFiles(dir, fileList = []) { const items = fs.readdirSync(dir); for (const item of items) { const fullPath = path.join(dir, item); const stat = fs.statSync(fullPath); if (stat.isDirectory()) { // Recursively search subdirectories findSatLocFiles(fullPath, fileList); } else if (stat.isFile()) { // Check if it's a potential SatLoc file const fileName = item.toLowerCase(); if (fileName.endsWith('.log') || fileName.endsWith('.txt') || (fileName.includes('satloc') && !fileName.endsWith('.csv'))) { fileList.push(fullPath); } } } return fileList; } async function processTestLogsFolder() { const testLogsDir = './test-logs'; if (!fs.existsSync(testLogsDir)) { console.log('ERROR: ./test-logs directory not found'); return; } console.log('=== SatLoc ID Extractor ==='); console.log('Extracting jobId (record 120) and aircraftId (record 100) from SatLoc files...'); console.log('Searching recursively through subfolders...\n'); const logFiles = findSatLocFiles(testLogsDir); if (logFiles.length === 0) { console.log('No SatLoc log files found in ./test-logs directory or its subdirectories'); return; } console.log(`Found ${logFiles.length} potential SatLoc files:`); logFiles.forEach(file => { const relativePath = path.relative(testLogsDir, file); console.log(` - ${relativePath}`); }); // Store results for summary table const results = []; for (const filePath of logFiles) { const result = await extractIdsQuiet(filePath); if (result) { results.push(result); } } // Generate formatted summary tables console.log('\n' + '='.repeat(80)); console.log('šŸ“Š COMPLETE RESULTS SUMMARY'); console.log('='.repeat(80)); // Separate root and subfolder files const rootFiles = results.filter(r => !r.relativePath.includes('/')); const subfolderFiles = results.filter(r => r.relativePath.includes('/')); if (rootFiles.length > 0) { console.log('\nšŸ—‚ļø ROOT FOLDER FILES:'); // Calculate the maximum width needed for each column const maxFileNameWidth = Math.max(45, ...rootFiles.map(r => r.fileName.length)); const maxJobIdWidth = Math.max(15, ...rootFiles.map(r => (r.jobId || 'Not found').length)); const maxAircraftIdWidth = Math.max(15, ...rootFiles.map(r => (r.aircraftId || 'Not found').length)); // Create headers with proper spacing const fileNameHeader = 'File Name'.padEnd(maxFileNameWidth); const jobIdHeader = 'Job ID'.padEnd(maxJobIdWidth); const aircraftIdHeader = 'Aircraft ID'.padEnd(maxAircraftIdWidth); const recordsHeader = 'Total Records'; console.log(`\n${fileNameHeader} ${jobIdHeader} ${aircraftIdHeader} ${recordsHeader}`); console.log('='.repeat(maxFileNameWidth + maxJobIdWidth + maxAircraftIdWidth + 15 + 3)); // +3 for spaces between columns rootFiles.forEach(result => { const fileName = result.fileName.padEnd(maxFileNameWidth); const jobId = (result.jobId || 'Not found').padEnd(maxJobIdWidth); const aircraftId = (result.aircraftId || 'Not found').padEnd(maxAircraftIdWidth); const records = result.totalRecords.toLocaleString().padStart(12); console.log(`${fileName} ${jobId} ${aircraftId} ${records}`); }); } if (subfolderFiles.length > 0) { console.log('\nšŸ“ SUBFOLDER FILES:'); // Calculate the maximum width needed for each column const maxFilePathWidth = Math.max(45, ...subfolderFiles.map(r => r.relativePath.length)); const maxJobIdWidth = Math.max(15, ...subfolderFiles.map(r => (r.jobId || 'Not found').length)); const maxAircraftIdWidth = Math.max(15, ...subfolderFiles.map(r => (r.aircraftId || 'Not found').length)); // Create headers with proper spacing const filePathHeader = 'File Path'.padEnd(maxFilePathWidth); const jobIdHeader = 'Job ID'.padEnd(maxJobIdWidth); const aircraftIdHeader = 'Aircraft ID'.padEnd(maxAircraftIdWidth); const recordsHeader = 'Total Records'; console.log(`\n${filePathHeader} ${jobIdHeader} ${aircraftIdHeader} ${recordsHeader}`); console.log('='.repeat(maxFilePathWidth + maxJobIdWidth + maxAircraftIdWidth + 15 + 3)); // +3 for spaces between columns subfolderFiles.forEach(result => { const filePath = result.relativePath.padEnd(maxFilePathWidth); const jobId = (result.jobId || 'Not found').padEnd(maxJobIdWidth); const aircraftId = (result.aircraftId || 'Not found').padEnd(maxAircraftIdWidth); const records = result.totalRecords.toLocaleString().padStart(12); console.log(`${filePath} ${jobId} ${aircraftId} ${records}`); }); } // Statistics summary const totalRecords = results.reduce((sum, r) => sum + r.totalRecords, 0); const uniqueJobIds = new Set(results.map(r => r.jobId).filter(id => id && id !== 'Not found')); const uniqueAircraftIds = new Set(results.map(r => r.aircraftId).filter(id => id && id !== 'Not found')); const largestFile = results.reduce((max, r) => r.totalRecords > max.totalRecords ? r : max, results[0]); console.log('\nšŸŽÆ KEY STATISTICS:'); console.log('ā”œā”€ Total files processed: ' + results.length); console.log('ā”œā”€ Total records across all files: ' + totalRecords.toLocaleString()); console.log('ā”œā”€ Unique Job IDs found: ' + uniqueJobIds.size); console.log('ā”œā”€ Unique Aircraft IDs found: ' + uniqueAircraftIds.size); console.log('└─ Largest file: ' + (largestFile.fileName || largestFile.relativePath) + ' (' + largestFile.totalRecords.toLocaleString() + ' records)'); console.log('\nāœ… UNIQUE JOB IDS:'); Array.from(uniqueJobIds).sort().forEach((id, index) => { console.log(' ' + (index + 1) + '. "' + id + '"'); }); console.log('\nāœˆļø UNIQUE AIRCRAFT IDS:'); Array.from(uniqueAircraftIds).sort().forEach((id, index) => { console.log(' ' + (index + 1) + '. "' + id + '"'); }); console.log('\n================================================================================'); console.log('šŸš€ Processing complete! Analyzed ' + results.length + ' SatLoc files with null termination fix applied.'); console.log('================================================================================'); // Create CSV format for easy copy-paste into spreadsheets console.log('\nšŸ“Š CSV FORMAT (Copy this into Excel/Google Sheets):'); console.log('File Name/Path,Job ID,Aircraft ID,Total Records,Location'); results.forEach(result => { const location = result.relativePath.includes('/') ? 'Subfolder' : 'Root'; const filePath = result.fileName || result.relativePath; const jobId = result.jobId || 'Not found'; const aircraftId = result.aircraftId || 'Not found'; console.log('"' + filePath + '","' + jobId + '","' + aircraftId + '",' + result.totalRecords + ',"' + location + '"'); }); } // Run if called directly if (require.main === module) { processTestLogsFolder().catch(error => { console.error('Fatal error:', error.message); process.exit(1); }); } module.exports = { extractIds, extractIdsQuiet, processTestLogsFolder, findSatLocFiles };