using JNPF.Common.Core.Manager; using JNPF.Common.Enums; using JNPF.DependencyInjection; using JNPF.DynamicApiController; using JNPF.FriendlyException; using Microsoft.AspNetCore.Mvc; using SqlSugar; using Tnb.QcMgr.Entities; using Tnb.QcMgr.Interfaces; namespace Tnb.QcMgr { /// /// spc模块 /// [ApiDescriptionSettings(Tag = ModuleConsts.Tag, Area = ModuleConsts.Area, Order = 800)] public class QcSpcService : IQcSpcService, IDynamicApiController, ITransient { private readonly ISqlSugarRepository _repository; private readonly IUserManager _userManager; public QcSpcService(ISqlSugarRepository repository, IUserManager userManager) { _repository = repository; _userManager = userManager; } /// /// 获取spcd数据 /// /// /// [HttpPost] public async Task GetSpcItems(string id) { List datas = await _repository.AsSugarClient().Queryable().Where(p => p.mainid == id).ToListAsync(); List SpcDataInputs = new(); datas.ForEach(p => { SpcDataInput SpcDataInput = new() { mainid = p.mainid, checktime = p.checktime, batch = p.batch, data = Array.ConvertAll(p.data!.Split(","), float.Parse), checknum = p.checknum, defectivenum = p.defectivenum }; SpcDataInputs.Add(SpcDataInput); }); return SpcDataInputs; } /// /// 保存spcd /// /// /// [HttpPost] public async Task SaveData(List SpcDataInput) { ISqlSugarClient db = _repository.AsSugarClient(); try { if (!string.IsNullOrEmpty(SpcDataInput.First().mainid)) { _ = await db.Deleteable(p => p.mainid == SpcDataInput.First().mainid).ExecuteCommandAsync(); } List QcSpcDs = new(); SpcDataInput.ForEach(p => { QcSpcD QcSpcD = new() { mainid = p.mainid, checktime = p.checktime, batch = p.batch, data = string.Join(",", p.data), checknum = p.checknum, defectivenum = p.defectivenum, create_id = _userManager.UserId, create_time = DateTime.Now }; QcSpcDs.Add(QcSpcD); }); await db.Ado.BeginTranAsync(); _ = await db.Insertable(QcSpcDs).ExecuteCommandAsync(); await db.Ado.CommitTranAsync(); } catch (Exception) { await db.Ado.RollbackTranAsync(); throw Oops.Oh(ErrorCode.COM1000); } } /// /// 获取spc图表 /// /// /// [HttpPost] public async Task GetSpcData(string id) { QcSpcH QcSpcH = await _repository.AsSugarClient().Queryable().Where(p => p.id == id).FirstAsync(); List QcSpcDs = await _repository.AsSugarClient().Queryable().Where(p => p.mainid == id).ToListAsync(); List cinfigs = await _repository.AsSugarClient().Queryable().ToListAsync(); if (QcSpcH.graphtype == "X-R控制图") { XRchart XRchart = new() { xcharts = new List(), rcharts = new List() }; foreach (QcSpcD QcSpcD in QcSpcDs) { List datas = Array.ConvertAll(QcSpcD.data!.Split(",", StringSplitOptions.RemoveEmptyEntries), float.Parse).ToList(); XRxchart xchart = new() { x = datas.Average(), jc = datas.Max() - datas.Min(), usl = QcSpcH.uplimit, cl = QcSpcH.target, lsl = QcSpcH.lowerlimit }; XRrchart rchart = new() { r = datas.Max() - datas.Min() }; XRchart.xcharts.Add(xchart); XRchart.rcharts.Add(rchart); } float? xAverage = XRchart.xcharts.Select(p => p.x).Average(); float? num = XRchart.xcharts.Select(p => p.jc).Average() * cinfigs.Where(p => p.spctype == "X-R图" && p.spckey == "A2" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First(); XRchart.xcharts.ForEach(p => { p.uclx = xAverage + num; p.clx = xAverage; p.lclx = xAverage - num; }); float? D4 = cinfigs.Where(p => p.spctype == "X-R图" && p.spckey == "D4" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First(); float? D3 = cinfigs.Where(p => p.spctype == "X-R图" && p.spckey == "D3" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First(); float? rAverage = XRchart.rcharts.Select(p => p.r).Average(); XRchart.rcharts.ForEach(p => { p.uclr = rAverage * D4; p.clr = rAverage; p.lclr = rAverage * D3; }); return XRchart; } if (QcSpcH.graphtype == "X-S控制图") { XSchart XSchart = new() { xcharts = new List(), scharts = new List() }; foreach (QcSpcD QcSpcD in QcSpcDs) { List datas = Array.ConvertAll(QcSpcD.data!.Split(",", StringSplitOptions.RemoveEmptyEntries), float.Parse).ToList(); XSxchart xchart = new() { x = datas.Average(), bzc = CalculateStdDev(datas), usl = QcSpcH.uplimit, cl = QcSpcH.target, lsl = QcSpcH.lowerlimit }; XSschart schart = new() { s = CalculateStdDev(datas) }; XSchart.xcharts.Add(xchart); XSchart.scharts.Add(schart); } float? xAverage = XSchart.xcharts.Select(p => p.x).Average(); float? num = XSchart.xcharts.Select(p => p.bzc).Average() * cinfigs.Where(p => p.spctype == "X-S图" && p.spckey == "A3" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First(); XSchart.xcharts.ForEach(p => { p.uclx = xAverage + num; p.clx = xAverage; p.lclx = xAverage - num; }); float? B4 = cinfigs.Where(p => p.spctype == "X-S图" && p.spckey == "B4" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First(); float? B3 = cinfigs.Where(p => p.spctype == "X-S图" && p.spckey == "B3" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First(); float? sAverage = XSchart.scharts.Select(p => p.s).Average(); XSchart.scharts.ForEach(p => { p.ucls = sAverage * B4; p.cls = sAverage; p.lcls = sAverage * B3; }); return XSchart; } if (QcSpcH.graphtype == "X中位数-R图") { XRchart XRchart = new() { xcharts = new List(), rcharts = new List() }; foreach (QcSpcD QcSpcD in QcSpcDs) { List datas = Array.ConvertAll(QcSpcD.data!.Split(",", StringSplitOptions.RemoveEmptyEntries), float.Parse).ToList(); XRxchart xchart = new() { x = CalculateMedian(datas), jc = datas.Max() - datas.Min(), usl = QcSpcH.uplimit, cl = QcSpcH.target, lsl = QcSpcH.lowerlimit }; XRrchart rchart = new() { r = datas.Max() - datas.Min() }; XRchart.xcharts.Add(xchart); XRchart.rcharts.Add(rchart); } float? xAverage = XRchart.xcharts.Select(p => p.x).Average(); float? num = XRchart.xcharts.Select(p => p.jc).Average() * cinfigs.Where(p => p.spctype == "中位数图" && p.spckey == "A2" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First(); XRchart.xcharts.ForEach(p => { p.uclx = xAverage + num; p.clx = xAverage; p.lclx = xAverage - num; }); float? D4 = cinfigs.Where(p => p.spctype == "中位数图" && p.spckey == "D4" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First(); float? D3 = cinfigs.Where(p => p.spctype == "中位数图" && p.spckey == "D3" && p.subcapacity == QcSpcH.samplesize).Select(p => p.spcdata).First(); float? rAverage = XRchart.rcharts.Select(p => p.r).Average(); XRchart.rcharts.ForEach(p => { p.uclr = rAverage * D4; p.clr = rAverage; p.lclr = rAverage * D3; }); return XRchart; } if (QcSpcH.graphtype == "X-MR控制图") { XMRchart XMRchart = new() { xmrxcharts = new List(), xmrmrcharts = new List() }; foreach (QcSpcD QcSpcD in QcSpcDs) { List datas = Array.ConvertAll(QcSpcD.data!.Split(",", StringSplitOptions.RemoveEmptyEntries), float.Parse).ToList(); XMRxchart xchart = new() { x = datas.Average(), usl = QcSpcH.uplimit, cl = QcSpcH.target, lsl = QcSpcH.lowerlimit }; if (XMRchart.xmrxcharts.Count > 0) { XMRmrschart rchart = new() { mr = Math.Abs((float)(xchart.x - XMRchart.xmrxcharts.Last().x)!) }; XMRchart.xmrmrcharts.Add(rchart); } XMRchart.xmrxcharts.Add(xchart); } float? xAverage = XMRchart.xmrxcharts.Select(p => p.x).Average(); float? mrAverage = XMRchart.xmrmrcharts.Select(p => p.mr).Average(); XMRchart.xmrxcharts.ForEach(p => { p.uclx = xAverage + (float)(2.66 * mrAverage)!; p.clx = xAverage; p.lclx = xAverage - (float)(2.66 * mrAverage)!; }); XMRchart.xmrmrcharts.ForEach(p => { p.uclmr = (float)(mrAverage * 3.267)!; p.clmr = mrAverage; p.lclmr = 0; }); return XMRchart; } if (QcSpcH.graphtype == "P图") { List pcharts = new(); foreach (QcSpcD QcSpcD in QcSpcDs) { Pchart pchart = new() { p = QcSpcD.defectivenum / QcSpcD.checknum, n = QcSpcD.checknum }; pcharts.Add(pchart); } float? pAverage = pcharts.Select(p => p.n * p.p).Sum() / pcharts.Select(p => p.n).Sum(); float? nAverage = pcharts.Select(p => p.n).Average(); pcharts.ForEach(p => { p.cl = pAverage; p.ucl = pAverage + (float)(3 * Math.Sqrt((double)(pAverage * (1 - pAverage))!) / Math.Sqrt((double)nAverage!)); p.lcl = pAverage - (float)(3 * Math.Sqrt((double)(pAverage * (1 - pAverage))!) / Math.Sqrt((double)nAverage!)) < 0 ? 0 : pAverage - (float)(3 * Math.Sqrt((double)(pAverage * (1 - pAverage))!) / Math.Sqrt((double)nAverage!)); }); return pcharts; } if (QcSpcH.graphtype == "U图") { List ucharts = new(); foreach (QcSpcD QcSpcD in QcSpcDs) { Uchart uchart = new() { u = QcSpcD.defectivenum / QcSpcD.checknum, n = QcSpcD.checknum }; ucharts.Add(uchart); } float? uAverage = ucharts.Select(p => p.u).Sum() / ucharts.Count(); float? nAverage = ucharts.Select(p => p.n).Average(); ucharts.ForEach(p => { p.cl = uAverage; p.ucl = uAverage + (float)(3 * Math.Sqrt((double)(uAverage / nAverage)!)); p.lcl = uAverage - (float)(3 * Math.Sqrt((double)(uAverage / nAverage)!)) < 0 ? 0 : uAverage - (float)(3 * Math.Sqrt((double)(uAverage / nAverage)!)); }); return ucharts; } if (QcSpcH.graphtype == "nP图") { List npcharts = new(); foreach (QcSpcD QcSpcD in QcSpcDs) { NPchart npchart = new() { np = QcSpcD.defectivenum }; npcharts.Add(npchart); } float? npAverage = npcharts.Select(p => p.np).Sum() / npcharts.Count(); float? pAverage = npcharts.Select(p => p.np).Sum() / (npcharts.Count() * QcSpcH.subcapacity); npcharts.ForEach(p => { p.cl = npAverage; p.ucl = npAverage + (float)(3 * Math.Sqrt((double)(npAverage * (1 - pAverage))!)); p.lcl = npAverage - (float)(3 * Math.Sqrt((double)(npAverage * (1 - pAverage))!)) < 0 ? 0 : npAverage - (float)(3 * Math.Sqrt((double)(npAverage * (1 - pAverage))!)); }); return npcharts; } if (QcSpcH.graphtype == "C图") { List ccharts = new(); foreach (QcSpcD QcSpcD in QcSpcDs) { Cchart cchart = new() { c = QcSpcD.defectivenum }; ccharts.Add(cchart); } float? cAverage = ccharts.Select(p => p.c).Sum() / ccharts.Count(); ccharts.ForEach(p => { p.cl = cAverage; p.ucl = cAverage + (float)(3 * Math.Sqrt((double)cAverage!)); p.lcl = cAverage - (float)(3 * Math.Sqrt((double)cAverage!)) < 0 ? 0 : cAverage - (float)(3 * Math.Sqrt((double)cAverage!)); }); return ccharts; } return null; } //标准差计算 private static float CalculateStdDev(IEnumerable values) { double ret = 0; if (values.Count() > 0) { // 计算平均数 double avg = values.Average(); // 计算各数值与平均数的差值的平方,然后求和 double sum = values.Sum(d => Math.Pow(d - avg, 2)); // 除以数量,然后开方 ret = Math.Sqrt(sum / values.Count()); } return (float)ret; } //中位数计算 private static float CalculateMedian(IEnumerable values) { float ret = 0; float[] floats = values.OrderBy(d => d).ToArray(); ret = floats.Count() % 2 == 0 ? (floats[(floats.Count() / 2) - 1] + floats[((floats.Count() + 2) / 2) - 1]) / 2 : floats[((floats.Count() + 1) / 2) - 1]; return ret; } //移动极差平均值计算 private static float CalculateMovRange(IEnumerable values) { List floats = new(); float[] arr = values.ToArray(); for (int i = 0; i < arr.Length - 1; i++) { floats.Add(Math.Abs(arr[i + 1] - arr[i])); } return floats.Average(); } } }