using System;
using System.Collections.ObjectModel;
using System.Threading;
using System.Windows;
namespace TeamAAS.FlowEngine.Execution
{
///
/// 运行统计中心。FlowRunner 每次产品运行结束后调用 AddRun 更新计数;
/// 首页 / 统计页直接绑定 Instance 的属性即可获得真实数据(不再写死假数据)。
///
public class RunStatistics : TeamAAS.BindableBase
{
public static RunStatistics Instance { get; } = new RunStatistics();
private long _totalCount;
private long _okCount;
private long _ngCount;
private long _cycleMs;
private RunStatistics()
{
Logs = new ObservableCollection();
}
/// 运行日志(首页"运行信息"面板直接绑定)
public ObservableCollection Logs { get; }
public long TotalCount => Interlocked.Read(ref _totalCount);
public long OkCount => Interlocked.Read(ref _okCount);
public long NgCount => Interlocked.Read(ref _ngCount);
public long CycleTimeMs => Interlocked.Read(ref _cycleMs);
public string YieldText =>
TotalCount == 0 ? "--" : (OkCount * 100.0 / TotalCount).ToString("F1") + "%";
public string UphText =>
CycleTimeMs > 0 ? Math.Round(3600000.0 / CycleTimeMs).ToString("F0") : "--";
public string CtText =>
CycleTimeMs > 0 ? (CycleTimeMs / 1000.0).ToString("F2") + "s" : "--";
/// 记录一次运行结果(后台线程安全,UI 属性自动跨线程刷新)
public void AddRun(bool success, long cycleMs)
{
Interlocked.Increment(ref _totalCount);
if (success) Interlocked.Increment(ref _okCount);
else Interlocked.Increment(ref _ngCount);
Interlocked.Exchange(ref _cycleMs, cycleMs);
RaiseCountersChanged();
Log((success ? "OK" : "NG") + $" 周期 {cycleMs}ms");
}
public void Reset()
{
Interlocked.Exchange(ref _totalCount, 0);
Interlocked.Exchange(ref _okCount, 0);
Interlocked.Exchange(ref _ngCount, 0);
Interlocked.Exchange(ref _cycleMs, 0);
OnUi(() => Logs.Clear());
RaiseCountersChanged();
Log("统计已清零");
}
/// 写一条运行日志(最多保留 200 条)
public void Log(string message)
{
// 并入统一日志流:经 AppLogger 进入公共日志文件 + 实时日志控件
TeamAAS.AppLogger.Info(message, "运行");
OnUi(() =>
{
Logs.Add(new RunLogEntry(DateTime.Now, message ?? ""));
while (Logs.Count > 200)
Logs.RemoveAt(0);
});
}
private void RaiseCountersChanged()
{
RaisePropertyChanged(nameof(TotalCount));
RaisePropertyChanged(nameof(OkCount));
RaisePropertyChanged(nameof(NgCount));
RaisePropertyChanged(nameof(CycleTimeMs));
RaisePropertyChanged(nameof(YieldText));
RaisePropertyChanged(nameof(UphText));
RaisePropertyChanged(nameof(CtText));
}
private static void OnUi(Action action)
{
if (Application.Current?.Dispatcher != null
&& !Application.Current.Dispatcher.CheckAccess())
Application.Current.Dispatcher.Invoke(action);
else
action();
}
}
/// 运行日志条目
public class RunLogEntry
{
public RunLogEntry(DateTime time, string message)
{
Time = time;
Message = message;
}
public DateTime Time { get; }
public string Message { get; }
public string TimeText => Time.ToString("HH:mm:ss");
}
}