using OfficeOpenXml.VBA;
using ProductionLineMonitor.Application.Services.FaultService.Dtos;
using ProductionLineMonitor.Application.Services.LineService.Dtos;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Timers;
namespace ProductionLineMonitor.Web.Services.LineService
{
///
/// 产线详情
///
public class ProductionLineViewModel
{
public ProductionLineViewModel() { }
public ProductionLineViewModel(int floor, int line, string date, string topic, string lineName)
{
Floor = floor;
Line = line;
Date = date;
LineName = lineName;
ProductionPlans = MesApiService.GetProductionPlansV1(Floor, Line, Date);
KeyInInfos = MesApiService.GetKeyInInfos(Floor, Line, Date);
HourKeyInInfos = GetHourKeyInInfos(KeyInInfos);
try
{
DateTime dateTime = Convert.ToDateTime($"{date} 08:00:00");
DateTime[] m = new DateTime[] { dateTime, dateTime.AddHours(12), dateTime.AddHours(24) };
MorningReplaceConsumables = AccumulativeReplaceConsumableTime(KeyInInfos.Where(x => x.StartTime >= m[0] && x.StartTime < m[1]));
NightReplaceConsumables = AccumulativeReplaceConsumableTime(KeyInInfos.Where(x => x.StartTime >= m[1] && x.StartTime < m[2]));
}
catch (Exception)
{
return;
}
MachineViewModel machineViewModel = new MachineViewModel(
topic, date,
KeyInInfos,
ProductionPlans, true);
if (machineViewModel.Statistics.Count() == 0)
{
return;
}
ModuleType = machineViewModel.Statistics.Last().ModuleType;
Capa = machineViewModel.Statistics.Last().Capa;
Capacity = machineViewModel.Statistics.Last().Capacity;
PlanCapacity = machineViewModel.Statistics.Last().PlanCapacity;
OEE = machineViewModel.Statistics.Last().OEE;
Statistics = machineViewModel.Statistics;
LoadOutPutPerHours = machineViewModel.LoadOutPutPerHours;
NewOutPutPerHours = machineViewModel.NewOutPutPerHours;
UpdateDown();
}
private List AccumulativeReplaceConsumableTime(IEnumerable keyInInfos)
{
List rev = new List();
foreach (var keyInInfo in keyInInfos)
{
if (keyInInfo.KeyInType != 8)
{
continue;
}
var temp = rev.Find(x => x.Name == keyInInfo.Description);
if (temp != null)
{
temp.Count += 1;
temp.AccumulativeTime += keyInInfo.AffectTime;
}
else
{
var replaceConsumable = new ReplaceConsumable()
{
Name = keyInInfo.Description,
Count = 1,
AccumulativeTime = keyInInfo.AffectTime
};
rev.Add(replaceConsumable);
}
}
return rev;
}
private IEnumerable GetHourKeyInInfos(List keyInInfos)
{
IList dtos = new List();
foreach (var key in keyInInfos)
{
if (key.StartTime == null || key.EndTime == null)
continue;
IList dateTimes = new List
{
key.StartTime.Value
};
DateTime d1 = key.StartTime.Value;
int j = 1;
while (d1 < key.EndTime.Value)
{
d1 = key.StartTime.Value.AddHours(j);
DateTime d2 = Convert.ToDateTime($"{d1:yyyy-MM-dd HH}:00:00");
j++;
if (d2 < key.EndTime.Value)
{
dateTimes.Add(d2);
}
}
dateTimes.Add(key.EndTime.Value);
for (int i = 0; i < dateTimes.Count - 1; i++)
{
KeyInInfo dto = new KeyInInfo
{
KeyInType = key.KeyInType,
Description = key.Description,
Id = key.Id,
StartTime = dateTimes[i],
EndTime = dateTimes[i + 1]
};
dto.AffectTime = (int)(dto.EndTime - dto.StartTime).Value.TotalMinutes;
if (dto.AffectTime > 1)
{
dtos.Add(dto);
}
}
}
return dtos;
}
private void UpdateDown()
{
if (Statistics != null)
{
if (Statistics.Count == 1)
{
Statistics[0].Reload = KeyInInfos.Where(x => x.KeyInType == 8).Sum(x => x.AffectTime);
double d = Statistics[0].IdelTime - Statistics[0].Reload;
if (d < 0)
d = 0;
Statistics[0].DownTime += d;
}
else
{
foreach (var item in Statistics)
{
var outs = NewOutPutPerHours.Where(x => x.ModuleType != "" && x.ModuleType[..8] == item.ModuleType).ToList();
if (outs.Count() > 0)
{
DateTime start = outs[0].DataTime;
DateTime end = outs.Last().DataTime.AddHours(1);
item.Reload = KeyInInfos.Where(
x => x.KeyInType == 8 && x.StartTime >= start && x.StartTime.Value < end).Sum(x => x.AffectTime);
double d = item.IdelTime - item.Reload;
if (d < 0)
d = 0;
item.DownTime += d;
}
}
}
}
}
private void CheckFault()
{
DateTime startTime = Convert.ToDateTime($"{Date} 08:00:00");
DateTime endTime = startTime.AddDays(1);
foreach (var item in Machines)
{
FaultStatistic faultStatistic = new FaultStatistic();
faultStatistic.Name = item.Type;
switch (item.Type)
{
case "AG":
faultStatistic.Name = "AG + FPL";
List tempFaults = new List();
tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL", endTime));
tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL01", endTime));
tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL02", endTime));
tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL03", endTime));
tempFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "FPL04", endTime));
double time1 = tempFaults.Sum(x => x.Duration);
double time2 = item.Statistics.Sum(x => x.DownTime);
faultStatistic.DownTime = Math.Round(time1 + time2);
break;
case "FOG":
// 在 FOG 前增加COG
List tempCogFaults = new List();
tempCogFaults.AddRange(getKeyInLineDayFaultRecord(Floor, Line, Date, "COG", endTime));
FaultStatistic cog = new FaultStatistic
{
Name = "COG",
DownTime = Math.Round(tempCogFaults.Sum(x => x.Duration))
};
FaultStatistics.Add(cog);
// FOG 故障时间
faultStatistic.DownTime = Math.Round(item.Statistics.Sum(x => x.DownTime));
break;
default:
faultStatistic.DownTime = Math.Round(item.Statistics.Sum(x => x.DownTime));
break;
}
FaultStatistics.Add(faultStatistic);
}
}
private List getKeyInLineDayFaultRecord(int floor, int line, string date, string type, DateTime endTime)
{
List lineDayFaultRecords = new List();
var fs = MesApiService.GetKeyInFaults(floor, line, date, type);
foreach (var f in fs)
{
LineDayFaultRecord fLineDayFaultRecord = new LineDayFaultRecord
{
MechineName = type,
FaultCode = f.FaultCode,
FaultInfo = f.FaultInfo,
StartTime = f.StartTime,
DataSource = 1
};
if (f.EndTime == null)
fLineDayFaultRecord.EndTime = endTime;
else
fLineDayFaultRecord.EndTime = f.EndTime.Value;
fLineDayFaultRecord.Duration = (fLineDayFaultRecord.EndTime.Value - fLineDayFaultRecord.StartTime).TotalMinutes;
lineDayFaultRecords.Add(fLineDayFaultRecord);
}
return lineDayFaultRecords;
}
private void CheckModuleType()
{
if (ModuleType != null && ModuleType != "")
{
if (ProductionPlans
.Where(x => x.ModuleType.Length >= 8)
.Where(x => x.ModuleType.Substring(0, 8) == ModuleType).Count() == 0)
{
State = 99;
StateMessage = "生产机种与排程不符";
}
}
}
public virtual void CheckState()
{
DateTime now = DateTime.Now;
DateTime time = Convert.ToDateTime($"{Date} {now:HH:mm:ss}");
if (time.Day != now.Day || time.Year != now.Year || time.Month != now.Month)
{
time = Convert.ToDateTime($"{Date} 07:59:00").AddDays(1);
}
foreach (var item in KeyInInfos)
{
if (item.KeyInType == 2 || item.KeyInType == 3 || item.KeyInType == 4 ||
item.KeyInType == 6 || item.KeyInType == 7 || item.KeyInType == 9)
{
if (time >= item.StartTime && time <= item.EndTime)
{
State = item.KeyInType;
StateMessage = item.Description;
return;
}
}
}
if (ProductionPlans.Count == 0)
{
State = 11;
StateMessage = "";
return;
}
if (ProductionPlans.Count == 1)
{
if (ProductionPlans[0].ModuleType == "未指定")
{
State = 11;
StateMessage = "";
return;
}
}
State = 99;
StateMessage = "";
}
public int Floor { get; set; }
public int Line { get; set; }
public string LineName { get; set; } = string.Empty;
public string Date { get; set; } = string.Empty;
private int _state = -1;
public int State
{
get { return _state; }
set
{
/// 0:品质异常停线
/// ---------------1:宕机
/// 2:换线
/// 3:实验
/// 4:W/F送样
/// ---------------5:物料缺料或生管调整影响
/// 6:放假
/// 7:停电气等停线
/// ---------------8:换耗材类
/// 9:停机未生产
/// ----------------10:效率爬升
_state = value;
switch (_state)
{
case 0: StateName = "品质异常停线"; break;
case 1: break;
case 2: StateName = "换线"; break;
case 3: StateName = "实验"; break;
case 4: StateName = "W/F送样"; break;
case 5: break;
case 6: StateName = "放假"; break;
case 7: StateName = "停电气等停线"; break;
case 8: break;
case 9: StateName = "停机未生产"; break;
case 10: break;
case 11: StateName = "未排产"; break;
default: StateName = "正常生产"; break;
}
}
}
public string StateName { get; set; } = string.Empty;
///
/// 状态描述
///
public string StateMessage { get; set; } = string.Empty;
///
/// 机种
///
public string ModuleType { get; set; } = string.Empty;
///
/// Capa
///
public int Capa { get; set; }
///
/// 计划产能
///
public int PlanCapacity { get; set; }
///
/// 产能
///
public int Capacity { get; set; }
///
/// OEE
///
public double OEE { get; set; }
public double TheoryRefueledTime { get; set; }
///
/// 生产计划
///
public List ProductionPlans { get; set; }
= new List();
///
/// key in 的异常
///
public List KeyInInfos { get; set; }
= new List();
public IEnumerable HourKeyInInfos { get; set; }
= new List();
///
/// 小时产能
///
public List LoadOutPutPerHours { get; set; }
= new List();
///
/// 清理后小时产能
///
public List NewOutPutPerHours { get; set; }
= new List();
///
/// 统计
///
public List Statistics { get; set; }
= new List();
///
/// 机台
///
public List Machines { get; set; }
= new List();
///
/// key in 故障
///
public List KeyInFaults { get; set; }
= new List();
public List FaultStatistics { get; set; }
= new List();
public class FaultStatistic
{
public string Name { get; set; } = string.Empty;
public double DownTime { get; set; }
}
public List ReplaceConsumables { get; set; }
= new List();
public List MorningReplaceConsumables { get; set; }
= new List();
public List NightReplaceConsumables { get; set; }
= new List();
}
}