# -*- coding: utf-8 -*-
"""
Created on Tue Jan  8 19:06:21 2019

@author: hjjiang
"""

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import cross_val_score
from sklearn.cluster import KMeans
from sklearn.cluster import AgglomerativeClustering
from sklearn.manifold import TSNE
from sklearn.decomposition import PCA
from pyclustering.cluster.kmedoids import kmedoids
from sklearn.preprocessing import normalize
from sklearn.mixture import GaussianMixture
from sklearn.feature_selection import RFECV
from sklearn.metrics import accuracy_score

##############################################################################
#------------------调参区域-------------------
#无监督学习
plot_E5_1 = 0 #E3-E7的TSNE图
plot_E5_2 = 0 #E5的ICM,TE的TSNE图
plot_E5_3 = 0 #E5的EPI,PE的TSNE图
method_E5_1 = 3 #分离E5的TE,ICM的聚类方法 见下方聚类方法
method_E5_2 = 3 #分离E5的EPI,PE的聚类方法 见下方聚类方法

plot_E7_1 = 0 #E7的ICM,TE的TSNE图
plot_E7_2 = 0 #E7的EPI,PE的TSNE图
method_E7_1 = 3 #分离E7的ICM,TE的聚类方法 见下方聚类方法
method_E7_2 = 3 #分离E7的EPI,PE的聚类方法 见下方聚类方法
'''
聚类方法
1:KMeans
2:GMM
3:AgglomerativeClustering
'''
#监督学习
method_LDA = 0
method_LinearSVC = 1
method_SVM = 0
method_RandomForest = 0
method_DecisionTree = 0
method_MultilayerPerceptron = 0
method_NearestNeighbor = 0

#画出E3,E4,E6,E7谱系分类情况 直方图
plot_LDA = 0
plot_LinearSVC = 1
plot_SVM = 0
plot_RandomForest = 0
plot_DecisionTree = 0
plot_MultilayerPerceptron = 0
plot_NearestNeighbor = 0

#特征选择 只有LDA LinearSVC可以设置feature_select_method_RFECV=1
feature_select_method_RFECV = 0 #recursive feature elimination
##############################################################################
#------数据读取，用我给的csv，已经把label放进去了-------
dat = pd.read_csv("./embryonic_data_490genes.csv", index_col = 0)
allX, ally = dat.iloc[:,1:], dat['label'] #提取数据和标签

#--------数据预处理---------------------------
allX = np.log10(allX + 1) #对数据取log

##############################################################################
#------------------无监督学习-------------------
#-----------TSNE，目的是比较每天的差异---------------------
X_2d = TSNE(n_components=2,random_state=0).fit_transform(allX)
if plot_E5_1:
    plt.figure(figsize=(6, 5))
    colors = 'r', 'g', 'b', 'c', 'm'
    la=np.array([3,4,5,6,7])
    for i, c, label in zip(la, colors, la):
        plt.scatter(X_2d[ally == i, 0], X_2d[ally == i, 1], c=c, label=label)
    plt.legend()
    plt.show()

#------E5分离pre-lineage-----------------------------------
threshold = 15 #根据上面的图人为设定的pre-lineage的界限

E5_without_pre = allX[(X_2d[:,0] < threshold) & (ally == 5)]  #E5_without_pre
allX['lineage'] = 0 #标签初始化为0   TE->1;ICM ->2(进一步分裂):EPI->2, PE->3; pre-lineage->4
allX['lineage'][(X_2d[:,0] > threshold) & (ally == 5)] = 4 # 给E5的pre-lineage贴标签

pca = PCA(n_components=3) #特征提取
E5_without_pre_processed = pca.fit_transform(E5_without_pre)

#------聚类：E5_without_pre，分成2类ICM和TE----------------
if method_E5_1 == 1:
    estimator = KMeans(n_clusters=2).fit(E5_without_pre_processed)
    label_pred = estimator.labels_  # 获取聚类标签 根据论文，多的是TE，少的是ICM(EPI+PE)

if method_E5_1 == 2:
    estimator = GaussianMixture(n_components=2, covariance_type='diag', random_state=0).fit(E5_without_pre_processed)
    label_pred = estimator.predict(E5_without_pre_processed)

if method_E5_1 == 3:
    estimator=AgglomerativeClustering(affinity='euclidean', compute_full_tree='auto',
            connectivity=None, linkage='ward', memory=None, n_clusters=2).fit(E5_without_pre_processed)
    label_pred = estimator.labels_

ind = int(sum(label_pred==0) < sum(label_pred==1)) #指示因子
allX['lineage'][(X_2d[:,0] < threshold) & (ally == 5)] = label_pred*(1-2*ind) +ind + 1

'''
这里有一个逻辑判断,由于少的那一类的标签，要定义为ICM，即贴上“2”的标签
1.label_pred==0 说明0少一些，0表示ICM
    ind = 1
    label_pred(1-2ind)+ind+1 = -label_pred+2   0(ICM)->2, 1(TE)->1
2.label_pred==1 说明1少一些，1表示ICM
    ind = 0
    label_pred(1-2ind)+ind+1 = label_pred+1    1(ICM)->2, 0(TE)->1
TE: 1  ICM: 2
'''

if plot_E5_2:
    X_2d = TSNE(n_components=2,random_state=0).fit_transform(E5_without_pre)
    plt.figure(figsize=(6, 5))
    colors = 'r', 'g'
    la=np.array([0,1])
    for i, c, label in zip(la, colors, la):
        plt.scatter(X_2d[label_pred == i, 0], X_2d[label_pred == i, 1], c=c, label=label)
    plt.legend()
    plt.title('ICM-TE t-SNE plot')
    plt.xlabel('t-SNE 1')
    plt.ylabel('t-SNE 2')
    plt.show()

#------聚类：E5_ICM，分成2类EPI和PE----------------
E5_ICM = allX[allX['lineage']== 2]  #选出E5中所有ICM
E5_ICM = E5_ICM.iloc[:,:-1]

if method_E5_2 == 1: #KNN
    estimator = KMeans(n_clusters=2).fit(E5_ICM)  #获取聚类标签 根据论文，多的是EPI，少的是PE
    label_pred_EPI_PE = estimator.labels_  # 获取聚类标签 根据论文，多的是TE，少的是ICM(EPI+PE)

if method_E5_2 == 2: #GMM
    estimator = GaussianMixture(n_components=2, covariance_type='diag', random_state=0).fit(E5_ICM)
    label_pred_EPI_PE = estimator.predict(E5_ICM)

if method_E5_2 == 3: #AgglomerativeClustering
    estimator=AgglomerativeClustering(affinity='euclidean', compute_full_tree='auto',
            connectivity=None, linkage='ward', memory=None, n_clusters=2).fit(E5_ICM)
    label_pred_EPI_PE = estimator.labels_

ind = int(sum(label_pred_EPI_PE==0) < sum(label_pred_EPI_PE==1)) #指示因子
allX['lineage'][allX['lineage']== 2] = label_pred_EPI_PE*(1-2*ind) +ind + 2 #重新贴标签，EPI=2,PE=3

if plot_E5_3:
    X_2d_EPI_PE = TSNE(n_components=2,random_state=0).fit_transform(E5_ICM)
    plt.figure(figsize=(6, 5))
    colors = 'r', 'g'
    la=np.array([0,1])
    for i, c, label in zip(la, colors, la):
        plt.scatter(X_2d_EPI_PE[label_pred_EPI_PE == i, 0], X_2d_EPI_PE[label_pred_EPI_PE == i, 1], c=c, label=label)
    plt.legend()
    plt.title('EPI-PE t-SNE plot')
    plt.xlabel('t-SNE 1')
    plt.ylabel('t-SNE 2')
    plt.show()

#E5结果统计
print('E5 TE NUM:', sum(allX['lineage']==1))
print('E5 EPI NUM:', sum(allX['lineage']==2))
print('E5 PE NUM:', sum(allX['lineage']==3))
print('E5 PRE NUM:', sum(allX['lineage']==4), '\n')

#E5聚类结果提取
new5= allX[allX['lineage'] != 0]
new_data5, new_label5 = new5.iloc[:,:490], new5['lineage']

##############################################################################
#----------------------------E7聚类-----------------------------------
allX['lineage'] = 0 #标签初始化为0   TE->1;ICM ->2(进一步分裂):EPI->2, PE->3;
E7_data = allX[ally == 7]
E7_data = E7_data.iloc[:,:-1]
E7_data = normalize(E7_data)
pca = PCA(n_components=3) #特征提取
E7_data = pca.fit_transform(E7_data)

#------聚类:分成2类ICM和TE----------------
if method_E7_1 == 1:
    estimator = KMeans(n_clusters=2).fit(E7_data)
    label_pred = estimator.labels_  # 获取聚类标签 根据论文，多的是TE，少的是ICM(EPI+PE)

if method_E7_1 == 2:
    estimator = GaussianMixture(n_components=2, covariance_type='diag', random_state=0).fit(E7_data)
    label_pred = estimator.predict(E7_data)

if method_E7_1 == 3:
    estimator = AgglomerativeClustering(affinity='euclidean', compute_full_tree='auto',
            connectivity=None, linkage='ward', memory=None, n_clusters=2).fit(E7_data)
    label_pred = estimator.labels_

ind = int(sum(label_pred == 0) < sum(label_pred == 1)) #指示因子
allX['lineage'][ally == 7] = label_pred*(1-2*ind) +ind + 1

if plot_E7_1:
    X_2d = TSNE(n_components=2,random_state=0).fit_transform(allX[ally == 7].iloc[:,:-1])
    plt.figure(figsize=(6, 5))
    colors = 'r', 'g'
    la=np.array([0,1])
    for i, c, label in zip(la, colors, la):
        plt.scatter(X_2d[label_pred == i, 0], X_2d[label_pred == i, 1], c=c, label=label)
    plt.legend()
    plt.title('ICM-TE t-SNE plot')
    plt.xlabel('t-SNE 1')
    plt.ylabel('t-SNE 2')
    plt.show()

#------聚类：E7_ICM，分成2类EPI和PE----------------
E7_ICM = allX[allX['lineage']== 2]  #选出E7中所有ICM
E7_ICM = E7_ICM.iloc[:,:-1]

if method_E7_2 == 1: #KNN
    estimator = KMeans(n_clusters=2).fit(E7_ICM)  #获取聚类标签 根据论文，多的是EPI，少的是PE
    label_pred_EPI_PE = estimator.labels_  # 获取聚类标签 根据论文，多的是TE，少的是ICM(EPI+PE)

if method_E7_2 == 2: #GMM
    estimator = GaussianMixture(n_components=2, covariance_type='diag', random_state=0).fit(E7_ICM)
    label_pred_EPI_PE = estimator.predict(E7_ICM)

if method_E7_2 == 3: #AgglomerativeClustering
    estimator = AgglomerativeClustering(affinity='euclidean', compute_full_tree='auto',
            connectivity=None, linkage='ward', memory=None, n_clusters=2).fit(E7_ICM)
    label_pred_EPI_PE = estimator.labels_

ind = int(sum(label_pred_EPI_PE==0) < sum(label_pred_EPI_PE==1)) #指示因子
allX['lineage'][allX['lineage']== 2] = label_pred_EPI_PE*(1-2*ind) +ind + 2 #重新贴标签，EPI=2,PE=3

if plot_E7_2:
    X_2d_EPI_PE = TSNE(n_components=2,random_state=0).fit_transform(E7_ICM)
    plt.figure(figsize=(6, 5))
    colors = 'r', 'g'
    la=np.array([0,1])
    for i, c, label in zip(la, colors, la):
        plt.scatter(X_2d_EPI_PE[label_pred_EPI_PE == i, 0], X_2d_EPI_PE[label_pred_EPI_PE == i, 1], c=c, label=label)
    plt.legend()
    plt.title('EPI-PE t-SNE plot')
    plt.xlabel('t-SNE 1')
    plt.ylabel('t-SNE 2')
    plt.show()

#E7结果统计
print('E7 TE NUM:', sum(allX['lineage']==1))
print('E7 EPI NUM:', sum(allX['lineage']==2))
print('E7 PE NUM:', sum(allX['lineage']==3))

#E7聚类结果提取
new7= allX[allX['lineage'] != 0]
new_data7, new_label7 = new7.iloc[:,:490], new7['lineage']

##############################################################################
#------------------监督学习-------------------
dat_3 = allX[ally == 3].iloc[:,:-1]
dat_4 = allX[ally == 4].iloc[:,:-1]
dat_6 = allX[ally == 6].iloc[:,:-1]
dat_7 = allX[ally == 7].iloc[:,:-1]

