import fs from 'node:fs' import path from 'node:path' /** * Function to clean up unwanted characters from the output data. * @param {string} data - The raw data to be cleaned. * @returns {string} - The cleaned data. */ export const cleanData = (data: string) => { return data .replace(/--More--\s*BS\s*BS\s*BS\s*BS\s*BS\s*BS/g, '') .replace(/\s*--More--\s*/g, '') .replace(/\x1b\[[0-9;]*m/g, '') // Remove ANSI escape codes .replace(/\x08/g, '') .replace(/[^\x20-\x7E\r\n]/g, '') // Remove non-printable characters // .replace(/\r\n/g, '\n') } export function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)) } export function appendLog(output: string, stationId: number, lineNumber: number, port: number) { const date = new Date().toISOString().slice(0, 10).replace(/-/g, '') // YYYYMMDD const logDir = path.join('storage', 'system_logs') const logFile = path.join(logDir, `${date}-Station_${stationId}-Line_${lineNumber}_${port}.log`) // Ensure folder exists if (!fs.existsSync(logDir)) { fs.mkdirSync(logDir, { recursive: true }) } fs.appendFile(logFile, output, (err) => { if (err) { console.error('❌ Failed to write log:', err.message) } }) } export const getPathLog = (stationId: number, lineNumber: number, port: number) => { const date = new Date().toISOString().slice(0, 10).replace(/-/g, '') // YYYYMMDD const logDir = path.join('storage', 'system_logs') const logFile = path.join(logDir, `${date}-Station_${stationId}-Line_${lineNumber}_${port}.log`) // Ensure folder exists if (!fs.existsSync(logDir)) { fs.mkdirSync(logDir, { recursive: true }) return null } else return logFile } /** * Utility function get scope log with timestamp. * @param {string} text - content log. * @param {number} time - Timestamp. */ export const getLogWithTimeScenario = (text: string, time: number) => { try { // Match all start and end blocks const regex = /---(start|end)-scenarios---(\d+)---/g let match const blocks = [] while ((match = regex.exec(text)) !== null) { blocks.push({ type: match[1], timestamp: match[2], index: match.index, }) } // Find the matching block for the end timestamp let result = null for (let i = 0; i < blocks.length; i++) { const block = blocks[i] if (block.type === 'end' && block.timestamp === time.toString()) { // Find nearest preceding "start" for (let j = i - 1; j >= 0; j--) { if (blocks[j].type === 'start') { const startIndex = blocks[j].index const endIndex = block.index + text.slice(block.index).indexOf('\n') // or manually offset length of the line result = text.slice(startIndex, endIndex).trim() break } } break } } return result } catch (err) { console.error('Error get log:', err) return '' } } export function isValidJson(string: string) { try { JSON.parse(string) return true // Chuỗi là định dạng JSON hợp lệ } catch (e) { return false // Chuỗi không phải là định dạng JSON hợp lệ } }