From 4f45f29e6b53f4c01b414409c5000ff4e212b3d9 Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期五, 05 六月 2026 13:36:54 +0800
Subject: [PATCH] 增加eip
---
report-server/src/main/java/com/ruoyi/report/service/impl/NormalDistributionServiceImpl.java | 193 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 193 insertions(+), 0 deletions(-)
diff --git a/report-server/src/main/java/com/ruoyi/report/service/impl/NormalDistributionServiceImpl.java b/report-server/src/main/java/com/ruoyi/report/service/impl/NormalDistributionServiceImpl.java
new file mode 100644
index 0000000..7f82fcb
--- /dev/null
+++ b/report-server/src/main/java/com/ruoyi/report/service/impl/NormalDistributionServiceImpl.java
@@ -0,0 +1,193 @@
+package com.ruoyi.report.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.excel.EasyExcel;
+import com.ruoyi.framework.exception.ErrorException;
+import com.ruoyi.report.dto.NormalDistributionDto;
+import com.ruoyi.report.mapper.NormalDistributionMapper;
+import com.ruoyi.report.service.NormalDistributionService;
+import com.ruoyi.report.vo.NormalDistributionVo;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 姝f�佸垎甯冨浘鏈嶅姟瀹炵幇
+ */
+@Service
+@AllArgsConstructor
+public class NormalDistributionServiceImpl implements NormalDistributionService {
+
+ private NormalDistributionMapper normalDistributionMapper;
+
+ @Override
+ public NormalDistributionVo analyze(NormalDistributionDto dto) {
+ // 鏌ヨ鏁版嵁
+ List<Map<String, Object>> itemData = normalDistributionMapper.getItemData(dto);
+
+ if (CollectionUtil.isEmpty(itemData)) {
+ return null;
+ }
+
+ if (itemData.size() < 10) {
+ throw new ErrorException("鏁版嵁閲忎笉瓒筹紝鑷冲皯闇�瑕�10涓暟鎹偣");
+ }
+
+ // 鑾峰彇鏁板�煎垪琛�
+ List<BigDecimal> values = itemData.stream()
+ .map(m -> new BigDecimal((String) m.get("lastValue")))
+ .sorted()
+ .collect(Collectors.toList());
+
+ // 璁$畻缁熻閲�
+ BigDecimal min = values.get(0);
+ BigDecimal max = values.get(values.size() - 1);
+ BigDecimal sum = values.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal mean = sum.divide(new BigDecimal(values.size()), 10, RoundingMode.HALF_UP);
+
+ // 璁$畻鏍囧噯宸�
+ BigDecimal variance = BigDecimal.ZERO;
+ for (BigDecimal v : values) {
+ BigDecimal diff = v.subtract(mean);
+ variance = variance.add(diff.multiply(diff));
+ }
+ variance = variance.divide(new BigDecimal(values.size() - 1), 10, RoundingMode.HALF_UP);
+ BigDecimal stdDev = sqrt(variance).setScale(6, RoundingMode.HALF_UP);
+
+ // 鐩存柟鍥惧垎缁�
+ int binCount = dto.getBinCount() != null ? dto.getBinCount() : 10;
+ BigDecimal range = max.subtract(min);
+ BigDecimal binWidth = range.divide(new BigDecimal(binCount), 10, RoundingMode.HALF_UP);
+
+ // 璁$畻鍒嗙粍杈圭晫
+ List<BigDecimal> binEdges = new ArrayList<>();
+ BigDecimal edge = min;
+ for (int i = 0; i <= binCount; i++) {
+ binEdges.add(edge.setScale(4, RoundingMode.HALF_UP));
+ edge = edge.add(binWidth);
+ }
+
+ // 璁$畻棰戞暟
+ List<Integer> frequencies = new ArrayList<>();
+ for (int i = 0; i < binCount; i++) {
+ BigDecimal lower = binEdges.get(i);
+ BigDecimal upper = binEdges.get(i + 1);
+ int count = 0;
+ for (BigDecimal v : values) {
+ if (v.compareTo(lower) >= 0 && (i == binCount - 1 ? v.compareTo(upper) <= 0 : v.compareTo(upper) < 0)) {
+ count++;
+ }
+ }
+ frequencies.add(count);
+ }
+
+ // 姝f�佸垎甯冩洸绾�
+ List<BigDecimal> normalX = new ArrayList<>();
+ List<BigDecimal> normalY = new ArrayList<>();
+
+ // 鐢熸垚鏇茬嚎鐐�
+ BigDecimal step = range.divide(new BigDecimal(100), 10, RoundingMode.HALF_UP);
+ BigDecimal x = min;
+ for (int i = 0; i <= 100; i++) {
+ normalX.add(x.setScale(4, RoundingMode.HALF_UP));
+
+ // 姝f�佸垎甯冨叕寮�: f(x) = (1/(蟽鈭�(2蟺))) * e^(-(x-渭)^2/(2蟽^2))
+ BigDecimal exponent = x.subtract(mean).pow(2)
+ .divide(stdDev.pow(2).multiply(new BigDecimal(2)), 10, RoundingMode.HALF_UP);
+ BigDecimal expValue = BigDecimal.valueOf(Math.exp(-exponent.doubleValue()));
+ BigDecimal coefficient = BigDecimal.ONE.divide(
+ stdDev.multiply(BigDecimal.valueOf(Math.sqrt(2 * Math.PI))),
+ 10, RoundingMode.HALF_UP);
+ BigDecimal y = coefficient.multiply(expValue)
+ .multiply(new BigDecimal(values.size()))
+ .multiply(binWidth)
+ .setScale(4, RoundingMode.HALF_UP);
+ normalY.add(y);
+
+ x = x.add(step);
+ }
+
+ // 鏋勫缓缁撴灉
+ NormalDistributionVo vo = new NormalDistributionVo();
+ vo.setBinEdges(binEdges);
+ vo.setFrequencies(frequencies);
+ vo.setNormalX(normalX);
+ vo.setNormalY(normalY);
+ vo.setMean(mean.setScale(4, RoundingMode.HALF_UP));
+ vo.setStdDev(stdDev.setScale(4, RoundingMode.HALF_UP));
+ vo.setMin(min.setScale(4, RoundingMode.HALF_UP));
+ vo.setMax(max.setScale(4, RoundingMode.HALF_UP));
+ vo.setSampleSize(values.size());
+
+ return vo;
+ }
+
+ @Override
+ public void export(NormalDistributionDto dto, HttpServletResponse response) {
+ List<Map<String, Object>> itemData = normalDistributionMapper.getItemData(dto);
+
+ if (CollectionUtil.isEmpty(itemData)) {
+ return;
+ }
+
+ try {
+ response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+ response.setCharacterEncoding("utf-8");
+ String fileName = "姝f�佸垎甯冨垎鏋愭暟鎹甠" + DateUtil.format(new Date(), "yyyyMMddHHmmss");
+ response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+
+ // 鏋勫缓瀵煎嚭鏁版嵁
+ List<Map<String, Object>> exportData = new ArrayList<>();
+ for (Map<String, Object> item : itemData) {
+ Map<String, Object> row = new HashMap<>();
+ row.put("sampleCode", item.get("sampleCode"));
+ row.put("sampleName", item.get("sampleName"));
+ row.put("itemName", item.get("itemName"));
+ row.put("lastValue", item.get("lastValue"));
+ row.put("insTime", item.get("insTime"));
+ exportData.add(row);
+ }
+
+ EasyExcel.write(response.getOutputStream())
+ .sheet("姝f�佸垎甯冨垎鏋愭暟鎹�")
+ .doWrite(exportData);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public List<String> getItemNames(NormalDistributionDto dto) {
+ return normalDistributionMapper.getItemNames(dto);
+ }
+
+ @Override
+ public List<String> getSampleNames(NormalDistributionDto dto) {
+ return normalDistributionMapper.getSampleNames(dto);
+ }
+
+ /**
+ * 骞虫柟鏍硅绠�
+ */
+ private BigDecimal sqrt(BigDecimal value) {
+ BigDecimal x = value;
+ BigDecimal tolerance = new BigDecimal("1E-10");
+ BigDecimal guess = value.divide(BigDecimal.valueOf(2), MathContext.DECIMAL128);
+
+ while (x.subtract(guess).abs().compareTo(tolerance) > 0) {
+ x = guess;
+ guess = x.add(value.divide(x, MathContext.DECIMAL128)).divide(new BigDecimal("2"), MathContext.DECIMAL128);
+ }
+
+ return guess;
+ }
+
+}
\ No newline at end of file
--
Gitblit v1.9.3