#Linear Discriminant Analysis with feature selection
if method_LDA:
    from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
    if feature_select_method_RFECV:
        LDA = LinearDiscriminantAnalysis()
        rfe = RFECV(estimator=LDA, step=10, cv=8)
        rfe = rfe.fit(new_data5, new_label5)
        index = np.where(rfe.support_ == True)[0]
        new_data5_selected = new_data5.iloc[:,index]
        LDA.fit(new_data5_selected, new_label5)
        LDA_prediction3=LDA.predict(dat_3.iloc[:,index])
        LDA_prediction4=LDA.predict(dat_4.iloc[:,index])
        LDA_prediction6=LDA.predict(dat_6.iloc[:,index])
        LDA_prediction7=LDA.predict(dat_7.iloc[:,index])
        print('----------------------RFECV----------------------')
    else:
        LDA = LinearDiscriminantAnalysis()
        new_data5_selected = new_data5
        LDA.fit(new_data5_selected, new_label5)
        LDA_prediction3=LDA.predict(dat_3)
        LDA_prediction4=LDA.predict(dat_4)
        LDA_prediction6=LDA.predict(dat_6)
        LDA_prediction7=LDA.predict(dat_7)

    if plot_LDA:
        for i in range(4):
            plt.figure(figsize=(6, 5))
            name_list = ['TE','EPI','PE','PRE']
            if i < 2:
                num_list = [sum(eval('LDA_prediction' + str(i+3)) == 1),sum(eval('LDA_prediction' + str(i+3)) == 2),sum(eval('LDA_prediction' + str(i+3)) == 3),sum(eval('LDA_prediction' + str(i+3)) == 4)]
            else:
                num_list = [sum(eval('LDA_prediction' + str(i+4)) == 1),sum(eval('LDA_prediction' + str(i+4)) == 2),sum(eval('LDA_prediction' + str(i+4)) == 3),sum(eval('LDA_prediction' + str(i+4)) == 4)]
            plt.bar(range(len(num_list)), num_list,color='rgbc',tick_label=name_list)
            plt.title('LDA-'+'E'+str(i+3)) if i <2 else plt.title('LDA-'+'E'+str(i+4))
            for a,b in zip(range(len(num_list)), num_list):
                plt.text(a, b+0.05, '%.0f' % b, ha='center', va='bottom', fontsize=10)
            plt.show()

    scores_LDA = cross_val_score(LDA, new_data5_selected, new_label5, cv=8)
    scores_LDA_mean=scores_LDA.mean()
    print('---------scores_LDA_mean---------:', scores_LDA_mean)
    scores_LDA_E7_test = accuracy_score(new_label7, LDA_prediction7)
    print('---------scores_LDA_E7_test---------:', scores_LDA_E7_test)

#SVM
if method_SVM:
    from sklearn.svm import SVC
    #if feature_select_method_REFCV: svm does not expose "coef_" or "feature_importances_" attributes
    SVM = SVC(kernel='rbf', gamma='auto')
    SVM.fit(new_data5, new_label5)
    SVM_prediction3=SVM.predict(dat_3)
    SVM_prediction4=SVM.predict(dat_4)
    SVM_prediction6=SVM.predict(dat_6)
    SVM_prediction7=SVM.predict(dat_7)
    scores_SVM = cross_val_score(SVM, new_data5, new_label5, cv=8)
    scores_SVM_mean=scores_SVM.mean()
    print('---------scores_SVM_mean---------:', scores_SVM_mean)
    scores_SVM_E7_test = accuracy_score(new_label7, SVM_prediction7)
    print('---------scores_SVM_E7_test---------:', scores_SVM_E7_test)

    if plot_SVM:
        for i in range(4):
            plt.figure(figsize=(6, 5))
            name_list = ['TE','EPI','PE','PRE']
            if i < 2:
                num_list = [sum(eval('SVM_prediction' + str(i+3)) == 1),sum(eval('SVM_prediction' + str(i+3)) == 2),sum(eval('SVM_prediction' + str(i+3)) == 3),sum(eval('SVM_prediction' + str(i+3)) == 4)]
            else:
                num_list = [sum(eval('SVM_prediction' + str(i+4)) == 1),sum(eval('SVM_prediction' + str(i+4)) == 2),sum(eval('SVM_prediction' + str(i+4)) == 3),sum(eval('SVM_prediction' + str(i+4)) == 4)]
            plt.bar(range(len(num_list)), num_list,color='rgbc',tick_label=name_list)
            plt.title('SVM-'+'E'+str(i+3)) if i <2 else plt.title('SVM-'+'E'+str(i+4))
            for a,b in zip(range(len(num_list)), num_list):
                plt.text(a, b+0.05, '%.0f' % b, ha='center', va='bottom', fontsize=10)
            plt.show()

#LinearSVC
if method_LinearSVC:
    from sklearn.svm import LinearSVC
    if feature_select_method_RFECV:
        LSVC = LinearSVC(C=0.01, penalty='l1', dual=False, max_iter=5000)
        rfe = RFECV(estimator=LSVC, step=100, cv=8)
        rfe = rfe.fit(new_data5, new_label5)
        index = np.where(rfe.support_ == True)[0]
        new_data5_selected = new_data5.iloc[:,index]
        LSVC.fit(new_data5_selected, new_label5)
        LSVC_prediction3=LSVC.predict(dat_3.iloc[:,index])
        LSVC_prediction4=LSVC.predict(dat_4.iloc[:,index])
        LSVC_prediction6=LSVC.predict(dat_6.iloc[:,index])
        LSVC_prediction7=LSVC.predict(dat_7.iloc[:,index])
        print('----------------------RFECV----------------------')

    else:
        LSVC = LinearSVC(C=0.01, penalty='l1', dual=False, max_iter=5000)
        new_data5_selected = new_data5
        LSVC.fit(new_data5_selected, new_label5)
        LSVC_prediction3=LSVC.predict(dat_3)
        LSVC_prediction4=LSVC.predict(dat_4)
        LSVC_prediction6=LSVC.predict(dat_6)
        LSVC_prediction7=LSVC.predict(dat_7)

    if plot_LinearSVC:
        for i in range(4):
            plt.figure(figsize=(6, 5))
            name_list = ['TE','EPI','PE','PRE']
            if i < 2:
                num_list = [sum(eval('LSVC_prediction' + str(i+3)) == 1),sum(eval('LSVC_prediction' + str(i+3)) == 2),sum(eval('LSVC_prediction' + str(i+3)) == 3),sum(eval('LSVC_prediction' + str(i+3)) == 4)]
            else:
                num_list = [sum(eval('LSVC_prediction' + str(i+4)) == 1),sum(eval('LSVC_prediction' + str(i+4)) == 2),sum(eval('LSVC_prediction' + str(i+4)) == 3),sum(eval('LSVC_prediction' + str(i+4)) == 4)]
            plt.bar(range(len(num_list)), num_list,color='rgbc',tick_label=name_list)
            plt.title('LinearSVC-'+'E'+str(i+3)) if i <2 else plt.title('LinearSVC-'+'E'+str(i+4))
            for a,b in zip(range(len(num_list)), num_list):
                plt.text(a, b+0.05, '%.0f' % b, ha='center', va='bottom', fontsize=10)
            plt.show()

    scores_LSVC = cross_val_score(LSVC, new_data5_selected, new_label5, cv=8)
    scores_LSVC_mean=scores_LSVC.mean()
    print('---------scores_LSVC_mean---------:', scores_LSVC_mean)
    scores_LSVC_E7_test = accuracy_score(new_label7, LSVC_prediction7)
    print('---------scores_LSVC_E7_test---------:', scores_LSVC_E7_test)

#Random Forest
if method_RandomForest:
    from sklearn.ensemble import RandomForestClassifier
    RF=RandomForestClassifier(n_estimators=100, max_depth=10,random_state=0)
    scores_RF = cross_val_score(RF, new_data5, new_label5, cv=8)
    scores_RF_mean=scores_RF.mean()
    print('---------scores_RF_mean---------:', scores_RF_mean)
    RF.fit(new_data5,new_label5)
    RF_prediction3=RF.predict(dat_3)
    RF_prediction4=RF.predict(dat_4)
    RF_prediction6=RF.predict(dat_6)
    RF_prediction7=RF.predict(dat_7)
    scores_RF_E7_test = accuracy_score(new_label7, RF_prediction7)
    print('---------scores_RF_E7_test---------:', scores_RF_E7_test)

    if plot_RandomForest:
        for i in range(4):
            plt.figure(figsize=(6, 5))
            name_list = ['TE','EPI','PE','PRE']
            if i < 2:
                num_list = [sum(eval('RF_prediction' + str(i+3)) == 1),sum(eval('RF_prediction' + str(i+3)) == 2),sum(eval('RF_prediction' + str(i+3)) == 3),sum(eval('RF_prediction' + str(i+3)) == 4)]
            else:
                num_list = [sum(eval('RF_prediction' + str(i+4)) == 1),sum(eval('RF_prediction' + str(i+4)) == 2),sum(eval('RF_prediction' + str(i+4)) == 3),sum(eval('RF_prediction' + str(i+4)) == 4)]
            plt.bar(range(len(num_list)), num_list,color='rgbc',tick_label=name_list)
            plt.title('RandomForest-'+'E'+str(i+3)) if i <2 else plt.title('RandomForest-'+'E'+str(i+4))
            for a,b in zip(range(len(num_list)), num_list):
                plt.text(a, b+0.05, '%.0f' % b, ha='center', va='bottom', fontsize=10)
            plt.show()

#Decision Tree
if method_DecisionTree:
    from sklearn import tree
    DT= tree.DecisionTreeClassifier()
    scores_DT = cross_val_score(DT, new_data5, new_label5, cv=8)
    scores_DT_mean=scores_DT.mean()
    print('---------scores_DT_mean---------:', scores_DT_mean)
    DT.fit(new_data5,new_label5)
    DT_prediction3=DT.predict(dat_3)
    DT_prediction4=DT.predict(dat_4)
    DT_prediction6=DT.predict(dat_6)
    DT_prediction7=DT.predict(dat_7)
    scores_DT_E7_test = accuracy_score(new_label7, DT_prediction7)
    print('---------scores_DT_E7_test---------:', scores_DT_E7_test)

    if plot_DecisionTree:
        for i in range(4):
            plt.figure(figsize=(6, 5))
            name_list = ['TE','EPI','PE','PRE']
            if i < 2:
                num_list = [sum(eval('DT_prediction' + str(i+3)) == 1),sum(eval('DT_prediction' + str(i+3)) == 2),sum(eval('DT_prediction' + str(i+3)) == 3),sum(eval('DT_prediction' + str(i+3)) == 4)]
            else:
                num_list = [sum(eval('DT_prediction' + str(i+4)) == 1),sum(eval('DT_prediction' + str(i+4)) == 2),sum(eval('DT_prediction' + str(i+4)) == 3),sum(eval('DT_prediction' + str(i+4)) == 4)]
            plt.bar(range(len(num_list)), num_list,color='rgbc',tick_label=name_list)
            plt.title('DecisionTree-'+'E'+str(i+3)) if i <2 else plt.title('DecisionTree-'+'E'+str(i+4))
            for a,b in zip(range(len(num_list)), num_list):
                plt.text(a, b+0.05, '%.0f' % b, ha='center', va='bottom', fontsize=10)
            plt.show()

#MLP
if method_MultilayerPerceptron:
    from sklearn.neural_network import MLPClassifier
    MLP= MLPClassifier(solver='lbfgs', alpha=1e-5, hidden_layer_sizes=9, random_state=1)
    scores_MLP = cross_val_score(MLP, new_data5, new_label5, cv=8)
    scores_MLP_mean=scores_MLP.mean()
    print('---------scores_MLP_mean---------:', scores_MLP_mean)
    MLP.fit(new_data5,new_label5)
    MLP_prediction3=MLP.predict(dat_3)
    MLP_prediction4=MLP.predict(dat_4)
    MLP_prediction6=MLP.predict(dat_6)
    MLP_prediction7=MLP.predict(dat_7)
    scores_MLP_E7_test = accuracy_score(new_label7, MLP_prediction7)
    print('---------scores_MLP_E7_test---------:', scores_MLP_E7_test)

    if plot_MultilayerPerceptron:
        for i in range(4):
            plt.figure(figsize=(6, 5))
            name_list = ['TE','EPI','PE','PRE']
            if i < 2:
                num_list = [sum(eval('MLP_prediction' + str(i+3)) == 1),sum(eval('MLP_prediction' + str(i+3)) == 2),sum(eval('MLP_prediction' + str(i+3)) == 3),sum(eval('MLP_prediction' + str(i+3)) == 4)]
            else:
                num_list = [sum(eval('MLP_prediction' + str(i+4)) == 1),sum(eval('MLP_prediction' + str(i+4)) == 2),sum(eval('MLP_prediction' + str(i+4)) == 3),sum(eval('MLP_prediction' + str(i+4)) == 4)]
            plt.bar(range(len(num_list)), num_list,color='rgbc',tick_label=name_list)
            plt.title('MultilayerPerceptron-'+'E'+str(i+3)) if i <2 else plt.title('MultilayerPerceptron-'+'E'+str(i+4))
            for a,b in zip(range(len(num_list)), num_list):
                plt.text(a, b+0.05, '%.0f' % b, ha='center', va='bottom', fontsize=10)
            plt.show()

