#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""

@author: zixuan

"""
#%%-----------------------------------------------------------------------
### EDA
#%%-----------------------------------------------------------------------
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
import os
os.chdir("/Users/yuanyuan/Desktop/DATS_6103/project/DM_data sets")

#%%-----------------------------------------------------------------------
# open dataset and view structure of each data set
aisles = pd.read_csv('aisles.csv')
departments = pd.read_csv('departments.csv')
train = pd.read_csv('order_products__train.csv')
prior = pd.read_csv('order_products__prior.csv')
orders = pd.read_csv('orders.csv')
products = pd.read_csv('products.csv')
sample = pd.read_csv('sample_submission.csv')

#pd.set_option('display.max_columns',10)
#all_sets = [aisles,departments,train,prior,orders,products,sample]
#for i in all_sets:
#    print(i.head())

#%%-----------------------------------------------------------------------
# Second part: product.csv (merge products.csv, aisles.csv and departments.csv)
product = products.merge(aisles).merge(departments)
print(product.shape)
print(product.columns)
print(product.dtypes)
pd.options.display.max_columns = None
print(product.head())

#%%-----------------------------------------------------------------------
# 2.1 products in departments and aisles
# 2.1.1 products in departments
grouped = product.groupby("department")["product_id"].aggregate({'Total_products': 'count'}).reset_index()
grouped  = grouped.groupby(['department']).sum()['Total_products'].sort_values(ascending=False)
print(grouped)

plt.xticks(rotation='vertical')
sns.barplot(grouped.index, grouped.values)
plt.ylabel('Number of products', fontsize=13)
plt.xlabel('Departments', fontsize=13)
plt.title("The number of products in each department")
plt.show()

# The most five important departments are personal care, snacks, pantry, beverages and frozen. The number of items from these departments were more than 4,000 times.

# 2.1.2 products in asiles among all departments
grouped2 = product.groupby("aisle")["product_id"].aggregate({'Total_products': 'count'}).reset_index()
grouped2 = grouped2.sort_values(by='Total_products', ascending=False)[:20]
print(grouped2)

grouped2  = grouped2.groupby(['aisle']).sum()['Total_products'].sort_values(ascending=False)
grouped2 = grouped2.drop(labels="missing",axis=0)

plt.xticks(rotation='vertical')
sns.barplot(grouped2.index, grouped2.values)
plt.ylabel('Number of products', fontsize=13)
plt.xlabel('Aisles', fontsize=13)
plt.title("The number of products in each aisle(top 20)")
plt.show()
# The most three important aisles are canding chocolate, ice cream and vitamins sumpplements.

# 2.1.3 products in asiles among each department

#grouped3 = product.groupby(['department','aisle'])
# grouped3 = grouped3['product_id'].aggregate({'Total_products': 'count'}).reset_index()
# print(grouped3)
#
# fig, axes = plt.subplots(7,3, figsize=(20,45),gridspec_kw =  dict(hspace=1.4))
# for (aisle, group), ax in zip(grouped3.groupby(["department"]), axes.flatten()):
#     g = sns.barplot(group.aisle, group.Total_products , ax=ax)
#     ax.set(xlabel = "Aisles", ylabel=" Number of products")
#     g.set_xticklabels(labels = group.aisle,rotation=90, fontsize=12)
#     ax.set_title(aisle, fontsize=15)

# Each graph shows the number of products in each aisle of different departments.

#%%-----------------------------------------------------------------------
# 2.3 Oreder of product(merge products+all_order(prior+train)+orders)
all_order = pd.concat([train, prior], axis=0)
order_flow = orders[['user_id', 'order_id']].merge(all_order[['order_id', 'product_id']]).merge(product)
order_flow.head()

print(order_flow.shape)
print(order_flow.columns)
print(order_flow.dtypes)
order_flow.count()

#%%-----------------------------------------------------------------------
# 2.3.1 Sales in each department(find best selling apartment)
grouped4 = order_flow.groupby("department")["order_id"].aggregate({'Total_orders': 'count'}).reset_index()
grouped4.sort_values(by='Total_orders', ascending=False, inplace=True)
print(grouped4)

grouped4  = grouped4.groupby(['department']).sum()['Total_orders'].sort_values(ascending=False)
plt.xticks(rotation='vertical')
sns.barplot(grouped4.index, grouped4.values)
plt.ylabel('Number of Orders', fontsize=13)
plt.xlabel('Departments', fontsize=13)
plt.title('Sales in each department')
plt.show()
# the most three popular departments are produce, dairy eggs and snacks.
#%%-----------------------------------------------------------------------
# 2.3.2 Sales in each aisle(best selling aisle)
grouped5 = order_flow.groupby("aisle")["order_id"].aggregate({'Total_orders': 'count'}).reset_index()
grouped5.sort_values(by='Total_orders', ascending=False, inplace=True )
print(grouped5.head(15))

grouped5 = grouped5.groupby(['aisle']).sum()['Total_orders'].sort_values(ascending=False)[:15]
plt.xticks(rotation='vertical')
sns.barplot(grouped5.index, grouped5.values)
plt.ylabel('Number of Orders', fontsize=13)
plt.xlabel('Aisles', fontsize=13)
plt.title('Sales in each aisle')
plt.show()

# the top three best selling aisles are fresh fruits, fresh vegetables and packaged vegetables fruits.
#%%-----------------------------------------------------------------------

#%%-----------------------------------------------------------------------
# 2.4 Reorder of product
# 2.4.1 the number of reordered products
reord=sum(prior['reordered']==1)
not_reord=sum(prior['reordered']==0)
order_sum = reord + not_reord
reord_pro=reord/order_sum
not_ord_pro=not_reord/order_sum

all_order = pd.concat([train, prior], axis=0)
grouped6 = all_order.groupby("reordered")["product_id"].aggregate({'Total_products': 'count'}).reset_index()
grouped6 = grouped6.groupby(['reordered']).sum()['Total_products'].sort_values(ascending=False)
print(grouped6)
sns.barplot(grouped6.index,grouped6.values)
plt.ylabel('Number of Products', fontsize=13)
plt.xlabel('Reordered or Not Reordered', fontsize=13)
plt.ticklabel_format(style='plain', axis='y')
plt.title("Not reorder vs Reorder")
plt.show()

# conclusion:
# 19126536 products are previously ordered by customers, reordered products take 0.59 % of ordered products.
# 13307953 products are not ordered by customers before, non-reordered products take 0.41 % of ordered products.
#%%-----------------------------------------------------------------------
# 2.4.2 highest reordered rate
grouped7 = all_order.groupby("product_id")["reordered"].aggregate({'reorder_sum': sum,'total': 'count'}).reset_index()
grouped7['reord_ratio']= grouped7['reorder_sum'] / grouped7['total']
grouped7 = pd.merge(grouped7, product, how='left', on=['product_id'])
grouped8 = grouped7.sort_values(['reord_ratio'],ascending=False).head(10)
print(grouped8)

sns.barplot(grouped8['product_name'],grouped8['reord_ratio'])
plt.ylim([0.85,0.95])
plt.xticks(rotation='vertical')
plt.title('Top 10 reordered rate')
plt.show()

# conclusion:
# 1.The three products with the highest reordered rate are Raw Veggie Wrappers, Serenity Ultimate Extrema Overnight Pads and Orange Energy Shots.
#%%-----------------------------------------------------------------------
# 2.4.3 department with highest reorder ratio
grouped9 = grouped7.sort_values(['reord_ratio'],ascending=False)
sns.lineplot(grouped7['department'],grouped7['reord_ratio'])
plt.xticks(rotation='vertical')
plt.title('Reordered ratio in each department')
plt.show()

# A: Personal care has lowest reorder ratio and dairy eggs have highest reorder ratio.
#%%-----------------------------------------------------------------------
# 2.4.4 Relationship between add_to_cart and reordered?

# add_to_cart_order: The sequence of product is added to the cart in each order

prior["add_to_cart_order_mod"] =prior["add_to_cart_order"].copy()
prior["add_to_cart_order_mod"].loc[prior["add_to_cart_order_mod"]>70] = 70
grouped_df = prior.groupby(["add_to_cart_order_mod"])["reordered"].aggregate("mean").reset_index()

plt.figure(figsize=(12,8))
sns.pointplot(grouped_df['add_to_cart_order_mod'].values, grouped_df['reordered'].values, alpha=0.8)
plt.ylabel('Reorder ratio', fontsize=12)
plt.xlabel('Add to cart order', fontsize=12)
plt.title("Add to cart order - Reorder ratio", fontsize=15)
plt.xticks(rotation='vertical')
plt.show()

# t-test
data1 = prior[prior['reordered']==0]['add_to_cart_order']
data2 = prior[prior['reordered']==1]['add_to_cart_order']
print(np.mean(data1))
print(np.mean(data2))
print(stats.ttest_ind(data1,data2))

# conclusion:
# 1.Orders placed initially in the cart are more likely to be reorderd than one placed later in the cart.
# 2.We did t-test to verify whether the sequence of adding to cart are siginificantly different between reordered products and not reordered products.
# We can conclude from the results showing the p-value is smaller than 0.05 that the sequence of adding to cart significantly influence whether the products being reordered.
#%%-----------------------------------------------------------------------

#%%-----------------------------------------------------------------------
### Naive Bayes
#%%-----------------------------------------------------------------------
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import roc_auc_score
import seaborn as sns
import matplotlib.pyplot as plt

from sklearn.naive_bayes import GaussianNB

clf = GaussianNB()
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
y_pred_score = clf.predict_proba(X_test)

print("Classification Report: ")
print(classification_report(y_test,y_pred))
print("\n")
print("Accuracy : ", accuracy_score(y_test, y_pred) * 100)
print("\n")
print("ROC_AUC : ", roc_auc_score(y_test,y_pred_score[:,1]) * 100)

conf_matrix = confusion_matrix(y_test, y_pred)
#class_names = total_info_train['reordered'].unique()

df_cm = pd.DataFrame(conf_matrix, index=['0','1'], columns=['0','1'] )

plt.figure(figsize=(5,5))
hm = sns.heatmap(df_cm, cbar=False, annot=True, square=True, fmt='d', annot_kws={'size': 20}, yticklabels=df_cm.columns, xticklabels=df_cm.columns)
hm.yaxis.set_ticklabels(hm.yaxis.get_ticklabels(), rotation=0, ha='right', fontsize=20)
hm.xaxis.set_ticklabels(hm.xaxis.get_ticklabels(), rotation=0, ha='right', fontsize=20)
plt.ylabel('True label',fontsize=20)
plt.xlabel('Predicted label',fontsize=20)
# Show heat map
plt.tight_layout()
plt.show()

#%%-----------------------------------------------------------------------

#%%-----------------------------------------------------------------------
### GUI
#%%-----------------------------------------------------------------------
import tkinter as tk
from tkinter import messagebox
from tkinter import ttk
import pandas as pd
import tkinter.font as tkFont
from imblearn.over_sampling import RandomOverSampler
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import roc_auc_score
import seaborn as sns
import matplotlib.pyplot as plt
from matplotlib.pyplot import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class Application(tk.Tk):
    def __init__(self):
        super().__init__()
        # self.geometry('600x400')
        self.createWidgets()
        self.color = sns.color_palette()

    def createWidgets(self):
        self.title("Presentation")
        tabControl = ttk.Notebook(self)
        self.tab1 = tk.Frame(tabControl)
        self.createTab1()
        tabControl.add(self.tab1, text = 'EDA')
        self.tab2 = tk.Frame(tabControl)
        self.createTab2()
        tabControl.add(self.tab2, text = 'Features')
        self.tab3 = tk.Frame(tabControl)
        self.createTab3()
        tabControl.add(self.tab3, text = 'Models')
        tabControl.pack(expand=1, fill="both")

    def addmenu(self, Menu):
        Menu(self)

    def createTab1(self):
        topframe = tk.Frame(self.tab1, height=80)
        #contentframe = tk.Frame(tab1)
        topframe.pack(side = tk.TOP)
        #contentframe.pack(side = tk.TOP)

        OrdersButton = tk.Menubutton(topframe, text = 'Orders')
        #OrdersButton.pack()
        ordersMenu = tk.Menu(OrdersButton, tearoff = False)
        ordersMenu.add_command(label = 'EDA1', command = self.oeda1)
        ordersMenu.add_command(label = 'EDA2', command = self.oeda2)
        ordersMenu.add_command(label = 'EDA3', command = self.oeda3)
        ordersMenu.add_command(label = 'EDA4', command = self.oeda4)
        OrdersButton.config(menu=ordersMenu)

        ProductsButton = tk.Menubutton(topframe, text = 'Products')
        #ProductsButton.pack()
        productsMenu = tk.Menu(ProductsButton, tearoff = False)
        productsMenu.add_command(label = 'EDA1', command = self.peda1)
        productsMenu.add_command(label = 'EDA2', command = self.peda2)
        productsMenu.add_command(label = 'EDA3', command = self.peda3)
        productsMenu.add_command(label = 'EDA4', command = self.peda4)
        ProductsButton.config(menu=productsMenu)

        OrdersButton.grid(row=0, column=0, sticky=tk.W)
        ProductsButton.grid(row=0, column=1)

        fig1 = Figure(figsize=(5, 4), dpi=100)
        self.ax1 = fig1.add_subplot(111)
        self.canvas1 = FigureCanvasTkAgg(fig1, master=self.tab1)
        self.canvas1.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
        self.canvas1._tkcanvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
        fig2 = Figure(figsize=(5, 4), dpi=100)
        self.ax2 = fig2.add_subplot(111)
        self.canvas2 = FigureCanvasTkAgg(fig2, master=self.tab1)
        self.canvas2.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas2._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)

    def createTab2(self):
        self.ft1 = tkFont.Font(size = 24)
        tk.Label(self.tab2, text='Select Feature:').pack()
        self.features = ttk.Combobox(self.tab2, values=list(data.columns))
        self.features.pack()
        tk.Button(self.tab2, text='Show first fifteen values', command=self.show_feature).pack()
        self.featureText = tk.Text(self.tab2, font = self.ft1)
        self.featureText.pack()

    def show_feature(self):
        identifier = self.features.get()  # get option
        self.featureText.delete(1.0, tk.END)  # empty widget to print new text
        self.featureText.insert(tk.END, str(data[identifier][0:15]))

    def createTab3(self):
        self.ft2 = tkFont.Font(size = 18)
        tk.Label(self.tab3, text='Select Model:').pack()
        self.models = ttk.Combobox(self.tab3, values=['Logistic Regression', 'k-NearestNeighbor', 'Random Forest'])
        self.models.pack()
        tk.Button(self.tab3, text='Show Result', command=self.show_result).pack()
        fig3 = Figure(figsize=(5, 4), dpi=100)
        self.ax1 = fig3.add_subplot(111)
        self.canvas3 = FigureCanvasTkAgg(fig3, master=self.tab3)
        self.canvas3.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas3._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)
        self.modelText = tk.Text(self.tab3)
        self.modelText.pack(side = tk.LEFT, fill = tk.BOTH, expand = True)
        # self.modelText.pack(side = tk.LEFT)

        # self.text.pack(side = tk.LEFT)

    def show_result(self):
        modelName = self.models.get()
        if modelName == 'Logistic Regression':

            self.modelText.delete(1.0, tk.END)
            self.modelText.insert(tk.END, "Classification Report:\n" + str(classification_report(y_test, LRy_pred)) + "\n" + "Accuracy : " + str((accuracy_score(y_test, LRy_pred) * 100)) + "\n" + "ROC_AUC : " + str((roc_auc_score(y_test, LRy_pred_score[:, 1]) * 100)))

            self.canvas3.get_tk_widget().destroy()
            self.canvas3._tkcanvas.destroy()
            fig = self.draw_cm(LRy_pred)
            self.canvas3 = FigureCanvasTkAgg(fig, master=self.tab3)
            self.canvas3.draw()
            self.canvas3.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
            self.canvas3._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)

        elif modelName == 'k-NearestNeighbor':

            self.modelText.delete(1.0, tk.END)
            self.modelText.insert(tk.END, "Classification Report:\n" + str(
                classification_report(y_test, KNNy_pred)) + "\n" + "Accuracy : " + str(
                (accuracy_score(y_test, KNNy_pred) * 100)) + "\n" + "ROC_AUC : " + str(
                (roc_auc_score(y_test, KNNy_pred_score[:, 1]) * 100)))

            self.canvas3.get_tk_widget().destroy()
            self.canvas3._tkcanvas.destroy()
            fig = self.draw_cm(KNNy_pred)
            self.canvas3 = FigureCanvasTkAgg(fig, master=self.tab3)
            self.canvas3.draw()
            self.canvas3.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
            self.canvas3._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)
        else:

            self.modelText.delete(1.0, tk.END)
            self.modelText.insert(tk.END, "Classification Report:\n" + str(
                classification_report(y_test, RFy_pred)) + "\n" + "Accuracy : " + str(
                (accuracy_score(y_test, RFy_pred) * 100)) + "\n" + "ROC_AUC : " + str(
                (roc_auc_score(y_test, RFy_pred_score[:, 1]) * 100)))

            self.canvas3.get_tk_widget().destroy()
            self.canvas3._tkcanvas.destroy()
            fig = self.draw_cm(RFy_pred)
            self.canvas3 = FigureCanvasTkAgg(fig, master=self.tab3)
            self.canvas3.draw()
            self.canvas3.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
            self.canvas3._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)

    def draw_cm(self, y_pred):
        conf_matrix = confusion_matrix(y_test, y_pred)
        df_cm = pd.DataFrame(conf_matrix, index=['0', '1'], columns=['0', '1'])

        f, ax = plt.subplots(figsize=(5, 4))
        hm = sns.heatmap(df_cm, cbar=False, annot=True, square=True, fmt='d', annot_kws={'size': 20},
                         yticklabels=df_cm.columns, xticklabels=df_cm.columns)
        hm.yaxis.set_ticklabels(hm.yaxis.get_ticklabels(), rotation=0, ha='right', fontsize=20)
        hm.xaxis.set_ticklabels(hm.xaxis.get_ticklabels(), rotation=0, ha='right', fontsize=20)
        plt.ylabel('True label', fontsize=20)
        plt.xlabel('Predicted label', fontsize=20)
        return f

    def create_oeda1(self):
        f, ax = plt.subplots(figsize = (5, 4))
        dist_eval_set = orders.eval_set.value_counts()
        sns.barplot(dist_eval_set.index, dist_eval_set.values, alpha=0.8, color=self.color[1])
        plt.ylabel('orders')
        plt.xlabel('eval_set type')
        plt.title('Number of orders in each set')
        return f

    def create_oeda2(self):
        f, ax = plt.subplots(figsize=(5, 4))
        group_ev = orders.groupby('eval_set')
        x = []
        y = []
        for name, group in group_ev:
            x.append(name)
            y.append(group.user_id.unique().shape[0])
        sns.barplot(x, y, alpha=0.8, color=self.color[2])
        plt.ylabel('users')
        plt.xlabel('eval_set type')
        plt.title('Number of users in each set')
        return f

    def create_oeda3(self):
        f, ax = plt.subplots(figsize=(5, 4))
        self.dist_no_orders = orders.groupby('user_id').order_number.max()
        self.dist_no_orders = self.dist_no_orders.value_counts()

        sns.barplot(self.dist_no_orders.index, self.dist_no_orders.values)
        plt.xlabel('orders')
        plt.ylabel('users')
        plt.title('Frequency of orders by users')
        return f

    def create_oeda4(self):
        f, ax = plt.subplots(figsize=(5, 4))
        sns.boxplot(self.dist_no_orders.index)
        return f

    def create_oeda5(self):
        f, ax = plt.subplots(figsize=(5, 4))
        self.dist_d_orders = orders.order_dow.value_counts()

        sns.barplot(self.dist_d_orders.index, self.dist_d_orders.values, palette=sns.color_palette('Blues_d', 7))
        plt.xlabel('day of week')
        plt.ylabel('orders')
        plt.title('Frequency of orders by day of week')
        return f

    def create_oeda6(self):
        f, ax = plt.subplots(figsize=(5, 4))
        dist_h_orders = orders.order_hour_of_day.value_counts()
        sns.barplot(dist_h_orders.index, dist_h_orders.values, palette=sns.color_palette('Greens_d', 24))
        plt.xlabel('hour of day')
        plt.ylabel('orders')
        plt.title('Frequency of orders by hour of day')
        return f

    def create_oeda7(self):
        f, ax = plt.subplots(figsize=(5, 4))
        grouped = orders.groupby(['order_dow', 'order_hour_of_day']).order_number.count().reset_index()
        # using reset_index to set order_dow and ordr_h_day as columns, or they would be index
        time_orders = grouped.pivot('order_dow', 'order_hour_of_day', 'order_number')
        sns.heatmap(time_orders, cmap='YlOrRd')
        plt.ylabel('Day of Week')
        plt.xlabel('Hour of Day')
        plt.title('Number of Orders Day of Week vs Hour of Day')
        return f

    def create_oeda8(self):
        f, ax = plt.subplots(figsize=(5, 4))
        dist_d_prior_orders = orders.days_since_prior_order.value_counts()
        sns.barplot(dist_d_prior_orders.index, dist_d_prior_orders.values, palette=sns.color_palette('Greens_d', 31))
        plt.xlabel('days of prior order')
        plt.ylabel('count')
        plt.title('Time interval between orders')
        return f

    def create_peda1(self):
        f, ax = plt.subplots(figsize=(5, 4))
        grouped = product.groupby("department")["product_id"].aggregate({'Total_products': 'count'}).reset_index()
        grouped = grouped.groupby(['department']).sum()['Total_products'].sort_values(ascending=False)
        plt.xticks(rotation='vertical')
        sns.barplot(grouped.index, grouped.values)
        plt.ylabel('Number of products', fontsize=13)
        plt.xlabel('Departments', fontsize=13)
        plt.title("The number of products in each department")
        return f

    def create_peda2(self):
        f, ax = plt.subplots(figsize=(5, 4))
        grouped2 = product.groupby("aisle")["product_id"].aggregate({'Total_products': 'count'}).reset_index()
        grouped2 = grouped2.sort_values(by='Total_products', ascending=False)[:20]

        grouped2 = grouped2.groupby(['aisle']).sum()['Total_products'].sort_values(ascending=False)

        plt.xticks(rotation='vertical')
        sns.barplot(grouped2.index, grouped2.values)
        plt.ylabel('Number of products', fontsize=13)
        plt.xlabel('Aisles', fontsize=13)
        plt.title("The number of products in each aisle(top 20)")
        return f

    def create_peda3(self):
        f, ax = plt.subplots(figsize=(5, 4))
        grouped4 = order_flow.groupby("department")["order_id"].aggregate({'Total_orders': 'count'}).reset_index()
        grouped4.sort_values(by='Total_orders', ascending=False, inplace=True)

        grouped4 = grouped4.groupby(['department']).sum()['Total_orders'].sort_values(ascending=False)
        plt.xticks(rotation='vertical')
        sns.barplot(grouped4.index, grouped4.values)
        plt.ylabel('Number of Orders', fontsize=13)
        plt.xlabel('Departments', fontsize=13)
        plt.title('Sales in each department')
        return f

    def create_peda4(self):
        f, ax = plt.subplots(figsize=(5, 4))
        grouped5 = order_flow.groupby("aisle")["order_id"].aggregate({'Total_orders': 'count'}).reset_index()
        grouped5.sort_values(by='Total_orders', ascending=False, inplace=True)
        grouped5 = grouped5.groupby(['aisle']).sum()['Total_orders'].sort_values(ascending=False)[:15]
        plt.xticks(rotation='vertical')
        sns.barplot(grouped5.index, grouped5.values)
        plt.ylabel('Number of Orders', fontsize=13)
        plt.xlabel('Aisles', fontsize=13)
        plt.title('Sales in each aisle')
        return f

    def create_peda5(self):
        f, ax = plt.subplots(figsize=(5, 4))
        grouped6 = all_order.groupby("reordered")["product_id"].aggregate({'Total_products': 'count'}).reset_index()
        grouped6 = grouped6.groupby(['reordered']).sum()['Total_products'].sort_values(ascending=False)

        sns.barplot(grouped6.index, grouped6.values)
        plt.ylabel('Number of Products', fontsize=13)
        plt.xlabel('Reordered or Not Reordered', fontsize=13)
        plt.ticklabel_format(style='plain', axis='y')
        plt.title("Not reorder vs Reorder")
        return f

    def create_peda6(self):
        f, ax = plt.subplots(figsize=(5, 4))
        self.grouped7 = all_order.groupby("product_id")["reordered"].aggregate({'reorder_sum': sum, 'total': 'count'}).reset_index()
        self.grouped7['reord_ratio'] = self.grouped7['reorder_sum'] / self.grouped7['total']
        self.grouped7 = pd.merge(self.grouped7, product, how='left', on=['product_id'])
        grouped8 = self.grouped7.sort_values(['reord_ratio'], ascending=False).head(10)

        sns.barplot(grouped8['product_name'], grouped8['reord_ratio'])
        plt.ylim([0.85, 0.95])
        plt.xticks(rotation='vertical')
        plt.title('Top 10 reordered rate')
        return f

    def create_peda7(self):
        f, ax = plt.subplots(figsize=(5, 4))
        grouped9 = self.grouped7.sort_values(['reord_ratio'], ascending=False)
        sns.lineplot(grouped9['department'], grouped9['reord_ratio'])
        plt.xticks(rotation='vertical')
        plt.title('Reordered ratio in each department')
        return f

    def create_peda8(self):
        f, ax = plt.subplots(figsize=(5, 4))
        prior["add_to_cart_order_mod"] = prior["add_to_cart_order"].copy()
        prior["add_to_cart_order_mod"].loc[prior["add_to_cart_order_mod"] > 70] = 70
        grouped_df = prior.groupby(["add_to_cart_order_mod"])["reordered"].aggregate("mean").reset_index()
        sns.pointplot(grouped_df['add_to_cart_order_mod'].values, grouped_df['reordered'].values, alpha=0.8)
        plt.ylabel('Reorder ratio', fontsize=12)
        plt.xlabel('Add to cart order', fontsize=12)
        plt.title("Add to cart order - Reorder ratio", fontsize=15)
        plt.xticks(rotation='vertical')
        return f

    def oeda1(self):
        self.canvas1.get_tk_widget().destroy()
        self.canvas1._tkcanvas.destroy()
        fig1 = self.create_oeda1()
        self.canvas1 = FigureCanvasTkAgg(fig1, master = self.tab1)
        self.canvas1.draw()
        self.canvas1.get_tk_widget().pack(side = tk.TOP, fill = tk.BOTH, expand = 1)
        self.canvas1._tkcanvas.pack(side = tk.LEFT, fill = tk.BOTH, expand = 1)

        self.canvas2.get_tk_widget().destroy()
        self.canvas2._tkcanvas.destroy()
        fig2 = self.create_oeda2()
        self.canvas2 = FigureCanvasTkAgg(fig2, master = self.tab1)
        self.canvas2.draw()
        self.canvas2.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas2._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)

    def oeda2(self):
        self.canvas1.get_tk_widget().destroy()
        self.canvas1._tkcanvas.destroy()
        fig1 = self.create_oeda3()
        self.canvas1.get_tk_widget().pack_forget()
        self.canvas1 = FigureCanvasTkAgg(fig1, master=self.tab1)
        self.canvas1.draw()
        self.canvas1.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas1._tkcanvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.canvas2.get_tk_widget().destroy()
        self.canvas2._tkcanvas.destroy()
        fig2 = self.create_oeda4()
        self.canvas2.get_tk_widget().pack_forget()
        self.canvas2 = FigureCanvasTkAgg(fig2, master=self.tab1)
        self.canvas2.draw()
        self.canvas2.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas2._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)

    def oeda3(self):
        self.canvas1.get_tk_widget().destroy()
        self.canvas1._tkcanvas.destroy()
        fig1 = self.create_oeda5()
        self.canvas1.get_tk_widget().pack_forget()
        self.canvas1 = FigureCanvasTkAgg(fig1, master=self.tab1)
        self.canvas1.draw()
        self.canvas1.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas1._tkcanvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.canvas2.get_tk_widget().destroy()
        self.canvas2._tkcanvas.destroy()
        fig2 = self.create_oeda6()
        self.canvas2.get_tk_widget().pack_forget()
        self.canvas2 = FigureCanvasTkAgg(fig2, master=self.tab1)
        self.canvas2.draw()
        self.canvas2.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas2._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)

    def oeda4(self):
        self.canvas1.get_tk_widget().destroy()
        self.canvas1._tkcanvas.destroy()
        fig1 = self.create_oeda7()
        self.canvas1.get_tk_widget().pack_forget()
        self.canvas1 = FigureCanvasTkAgg(fig1, master=self.tab1)
        self.canvas1.draw()
        self.canvas1.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas1._tkcanvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.canvas2.get_tk_widget().destroy()
        self.canvas2._tkcanvas.destroy()
        fig2 = self.create_oeda8()
        self.canvas2.get_tk_widget().pack_forget()
        self.canvas2 = FigureCanvasTkAgg(fig2, master=self.tab1)
        self.canvas2.draw()
        self.canvas2.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas2._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)

    def peda1(self):
        self.canvas1.get_tk_widget().destroy()
        self.canvas1._tkcanvas.destroy()
        fig1 = self.create_peda1()
        self.canvas1.get_tk_widget().pack_forget()
        self.canvas1 = FigureCanvasTkAgg(fig1, master=self.tab1)
        self.canvas1.draw()
        self.canvas1.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas1._tkcanvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.canvas2.get_tk_widget().destroy()
        self.canvas2._tkcanvas.destroy()
        fig2 = self.create_peda2()
        self.canvas2.get_tk_widget().pack_forget()
        self.canvas2 = FigureCanvasTkAgg(fig2, master=self.tab1)
        self.canvas2.draw()
        self.canvas2.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas2._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)

    def peda2(self):
        self.canvas1.get_tk_widget().destroy()
        self.canvas1._tkcanvas.destroy()
        fig1 = self.create_peda3()
        self.canvas1.get_tk_widget().pack_forget()
        self.canvas1 = FigureCanvasTkAgg(fig1, master=self.tab1)
        self.canvas1.draw()
        self.canvas1.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas1._tkcanvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.canvas2.get_tk_widget().destroy()
        self.canvas2._tkcanvas.destroy()
        fig2 = self.create_peda4()
        self.canvas2.get_tk_widget().pack_forget()
        self.canvas2 = FigureCanvasTkAgg(fig2, master=self.tab1)
        self.canvas2.draw()
        self.canvas2.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas2._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)

    def peda3(self):
        self.canvas1.get_tk_widget().destroy()
        self.canvas1._tkcanvas.destroy()
        fig1 = self.create_peda5()
        self.canvas1.get_tk_widget().pack_forget()
        self.canvas1 = FigureCanvasTkAgg(fig1, master=self.tab1)
        self.canvas1.draw()
        self.canvas1.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas1._tkcanvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.canvas2.get_tk_widget().destroy()
        self.canvas2._tkcanvas.destroy()
        fig2 = self.create_peda6()
        self.canvas2.get_tk_widget().pack_forget()
        self.canvas2 = FigureCanvasTkAgg(fig2, master=self.tab1)
        self.canvas2.draw()
        self.canvas2.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas2._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)

    def peda4(self):
        self.canvas1.get_tk_widget().destroy()
        self.canvas1._tkcanvas.destroy()
        fig1 = self.create_peda7()
        self.canvas1.get_tk_widget().pack_forget()
        self.canvas1 = FigureCanvasTkAgg(fig1, master=self.tab1)
        self.canvas1.draw()
        self.canvas1.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas1._tkcanvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.canvas2.get_tk_widget().destroy()
        self.canvas2._tkcanvas.destroy()
        fig2 = self.create_peda8()
        self.canvas2.get_tk_widget().pack_forget()
        self.canvas2 = FigureCanvasTkAgg(fig2, master=self.tab1)
        self.canvas2.draw()
        self.canvas2.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.canvas2._tkcanvas.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)

class MyMenu():
    def __init__(self, root):
        self.root = root
        self.menubar = tk.Menu(self.root)
        # add menu to root
        root.config(menu=self.menubar)

        self.myMenu = tk.Menu(self.menubar)
        self.myMenu.add_command(label = "About", command = self.about)

        self.myMenu.add_separator()
        self.myMenu.add_command(label = "quit", command = root.quit)

        # add menu to Menu
        self.menubar.add_cascade(label = "Menu", menu = self.myMenu)

    def about(self):
        pass

def LoadAndPreprocess():
    global aisles
    global departments
    global train
    global prior
    global orders
    global products
    global product
    global all_order
    global order_flow
    global data
    global X_train
    global X_test
    global y_train
    global y_test
    global LRy_pred
    global LRy_pred_score
    global KNNy_pred
    global KNNy_pred_score
    global RFy_pred
    global RFy_pred_score

    aisles = pd.read_csv('aisles.csv')
    departments = pd.read_csv('departments.csv')
    train = pd.read_csv('order_products__train.csv')
    prior = pd.read_csv('order_products__prior.csv')
    orders = pd.read_csv('orders.csv')
    products = pd.read_csv('products.csv')
    data = pd.read_csv('data.csv')
    product = products.merge(aisles).merge(departments)
    all_order = pd.concat([train, prior], axis=0)
    order_flow = orders[['user_id', 'order_id']].merge(all_order[['order_id', 'product_id']]).merge(product)
    Xdata, Ydata = data.drop('reordered', axis=1), data.reordered
    ros = RandomOverSampler(random_state=0)
    Xdata, Ydata = ros.fit_sample(Xdata, Ydata)
    X_train, X_test, y_train, y_test = train_test_split(Xdata, Ydata, test_size=0.3, random_state=100)
    LRy_pred, LRy_pred_score = LRModel()
    KNNy_pred, KNNy_pred_score = KNNModel()
    RFy_pred, RFy_pred_score = RFModel()

def featureSelection():

    prior_orders = orders.merge(prior, on='order_id', how='inner')
    prior_orders.head()

    user_f_1 = prior_orders.groupby('user_id').order_number.max().reset_index(name='n_orders_users')
    user_f_2 = prior_orders.groupby('user_id').product_id.count().reset_index(name='n_products_users')
    user_f_2['avg_products_users'] = user_f_2.n_products_users / user_f_1.n_orders_users
    temp = prior_orders.groupby('user_id')['order_dow'].value_counts().reset_index(name='times_d')
    user_f_3 = temp.loc[temp.groupby('user_id')['times_d'].idxmax(), ['user_id', 'order_dow']]
    user_f_3 = user_f_3.rename(columns={'order_dow': 'dow_most_user'})
    temp = prior_orders.groupby('user_id')['order_hour_of_day'].value_counts().reset_index(name='times_h')
    user_f_4 = temp.loc[temp.groupby('user_id')['times_h'].idxmax(), ['user_id', 'order_hour_of_day']]
    user_f_4 = user_f_4.rename(columns={'order_hour_of_day': 'hod_most_user'})
    user_f_5 = prior_orders.groupby('user_id').reordered.mean().reset_index(name='reorder_ratio_user')
    order_user_group = prior_orders.groupby('user_id')
    user_f_6 = (order_user_group.days_since_prior_order.sum() / order_user_group.days_since_prior_order.count()).reset_index(name='shopping_freq')

    user = pd.merge(user_f_1, user_f_2, on='user_id')
    user = user.merge(user_f_3, on='user_id')
    user = user.merge(user_f_4, on='user_id')
    user = user.merge(user_f_5, on='user_id')
    user = user.merge(user_f_6, on='user_id')

    prod_f_1 = prior.groupby('product_id').order_id.count().reset_index(name='times_bought_prod')
    prod_f_2 = prior.groupby('product_id').reordered.mean().reset_index(name='reorder_ratio_prod')
    prod_f_3 = prior.groupby('product_id').add_to_cart_order.mean().reset_index(name='position_cart_prod')
    prod_dep = pd.merge(departments['department_id'], products[['department_id', 'product_id']], on='department_id', how='right')
    totall_info = pd.merge(prod_dep, prod_f_2, on='product_id', how='right')

    group = totall_info.groupby('department_id')
    prod_f_4 = group.reorder_ratio_prod.mean().reset_index(name='reorder_ratio_dept')

    prod_f_4 = pd.merge(prod_f_4, totall_info, on='department_id')
    del prod_f_4['reorder_ratio_prod']

    prod = pd.merge(prod_f_1, prod_f_2, on='product_id')
    prod = prod.merge(prod_f_3, on='product_id')
    prod = prod.merge(prod_f_4, on='product_id')

    user_prd_f_1 = prior_orders.groupby(['user_id', 'product_id']).order_id.count().reset_index(name='times_bought_up')

    # number of orders for one user
    user_prd_f_2 = prior_orders.groupby('user_id').order_number.max().reset_index(name='n_orders_users')
    # when the user bought the product for the first time
    temp = prior_orders.groupby(['user_id', 'product_id']).order_number.min().reset_index(name='first_bought_number')
    # merge two datasets
    user_prd_f_2 = pd.merge(user_prd_f_2, temp, on='user_id')
    # how many orders performed after the user bought the product for the first time
    user_prd_f_2['order_range'] = user_prd_f_2['n_orders_users'] - user_prd_f_2['first_bought_number'] + 1
    # reordered ratio
    user_prd_f_2['reorder_ratio_up'] = user_prd_f_1.times_bought_up / user_prd_f_2.order_range
    user_prd_f_2 = user_prd_f_2.loc[:, ['user_id', 'product_id', 'reorder_ratio_up']]

    # Reversing the order number for each product.
    prior_orders['order_number_back'] = prior_orders.groupby('user_id')['order_number'].transform(max) - prior_orders[
        'order_number'] + 1

    temp1 = prior_orders.loc[prior_orders['order_number_back'] <= 4]
    user_prd_f_3 = (temp1.groupby(['user_id', 'product_id'])['order_number_back'].count() / 4).reset_index(
        name='ratio_last4_orders_up')

    user_prd = pd.merge(user_prd_f_1, user_prd_f_2, on=['user_id', 'product_id'])
    user_prd = user_prd.merge(user_prd_f_3, on=['user_id', 'product_id'], how='left')

    user_prd.ratio_last4_orders_up.fillna(0, inplace=True)

    data = user_prd.merge(user, on='user_id', how='left')
    data = data.merge(prod, on='product_id', how='left')
    orders_future = orders[((orders.eval_set == 'train') | (orders.eval_set == 'test'))]
    orders_future = orders_future[['user_id', 'eval_set', 'order_id']]
    data = data.merge(orders_future, on='user_id', how='left')
    data = data[data.eval_set == 'train']
    data = data.merge(train[['product_id', 'order_id', 'reordered']], on=['product_id', 'order_id'], how='left')
    data['reordered'] = data['reordered'].fillna(0)
    data = data.drop(['department_id', 'eval_set', 'order_id'], axis=1)
    data = data.set_index(['user_id', 'product_id'])
    #data.to_csv("data.csv")
    return data

def LRModel():
    clf = LogisticRegression(random_state=0).fit(X_train, y_train)
    y_pred = clf.predict(X_test)
    y_pred_score = clf.predict_proba(X_test)
    return y_pred, y_pred_score

def KNNModel():
    clf = KNeighborsClassifier(n_neighbors=3)
    clf.fit(X_train, y_train)
    y_pred = clf.predict(X_test)
    y_pred_score = clf.predict_proba(X_test)
    return y_pred, y_pred_score

def RFModel():
    clf = RandomForestClassifier(n_estimators=100)
    clf.fit(X_train, y_train)
    y_pred = clf.predict(X_test)
    y_pred_score = clf.predict_proba(X_test)
    return y_pred, y_pred_score

def main():
    app = Application()
    app.addmenu(MyMenu)
    app.mainloop()

if __name__ == '__main__':

    LoadAndPreprocess()
    #featureSelection()
    main()


from collections import Iterable, Callable
from statistics import mean

import numpy as np

from common.experiment import Example, TestCase
from common.tokens.string_tokens import Drop
from evaluation.experiment_procedure import extract_trans_tokens_from_domain_name, extract_bool_tokens_from_domain_name
from example_parser.parser import Parser
from example_parser.pixel_parser import PixelParser
from example_parser.robot_parser import RobotParser
from example_parser.string_parser import StringParser
from search.abstract_search import SearchAlgorithm

class ParameterTuning:

    def __init__(self,
                 domain: str,
                 files: (Iterable[int], Iterable[int], Iterable[int]),
                 repetitions: int,
                 search_cons: Callable[[float], SearchAlgorithm],
                 values: list[float],
                 debug: bool = False):
        self.search_cons = search_cons
        self.values = values
        self.repetitions = repetitions
        self.files = files
        self.debug = debug

        self.parser = self._get_parser(domain)
        self.test_cases = self._get_test_cases(files)
        self.env_tokens = set([c() for c in extract_trans_tokens_from_domain_name(domain)])
        self.bool_tokens = set([c() for c in extract_bool_tokens_from_domain_name(domain)])

    def run(self):
        for v in self.values:
            res = []
            for _ in range(self.repetitions):
                r = self._test_search(self.search_cons(v))
                res.append(r)

            res = self._process(res)
            res["value"] = v

            print(res)

    def _test_search(self, search: SearchAlgorithm) -> dict:
        total_cost = 0
        total_time = 0
        total_iterations = 0
        total_program_length = 0
        time_destroy = 0
        time_repair = 0
        time_cost = 0
        n_correct = 0
        n_failed = 0
        correct_cases = {}

        for tc in self.test_cases:
            r = search.run(tc.training_examples, self.env_tokens, self.bool_tokens)

            c = search.cost(tc.test_examples, r.dictionary["program"])

            total_time += r.dictionary["execution_time"]
            total_iterations += r.dictionary["iterations"]
            total_program_length += r.dictionary["program_length"]
            time_destroy += r.dictionary["time_destroy"]
            time_repair += r.dictionary["time_repair"]
            time_cost += r.dictionary["time_cost"]

            ca = tc.path_to_result_file.split("-")

            if c == 0:
                n_correct += 1

                if self.debug:
                    print("Solved {}-{}-{} with: {}".format(ca[1],ca[2],ca[3], r.dictionary["program"]))

                if ca[2] not in correct_cases:
                    correct_cases[ca[2]] = 1
                else:
                    correct_cases[ca[2]] += 1
            else:
                if self.debug:
                    print("Failed solving {}-{}-{}. Best found ({}): {}".format(ca[1],ca[2],ca[3], c.__round__(2), r.dictionary["program"]))
            if c == float('inf'):
                n_failed += 1
            else:
                total_cost += c

        size = len(self.test_cases)

        total_cost /= size
        total_time /= size
        total_iterations /= size
        total_program_length /= size
        time_destroy /= size
        time_repair /= size
        time_cost /= size
        n_correct /= size
        n_failed /= size

        return {
            "ave_cost": total_cost,
            "ave_exe_time": total_time,
            "ave_iterations": total_iterations,
            "ave_time_destroy": time_destroy,
            "ave_time_repair": time_repair,
            "ave_time_cost": time_cost,
            "per_correct": n_correct,
            "per_failed": n_failed,
            "average_program_length": total_program_length,
        }

    def _process(self, results: list[dict[str, float]]) -> dict[str, (float, float)]:
        res = {}

        for d in results:
            for k, v in d.items():
                if k not in res:
                    res[k] = []

                res[k].append(v)

        return {k: (mean(v).__round__(4), np.std(v).__round__(4)) for k, v in res.items()}

    def _get_test_cases(self, files: (Iterable[int], Iterable[int], Iterable[int])) -> list[TestCase]:
        res = []

        for i1 in files[0]:
            for i2 in files[1]:
                for i3 in files[2]:
                    res.append(self.parser.parse_file("{}-{}-{}.pl".format(i1, i2, i3)))

        return res

    @staticmethod
    def _get_parser(domain: str) -> Parser:
        if domain == "string":
            return StringParser()
        elif domain == "robot":
            return RobotParser()
        elif domain == "pixel":
            return PixelParser()
        else:
            raise Exception()


import pandas as pd
import numpy as np
import re

df1 = pd.read_excel("固定资产.xlsx", sheet_name=3)
df2 = df1.iloc[1:]
df3 = df2.drop(columns=['Unnamed: 16', 'Unnamed: 22', 'Unnamed: 23', 'Unnamed: 24'])
df3.columns = ['项目', '编号', 'NC入账时间', '完工日期', '资产名称/摘要', '原值', '残值率', '使用年限(年)',
       '使用年限(月)', '累计折旧', '净值', '净残值', '是否提足折旧', '是否在本年提足折旧', '期初累计折旧',
       '每月应折旧额', '本年折旧月份', '折旧月份(按完工日期）', '本年折旧', '差异']
df3["NC入账时间"] = pd.to_datetime(df3["NC入账时间"])
df3["完工日期"] = pd.to_datetime(df3["完工日期"])
df3 = df3[['项目', 'NC入账时间', '资产名称/摘要', '累计折旧', '完工日期',  '编号', '原值', '残值率', '使用年限(年)',
       '使用年限(月)', '净值', '净残值', '是否提足折旧', '是否在本年提足折旧', '期初累计折旧',
       '每月应折旧额', '本年折旧月份', '折旧月份(按完工日期）', '本年折旧', '差异']]
pat = "[A-Za-z0-9\u4E00-\u9FFF]+"
df3["特征码"] = df3["资产名称/摘要"].apply(lambda x: "".join(re.compile(pat).findall(x)))
df2018 = df3[["项目", "NC入账时间", "原值", "编号", "累计折旧", '资产名称/摘要']]
df2018 = df2018.rename(columns={"累计折旧": "2018累计折旧", '资产名称/摘要': '2018资产名称/摘要'})
df2018 = df2018.sort_values(["项目", "NC入账时间", "原值", "编号", '2018资产名称/摘要']).reset_index(drop=True)

def calc(x):
    df = x.reset_index(drop=True)
    return df[["2018累计折旧", "项目", "2018资产名称/摘要"]]

df2018a = df2018.groupby(["NC入账时间", "原值"]).apply(calc).reset_index()
df2018a = df2018a.rename(columns={"level_2": "索引号"})
# 组内予以升序编号; 但是运行偏慢;
# df2018.groupby(["NC入账时间", "原值"]).cumcount() is OK

df4 = pd.read_excel("固定资产.xlsx", sheet_name=4, header=1)
df4 = df4.drop(columns=['Excel名'])
df4 = df4.drop(columns=['Unnamed: 18', 'Unnamed: 0'])
df4 = df4.rename(columns={"本年折旧.1": "本年折旧"})

def calc(x):
    try:
        return pd.to_datetime(x)
    except:
        return np.nan

df4["NC入账时间"] = df4["NC入账时间"].apply(calc)
df4["完工日期"] = df4["完工日期"].apply(calc)
df4 = df4.iloc[:-1]

for i in range(len(df4)):
    if pd.isna(df4.loc[i, "资产名称/摘要"]):
        df4.loc[i, "资产名称/摘要"] = df4.loc[i, "编号"]

df4["特征码"] = df4["资产名称/摘要"].apply(lambda x: "".join(re.compile(pat).findall(x)))
df4 = df4[['项目', 'NC入账时间', '原值', '累计折旧', '编号', '完工日期', '资产名称/摘要',  '残值率', '使用年限(年)',
       '使用年限(月)',  '净值', '净残值', '是否提足折旧', '是否在本年提足折旧', '期初累计折旧',
       '每月应折旧额', '本年折旧月份', '折旧月份(按完工日期）', '本年折旧', '差异', ]]

df2019 = df4.copy()
df2019 = df2019.sort_values(["项目", "NC入账时间", "原值", "编号", "资产名称/摘要"]).reset_index(drop=True)

def calc(x):
    df = x.reset_index(drop=True)
    return df[["项目", '累计折旧', '编号', '完工日期', '资产名称/摘要', '残值率', '使用年限(年)',
       '使用年限(月)', '净值', '净残值', '是否提足折旧', '是否在本年提足折旧', '期初累计折旧',
       '每月应折旧额', '本年折旧月份', '折旧月份(按完工日期）', '本年折旧', '差异']]

df2019a = df2019.groupby(["NC入账时间", "原值"]).apply(calc).reset_index()
df2019a = df2019a.rename(columns={"level_2": "索引号"})
df2018a["原值"] = df2018a["原值"].apply(lambda x: round(x, 2))
df2019a["原值"] = df2019a["原值"].apply(lambda x: round(x, 2))

res = pd.merge(df2019a, df2018a, "left", on=["NC入账时间", "原值", "索引号"], indicator=True)
res = res.rename(columns={"_merge": "合并状态"})
res[["累计折旧", "2018累计折旧"]] = res[["累计折旧", "2018累计折旧"]].applymap(lambda x: round(x, 2))
res = res.rename(columns={"项目_x":"2019项目名称", "项目_y": "2018项目名称"})
res = res.sort_values(["2019项目名称", "NC入账时间", "原值", "索引号"])
res = res[['2019项目名称', 'NC入账时间', '原值', '索引号', '累计折旧', '编号', '完工日期', '资产名称/摘要',
       '残值率', '使用年限(年)', '使用年限(月)', '净值', '净残值', '是否提足折旧', '是否在本年提足折旧',
       '期初累计折旧', '每月应折旧额', '本年折旧月份', '折旧月份(按完工日期）', '本年折旧', '差异', '2018累计折旧', '2018项目名称',
       '2018资产名称/摘要', '合并状态']]
res = res.reset_index(drop=True)
res.to_csv("合并结果.csv", index=False, encoding="gbk")


import socket
import sys
import hashlib

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

server_address = ('localhost', 10002)
print >>sys.stderr, 'starting up on %s port %s' % server_address
sock.bind(server_address)

f = open('udpFile', 'w')

def compute_sha256(data):
    m = hashlib.sha256()
    m.update(data)
    return m.hexdigest()

def compute_md5(data):
    m = hashlib.md5()
    m.update(data)
    return m.hexdigest()

while True:
    print >>sys.stderr, '\nwaiting to receive message'
    data, address = sock.recvfrom(4096)

    x = ('received %s bytes from %s' % (len(data), address))
    f.write(str(x))
    f.write('\n')

    x = ('sha256 ', compute_sha256(data))
    f.write(str(x))
    f.write('\n')

    x = ('md5 ', compute_md5(data))
    f.write(str(x))
    f.write('\n')

    print >>sys.stderr, 'received %s bytes from %s' % (len(data), address)
    print >>sys.stderr, data


def is_black_image(img_inst):
    """:return: True if the image is completely black"""
    img_width, img_height = img_inst.size

    for x in xrange(img_width):
        for y in xrange(img_height):
            # 0 means black color
            if img_inst.getpixel((x, y)) != 0:
                return False

    return True


import numpy as np

# wywolanie Tinter = inter(wsp_wezl za xy , cells za def_kom, T za T)
# interpolacja na wezly siatki z centrow komorek

def inter(xy, def_kom, T):
    Tn = np.zeros(len(xy))                 # tyle ile punktow wezlow siatki
    d = np.zeros_like(Tn)
    kom_wez = [list() for i in xy]         # tyle ile pkt wezl siatki ale lista list

    for cid, kom in enumerate(def_kom):     # def_kom czyli cells [ 0 1 12 11] itd.
        for w in kom:                       # dla kazdej komorki
            kom_wez[w].append(cid)          # do kom_wez[odp wezlowi siatki] dodaj numer komorki
    for wid, kom in enumerate(kom_wez):
        wxy = xy[wid]                       # pobierz wsp punktu siatki (meszu) w ktorej interpoluje temp
        for c in kom:
            cw = def_kom[c]                  # wezly c1 [0, 1, 12, 11]
            cxy = xy[cw]                     # wsp. wezl dla komorki xy[ [0, 1, 12, 11] ]
            csr = sum(cxy) / len(cxy)        # z nich sr komorki jako suma wsp/ ilosc ws
            delta = wxy - csr                # wsp wektora od sr_kom do
            dist = np.sqrt(np.dot(delta, delta))    # dlugosc tego wektora
            # mam juz wartosc temp w sr kom T[c] i mam odl do punktu siatki w ktorym interp temp
            Tn[wid] += 1./dist * T[c]       # wartosc temp w tym pkt. to
            d[wid] += 1./dist

    Tn = Tn / d
    return Tn


#!/usr/bin/python3

import argparse
import os
import re
import pandas as pd
from bokeh.plotting import figure, output_file, show
from bokeh.models import Legend
from bokeh.colors import named
from bokeh.io import export_png
from bokeh.io import export_svgs

parser = argparse.ArgumentParser(description = "Creates an HTML file containing the plot of waves defined by the input file in text table format.")
parser.add_argument("-i", "--input_file", type = str, dest = "wave_input_file", required = True, help = "Specifies the input waveform file in text table format.")
parser.add_argument("-o", "--output_file", type = str, dest = "wave_output_file", help = "Specifies the output plot file.")
parser.add_argument("-hi", "--header_index", type = int, dest = "header_index", default = 1, help = "Specifies the line at which the data starts. Default = line 1.")
parser.add_argument("-t", "--title", type = str, dest = "title", help = "Specifies the output plot title.")
parser.add_argument("-xl", "--x_label", type = str, dest = "x_axis_label", help = "Specifies the label for the x axis.")
parser.add_argument("-yl", "--y_label", type = str, dest = "y_axis_label", help = "Specifies the label for the y axis.")
parser.add_argument("-dp", "--show_data_points", action = "store_true", default = False, help = "Show data point over the plot-line.")
parser.add_argument("-lw", "--line_width", type = int, dest = "line_width", choices = range(1,7), default = 1, help = "Specifies the data line width. Affects all the lines.")
parser.add_argument("--x_axis_log", action = "store_true", default = False, help = "Changes the x axis to log scale.")
parser.add_argument("--y_axis_log", action = "store_true", default = False, help = "Changes the y axis to log scale.")
parser.add_argument("-pm", "--presentation_mode", action = "store_true", default = False, help = "Shows the legend for the different curves inside the plotting area.")
parser.add_argument("--save_svg", action = "store_true", default = False, help = "Saves the plot in a svg file.")
parser.add_argument("--save_png", action = "store_true", default = False, help = "Saves the plot in a png file.")
parser.add_argument("--no_output", action = "store_true", default = False, help = "Does not create the HTML output file and does not open the browser to show it.")
args = parser.parse_args()

# Data configutation section ##################################################

wave_input_file = args.wave_input_file

if (args.wave_output_file == None):
    wave_output_file = wave_input_file
else:
    wave_output_file = args.wave_output_file

# Plot configuration section ##################################################

if (args.title == None):
    _, plot_title = os.path.split(args.wave_input_file)
else:
    plot_title = args.title

line_width = args.line_width

if (args.x_axis_log):
    x_axis_type = "log"
else:
    x_axis_type = "linear"

if (args.y_axis_log):
    y_axis_type = "log"
else:
    y_axis_type = "linear"

x_axis_label = args.x_axis_label
y_axis_label = args.y_axis_label

#colors = [name for name in named.__all__]
colors = ["red", "blue", "green", "yellow", "purple", "black"]

###############################################################################

# Example of a text table
# #format table ## [Custom WaveView] saved 14:46:01 Sat Oct  6 2018
# XVAL gm/id_long_L_6_:_dc id_long_6
#  0.000E+00  1.986E+01 -0.000E+00

table = pd.read_csv(wave_input_file, header = args.header_index, sep = "\s+")

output_file(wave_output_file + ".html")
p = figure(title = plot_title, x_axis_label = x_axis_label, y_axis_label = y_axis_label, x_axis_type = x_axis_type, y_axis_type = y_axis_type, toolbar_location = "above")

legends = []

for signal, data_color in zip(table.columns[1::], colors):
    if (args.show_data_points):
        p.circle(table[table.columns[0]], table[signal], color = data_color, alpha = 0.4, muted_color = data_color, muted_alpha = 0.2)

    if (args.presentation_mode):
        obj = p.line(table[table.columns[0]], table[signal], legend = signal, line_width = line_width, color = data_color, muted_color = data_color, muted_alpha = 0.1)
    else:
        obj = p.line(table[table.columns[0]], table[signal], line_width = line_width, color = data_color, muted_color = data_color, muted_alpha = 0.1)
        legends.append((signal, [obj]))

legend = Legend(items=legends, location=(10, 0))
legend.click_policy = "mute"
p.add_layout(legend, 'right')
p.legend.background_fill_alpha = 1

p.left[0].formatter.use_scientific = False
p.below[0].formatter.use_scientific = False

if (args.save_png):
    p.toolbar_location = None
    export_png(p, filename = wave_output_file + ".png")
    p.toolbar_location = "above"
if (args.save_svg):
    p.output_backend = "svg"
    export_svgs(p, filename = wave_output_file + ".svg")
if (not args.no_output):
    show(p)


from tag import Tag

def add_tags(category, kvp):
    with category.make_mutable():
        for (k, v) in kvp.items():
            category._add_new_enum_value(k, v)

func_tags = {
    'attractor_charms': 2262496390,
    'attractor_potions': 3858182614,
    'attractor_herbology': 4250065225,
    'attractor_datda': 3706829272
}

add_tags(Tag, func_tags)


from django import template

from explore.models import saved_item

register = template.Library()

@register.simple_tag(name='is_item_already_saved')
def is_item_already_saved(item, user):
    applied = saved_item.objects.filter(item=item, user=user)
    if applied:
        return True
    else:
        return False


# import flask dependencies
from flask import Flask, request, make_response, jsonify, Response

# initialize the flask app
app = Flask(__name__)

# default route
@app.route('/callback', methods=['POST'])
def index():
    print(request.json)
    data = request.json['challenge']
    print(data)
    return make_response(data, 201)

if __name__ == "__main__":
    # Flask must run on 443 and on HTTPS as per requirement from Twitch
    app.run(ssl_context='adhoc', debug=True, port=443)


# coding=utf-8

""" Batch module """

import ee
from . import alerts, utils
import requests
import os
from geetools import batch as gbatch

FUNCTIONS = {
    'probable': alerts.get_probable,
    'confirmed': alerts.get_confirmed,
    'both': alerts.oneday,
    'period': alerts.period
}

def mask(image, vector, raster):
    """ Mask out a vector mask or a raster mask """
    if vector:
        return image.clip(vector)
    elif raster:
        return image.updateMask(raster)
    else:
        return image

def downloadFile(url, name, ext, path=None):
    """ Download a file from a given url

    :param url: full url
    :type url: str
    :param name: name for the file (can contain a path)
    :type name: str
    :param ext: extension for the file
    :type ext: str
    :return: the created file (closed)
    :rtype: file
    """
    response = requests.get(url, stream=True)
    code = response.status_code

    if path is None:
        path = os.getcwd()

    path = os.path.join(path, name)

    while code != 200:
        if code == 400:
            return None
        response = requests.get(url, stream=True)
        code = response.status_code
        size = response.headers.get('content-length', 0)
        if size: print('size:', size)

    filename = '{}.{}'.format(path, ext)

    with open(filename, "wb") as handle:
        for data in response.iter_content():
            handle.write(data)

    return handle

def _download(vector, name, extension='JSON', path=None, verbose=True,
              logger=None):
    if extension in ['JSON', 'json', 'geojson', 'geoJSON']:
        try:
            gbatch.Download.table.toGeoJSON(vector, name, path)
        except Exception as e:
            msg = 'Download method failed: {} \n\ntrying another method...'.format(e)
            if verbose:
                print(msg)
            if logger:
                logger.log(msg)
            try:
                gbatch.Download.table.toLocal(vector, name, 'geojson',
                                              path=path)
            except Exception as e:
                msg = "Download failed: {}".format(e)
                if verbose:
                    print(msg)
                if logger:
                    logger.log(msg)
    else:
        print('Format {} not supported'.format(extension))

def _toDrive(vector, filename, folder, extension, **kwargs):
    verbose = kwargs.get('verbose', False)
    logger = kwargs.get('logger', None)

    try:
        task = ee.batch.Export.table.toDrive(vector, filename,
                                             folder, filename,
                                             extension)
        task.start()
        msg = 'uploading {} to {} in GDrive'.format(filename, folder)
        if verbose:
            print(msg)
        if logger:
            logger.log(msg)

    except Exception as e:
        msg = 'ERROR writing {} - {}'.format(filename, e)
        if verbose:
            print(msg)
        if logger:
            logger.log(msg)

def _toAsset(vector, filename, folder, **kwargs):
    verbose = kwargs.get('verbose', False)
    logger = kwargs.get('logger', None)

    user = ee.data.getAssetRoots()[0]['id']
    path = '{}/{}'.format(user, folder)

    assetId = '{}/{}'.format(path, filename)

    try:
        # task = ee.batch.Export.table.toAsset(vector, filename, assetId)
        # task.start()
        gbatch.Export.table.toAsset(vector, path, filename)
        msg = 'uploading {} to {} in Assets'.format(filename, path)
        if verbose:
            print(msg)
        if logger:
            logger.log(msg)

    except Exception as e:
        msg = 'ERROR in {} to {} in Assets - {}'.format(filename, path, e)
        if verbose:
            print(msg)
        if logger:
            logger.log(msg)

def _toLocal(vector, filename, folder=None, extension='geojson',
             subfolders=True, subname=None, **kwargs):

    verbose = kwargs.get('verbose', True)
    logger = kwargs.get('logger', None)

    # MANAGE ALERTS PATH
    if folder is None:
        folder = os.path.join(os.getcwd(), 'alerts')

    # make path if not present
    if not os.path.isdir(folder):
        if verbose:
            print('creating {} folder'.format(folder))
        os.mkdir(folder)

    if subfolders:
        subpath = os.path.join(folder, subname)
        if not os.path.isdir(subpath):
            if verbose:
                print('creating {}'.format(subpath))
            os.mkdir(subpath)
    else:
        subpath = folder

    msg = '{}: Downloading "{}" to "{}"'.format(subname, filename, subpath)
    if verbose:
        print(msg)
    if logger:
        logger.log(msg)

    try:
        _download(vector, filename, extension, subpath)
    except Exception as e:
        msg = '{}: ERROR writing {}'.format(subname, filename)
        if logger:
            logger.log(msg)
    else:
        msg = '{}: "{}" downloaded to "{}"'.format(subname, filename, subpath)
        if logger:
            logger.log(msg)

def _are_alerts(alert, name, date, clas, region, verbose, logger):
    try:
        count = utils.histogram(alert, clas, region).getInfo()
    except Exception as e:
        msg = '{}: ERROR getting histogram - {}'.format(name, e)
        if logger:
            logger.log(msg)
        return False

    if count == 0:
        msg = '{}: no alerts for {}'.format(name, date)
        if verbose:
            print(msg)
        if logger:
            logger.log(msg)
        return False
    else:
        return True

def _process_period(start, end, geometry, limit, year=None,
                    eightConnected=False, useProxy=False, mask=None,
                    destination='local', name=None, folder=None, **kwargs):
    verbose = kwargs.get('verbose', True)
    logger = kwargs.get('logger', None)

    try:
        alert = FUNCTIONS['period'](start, end, geometry, limit, year,
                                    eightConnected, useProxy, mask)
    except Exception as e:
        msg = 'ERROR while getting period alert {} to {}'.format(start, end)
        if verbose:
            print(msg)
        if logger:
            logger.log(msg)
        raise e

    date_str = '{} to {}'.format(start, end)

    are_alerts = _are_alerts(alert, name, date_str, 'both', geometry, **kwargs)
    if not are_alerts:
        return None

    filename = '{}_{}_to_{}'.format(name, start, end)

    vector = utils.make_alerts_vector(alert, geometry)
    # LOCAL
    if destination == 'local':
        subfolders = kwargs.get('subfolders', True)
        ext = kwargs.get('extension', 'geojson')
        _toLocal(vector, filename, folder, ext, subfolders,
                 name, **kwargs)

    elif destination == 'drive':
        filename = filename.encode().decode('ascii', errors='ignore')
        ext = kwargs.get('extension', 'geojson')
        _toDrive(vector, filename, folder, ext, **kwargs)

    elif destination == 'asset':
        _toAsset(vector, filename, folder, **kwargs)

def _process(geometry, date, clas, limit, folder, raster_mask, destination,
             filename,  name, **kwargs):
    verbose = kwargs.get('verbose', True)
    logger = kwargs.get('logger', None)

    try:
        alert = FUNCTIONS[clas](geometry, date, limit, mask=raster_mask)
    except Exception as e:
        msg = 'ERROR while getting alert for {}'.format(date)
        if verbose:
            print(msg)
        if logger:
            logger.log(msg)
        raise e

    # SKIP IF EMPTY ALERT
    are_alerts = _are_alerts(alert, name, date, clas, geometry, **kwargs)
    if not are_alerts:
        return None

    vector = utils.make_alerts_vector(alert, geometry)
    # LOCAL
    if destination == 'local':
        subfolders = kwargs.get('subfolders', True)
        ext = kwargs.get('extension', 'geojson')
        _toLocal(vector, filename, folder, ext, subfolders,
                 name, **kwargs)

    elif destination == 'drive':
        filename = filename.encode().decode('ascii', errors='ignore')
        ext = kwargs.get('extension', 'geojson')
        _toDrive(vector, filename, folder, ext, **kwargs)

    elif destination == 'asset':
        _toAsset(vector, filename, folder, **kwargs)

def period(site, start, end, limit, year=None, proxy=False, eightConnected=False,
           folder=None, property_name=None, raster_mask=None,
           destination='local', verbose=True, logger=None):
    """ General download function for a period """

    args = dict(verbose=verbose, logger=logger)

    # START PROCESS
    # If it is a FeatureCollection and there is a property name
    if isinstance(site, ee.FeatureCollection) and property_name:
        names = utils.get_options(site, property_name)
        names_cli = names.getInfo()
        for name in names_cli:

            geom = site.filterMetadata(
                property_name, 'equals', name).first().geometry()

            _process_period(start, end, geom, limit, year, eightConnected,
                            proxy, raster_mask, destination, name, folder,
                            **args)
    else:
        if isinstance(site, ee.Feature) and property_name:
            name = ee.String(site.get(property_name)).getInfo()
        else:
            name = 'N/A'

        # GET GEOMETRY
        if isinstance(site, (ee.FeatureCollection, ee.Feature)):
            geom = site.geometry()
        else:
            geom = site

        _process_period(start, end, geom, limit, year, eightConnected,
                        proxy, raster_mask, destination, name, folder,
                        **args)

def download(site, date, clas, limit, folder=None, property_name=None,
             raster_mask=None, destination='local', verbose=True, logger=None):
    """ General download function """
    if not utils.has_image(date, alerts.ALERTS).getInfo():
        msg = 'GLAD alerts not available for date {}'.format(date)
        if logger:
            logger.log(msg)
        return None

    if clas not in ['probable', 'confirmed', 'both']:
        clas = 'both'

    # BASE NAME FOR OUTPUT FILE
    if clas == 'both':
        basename = 'alerts_for'
    else:
        basename = '{}_alerts_for'.format(clas)

    args = dict(verbose=verbose, logger=logger)

    # START PROCESS
    # If it is a FeatureCollection and there is a property name
    if isinstance(site, ee.FeatureCollection) and property_name:
        names = utils.get_options(site, property_name)
        names_cli = names.getInfo()
        for name in names_cli:
            filename = '{}_{}_{}'.format(basename, date, name)

            geom = site.filterMetadata(
                property_name, 'equals', name).first().geometry()

            _process(geom, date, clas, limit, folder, raster_mask, destination,
                     filename,  name, **args)
    else:
        if isinstance(site, ee.Feature) and property_name:
            name = ee.String(site.get(property_name)).getInfo()
            filename = '{}_{}_{}'.format(basename, date, name)
        else:
            name = 'N/A'
            filename = '{}_{}'.format(basename, date)

        # GET GEOMETRY
        if isinstance(site, (ee.FeatureCollection, ee.Feature)):
            geom = site.geometry()
        else:
            geom = site

        _process(geom, date, clas, limit, folder, raster_mask, destination,
                 filename,  name, **args)


from flask_restful import Resource, reqparse
from models.Rproducts import Rproducts

class Registerrentalproducts(Resource):

	def post(self):
		parser = reqparse.RequestParser()
		parser.add_argument('rproductname',
			type=str,
			required=True,
			help="This field cannot be left blank!"
			)
		parser.add_argument('rprice',
			type=str,
			required=True,
			help="This field cannot be left blank!"
			)
		parser.add_argument('rquantity',
			type=str,
			required=True,
			help="This field cannot be left blank!"
			)
		data = parser.parse_args()

		new_rproducts = Rproducts(
			rproductname=data.rproductname,
			rprice=data.rprice,
			rquantity=data.rquantity
			)
		new_rproducts.insert()
		return {'message':'Product Registered!'}


from __future__ import annotations
from abc import ABC , abstractmethod
from typing import List

class Strategy(ABC):

    @abstractmethod
    def doAlgorithm(self , data: List):
        pass

class Context():

    def __init__(self , strategy : Strategy)-> None:

        self._strategy = strategy

    @property
    def strategy(self) -> Strategy:

        return self._strategy

    @strategy.setter
    def strategy(self , strategy: Strategy) -> None:

        self._strategy = strategy

    def doSomeBusinessLogic(self) -> None:

        print(" CONTEXT : SORTING DATA USING STRATEGY")

        resultado = self.strategy.doAlgorithm(["BRASIL","ARGENTINA","VENEZUELA" , "URUGAUAI","PARAGUAI","CHILE", "COLOMBIA", "BOLIVIA", "PERU","EQUADOR","GUIANA FRANCESA","SURINAME","GUIANA" ])
        print(" - ".join(resultado))

class ConcreteStrategyA(Strategy):

    def doAlgorithm(self, data: List):
        return sorted(data)

class ConcreteStrategyB(Strategy):

    def doAlgorithm(self, data: List):
        return reversed(sorted(data))

if __name__ == "__main__":

    print("CLIENTE : STRATEGY IS SET TO NORMAL SORTING \n")
    context = Context(ConcreteStrategyA())
    context.doSomeBusinessLogic()
    print("\n")

    print("CLIENTE : STRATEGY IS SET TO REVERSED SORTING \n")
    context = Context(ConcreteStrategyB())
    context.doSomeBusinessLogic()
    print("\n")


import requests, time
from bs4 import BeautifulSoup

# 要爬的網址
allurl = ['https://finance.yahoo.com/quote/%5ESOX/history?p=%5ESOX',
          'https://finance.yahoo.com/quote/%5EIXIC/history?p=%5EIXIC',
          'https://finance.yahoo.com/quote/%5EGSPC/history?p=%5EGSPC',
          'https://finance.yahoo.com/quote/%5EDJI/history?p=%5EDJI']

# 爬蟲設定
ss = requests.session()
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'}

for url in allurl:
    res = ss.get(url=url, headers=headers)
    soup = BeautifulSoup(res.text, 'html.parser')

    # 名稱
    title = soup.select('div[class="D(ib)"]')[0].text.split('^')[1].split(')')[0]
    # 日期
    content = soup.select('tr[class="BdT Bdc($seperatorColor) Ta(end) Fz(s) Whs(nw)"]')[0]
    Date_before = content.select('td[class="Py(10px) Ta(start) Pend(10px)"]')[0].text
    # 轉換時間格式
    Date_change = time.strptime(Date_before, "%b %d, %Y")
    Date = time.strftime("%Y-%m-%d", Date_change)
    # 開盤
    Open = content.select('td[class="Py(10px) Pstart(10px)"]')[0].text
    # 最高
    High = content.select('td[class="Py(10px) Pstart(10px)"]')[1].text
    # 最低
    Low = content.select('td[class="Py(10px) Pstart(10px)"]')[2].text
    # 收盤
    Close = content.select('td[class="Py(10px) Pstart(10px)"]')[3].text
    # 漲跌
    content2 = soup.select('div[class="D(ib) Mend(20px)"]')[0]
    PriceChange = content2.select('span')[1].text.split(' ')[0]
    # 漲跌幅
    PerChange = content2.select('span')[1].text.split('(')[1].split('%')[0]
    print('title:', title)
    print('Date:', Date)
    print('Open:', Open)
    print('High:', High)
    print('Low:', Low)
    print('Close:', Close)
    print('PriceChange:', PriceChange)
    print('PerChange:', PerChange)