use json::{JsonValue, object};
use crate::stats::{stdev, stdevp, variance, variancep};
pub struct Spc {
pub data: Vec<f64>,
pub data_len: usize,
pub group_len: usize,
pub upper: f64,
pub lower: f64,
pub value: f64,
pub max: f64,
pub min: f64,
pub avg: f64,
pub total: f64,
pub group_avg: Vec<f64>,
pub group_range: Vec<f64>,
pub group_range_max: f64,
pub group_range_min: f64,
pub group_r_avgs: Vec<f64>,
pub group_x_avgs: Vec<f64>,
pub group_r_avg: f64,
pub group_x_avg: f64,
pub group_r_avg_sum: f64,
pub group_x_avg_sum: f64,
pub group_sums: Vec<f64>,
pub group_data: Vec<Vec<f64>>,
pub decimal: usize,
pub cpu: f64,
pub cpl: f64,
pub a2: f64,
pub d2: f64,
pub d3: f64,
pub d4: f64,
pub cp: f64,
pub cpk: f64,
pub cr: f64,
pub stdev: f64,
pub stdevp: f64,
pub var: f64,
pub varp: f64,
pub pp: f64,
pub pr: f64,
pub ppk: f64,
pub sigma: f64,
pub sigma_list: Vec<f64>,
pub uclr: f64,
pub clr: f64,
pub lclr: f64,
pub uclx: f64,
pub clx: f64,
pub lclx: f64,
}
impl Spc {
pub fn new(upper: f64, lower: f64, value: f64, array: Vec<f64>, group_len: usize, decimal: usize) -> Self {
Self {
data: array.clone(),
data_len: array.len(),
total: 0.0,
upper,
value,
lower,
max: 0.0,
min: 0.0,
avg: 0.0,
group_len: group_len.clone(),
group_avg: vec![],
group_range: vec![],
group_range_max: 0.0,
group_range_min: 0.0,
group_r_avgs: vec![],
group_data: vec![],
decimal,
cpu: 0.0,
cpl: 0.0,
a2: a2(group_len),
d2: d2(group_len),
d3: d3(group_len),
d4: d4(group_len),
cp: 0.0,
cpk: 0.0,
cr: 0.0,
stdev: 0.0,
stdevp: 0.0,
var: 0.0,
varp: 0.0,
pp: 0.0,
pr: 0.0,
ppk: 0.0,
sigma: 0.0,
sigma_list: vec![],
group_x_avgs: vec![],
group_r_avg: 0.0,
group_x_avg: 0.0,
group_r_avg_sum: 0.0,
group_x_avg_sum: 0.0,
group_sums: vec![],
uclr: 0.0,
clr: 0.0,
lclr: 0.0,
uclx: 0.0,
clx: 0.0,
lclx: 0.0,
}
}
pub fn compute(&mut self) -> &mut Self {
self.max = 0.0;
self.min = self.data[0].to_string().parse::<f64>().unwrap();
let mut group_list = vec![];
for x in self.data.clone() {
self.total += x.clone();
if x > self.max.clone() {
self.max = x.clone();
}
if x < self.min.clone() {
self.min = x.clone();
}
group_list.push(x.clone());
if group_list.len() == self.group_len {
self.get_group_list_info(group_list.clone());
self.group_data.push(group_list.clone());
group_list = vec![];
}
}
if !group_list.is_empty() {
self.get_group_list_info(group_list.clone());
self.group_data.push(group_list.clone());
}
self.uclr = self.d4 * self.group_r_avg;
self.uclr = format!("{0:.1$}", self.uclr, self.decimal).parse::<f64>().unwrap();
self.clr = self.group_r_avg;
self.clr = format!("{0:.1$}", self.clr, self.decimal).parse::<f64>().unwrap();
self.lclr = self.d3 * self.group_r_avg;
self.lclr = format!("{0:.1$}", self.lclr, self.decimal).parse::<f64>().unwrap();
self.uclx = self.group_x_avg + self.a2 * self.group_r_avg;
self.uclx = format!("{0:.1$}", self.uclx, self.decimal).parse::<f64>().unwrap();
self.clx = self.group_x_avg;
self.clx = format!("{0:.1$}", self.clx, self.decimal).parse::<f64>().unwrap();
self.lclx = self.group_x_avg - self.a2 * self.group_r_avg;
self.lclx = format!("{0:.1$}", self.lclx, self.decimal).parse::<f64>().unwrap();
self.cp = (self.upper - self.lower) / (6.0 * (self.group_r_avg / self.d2));
let k = (self.value - self.group_x_avg).abs() / ((self.upper - self.lower) / 2.0);
self.cpk = (1.0 - k) * self.cp;
self.cp = format!("{0:.1$}", self.cp, self.decimal).parse::<f64>().unwrap();
self.cpk = format!("{0:.1$}", self.cpk, self.decimal).parse::<f64>().unwrap();
self.avg = self.data.clone().iter().sum::<f64>() as f64 / self.data_len.clone() as f64;
let variance = self.data.clone().iter().map(|value| {
let diff = self.avg.clone() - (value.clone() as f64);
diff.clone() * diff.clone()
}).sum::<f64>() / (self.data_len.clone() - 1) as f64;
self.sigma = variance.sqrt();
return self;
}
fn get_group_list_info(&mut self, mut group_list: Vec<f64>) {
group_list.sort_by(|a, b| a.partial_cmp(b).unwrap());
let max = group_list.last().unwrap();
let min = group_list.first().unwrap();
let max_min = format!("{0:.1$}", max - min, self.decimal).parse::<f64>().unwrap();
self.group_r_avgs.push(max_min);
self.group_r_avg_sum = self.group_r_avgs.iter().sum();
self.group_r_avg = self.group_r_avg_sum / self.group_r_avgs.len() as f64;
let mut total = 0.0;
for group in group_list.clone() {
total += group;
}
self.group_sums.push(total);
let group_x_avg = format!("{0:.1$}", total / group_list.len() as f64, self.decimal).parse::<f64>().unwrap();
self.group_x_avgs.push(group_x_avg);
self.group_x_avg_sum = self.group_x_avgs.iter().sum();
self.group_x_avg = self.group_x_avg_sum / self.group_x_avgs.len() as f64;
}
pub fn xbar_r(&self) -> JsonValue {
object! {
data:self.group_r_avgs.clone(),
UCLR:self.uclr,
CLR:self.clr,
LCLR:self.lclr
}
}
pub fn xbar_x(&self) -> JsonValue {
object! {
data:self.group_x_avgs.clone(),
UCLX:self.uclx,
CLX:self.clx,
LCLX:self.lclx
}
}
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 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", "制程能力好差,应考虑重新整改设计制程。")
}
}
}
fn a2(len: usize) -> f64 {
match len {
2 => 1.880,
3 => 1.023,
4 => 0.729,
5 => 0.577,
6 => 0.483,
7 => 0.149,
8 => 0.373,
9 => 0.337,
10 => 0.308,
11 => 0.285,
12 => 0.266,
13 => 0.249,
14 => 0.235,
15 => 0.223,
16 => 0.212,
17 => 0.203,
18 => 0.194,
19 => 0.187,
20 => 0.180,
21 => 0.173,
22 => 0.167,
23 => 0.162,
24 => 0.157,
25 => 0.153,
_ => 0.0
}
}
fn d2(len: usize) -> f64 {
match len {
2 => 1.128,
3 => 1.693,
4 => 2.059,
5 => 2.326,
6 => 2.534,
7 => 2.704,
8 => 2.847,
9 => 2.970,
10 => 3.078,
11 => 3.173,
12 => 3.258,
13 => 3.336,
14 => 3.407,
15 => 3.472,
16 => 3.532,
17 => 3.588,
18 => 3.640,
19 => 3.689,
20 => 3.735,
21 => 3.778,
22 => 3.819,
23 => 3.858,
24 => 3.895,
25 => 3.931,
_ => 0.0
}
}
fn d3(len: usize) -> f64 {
match len {
7 => 0.076,
8 => 0.136,
9 => 0.184,
10 => 0.223,
11 => 0.256,
12 => 0.283,
13 => 0.307,
14 => 0.328,
15 => 0.347,
16 => 0.363,
17 => 0.738,
18 => 0.391,
19 => 0.403,
20 => 0.415,
21 => 0.425,
22 => 0.434,
23 => 0.443,
24 => 0.451,
25 => 0.459,
_ => 0.0
}
}
fn d4(len: usize) -> f64 {
match len {
2 => 3.267,
3 => 2.574,
4 => 2.282,
5 => 2.114,
6 => 2.004,
7 => 1.924,
8 => 1.864,
9 => 1.816,
10 => 1.777,
11 => 1.744,
12 => 1.717,
13 => 1.693,
14 => 1.672,
15 => 1.653,
16 => 1.637,
17 => 1.622,
18 => 1.608,
19 => 1.597,
20 => 1.585,
21 => 1.575,
22 => 1.566,
23 => 1.557,
24 => 1.548,
25 => 1.541,
_ => 0.0
}
}