import datetime
import os
import shutil
from asyncio import constants
from glob import glob

import matplotlib.cm as cm
import matplotlib.colors as colors
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import plotly as py
import plotly.express as px
import plotly.graph_objects as go
import plotly.io as pio
from matplotlib.axis import YAxis
from matplotlib.colors import Normalize
from mpl_toolkits.mplot3d import Axes3D
from plotly.subplots import make_subplots

from plot_set import fig_init, fig_init_horizon_bar, fig_output, x_axis_scale

def get_latest_modified_file_path(dirname):
    target = os.path.join(dirname, "*")
    files = [(f, os.path.getmtime(f)) for f in glob(target)]
    latest_modified_file_path = sorted(files, key=lambda files: files[1])[-1]
    return latest_modified_file_path[0]

copy_base_dir = "G:/マイドライブ/Documents/University/lab/Research/FFGNSS/plot_result/"

# ここを設定
SEPARATION = 0
ISS = 0
IAR = 0
CALIBRATION = 0
RECEIVER = 0
FILTER = 0
PCV_METHOD = 0
COST_ACCURACY = 0
PCO = 0
REL_POS_BIAS = 0
ORBITS = 0
PCC_ERR = 1

log_base = copy_base_dir
separation_files = [
    "20230124_163016_100m",
    "20230124_165001_500m",
    "20230124_100149_1km",
    "20230124_161620_2km",
    "20230128_001743_3km",
    "20230124_170120_10km",  # 一つ抜けているのでなくしていいかも
    # "w_PCCerror/20230128_094542_100m_after_PCC",
    # "w_PCCerror/20230129_130455_500m_after_PCC",
    # "w_PCCerror/20230127_170520_WLS_PCC1cycle_1km",
    # "w_PCCerror/20230129_123418_2km_after_PCC",
    # "w_PCCerror/20230127_233258_3km_afterPCCestimation",
    # # "20230124_170120_10km",  # 一つ抜けているのでなくしていいかも
]
ISS_separation_files = [
    # "20230124_230233_WLS_postPCV_ISS_sep100m",
    # "20230124_232716_WLS_postPCV_ISS_sep500m",
    # "20230128_000212_ISS_900m_postPCO",
    # "20230130_134830_WLS_PCC1cycle1km_wo_PCO_horizon",
    "wo_PCC_estimation/20230129_142557_100m",
    "wo_PCC_estimation/20230129_144719_500m",
    "wo_PCC_estimation/20230129_140414_900m",
    # "wo_PCC_estimation/20230130_140933_wo_PCC_1km",
]
IAR_files = ["20230124_105907_wo_IAR_wo_PCCerror", "20230124_100149_w_IAR_wo_PCCerror"]
PCC_calibration_files = [
    "20230124_100149_w_IAR_wo_PCCerror",
    "20230126_160837_PCC1cycle_wo_PCC_error",
    # "20230123_110838_PCC_2cycle_1km",
]
receiver_files = [
    "20230123_081904_PCC1cycle_1km_Phoenix",
    "20230123_212716_PCC1cycle_OEM",
    "20230123_231352_PCC1cycle_SILVIA",
    "20230124_002738_PCC1cycle_TsinhuaSat",
]
filter_files = ["20230125_182712_EKF_w_IAR_w_PCCerror", "20230124_103810_AEKF_w_IAR_w_PCCerror"]
pcv_method_files = [
    "20230127_163104_wo_estimation",
    "20230127_170520_WLS_PCC1cycle",
    "20230127_171952_RES_PCC1cycle",
]
orbits_csv_files = ["dr_accuracies_all_SSO_wo2km.csv", "dr_accuracies_all_ISS.csv"]
cost_accuracy_files = [
    # "20230131_191315_WLS_10_PCC1cycle",
    # "20230130_145307_WLS_20_PCC1cycle",
    # "20230127_170520_WLS_40_PCC1cycle",
    # "20230130_150824_WLS_80_PCC1cycle",
    # "Residual/20230126_010656_RES_after2560",
    # "Residual/20230130_192307_RES_after4030",
    # "Residual/20230126_003114_RES_after_6970",
    "Residual/20230131_104331_RES_90deg_10800_after",
    "Residual/20230131_170713_RES_45deg_PCC1cycle",
    "Residual/20230131_174452_RES_30deg_PCC1cycle",
    "Residual/20230131_134355_RES_PCC1cycle_10800_15deg",
]
pco_files = [
    "20230127_163104_wo_estimation",
    "20230129_170121_only_PCO",
    "20230129_171707_only_PCO_rotate",
]
rel_pos_bias_files = [
    # "20230107_201550_after_PCV_WLS_w_rel_pos_bias_1cm_z",
    # "20230107_173154_after_PCV_WLS_w_rel_pos_bias_1cm_x",
    # "20230107_194024_after_PCV_WLS_w_rel_pos_bias_1cm_y",
    "20230107_204525_after_PCV_RES_w_rel_pos_bias_1cm_z",
    "20230107_174958_after_PCV_RES_w_rel_pos_bias_1cm_x",
    "20230107_195426_after_PCV_RES_w_rel_pos_bias_1cm_y",
]
rel_pos_bias_csv_files = ["accuracies_mean.csv", "accuracies_std.csv"]
pcc_error_files = [
    "20230316_212013_wo_calibration",
    "20230314_201311_true_PCC_wo_calibration",
]

if SEPARATION:
    log_base += "202301_thesis_separation/"
    files = separation_files
    legend_names = ["100m", "500m", "1km", "2km", "3km", "10km"]
elif ISS:
    log_base += "202301_thesis_ISS/"
    files = ISS_separation_files
    legend_names = ["100m", "500m", "900m"]
    # legend_names = ["w/o PCC estimation", "w/ PCC estimation"]
elif IAR:
    log_base += "202301_thesis_IAR/"
    files = IAR_files
    legend_names = ["w/o IAR", "w/ IAR"]
elif CALIBRATION:
    log_base += "202301_thesis_PCC_error_wo_PCCestimation/"
    files = PCC_calibration_files
    legend_names = ["w/o calibration", "1 cycle", "2 cycle"]
elif RECEIVER:
    log_base += "202301_thesis_receiver_performance/"
    files = receiver_files
    legend_names = ["Phoenix", "OEM", "NGPSR", "Tsinghua"]
elif FILTER:
    log_base += "202301_thesis_AKF/"
    files = filter_files
    legend_names = ["EKF", "AEKF"]
elif PCV_METHOD:
    log_base += "202301_thesis_1km_base_results/"
    files = pcv_method_files
    legend_names = ["w/o calibration", "Model", "Residual"]
elif ORBITS:
    log_base += "202301_thesis_orbits/"
    files = orbits_csv_files
    legend_names = [["100m", "500m", "1km", "3km"], ["100m", "500m", "900m"]]
    subplot_names = ["SSO", "ISS"]
elif COST_ACCURACY:
    log_base += "202301_thesis_computational_cost_accuracy/"
    files = cost_accuracy_files
    legend_names = ["900", "1800", "3600", "7200"]  # matrix size
    # legend_names = ["2560s", "4030s", "6970s"]  # residual time
    legend_names = ["90deg", "45deg", "30deg", "15deg"]  # residual bin size
elif PCO:
    log_base += "202301_thesis_PCO/"
    files = pco_files
    legend_names = ["w/o PCO estimation", "along-track: north", "along-track: east"]  # matrix size
elif REL_POS_BIAS:
    # log_base += "202301_thesis_relpos_performance/bias/"
    log_base += "20230130_220120_rel_pos_bias_RES/"
    files = rel_pos_bias_csv_files  # rel_pos_bias_files
    legend_names = ["radial", "tangential", "normal"]
    subplot_names = ["mean", "std"]
elif PCC_ERR:
    # log_base += "202301_thesis_PCO/"
    files = pcc_error_files
    legend_names = ["w/ error", "w/o error"]
else:
    print("false input!")
    abort()

log_bases = [log_base + each_dir + "/" for each_dir in files]  # fileを設定

output_path = "figure/"
os.makedirs(output_path, exist_ok=True)
dt_now = datetime.datetime.now()
copy_dir = copy_base_dir + dt_now.strftime("%Y%m%d_%H%M%S") + "/"
os.makedirs(copy_dir)
# shutil.copytree(s2e_log_dir, copy_dir, ignore=shutil.ignore_patterns("figure"))
accuracy_file = copy_dir + "accuracies.csv"

# accuracy_log = pd.DataFrame(columns=["name", "axis", "unit", "value"])  # ここに計算した精度を入れていく．
accuracy_log = pd.DataFrame(
    columns=["legend", "name", "axis", "unit", "mean", "std", "rms"]
)  # ここに計算した精度を入れていく．

# この二つはどっかからとってきたいな．
REDUCE_DYNAMIC = 1
GNSS_CH_NUM = 15
# SVG_ENABLE = 1
# PCV = 0
data_offset = 1000  # s 6580(WLS)
x_axis_scale = 1.0 / 3600  # sec -> hour

# true information
col_true_info = [
    "x_m_t",
    "y_m_t",
    "z_m_t",
    "t_m_t",
    "vx_m_t",
    "vy_m_t",
    "vz_m_t",
    "x_t_t",
    "y_t_t",
    "z_t_t",
    "t_t_t",
    "vx_t_t",
    "vy_t_t",
    "vz_t_t",
]
col_est_info = [
    "x_m_e",
    "y_m_e",
    "z_m_e",
    "t_m_e",
    "vx_m_e",
    "vy_m_e",
    "vz_m_e",
    "ar_m_e",
    "at_m_e",
    "an_m_e",
    "x_t_e",
    "y_t_e",
    "z_t_e",
    "t_t_e",
    "vx_t_e",
    "vy_t_e",
    "vz_t_e",
    "ar_t_e",
    "at_t_e",
    "an_t_e",
]
col_residual = [
    "res_pos_R_m",
    "res_pos_T_m",
    "res_pos_N_m",
    "res_vel_R_m",
    "res_vel_T_m",
    "res_vel_N_m",
    "res_pos_R_t",
    "res_pos_T_t",
    "res_pos_N_t",
    "res_vel_R_t",
    "res_vel_T_t",
    "res_vel_N_t",
]
col_ambiguity_main = ["N" + str(i + 1) + "_m_t" for i in range(GNSS_CH_NUM)] + [
    "N" + str(i + 1) + "_m_e" for i in range(GNSS_CH_NUM)
]
col_ambiguity_target = ["N" + str(i + 1) + "_t_t" for i in range(GNSS_CH_NUM)] + [
    "N" + str(i + 1) + "_t_e" for i in range(GNSS_CH_NUM)
]
col_ambiguity = col_ambiguity_main + col_ambiguity_target

