MachineViewModel.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. using NPOI.SS.Formula.Functions;
  2. using NPOI.XWPF.UserModel;
  3. using ProductionLineMonitor.Application.Services.LineService.Dtos;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Drawing;
  7. using System.Linq;
  8. namespace ProductionLineMonitor.Web.Services.LineService
  9. {
  10. /// <summary>
  11. /// 机台
  12. /// </summary>
  13. public class MachineViewModel
  14. {
  15. public MachineViewModel()
  16. {
  17. }
  18. public MachineViewModel(string topic, string date, List<KeyInInfo> keyInInfos,
  19. List<ProductionPlanDtoV1> productionPlans, bool isLine)
  20. {
  21. CurrentTime = DateTime.Now;
  22. Date = date;
  23. if (!isLine)
  24. AnalysisTopic(topic);
  25. else
  26. Topic = topic;
  27. ProductionPlans = productionPlans;
  28. KeyInInfos = keyInInfos;
  29. LoadOutPutPerHours = MesApiService.GetOutPutPerHours(Topic, Date);
  30. if (LoadOutPutPerHours.Count() < 24)
  31. {
  32. Statistics = new List<Statistic>();
  33. return;
  34. }
  35. WashOutPutPerHours();
  36. CalculateV1();
  37. }
  38. /// <summary>
  39. /// 解析Topic
  40. /// </summary>
  41. /// <param name="topic"></param>
  42. protected void AnalysisTopic(string topic)
  43. {
  44. Topic = topic;
  45. int index = topic.IndexOf('-');
  46. Floor = Convert.ToInt16(topic.Substring(index + 1, 1));
  47. Line = Convert.ToInt16(topic.Substring(index - 2, 2));
  48. index = topic.IndexOf("Data");
  49. Type = topic[..index];
  50. }
  51. private string _date = string.Empty;
  52. /// <summary>
  53. /// 日期
  54. /// </summary>
  55. public string Date
  56. {
  57. get
  58. {
  59. return _date;
  60. }
  61. set
  62. {
  63. _date = value;
  64. StartTime = Convert.ToDateTime($"{_date} 08:00:00");
  65. EndTime = StartTime.AddDays(1);
  66. }
  67. }
  68. public DateTime StartTime { get; set; }
  69. public DateTime EndTime { get; set; }
  70. /// <summary>
  71. /// 当前时间
  72. /// </summary>
  73. public DateTime CurrentTime { get; set; }
  74. /// <summary>
  75. /// topic
  76. /// </summary>
  77. public string Topic { get; set; } = string.Empty;
  78. /// <summary>
  79. /// 楼层
  80. /// </summary>
  81. public int Floor { get; set; }
  82. /// <summary>
  83. /// 线别
  84. /// </summary>
  85. public int Line { get; set; }
  86. /// <summary>
  87. /// 类型
  88. /// </summary>
  89. public string Type { get; set; } = string.Empty;
  90. /// <summary>
  91. /// 生产计划
  92. /// </summary>
  93. public List<ProductionPlanDtoV1> ProductionPlans { get; set; }
  94. = new List<ProductionPlanDtoV1>();
  95. /// <summary>
  96. /// key in 的异常
  97. /// </summary>
  98. public List<KeyInInfo> KeyInInfos { get; set; }
  99. = new List<KeyInInfo>();
  100. /// <summary>
  101. /// 小时产能
  102. /// </summary>
  103. public List<MachineDayOutPutPerHour> LoadOutPutPerHours { get; set; }
  104. = new List<MachineDayOutPutPerHour>();
  105. /// <summary>
  106. /// 清理后小时产能
  107. /// </summary>
  108. public List<NewMachineDayOutPutPerHour> NewOutPutPerHours { get; set; }
  109. = new List<NewMachineDayOutPutPerHour>();
  110. /// <summary>
  111. /// 统计
  112. /// </summary>
  113. public List<Statistic> Statistics { get; set; }
  114. = new List<Statistic>();
  115. /// <summary>
  116. /// 获取小时产能
  117. /// </summary>
  118. public void UpdateModuleType()
  119. {
  120. if (Type != "AG"
  121. && Type != "FPL"
  122. && Type != "BT"
  123. && Type != "PS"
  124. && Type != "EC"
  125. && Type != "TP")
  126. return;
  127. string topic = $"FOGData#{Line}#{Line}-{Floor}FOG01";
  128. if (Line < 10)
  129. topic = $"FOGData#{Line}#0{Line}-{Floor}FOG01";
  130. var outs = MesApiService.GetOutPutPerHours(topic, Date);
  131. foreach (var item in outs)
  132. {
  133. var t = LoadOutPutPerHours.Find(x => x.DataTime == item.DataTime);
  134. if (t != null)
  135. t.ModuleType = item.ModuleType;
  136. }
  137. }
  138. /// <summary>
  139. /// 根据 key in 时间清洗小时产能
  140. /// </summary>
  141. public void WashOutPutPerHours()
  142. {
  143. /*
  144. 0: 品质异常停线
  145. 1: 宕机
  146. 2: 换线
  147. 3: 实验
  148. 4: W/F送样
  149. 5: 物料缺料或生管调整影响
  150. 6: 放假
  151. 7: 停电气等停线
  152. 8: 换耗材类
  153. 9: 停机未生产
  154. 10: 效率爬升
  155. */
  156. NewOutPutPerHours = new List<NewMachineDayOutPutPerHour>();
  157. if (LoadOutPutPerHours == null)
  158. {
  159. return;
  160. }
  161. if (LoadOutPutPerHours.Count() == 0)
  162. {
  163. return;
  164. }
  165. foreach (var item in LoadOutPutPerHours)
  166. {
  167. NewMachineDayOutPutPerHour outPutPerHour = new NewMachineDayOutPutPerHour()
  168. {
  169. DataTime = item.DataTime,
  170. ModuleType = item.ModuleType,
  171. OutPut = item.OutPut,
  172. AutoRunTime = item.AutoRunTime,
  173. AlarmTime = item.AlarmTime,
  174. IdleTime = item.IdleTime,
  175. IdleTimeDownstream = item.IdleTimeDownstream,
  176. IdleTimeUpstream = item.IdleTimeUpstream,
  177. AlarmSum = item.AlarmSum,
  178. IdleTimeSelf = item.IdleTimeSelf,
  179. TargetTT = item.TargetTT,
  180. ActualTT = item.ActualTT,
  181. LoadMATSum = item.LoadMATSum,
  182. LoadMATTime = item.LoadMATTime,
  183. LoadTime = 0,
  184. };
  185. if (item.DataTime > DateTime.Now)
  186. {
  187. outPutPerHour.ModuleType = "";
  188. }
  189. NewOutPutPerHours.Add(outPutPerHour);
  190. }
  191. if (NewOutPutPerHours.Count == 0)
  192. return;
  193. foreach (var key in KeyInInfos)
  194. {
  195. if (key.KeyInType == 2 || key.KeyInType == 3 || key.KeyInType == 4 ||
  196. key.KeyInType == 6 || key.KeyInType == 7 || key.KeyInType == 9)
  197. {
  198. if (key.StartTime == null)
  199. continue;
  200. if (key.EndTime == null || key.EndTime.Value.Year < 2000)
  201. {
  202. if (key.StartTime.Value.Hour >= 0 || key.StartTime.Value.Hour <= 7)
  203. key.EndTime = Convert.ToDateTime($"{key.StartTime.Value:yyyy-MM-dd} 08:00:00");
  204. else
  205. key.EndTime = Convert.ToDateTime($"{key.StartTime.Value.AddDays(1):yyyy-MM-dd} 08:00:00");
  206. if (key.EndTime > EndTime)
  207. key.EndTime = EndTime;
  208. }
  209. var ds = GetLoadTime(key.StartTime.Value, key.EndTime.Value);
  210. for (int i = 0; i < ds.Length; i++)
  211. {
  212. if (ds[i] > 0)
  213. {
  214. if (ds[i] == 60)
  215. {
  216. NewOutPutPerHours[i].ModuleType = "";
  217. NewOutPutPerHours[i].OutPut = 0;
  218. NewOutPutPerHours[i].AutoRunTime = 0;
  219. NewOutPutPerHours[i].AlarmTime = 0;
  220. NewOutPutPerHours[i].IdleTime = 0;
  221. NewOutPutPerHours[i].IdleTimeDownstream = 0;
  222. NewOutPutPerHours[i].IdleTimeUpstream = 0;
  223. NewOutPutPerHours[i].AlarmSum = 0;
  224. NewOutPutPerHours[i].IdleTimeSelf = 0;
  225. NewOutPutPerHours[i].TargetTT = 0;
  226. NewOutPutPerHours[i].ActualTT = 0;
  227. NewOutPutPerHours[i].LoadMATSum = 0;
  228. NewOutPutPerHours[i].LoadMATTime = 0;
  229. NewOutPutPerHours[i].LoadTime = 60;
  230. }
  231. else
  232. {
  233. NewOutPutPerHours[i].LoadTime += (int)ds[i];
  234. if (NewOutPutPerHours[i].LoadTime > 60)
  235. NewOutPutPerHours[i].LoadTime = 60;
  236. }
  237. }
  238. }
  239. }
  240. }
  241. }
  242. private double[] GetLoadTime(DateTime startTime, DateTime endTime)
  243. {
  244. // [00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
  245. // [08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 00 01 02 03 04 05 06 07]
  246. // [00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
  247. double[] loadTimes = new double[24];
  248. startTime = Convert.ToDateTime($"{startTime:yyyy-MM-dd HH:mm:00}");
  249. endTime = Convert.ToDateTime($"{endTime:yyyy-MM-dd HH:mm:00}");
  250. if ((endTime - startTime).TotalMinutes <= 60 && endTime.Hour == startTime.Hour)
  251. {
  252. loadTimes[endTime.Hour >= 8 ? endTime.Hour - 8 : endTime.Hour + 16] = Math.Ceiling((endTime - startTime).TotalMinutes);
  253. return loadTimes;
  254. }
  255. DateTime d1 = Convert.ToDateTime($"{startTime.AddHours(1):yyyy-MM-dd HH}:00:00");
  256. DateTime d2 = Convert.ToDateTime($"{endTime:yyyy-MM-dd HH}:00:00");
  257. for (DateTime dt = d1; dt < d2; dt = dt.AddHours(+1))
  258. {
  259. loadTimes[dt.Hour >= 8 ? dt.Hour - 8 : dt.Hour + 16] = 60;
  260. }
  261. loadTimes[startTime.Hour >= 8 ? startTime.Hour - 8 : startTime.Hour + 16] = Math.Ceiling((d1 - startTime).TotalMinutes);
  262. if (endTime > d2)
  263. loadTimes[endTime.Hour >= 8 ? endTime.Hour - 8 : endTime.Hour + 16] = Math.Ceiling((endTime - d2).TotalMinutes);
  264. return loadTimes;
  265. }
  266. /// <summary>
  267. /// 计算
  268. /// </summary>
  269. public void Calculate()
  270. {
  271. int len = 10;
  272. if (NewOutPutPerHours.Count() <= 0)
  273. {
  274. return;
  275. }
  276. IEnumerable<string> moduleTypes = NewOutPutPerHours
  277. .Where(x => x.ModuleType != null && x.ModuleType != "" && x.ModuleType.Length >= len)
  278. .Select(x => x.ModuleType[..len])
  279. .Distinct();
  280. if (moduleTypes.Count() == 0)
  281. {
  282. Statistic statistic = new Statistic();
  283. Statistics.Add(statistic);
  284. return;
  285. }
  286. foreach (var moduleType in moduleTypes)
  287. {
  288. string str = moduleType[..len];
  289. Statistic statistic = new Statistic()
  290. {
  291. ModuleType = str
  292. };
  293. var plan = ProductionPlans.Where(
  294. x =>
  295. x.ModuleType != "" &&
  296. x.ModuleType.Length >= 8 &&
  297. x.ModuleType[..len] == str).ToList();
  298. if (plan != null && plan.Count() > 0)
  299. {
  300. statistic.Capa = plan[0].Capa == -1 ? 0 : plan[0].Capa;
  301. statistic.TT = plan[0].TT == -1 ? 0 : plan[0].TT;
  302. statistic.PlanCapacity = plan.Where(x => x.PlanCapacity > 0).Select(x => x.PlanCapacity).Sum();
  303. var newOutPuts = NewOutPutPerHours.Where(
  304. x =>
  305. x.ModuleType != null &&
  306. x.ModuleType != "" &&
  307. x.ModuleType[..len] == str &&
  308. x.DataTime <= CurrentTime).ToList();
  309. statistic.RunTime = newOutPuts.Sum(x => x.AutoRunTime);
  310. double loadTime = newOutPuts.Sum(x => x.LoadTime);
  311. DateTime endTime = Convert.ToDateTime($"{Date} 08:00:00").AddDays(1);
  312. if (CurrentTime > endTime)
  313. statistic.LoadTime = newOutPuts.Count() * 60 - loadTime;
  314. else
  315. statistic.LoadTime = (newOutPuts.Count() - 1) * 60 - loadTime
  316. + Math.Round((CurrentTime - newOutPuts.Last().DataTime).TotalMinutes);
  317. statistic.DownTime = newOutPuts.Sum(x => x.AlarmTime);
  318. statistic.IdelTime = statistic.LoadTime - statistic.DownTime - statistic.RunTime;
  319. statistic.Capacity = newOutPuts.Sum(x => x.OutPut);
  320. statistic.MorningShiftCapacity = newOutPuts.Where(x => x.DataTime.Hour >= 8 && x.DataTime.Hour < 20).Sum(x => x.OutPut);
  321. statistic.NightShiftCapacity = newOutPuts.Where(x => x.DataTime.Hour >= 20 || x.DataTime.Hour < 7).Sum(x => x.OutPut);
  322. statistic.Availability = Math.Round(statistic.LoadTime == 0 ? 0 : statistic.RunTime / statistic.LoadTime, 2);
  323. statistic.Performance = Math.Round(statistic.RunTime == 0 ? 0 : statistic.TT / 60 * statistic.Capacity / statistic.RunTime, 2);
  324. statistic.Quality = 1;
  325. statistic.OEE = Math.Round(statistic.Availability * statistic.Performance * statistic.Quality, 2);
  326. }
  327. else
  328. {
  329. var newOutPuts = NewOutPutPerHours.Where(
  330. x =>
  331. x.ModuleType != null &&
  332. x.ModuleType != "" &&
  333. x.ModuleType[..len] == str &&
  334. x.DataTime <= CurrentTime).ToList();
  335. statistic.RunTime = newOutPuts.Sum(x => x.AutoRunTime);
  336. double loadTime = newOutPuts.Sum(x => x.LoadTime);
  337. DateTime endTime = Convert.ToDateTime($"{Date} 08:00:00").AddDays(1);
  338. if (CurrentTime > endTime)
  339. statistic.LoadTime = newOutPuts.Count() * 60 - loadTime;
  340. else
  341. statistic.LoadTime = (newOutPuts.Count() - 1) * 60 - loadTime
  342. + Math.Round((CurrentTime - newOutPuts.Last().DataTime).TotalMinutes);
  343. statistic.DownTime = newOutPuts.Sum(x => x.AlarmTime);
  344. statistic.IdelTime = statistic.LoadTime - statistic.DownTime - statistic.RunTime;
  345. statistic.Capacity = newOutPuts.Sum(x => x.OutPut);
  346. statistic.MorningShiftCapacity = newOutPuts.Where(x => x.DataTime.Hour >= 8 && x.DataTime.Hour < 20).Sum(x => x.OutPut);
  347. statistic.NightShiftCapacity = newOutPuts.Where(x => x.DataTime.Hour >= 20 || x.DataTime.Hour < 7).Sum(x => x.OutPut);
  348. statistic.Availability = Math.Round(statistic.LoadTime == 0 ? 0 : statistic.RunTime / statistic.LoadTime, 2);
  349. }
  350. Statistics.Add(statistic);
  351. }
  352. }
  353. public void CalculateV1()
  354. {
  355. IEnumerable<string> moduleTypes = ProductionPlans
  356. .Where(x => x.ModuleType != null && x.ModuleType != "")
  357. .Select(x => x.ModuleType)
  358. .Distinct();
  359. if (moduleTypes.Count() == 0)
  360. {
  361. Statistic statistic = new Statistic();
  362. Statistics.Add(statistic);
  363. return;
  364. }
  365. foreach (var moduleType in moduleTypes)
  366. {
  367. Statistic statistic = new Statistic()
  368. {
  369. ModuleType = moduleType
  370. };
  371. var plan = ProductionPlans.Where(
  372. x =>
  373. x.ModuleType != "" &&
  374. x.ModuleType == moduleType).ToList();
  375. if (plan == null || plan.Count() <= 0)
  376. {
  377. Statistics.Add(statistic);
  378. continue;
  379. }
  380. statistic.Capa = plan[0].Capa == -1 ? 0 : plan[0].Capa;
  381. statistic.TT = plan[0].TT == -1 ? 0 : plan[0].TT;
  382. statistic.PlanCapacity = plan.Where(x => x.PlanCapacity > 0).Select(x => x.PlanCapacity).Sum();
  383. var newOutPuts = NewOutPutPerHours.Where(
  384. x =>
  385. x.ModuleType != null &&
  386. x.ModuleType != "" &&
  387. x.ModuleType.Length >= moduleType.Length &&
  388. x.ModuleType[..moduleType.Length] == moduleType &&
  389. x.DataTime <= CurrentTime).ToList();
  390. if (newOutPuts == null || newOutPuts.Count <= 0)
  391. {
  392. Statistics.Add(statistic);
  393. continue;
  394. }
  395. statistic.RunTime = newOutPuts.Sum(x => x.AutoRunTime);
  396. double loadTime = newOutPuts.Sum(x => x.LoadTime);
  397. DateTime endTime = Convert.ToDateTime($"{Date} 08:00:00").AddDays(1);
  398. if (CurrentTime > endTime)
  399. statistic.LoadTime = newOutPuts.Count() * 60 - loadTime;
  400. else
  401. statistic.LoadTime = (newOutPuts.Count() - 1) * 60 - loadTime
  402. + Math.Round((CurrentTime - newOutPuts.Last().DataTime).TotalMinutes);
  403. statistic.DownTime = newOutPuts.Sum(x => x.AlarmTime);
  404. statistic.IdelTime = statistic.LoadTime - statistic.DownTime - statistic.RunTime;
  405. statistic.Capacity = newOutPuts.Sum(x => x.OutPut);
  406. statistic.MorningShiftCapacity = newOutPuts.Where(x => x.DataTime.Hour >= 8 && x.DataTime.Hour < 20).Sum(x => x.OutPut);
  407. statistic.NightShiftCapacity = newOutPuts.Where(x => x.DataTime.Hour >= 20 || x.DataTime.Hour < 7).Sum(x => x.OutPut);
  408. statistic.Availability = Math.Round(statistic.LoadTime == 0 ? 0 : statistic.RunTime / statistic.LoadTime, 2);
  409. statistic.Performance = Math.Round(statistic.RunTime == 0 ? 0 : statistic.TT / 60 * statistic.Capacity / statistic.RunTime, 2);
  410. statistic.Quality = 1;
  411. statistic.OEE = Math.Round(statistic.Availability * statistic.Performance * statistic.Quality, 2);
  412. Statistics.Add(statistic);
  413. }
  414. }
  415. }
  416. }