#Nearest Neighbour Classification
if method_NearestNeighbor:
    from sklearn.neighbors import KNeighborsClassifier
    KNN = KNeighborsClassifier(n_neighbors=6)
    scores_KNN = cross_val_score(KNN, new_data5, new_label5, cv=8)
    scores_KNN_mean=scores_KNN.mean()
    print('---------scores_KNN_mean---------:', scores_KNN_mean)
    KNN.fit(new_data5,new_label5)
    KNN_prediction3=KNN.predict(dat_3)
    KNN_prediction4=KNN.predict(dat_4)
    KNN_prediction6=KNN.predict(dat_6)
    KNN_prediction7=KNN.predict(dat_7)
    scores_KNN_E7_test = accuracy_score(new_label7, KNN_prediction7)
    print('---------scores_KNN_E7_test---------:', scores_KNN_E7_test)

    if plot_NearestNeighbor:
        for i in range(4):
            plt.figure(figsize=(6, 5))
            name_list = ['TE','EPI','PE','PRE']
            if i < 2:
                num_list = [sum(eval('KNN_prediction' + str(i+3)) == 1),sum(eval('KNN_prediction' + str(i+3)) == 2),sum(eval('KNN_prediction' + str(i+3)) == 3),sum(eval('KNN_prediction' + str(i+3)) == 4)]
            else:
                num_list = [sum(eval('KNN_prediction' + str(i+4)) == 1),sum(eval('KNN_prediction' + str(i+4)) == 2),sum(eval('KNN_prediction' + str(i+4)) == 3),sum(eval('KNN_prediction' + str(i+4)) == 4)]
            plt.bar(range(len(num_list)), num_list,color='rgbc',tick_label=name_list)
            plt.title('NearestNeighbor-'+'E'+str(i+3)) if i <2 else plt.title('NearestNeighbor-'+'E'+str(i+4))
            for a,b in zip(range(len(num_list)), num_list):
                plt.text(a, b+0.05, '%.0f' % b, ha='center', va='bottom', fontsize=10)
            plt.show()


from histologieverwaltung.views import HistoMethods
from django.conf.urls import patterns, url

urlpatterns = patterns('histologieverwaltung.views',

    url(r'^$', 'index', name='index'),
    url(r'^detail/(?P<patient_id>[a-z A-Z 0-9]+)/(?P<histo_id>[\d\-H]+)/$', HistoMethods.showHistoDetail, name='histoDetail'),
    url(r'^showPatientHisto/(?P<patient_id>[a-z A-Z 0-9]+)/$', HistoMethods.showPatientHisto, name='showPatientProbe'),
    url(r'^anzeigeHistologiebefunde_admin/$', HistoMethods.showHistoBefunde_admin,name='showHistoBefunde_admin'),
    url(r'^erstelleHistologiebefund/(?P<patient_id>[a-z A-Z 0-9]+)/$', HistoMethods.createHistoBefund, name='createHistoBefund'),
    url(r'^editHistologiebefund/(?P<histo_ID>[\d\-H]+)$', HistoMethods.editHistoBefund,name='editHistoBefundForm'),
    url(r'^anzeigeHistologiebefunde_admin/deleteToggleHistologiebefund/(?P<histo_ID>[\d\-H]+)$', HistoMethods.toggleHisto, name='toggleHisto'),

)


import collections
import itertools
import os
import re
import random
from glob import glob

from .utils import *

from onmt.utils.logging import logger

RE_SHARD = re.compile(r'([0-9]*)\.([a-z]*)(\.gz)?')

def infinite_iterator(iterator_factory):
    while True:
        yield from iterator_factory()

class TaskEpoch():
    def __init__(self, data_config, task):
        self.data_config = data_config
        self.task = task
        self.indices = set()
        self.files = collections.defaultdict(list)
        self.compressed = False
        self.epoch = 0
        # share_inputs causes this task to use another one's data
        data_task = self.data_config['tasks'][task].get('share_inputs', task)
        self.taskdir = os.path.join(
            self.data_config['meta']['shard']['rootdir'],
            'shards', data_task)
        self.task_type = self.data_config['tasks'][task]['type']
        if self.task_type == 'para':
            self.sides = ('src', 'tgt')
        elif self.task_type == 'mono':
            self.sides = ('mono',)
        else:
            raise Exception('Unrecognized task type "{}"'.format(
                self.task_type))
        # reverse causes roles of src and tgt data to be reversed
        # useful for backtranslation
        # (note that meta src_lang and trg_lang are not modified)
        if self.data_config['meta']['train'].get('reverse', False):
            self.sides = self.sides[::-1]
        self._find_shards()
        logger.info('Shard task "{}" from "{}"'.format(self.task,
                                                       self.taskdir))

    def _find_shards(self):
        for filename in os.listdir(self.taskdir):
            m = RE_SHARD.match(filename)
            if not m:
                continue
            index, suffix, ext = m.groups()
            self.indices.add(index)
            path = os.path.join(self.taskdir, filename)
            self.files[(suffix, index)] = path
            if ext == '.gz':
                self.compressed = True
            elif self.compressed:
                raise Exception('Cannot mix compressed and uncompressed')
        for side in self.sides:
            for index in self.indices:
                if not (side, index) in self.files:
                    raise Exception('Missing shard: {} {}, {}'.format(
                        self.task, side, index))

    def yield_epoch(self):
        self.epoch += 1
        all_shards = []
        for index in self.indices:
            all_shards.append([self.files[(side, index)]
                               for side in self.sides])
        random.shuffle(all_shards)
        yield from all_shards

def debug(stream, prefix='debug'):
    for item in stream:
        print('{}: {}'.format(prefix, item))
        yield item

class ShardIterator():
    def __init__(self, task, files, transforms):
        self.task = task
        self.files = files
        self.transforms = transforms

    def tokenize(self, stream):
        for line in stream:
            yield tuple(line.rstrip('\n').split())

    def transpose(self, streams):
        tpls = list(zip(*streams))
        return tpls

    def transform(self, stream, is_train):
        for tpl in stream:
            for transform in self.transforms:
                tpl = transform.apply(tpl, self.task, is_train)
            if tpl is None:
                # the last transform can filter by returning None
                if not is_train:
                    raise Exception('Cannot filter validation set')
                continue
            yield tpl

    def add_index(self, stream):
        for i, tpl in enumerate(stream):
            yield tpl + (i,)

class TrainShardIterator(ShardIterator):
    def __call__(self, is_train=True):
        fobjs = [open(path, 'r') for path in self.files]
        tokenized = [self.tokenize(stream) for stream in fobjs]
        transposed = self.transpose(tokenized)
        if is_train:
            random.shuffle(transposed)
        for fobj in fobjs:
            fobj.close()
        # transposed = debug(transposed, 'transposed')
        transformed = self.transform(transposed, is_train)
        # transformed = debug(transformed, 'transformed')
        indexed = self.add_index(transformed)
        yield from indexed

class TranslateShardIterator(ShardIterator):
    def __call__(self, is_train=False):
        assert not is_train
        decoded = [self.decode(stream) for stream in self.files]
        tokenized = [self.tokenize(stream) for stream in decoded]
        transposed = self.transpose(tokenized)
        transformed = self.transform(transposed, is_train)
        # transformed = debug(transformed, 'transformed')
        indexed = self.add_index(transformed)
        yield from indexed

    def decode(self, stream):
        for bstr in stream:
            yield bstr.decode("utf-8")

def yield_infinite(task_epoch, task, transforms, is_train):
    for tpl in infinite_iterator(task_epoch.yield_epoch):
        si = TrainShardIterator(task, tpl, transforms)
        yield from si(is_train=is_train)

def yield_once(task_epoch, task, transforms, is_train):
    for tpl in task_epoch.yield_epoch():
        si = TrainShardIterator(task, tpl, transforms)
        yield from si(is_train=is_train)

def yield_translate(files, task, transforms):
    for tpl in files:
        si = TranslateShardIterator(task, tpl, transforms)
        yield from si(is_train=False)

def yield_debug(files, task, transforms, is_train):
    si = TrainShardIterator(task, files, transforms)
    yield from si(is_train=is_train)

class TransformReader():
    def __init__(self, task, transforms):
        self.task = task
        self.transforms = transforms

    def read(self, src_file, side, _dir=None):
        if side != 'src':
            # TODO: make a hacky thing that buffers the joint data
            # and provides access to src and tgt separately via
            # two objects having a read method
            raise Exception("dynamicdata doesn't support tgt")
        files = [(src_file,)]
        stream = yield_translate(files, self.task, self.transforms)
        for (src, idx) in stream:
            yield {'src': src, 'indices': idx}

class MixingWeightSchedule():
    def __init__(self, data_config, keys):
        self.keys = keys
        self.schedule_steps = self._list(
            data_config['meta']['train'].get('mixing_weight_schedule', []))
        self.schedule_steps.append(None)
        self.mixing_weights = {
            key: self._list(data_config['tasks'][key]['weight'],
                            len(self.schedule_steps))
            for key in keys}
        for key in keys:
            if len(self.mixing_weights[key]) != len(self.schedule_steps):
                raise Exception('task "{}" has {} mixing weights,'
                                'expecting {}'.format(
                                key, len(self.mixing_weights[key]),
                                len(self.schedule_steps)))
        self.next_threshold = 0

    def _list(self, val, repeat=None):
        if isinstance(val, int):
            if repeat:
                return [val] * repeat
            else:
                return [val]
        return list(val)

    def __call__(self, i):
        if self.next_threshold is None:
            # no adjustments left
            return None
        if i < self.next_threshold:
            # no adjustment yet
            return None
        new_weights = None
        while self.next_threshold is not None and self.next_threshold <= i:
            self.next_threshold = self.schedule_steps.pop(0)
            new_weights = []
            for key in self.keys:
                new_weights.append(self.mixing_weights[key].pop(0))
        return new_weights

    def min_bucket_size(self):
        sums = []
        for tpl in zip(*self.mixing_weights.values()):
            sums.append(sum(tpl))
        return max(sums)

class TaskMixer():
    def __init__(self, data_config, task_streams, bucket_size=2048):
        self.data_config = data_config
        self.task_streams = task_streams
        self.keys = sorted(self.task_streams.keys())

        self.schedule = MixingWeightSchedule(data_config, self.keys)
        self.current_weights = None
        min_bucket_size = self.schedule.min_bucket_size()
        if bucket_size < min_bucket_size:
            bucket_size = min_bucket_size
            logger.info('increased bucket_size to {}'.format(bucket_size))
        self.bucket_size = bucket_size

    def __call__(self):
        self.maybe_adjust_mix(0)
        mixed = self.mix()
        bucketed = self.bucket(mixed)
        yield from bucketed

    def mix(self):
        # using this while-try-next construction in order to allow
        # self.mixed to be replaced by mix weight schedule while looping
        while True:
            try:
                yield next(self.mixed)
            except StopIteration:
                break

    def bucket(self, stream):
        stream = iter(stream)
        while True:
            bucket = list(itertools.islice(stream, self.bucket_size))
            if len(bucket) == 0:
                break
            yield bucket

    def maybe_adjust_mix(self, i):
        new_weights = self.schedule(i)
        if new_weights is not None:
            self.current_weights = new_weights
            logger.info('*** mb %s set weights to %s',
                        i, list(zip(self.keys, self.current_weights)))
        self.mixed = weighted_roundrobin(
            [self.task_streams[key] for key in self.keys],
            self.current_weights)

def build_mixer(data_config, transforms, is_train=True, bucket_size=1):
    split = 'train' if is_train else 'valid'
    task_epochs = {}
    task_streams = {}
    for task in data_config['tasks']:
        if data_config['tasks'][task]['split'] != split:
            continue
        task_epoch = TaskEpoch(data_config, task)
        if is_train:
            stream = yield_infinite(task_epoch,
                                    task,
                                    transforms[task],
                                    is_train=is_train)
        else:
            # yield validation data only once
            stream = yield_once(task_epoch,
                                task,
                                transforms[task],
                                is_train=is_train)
        task_epochs[task] = task_epoch
        task_streams[task] = stream
    mixer = TaskMixer(data_config, task_streams, bucket_size=bucket_size)
    return mixer, task_epochs


import torch
from torch import nn
from torch import optim
from copy import deepcopy

class BaseModel(nn.Module):
    def __init__(self,sequential=None):
        super(BaseModel,self).__init__()
        self.sequential = sequential

    def forward(self, x):
        if self.sequential:
            out = self.sequential(x)
            return out
        return None

    def predict(self,x_test):
        self.eval()
        y_pred = self(x_test)
        return y_pred

    def predict_dataloader(self,loader):
        self.eval()
        total_loss = 0.0
        acc = 0.0
        for data in test_loader:
            img, y_train = data
            #img = img.view(img.size(0), -1)
            y_pred = self(img)

            loss = self.loss_fn(y_pred, y_train)
            total_loss += loss.data.item()

            _, pred = torch.max(y_pred, 1)
            num_correct = (pred == y_train).sum()
            acc += num_correct.data.item()

        print(total_loss/len(loader),acc/32/len(loader))

    def save(self,path):
        torch.save(self.state_dict(), path)

    def compile(self,optimizer,loss,metrics=None):

        self.optimizer = optimizer(self.parameters(), lr=1e-4)
        self.loss_fn = loss()
        if metrics is not None:
            self.metrics = metrics()

    def fit_dataloader(self,loader):
        num_epochs = 100
        for epoch in range(num_epochs):

            batch_loss = 0.0
            batch_acc = 0.0
            step = 300
            for i,data in enumerate(loader):
                img,y_train = data
                #print('input size:',img.size())
                y_pred = self(img)
                #print(y_pred.size())
                #y_pred = self(img.view(img.size()[0],-1))

                #计算当前批次的准确率（max:返回每列最大的，第二个返回值是对应的下标)
                _, pred = torch.max(y_pred, 1)
                num_correct = (pred == y_train).sum()
                batch_acc += num_correct.data.item()

                # 反向传播
                self.optimizer.zero_grad()
                loss = self.loss_fn(y_pred, y_train)

                #计算当前批次的损失
                batch_loss += loss.data.item()

                loss.backward()
                self.optimizer.step()

                if (i+1) % step == 0:
                    print('Epoch[{}/{}],batch:{}, avg loss: {:.6f},train acc:{:.6f}'
                          .format(epoch + 1, num_epochs,i+1, batch_loss/step,batch_acc/(step*32)))
                    batch_loss = 0.0
                    batch_acc = 0.0

    def fit(self, x_train, y_train):
        # 开始训练
        num_epochs = 1000
        for epoch in range(num_epochs):
            y_pred = self(x_train)
            # 这里顺序不能反，前者是预测值out，后者是target

            # backward
            self.optimizer.zero_grad()
            loss = self.loss_fn(y_pred, y_train)
            loss.backward()
            self.optimizer.step()

            if (epoch + 1) % 20 == 0:
                print('Epoch[{}/{}], loss: {:.6f}'
                      .format(epoch + 1, num_epochs, loss.data.item()))

