Files
ENIG/AGVLogic/AGVSimulator/Forms/ProgressLogForm.cs
ChiKyun Kim 58ca67150d 파일정리
2026-01-29 14:03:17 +09:00

245 lines
8.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
namespace AGVSimulator.Forms
{
/// <summary>
/// 경로 예측 테스트 진행 상황 로그 표시 폼
/// </summary>
public partial class ProgressLogForm : Form
{
private List<PathTestLogItem> _logItems;
/// <summary>
/// 취소 요청 여부
/// </summary>
public bool CancelRequested { get; private set; }
public ProgressLogForm()
{
InitializeComponent();
CancelRequested = false;
_logItems = new List<PathTestLogItem>();
}
/// <summary>
/// 로그 추가 (PathTestLogItem)
/// </summary>
public void AddLogItem(PathTestLogItem item)
{
if (InvokeRequired)
{
Invoke(new Action<PathTestLogItem>(AddLogItem), item);
return;
}
_logItems.Add(item);
var listItem = new ListViewItem(item.PreviousPosition ?? "-");
listItem.SubItems.Add(item.MotorDirection ?? "-");
listItem.SubItems.Add(item.CurrentPosition ?? "-");
listItem.SubItems.Add(item.TargetPosition ?? "-");
listItem.SubItems.Add(item.DockingPosition ?? "-");
listItem.SubItems.Add(item.Success ? "O" : "X");
listItem.SubItems.Add(item.Message ?? "-");
listItem.SubItems.Add(item.DetailedPath ?? "-");
listItem.SubItems.Add(item.Timestamp.ToString("HH:mm:ss"));
// 성공 여부에 따라 색상 설정
if (!item.Success)
{
listItem.BackColor = Color.LightPink;
}
var dockpos = item.DockingPosition ?? string.Empty;
var targerpos = item.TargetPosition ?? string.Empty;
if (dockpos.Equals("충전기") && targerpos.StartsWith("0015"))
listItem.ForeColor = Color.DarkViolet;
_logListView.Items.Add(listItem);
_logListView.EnsureVisible(_logListView.Items.Count - 1);
}
/// <summary>
/// 간단한 텍스트 로그 추가 (상태 메시지용)
/// </summary>
public void AppendLog(string message)
{
var item = new PathTestLogItem
{
Message = message,
Success = true
};
AddLogItem(item);
}
/// <summary>
/// 상태 메시지 업데이트
/// </summary>
public void UpdateStatus(string status)
{
if (InvokeRequired)
{
Invoke(new Action<string>(UpdateStatus), status);
return;
}
_statusLabel.Text = status;
}
/// <summary>
/// 프로그레스바 업데이트
/// </summary>
public void UpdateProgress(int value, int maximum)
{
if (InvokeRequired)
{
Invoke(new Action<int, int>(UpdateProgress), value, maximum);
return;
}
_progressBar.Maximum = maximum;
_progressBar.Value = Math.Min(value, maximum);
}
/// <summary>
/// 작업 완료 시 호출
/// </summary>
public void SetCompleted()
{
if (InvokeRequired)
{
Invoke(new Action(SetCompleted));
return;
}
_cancelButton.Enabled = false;
_closeButton.Enabled = true;
UpdateStatus("작업 완료");
}
/// <summary>
/// 작업 취소 시 호출
/// </summary>
public void SetCancelled()
{
if (InvokeRequired)
{
Invoke(new Action(SetCancelled));
return;
}
_cancelButton.Enabled = false;
_closeButton.Enabled = true;
UpdateStatus("작업 취소됨");
}
private void OnCancel_Click(object sender, EventArgs e)
{
var result = MessageBox.Show(
"진행 중인 작업을 취소하시겠습니까?",
"취소 확인",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
CancelRequested = true;
_cancelButton.Enabled = false;
UpdateStatus("취소 요청됨...");
AppendLog("사용자가 취소를 요청했습니다.");
}
}
private void OnSaveCSV_Click(object sender, EventArgs e)
{
if (_logItems.Count == 0)
{
MessageBox.Show("저장할 데이터가 없습니다.", "알림", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
using (var saveDialog = new SaveFileDialog())
{
saveDialog.Filter = "CSV 파일 (*.csv)|*.csv|모든 파일 (*.*)|*.*";
saveDialog.DefaultExt = "csv";
saveDialog.FileName = $"경로예측테스트_{DateTime.Now:yyyyMMdd_HHmmss}.csv";
if (saveDialog.ShowDialog() == DialogResult.OK)
{
try
{
SaveToCSV(saveDialog.FileName);
MessageBox.Show($"CSV 파일이 저장되었습니다.\n{saveDialog.FileName}",
"저장 완료", MessageBoxButtons.OK, MessageBoxIcon.Information);
var prc = new System.Diagnostics.Process();
prc.StartInfo = new System.Diagnostics.ProcessStartInfo("explorer", saveDialog.FileName);
prc.Start();
}
catch (Exception ex)
{
MessageBox.Show($"CSV 저장 중 오류가 발생했습니다:\n{ex.Message}",
"오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
/// <summary>
/// CSV 파일로 저장
/// </summary>
private void SaveToCSV(string filePath)
{
using (var writer = new StreamWriter(filePath, false, Encoding.UTF8))
{
// 헤더 작성
writer.WriteLine("이전위치,모터방향,현재위치,대상위치,도킹위치,성공,메세지,상세경로,시간");
// 데이터 작성
foreach (var item in _logItems)
{
var line = $"{EscapeCSV(item.PreviousPosition)}," +
$"{EscapeCSV(item.MotorDirection)}," +
$"{EscapeCSV(item.CurrentPosition)}," +
$"{EscapeCSV(item.TargetPosition)}," +
$"{EscapeCSV(item.DockingPosition)}," +
$"{(item.Success ? "O" : "X")}," +
$"{EscapeCSV(item.Message)}," +
$"{EscapeCSV(item.DetailedPath)}," +
$"{item.Timestamp:yyyy-MM-dd HH:mm:ss}";
writer.WriteLine(line);
}
}
}
/// <summary>
/// CSV 셀 데이터 이스케이프 처리
/// </summary>
private string EscapeCSV(string value)
{
if (string.IsNullOrEmpty(value))
return "";
// 쉼표, 큰따옴표, 줄바꿈이 있으면 큰따옴표로 감싸고 내부 큰따옴표는 두 개로
if (value.Contains(",") || value.Contains("\"") || value.Contains("\n") || value.Contains("\r"))
{
return "\"" + value.Replace("\"", "\"\"") + "\"";
}
return value;
}
private void OnClose_Click(object sender, EventArgs e)
{
this.Close();
}
}
}