using NPOI.SS.Formula.Functions; using NPOI.XWPF.UserModel; using ProductionLineMonitor.Application.Services.LineService.Dtos; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; namespace ProductionLineMonitor.Web.Services.LineService { /// /// 机台 /// public class MachineViewModel { public MachineViewModel() { } public MachineViewModel(string topic, string date, List keyInInfos, List productionPlans, bool isLine) { CurrentTime = DateTime.Now; Date = date; if (!isLine) AnalysisTopic(topic); else Topic = topic; ProductionPlans = productionPlans; KeyInInfos = keyInInfos; LoadOutPutPerHours = MesApiService.GetOutPutPerHours(Topic, Date); if (LoadOutPutPerHours.Count() < 24) { Statistics = new List(); return; } WashOutPutPerHours(); CalculateV1(); } /// /// 解析Topic /// /// protected void AnalysisTopic(string topic) { Topic = topic; int index = topic.IndexOf('-'); Floor = Convert.ToInt16(topic.Substring(index + 1, 1)); Line = Convert.ToInt16(topic.Substring(index - 2, 2)); index = topic.IndexOf("Data"); Type = topic[..index]; } private string _date = string.Empty; /// /// 日期 /// public string Date { get { return _date; } set { _date = value; StartTime = Convert.ToDateTime($"{_date} 08:00:00"); EndTime = StartTime.AddDays(1); } } public DateTime StartTime { get; set; } public DateTime EndTime { get; set; } /// /// 当前时间 /// public DateTime CurrentTime { get; set; } /// /// topic /// public string Topic { get; set; } = string.Empty; /// /// 楼层 /// public int Floor { get; set; } /// /// 线别 /// public int Line { get; set; } /// /// 类型 /// public string Type { get; set; } = string.Empty; /// /// 生产计划 /// public List ProductionPlans { get; set; } = new List(); /// /// key in 的异常 /// public List KeyInInfos { 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 void UpdateModuleType() { if (Type != "AG" && Type != "FPL" && Type != "BT" && Type != "PS" && Type != "EC" && Type != "TP") return; string topic = $"FOGData#{Line}#{Line}-{Floor}FOG01"; if (Line < 10) topic = $"FOGData#{Line}#0{Line}-{Floor}FOG01"; var outs = MesApiService.GetOutPutPerHours(topic, Date); foreach (var item in outs) { var t = LoadOutPutPerHours.Find(x => x.DataTime == item.DataTime); if (t != null) t.ModuleType = item.ModuleType; } } /// /// 根据 key in 时间清洗小时产能 /// public void WashOutPutPerHours() { /* 0: 品质异常停线 1: 宕机 2: 换线 3: 实验 4: W/F送样 5: 物料缺料或生管调整影响 6: 放假 7: 停电气等停线 8: 换耗材类 9: 停机未生产 10: 效率爬升 */ NewOutPutPerHours = new List(); if (LoadOutPutPerHours == null) { return; } if (LoadOutPutPerHours.Count() == 0) { return; } foreach (var item in LoadOutPutPerHours) { NewMachineDayOutPutPerHour outPutPerHour = new NewMachineDayOutPutPerHour() { DataTime = item.DataTime, ModuleType = item.ModuleType, OutPut = item.OutPut, AutoRunTime = item.AutoRunTime, AlarmTime = item.AlarmTime, IdleTime = item.IdleTime, IdleTimeDownstream = item.IdleTimeDownstream, IdleTimeUpstream = item.IdleTimeUpstream, AlarmSum = item.AlarmSum, IdleTimeSelf = item.IdleTimeSelf, TargetTT = item.TargetTT, ActualTT = item.ActualTT, LoadMATSum = item.LoadMATSum, LoadMATTime = item.LoadMATTime, LoadTime = 0, }; if (item.DataTime > DateTime.Now) { outPutPerHour.ModuleType = ""; } NewOutPutPerHours.Add(outPutPerHour); } if (NewOutPutPerHours.Count == 0) return; foreach (var key in KeyInInfos) { if (key.KeyInType == 2 || key.KeyInType == 3 || key.KeyInType == 4 || key.KeyInType == 6 || key.KeyInType == 7 || key.KeyInType == 9) { if (key.StartTime == null) continue; if (key.EndTime == null || key.EndTime.Value.Year < 2000) { if (key.StartTime.Value.Hour >= 0 || key.StartTime.Value.Hour <= 7) key.EndTime = Convert.ToDateTime($"{key.StartTime.Value:yyyy-MM-dd} 08:00:00"); else key.EndTime = Convert.ToDateTime($"{key.StartTime.Value.AddDays(1):yyyy-MM-dd} 08:00:00"); if (key.EndTime > EndTime) key.EndTime = EndTime; } var ds = GetLoadTime(key.StartTime.Value, key.EndTime.Value); for (int i = 0; i < ds.Length; i++) { if (ds[i] > 0) { if (ds[i] == 60) { NewOutPutPerHours[i].ModuleType = ""; NewOutPutPerHours[i].OutPut = 0; NewOutPutPerHours[i].AutoRunTime = 0; NewOutPutPerHours[i].AlarmTime = 0; NewOutPutPerHours[i].IdleTime = 0; NewOutPutPerHours[i].IdleTimeDownstream = 0; NewOutPutPerHours[i].IdleTimeUpstream = 0; NewOutPutPerHours[i].AlarmSum = 0; NewOutPutPerHours[i].IdleTimeSelf = 0; NewOutPutPerHours[i].TargetTT = 0; NewOutPutPerHours[i].ActualTT = 0; NewOutPutPerHours[i].LoadMATSum = 0; NewOutPutPerHours[i].LoadMATTime = 0; NewOutPutPerHours[i].LoadTime = 60; } else { NewOutPutPerHours[i].LoadTime += (int)ds[i]; if (NewOutPutPerHours[i].LoadTime > 60) NewOutPutPerHours[i].LoadTime = 60; } } } } } } private double[] GetLoadTime(DateTime startTime, DateTime endTime) { // [00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23] // [08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 00 01 02 03 04 05 06 07] // [00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00] double[] loadTimes = new double[24]; startTime = Convert.ToDateTime($"{startTime:yyyy-MM-dd HH:mm:00}"); endTime = Convert.ToDateTime($"{endTime:yyyy-MM-dd HH:mm:00}"); if ((endTime - startTime).TotalMinutes <= 60 && endTime.Hour == startTime.Hour) { loadTimes[endTime.Hour >= 8 ? endTime.Hour - 8 : endTime.Hour + 16] = Math.Ceiling((endTime - startTime).TotalMinutes); return loadTimes; } DateTime d1 = Convert.ToDateTime($"{startTime.AddHours(1):yyyy-MM-dd HH}:00:00"); DateTime d2 = Convert.ToDateTime($"{endTime:yyyy-MM-dd HH}:00:00"); for (DateTime dt = d1; dt < d2; dt = dt.AddHours(+1)) { loadTimes[dt.Hour >= 8 ? dt.Hour - 8 : dt.Hour + 16] = 60; } loadTimes[startTime.Hour >= 8 ? startTime.Hour - 8 : startTime.Hour + 16] = Math.Ceiling((d1 - startTime).TotalMinutes); if (endTime > d2) loadTimes[endTime.Hour >= 8 ? endTime.Hour - 8 : endTime.Hour + 16] = Math.Ceiling((endTime - d2).TotalMinutes); return loadTimes; } /// /// 计算 /// public void Calculate() { int len = 10; if (NewOutPutPerHours.Count() <= 0) { return; } IEnumerable moduleTypes = NewOutPutPerHours .Where(x => x.ModuleType != null && x.ModuleType != "" && x.ModuleType.Length >= len) .Select(x => x.ModuleType[..len]) .Distinct(); if (moduleTypes.Count() == 0) { Statistic statistic = new Statistic(); Statistics.Add(statistic); return; } foreach (var moduleType in moduleTypes) { string str = moduleType[..len]; Statistic statistic = new Statistic() { ModuleType = str }; var plan = ProductionPlans.Where( x => x.ModuleType != "" && x.ModuleType.Length >= 8 && x.ModuleType[..len] == str).ToList(); if (plan != null && plan.Count() > 0) { statistic.Capa = plan[0].Capa == -1 ? 0 : plan[0].Capa; statistic.TT = plan[0].TT == -1 ? 0 : plan[0].TT; statistic.PlanCapacity = plan.Where(x => x.PlanCapacity > 0).Select(x => x.PlanCapacity).Sum(); var newOutPuts = NewOutPutPerHours.Where( x => x.ModuleType != null && x.ModuleType != "" && x.ModuleType[..len] == str && x.DataTime <= CurrentTime).ToList(); statistic.RunTime = newOutPuts.Sum(x => x.AutoRunTime); double loadTime = newOutPuts.Sum(x => x.LoadTime); DateTime endTime = Convert.ToDateTime($"{Date} 08:00:00").AddDays(1); if (CurrentTime > endTime) statistic.LoadTime = newOutPuts.Count() * 60 - loadTime; else statistic.LoadTime = (newOutPuts.Count() - 1) * 60 - loadTime + Math.Round((CurrentTime - newOutPuts.Last().DataTime).TotalMinutes); statistic.DownTime = newOutPuts.Sum(x => x.AlarmTime); statistic.IdelTime = statistic.LoadTime - statistic.DownTime - statistic.RunTime; statistic.Capacity = newOutPuts.Sum(x => x.OutPut); statistic.MorningShiftCapacity = newOutPuts.Where(x => x.DataTime.Hour >= 8 && x.DataTime.Hour < 20).Sum(x => x.OutPut); statistic.NightShiftCapacity = newOutPuts.Where(x => x.DataTime.Hour >= 20 || x.DataTime.Hour < 7).Sum(x => x.OutPut); statistic.Availability = Math.Round(statistic.LoadTime == 0 ? 0 : statistic.RunTime / statistic.LoadTime, 2); statistic.Performance = Math.Round(statistic.RunTime == 0 ? 0 : statistic.TT / 60 * statistic.Capacity / statistic.RunTime, 2); statistic.Quality = 1; statistic.OEE = Math.Round(statistic.Availability * statistic.Performance * statistic.Quality, 2); } else { var newOutPuts = NewOutPutPerHours.Where( x => x.ModuleType != null && x.ModuleType != "" && x.ModuleType[..len] == str && x.DataTime <= CurrentTime).ToList(); statistic.RunTime = newOutPuts.Sum(x => x.AutoRunTime); double loadTime = newOutPuts.Sum(x => x.LoadTime); DateTime endTime = Convert.ToDateTime($"{Date} 08:00:00").AddDays(1); if (CurrentTime > endTime) statistic.LoadTime = newOutPuts.Count() * 60 - loadTime; else statistic.LoadTime = (newOutPuts.Count() - 1) * 60 - loadTime + Math.Round((CurrentTime - newOutPuts.Last().DataTime).TotalMinutes); statistic.DownTime = newOutPuts.Sum(x => x.AlarmTime); statistic.IdelTime = statistic.LoadTime - statistic.DownTime - statistic.RunTime; statistic.Capacity = newOutPuts.Sum(x => x.OutPut); statistic.MorningShiftCapacity = newOutPuts.Where(x => x.DataTime.Hour >= 8 && x.DataTime.Hour < 20).Sum(x => x.OutPut); statistic.NightShiftCapacity = newOutPuts.Where(x => x.DataTime.Hour >= 20 || x.DataTime.Hour < 7).Sum(x => x.OutPut); statistic.Availability = Math.Round(statistic.LoadTime == 0 ? 0 : statistic.RunTime / statistic.LoadTime, 2); } Statistics.Add(statistic); } } public void CalculateV1() { IEnumerable moduleTypes = ProductionPlans .Where(x => x.ModuleType != null && x.ModuleType != "") .Select(x => x.ModuleType) .Distinct(); if (moduleTypes.Count() == 0) { Statistic statistic = new Statistic(); Statistics.Add(statistic); return; } foreach (var moduleType in moduleTypes) { Statistic statistic = new Statistic() { ModuleType = moduleType }; var plan = ProductionPlans.Where( x => x.ModuleType != "" && x.ModuleType == moduleType).ToList(); if (plan == null || plan.Count() <= 0) { Statistics.Add(statistic); continue; } statistic.Capa = plan[0].Capa == -1 ? 0 : plan[0].Capa; statistic.TT = plan[0].TT == -1 ? 0 : plan[0].TT; statistic.PlanCapacity = plan.Where(x => x.PlanCapacity > 0).Select(x => x.PlanCapacity).Sum(); var newOutPuts = NewOutPutPerHours.Where( x => x.ModuleType != null && x.ModuleType != "" && x.ModuleType.Length >= moduleType.Length && x.ModuleType[..moduleType.Length] == moduleType && x.DataTime <= CurrentTime).ToList(); if (newOutPuts == null || newOutPuts.Count <= 0) { Statistics.Add(statistic); continue; } statistic.RunTime = newOutPuts.Sum(x => x.AutoRunTime); double loadTime = newOutPuts.Sum(x => x.LoadTime); DateTime endTime = Convert.ToDateTime($"{Date} 08:00:00").AddDays(1); if (CurrentTime > endTime) statistic.LoadTime = newOutPuts.Count() * 60 - loadTime; else statistic.LoadTime = (newOutPuts.Count() - 1) * 60 - loadTime + Math.Round((CurrentTime - newOutPuts.Last().DataTime).TotalMinutes); statistic.DownTime = newOutPuts.Sum(x => x.AlarmTime); statistic.IdelTime = statistic.LoadTime - statistic.DownTime - statistic.RunTime; statistic.Capacity = newOutPuts.Sum(x => x.OutPut); statistic.MorningShiftCapacity = newOutPuts.Where(x => x.DataTime.Hour >= 8 && x.DataTime.Hour < 20).Sum(x => x.OutPut); statistic.NightShiftCapacity = newOutPuts.Where(x => x.DataTime.Hour >= 20 || x.DataTime.Hour < 7).Sum(x => x.OutPut); statistic.Availability = Math.Round(statistic.LoadTime == 0 ? 0 : statistic.RunTime / statistic.LoadTime, 2); statistic.Performance = Math.Round(statistic.RunTime == 0 ? 0 : statistic.TT / 60 * statistic.Capacity / statistic.RunTime, 2); statistic.Quality = 1; statistic.OEE = Math.Round(statistic.Availability * statistic.Performance * statistic.Quality, 2); Statistics.Add(statistic); } } } }