# 线性模型
class LinearRegression(BaseModel):
    def __init__(self):
        super(LinearRegression, self).__init__()
        self.linear = nn.Linear(1, 1)  # input and output is 1 dimension

    def forward(self, x):
        out = self.linear(x)
        return out

# 定义 Logistic Regression 模型
class Logstic_Regression(BaseModel):
    def __init__(self, in_dim, n_class):
        super(Logstic_Regression, self).__init__()
        self.logstic = nn.Linear(in_dim, n_class)

    def forward(self, x):
        out = self.logstic(x)
        return out

class MLP(BaseModel):
    def __init__(self,n_input,n_hidden_1,n_hidden_2,n_output):
        super(MLP,self).__init__()
        self.layer1 = nn.Linear(n_input,n_hidden_1)
        self.layer2 = nn.Linear(n_hidden_1,n_hidden_2)
        self.layer3 = nn.Linear(n_hidden_2,n_output)

    def forward(self, x):
        out =  self.layer1(x)
        out = self.layer2(out)
        out = self.layer3(out)
        return out

# 定义 Convolution Network 模型
class Cnn(BaseModel):
    def __init__(self, in_dim, n_class):
        super(Cnn, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(in_dim, 6, 3, stride=1, padding=1),
            nn.ReLU(True),
            nn.MaxPool2d(2, 2),
            nn.Conv2d(6, 16, 5, stride=1, padding=0),
            nn.ReLU(True), nn.MaxPool2d(2, 2))

        self.fc = nn.Sequential(
            nn.Linear(400, 120), nn.Linear(120, 84), nn.Linear(84, n_class))

    def forward(self, x):
        out = self.conv(x)
        out = out.view(out.size(0), -1)
        out = self.fc(out)
        return out

# 定义 Recurrent Network - LSTM模型
class Lstm(BaseModel):
    def __init__(self, in_dim, hidden_dim, n_layer, n_class):
        super(Lstm, self).__init__()
        self.n_layer = n_layer
        self.hidden_dim = hidden_dim
        self.lstm = nn.LSTM(in_dim, hidden_dim, n_layer, batch_first=True)
        self.classifier = nn.Linear(28*hidden_dim, n_class)

    def forward(self, x):
        out, _ = self.lstm(x)
        #print(type(out),out.size())
        out = out[:, -1, :] #这里直接把（32，28，128） => (32,128)，直接扔掉？
        #out = out.view(32,-1) view操作竟然不行
        #print(out.size())
        out = self.classifier(out)
        return out

import numpy as np
def test_linear2():
    seq = nn.Sequential(
        nn.Linear(1,1)
    )
    model = BaseModel(seq)
    model.compile(optimizer=optim.SGD, loss=nn.MSELoss)
    x_train = np.array([[3.3], [4.4], [5.5], [6.71], [6.93], [4.168],
                        [9.779], [6.182], [7.59], [2.167], [7.042],
                        [10.791], [5.313], [7.997], [3.1]])

    y_train = np.array([[1.7], [2.76], [2.09], [3.19], [1.694], [1.573],
                        [3.366], [2.596], [2.53], [1.221], [2.827],
                        [3.465], [1.65], [2.904], [1.3]])

    model.fit(torch.Tensor(x_train), torch.Tensor(y_train))
    y_pred = model.predict(torch.Tensor(x_train))

    data = y_pred.data

    import matplotlib.pyplot as plt
    plt.plot(x_train, y_pred.data.numpy(), label='Fitting Line')
    plt.show()

def test_linear():
    model = LinearRegression()
    model.compile(optimizer=optim.SGD,loss=nn.MSELoss)

    x_train = np.array([[3.3], [4.4], [5.5], [6.71], [6.93], [4.168],
                        [9.779], [6.182], [7.59], [2.167], [7.042],
                        [10.791], [5.313], [7.997], [3.1]])

    y_train = np.array([[1.7], [2.76], [2.09], [3.19], [1.694], [1.573],
                        [3.366], [2.596], [2.53], [1.221], [2.827],
                        [3.465], [1.65], [2.904], [1.3]])

    model.fit(torch.Tensor(x_train),torch.Tensor(y_train))
    y_pred = model.predict(torch.Tensor(x_train))

    data = y_pred.data

    import matplotlib.pyplot as plt
    plt.plot(x_train, y_pred.data.numpy(), label='Fitting Line')
    plt.show()

    model.save('./mymodel.pth')

def test_logistic(loader):
    model = Logstic_Regression(28 * 28, 10)  # 图片大小是28x28
    model.compile(optimizer=optim.SGD,loss=nn.CrossEntropyLoss)
    model.fit_dataloader(loader)

def test_MLP(loader,test_loader):
    model = MLP(28*28,300,100,10)
    model.compile(optimizer=optim.SGD,loss=nn.CrossEntropyLoss)
    model.fit_dataloader(loader)
    model.predict_dataloader(test_loader)

def test_cnn(loader,test_loader):
    model = Cnn(1,10)
    model.compile(optimizer=optim.SGD, loss=nn.CrossEntropyLoss)
    model.fit_dataloader(loader)
    model.predict_dataloader(test_loader)

def test_lstm(loader,test_loader):
    model = Lstm(28, 128, 2, 10)  # 图片大小是28x28
    model.compile(optimizer=optim.Adam, loss=nn.CrossEntropyLoss)
    model.fit_dataloader(loader)
    model.predict_dataloader(test_loader)

class LstmTrans(object):
    def __call__(self, pic):
        out = pic.squeeze(0)# 1x28x28 =>28x28,把channel压缩掉
        return out

    def __repr__(self):
        return self.__class__.__name__ + '()'

class Trans(object):
    def __call__(self, pic):
        #print('pic:',pic.size())
        out = pic.view(-1)
        #print('out',out.size())
        return out

    def __repr__(self):
        return self.__class__.__name__ + '()'

if __name__ == '__main__':
    from torchvision import datasets,transforms
    from torch.utils.data import DataLoader

    composed = transforms.Compose([transforms.ToTensor(),
                                  LstmTrans()])

    train_dataset = datasets.MNIST(
        root='./data', train=True, transform=composed, download=True)

    test_dataset = datasets.MNIST(
        root='./data', train=False, transform=composed)

    train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
    test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)

    #test_linear()
    #test_MLP(train_loader,test_loader)
    #test_cnn(train_loader,test_loader)
    test_lstm(train_loader,test_loader)


import cv2
import numpy as np

#Basic image processing methods

#Method for filling holes in connected components of the mask
#In other words, brings all the connected components to simply connected

def fill_holes (img):
    (h, w) = img.shape

    before_area = img.sum ()

    img_enlarged = np.zeros ((h + 2, w + 2), np.uint8)
    img_enlarged [1:h+1, 1:w+1] = img

    img_enl_not = cv2.bitwise_not (img_enlarged)
    th, im_th = cv2.threshold (img_enl_not, 220, 255, cv2.THRESH_BINARY_INV);

    im_floodfill = im_th.copy()

    h, w = im_th.shape[:2]
    mask = np.zeros((h+2, w+2), np.uint8)

    cv2.floodFill(im_floodfill, mask, (0,0), 255);
    im_floodfill_inv = cv2.bitwise_not(im_floodfill)
    im_out = im_th | im_floodfill_inv

    result = im_out [1:h-1, 1:w-1]

    return result

#Method for bringing 3-channel image to RG-chromaticity color space
#Essentially it is a kind of normalization such that the absolute
#values of the intensity are neglected; the components ratios are not

def to_RG_chromaticity (img):
    (h, w, d) = img.shape

    norm = np.zeros ((h, w), np.float)
    norm = img [:, :, 0].astype ('float') +\
           img [:, :, 1].astype ('float') +\
           img [:, :, 2].astype ('float')

    norm [norm == 0] = 5

    turned = np.zeros (img.shape, np.uint8)
    turned [:, :, 0] = ((img [:, :, 0].astype ('float')) / norm * 255).astype ('uint8')
    turned [:, :, 1] = ((img [:, :, 1].astype ('float')) / norm * 255).astype ('uint8')
    turned [:, :, 2] = ((img [:, :, 2].astype ('float')) / norm * 255).astype ('uint8')

    return turned

#Method for finding the bounding box of the connected component having the biggest value
#of the given criterion, i.e. height, width, area.
#Not implemented yet.

#def find_bounding_box (mask, criterion):
#    result = np.array (mask)
#    output = cv2.connectedComponentsWithStats (mask, 8, cv2.CV_32S)
#    labels_num = output      [0]
#    labels     = output      [1]
#    stats      = output      [2]
#    sz         = stats.shape [0]
#
#    max_crit_val = 0
#    max_label    = 0
#
#    for label_num in range (1, sz - 1):
#        if (stats [label_num, cv2.CC_STAT_AREA] > max_w):
#            max_w = stats [label_num, cv2.CC_STAT_AREA]
#            max_label = label_num
#
#    top    = stats [max_label, cv2.CC_STAT_TOP]
#    left   = stats [max_label, cv2.CC_STAT_LEFT]
#    width  = stats [max_label, cv2.CC_STAT_WIDTH]
#    height = stats [max_label, cv2.CC_STAT_HEIGHT]
#
#    return (left, top), (left + width, top + height)

def find_max_bounding_box (mask):
    result = np.array (mask)
    output = cv2.connectedComponentsWithStats (mask, 8, cv2.CV_32S)
    labels_num = output      [0]
    labels     = output      [1]
    stats      = output      [2]
    sz         = stats.shape [0]

    max_area  = 0
    max_label = 0

    for label_num in range (1, sz):
        if (stats [label_num, cv2.CC_STAT_AREA] > max_area):
            max_area = stats [label_num, cv2.CC_STAT_AREA]
            max_label = label_num

    top    = stats [max_label, cv2.CC_STAT_TOP]
    left   = stats [max_label, cv2.CC_STAT_LEFT]
    width  = stats [max_label, cv2.CC_STAT_WIDTH]
    height = stats [max_label, cv2.CC_STAT_HEIGHT]

    return (left, top), (left + width, top + height)


# test our installation of h5py

import sys
import os
import numpy as np
import h5py

fname = 'run_test_helloworld.h5'
f = h5py.File(fname,'w')
f['data'] = 'hello world!'
f['data2'] = np.zeros((3,5), np.int32)
del f
h5 = h5py.File(fname,'r')
assert h5['data'].value == 'hello world!'
assert h5['data2'].shape[0]==3
assert h5['data2'].shape[1]==5
assert np.sum(h5['data2'][:])==0

del h5
os.unlink(fname)

from mpi4py import MPI
sys.stdout.write("mpi version: %r\n" % (MPI.get_vendor(),))


import numpy as np
import matplotlib,demo,cv2,time
matplotlib.rcParams['figure.figsize'] = (20.0, 10.0)
from matplotlib import pyplot as plt

cams = demo.get_cameras()
print(cams)

while True:
    rL,L = cams[1].read()
    rR,R = cams[2].read()

    L = cv2.flip(cv2.pyrDown(cv2.cvtColor(L,cv2.COLOR_BGR2GRAY)),0)
    R = cv2.flip(cv2.pyrDown(cv2.cvtColor(R,cv2.COLOR_BGR2GRAY)),0)
    # window_size = 7
    # min_disp = 16
    # num_disp = 16*2
    # stereo = cv2.StereoSGBM(minDisparity = min_disp,
    #     numDisparities = num_disp,
    #     SADWindowSize = window_size,
    #     uniquenessRatio = 1,
    #     speckleWindowSize = 100,
    #     speckleRange = 32,
    #     disp12MaxDiff = 1,
    #     P1 = 8*3*window_size**2,
    #     P2 = 32*3*window_size**2,
    #     fullDP = False
    # )

    window_size = 5
    min_disp = 16
    num_disp = 16*3
    stereo = cv2.StereoSGBM(minDisparity = min_disp,numDisparities = num_disp,SADWindowSize = window_size,
                            uniquenessRatio = 3,speckleWindowSize = 100,speckleRange = 32,disp12MaxDiff = 1,
        P1 = 8*3*window_size**2,
        P2 = 32*3*window_size**2,
        fullDP = False
    )
    # disp = stereo.compute(L,R)

    disp = stereo.compute(L,R)
    # norm = cv2.normalize(disp, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX)
    # eq = cv2.equalizeHist(disp)
    # out = np.concatenate((L,R,disp),axis=1)
    out = disp
    # plt.axis('off')
    # plt.subplot(1,3,1)
    # plt.imshow(L,cmap='gray')
    # plt.subplot(1,3,2)
    # plt.imshow(R,cmap='gray')
    # plt.subplot(1,3,3)
    # plt.imshow(disp,cmap='gray')
    # plt.show()
    # raw_input()
    # plt.clf()

    cv2.imshow('test', out)
    cv2.waitKey(300)
    if cv2.waitKey(33) == ord('a'):
        for c in cams:
            c.release()
            cv2.destroyAllWindows()
        break


