1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use std::fmt::Display;
use crate::stats::stddev;

/// 制程能力指标
pub struct Cpk {
    /// 制程能力
    pub cpk: f64,
    /// 制程准确度
    pub ca: f64,
    /// 制程精密度
    pub cp: f64,

    /// 规格上限
    pub usl: f64,
    /// 规格下限
    pub lsl: f64,
    /// 标准差
    pub stddev: f64,
    /// 平均值
    pub avg: f64,
    /// 最大值
    pub max: f64,
    /// 最小值
    pub min: f64,
}

impl Cpk {
    /// 初始化
    ///
    /// * usl 上限值
    /// * lsl 下限值
    /// * array 数据
    pub fn new<T: Display + std::fmt::Debug>(usl: f64, lsl: f64, array: Vec<T>) -> Self {
        let mut total = 0.0;
        let list: Vec<f64> = array.iter().map(|x|
            {
                let y = x.to_string().parse::<f64>().unwrap();
                total += y;
                y
            }
        ).collect();

        // 标准差
        let stddev = stddev(array);
        // 样本数量
        let n = list.len();
        // 平均值
        let x = total / n as f64;

        let mut max = 0.0;
        for item in list.iter() {
            if item > &max {
                max = *item;
            }
        }

        let mut min = 0.0;
        for item in list.iter() {
            if item > &min {
                min = *item;
            }
        }

        // 规格公差
        let t = usl - lsl;

        // 规格中心
        let u = (usl + lsl) / 2.0;
        let mut cp = t / (6.0 * stddev);
        let cpu = (usl - x).abs() / (3.0 * stddev);
        let cpl = (x - lsl).abs() / (3.0 * stddev);
        let ca = (x - u) / (t / 2.0);
        let mut cpk = if cpu > cpl { cpl } else { cpu };
        if cpk.is_infinite() {
            cpk = 0.0;
        }
        if cp.is_infinite() {
            cp = 0.0;
        }
        Self {
            stddev,
            max,
            min,
            avg: x,
            cpk,
            ca: ca * 100.0,
            cp,
            usl,
            lsl,
        }
    }
    pub fn cpk_rating_criteria(&self) -> (&'static str, &'static str) {
        if self.cpk >= 2.0 {
            return ("A++", "特优,可考虑降低成本。");
        } else if 1.67 <= self.cpk && self.cpk < 2.0 {
            return ("A+", "优,应当保持之。");
        } else if 1.33 <= self.cpk && self.cpk < 1.67 {
            ("A", "良,能力好,状态稳定,但应尽力提升到A+级。")
        } else if 1.00 <= self.cpk && self.cpk < 1.33 {
            ("B", "一般,制程因素稍有变异即有生产不良的危险,应利用各种资源及方法将其提升为A级。")
        } else if 0.67 <= self.cpk && self.cpk < 1.00 {
            ("C", "差,制程不良较多。须提升其能力。")
        } else {
            ("D", "不可接受,其能力太差,应考虑重新整改设计制程。")
        }
    }
    pub fn ca_rating_criteria(&self) -> (&'static str, &'static str) {
        if self.ca <= 12.5 {
            ("A", "作业员遵守作业标准操作并达到要求,需继续保持。")
        } else if 12.5 <= self.ca && self.ca <= 25.0 {
            ("B", "有必要将其改进为A级。")
        } else if 25.0 <= self.ca && self.ca <= 50.0 {
            ("C", "作业员可能看错规格或不按作业标准操作。须检讨规格及作业标准。")
        } else {
            ("D", "应采取紧急措施全面检讨所有可能影响之因素,必要时得停止生产。")
        }
    }
    pub fn cp_rating_criteria(&self) -> (&'static str, &'static str) {
        if self.cp >= 1.67 {
            ("A+", "无缺点,可考虑降低成本。")
        } else if 1.33 <= self.cp && self.cp <= 1.67 {
            ("A", "状态良好维持现状。")
        } else if 1.00 <= self.cp && self.cp <= 1.33 {
            ("B", "可以改进为A级。")
        } else if 0.67 <= self.cp && self.cp <= 1.00 {
            ("C", "制程不良较多。须提升能力。")
        } else {
            ("D", "制程能力好差,应考虑重新整改设计制程。")
        }
    }
}