import pandas as pd
import numpy as np

import json


#rule1:连续K点超限

def rule1Examiner(value_list, thrsh_in, UB, LB):

    values2check = value_list[((-1)*int(thrsh_in)):]

    if all(np.array(values2check)>UB) | all(np.array(values2check)< LB):
        return 1
    else:
        return 0 

#rule2: 连续K点在中心线同侧,C区或以上

def rule2Examiner(value_list, thrsh_in, UB, LB):
    values2check = value_list[((-1)*int(thrsh_in)):]

    spec_center = (UB+LB) / 2

    if all(np.array(values2check)>spec_center) | all(np.array(values2check)< spec_center):
        return 1
    else:
        return 0 

#rule3: 连续K点上升或下降

def rule3Examiner(value_list, thrsh_in):
    values2check = value_list[((-1)*int(thrsh_in+1)):]

    diffList = np.diff(np.array(values2check)) 

    if all(diffList > 0) | all(diffList < 0):
        return 1
    else:
        return 0 

#rule4: 连续3点中有K点，距离中心线(同侧)大于二倍标准差

def rule4Examiner(value_list, thrsh_in, UB, LB):
    values2check = value_list[-3:]

    points = np.array(values2check)

    spec_center = (LB+UB)/2

    B_upper = spec_center + (UB-LB)*2/3
    B_lower = spec_center - (UB-LB)*2/3
    
    aboveN = np.sum(points>B_upper)
    belowN = np.sum(points<B_lower)

    if (aboveN >= thrsh_in) | (belowN>= thrsh_in):
        return 1
    else:
        return 0

#rule5: 连续K点落在距离中心线一倍标准差线(C区)内部

def rule5Examiner(value_list, thrsh_in, UB, LB):
    spec_center = (UB+LB)/2
    
    C_upper = spec_center + (UB-LB)/3
    C_lower = spec_center - (UB-LB)/3

    values2check = value_list[((-1)*int(thrsh_in)):]

    if all(np.array(values2check)>C_lower) & all(np.array(values2check)< C_upper):
        return 1
    else:
        return 0 


#rule6: 连续K点落在一倍标准差之外(C区以外)

def rule6Examiner(value_list, thrsh_in, UB, LB):
    spec_center = (UB+LB)/2
    
    C_upper = spec_center + (UB-LB)/3
    C_lower = spec_center - (UB-LB)/3

    values2check = value_list[((-1)*int(thrsh_in)):]

    if all(np.array(values2check)<C_lower) | all(np.array(values2check) > C_upper):
        return 1
    else:
        return 0 


#rule7: 连续5点中有K点，距离中心线(同侧)大于一倍标准差

def rule7Examiner(value_list, thrsh_in, UB, LB):
    values2check = value_list[-5:]

    points = np.array(values2check)

    spec_center = (LB+UB)/2

    C_upper = spec_center + (UB-LB)/3
    C_lower = spec_center - (UB-LB)/3
    
    aboveN = np.sum(points>C_upper)
    belowN = np.sum(points<C_lower)

    if (aboveN >= thrsh_in) | (belowN>= thrsh_in):
        return 1
    else:
        return 0

#rule8: 连续K点上下交错

def rule8Examiner(value_list, thrsh_in, UB, LB):
    
    spec_center = (UB+LB)/2
    
    C_upper = spec_center + (UB-LB)/3
    C_lower = spec_center - (UB-LB)/3

    values2check = value_list[((-1)*int(thrsh_in)):]

    points = np.array(values2check)

    odds = points[::2]
    evens = points[1::2]
    
    if odds[0] - spec_center > 0.0:
        odds = odds[odds > spec_center]
        evens = evens[evens < spec_center]
    else:
        odds = odds[odds < spec_center]
        evens = evens[evens > spec_center]

    if len(odds) + len(evens) == thrsh_in:
        return 1
    else:
        return 0





def DynamicDiag(json_data):

    kwargs_data = json_data

    currID = int(kwargs_data['itemID'])
    currUCL = float(kwargs_data['UCL'])
    currLCL = float(kwargs_data['LCL'])
    currTrace = int(kwargs_data['traceID'])
    currValueStr = kwargs_data['value'].split(',')
    currValue = []
    for value in currValueStr:
        currValue.append(float(value))

    rule1Thrsh = int(kwargs_data['rule1'])
    rule2Thrsh = int(kwargs_data['rule2'])
    rule3Thrsh = int(kwargs_data['rule3'])
    rule4Thrsh = int(kwargs_data['rule4'])
    rule5Thrsh = int(kwargs_data['rule5'])
    rule6Thrsh = int(kwargs_data['rule6'])
    rule7Thrsh = int(kwargs_data['rule7'])
    rule8Thrsh = int(kwargs_data['rule8'])

    rule1Res = rule1Examiner(currValue, rule1Thrsh, currUCL, currLCL)
    rule2Res = rule2Examiner(currValue, rule2Thrsh, currUCL, currLCL)
    rule3Res = rule3Examiner(currValue, rule3Thrsh)
    rule4Res = rule4Examiner(currValue, rule4Thrsh, currUCL, currLCL)
    rule5Res = rule5Examiner(currValue, rule5Thrsh, currUCL, currLCL)
    rule6Res = rule6Examiner(currValue, rule6Thrsh, currUCL, currLCL)
    rule7Res = rule7Examiner(currValue, rule7Thrsh, currUCL, currLCL)
    rule8Res = rule8Examiner(currValue, rule8Thrsh, currUCL, currLCL)

    dict2filter = {'traceID':currID,
        'rule1':rule1Res,'rule2':rule2Res,'rule3':rule3Res,'rule4':rule4Res,
        'rule5':rule5Res,'rule6':rule6Res,'rule7':rule7Res,'rule8':rule8Res,
    }

    dict2output = {}

    for thiskey in dict2filter.keys():
        if dict2filter[thiskey] == 1:
            dict2output.update({thiskey:dict2filter[thiskey]})

    dict2output.update({'traceID':currID})

    print(json.dumps(dict2output))



def DynamicHistParams(json_data):

    kwargs_data = json.loads(json_data)

    currID = int(kwargs_data['itemID'])
    currUCL = float(kwargs_data['UCL'])
    currLCL = float(kwargs_data['LCL'])
    currValueStr = kwargs_data['value'].split(',')
    currValue = []
    for value in currValueStr:
        currValue.append(float(value))

    spec_center = (UCL+LCL)/2
    sample_mu = np.mean(currValue)
    sample_std = np.std(currValue)
    
    currCpu = (currUCL - sample_mu)/(3*sample_std)
    currCpl = (sample_mu - currLCL)/(3*sample_std)

    currCp = (currUCL- currLCL)/(6*sample_std)

    currCpk = np.min(currCpu, currCpl)

    dict2output = {
        'SampleSize':len(currValue),
        'SampleMean':sample_mu,
        'SampleStd':sample_std,
        'UpperLimit':currUCL,
        'LowerLimit':currLCL,
        'MidLine':spec_center,
        'Cp':currCp,
        'Cpk':currCpk,
        'Cpu':currCpu,
        'Cpl':currCpl
    }

    print(json.dumps(dict2output))




    