import io
import json
from datetime import date, datetime, timedelta, timezone

import cv2
import numpy as np
from discord import Embed, File, Game
from discord.ext import commands as c
from PIL import Image, ImageDraw, ImageFont

from module import db, item

with open('../assets/login_bonus.json', encoding='utf-8') as f:
    df = json.load(f)

class Cog(c.Cog):
    def __init__(self, bot):
        self.bot = bot

    @c.Cog.listener()
    async def on_command(self, ctx):
        def overlay(cv_background_image, cv_overlay_image, point,):
            """
            [summary]
                OpenCV形式の画像に指定画像を重ねる
            Parameters
            ----------
            cv_background_image : [OpenCV Image]
            cv_overlay_image : [OpenCV Image]
            point : [(x, y)]
            Returns : [OpenCV Image]
            """
            overlay_height, overlay_width = cv_overlay_image.shape[:2]

            # OpenCV形式の画像をPIL形式に変換(α値含む)
            # 背景画像
            cv_rgb_bg_image = cv2.cvtColor(cv_background_image, cv2.COLOR_BGR2RGB)
            pil_rgb_bg_image = Image.fromarray(cv_rgb_bg_image)
            pil_rgba_bg_image = pil_rgb_bg_image.convert('RGBA')
            # オーバーレイ画像
            cv_rgb_ol_image = cv2.cvtColor(cv_overlay_image, cv2.COLOR_BGRA2RGBA)
            pil_rgb_ol_image = Image.fromarray(cv_rgb_ol_image)
            pil_rgba_ol_image = pil_rgb_ol_image.convert('RGBA')

            # composite()は同サイズ画像同士が必須のため、合成用画像を用意
            pil_rgba_bg_temp = Image.new('RGBA', pil_rgba_bg_image.size,
                                            (255, 255, 255, 0))
            # 座標を指定し重ね合わせる
            pil_rgba_bg_temp.paste(pil_rgba_ol_image, point, pil_rgba_ol_image)
            result_image = Image.alpha_composite(pil_rgba_bg_image, pil_rgba_bg_temp)

            # OpenCV形式画像へ変換
            cv_bgr_result_image = cv2.cvtColor(
                np.asarray(result_image), cv2.COLOR_RGBA2BGRA)

            return cv_bgr_result_image
        login_timezone = timezone(timedelta(hours=+0), 'UTC')
        # timezone = timezone(timedelta(hours=+9), 'JST')
        now = datetime.now(login_timezone)
        login_data = db.player.login.get(ctx.author.id)
        login_datetime = datetime.fromtimestamp(login_data[1],login_timezone)
        next_login_datetime=datetime(login_datetime.year,login_datetime.month,login_datetime.day,tzinfo=login_timezone)+timedelta(1)
        #if now.timestamp()-login_data[1] >= 86400:  # 最終ログインから24時間
        login_const = 15
        if next_login_datetime <= now:# or True:
            count=login_data[0]%login_const+1
            image = cv2.imread("../assets/back.jpg")
            for y in range(3):
                for x in range(5):
                    cv_overlay_image = cv2.imread(df[x+5*y]["img"], cv2.IMREAD_UNCHANGED)  # IMREAD_UNCHANGEDを指定しα込みで読み込む
                    cv_overlay_image = cv2.resize(cv_overlay_image, (140, 140))
                    image = overlay(image, cv_overlay_image, (215+255*x, 270+255*y))
                    if count>x+5*y:
                        cv_overlay_image = cv2.imread("../assets/received.png", cv2.IMREAD_UNCHANGED)  # IMREAD_UNCHANGEDを指定しα込みで読み込む
                        cv_overlay_image = cv2.resize(cv_overlay_image, (200, 200))
                        image = overlay(image, cv_overlay_image, (188+254*x, 240+255*y))
                    img_pil = Image.fromarray(image)
                    draw = ImageDraw.Draw(img_pil)
                    draw.text((350+255*x, 400+255*y), str(df[x+5*y]["reward"]), font=ImageFont.truetype('../assets/HGRPP1.TTC', 64), fill = (256-150*(count>x+5*y),)*3+(0,))
                    image = np.array(img_pil)
            _,img=cv2.imencode(".jpg",image,[int(cv2.IMWRITE_JPEG_QUALITY), 100])
            db.player.login.do(ctx.author.id, now.timestamp())
            f = File(fp=io.BytesIO(img),filename="login_image.jpg")
            login_bonus = df[login_data[0]%login_const]
            if login_bonus["item_id"]=="FG":
                db.player.money.add(ctx.author.id,login_bonus["reward"])
                e = Embed(title="【ログインボーナス】",description="{0}は{1}FG手に入れた。".format(ctx.author.mention,login_bonus["reward"]))
            else:
                item.obtain_an_item(ctx.author.id, login_bonus["item_id"], login_bonus["reward"])
                e = Embed(title="【ログインボーナス】",description="{0}は{1}を{2}個手に入れた。".format(ctx.author.mention,item.items.get(str(login_bonus["item_id"]),{"name": "unknown"})["name"],login_bonus["reward"]))
            e.set_image(url="attachment://login_image.jpg")
            await ctx.send(file=f, embed=e)

    @c.command(pass_context=True, description='仮実装のloginコマンド。実行はしないほうがいいかもな')
    async def login(self, ctx):
        login_timezone = timezone(timedelta(hours=+0), 'UTC')
        # login_timezone = timezone(timedelta(hours=+9), 'JST')
        now = datetime.now(login_timezone)
        login_data = db.player.login.get(ctx.author.id)
        login_datetime = datetime.fromtimestamp(login_data[1], login_timezone)
        next_login_datetime=datetime(login_datetime.year,login_datetime.month,login_datetime.day,tzinfo=login_timezone)+timedelta(1)
        #if now.timestamp()-login_data[1] >= 86400:  # 最終ログインから24時間
        if next_login_datetime > now:
            await ctx.send("あなたはすでにログインしています\n最終ログイン："+login_datetime.isoformat(sep=' ')+"\n次回ログイン可能："+next_login_datetime.isoformat(sep=' '))

def setup(bot):
    bot.add_cog(Cog(bot))


import json
import os
import copy
import math

#将数字转化为文字，取消小数点和无用末尾0
def better_float_to_text(x):
    if isinstance(x,float) and int(x)==x:
        return str(int(x))
    else:
        return str(x)

# 查询数据范围
def findtb(source, start, end, tb, brace=0):
    i = j = 0
    tb[0] = start
    tb[1] = end
    for i in range(start, end):
        if source[i] == '{':
            brace += 1
            if brace > 0:
                tb[0] = i + 1
                for j in range(i + 1, tb[1]):
                    if source[j] == '{':
                        brace += 1
                    elif source[j] == '}':
                        brace -= 1
                        if brace == 0:
                            tb[1] = j - 1
                            return True
        elif source[i] == '}':
            return False
    return False

def findabilityname(source, tb):
    i = source.rfind('\"', 0, tb[0])
    j = source.rfind('\"', 0, i - 1)
    return source[j + 1:i]

# 寻找属性（查询源字符串，数据存储位置，上下限，属性序数，是否为存在属性）
def findabilitypro(source, data, tb, pro, bool=False):
    if bool:
        i = source.find(pro[1], tb[0], tb[1])
        if i != -1:
            data[pro[1]] = {"1": 1}
    else:
        i = source.find('\"' + pro[1] + '\"', tb[0], tb[1])
        if i != -1:
            j = source.find('\"', i + 1, tb[1])
            j = source.find('\"', j + 1, tb[1])
            k = source.find('\"', j + 1, tb[1])
            if k > j + 1:
                splitit = source[j + 1:k].split(' ')
                data[pro[1]] = {}
                bool = True
                for j in range(len(splitit)):
                    data[pro[1]][str(j + 1)] = float(splitit[j])
                    bool = bool and splitit[0] == splitit[j]
                if bool:
                    data[pro[1]] = {"1": data[pro[1]]["1"]}
    return

def findabilityspecial(source, data, tb):
    i = source.find("AbilitySpecial", tb[0], tb[1])
    if i == -1:
        return
    else:
        k = source.find("{", i, tb[1])
        while True:
            j = source.find("{", k + 1, tb[1])
            k = source.find("}", k + 1, tb[1])
            if j < k and j != -1:
                r = [0, 0, 0, 0]
                r[0] = source.find('\"', j, k) + 1
                r[0] = source.find('\"', r[0], k) + 1
                r[0] = source.find('\"', r[0], k) + 1
                r[0] = source.find('\"', r[0], k) + 1
                r[0] = source.find('\"', r[0], k) + 1
                r[1] = source.find('\"', r[0], k)
                r[2] = source.find('\"', r[1] + 1, k) + 1
                r[3] = source.find('\"', r[2], k)
                splitit = source[r[2]:r[3]].split(' ')
                if splitit[0] != '':
                    data[source[r[0]:r[1]]] = {}
                    bool = True
                    for l in range(len(splitit)):
                        data[source[r[0]:r[1]]][str(l + 1)] = float(splitit[l])
                        bool = bool and splitit[0] == splitit[l]
                    if bool:
                        data[source[r[0]:r[1]]] = {"1": data[source[r[0]:r[1]]]["1"]}
            else:
                return

def get_hero_data_from_txt(base_txt, address):
    this_file = open("E:/Steam/steamapps/common/dota 2 beta/game/dota/scripts/npc/npc_abilities.txt", mode="r")
    this_string = this_file.read()
    tb = [0, 0]
    findtb(this_string, 0, len(this_string), tb, -1)
    while (True):
        if (findtb(this_string, tb[1] + 2, len(this_string), tb, 0)):
            name = findabilityname(this_string, tb)
            base_txt[name] = {}
            for i in abilitypro_num:
                findabilitypro(this_string, base_txt[name], tb, i, False)
            for i in abilitypro_bool:
                findabilitypro(this_string, base_txt[name], tb, i, True)
            findabilityspecial(this_string, base_txt[name], tb)
        else:
            break

def get_source_to_data(all_json, upgrade_json, version):
    for ijk in all_json['技能']:
        unit_dic = copy.deepcopy(all_json['技能'][ijk])
        unit_dic["分类"] = "技能"
        unit_dic["版本"] = version
        unit_dic["应用"] = 1
        if unit_dic["技能排序"] == "":
            if unit_dic["默认按键"] == "Q":
                unit_dic["技能排序"] = "d"
            elif unit_dic["默认按键"] == "W":
                unit_dic["技能排序"] = "e"
            elif unit_dic["默认按键"] == "E":
                unit_dic["技能排序"] = "f"
            elif unit_dic["默认按键"] == "D":
                unit_dic["技能排序"] = "g"
            elif unit_dic["默认按键"] == "F":
                unit_dic["技能排序"] = "h"
            elif unit_dic["默认按键"] == "R":
                unit_dic["技能排序"] = "i"
            elif unit_dic["默认按键"] == "T":
                unit_dic["技能排序"] = "j"
            else:
                unit_dic["技能排序"] = "z"
        temp1 = copy.deepcopy(all_json['技能源'][unit_dic["数据来源"]])
        if unit_dic["次级分类"] == "天赋技能":
            unit_dic["图片"] = all_json["英雄"][unit_dic["技能归属"]]["图片"]
            unit_dic["迷你图片"] = all_json["英雄"][unit_dic["技能归属"]]["迷你图片"]
        elif unit_dic["次级分类"] == "物品技能":
            if unit_dic["技能归属"] in all_json["物品"]:
                unit_dic["图片"] = all_json["物品"][unit_dic["技能归属"]]["图片"]
                unit_dic["迷你图片"] = all_json["物品"][unit_dic["技能归属"]]["迷你图片"]
            else:
                unit_dic["图片"] = "items_" + temp1["代码"] + ".png"
                unit_dic["迷你图片"] = "items_" + temp1["代码"] + ".png"
        else:
            unit_dic["图片"] = "spellicons " + temp1["代码"] + ".png"
            unit_dic["迷你图片"] = "spellicons " + temp1["代码"] + ".png"
        for i in temp1:
            if i in ability_trait_level[0]:
                unit_dic[i] = temp1[i]
            elif i in ability_trait_level[1]:
                unit_dic[i] = {}
                j = 0
                while True:
                    j += 1
                    if str(j) in temp1[i]:
                        unit_dic[i][str(j)] = group_source(temp1[i][str(j)])
                    else:
                        break
            elif i in ability_trait_level[2]:
                unit_dic[i] = {}
                j = 0
                while True:
                    j += 1
                    if str(j) in temp1[i]:
                        unit_dic[i][str(j)] = {}
                        k = 0
                        while True:
                            k += 1
                            if str(k) in temp1[i][str(j)]:
                                unit_dic[i][str(j)][str(k)] = group_source(temp1[i][str(j)][str(k)])
                            else:
                                break
                        if '名称' in temp1[i][str(j)]:
                            unit_dic[i][str(j)]['名称'] = temp1[i][str(j)]['名称']
                    else:
                        break
            elif i == "升级":
                if "A杖" in temp1[i] and len(temp1[i]["A杖"]) > 0 or "技能" in temp1[i] and len(temp1[i]["技能"]) > 0 or "混合" in temp1[i] and len(temp1[i]["混合"]) > 0:
                    upgrade_json[unit_dic["页面名"]] = copy.deepcopy(temp1[i])
            elif i == "页面名":
                continue
            else:
                unit_dic[i] = group_source(temp1[i])
        unit_dic["技能升级信息"]={}
        all_json["技能"][unit_dic["页面名"]] = copy.deepcopy(unit_dic)