col_MN_main = ["MN" + str(i + 1) + "_m" for i in range(GNSS_CH_NUM)]
col_MN_target = ["MN" + str(i + 1) + "_t" for i in range(GNSS_CH_NUM)]

col_M = (
    ["Mx_m", "My_m", "Mz_m", "Mt_m", "Mvx_m", "Mvy_m", "Mvz_m", "Mar_m", "Mat_m", "Man_m"]
    + col_MN_main
    + ["Mx_t", "My_t", "Mz_t", "Mt_t", "Mvx_t", "Mvy_t", "Mvz_t", "Mar_t", "Mat_t", "Man_t"]
    + col_MN_target
    + [
        "Mrr_m",
        "Mrt_m",
        "Mrn_m",
        "Mvr_m",
        "Mvt_m",
        "Mvn_m",
        "Mrr_t",
        "Mrt_t",
        "Mrn_t",
        "Mvr_t",
        "Mvt_t",
        "Mvn_t",
    ]
)

col_gnss_dir_main = ["azi" + str(i + 1) + "_m" for i in range(GNSS_CH_NUM)] + [
    "ele" + str(i + 1) + "_m" for i in range(GNSS_CH_NUM)
]
col_gnss_dir_target = ["azi" + str(i + 1) + "_t" for i in range(GNSS_CH_NUM)] + [
    "ele" + str(i + 1) + "_t" for i in range(GNSS_CH_NUM)
]
col_gnss_dir = col_gnss_dir_main + col_gnss_dir_target

col_pco = ["pco_x_m", "pco_y_m", "pco_z_m", "pco_x_t", "pco_y_t", "pco_z_t"]
col_ambiguity_flag = ["N" + str(i + 1) + "_m" for i in range(GNSS_CH_NUM)] + [
    "N" + str(i + 1) + "_t" for i in range(GNSS_CH_NUM)
]

data_col = (
    col_true_info
    + col_est_info
    + col_residual
    + col_ambiguity
    + col_M
    + ["sat_num_main", "sat_num_target", "sat_num_common"]
    + ["id_ch" + str(i + 1) + "_m" for i in range(GNSS_CH_NUM)]
    + ["id_ch" + str(i + 1) + "_t" for i in range(GNSS_CH_NUM)]
    + ["Qx_m", "Qy_m", "Qz_m", "Qt_m", "Qvx_m", "Qvy_m", "Qvz_m", "Qar_m", "Qat_m", "Qan_m"]
    + ["QN" + str(i + 1) + "_m" for i in range(GNSS_CH_NUM)]
    + ["Qx_t", "Qy_t", "Qz_t", "Qt_t", "Qvx_t", "Qvy_t", "Qvz_t", "Qar_t", "Qat_t", "Qan_t"]
    + ["QN" + str(i + 1) + "_t" for i in range(GNSS_CH_NUM)]
    + ["Rgr" + str(i + 1) + "_m" for i in range(GNSS_CH_NUM)]
    + ["Rgr" + str(i + 1) + "_t" for i in range(GNSS_CH_NUM)]
    + ["Rcp" + str(i + 1) for i in range(GNSS_CH_NUM)]
    + [
        "ax_m",
        "ay_m",
        "az_m",
        "ax_t",
        "ay_t",
        "az_t",
        "ax_dist_m",
        "ay_dist_m",
        "az_dist_m",
        "ax_dist_t",
        "ay_dist_t",
        "az_dist_t",
        "ar_dist_m",
        "at_dist_m",
        "an_dist_m",
        "ar_dist_t",
        "at_dist_t",
        "an_dist_t",
    ]
    + col_gnss_dir
    + col_pco
    + col_ambiguity_flag
    + [""]
)
acc_col = [
    "Mar_m",
    "Mat_m",
    "Man_m",
    "Mar_t",
    "Mat_t",
    "Man_t",
    "Qar_m",
    "Qat_m",
    "Qan_m",
    "Qar_t",
    "Qat_t",
    "Qan_t",
]

s2e_data_col = [
    "sat_position_i(X)[m]",
    "sat_position_i(Y)[m]",
    "sat_position_i(Z)[m]",
    "sat_acc_i_i(X)[m/s^2]",
    "sat_acc_i_i(Y)[m/s^2]",
    "sat_acc_i_i(Z)[m/s^2]",
    "sat_acc_rtn_rtn(X)[m/s^2]",
    "sat_acc_rtn_rtn(Y)[m/s^2]",
    "sat_acc_rtn_rtn(Z)[m/s^2]",
    "gnss_position_eci(X)[m]",
    "gnss_position_eci(Y)[m]",
    "gnss_position_eci(Z)[m]",
    "gnss_arp_true_eci(X)[m]",
    "gnss_arp_true_eci(Y)[m]",
    "gnss_arp_true_eci(Z)[m]",
]
s2e_data_col += [col + ".1" for col in s2e_data_col]

def find_log_data(log_base: str) -> list:
    """
    log_base: plotスクリプトを実行した後の一つのログフォルダパス
    return:
        [data, data_s2e]: 独自csvとs2e logのPandasDataFrameをまとめたリスト
    """
    sim_config_path = log_base + "readme.txt"
    log_path = log_base + "result.csv"
    s2e_log_dir = log_base
    s2e_csv_log_path = (
        s2e_log_dir
        + [file for file in os.listdir(s2e_log_dir) if file.endswith(".csv")][0]  # バグりそう．
    )
    # pcc_log_path = log_base + "pcc_1.csv"
    # pcv_log_path = log_base + "pcv_1.csv"

    data = pd.read_csv(log_path, header=None)
    if len(data.columns) != len(data_col):
        REDUCE_DYNAMIC = 0
        for name in acc_col:
            data_col.remove(name)
    data = data.set_axis(data_col, axis=1)

    # ログの頻度を合わせて回すこと！
    data_s2e = pd.read_csv(s2e_csv_log_path)

    return [data, data_s2e]

# 3drmsを含めてしまいたいが
def add_accuracy(
    precision: pd.DataFrame(), legend_name: str, name: str, axis: str, unit: str
) -> None:
    global accuracy_log
    accuracy_log = accuracy_log.append(
        {
            "legend": legend_name,
            "name": name,
            "axis": axis,
            "unit": unit,
            "mean": float("{:.3f}".format(precision.mean())),
            "std": float("{:.3f}".format(precision.std())),
            "rms": float("{:.3f}".format(np.sqrt(np.mean(precision**2)))),
        },
        ignore_index=True,
    )

def add_3d_rms(
    precision: pd.DataFrame(), legend_name: str, name: str, axes: list, unit: str
) -> None:
    global accuracy_log
    _3d_ms = 0
    for axis in axes:
        _3d_ms += np.mean(precision[axis] ** 2)
    _3d_rms = np.sqrt(_3d_ms)
    accuracy_log = accuracy_log.append(
        {
            "legend": legend_name,
            "name": name,
            "axis": "3d",
            "unit": unit,
            "rms": float("{:.3f}".format(_3d_rms)),
        },
        ignore_index=True,
    )

def get_suffix(m_t: str) -> str:
    if m_t == "m":
        return "main"
    elif m_t == "t":
        return "target"
    else:
        # print("ERROR: input error!")
        return ""

def DCM_from_eci_to_lvlh(base_pos_vel):
    r_i, v_i = base_pos_vel
    z_lvlh_i = -r_i / np.linalg.norm(r_i)
    x_lvlh_i = v_i / np.linalg.norm(v_i)
    y_lvlh_i = np.cross(z_lvlh_i, x_lvlh_i)
    x_lvlh_i = np.cross(y_lvlh_i, z_lvlh_i)
    DCM_from_eci_to_lvlh = np.array([x_lvlh_i, y_lvlh_i, z_lvlh_i])
    return DCM_from_eci_to_lvlh

def DCM_from_eci_to_rtn(base_pos_vel):
    r_i, v_i = base_pos_vel
    r_rtn_i = r_i / np.linalg.norm(r_i)
    t_rtn_i = v_i / np.linalg.norm(v_i)
    n_rtn_i = np.cross(r_rtn_i, t_rtn_i)
    t_rtn_i = np.cross(n_rtn_i, r_rtn_i)
    DCM_from_eci_to_rtn = np.array([r_rtn_i, t_rtn_i, n_rtn_i])
    return DCM_from_eci_to_rtn

def calc_relinfo(r_v_a, t_e, data):
    """
    Args:
        r_v_a: position or velocity or acceleration
        t_e: true or estimation
        data: data(PandasDataframe)
    """
    if r_v_a == "r":
        base_names = ["x", "y", "z"]
    elif r_v_a == "v":
        base_names = ["vx", "vy", "vz"]
    elif r_v_a == "a":
        base_names = ["ar", "at", "an"]
    else:
        print("false input")
        return

    frame_names = ["R", "T", "N"]
    col_names = ["d" + r_v_a + "_" + frame for frame in frame_names]
    names_main = [base_name + "_m_" + t_e for base_name in base_names]
    names_target = [base_name + "_t_" + t_e for base_name in base_names]
    base = pd.DataFrame()
    for i in range(len(base_names)):
        base[col_names[i]] = data[names_target[i]] - data[names_main[i]]
    return base

# 加速度の精度
def calc_a_precision(
    data: pd.DataFrame(), data_s2e_log: pd.DataFrame(), m_t: str, frame: str
) -> pd.DataFrame():
    if frame == "eci":
        a_base_names = ["ax", "ay", "az"]
        a_names = [base_name + "_" + m_t for base_name in a_base_names]
        a_t_names = [
            "sat_acc_i_i(X)[m/s^2]",
            "sat_acc_i_i(Y)[m/s^2]",
            "sat_acc_i_i(Z)[m/s^2]",
        ]  # 一旦べた書き
    elif frame == "rtn":
        a_base_names = ["ar", "at", "an"]
        a_names = [base_name + "_" + m_t + "_e" for base_name in a_base_names]
        a_t_names = [
            "sat_acc_rtn_rtn(X)[m/s^2]",
            "sat_acc_rtn_rtn(Y)[m/s^2]",
            "sat_acc_rtn_rtn(Z)[m/s^2]",
        ]
    else:
        return
    a_dist_names = [base_name + "_dist_" + m_t for base_name in a_base_names]
    a_e = pd.DataFrame()
    for i in range(3):
        a_e[a_base_names[i]] = data[a_names[i]] * 1e-3 + data[a_dist_names[i]] * 1e6  # um/s2

    if m_t == "t":
        a_t_names = [name + ".1" for name in a_t_names]
    a_t = pd.DataFrame()
    for i in range(3):
        a_t[a_base_names[i]] = data_s2e_log[a_t_names[i]] * 1e6  # um/s2
    a_t = a_t[1:].reset_index()  # ここはs2e_logとのindexずれがあるので補正している．

    M_names = ["M" + name + "_" + m_t for name in a_base_names]

    precision = pd.DataFrame()
    for i in range(3):
        precision[a_names[i]] = a_e[a_base_names[i]] - a_t[a_base_names[i]]
    # Mのデータも追加．
    for i in range(3):
        precision[M_names[i]] = data[M_names[i]] * (1e-3) ** 2  # um/s2 Mは2乗なので
        data[M_names[i]] = precision[M_names[i]]  # dataの方にもコピー
    return precision

