You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
8.9 KiB
228 lines
8.9 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Windows;
|
|
using leak_test_project.Models;
|
|
|
|
namespace leak_test_project.Utils
|
|
{
|
|
/// <summary>
|
|
/// 통신 로그 및 시스템 이력을 파일로 저장하는 유틸리티
|
|
/// </summary>
|
|
public static class FileLogger
|
|
{
|
|
private static readonly string LogDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
|
|
private static readonly object _lock = new object();
|
|
|
|
/// <summary>
|
|
/// 검사 데이터를 Logs/yyyy-MM-dd.csv 파일에 저장함
|
|
/// </summary>
|
|
public static void LogInspectData(InspectData data)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
try
|
|
{
|
|
if (!Directory.Exists(LogDirectory))
|
|
Directory.CreateDirectory(LogDirectory);
|
|
|
|
string dateStr = DateTime.Now.ToString("yyyy-MM-dd");
|
|
string filePath = Path.Combine(LogDirectory, $"{dateStr}.csv");
|
|
|
|
bool isNewFile = !File.Exists(filePath);
|
|
|
|
// CSV 헤더: Date,Time,Channel,ID,Value,Judgment,Mode,LineNo,ProductType,SpecUL,SpecLL,Retest
|
|
if (isNewFile)
|
|
{
|
|
string header = "Date,Time,Channel,ID,Value,Judgment,Mode,LineNo,ProductType,SpecUL,SpecLL,Retest" + Environment.NewLine;
|
|
File.WriteAllText(filePath, header, Encoding.UTF8);
|
|
}
|
|
|
|
string csvLine = $"{Esc(data.InspectDate)},{Esc(data.InspectTime)},{Esc(data.Channel)},{Esc(data.ProductId)}," +
|
|
$"{Esc(data.MeasuredValue)},{Esc(data.Judgment)},{Esc(data.Mode)},{Esc(data.LineNo)}," +
|
|
$"{Esc(data.ProductType)},{Esc(data.SpecUL)},{Esc(data.SpecLL)},{Esc(data.Retest)}{Environment.NewLine}";
|
|
|
|
File.AppendAllText(filePath, csvLine, Encoding.UTF8);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[FileLogger Error] {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 단순 텍스트 로그 (기존 호환성 유지용)
|
|
/// </summary>
|
|
public static void Log(string tag, string message)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
try
|
|
{
|
|
if (!Directory.Exists(LogDirectory))
|
|
Directory.CreateDirectory(LogDirectory);
|
|
|
|
string dateStr = DateTime.Now.ToString("yyyy-MM-dd");
|
|
string filePath = Path.Combine(LogDirectory, $"{dateStr}_system.log");
|
|
|
|
string logEntry = $"[{DateTime.Now:HH:mm:ss.fff}] [{tag}] {message}{Environment.NewLine}";
|
|
File.AppendAllText(filePath, logEntry, Encoding.UTF8);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[FileLogger Error] {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// CSV 값 이스케이프: 쉼표, 따옴표, 줄바꿈이 포함된 값을 안전하게 감싸줌
|
|
/// </summary>
|
|
private static string Esc(string value)
|
|
{
|
|
if (string.IsNullOrEmpty(value)) return "";
|
|
if (value.Contains(",") || value.Contains("\"") || value.Contains("\n"))
|
|
return $"\"{value.Replace("\"", "\"\"")}\"";
|
|
return value;
|
|
}
|
|
}
|
|
|
|
public static class LogParser
|
|
{
|
|
private static readonly string LogDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
|
|
|
|
public static List<InspectData> ParseLogs(DateTime start, DateTime end, string judgmentFilter = "[전체]", string serialFilter = "")
|
|
{
|
|
var results = new List<InspectData>();
|
|
|
|
if (!Directory.Exists(LogDirectory))
|
|
{
|
|
// 디렉토리가 없으면 빈 리스트 반환
|
|
return results;
|
|
}
|
|
|
|
// 날짜 범위 내의 모든 로그 파일 찾기 (.csv)
|
|
var files = Directory.GetFiles(LogDirectory, "*.csv")
|
|
.Where(f => {
|
|
string fileName = Path.GetFileNameWithoutExtension(f);
|
|
if (DateTime.TryParse(fileName, out DateTime fileDate))
|
|
{
|
|
return fileDate.Date >= start.Date && fileDate.Date <= end.Date;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
foreach (var file in files)
|
|
{
|
|
try
|
|
{
|
|
var lines = File.ReadAllLines(file);
|
|
if (lines.Length <= 1) continue; // Header only or empty
|
|
|
|
// CSV 헤더: Date,Time,Channel,ID,Value,Judgment,Mode,LineNo,ProductType,SpecUL,SpecLL,Retest
|
|
for (int i = 1; i < lines.Length; i++)
|
|
{
|
|
string line = lines[i];
|
|
if (string.IsNullOrWhiteSpace(line)) continue;
|
|
var parts = line.Split(',');
|
|
if (parts.Length < 12) continue;
|
|
|
|
string date = parts[0].Trim();
|
|
string time = parts[1].Trim();
|
|
string channel = parts[2].Trim();
|
|
string id = parts[3].Trim();
|
|
string val = parts[4].Trim();
|
|
string judg = parts[5].Trim();
|
|
string mode = parts[6].Trim();
|
|
string lineNo = parts[7].Trim();
|
|
string prodType = parts[8].Trim();
|
|
string specUl = parts[9].Trim();
|
|
string specLl = parts[10].Trim();
|
|
string retest = parts[11].Trim();
|
|
|
|
// 필터 적용
|
|
if (judgmentFilter != "[전체]" && judg != judgmentFilter) continue;
|
|
if (!string.IsNullOrEmpty(serialFilter) && !id.Contains(serialFilter)) continue;
|
|
|
|
results.Add(new InspectData
|
|
{
|
|
InspectDate = date,
|
|
InspectTime = time,
|
|
Channel = channel,
|
|
ProductId = id,
|
|
MeasuredValue = val,
|
|
Judgment = judg,
|
|
Mode = mode,
|
|
LineNo = lineNo,
|
|
ProductType = prodType,
|
|
SpecUL = specUl,
|
|
SpecLL = specLl,
|
|
Retest = retest
|
|
});
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[LogParser] Error reading file {file}: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
return results.OrderByDescending(r => r.InspectDate).ThenByDescending(r => r.InspectTime).ToList();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 데이터를 CSV 파일로 내보내는 유틸리티
|
|
/// </summary>
|
|
public static class CsvExporter
|
|
{
|
|
/// <summary>
|
|
/// 컬렉션 데이터를 CSV 파일로 저장함
|
|
/// </summary>
|
|
/// <typeparam name="T">데이터 모델 클래스</typeparam>
|
|
/// <param name="items">내보낼 데이터 목록</param>
|
|
/// <param name="filePath">저장할 파일 경로</param>
|
|
public static bool ExportToCsv<T>(IEnumerable<T> items, string filePath)
|
|
{
|
|
try
|
|
{
|
|
var sb = new StringBuilder();
|
|
var props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
|
|
|
// Header
|
|
foreach (var prop in props)
|
|
{
|
|
sb.Append(prop.Name).Append(",");
|
|
}
|
|
sb.AppendLine();
|
|
|
|
// Body
|
|
foreach (var item in items)
|
|
{
|
|
foreach (var prop in props)
|
|
{
|
|
var val = prop.GetValue(item, null);
|
|
var str = val?.ToString() ?? "";
|
|
if (str.Contains(",") || str.Contains("\"") || str.Contains("\n"))
|
|
sb.Append($"\"{str.Replace("\"", "\"\"")}\"");
|
|
else
|
|
sb.Append(str);
|
|
sb.Append(",");
|
|
}
|
|
sb.AppendLine();
|
|
}
|
|
|
|
File.WriteAllText(filePath, sb.ToString(), Encoding.UTF8);
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"CSV 저장 실패: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|