def group_source(a):
    temp = {"1": {}}
    for i in a:
        if i == "名称" or i == "后缀":
            temp[i] = a[i]
        else:
            temp["1"][i] = a[i]
    return temp

def input_upgrade(all_json, upgrade_json):
    for i in upgrade_json:
        for j in upgrade_json[i]["A杖"]:
            if upgrade_json[i]["A杖"][j]["目标"]["1"] == "":
                upgrade_json[i]["A杖"][j]["目标"]["1"] = "技能"
            if upgrade_json[i]["A杖"][j]["目标"]["2"] == "":
                upgrade_json[i]["A杖"][j]["目标"]["2"] = i
            if "代码" in upgrade_json[i]["A杖"][j]["值"] and isinstance(upgrade_json[i]["A杖"][j]["值"]["代码"], dict):
                if "1" in upgrade_json[i]["A杖"][j]["值"]["代码"] and upgrade_json[i]["A杖"][j]["值"]["代码"]["1"] == "":
                    upgrade_json[i]["A杖"][j]["值"]["代码"]["1"] = "技能"
                if "2" in upgrade_json[i]["A杖"][j]["值"]["代码"] and upgrade_json[i]["A杖"][j]["值"]["代码"]["2"] == "":
                    upgrade_json[i]["A杖"][j]["值"]["代码"]["2"] = all_json["技能"][i]["代码"]
            k = 1
            temp = all_json[upgrade_json[i]["A杖"][j]["目标"]["1"]]
            while True:
                k += 1
                if str(k) in upgrade_json[i]["A杖"][j]["目标"]:
                    if upgrade_json[i]["A杖"][j]["目标"][str(k)] in temp:
                        temp = temp[upgrade_json[i]["A杖"][j]["目标"][str(k)]]
                    else:
                        temp[upgrade_json[i]["A杖"][j]["目标"][str(k)]] = {}
                        temp = temp[upgrade_json[i]["A杖"][j]["目标"][str(k)]]
                else:
                    break
            if "0" in upgrade_json[i]["A杖"][j]["目标"] and upgrade_json[i]["A杖"][j]["目标"]["0"] == "替换":
                if "2" not in temp:
                    temp["2"] = copy.deepcopy(temp["1"])
                for k in upgrade_json[i]["A杖"][j]["值"]:
                    temp["2"][k] = copy.deepcopy(upgrade_json[i]["A杖"][j]["值"][k])
            else:
                temp["2"] = upgrade_json[i]["A杖"][j]["值"]
        for j in upgrade_json[i]["技能"]:
            if "代码" in upgrade_json[i]["技能"][j]["值"] and isinstance(upgrade_json[i]["技能"][j]["值"]["代码"], dict):
                if "1" in upgrade_json[i]["技能"][j]["值"]["代码"] and upgrade_json[i]["技能"][j]["值"]["代码"]["1"] == "":
                    upgrade_json[i]["技能"][j]["值"]["代码"]["1"] = "技能"
                if "2" in upgrade_json[i]["技能"][j]["值"]["代码"] and upgrade_json[i]["技能"][j]["值"]["代码"]["2"] == "":
                    upgrade_json[i]["技能"][j]["值"]["代码"]["2"] = all_json["技能"][i]["代码"]
            k = 1
            temp = all_json[upgrade_json[i]["技能"][j]["目标"]["1"]]
            while True:
                k += 1
                if str(k) in upgrade_json[i]["技能"][j]["目标"]:
                    if upgrade_json[i]["技能"][j]["目标"][str(k)] in temp:
                        temp = temp[upgrade_json[i]["技能"][j]["目标"][str(k)]]
                    else:
                        temp[upgrade_json[i]["技能"][j]["目标"][str(k)]] = {}
                        temp = temp[upgrade_json[i]["技能"][j]["目标"][str(k)]]
                else:
                    break
            if "0" in upgrade_json[i]["技能"][j]["目标"] and upgrade_json[i]["技能"][j]["目标"]["0"] == "替换":
                if "3" not in temp:
                    temp["3"] = copy.deepcopy(temp["1"])
                for k in upgrade_json[i]["技能"][j]["值"]:
                    temp["3"][k] = copy.deepcopy(upgrade_json[i]["技能"][j]["值"][k])
            else:
                temp["3"] = upgrade_json[i]["技能"][j]["值"]
            temp["3"]["升级来源"] = {"1": {"名称": i}}
            if all_json["技能"][i]["次级分类"] == "天赋技能":
                temp["3"]["升级来源"]["1"]["图片"] = "talent.png"
            else:
                temp["3"]["升级来源"]["1"]["图片"] = all_json["技能"][i]["迷你图片"]
            if upgrade_json[i]["技能"][j]["目标"]["1"]=='技能':
                upgrade_info = all_json['技能'][upgrade_json[i]["技能"][j]["目标"]["2"]]['技能升级信息']
                upbool = True
                for upi in upgrade_info:
                    if upgrade_info[upi]['技能名'] == i:
                        upbool = False
                if upbool:
                    upnum = len(upgrade_info)
                    upgrade_info[str(upnum + 1)] = {'技能名': i}
        for j in upgrade_json[i]["混合"]:
            if "代码" in upgrade_json[i]["混合"][j]["值"]:
                if "1" in upgrade_json[i]["混合"][j]["值"]["代码"] and upgrade_json[i]["混合"][j]["值"]["代码"]["1"] == "":
                    upgrade_json[i]["混合"][j]["值"]["代码"]["1"] = "技能"
                if "2" in upgrade_json[i]["混合"][j]["值"]["代码"] and upgrade_json[i]["混合"][j]["值"]["代码"]["2"] == "":
                    upgrade_json[i]["混合"][j]["值"]["代码"]["2"] = all_json["技能"][i]["代码"]
            k = 1
            temp = all_json[upgrade_json[i]["混合"][j]["目标"]["1"]]
            while True:
                k += 1
                if str(k) in upgrade_json[i]["混合"][j]["目标"]:
                    if upgrade_json[i]["混合"][j]["目标"][str(k)] in temp:
                        temp = temp[upgrade_json[i]["混合"][j]["目标"][str(k)]]
                    else:
                        temp[upgrade_json[i]["混合"][j]["目标"][str(k)]] = {}
                        temp = temp[upgrade_json[i]["混合"][j]["目标"][str(k)]]
                else:
                    break
            if "0" in upgrade_json[i]["混合"][j]["目标"] and upgrade_json[i]["混合"][j]["目标"]["0"] == "替换":
                if "3" not in temp:
                    temp["3"] = copy.deepcopy(temp["1"])
                for k in upgrade_json[i]["混合"][j]["值"]:
                    temp["3"][k] = copy.deepcopy(upgrade_json[i]["混合"][j]["值"][k])
            else:
                temp["3"] = upgrade_json[i]["混合"][j]["值"]
            temp["3"]["升级来源"] = {}
            for k in upgrade_json[i]["混合"][j]["来源技能"]:
                if upgrade_json[i]["混合"][j]["来源技能"][k] == "A杖":
                    temp["3"]["升级来源"][k] = {"名称": "阿哈利姆神杖", "图片": "agha.png"}
                elif upgrade_json[i]["混合"][j]["来源技能"][k] == "本技能":
                    temp["3"]["升级来源"][k] = {"名称": i}
                    if all_json["技能"][i]["次级分类"] == "天赋技能":
                        temp["3"]["升级来源"][k]["图片"] = "talent.png"
                    else:
                        temp["3"]["升级来源"][k]["图片"] = all_json["技能"][i]["迷你图片"]
                else:
                    temp["3"]["升级来源"][k] = {"名称": upgrade_json[i]["混合"][j]["来源技能"][k]}
                    if all_json["技能"][upgrade_json[i]["混合"][j]["来源技能"][k]]["次级分类"] == "天赋技能":
                        temp["3"]["升级来源"][k]["图片"] = "talent.png"
                    else:
                        temp["3"]["升级来源"][k]["图片"] = all_json["技能"][upgrade_json[i]["混合"][j]["来源技能"][k]]["迷你图片"]
            if upgrade_json[i]["技能"][j]["目标"]["1"]=='技能':
                upgrade_info = all_json['技能'][upgrade_json[i]["技能"][j]["目标"]["2"]]['技能升级信息']
                upbool = True
                for upi in upgrade_info:
                    if upgrade_info[upi]['技能名'] == i:
                        upbool = False
                if upbool:
                    upnum = len(upgrade_info)
                    upgrade_info[str(upnum + 1)] = {'技能名': i}
    for i in all_json["技能"]:
        for j in all_json["技能"][i]["效果"]:
            for k in ["2", "3"]:
                if k in all_json["技能"][i]["效果"][j]:
                    if '名称' in all_json["技能"][i]["效果"][j][k]:
                        all_json["技能"][i]["效果"][j]['名称'] = all_json["技能"][i]["效果"][j][k]['名称']
                        all_json["技能"][i]["效果"][j][k].pop('名称')
                    l = 0
                    while True:
                        l += 1
                        if str(l) in all_json["技能"][i]["效果"][j][k] and all_json["技能"][i]["效果"][j][k][str(l)] == '删除':
                            m = l
                            while True:
                                m = m + 1
                                if str(m) in all_json["技能"][i]["效果"][j][k]:
                                    all_json["技能"][i]["效果"][j][k][str(m - 1)] = copy.deepcopy(all_json["技能"][i]["效果"][j][k][str(m)])
                                else:
                                    all_json["技能"][i]["效果"][j][k].pop(str(m - 1))
                                    l -= 1
                                    break
                        else:
                            break
                    m = 0
                    l -= 1
                    while True:
                        m += 1
                        l += 1
                        if "+" + str(m) in all_json["技能"][i]["效果"][j][k]:
                            all_json["技能"][i]["效果"][j][k][str(l)] = copy.deepcopy(all_json["技能"][i]["效果"][j][k]["+" + str(m)])
                            all_json["技能"][i]["效果"][j][k].pop("+" + str(m))
                        else:
                            break

def complete_upgrade(all_json, base_txt):
    for i in all_json:
        for j in all_json[i]["属性"]:
            fulfil(all_json[i]["属性"][j]["1"]["代码"], all_json[i])
            one_upgrade(all_json[i]["属性"][j], base_txt)
        for j in all_json[i]["冷却时间"]:
            if all_json[i]["冷却时间"][j]["1"]["代码"]["1"] == '不存在':
                all_json[i]["冷却时间"][j]["1"]["代码"] = {"1": "不存在"}
            else:
                fulfil(all_json[i]["冷却时间"][j]["1"]["代码"], all_json[i])
                one_upgrade(all_json[i]["冷却时间"][j], base_txt)
        for j in all_json[i]["魔法消耗"]:
            for k in all_json[i]["魔法消耗"][j]:
                if k != '名称':
                    if all_json[i]["魔法消耗"][j][k]["1"]["代码"]["1"] == '不存在':
                        all_json[i]["魔法消耗"][j][k]["1"]["代码"] = {"1": "不存在"}
                    else:
                        fulfil(all_json[i]["魔法消耗"][j][k]["1"]["代码"], all_json[i])
                        one_upgrade(all_json[i]["魔法消耗"][j][k], base_txt)
        if all_json[i]["施法前摇"]["1"]["代码"]["1"] == '不存在':
            all_json[i]["施法前摇"]["1"]["代码"] = {"1": "不存在"}
        else:
            fulfil(all_json[i]["施法前摇"]["1"]["代码"], all_json[i])
            one_upgrade(all_json[i]["施法前摇"], base_txt)
        if all_json[i]["施法后摇"]["1"]["代码"]["1"] == '不存在':
            all_json[i]["施法后摇"]["1"]["代码"] = {"1": "不存在"}
        else:
            fulfil(all_json[i]["施法后摇"]["1"]["代码"], all_json[i])
            one_upgrade(all_json[i]["施法后摇"], base_txt)

def fulfil(arr, json):
    if '0' in arr and arr['0'] == '手填':
        return
    else:
        if "1" in arr and arr["1"] == "":
            if json['次级分类'] == '物品技能':
                arr["1"] = "物品"
            else:
                arr["1"] = "技能"
        if "2" in arr and arr["2"] == "":
            arr["2"] = json["代码"]