red_list = [(103, 0, 13), (165, 15, 21), (203, 24, 29), (239, 59, 44), (251, 106, 74)]  # Reds

color_list = [
    "darkred",
    "tomato",
    "goldenrod",
    "chartreuse",
    "darkcyan",
    "darkblue",
    "darkmagenta",
    # "darkred",
    # "chartreuse",
    # "darkblue",
    # "darkmagenta",
    # "tomato",
    # "goldenrod",
    # "darkcyan",
]

class PlotSettings:
    def __init__(self, r_v_a: str, m_t: str, data_type: str):
        self.r_v_a = r_v_a
        self.m_t = m_t
        self.suffix = get_suffix(m_t)

        if data_type == "abs_rtn":
            self.init_abs_rtn()
        elif data_type == "rel_rtn":
            self.init_rel_rtn()
        else:
            print("false input!")

    # 使わない．
    # def init_abs_eci(self):
    #     if self.r_v_a == "r":
    #         self.base_names = ["x", "y", "z"]
    #         self.axis_names = base_names
    #         self.unit = "m"
    #         self.scale_param = 1
    #     elif self.r_v_a == "v":
    #         self.base_names = ["vx", "vy", "vz"]
    #         self.axis_names = ["v_x", "v_y", "v_z"]
    #         self.unit = "mm/s"
    #         self.scale_param = 1000
    #     elif self.r_v_a == "a":
    #         self.base_names = ["ax", "ay", "az"]
    #         self.axis_names = ["a_x", "a_y", "a_z"]
    #         self.unit = "um/s^2"
    #         self.scale_param = 1e-3
    #     else:
    #         print("false input")

    def init_abs_rtn(self):
        if self.r_v_a == "r":
            col_base_name = "res_pos_"
            self.unit = "m"
            self.scale_param = 1
            self.output_name = "position_rtn"
            self.M_names_base = ["Mrr", "Mrt", "Mrn"]
            self.y_range = 2.5
        elif self.r_v_a == "v":
            col_base_name = "res_vel_"
            self.unit = "mm/s"
            self.scale_param = 1000
            self.output_name = "velocity_rtn"
            self.M_names_base = ["Mvr", "Mvt", "Mvn"]
            self.y_range = 5.0
        elif self.r_v_a == "a":
            self.col_names = ["a_R", "a_T", "a_N"]
            self.unit = "um/s^2"
            self.scale_param = 1
            self.output_name = "a_rtn"
            self.M_names_base = ["Mar", "Mat", "Man"]
            self.y_range = 20.0  # ホンマはautoにしたい．
        else:
            print("false input")
            return

        self.frame_names = ["R", "T", "N"]
        # ちょっと気持ち悪いので統一したい．
        if self.r_v_a != "a":
            self.col_names = [
                col_base_name + frame_name + "_" + self.m_t for frame_name in self.frame_names
            ]
        self.base_name = self.r_v_a
        self.names = [self.base_name + "_" + frame for frame in self.frame_names]

    def init_rel_rtn(self):
        if self.r_v_a == "r":
            self.unit = "cm"
            self.scale_param = 100
            self.output_name = "relative_position"
            self.M_names = ["Mrr", "Mrt", "Mrn"]
            self.y_range = 0.14 * self.scale_param  # 0.18
        elif self.r_v_a == "v":
            self.unit = "mm/s"
            self.scale_param = 1000
            self.output_name = "relative_velocity"
            self.M_names = ["Mvr", "Mvt", "Mvn"]
            self.y_range = 1.2  # 3.5
        elif self.r_v_a == "a":
            self.unit = "um/s^2"
            self.scale_param = 1
            self.output_name = "relative_a"
            self.M_names = ["Mar", "Mat", "Man"]
            self.y_range = 0.07
        else:
            print("input error!")
            return

        self.frame_names = ["R", "T", "N"]
        self.base_name = "d" + self.r_v_a
        self.col_names = [self.base_name + "_" + frame_name for frame_name in self.frame_names]
        self.names = self.col_names

def plot_multiple_precision(r_v_a: str, m_t: str, data_type: str, datas: list) -> None:
    plot_set = PlotSettings(r_v_a, m_t, data_type)
    fig = fig_init(datas[0], plot_set.names, plot_set.unit)

    for i, data in enumerate(datas):
        if data_type == "abs_rtn":
            plot_precision_rtn(fig, data, plot_set, color_list[i], legend_name=legend_names[i])
        elif data_type == "rel_rtn":
            plot_differential_precision(fig, data, plot_set, color_list[i], legend_names[i])
    fig_output(fig, output_path + plot_set.output_name + "_precision_" + plot_set.suffix)

# 座標系に対しても統合したい．
def plot_precision_rtn(
    fig, data: pd.DataFrame(), plot_set: PlotSettings, color_str: str, legend_name: str
) -> None:

    data_for_plot = data * plot_set.scale_param
    # M_names = [M_name_base + "_" + m_t for M_name_base in M_names_base]

    for i in range(len(plot_set.names)):
        add_accuracy(
            data_for_plot.loc[data_offset:, plot_set.col_names[i]],
            legend_name,
            plot_set.base_name + "_" + plot_set.m_t,
            plot_set.frame_names[i],
            plot_set.unit,
        )
        RMS = np.sqrt(np.mean(data_for_plot.loc[data_offset:, plot_set.col_names[i]] ** 2))
        show_legend = False
        if i == 0:
            show_legend = True
        fig.add_trace(
            go.Scatter(
                mode="markers",
                x=data_for_plot.index * x_axis_scale,
                y=data_for_plot.loc[:, plot_set.col_names[i]],
                name=legend_name,
                legendgroup=str(i + 1),
                marker=dict(size=2, color=color_str),
                # marker=dict(
                #     size=2,
                # ),
                showlegend=show_legend,
            ),
            row=(i + 1),
            col=1,
        )
        # # 1 sigmaを計算してプロットする．
        # fig.add_trace(
        #     go.Scatter(
        #         x=data.index * x_axis_scale,
        #         y=np.sqrt(data[M_names[i]]) * scale_param,
        #         legendgroup=str(i),
        #         line=dict(width=1, color="black"),
        #         showlegend=False,
        #     ),
        #     row=(i + 1),
        #     col=1,
        # )
        # fig.add_trace(
        #     go.Scatter(
        #         x=data.index * x_axis_scale,
        #         y=-np.sqrt(data[M_names[i]]) * scale_param,
        #         legendgroup=str(i),
        #         line=dict(width=1, color="black"),
        #         showlegend=False,
        #     ),
        #     row=(i + 1),
        #     col=1,
        # )
        fig.update_yaxes(
            range=(-plot_set.y_range, plot_set.y_range),
            row=(i + 1),
            col=1,
        )
    add_3d_rms(
        data_for_plot.loc[data_offset:, :],
        legend_name,
        plot_set.base_name + "_" + plot_set.m_t,
        plot_set.col_names,
        plot_set.unit,
    )
    # fig_output(fig, output_path + output_name + "_precision_" + suffix)

def trans_eci_to_rtn(DCMs, precision_data):
    for i in range(len(precision_data)):
        DCM = DCMs[i]
        precision_data.iloc[i, :] = np.dot(DCM, precision_data.iloc[i, :])
    return precision_data

def plot_differential_precision(
    fig, precision_data: pd.DataFrame(), plot_set: PlotSettings, color_str: str, legend_name: str
) -> None:
    precision_data *= plot_set.scale_param
    # # eci -> rtnに変換
    # if input_frame == "ECI":
    #     for i in range(len(precision_data)):
    #         DCM = DCM_from_eci_to_rtn(
    #             (data.loc[i, "x_m_t":"z_m_t"], data.loc[i, "vx_m_t":"vz_m_t"])
    #         )
    #         precision_data.iloc[i, :] = np.dot(DCM, precision_data.iloc[i, :])

    for i in range(len(plot_set.names)):
        add_accuracy(
            precision_data.iloc[data_offset:, i],
            legend_name,
            plot_set.base_name,
            plot_set.frame_names[i],
            plot_set.unit,
        )
        RMS = np.sqrt(np.mean(precision_data.iloc[data_offset:, i] ** 2))
        show_legend = False
        if i == 0:
            show_legend = True
        fig.add_trace(
            go.Scatter(
                mode="markers",
                x=precision_data.index * x_axis_scale,
                y=precision_data.iloc[:, i],
                name=legend_name,
                legendgroup=str(i + 1),
                marker=dict(size=2, color=color_str),
                # marker=dict(size=2),
                showlegend=show_legend,
            ),
            row=(i + 1),
            col=1,
        )
        # 分散のところは絶対的な状態量から出しているもので正確ではないのでplotしない．
        fig.update_yaxes(
            range=(-plot_set.y_range, plot_set.y_range),
            row=(i + 1),
            col=1,
        )
    add_3d_rms(
        precision_data.loc[data_offset:, :],
        legend_name,
        plot_set.base_name,
        plot_set.col_names,
        plot_set.unit,
    )
    # fig_output(fig, output_path + output_name + "_precision")

def plot_multiple_bar(
    accuracy_data: pd.DataFrame(), categories: list, r_v_a: str, m_t: str, data_type: str
) -> None:
    plot_set = PlotSettings(r_v_a, m_t, data_type)
    precision_title = "$" + plot_set.base_name + "[\\text{" + plot_set.unit + "}]$"
    fig = fig_init_horizon_bar([accuracy_data], legend_names, precision_title)

    for i, category in enumerate(categories):
        fig = plot_accuracy_bar(
            fig, accuracy_data[accuracy_data["legend"] == category], category, color_list[i], 1
        )

    fig.update_layout(barmode="group")
    fig_output(fig, output_path + plot_set.output_name + "_precision_bar")

def plot_accuracy_bar(
    fig: go.Figure(), accuracy_data: pd.DataFrame(), category: str, color_str: str, col_num: int
) -> go.Figure():
    fig.add_trace(
        go.Bar(
            name=category,
            x=accuracy_data["axis"],
            y=accuracy_data["rms"],
            # text=accuracy_data["std"],
            texttemplate="%{y:.3f}",
            textposition="outside",
            textfont=dict(size=25),
            marker_color=color_str,
            legendgroup=str(col_num),
            # showlegend=False,
        ),
        row=1,
        col=col_num,
    )
    # mean, stdもプロットしたいときはsubplotごとにする．
    return fig

