using Bro.Common.Base;
|
using Bro.Common.Helper;
|
using Bro.Common.Interface;
|
using Bro.Common.Model;
|
using Bro.M135.Common;
|
using Newtonsoft.Json;
|
using NPOI.SS.Formula.Functions;
|
using System;
|
using System.Collections.Generic;
|
using System.ComponentModel;
|
using System.Drawing.Design;
|
using System.Drawing.Printing;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
|
namespace Bro.M141.Process
|
{
|
public partial class M141Process
|
{
|
public event Action<ProductModel> UploadProductForStatistic;
|
public List<ISpec> GetSpecHeads()
|
{
|
return Config.GetSpecList().Where(u => u.IsEnabled).OrderBy(u => u.Code).ToList();
|
}
|
|
object _pListForStatisticLock = new object();
|
public List<ProductModel> ProductListForStatistic { get; set; } = new List<ProductModel>();
|
|
private async void HandleProductStatistc(ProductModel product)
|
{
|
await Task.Run(() =>
|
{
|
if (product == null)
|
return;
|
|
lock (_pListForStatisticLock)
|
{
|
//foreach (var item in product.ProductResultCollection)
|
//{
|
// item.Value.PID = product.PID;
|
// item.Value.ProductSeq = item.Key;
|
// item.Value.EndTime = DateTime.Now;
|
|
SummaryOKRate(product);
|
ProductListForStatistic.Insert(0, product);
|
|
UploadProductForStatistic?.Invoke(product);
|
//}
|
|
while (ProductListForStatistic.Count > M141Config.MaxProductNumForStatistic)
|
{
|
ProductListForStatistic.RemoveAt(ProductListForStatistic.Count - 1);
|
}
|
}
|
|
//UploadProductForStatistic?.Invoke(product);
|
});
|
}
|
|
#region 良率统计
|
public SummaryData SummaryData { get; set; } = new SummaryData();
|
|
object _okRateLock = new object();
|
public OKRateModel OKRateModel => SummaryData.OKRateModel;
|
public List<ShiftSummary> ShiftSummaryDatas => SummaryData.ShiftSummaryDatas;
|
|
private void SummaryOKRate(ProductModel singleResult)
|
{
|
var results = singleResult.Result;
|
|
if (results == "NG")
|
{
|
List<string> ngitem = new List<string>();
|
foreach (var v in singleResult.Details)
|
{
|
ngitem.AddRange(v.ResultList.GetDefectDescList());
|
ngitem.AddRange(v.DefectList);
|
}
|
ngitem = ngitem.Distinct().ToList();
|
List<string> ngitemD = ngitem.Where(u => u.ToUpper().Contains("FAI")).ToList();
|
//List<string> ngitemC = ngitem.Where(u => !u.ToUpper().Contains("FAI")).ToList();
|
if (ngitemD != null && ngitemD.Count > 0)
|
{
|
results = "CNG";
|
}
|
else
|
{
|
results = "WNG";
|
}
|
|
}
|
|
|
|
|
|
lock (_okRateLock)
|
{
|
OKRateModel.TotalNum++;
|
|
bool isSpecOK = true;
|
bool isDefectOK = true;
|
|
if (results.ToUpper().Equals("CNG"))
|
{
|
OKRateModel.Spec_NG++;
|
isSpecOK = false;
|
}
|
|
if (results.ToUpper().Equals("WNG"))
|
{
|
OKRateModel.Defect_NG++;
|
isDefectOK = false;
|
}
|
|
if (isSpecOK && isDefectOK)
|
{
|
OKRateModel.OKNum++;
|
}
|
|
|
ShiftSummary? shift = InitialCurrentShift(singleResult.EndTime??DateTime.Now);
|
|
var hourData = shift.HourDatas.FirstOrDefault(u => u.HourTime <= singleResult.EndTime && u.HourTime.AddHours(1) > singleResult.EndTime);
|
if (hourData == null)
|
{
|
LogAsync(DateTime.Now, Common.Helper.EnumHelper.LogLevel.Error, $"产品{singleResult.PID},结束时间{(singleResult.EndTime??DateTime.Now).ToString("MM/dd HH:mm")}未能统计到合适的时段");
|
}
|
else
|
{
|
hourData.OKRateModel.TotalNum++;
|
if (!isSpecOK)
|
{
|
hourData.OKRateModel.Spec_NG++;
|
}
|
|
if (!isDefectOK)
|
{
|
hourData.OKRateModel.Defect_NG++;
|
}
|
|
if (isSpecOK && isDefectOK)
|
{
|
hourData.OKRateModel.OKNum++;
|
}
|
}
|
|
_saveSummaryDataTimer.Change(15 * 1000, -1);
|
}
|
}
|
|
private ShiftSummary InitialCurrentShift(DateTime dtNow)
|
{
|
var shift = ShiftSummaryDatas.FirstOrDefault(u => u.StartTime <= dtNow && u.EndTime > dtNow);
|
if (shift == null)
|
{
|
DateTime shiftStartTime = DateTime.Now;
|
if (dtNow.Hour >= 8 && dtNow.Hour < 20)
|
{
|
shiftStartTime = dtNow.Date.AddHours(8);
|
}
|
else if (dtNow.Hour >= 20 && dtNow.Hour < 0)
|
{
|
shiftStartTime = dtNow.Date.AddHours(20);
|
}
|
else
|
{
|
shiftStartTime = dtNow.AddDays(-1).AddHours(20);
|
}
|
|
shift = new ShiftSummary()
|
{
|
StartTime = shiftStartTime,
|
EndTime = shiftStartTime.AddHours(12),
|
};
|
shift.Initial();
|
ShiftSummaryDatas.Add(shift);
|
|
while (ShiftSummaryDatas.Count > 2)
|
{
|
ShiftSummaryDatas.RemoveAt(0);
|
}
|
|
while (ShiftSummaryDatas.Count < 2)
|
{
|
ShiftSummary tempShift = new ShiftSummary()
|
{
|
StartTime = ShiftSummaryDatas[ShiftSummaryDatas.Count - 1].EndTime,
|
EndTime = ShiftSummaryDatas[ShiftSummaryDatas.Count - 1].EndTime.AddHours(12),
|
};
|
tempShift.Initial();
|
|
ShiftSummaryDatas.Add(tempShift);
|
}
|
}
|
|
return shift;
|
}
|
|
public void ResetOKRate()
|
{
|
lock (_okRateLock)
|
{
|
OKRateModel.TotalNum = OKRateModel.OKNum = OKRateModel.Spec_NG = OKRateModel.Defect_NG = 0;
|
}
|
}
|
|
System.Threading.Timer _saveSummaryDataTimer = null;
|
public void InitialSummaryData()
|
{
|
if (_saveSummaryDataTimer == null)
|
{
|
_saveSummaryDataTimer = new System.Threading.Timer(SaveSummaryData, null, -1, -1);
|
}
|
|
string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SummaryData.json");
|
if (File.Exists(filePath))
|
{
|
try
|
{
|
using (StreamReader reader = new StreamReader(filePath, System.Text.Encoding.UTF8))
|
{
|
var dataStr = reader.ReadToEnd();
|
|
SummaryData = JsonConvert.DeserializeObject<SummaryData>(dataStr);
|
if (SummaryData == null)
|
{
|
SummaryData = new SummaryData();
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
SummaryData = new SummaryData();
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"统计汇总信息读取失败,初始化统计汇总");
|
}
|
}
|
|
InitialCurrentShift(DateTime.Now);
|
}
|
|
|
private void SaveSummaryData(object? state)
|
{
|
if (!SaveSummaryData(out string error))
|
{
|
LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"统计汇总信息保存失败,{error}");
|
}
|
}
|
|
public bool SaveSummaryData(out string error)
|
{
|
error = "";
|
|
try
|
{
|
using (StreamWriter sw = new StreamWriter(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SummaryData.json"), false, System.Text.Encoding.UTF8))
|
{
|
sw.Write(JsonConvert.SerializeObject(SummaryData));
|
}
|
}
|
catch (Exception ex)
|
{
|
error = ex.GetExceptionMessage();
|
return false;
|
}
|
|
return true;
|
}
|
#endregion
|
|
//[ProcessMethod("TestHandleProductStatistic", "TestHandleProductStatistic", "处理产品统计测试方法", InvokeType.TestInvoke)]
|
//public ResponseMessage TestHandleProductStatistic(IOperationConfig config, IDevice executeDevice, IDevice sourceDevice)
|
//{
|
// ProductModel productModel = new ProductModel();
|
// SingleProductResultCollection resultCollection = new SingleProductResultCollection();
|
// productModel.ProductResultCollection.Add(0, resultCollection);
|
|
// DetectResult result = new DetectResult();
|
// result.ResultState = EnumHelper.ResultState.OK;
|
// resultCollection.AddPositionSnapshotResult(1, new List<DetectResult>() { result });
|
|
// if (config is M141Process.HandleProductStatisticTestOpConfig opConfig)
|
// {
|
// if (opConfig.Defects.Count > 0)
|
// {
|
// opConfig.Defects.ForEach(d =>
|
// {
|
// result.AddNetResult(new NetResult()
|
// {
|
// DetectDetails = new List<DefectDetail>()
|
// {
|
// new DefectDetail()
|
// {
|
// ClassName=d,
|
// FinalResult=EnumHelper.ResultState.NG,
|
// }
|
// }
|
// });
|
// });
|
// }
|
|
// if (opConfig.FAINGs.Count > 0)
|
// {
|
// opConfig.FAINGs.ForEach(f =>
|
// {
|
// result.Specs.Add(new Spec()
|
// {
|
// Code = f,
|
// ActualValue = 999,
|
// MeasureResult = false,
|
// });
|
// });
|
// }
|
|
// result.SetResult();
|
// }
|
|
// HandleProductStatistc(productModel);
|
|
// return new ResponseMessage();
|
//}
|
|
//[Device("TestHandleProductStatistic", "处理产品统计测试方法配置", EnumHelper.DeviceAttributeType.OperationConfig)]
|
//public class HandleProductStatisticTestOpConfig : OperationConfigBase
|
//{
|
// [Category("缺陷信息")]
|
// [Description("缺陷NG信息")]
|
// [DisplayName("缺陷NG信息")]
|
// [TypeConverter(typeof(SimpleCollectionConvert<string>))]
|
// [Editor(typeof(SimpleCollectionEditor<string>), typeof(UITypeEditor))]
|
// public List<string> Defects { get; set; } = new List<string>();
|
|
// [Category("缺陷信息")]
|
// [Description("尺寸NG信息")]
|
// [DisplayName("尺寸NG信息")]
|
// [TypeConverter(typeof(SimpleCollectionConvert<string>))]
|
// [Editor(typeof(SimpleCollectionEditor<string>), typeof(UITypeEditor))]
|
// public List<string> FAINGs { get; set; } = new List<string>();
|
//}
|
}
|
}
|
|
public class SummaryData
|
{
|
public OKRateModel OKRateModel { get; set; } = new OKRateModel();
|
public List<ShiftSummary> ShiftSummaryDatas { get; set; } = new List<ShiftSummary>();
|
}
|
|
public class OKRateModel
|
{
|
public int TotalNum { get; set; } = 0;
|
public int OKNum { get; set; } = 0;
|
public int Spec_NG { get; set; } = 0;
|
public int Defect_NG { get; set; } = 0;
|
}
|
|
public class ShiftSummary
|
{
|
public DateTime StartTime { get; set; }
|
public DateTime EndTime { get; set; }
|
|
public List<HourData> HourDatas { get; set; } = new List<HourData>();
|
|
public class HourData
|
{
|
public DateTime HourTime { get; set; }
|
public OKRateModel OKRateModel { get; set; } = new OKRateModel();
|
}
|
|
public void Initial()
|
{
|
HourDatas.Clear();
|
|
for (int i = 0; i < 12; i++)
|
{
|
HourDatas.Add(new HourData()
|
{
|
HourTime = StartTime.AddHours(i),
|
});
|
}
|
}
|
|
|
|
|
|
}
|
|
//public class SingleProductResultCollection
|
//{
|
// public string PID { get; set; } = "";
|
// public int ProductSeq { get; set; } = 0;
|
// public DateTime EndTime { get; set; }
|
// //public List<List<DetectResult>> DetectResults { get; set; } = new List<List<DetectResult>>();
|
// public Dictionary<int, List<List<DetectResult>>> DetectResults { get; set; } = new Dictionary<int, List<List<DetectResult>>>();
|
|
// object _resultLock = new object();
|
// public void AddPositionSnapshotResult(int positionNum, List<DetectResult> results)
|
// {
|
// lock (_resultLock)
|
// {
|
// if (!DetectResults.ContainsKey(positionNum))
|
// {
|
// DetectResults[positionNum] = new List<List<DetectResult>>();
|
// }
|
|
// DetectResults[positionNum].Add(results);
|
// }
|
// }
|
//}
|