def one_upgrade(json, base_txt):
    inbool = ["2" in json, "3" in json]
    inbool.append(inbool[0] and inbool[1])
    getvalue = [[], [], [], []]
    calvalue = [[], [], [], []]
    caloprate = [[], [], []]
    if "0" in json["1"]["代码"] and json["1"]["代码"]['0'] != '':
        if json["1"]["代码"]["0"] == "手填":
            k = 0
            while True:
                k += 1
                if str(k) in json["1"]["代码"] and json["1"]["代码"][str(k)] != '':
                    try:
                        getvalue[0].append(float(json["1"]["代码"][str(k)]))
                    except ValueError:
                        getvalue[0].append(json["1"]["代码"][str(k)])
                else:
                    break
        elif json["1"]["代码"]["0"] == "不存在":
            return
    else:
        for k in base_txt[json["1"]["代码"]["1"]][json["1"]["代码"]["2"]][json["1"]["代码"]["3"]]:
            getvalue[0].append(base_txt[json["1"]["代码"]["1"]][json["1"]["代码"]["2"]][json["1"]["代码"]["3"]][k])
    if json["1"]["修正"]["1"] == "":
        inbool.append(False)
    else:
        inbool.append(True)
        caloprate[0].append(json["1"]["修正"]["1"])
        k = 1
        while True:
            k += 1
            if str(k) in json["1"]["修正"]:
                getvalue[1].append(json["1"]["修正"][str(k)])
            else:
                break
    if inbool[0]:
        if "0" in json["2"]["代码"] and json["2"]["代码"]["0"] == "手填":
            k = 0
            while True:
                k += 1
                if str(k) in json["2"]["代码"]:
                    try:
                        getvalue[2].append(float(json["2"]["代码"][str(k)]))
                    except ValueError:
                        getvalue[2].append(json["2"]["代码"][str(k)])
                else:
                    break
        else:
            for k in base_txt[json["2"]["代码"]["1"]][json["2"]["代码"]["2"]][json["2"]["代码"]["3"]]:
                getvalue[2].append(base_txt[json["2"]["代码"]["1"]][json["2"]["代码"]["2"]][json["2"]["代码"]["3"]][k])
        caloprate[1].append(json["2"]["修正"]["1"])
    if inbool[1]:
        if "0" in json["3"]["代码"] and json["3"]["代码"]["0"] == "手填":
            k = 0
            while True:
                k += 1
                if str(k) in json["3"]["代码"]:
                    try:
                        getvalue[3].append(float(json["3"]["代码"][str(k)]))
                    except ValueError:
                        getvalue[3].append(json["3"]["代码"][str(k)])
                else:
                    break
        else:
            for k in base_txt[json["3"]["代码"]["1"]][json["3"]["代码"]["2"]][json["3"]["代码"]["3"]]:
                getvalue[3].append(base_txt[json["3"]["代码"]["1"]][json["3"]["代码"]["2"]][json["3"]["代码"]["3"]][k])
        caloprate[2].append(json["3"]["修正"]["1"])
    maxlen=0
    for i in range(4):
        maxlen=max(maxlen,len(getvalue[i]))
    for i in range(4):
        for j in range(maxlen):
            if 0<len(getvalue[i]) and len(getvalue[i])<=j:
                getvalue[i].append(getvalue[i][j-1])
    calvalue[0] = copy.deepcopy(getvalue[0])
    calvalue[1] = copy.deepcopy(getvalue[0])
    calvalue[2] = copy.deepcopy(getvalue[0])
    calvalue[3] = copy.deepcopy(getvalue[0])
    if inbool[1]:
        array_cal(calvalue[2], getvalue[3], caloprate[2], -1)
        array_cal(calvalue[3], getvalue[3], caloprate[2], -1)
    if inbool[0]:
        array_cal(calvalue[1], getvalue[2], caloprate[1], 0)
        array_cal(calvalue[3], getvalue[2], caloprate[1], 0)
    if inbool[1]:
        array_cal(calvalue[2], getvalue[3], caloprate[2], 0)
        array_cal(calvalue[3], getvalue[3], caloprate[2], 0)
    if inbool[3]:
        array_cal(calvalue[0], getvalue[1], caloprate[0], 0)
        array_cal(calvalue[1], getvalue[1], caloprate[0], 0)
        array_cal(calvalue[2], getvalue[1], caloprate[0], 0)
        array_cal(calvalue[3], getvalue[1], caloprate[0], 0)
    if inbool[1]:
        array_cal(calvalue[2], getvalue[3], caloprate[2], 1)
        array_cal(calvalue[3], getvalue[3], caloprate[2], 1)
    cut_the_same_to_one(calvalue[0])
    for k in range(len(calvalue[0])):
        json["1"][str(k + 1)] = calvalue[0][k]
    if inbool[0]:
        cut_the_same_to_one(calvalue[1])
        for k in range(len(calvalue[1])):
            json["2"][str(k + 1)] = calvalue[1][k]
    if inbool[1]:
        cut_the_same_to_one(calvalue[2])
        for k in range(len(calvalue[2])):
            json["3"][str(k + 1)] = calvalue[2][k]
    if inbool[2]:
        cut_the_same_to_one(calvalue[3])
        json["4"] = {}
        for k in range(len(calvalue[3])):
            json["4"][str(k + 1)] = calvalue[3][k]
        json["4"]["升级来源"] = copy.deepcopy(json["3"]["升级来源"])

def cut_the_same_to_one(lists):
    bool = True
    i = 1
    delete_number = 0
    while i < len(lists):
        if lists[0] == lists[i]:
            delete_number += 1
            i = i + 1
        else:
            bool = False
            break
    if bool and i > 1:
        for i in range(delete_number):
            lists.pop(1)

def array_cal(arr1, arr2, op, num):
    for i in range(len(arr1)):
        if i < len(arr2):
            try:
                temp = float(arr2[i])
            except ValueError:
                temp = arr2[i]
        else:
            try:
                temp = float(arr2[0])
            except ValueError:
                temp = arr2[0]
        if num == 0:
            opp = '1' + op[0] + '1'
        elif num == -1:
            opp = op[0] + '1'
        elif num == 1:
            opp = '1' + op[0]
        if opp == '1=1':
            arr1[i] = temp
        elif opp == '1+1':
            arr1[i] = arr1[i] + temp
        elif opp == '1-1':
            arr1[i] = arr1[i] - temp
        elif opp == '1\\-1':
            arr1[i] = temp - arr1[i]
        elif opp == '1*1':
            arr1[i] = arr1[i] * temp
        elif opp == '1/1':
            arr1[i] = arr1[i] / temp
        elif opp == '1\\1':
            arr1[i] = temp / arr1[i]
        elif opp == '1%-1':
            arr1[i] = arr1[i] * (100 - temp) / 100
        elif opp == '1%+1':
            arr1[i] = arr1[i] * (100 + temp) / 100
        elif opp == '1-%1':
            arr1[i] = arr1[i] * (1 - temp)

def complete_mech(all_json, mech_json):
    for i in all_json:
        for j in all_json[i]["施法目标"]:
            mech_target(all_json[i]["施法目标"][j], mech_json["目标"])
        for j in all_json[i]["效果"]:
            for k in all_json[i]["效果"][j]:
                if "生效目标" in all_json[i]["效果"][j][k]:
                    mech_target(all_json[i]["效果"][j][k]["生效目标"], mech_json["目标"])
        mech_mech(all_json[i], mech_json["机制"])
        mech_junior(all_json[i], mech_json["次级"])
        mech_sign(all_json[i]["效果"], mech_json["标记"])
        mech_repeat(all_json[i]["效果"], mech_json["叠加"])
        mech_others(all_json[i], mech_json)

def mech_target(json, mech):
    for i in ["不分类", "英雄", "非英雄"]:
        if i in json:
            for j in json[i]:
                json[i][j]["值"] = mech["势力"][str(json[i][j]["代码"])]["名称"]
                json[i][j]["颜色"] = mech["势力"][str(json[i][j]["代码"])]["颜色"]
                k = 0
                while True:
                    k = k + 1
                    if str(k) in json[i][j]:
                        json[i][j][str(k)]["值"] = mech["分类"][str(json[i][j][str(k)]["代码"])]["名称"]
                        l = 0
                        while True:
                            l += 1
                            if str(l) in json[i][j][str(k)]:
                                json[i][j][str(k)][str(l)]["值"] = mech["分类"][str(json[i][j][str(k)]["代码"])][str(json[i][j][str(k)][str(l)]["代码"])]
                            else:
                                break
                    else:
                        break

def mech_mech(json, mech):
    for i in mech:
        if i == "施法类型":
            for j in json["施法类型"]:
                k = 0
                while True:
                    k += 1
                    if str(k) in json["施法类型"][j]:
                        json["施法类型"][j][str(k)]["值"] = mech["施法类型"][str(json["施法类型"][j][str(k)]["代码"])]
                    else:
                        break
        elif i == "效果":
            for j in json[i]:
                for k in json[i][j]:
                    if "代码" in json[i][j][k]:
                        json[i][j][k]["值"] = mech[i][str(json[i][j][k]["代码"])]["名称"]
                        json[i][j][k]["图片"] = mech[i][str(json[i][j][k]["代码"])]["图片"]
        else:
            for j in json[i]:
                if str(json[i][j]["代码"]) in mech[i]:
                    json[i][j]["值"] = mech[i][str(json[i][j]["代码"])]["名称"]
                    json[i][j]["图片"] = mech[i][str(json[i][j]["代码"])]["图片"]
                    if json[i][j]["简述"] == "":
                        json[i][j]["简述"] = mech[i][str(json[i][j]["代码"])]["简述"]

def mech_junior(json, mech):
    for i in mech:
        if i in ["即时攻击", "技能窃取"]:
            for j in json[i]:
                k = 0
                while True:
                    k += 1
                    if str(k) in json[i][j]:
                        if str(json[i][j][str(k)]["代码"]) in mech[i]:
                            json[i][j][str(k)]["值"] = mech[i][str(json[i][j][str(k)]["代码"])]["名称"]
                            if "简述" not in json[i][j][str(k)] or json[i][j][str(k)]["简述"] == "":
                                json[i][j][str(k)]["简述"] = mech[i][str(json[i][j][str(k)]["代码"])]["简述"]
                    else:
                        break
        else:
            for j in json["效果"]:
                for k in json["效果"][j]:
                    if isinstance(json["效果"][j][k], dict) and i in json["效果"][j][k]:
                        if str(json["效果"][j][k][i]["代码"]) in mech[i]:
                            json["效果"][j][k][i]["值"] = mech[i][str(json["效果"][j][k][i]["代码"])]["名称"]
                            if "图片" in mech[i][str(json["效果"][j][k][i]["代码"])]:
                                json["效果"][j][k][i]["图片"] = mech[i][str(json["效果"][j][k][i]["代码"])]["图片"]
                            if "简述" not in json["效果"][j][k][i] or json["效果"][j][k][i]["简述"] == "":
                                json["效果"][j][k][i]["简述"] = mech[i][str(json["效果"][j][k][i]["代码"])]["简述"]

def mech_sign(json, mech):
    for i in json:
        for j in json[i]:
            if "标记" in json[i][j]:
                for k in json[i][j]["标记"]:
                    if json[i][j]["标记"][k]["类型"] in mech and str(json[i][j]["标记"][k]["代码"]) in mech[json[i][j]["标记"][k]["类型"]]:
                        json[i][j]["标记"][k]["值"] = mech[json[i][j]["标记"][k]["类型"]][str(json[i][j]["标记"][k]["代码"])]

def mech_repeat(json, mech):
    for i in json:
        for j in json[i]:
            if isinstance(json[i][j], dict) and "叠加" in json[i][j]:
                for k in json[i][j]["叠加"]:
                    if str(json[i][j]["叠加"][k]["代码1"]) in mech["来源"] and str(json[i][j]["叠加"][k]["代码2"]) in mech["方式"]:
                        json[i][j]["叠加"][k]["来源"] = mech["来源"][str(json[i][j]["叠加"][k]["代码1"])]
                        json[i][j]["叠加"][k]["方式"] = mech["方式"][str(json[i][j]["叠加"][k]["代码2"])]

def mech_others(json, mech):
    for i in json["魔法消耗"]:
        for j in json["魔法消耗"][i]:
            if j != '名称':
                for k in json["魔法消耗"][i][j]:
                    if "类型" in json["魔法消耗"][i][j][k]:
                        json["魔法消耗"][i][j][k]["类型"]["值"] = mech["魔法消耗"][str(json["魔法消耗"][i][j][k]["类型"]["代码"])]['名称']
                        json["魔法消耗"][i][j][k]["类型"]["后缀"] = mech["魔法消耗"][str(json["魔法消耗"][i][j][k]["类型"]["代码"])]['后缀']
    for i in json["冷却时间"]:
        for j in json["冷却时间"][i]:
            if "类型" in json["冷却时间"][i][j]:
                json["冷却时间"][i][j]["类型"]["值"] = mech["冷却时间"][str(json["冷却时间"][i][j]["类型"]["代码"])]["名称"]
                json["冷却时间"][i][j]["类型"]["图片"] = mech["冷却时间"][str(json["冷却时间"][i][j]["类型"]["代码"])]["图片"]
    for i in json["施法前摇"]:
        if str(json["施法前摇"][i]["即时生效"]["代码"]) in mech["即时生效"]:
            json["施法前摇"][i]["即时生效"]["图片"] = mech["即时生效"][str(json["施法前摇"][i]["即时生效"]["代码"])]

def loop_check(json, data, all_json, name):
    for i in json:
        if isinstance(json[i], dict):
            if "混合文字" in json[i]:
                change_combine_txt(json, i, data, all_json, name)
            else:
                loop_check(json[i], data, all_json, name)