def plot_accuracy_comparison_w_subplot(
    r_v_a: str, m_t: str, data_type: str, datas: list, categories: list, subplot_names: list
) -> None:
    plot_set = PlotSettings(r_v_a, m_t, data_type)
    fig = fig_init_horizon_bar(datas, plot_set.names, plot_set.unit)

    for j, data in enumerate(datas):
        for i, category in enumerate(categories[j]):  # categories[j]
            fig = plot_accuracy_bar(
                fig, data[data["legend"] == category], category, color_list[i], j + 1
            )
        fig.update_xaxes(
            col=j + 1,
            title=dict(
                text=subplot_names[j],
                # standoff=2,
            ),
        )
    fig.update_traces(
        showlegend=True,
        row=1,
        col=1,
    )

    fig_output(fig, output_path + plot_set.output_name + "_precision_bar_all")

# pd.options.display.float_format = "{:.2f}".format
# pd.options.display.precision = 3
data_type_abs = "abs_rtn"
data_type_rel = "rel_rtn"

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
datas_list = []
for log_path in log_bases:
    datas_list.append(find_log_data(log_path))
datas, s2e_datas = list(zip(*datas_list))

dr_precisions = []
dv_precisions = []
da_precisions = []
# am_precisions = []
# at_precisions = []

# この辺の計算が重いからやっぱり一回csvに残しておきたいな．
DCMs = []  # 主衛星の軌道は変わらないので使いまわせる．
data = datas[0]
for i in range(len(data)):
    DCMs.append(
        DCM_from_eci_to_rtn((data.loc[i, "x_m_t":"z_m_t"], data.loc[i, "vx_m_t":"vz_m_t"]))
    )
for data, s2e_data in zip(datas, s2e_datas):
    dr_precision = calc_relinfo("r", "e", data) - calc_relinfo("r", "t", data)
    dr_precisions.append(trans_eci_to_rtn(DCMs, dr_precision))

    dv_precision = calc_relinfo("v", "e", data) - calc_relinfo("v", "t", data)
    dv_precisions.append(trans_eci_to_rtn(DCMs, dv_precision))

    # a_m_precision = calc_a_precision(data, s2e_data, "m", "rtn")
    # a_t_precision = calc_a_precision(data, s2e_data, "t", "rtn")
    # # plot_precision_rtn("a", "m", a_m_precision)
    # # plot_precision_rtn("a", "t", a_t_precision)
    # da_precision = calc_relinfo("a", "e", pd.concat([a_m_precision, a_t_precision], axis=1))
    # da_precisions.append(da_precision)
    # # plot_differential_precision(
    # #     data, a_t_precision.iloc[:, 0:3] - a_m_precision.iloc[:, 0:3], "a", "RTN"
    # # )

plot_multiple_precision("r", "m", data_type_abs, datas)
# plot_multiple_precision("r", "t", data_type_abs, datas)
plot_multiple_precision("v", "m", data_type_abs, datas)
# plot_multiple_precision("v", "t", data_type_abs, datas)

plot_multiple_precision("r", "", data_type_rel, dr_precisions)
plot_multiple_precision("v", "", data_type_rel, dv_precisions)
# plot_multiple_precision("a", "", data_type_rel, da_precisions)

# bar plot
plot_multiple_bar(
    # accuracy_log.query('name.str().contains("dr")'),  # engine="python"),
    accuracy_log[accuracy_log["name"] == "dr"],
    legend_names,
    "r",
    "",
    data_type_rel,
)
plot_multiple_bar(
    # accuracy_log.query('name.str().contains("dv")'),  # engine="python"),
    accuracy_log[accuracy_log["name"] == "dv"],
    legend_names,
    "v",
    "",
    data_type_rel,
)

# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# accuracy_logs = [log_base + log for log in files]
# accuracy_datas = []
# for file in accuracy_logs:
#     accuracy_datas.append(pd.read_csv(file))

# plot_accuracy_comparison_w_subplot(
#     "r", "", data_type_rel, accuracy_datas, legend_names, subplot_names
# )

accuracy_log.to_csv(accuracy_file, sep=",", index=False)
# 最後に全グラフをまとめてコピー
# shutil.move(output_path, copy_dir + "figure/")
shutil.move(output_path, copy_dir)


import heapq

class Solution:
    def thirdMax(self, nums: List[int]) -> int:
        dup = set()
        heap = []
        for num in nums:
            if num not in dup:
                heapq.heappush(heap, num)
                if len(heap) > 3:
                    heapq.heappop(heap)
                dup.add(num)
        if len(heap) == 3:
            return heap[0]
        else:
            return max(nums)


from pprint import pprint
from fastapi import FastAPI, Request
import redis

app = FastAPI()
r = redis.Redis(host='localhost', port=6379, db=0)

@app.get("/")
async def root():
    return {"message": "Hello World"}

@app.post("/")
async def listen(request: Request):
    body = await request.body()
    r.rpush("nglue", body)
    return True


#!/usr/bin/python3
def weight_average(my_list=[]):
    if len(my_list) == 0 or my_list is None:
        return 0
    numerator = 0
    denominator = 0
    for tupl in my_list:
        numerator += tupl[0] * tupl[1]
        denominator += tupl[1]
    return numerator/denominator


import numpy as np
import pandas as pd
import torch
import torch.nn as nn
from sklearn.model_selection import train_test_split
from torch.optim.lr_scheduler import StepLR
from torch.utils.data import Dataset, DataLoader

device = "cuda" if torch.cuda.is_available() else "cpu"
import multiprocessing as mp

NUM_PROCS = mp.cpu_count()

class SimpleGRUClassifier(nn.Module):
    """GRU without lightning."""

    def __init__(
        self,
        n_classes: int = 2,
        input_size: int = 1000,
        hidden_layer_size: int = 500,
        n_layers: int = 1,
        hidden_size: int = 1,
        batch_size: int = 1,
    ):
        """Instantiate the instance."""
        super().__init__()
        # self.n_classes = len(label_encoder.classes_)
        self.n_classes = n_classes
        self.n_layers = n_layers
        self.batch_size = batch_size
        self.hidden_size = hidden_size
        self.hidden_layer_size = hidden_layer_size
        self.gru = nn.GRU(
            input_size, hidden_layer_size, n_layers, batch_first=True
        )
        self.fc1 = nn.Linear(hidden_layer_size, hidden_layer_size)
        self.fc = nn.Linear(hidden_layer_size, self.n_classes)
        self.relu = nn.ReLU()
        self.criterion = nn.CrossEntropyLoss()

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        """Forward computing."""
        hidden = self._init_hidden(self.hidden_layer_size)
        output, hidden = self.gru(x, hidden.view(self.n_layers, -1))
        fc_output = self.relu(self.fc1(output))
        fc_output = self.fc(fc_output)
        return fc_output

    def _init_hidden(self, batch_size):
        """Return initial condition of hidden state tensor."""
        hidden = torch.zeros(self.n_layers, batch_size, self.hidden_size)
        return hidden.clone().detach().to(device)

def train(
    model: SimpleGRUClassifier,
    device: str,
    criterion: nn.CrossEntropyLoss,
    train_loader: DataLoader,
    optimizer: torch.optim.Adam,
    epoch: int,
):
    """Train the neural network without Lightning."""
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()
        if batch_idx % 20 == 0:
            print(
                f"Train Epoch: {epoch} [{batch_idx * len(data)}/{len(train_loader.dataset)} ({100.0 * batch_idx / len(train_loader):.0f}%)]\tLoss: {loss.item():.6f}"
            )

def test(
    model: SimpleGRUClassifier,
    device: str,
    criterion: nn.CrossEntropyLoss,
    test_loader: DataLoader,
):
    """Test the neural network without lightning."""
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            test_loss += criterion(output, target).item()  # sum up batch loss
            pred = output.argmax(
                dim=1, keepdim=True
            )  # get the index of the max log-probability
            correct += pred.eq(target.view_as(pred)).sum().item()

    test_loss /= len(test_loader.dataset)

    print(
        f"\nTest set: Average loss: {test_loss:.4f}, Accuracy: {correct}/{len(test_loader.dataset)} ({100.0 * correct / len(test_loader.dataset):.0f}%)\n"
    )

class MushroomDataSet(Dataset):
    """Dataset."""

    def __init__(
        self,
        X: np.ndarray,
        Y: np.ndarray
    ):
        """Initialize the instance."""
        self.X = X
        self.Y = Y
        self.len = len(X)

    def __getitem__(self, index):
        """Get an item from given index."""
        return torch.Tensor(
            self.X[index]
        ), int(self.Y[index])

    def __len__(self):
        """Return length of dataset."""
        return self.len

def main() -> None:
    """Run the code."""
    mushroomsfile = 'mushrooms.csv'
    data_array = np.genfromtxt(
        mushroomsfile, delimiter=',', dtype=str, skip_header=1)
    for col in range(data_array.shape[1]):
        data_array[:, col] = np.unique(data_array[:, col], return_inverse=True)[1]

    X = data_array[:, 1:].astype(np.float32)
    Y = data_array[:, 0].astype(np.int32)[:, None]
    df = pd.DataFrame(X)
    df['label'] = Y
    X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.33, random_state=112)

    train_dataset = MushroomDataSet(
        X_train,
        y_train
    )
    test_dataset = MushroomDataSet(
        X_test,
        y_test
    )
    train_loader = torch.utils.data.DataLoader(
        train_dataset,
        shuffle=True,
        batch_size=1,
        num_workers=NUM_PROCS,
    )
    test_loader = torch.utils.data.DataLoader(
        test_dataset,
        shuffle=False,
        batch_size=1,
        num_workers=NUM_PROCS,
    )
    model = SimpleGRUClassifier(n_classes=2, input_size=22)
    optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
    criterion = nn.CrossEntropyLoss()
    scheduler = StepLR(optimizer, step_size=1, gamma=0.7)

    for epoch in range(1, 1 + 1):
        train(model, device, criterion, train_loader, optimizer, epoch)
        test(model, device, criterion, test_loader)
        scheduler.step()

if __name__ == "__main__":
    main()


import networkx as nx
import numpy as np
from sklearn.preprocessing import MinMaxScaler
import Utility.personalizedSort as ps