def change_combine_txt(json, ii, data, all_json, name):
    returntxt = ""
    i = 0
    while True:
        i += 1
        if str(i) in json[ii]["混合文字"]:
            if isinstance(json[ii]["混合文字"][str(i)], dict):
                j = 0
                while True:
                    j += 1
                    if str(j) in json[ii]["混合文字"][str(i)]:
                        if json[ii]["混合文字"][str(i)][str(j)]["0"] == "升级属性":
                            if json[ii]["混合文字"][str(i)][str(j)]["1"] == "":
                                json[ii]["混合文字"][str(i)][str(j)]["1"] = "技能"
                            if json[ii]["混合文字"][str(i)][str(j)]["2"] == "":
                                json[ii]["混合文字"][str(i)][str(j)]["2"] = name
                        elif json[ii]["混合文字"][str(i)][str(j)]["0"] == "数据库":
                            if json[ii]["混合文字"][str(i)][str(j)]["1"] == "":
                                json[ii]["混合文字"][str(i)][str(j)]["1"] = "技能"
                            if json[ii]["混合文字"][str(i)][str(j)]["2"] == "":
                                json[ii]["混合文字"][str(i)][str(j)]["2"] = all_json["技能"][name]["代码"]
                    else:
                        break
                temp = combine_txt_numbers(json[ii]["混合文字"][str(i)], [1], all_json, data)
                if "等级" in json[ii]["混合文字"][str(i)] and int(json[ii]["混合文字"][str(i)]["等级"]) > 0:
                    level = int(json[ii]["混合文字"][str(i)]["等级"])
                else:
                    level = 0
                if "后缀" in json[ii]["混合文字"][str(i)]:
                    post = json[ii]["混合文字"][str(i)]["后缀"]
                else:
                    post = ""
                for j in range(4):
                    bool = True
                    for k in range(len(temp[j + 1])):
                        bool = bool and temp[j + 1][0] == temp[j + 1][k]
                    if bool:
                        temp[j + 1] = [temp[j + 1][0]]
                returntxt += combine_numbers_post_level(temp[1], post, level)
                if temp[0][0] or temp[0][1]:
                    returntxt += "("
                    if temp[0][0]:
                        for j in temp[0][3]:
                            returntxt += "[[file:" + temp[0][3][j]["图片"].replace('talent.png', 'talentb.png') + "|x18px|link=" + temp[0][3][j]["名称"] + "]]"
                        returntxt += combine_numbers_post_level(temp[2], post, level)
                    if temp[0][1]:
                        for j in temp[0][4]:
                            returntxt += "[[file:" + temp[0][4][j]["图片"].replace('talent.png', 'talentb.png') + "|x18px|link=" + temp[0][4][j]["名称"] + "]]"
                        returntxt += combine_numbers_post_level(temp[3], post, level)
                    if temp[0][2]:
                        for j in temp[0][3]:
                            returntxt += "[[file:" + temp[0][3][j]["图片"].replace('talent.png', 'talentb.png') + "|x18px|link=" + temp[0][3][j]["名称"] + "]]"
                        for j in temp[0][4]:
                            returntxt += "[[file:" + temp[0][4][j]["图片"].replace('talent.png', 'talentb.png') + "|x18px|link=" + temp[0][4][j]["名称"] + "]]"
                        returntxt += combine_numbers_post_level(temp[4], post, level)
                    returntxt += ")"
            else:
                returntxt += json[ii]["混合文字"][str(i)]
        else:
            break
    json[ii] = returntxt

def combine_txt_numbers(json, index, all_json, base_txt):
    i = index[0]
    if json[str(i)]["1"] == "(" or json[str(i)]["1"] == "（":
        index[0] += 1
        re = combine_txt_numbers(json, index, all_json, base_txt)
        i = index[0]
    re = one_combine_txt_numbers(json[str(i)], all_json, base_txt)
    while True:
        i += 1
        if str(i) in json:
            if json[str(i)]["1"] == "(" or json[str(i)]["1"] == "（":
                index[0] += 1
                temp = combine_txt_numbers(json, index, all_json, base_txt)
                i = index[0]
            elif json[str(i)]["符号"] == ")" or json[str(i)]["符号"] == "）":
                return re
            else:
                temp = one_combine_txt_numbers(json[str(i)], all_json, base_txt)
            calculate_combine_txt_numbers(re, temp, json[str(i)]["符号"])
        else:
            return re

def one_combine_txt_numbers(json, all_json, base_txt):
    re = [[False, False, False, {"1": {"名称": "阿哈利姆神杖", "图片": "agha.png"}}, {}], [], [], [], []]
    if json["0"] == "属性":
        temp = all_json[json["1"]][json["2"]][json["3"]]
        i = 3
        while True:
            i += 1
            if str(i) in json and json[str(i)] != '':
                temp = temp[json[str(i)]]
            else:
                break
        j = 0
        while True:
            j += 1
            if str(j) in temp:
                re[1].append(temp[str(j)])
            else:
                break
    elif json["0"] == "数据库":
        temp = base_txt[json["1"]][json["2"]][json["3"]]
        i = 3
        while True:
            i += 1
            if str(i) in json and json[str(i)] != '':
                temp = temp[json[str(i)]]
            else:
                break
        j = 0
        while True:
            j += 1
            if str(j) in temp:
                re[1].append(temp[str(j)])
            else:
                break
    elif json['0'] == '普通属性':
        temp = all_json[json["1"]][json["2"]][json["3"]]
        i = 3
        while True:
            i += 1
            if str(i) in json and json[str(i)] != '':
                temp = temp[json[str(i)]]
            else:
                break
        re[1].append(temp)
    elif json['0'] == '图片链接':
        temp = all_json[json["1"]][json["2"]]
        re[1].append('[[file:' + temp['迷你图片'] + '|' + json['3'] + '|link=]][[' + temp['页面名'] + ']]')
    elif json["0"] == "手填":
        j = 0
        while True:
            j += 1
            if str(j) in json:
                try:
                    re[1].append(float(json[str(j)]))
                except ValueError:
                    re[1].append(json[str(j)])
            else:
                break
    elif json["0"] == "升级属性":
        temp = all_json[json["1"]][json["2"]][json["3"]]
        i = 3
        while True:
            i += 1
            if str(i) in json:
                if str(json[str(i)]) == '升级':
                    ii = i + 1
                    break
                else:
                    if str(json[str(i)]) in temp:
                        temp = temp[str(json[str(i)])]
                    elif str(json[str(i)]).isdigit():
                        temp = temp["1"]
            else:
                ii = 0
                break
        for i in range(4):
            if str(i + 1) in temp:
                if i > 0:
                    re[0][i - 1] = True
                    if i == 2:
                        re[0][4] = copy.deepcopy(temp["3"]["升级来源"])
                if ii == 0:
                    j = 0
                    while True:
                        j += 1
                        if str(j) in temp[str(i + 1)]:
                            re[i + 1].append(temp[str(i + 1)][str(j)])
                        else:
                            break
                else:
                    if str(json[str(ii)]) in temp[str(i + 1)]:
                        re[i + 1] = [temp[str(i + 1)][json[str(ii)]]]
                    elif str(json[str(ii)]).isdigit():
                        re[i + 1] = [temp[str(i + 1)]["1"]]
    else:
        temp = all_json[json["1"]][json["2"]][json["3"]]
        i = 3
        while True:
            i += 1
            if str(i) in json:
                if str(json[str(i)]) in temp:
                    temp = temp[str(json[str(i)])]
                elif str(json[str(i)]).isdigit():
                    temp = temp["1"]
            else:
                break
        for i in range(4):
            if str(i + 1) in temp:
                if i > 0:
                    re[0][i - 1] = True
                    if i == 2:
                        re[0][4] = copy.deepcopy(temp["3"]["升级来源"])
                if isinstance(temp[str(i + 1)], dict):
                    j = 0
                    while True:
                        j += 1
                        if str(j) in temp[str(i + 1)]:
                            re[i + 1].append(temp[str(i + 1)][str(j)])
                        else:
                            break
                else:
                    re[i + 1] = [temp[str(i + 1)]]
    if not re[0][0]:
        re[2] = copy.deepcopy(re[1])
    if not re[0][1]:
        re[3] = copy.deepcopy(re[1])
    if not re[0][2]:
        if re[0][0]:
            re[4] = copy.deepcopy(re[2])
        else:
            re[4] = copy.deepcopy(re[3])
    return re

def calculate_combine_txt_numbers(re, temp, op):
    re[0][0] = re[0][0] or temp[0][0]
    re[0][1] = re[0][1] or temp[0][1]
    re[0][2] = re[0][2] or temp[0][2] or re[0][0] and re[0][1]
    if temp[0][4] != {}:
        if re[0][4] == {}:
            re[0][4] = copy.deepcopy(temp[0][4])
        elif re[0][4]["1"]["名称"]!=temp[0][4]["1"]["名称"]:
            re[0][0]=True
            re[0][2]=True
            re[0][3]=copy.deepcopy(temp[0][4])
            temp[2]=copy.deepcopy(temp[3])
            temp[3]=copy.deepcopy(temp[1])
    for i in range(4):
        for j in range(max(len(re[i + 1]), len(temp[i + 1]))):
            if j >= len(re[i + 1]):
                re[i + 1].append(re[i + 1][0])
            if j >= len(temp[i + 1]):
                temp[i + 1].append(temp[i + 1][0])
        if op == 'max_stack':
            re[i + 1] = [re[i + 1][0]]
            j = 0
            while True:
                if j * temp[i + 1][0] < re[i + 1][j]:
                    re[i + 1].insert(j, j * temp[i + 1][0])
                    j += 1
                else:
                    break
        elif op == 'num_stack':
            jj = re[i + 1][0]
            re[i + 1] = []
            for j in range(int(jj)):
                re[i + 1].append(j * temp[i + 1][0])
        else:
            for j in range(len(re[i + 1])):
                if op == '+':
                    re[i + 1][j] += temp[i + 1][j]
                elif op == '-':
                    re[i + 1][j] -= temp[i + 1][j]
                elif op == '*':
                    re[i + 1][j] *= temp[i + 1][j]
                elif op == '/':
                    re[i + 1][j] /= temp[i + 1][j]
                elif op == '\\':
                    re[i + 1][j] = temp[i + 1][j] / re[i + 1][j]
                elif op == '^' or op == 'pow':
                    re[i + 1][j] = pow(re[i + 1][j], temp[i + 1][j])
                elif op == '%-':
                    re[i + 1][j] = re[i + 1][j] * (100 - temp[i + 1][j]) / 100
                elif op == '-%':
                    re[i + 1][j] = re[i + 1][j] * (1 - temp[i + 1][j])
                elif op == '%+':
                    re[i + 1][j] = re[i + 1][j] * (100 + temp[i + 1][j]) / 100
                elif op == '+%':
                    re[i + 1][j] = re[i + 1][j] * (1 + temp[i + 1][j])
                elif op == 'min' or op == "↓":
                    re[i + 1][j] = min(re[i + 1][j], temp[i + 1][j])
                elif op == 'max' or op == "↑":
                    re[i + 1][j] = max(re[i + 1][j], temp[i + 1][j])
                elif op == 'round':
                    re[i + 1][j] = round(re[i + 1][j], int(temp[i + 1][j]))
                elif op == 'ceil':
                    re[i + 1][j] = math.ceil(re[i + 1][j] * pow(10, temp[i + 1][j])) / pow(10, temp[i + 1][j])
                elif op == 'floor':
                    re[i + 1][j] = math.floor(re[i + 1][j] * pow(10, temp[i + 1][j])) / pow(10, temp[i + 1][j])
                elif op == '%*%':
                    re[i + 1][j] = (100 - (100 - re[i + 1][j]) * (100 - temp[i + 1][j]) / 100)
                elif op == 'a2%':
                    re[i + 1][j] = 13 * re[i + 1][j] / (225 + 12 * abs(re[i + 1][j])) * temp[i + 1][j]
                elif op == '%2a':
                    re[i + 1][j] = 225 * re[i + 1][j] / (13 * temp[i + 1][j] - 12 * abs(re[i + 1][j]))
                elif op == 'int':
                    re[i + 1][j] = int(re[i + 1][j])
                elif op == 'gp_s':#等比数列（GP）求和
                    re[i + 1][j] = (1-pow(re[i + 1][j],temp[i + 1][j]))/(1-re[i + 1][j])

def combine_numbers_post_level(arr, post, level):
    re = ""
    if level > 0:
        if level < len(arr):
            re += better_float_to_text(arr[level])
        else:
            re += better_float_to_text(arr[0])
        re += post
    else:
        for i in range(len(arr)):
            if i > 0:
                re += "/"
            re += better_float_to_text(arr[i])
            re += post
    return re

def confirm_upgrade_info(arr):
    for i in arr:
        if len(arr[i])>0:
            for j in arr[i]['技能升级信息']:
                arr[i]['技能升级信息'][j]['中文名']=arr[arr[i]['技能升级信息'][j]['技能名']]['中文名']
                arr[i]['技能升级信息'][j]['图片']=arr[arr[i]['技能升级信息'][j]['技能名']]['迷你图片']

def create_file(all_json):
    for i in all_json:
        file = open("E:/json/pythonupload/" + i + '.json', mode="w")
        file.write(json.dumps(all_json[i]))
        file.close()

abilitypro_num = [["a_cast_range", "AbilityCastRange"]
    , ["a_cast_range_buff", "AbilityCastRangeBuffer"]
    , ["a_cast", "AbilityCastPoint"]
    , ["a_channel", "AbilityChannelTime"]
    , ["a_cool", "AbilityCooldown"]
    , ["a_duration", "AbilityDuration"]
    , ["a_damage", "AbilityDamage"]
    , ["a_mana", "AbilityManaCost"]
    , ["a_charges", "AbilityCharges"]
    , ["a_charges_restore_time", "AbilityChargeRestoreTime"]]
abilitypro_bool = [["immediate", "DOTA_ABILITY_BEHAVIOR_IMMEDIATE"]
    , ["ignore_channel", "DOTA_ABILITY_BEHAVIOR_IGNORE_CHANNEL"]]
ability_trait_level = [["中文名", "英文名", "代码", "传说", "描述", "天赋代码", "A杖信息", "注释"], ["效果", "属性", "冷却时间"], ["魔法消耗"]]