class SelectPowerfulUser:

    def __init__(self):
        self.usermatrix=None
        self.usernames=None

    def userRank(self):
        G = nx.DiGraph(self.usermatrix)
        pr = nx.pagerank_numpy(G, alpha=0.9)
        #print(pr)
        X=[]
        for i in range(len(pr)):
            #index,name,rank score
            X.insert(i,(i,self.usernames[i],pr[i]))

        m_s=ps.MySort(X)
        m_s.compare_vec_index=-1
        X=m_s.mergeSort()
        X=np.array(X)
        #print()
        #print(X[:3])
        names=X[:,1]
        X=np.array(np.delete(X,1,1),dtype=np.float32)

        return X,names

    def setMatrixData(self,data):

        self.usermatrix=np.array(data["data"])
        self.usernames=np.array(data["users"])
        minmax=MinMaxScaler(feature_range=(0,1))
        self.usermatrix=minmax.fit_transform(self.usermatrix)

def rankOnDIG(data):
    '''
    :param data:{"data":i_matrix,"users":users_list}
    :return: rank
    '''

    poweruser=SelectPowerfulUser()
    poweruser.setMatrixData(data=data)
    X, names = poweruser.userRank()

    return X,names


import socket
import os
import threading
import _thread
from socketserver import ThreadingMixIn
#======================================INITIALISE ALL THE VARIABLES===================================================
SYNC_BIT = 0
CENTRAL_IP = "0.0.0.0"
CLOSE_CONNECTION = 0
CLIENT_count = 0
TIMEOUT = 0
HOST_count = 0
flag_1 = 0
flag_2 = 0
flag_3 = 0
MAX_CONNECTIONS = 5
MIN_CONNECTIONS = 1
BASE_PORT = 60069
IP_1 = "0.0.0.0.0"
IP_2 = "0.0.0.0.0"
IP_3 = "0.0.0.0.0"
IP_4 = "0.0.0.0.0"
IP_5 = "0.0.0.0.0"
IP_LIST = []
ACTIVE_CONNECTIONS = 0
#=========================================GLOBAL VARIABLES ENDS HERE===================================================

CENTRAL_IP = "192.168.43.126"

def dummy_connections():
    dummy=0
    central_host = socket.socket()
    # =================================================================
    #                       ININTIALISE THE HOST
    # =================================================================
    try:
        central_host.bind((CENTRAL_IP, BASE_PORT))
        print("host is active")
    except:
        print("binding error")

    central_host.listen(5)
    client_1,addr = central_host.accept()
    new_thread = ClientThread(addr[0],addr[1])
    new_thread.start()
    client_1.send(b'ACKNOWLEDGE')
    IP_LIST.append(addr[0])
    #while not SYNC_BIT:
       # pass
    #for dummy in MAX_CONNECTIONS:
      #  client_1.send(bytes(IP_LIST[dummy] , 'utf-8'))
    #client_1.close()

try:
    _thread.start_new_thread(dummy_connections, ())
    _thread.start_new_thread(dummy_connections, ())
    _thread.start_new_thread(dummy_connections, ())
    _thread.start_new_thread(dummy_connections, ())
    _thread.start_new_thread(dummy_connections, ())
except:
    print("connection not possible")

#while(IP_LIST[5] == "0"):
 #   pass
#SYNC_BIT=1

while True:
    pass
    #print(IP_LIST)
    #print("\n")


"""
    Note: when testing this do:
    $ pip install --editable .

    But if you make a change:
    $ pip uninstall azul
    $ pip install --editable .

    Also note, if you are in the top azul directory and type "azul" with no other options the shell will take you
    the azul directory instead of running the command line.
"""

import click
import azul
import logbook

@click.group()
def cli():
    """azul is a command line tool for downloading historical price data that can be used in a zipline bundle."""

    # install a logbook handler before performing any other operations
    logbook.StderrHandler(level='NOTICE').push_application()
    global log
    log = logbook.Logger('AzulCli')

@click.command()
@click.option(
    '--symbol-source',
    type=click.STRING,
    metavar="['sp500', 'polygon_cs', 'iex', 'faang']",
    default='faang',
    help='The source to get symbols from.'
)
@click.option(
    '--data-source',
    type=click.STRING,
    metavar="['polygon', 'iex']",
    default='iex',
    help='The source to get data from.'
)
@click.option(
    '-o',
    '--output-dir',
    type=click.Path(file_okay=False),
    default=None,
    metavar='[~/.azul/<data-source>]',
    show_default=False,
    help="The directory write the data too."
)
@click.option(
    '-s',
    '--start',
    type=click.DateTime(formats=['%Y-%m-%d']),
    default=None,
    help='The date to start downloading data from.',
)
@click.option(
    '-e',
    '--end',
    type=click.DateTime(formats=['%Y-%m-%d']),
    default=None,
    help='The date to end downloading data from.',
)
def download(symbol_source, data_source, output_dir, start, end):
    """Download historical price data."""
    try:
        azul.get_price_data(symbol_source, data_source, output_dir, start, end)
    except Exception as e:
        log.error(e)
        raise

@click.command()
def update():
    """Update symbols with any new data."""
    pass

cli.add_command(download)
cli.add_command(update)


import numpy as np

def compute_mean_image(frames):
    """
    Compute mean image of given frames

    Parameters
    -------
    frames : list of numpy.ndarray
        All frame must have same shape

    Returns
    -------
    mean_image : numpy.ndarray
        Mean image of given frame.
    """
    frame = frames[0]
    prev_frame = frame
    mean_image = np.zeros(shape=frame.shape, dtype=np.float32)
    N = len(frames)
    for frame in frames:
        if not prev_frame.shape == frame.shape:
            raise ValueError("Given frames does not have same shape. {} != {}".format(
                prev_frame.shape, frame.shape))
        mean_image += frame
        prev_frame = frame
    return mean_image / N


from collections import deque

n = int(input())
list = []
for i in range(n):
    word = deque(input())
    for j in range(len(word)):
        tmp = ''.join(word)
        if tmp in list:
            break
        word.rotate()
    else:
        list.append(''.join(word))
print(len(list))


import numpy as np

def obtain_probabilities(test, model):
    z = model.decision_function(np.array(test))
    p = [1/(1+np.exp(-i)) for i in z]
    return p

def p_matrix(data, model, n):
    p = np.zeros((n, n))
    k = 0
    for i in range(n * n):
        if i // n != n -1 and i % n != 0 and i % n != n - 1 and i // n != i % n:
            p[i//n, i % n] = obtain_probabilities(data[k].reshape((1, -1)), model)[0]
            k += 1
    return p

def predictions_matrix(data, model, n):
    p = np.full((n, n), "neg")
    k = 0
    for i in range(n * n):
        if i // n != n - 1 and i % n != 0 and i % n != n - 1 and i // n != i % n:
            p[i//n, i % n] = model.predict(data[k].reshape((1, -1)))[0]
            k += 1
    print(k, len(data))
    return p


# -*- coding: utf-8 -*-

import wx.animate

###########################################################################
## Class main_frame
###########################################################################

class main_frame ( wx.Frame ):

	def __init__( self, parent ):
		wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Partition Text", pos = wx.DefaultPosition, size = wx.Size( 700,500 ), style = wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.SYSTEM_MENU|wx.TAB_TRAVERSAL )

		self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

		sizer_main = wx.BoxSizer( wx.VERTICAL )

		self.panel = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
		bSizer3 = wx.BoxSizer( wx.HORIZONTAL )

		bSizer41 = wx.BoxSizer( wx.VERTICAL )

		bSizer27 = wx.BoxSizer( wx.HORIZONTAL )

		bSizer271 = wx.BoxSizer( wx.VERTICAL )

		bSizer23 = wx.BoxSizer( wx.HORIZONTAL )

		bSizer24 = wx.BoxSizer( wx.VERTICAL )

		self.filename_label = wx.StaticText( self.panel, wx.ID_ANY, u"File", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.filename_label.Wrap( -1 )
		bSizer24.Add( self.filename_label, 0, wx.ALL|wx.EXPAND, 5 )

		bSizer23.Add( bSizer24, 1, wx.ALL|wx.EXPAND, 5 )

		bSizer25 = wx.BoxSizer( wx.HORIZONTAL )

		bSizer241 = wx.BoxSizer( wx.VERTICAL )

		self.file_box = wx.TextCtrl( self.panel, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.TE_NO_VSCROLL )
		bSizer241.Add( self.file_box, 0, wx.ALL|wx.EXPAND, 5 )

		bSizer25.Add( bSizer241, 1, wx.EXPAND, 5 )

		bSizer251 = wx.BoxSizer( wx.VERTICAL )

		self.file_open_button = wx.Button( self.panel, wx.ID_ANY, u"...", wx.DefaultPosition, wx.Size( 20,-1 ), 0 )
		bSizer251.Add( self.file_open_button, 0, wx.ALL, 5 )

		bSizer25.Add( bSizer251, 0, wx.EXPAND, 5 )

		bSizer23.Add( bSizer25, 3, wx.EXPAND, 5 )

		bSizer271.Add( bSizer23, 0, wx.EXPAND, 5 )

		bSizer19 = wx.BoxSizer( wx.HORIZONTAL )

		bSizer20 = wx.BoxSizer( wx.VERTICAL )

		self.output_folder_label = wx.StaticText( self.panel, wx.ID_ANY, u"Output Folder", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.output_folder_label.Wrap( -1 )
		bSizer20.Add( self.output_folder_label, 0, wx.ALL|wx.EXPAND, 5 )

		bSizer19.Add( bSizer20, 1, wx.ALL|wx.EXPAND, 5 )

		bSizer22 = wx.BoxSizer( wx.HORIZONTAL )

		bSizer28 = wx.BoxSizer( wx.VERTICAL )

		self.output_folder_box = wx.TextCtrl( self.panel, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.TE_NO_VSCROLL )
		bSizer28.Add( self.output_folder_box, 0, wx.ALL|wx.EXPAND, 5 )

		bSizer22.Add( bSizer28, 1, wx.EXPAND, 5 )

		bSizer29 = wx.BoxSizer( wx.VERTICAL )

		self.output_folder_browse = wx.Button( self.panel, wx.ID_ANY, u"...", wx.DefaultPosition, wx.Size( 20,-1 ), 0 )
		bSizer29.Add( self.output_folder_browse, 0, wx.ALL, 5 )

		bSizer22.Add( bSizer29, 0, wx.EXPAND, 5 )

		bSizer19.Add( bSizer22, 3, wx.EXPAND, 5 )

		bSizer271.Add( bSizer19, 0, wx.EXPAND, 5 )

		bSizer7 = wx.BoxSizer( wx.HORIZONTAL )

		bSizer8 = wx.BoxSizer( wx.VERTICAL )

		self.staticText_linesperfile = wx.StaticText( self.panel, wx.ID_ANY, u"Lines Per File", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.staticText_linesperfile.Wrap( -1 )
		self.staticText_linesperfile.Hide()

		bSizer8.Add( self.staticText_linesperfile, 0, wx.ALL|wx.EXPAND, 5 )

		self.staticText_numberofparts = wx.StaticText( self.panel, wx.ID_ANY, u"Number Of Parts", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.staticText_numberofparts.Wrap( -1 )
		bSizer8.Add( self.staticText_numberofparts, 0, wx.ALL|wx.EXPAND, 5 )

		bSizer7.Add( bSizer8, 1, wx.ALL|wx.EXPAND, 5 )

		bSizer10 = wx.BoxSizer( wx.VERTICAL )

		self.spinCtrl_divisionParameter = wx.SpinCtrl( self.panel, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.SP_ARROW_KEYS|wx.TE_PROCESS_ENTER, 1, 9999, 1 )
		bSizer10.Add( self.spinCtrl_divisionParameter, 0, wx.ALL, 5 )

		bSizer7.Add( bSizer10, 3, wx.EXPAND, 5 )

		bSizer271.Add( bSizer7, 0, wx.EXPAND, 5 )

		bSizer27.Add( bSizer271, 2, wx.EXPAND, 5 )

		bSizer281 = wx.BoxSizer( wx.HORIZONTAL )

		self.m_staticline1 = wx.StaticLine( self.panel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_VERTICAL )
		bSizer281.Add( self.m_staticline1, 0, wx.EXPAND|wx.LEFT, 5 )

		bSizer282 = wx.BoxSizer( wx.VERTICAL )

		bSizer291 = wx.BoxSizer( wx.HORIZONTAL )

		bSizer33 = wx.BoxSizer( wx.HORIZONTAL )

		self.m_staticText6 = wx.StaticText( self.panel, wx.ID_ANY, u"Size", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText6.Wrap( -1 )
		bSizer33.Add( self.m_staticText6, 0, wx.ALL, 5 )

		self.file_size_diplay = wx.StaticText( self.panel, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.file_size_diplay.Wrap( -1 )
		bSizer33.Add( self.file_size_diplay, 1, wx.ALL, 5 )

		bSizer291.Add( bSizer33, 1, wx.EXPAND, 5 )

		bSizer34 = wx.BoxSizer( wx.HORIZONTAL )

		self.m_staticText8 = wx.StaticText( self.panel, wx.ID_ANY, u"Lines", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText8.Wrap( -1 )
		bSizer34.Add( self.m_staticText8, 0, wx.ALL, 5 )

		self.lines_label = wx.StaticText( self.panel, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.lines_label.Wrap( -1 )
		bSizer34.Add( self.lines_label, 1, wx.ALL, 5 )

		self.animCtrl_scanner = wx.animate.AnimationCtrl( self.panel, wx.ID_ANY, wx.animate.NullAnimation, wx.DefaultPosition, wx.DefaultSize, wx.animate.AC_DEFAULT_STYLE )
		self.animCtrl_scanner.LoadFile( u"C:\\Users\\Dibyendu\\Workspace\\Text_Splitter\\icon\\scanning.GIF" )

		self.animCtrl_scanner.Play()
		self.animCtrl_scanner.Hide()

		bSizer34.Add( self.animCtrl_scanner, 0, wx.ALL|wx.EXPAND, 5 )

		bSizer291.Add( bSizer34, 1, wx.EXPAND, 5 )

		bSizer282.Add( bSizer291, 0, wx.ALL|wx.EXPAND, 5 )

		bSizer30 = wx.BoxSizer( wx.VERTICAL )

		radioBox_divideoptionChoices = [ u"Number Of Parts", u"Number Of Lines" ]
		self.radioBox_divideoption = wx.RadioBox( self.panel, wx.ID_ANY, u"Divide According To", wx.DefaultPosition, wx.DefaultSize, radioBox_divideoptionChoices, 1, wx.RA_SPECIFY_COLS )
		self.radioBox_divideoption.SetSelection( 0 )
		bSizer30.Add( self.radioBox_divideoption, 0, wx.ALL, 5 )

		bSizer282.Add( bSizer30, 1, wx.EXPAND, 5 )

		bSizer32 = wx.BoxSizer( wx.VERTICAL )

		bSizer282.Add( bSizer32, 1, wx.EXPAND, 5 )

		bSizer281.Add( bSizer282, 1, wx.EXPAND, 5 )

		bSizer27.Add( bSizer281, 1, wx.EXPAND, 5 )

		bSizer41.Add( bSizer27, 0, wx.EXPAND, 5 )

		bSizer11 = wx.BoxSizer( wx.VERTICAL )

		self.split_button = wx.Button( self.panel, wx.ID_ANY, u"&Split", wx.DefaultPosition, wx.DefaultSize, 0 )
		bSizer11.Add( self.split_button, 0, wx.ALIGN_CENTER|wx.ALL, 5 )

		bSizer41.Add( bSizer11, 0, wx.EXPAND, 5 )

		sbSizer1 = wx.StaticBoxSizer( wx.StaticBox( self.panel, wx.ID_ANY, u"File Preview" ), wx.VERTICAL )

		self.text_display = wx.TextCtrl( self.panel, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.TE_MULTILINE|wx.TE_READONLY )
		sbSizer1.Add( self.text_display, 1, wx.EXPAND, 5 )

		bSizer41.Add( sbSizer1, 1, wx.EXPAND, 0 )

		self.progress_bar = wx.Gauge( self.panel, wx.ID_ANY, 100, wx.DefaultPosition, wx.Size( -1,20 ), wx.GA_HORIZONTAL|wx.GA_SMOOTH )
		self.progress_bar.SetValue( 0 )
		bSizer41.Add( self.progress_bar, 0, wx.ALL|wx.EXPAND, 0 )

		bSizer3.Add( bSizer41, 1, wx.ALL|wx.EXPAND, 5 )

		self.panel.SetSizer( bSizer3 )
		self.panel.Layout()
		bSizer3.Fit( self.panel )
		sizer_main.Add( self.panel, 1, wx.ALL|wx.EXPAND, 0 )

		self.SetSizer( sizer_main )
		self.Layout()
		self.statusbar = self.CreateStatusBar( 1, wx.ST_SIZEGRIP, wx.ID_ANY )
		self.menubar = wx.MenuBar( 0 )
		self.file_menu = wx.Menu()
		self.file_menu_open = wx.MenuItem( self.file_menu, wx.ID_ANY, u"&Open"+ u"\t" + u"Ctrl+O", u"Open file to split or extract from..", wx.ITEM_NORMAL )
		self.file_menu_open.SetBitmap( wx.Bitmap( u"icon/open_icon.png", wx.BITMAP_TYPE_ANY ) )
		self.file_menu.AppendItem( self.file_menu_open )

		self.file_menu_exit = wx.MenuItem( self.file_menu, wx.ID_ANY, u"&Exit"+ u"\t" + u"ALT+F4", u"Exit Partition Text", wx.ITEM_NORMAL )
		self.file_menu_exit.SetBitmap( wx.Bitmap( u"icon/close_icon.png", wx.BITMAP_TYPE_ANY ) )
		self.file_menu.AppendItem( self.file_menu_exit )

		self.menubar.Append( self.file_menu, u"&File" )

		self.help_menu = wx.Menu()
		self.help_menu_about = wx.MenuItem( self.help_menu, wx.ID_ANY, u"&About"+ u"\t" + u"F1", u"About Partition Text", wx.ITEM_NORMAL )
		self.help_menu_about.SetBitmap( wx.Bitmap( u"icon/about_icon.png", wx.BITMAP_TYPE_ANY ) )
		self.help_menu.AppendItem( self.help_menu_about )

		self.menubar.Append( self.help_menu, u"&Help" )

		self.SetMenuBar( self.menubar )

		self.Centre( wx.BOTH )

		# Connect Events
		self.file_open_button.Bind( wx.EVT_BUTTON, self.OnOpenFile )
		self.output_folder_browse.Bind( wx.EVT_BUTTON, self.OnOutputFolderSelect )
		self.spinCtrl_divisionParameter.Bind( wx.EVT_TEXT_ENTER, self.on_spinCtrl_edit )
		self.radioBox_divideoption.Bind( wx.EVT_RADIOBOX, self.on_divide_mode_select )
		self.split_button.Bind( wx.EVT_BUTTON, self.OnSplit )
		self.Bind( wx.EVT_MENU, self.OnOpenFile, id = self.file_menu_open.GetId() )
		self.Bind( wx.EVT_MENU, self.OnExit, id = self.file_menu_exit.GetId() )
		self.Bind( wx.EVT_MENU, self.OnAbout, id = self.help_menu_about.GetId() )

	def __del__( self ):
		pass

	# Virtual event handlers, overide them in your derived class
	def OnOpenFile( self, event ):
		event.Skip()

	def OnOutputFolderSelect( self, event ):
		event.Skip()

	def on_spinCtrl_edit( self, event ):
		event.Skip()

	def on_divide_mode_select( self, event ):
		event.Skip()

	def OnSplit( self, event ):
		event.Skip()

	def OnExit( self, event ):
		event.Skip()

	def OnAbout( self, event ):
		event.Skip()

###########################################################################
## Class about_frame
###########################################################################

class about_frame ( wx.Dialog ):

	def __init__( self, parent ):
		wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"About Partition Text", pos = wx.DefaultPosition, size = wx.Size( 232,178 ), style = wx.DEFAULT_DIALOG_STYLE|wx.STAY_ON_TOP )

		self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

		bSizer12 = wx.BoxSizer( wx.VERTICAL )

		self.m_panel4 = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
		bSizer13 = wx.BoxSizer( wx.VERTICAL )

		bSizer121 = wx.BoxSizer( wx.HORIZONTAL )

		bSizer15 = wx.BoxSizer( wx.VERTICAL )

		self.m_bitmap1 = wx.StaticBitmap( self.m_panel4, wx.ID_ANY, wx.Bitmap( u"icon/about_pic.png", wx.BITMAP_TYPE_ANY ), wx.DefaultPosition, wx.DefaultSize, 0 )
		bSizer15.Add( self.m_bitmap1, 0, wx.ALL, 5 )

		bSizer121.Add( bSizer15, 1, wx.EXPAND, 5 )

		bSizer17 = wx.BoxSizer( wx.VERTICAL )

		self.m_staticText7 = wx.StaticText( self.m_panel4, wx.ID_ANY, u"PARTITION TEXT\n    Version 1.0", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText7.Wrap( -1 )
		self.m_staticText7.SetFont( wx.Font( wx.NORMAL_FONT.GetPointSize(), 70, 90, 92, False, "Arial" ) )

		bSizer17.Add( self.m_staticText7, 0, wx.ALL, 10 )

		bSizer121.Add( bSizer17, 3, wx.EXPAND, 0 )

		bSizer13.Add( bSizer121, 1, wx.EXPAND, 0 )

		bSizer14 = wx.BoxSizer( wx.VERTICAL )

		self.m_staticText8 = wx.StaticText( self.m_panel4, wx.ID_ANY, u"Created By : Dibyendu Das", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText8.Wrap( -1 )
		bSizer14.Add( self.m_staticText8, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 5 )

		bSizer13.Add( bSizer14, 1, wx.EXPAND, 5 )

		self.m_panel4.SetSizer( bSizer13 )
		self.m_panel4.Layout()
		bSizer13.Fit( self.m_panel4 )
		bSizer12.Add( self.m_panel4, 1, wx.EXPAND |wx.ALL, 10 )

		self.SetSizer( bSizer12 )
		self.Layout()

		self.Centre( wx.BOTH )

	def __del__( self ):
		pass


import sys
import requests
import os

class ImageDownload:
    def __init__(self, img, id):
        self.images = img
        self.id = id

    def GetLinks(self):
        return [x['src'] for x in self.images]

    def SaveToDisk(self):
        try:
            # creating the folder based on their ids
            os.makedirs(f"C://Users/cojoc/PycharmProjects/scraping/photos/{self.id}")
            for i, image in enumerate(self.GetLinks()):  # using enumerate to index through the links of photos
                r = requests.get(image, stream=True)  # reuqesting to get the image
                # This will allow us to save the images in the folder based by their ids
                with open(f'C://Users/cojoc/PycharmProjects/scraping/photos/{self.id}/image_' + str(i) + '.jpg',
                          'wb') as f:
                    for chunk in r:
                        f.write(chunk)
        except:
            print("The Folder already exists")
            sys.exit()  # exiting the program if the folder with the car's id already exist


bli = "".join(input().split())
N = int(input())
ali = [input() for _ in range(N)]
for i in range(N):
    ali[i] = int(ali[i].translate(str.maketrans(bli, "0123456789")))
ali.sort()
for i in range(N):
    ali[i] = str(ali[i])
    ali[i] = ali[i].translate(str.maketrans("0123456789", bli))
    print(ali[i])


import sys
import json
from os import listdir
from os.path import isfile, join
import re
import argparse
import pickle
def run_process(fname,fpath):
    sentences = []
    with open(join(fpath,fname),'r') as fin:
        doc = fin.read()
    for line in doc.split('\n')[:-1]:
        # print(line)
        segs = line.split('\t')
        # print(segs)
        sentence = re.sub(r'(.|,|!) *((I )|(me )|(Me )|(We)|(we))',segs[1],segs[2])
        sentences.append(sentence)
    fout = join('CLEF/test/',f.rsplit('.',1)[0] + '_fp.pkl')
    with open(fout,'wb') as fout:
        pickle.dump(sentences,fout)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Input file/fphath, at least one must be provided.')
    # parser.add_argument('--folder',
    #                help='given folder or not')
    # parser.add_argument('file', type=str, default=None,
    #                     help='path to the file that needs to be processed')
    parser.add_argument('folder', type=str,default=None,
                        help='path to the folder that all the files need to be processed')

    args = parser.parse_args()

    # if args.file != None:
    #     run_process(args.file)

    if args.folder != None:
        files = [f for f in listdir(args.folder) if isfile(join(args.folder, f))]
        for f in files:
            run_process(f,args.folder)


lst = ['','A','E','I','O','U']
# t = []
# t = set(t)
# for j in lst:
#     for k in lst:
#         for q in lst:
#             for p in lst:
#                 for w in lst:
#                     t.add((j+k+q+p+w).strip())
# t = list(t)
# t.sort()

# def solution(word):
#     for i in t:
#         if i == word:
#             return t.index(i)

# #시간복잡도는 list t의 n번 순회 O(N)

from itertools import product
t2 = []
t2 = set(t2)
for i in product(lst,repeat = 5):
    s = ''.join(i)
    t2.add(s)
t2 = list(t2)
t2.sort()
t2.pop()
print(t2)

#중복순열   t==t2


#{
 # Driver Code Starts
#Initial Template for Python 3

# } Driver Code Ends
#User function Template for python3

def nearestPower(A, B):
    ##Your code here
    ##return the closest power
    P = 1
    min_diff = float('inf')
    closest_power = 0

    while True:
        X = A ** P
        diff = abs(X - B)

        if diff < min_diff:
            min_diff = diff
            closest_power = X

        if X >= B:
            break

        P += 1

    return closest_power

#{
 # Driver Code Starts.

import math

def main():
    testcases=int(input()) #testcases
    while(testcases>0):
        A = int(input())
        B = int(input())
        print(nearestPower(A, B))
        testcases-=1

if __name__=='__main__':
    main()
# } Driver Code Ends


import os
import pandas as pd
import features_extraction

# pre-processing
from scipy import signal
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler

# Constant to declare for the parameters for the sliding window
WINDOW_SIZE = 512
STEP = 128
order = 3
f_sample = 100
f_cutoff = 30
nyquist_rate = f_cutoff / (f_sample / 2)

# Data path should arrive in the format of <phone>/<vibrated>/<frequency>/<.csv> file
def create_windows(data_path):
    columns = ["x", "y", "z"]
    df = pd.read_csv(data_path, usecols=[1, 2, 3], header=None)
    # Assigning columns to the data set
    df.columns = columns
    data_readings = df.values
    # # `noise reduction
    for axis in range(0, 3):
        # order 3 lowpass butterworth filter
        b, a = signal.butter(order, nyquist_rate)
        data_readings[:, axis] = signal.filtfilt(b, a, data_readings[:, axis])

    ###############################################################################################
    # Trying different scaling functions
    ###############################################################################################
    # Min Max Scaler
    # min_max_scaler = preprocessing.MinMaxScaler()
    # data_readings = min_max_scaler.fit_transform(data_readings)

    # Standard Scaler
    scaler = StandardScaler()
    data_readings = scaler.fit_transform(data_readings)
    num_rows = len(data_readings)
    all_window = []

    for start in range(0, num_rows - WINDOW_SIZE, STEP):
        window = data_readings[start:start + WINDOW_SIZE]
        all_window.append(window)

    return all_window

# Getting labels for phone data
phone_list = []
data_dir = os.path.abspath("./100hz_data")
for phone in os.listdir(data_dir):
    phone_list.append(phone)

columns = ['min_x', 'min_y', 'min_z', 'min_rss', 'max_x', 'max_y', 'max_z', 'max_rss', 'std_x', 'std_y', 'std_z',
           'std_rss', 'mean_x', 'mean_y', 'mean_z', 'mean_rss', 'variance_x', 'variance_y', 'variance_z',
           'variance_rss', 'kurtosis_x', 'kurtosis_y', 'kurtosis_z', 'kurtosis_rss',
           'skew_x', 'skew_y', 'skew_z', 'skew_rss', 'phone']

main_df = pd.DataFrame(columns=columns)

# Setting up to traverse through CSV files to extract features
for folder in os.listdir(data_dir):
    data_segments = []
    vibrated_folder = os.path.abspath(os.path.join(data_dir, folder))
    list_of_csv = os.listdir(vibrated_folder)
    for csv in list_of_csv:
        csv_path = os.path.join(vibrated_folder, csv)

        # Making the entire CSV file return a list of list of segments
        data_segments = create_windows(csv_path)

        # For each segment, i extract the features
        for i in data_segments:
            features_csv = []
            features_csv = features_extraction.extract_features(i)
            label = str(folder)
            features_csv.append(label)
            main_df = main_df.append(pd.Series(features_csv, index=main_df.columns), ignore_index=True)

# Export to CSV for machine learning
main_df.to_csv("./features.csv")

# ##################################################################
# # For graph plotting and visualization purposes
# ##################################################################
#
# data = "D:\\Y4S1\\CS4276\\device-fingerprint\\data\\black_huawei\\gyro_100hz_14102019_143558.csv"
# # data = "D:\\Y4S1\\CS4276\\device-fingerprint\\data\\htc_u11\\gyro_100hz_16102019_205643.csv"
# # # data = "D:\\Y4S1\\CS4276\\device-fingerprint\\data\\mi_max\\gyro_100hz_14102019_212145.csv"
# data1 = "D:\\Y4S1\\CS4276\\device-fingerprint\\data\\black_huawei\\gyro_100hz_14102019_143651.csv"
# #
# name1 ="black_huawei"
# name2 ="black_huawei"
# #
# #
# # # For Black huawei
# data_segments = create_segments(data)
# # data_windows = create_window(data)
# #
# # # for blue huawei
# data1_segments = create_segments(data1)
# # data1_windows = create_window(data1)
# #
# # for black huawei
# features_segment = []
# for i in data_segments:
#     features_segment.append(features_extraction.extract_features(i))
#
# # for blue huawei
# features_segment1 = []
# for i in data1_segments:
#     features_segment1.append(features_extraction.extract_features(i))
#
#
# for j in range(len(features_segment[0])):
#     list1 = []
#     list2 = []
#     for i in features_segment:
#         list1.append(i[j])
#
#     for i in features_segment1:
#         list2.append(i[j])
#
#     plt.plot(list1, label=name1)
#     plt.plot(list2, label=name2)
#     plt.xlabel("segments")
#     plt.ylabel("readings")
#     legend = plt.legend(loc='upper center', shadow=True, fontsize='large')
#     if not os.path.exists("./" + name1 + "_" + name2):
#         os.mkdir("./" + name1 + "_" + name2)
#     plt.savefig("./" + name1 + "_" + name2 + "/" + str(j) + name1 + "_" + name2 + '.png')
#     plt.clf()
#


from flask_login import current_user
from html2text import html2text

from extensions import db
from models import Notification, Comment, DeletedPost, Reply
from flask import redirect, url_for, flash, abort, render_template
from utils import generate_date
from maintenance import clean_notifications
from post_system.reply.functions import get_comment_replies, get_full_comment_replies

def get_comment(comment_id):
    try:
        comment = Comment.query.get(comment_id)
    except AttributeError:
        return None
    if comment is not None:
        return comment
    return None

def add_comment(requested_post, comment):
    if requested_post:
        post_id = requested_post.id
        if current_user.is_authenticated:
            new_comment = Comment(author=current_user,
                                  parent_post=requested_post,
                                  comment=comment,
                                  date=generate_date())
            new_notification = Notification(user=requested_post.author, by_user=current_user.email,
                                            user_name=current_user.name,
                                            parent_comment=new_comment, category='comment',
                                            body=f"{current_user.name} commented on your post.",
                                            date=generate_date())
            db.session.add(new_comment, new_notification)
            db.session.commit()
            return redirect(url_for('post.show_post', post_id=post_id))
        else:
            flash("User is not logged in.")
            return redirect(url_for('post.show_post', post_id=post_id))
    else:
        return abort(404)

def get_comment_elements(comment_id, deleted, post_id):
    if comment_id:
        try:
            if deleted:
                if post_id:
                    requested_post = (DeletedPost.query.get(post_id).id, DeletedPost.query.get(post_id).json_column)
                    requested_comment = [comment for comment in requested_post[1]["comments"]
                                         if comment['comment_id'] == comment_id][0]
                    replies = requested_comment["replies"]
                    parent_post = requested_post
                else:
                    return abort(400)
            else:
                requested_comment = get_comment(comment_id)
                replies = requested_comment.replies
                parent_post = requested_comment.parent_post
            return requested_comment, replies, parent_post
        except (AttributeError, IndexError, KeyError):
            return abort(404)
    else:
        return abort(400)

def comment_edition(requested_comment, form, request='GET'):
    if requested_comment and form:
        if request == 'POST':
            try:
                requested_comment.comment = form.comment.data
            except AttributeError:
                return abort(400)
            db.session.commit()
            return redirect(url_for('comment.show_comment', comment_id=requested_comment.id))
        else:
            return render_template('config.html', config_title="Edit Your Comment",
                                   config_desc="Here, you'll be able to edit your comments.", form=form,
                                   config_func="edit_comment",
                                   comment_id=requested_comment.id)
    else:
        return abort(400)

def comment_deletion(requested_comment):
    if current_user.is_authenticated:
        if requested_comment.parent_post.author.email == current_user.email \
                or current_user.email == requested_comment.author.email:
            try:
                current_post = requested_comment.post_id
            except AttributeError:
                return abort(400)
            replies = Reply.query.filter_by(parent_comment=requested_comment).all()
            [db.session.delete(reply) for reply in replies]
            db.session.delete(requested_comment)
            [clean_notifications(current_category) for current_category in ['comment', 'reply']]
            db.session.commit()
            return redirect(url_for('post.show_post', post_id=current_post))
        else:
            return abort(403)
    else:
        return abort(401)

def get_comment_dict(comment):
    return {"comment_author": comment.author.name, "comment": html2text(comment.comment).strip(),
            "commented_on": comment.date,
            "replies": get_comment_replies(comment)}

def get_full_comment_dict(comment):
    return {"author_id": comment.author_id, "author": comment.author.name,
            "author_email": comment.author.email, "post_id": comment.post_id,
            "comment": comment.comment, "comment_id": comment.id,
            "date": comment.date, "replies": get_full_comment_replies(comment)}


from lib import coord_conversion
from lib import route_conversion
from lib import stop_conversion
from lib import arrival_conversion
from lib import message_conversion
import app_configuration as ac
import sys

local_coords = sys.argv[1]
gps_coords = sys.argv[2]
arrivals = sys.argv[3]
messages = sys.argv[4]
scenario = sys.argv[5]

print("Making trips list...")
trips = coord_conversion.make_trips(local_coords, gps_coords)

print("Making routes list...")
routes = route_conversion.make_routes(gps_coords)

print("Making stops list...")
stops = stop_conversion.make_stops(gps_coords, scenario)

print("Making arrivals list...")
arrivals = arrival_conversion.make_arrivals(arrivals, gps_coords)

print("Making messages list...")
messages = message_conversion.message_json(messages, gps_coords)

with open("toolkit/visualization/app/app.js", 'w') as template:
    ac.write_lines(routes, messages, stops, arrivals, trips, template, scenario)


from csv_data import CsvData
from node import Node
from test_case import TestCase
from decision_tree import DecisionTree
from anytree import Node as anyNode, RenderTree
import uuid

# set data first time
percent = input("Split percent(%) : ")

dataset = CsvData("quality")
dataset.setPath("data.csv")
data_test = dataset.splitData(percent)
dataset.initialize()
dataset.calculate()

root = Node(None, None, None, dataset)
root.uuid = str(uuid.uuid4().fields[-1])[:5]
root.an = anyNode(root.csv_data.max_attribute + ' >= ' + str(root.csv_data.result_calculate[root.csv_data.max_attribute].median) + " (" + str(len(root.csv_data.rows)) +")")

generate = DecisionTree(root, "quality")
generate.generate(root)
generate.copyGenerataGraph()
generate.printGraph()

root = generate.index

test_case = TestCase(root, data_test)
test_case.generateConfusedMatrix()

# print("lenght data test ",len(data_test))

# print("tp ", test_case.tp)
# print("tn ", test_case.tn)
# print("fp ", test_case.fp)
# print("fn ", test_case.fn)

total = test_case.tp + test_case.tn + test_case.fp + test_case.fn

# print("correctly ", test_case.tp+test_case.fn)
# print("incorrectly ", test_case.tn+test_case.fp)

# print("empty false ", test_case.empty_false)
# print("empty true ", test_case.empty_true)
print("Split Test (%) : ", percent)
print("\n====== Accuracy ======")
print("correcly percent (%) ", (test_case.tp+test_case.fn) / total * 100)
print("incorrectly percent (%) ", (test_case.tn+test_case.fp) / total * 100)

print("\n==== Confusion Matrix ====")
print("a : b")
print(test_case.fn, " : ", test_case.tn, " | a = no")
print(test_case.fp, " : ", test_case.tp, " | b = yes")

# print accuracy
yesDict = dict()
noDict = dict()

yesDict["tpRate"] = test_case.fp / (test_case.fp + test_case.tn)
yesDict["fpRate"] = test_case.tp / (test_case.tp + test_case.fn)

noDict["tpRate"] = test_case.fn / (test_case.fn + test_case.tp)
noDict["fpRate"] = test_case.tn / (test_case.tn + test_case.fp)

yesDict["recall"] = yesDict["tpRate"]
noDict["recall"] = noDict["tpRate"]

yesDict["precision"] = test_case.tp / (test_case.tp + test_case.fp)
noDict["precision"] = test_case.fn / (test_case.fn + test_case.tn)

yesDict["f-measure"] = 2 * (yesDict["precision"] * yesDict["recall"] / (yesDict["precision"] + yesDict["recall"]))
noDict["f-measure"] = 2 * (noDict["precision"] * noDict["recall"] / (noDict["precision"] + noDict["recall"]))

print("\n====== Detail accuracy by class =====")
print("Tp Rate : Fp Rate : Precision : Recall : F-Measure")
print(noDict["tpRate"], " : ", noDict["fpRate"], " : ", noDict["precision"], " : ", noDict["tpRate"], " : ", noDict["f-measure"], " -no")
print(yesDict["tpRate"], " : ", yesDict["fpRate"], " : ", yesDict["precision"], " : ", yesDict["tpRate"], " : ", yesDict["f-measure"], " -yes")
# print(dataset.attribute_types, " ", dataset.rows)


from PIL import Image
import cv2 as cv
import numpy as np
import mediapipe as mp
from syncronizer import Capture
from tqdm import tqdm

class Video:
    def __init__(self, name, reference, path):
        self.name = name
        self.reference = reference
        self.path = path
        self.Captures = []
        self.All_Normalized_Landmarks = []  # Format: [[[x,y,z],[x,y,z], ... , [x,y,z]], ...] # Dimensions: length x 33 x 3
        self.All_World_Landmarks = []  # Format: [[[x,y,z],[x,y,z], ... , [x,y,z]], ...] # Dimensions: length x 33 x 3
        self.reference_length_candidates = None
        self.position_candidates = None
        self.reference_lengths = []  # [0] -> Normalized reference length, [1] -> World reference length
        self.reference_positions = []  # [0] -> Normalized reference position, [1] -> World reference position
        self.normalization_factors = []  # [0] -> Normalized normalization factor, [1] -> World normalization factor
        self.translation_factor = []  # [0] -> Normalized translation factor, [1] -> World translation factor
        self.mean_errors = []
        self.fps = 30

    def deconstruct(self, shape):
        VIDEO_FILE = cv.VideoCapture(self.path)
        self.fps = int(VIDEO_FILE.get(cv.CAP_PROP_FPS) + 0.5)

        time = 0

        # Deconstruction into folders
        while True:
            # Extract images
            ret, frame = VIDEO_FILE.read()
            if not ret:
                break
            cv.resize(frame, shape, interpolation=cv.INTER_NEAREST)
            self.Captures.append(Capture(time, np.array(frame), self))
            time += 1

    def process(self, detector):
        counter = 0
        for capture in tqdm(self.Captures):
            image = mp.Image(image_format=mp.ImageFormat.SRGB, data=capture.frame)
            capture.detection_result = detector.detect(image)

            _ = []
            try:
                for landmark in capture.detection_result.pose_landmarks[0]:
                    _.append([landmark.x, landmark.y, landmark.z])
                self.All_Normalized_Landmarks.append(_)

                _ = []
                for landmark in capture.detection_result.pose_world_landmarks[0]:
                    _.append([landmark.x, landmark.y, landmark.z])
                self.All_World_Landmarks.append(_)
                counter += 1

            except:
                self.Captures[counter].detection_result = self.Captures[counter - 1].detection_result
                self.All_Normalized_Landmarks.append(self.All_Normalized_Landmarks[counter - 1])
                self.All_World_Landmarks.append(self.All_World_Landmarks[counter - 1])
                print(f"At {counter} the model had to approximate")
                counter += 1

            if len(self.All_Normalized_Landmarks) != counter:
                print(f"At {counter} normalized landmark is missing")

            if len(self.All_World_Landmarks) != counter:
                print(f"At {counter} world landmark is missing")

    def set_normalization_factors(self, ref):
        if self is not ref:
            normalized_normalization_factor = ref.reference_lengths[0] / self.reference_lengths[0]
            world_normalization_factor = ref.reference_lengths[1] / self.reference_lengths[1]

            self.normalization_factors = [normalized_normalization_factor, world_normalization_factor]
            # Set translation factors
            self.translation_factor.append(self.reference_positions[0]*self.normalization_factors[0] - ref.reference_positions[0])
            self.translation_factor.append(self.reference_positions[1]*self.normalization_factors[0] - ref.reference_positions[1])
        else:
            self.normalization_factors = [1, 1]
            self.translation_factor = [[0, 0, 0], [0, 0, 0]]

def set_average_length(objects):
    for obj in objects:
        obj.reference_lengths = [max(list(obj.reference_length_candidates[0].keys())),
                                 max(list(obj.reference_length_candidates[1].keys()))]

        # reference-point = 27
        obj.reference_positions = [obj.position_candidates[0][0][27],
                                   obj.position_candidates[1][0][27]]

def find_min(objects):
    lengths = []

    for obj in objects:
        lengths.append(obj.reference_lengths[0])

    return objects[lengths.index(min(lengths))]