"""
Train base model. This model will be used to continue training.
"""
from __future__ import print_function, division

import warnings
warnings.filterwarnings('ignore')

import os
import sys
import platform
from pathlib import Path
import psutil
import argparse
from datetime import datetime
from time import time
from pprint import pprint, pformat
from collections import OrderedDict
from glob import glob

import sklearn
import numpy as np
import pandas as pd

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

from sklearn.ensemble import RandomForestRegressor
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn.externals import joblib
from sklearn.metrics import r2_score, mean_absolute_error, median_absolute_error, explained_variance_score
from scipy.stats import spearmanr

import keras as ke
from keras import backend as K

from keras.models import Sequential, Model, model_from_json, model_from_yaml, load_model
from keras.optimizers import SGD, Adam, RMSprop, Adadelta
from keras.utils import np_utils, multi_gpu_model, plot_model
from keras.callbacks import Callback, ModelCheckpoint, CSVLogger, ReduceLROnPlateau, EarlyStopping

import lightgbm as lgb

SEED = 42
t_start = time()

# File path
file_path = Path(__file__).resolve().parent

# Utils
import utils

utils_path = file_path / '../../utils'
sys.path.append(str(utils_path))
#import utils
from classlogger import Logger
import ml_models
from ml_models import r2_krs

# Import custom callbacks
keras_contrib = '/vol/ml/apartin/projects/keras-contrib/keras_contrib/callbacks'
sys.path.append(keras_contrib)
from cyclical_learning_rate import CyclicLR

# Path
PRJ_NAME = Path(file_path.name)/'transfer_learn_keras'
OUTDIR = file_path / '../../out/' / PRJ_NAME

def parse_args(args):
    parser = argparse.ArgumentParser(description="Transfer learning.")

    # Input data
    parser.add_argument('-bs_dir', '--base_model_dir', default=None, type=str, help='Path to base (pre-trained) model dir.')
    parser.add_argument('--tl_src', default='PDM', type=str, choices=['CCLE', 'CTRP', 'gCSI', 'GDSC', 'NCI60', 'all'],
                        help='Data name for which we apply transfer learning (default: PDM).')
    parser.add_argument('--tl_method', default='fe', type=str, choices=['ft', 'fe'], help="'ft': finetune, 'fe': feature extractor")

    parser.add_argument('--trial', default=0, type=int, help='PDM trial (there are 10 trial, in each trial 10 cv splits; default: 0).')

    parser.add_argument('--drg_subset', default='all', choices=['pdm', 'common', 'all'], help='Drug subset to use for training (default: all).')

    parser.add_argument('-ml', '--model_name', type=str, default='nn_reg0', help="Model to use train baseline NN model (default: 'nn_reg0').")
    parser.add_argument('-ep', '--epochs', default=50, type=int, help='Epochs (default: 50).')
    parser.add_argument('-b', '--batch_size', default=32, type=float, help='Batch size (default: 32).')
    parser.add_argument('--dr_rate', default=0.2, type=float, help='Dropout rate (default: 0.2).')

    parser.add_argument('--opt', default='clr_exp', type=str, choices=['sgd', 'adam', 'clr_trng1', 'clr_trng2', 'clr_exp'], help="Optimizer name (default: 'clr_exp').")
    parser.add_argument('--base_lr', type=float, default=1e-4, help='Base lr for cycle lr.')
    parser.add_argument('--max_lr', type=float, default=1e-3, help='Max lr for cycle lr.')
    parser.add_argument('--gamma', type=float, default=0.999994, help='Gamma parameter for learning cycle LR (default: 0.999994).')

    parser.add_argument('-kp_to', '--keep_up_to', type=str, default='a4', help='Feature extraction (how many layers to keep).')
    parser.add_argument('-frz_to', '--freeze_up_to', type=str, default='drp4', help='Finetuning (until what layer to freeze the network).')

    parser.add_argument('--skp_ep', type=int, default=3, help='Number of epochs to skip when plotting training curves.')
    parser.add_argument('--n_jobs', default=8, type=int, help='Number of cpu workers (default: 4).')
    args = parser.parse_args(args)
    return args

def create_outdir(outdir, args):
    t = datetime.now()
    t = [t.year, '-', t.month, '-', t.day, '_', 'h', t.hour, '-', 'm', t.minute]
    t = ''.join([str(i) for i in t])

    l = [args['bs_src'] + '_to_'+args['tl_src']] + [args['tl_method']] + [args['opt']] +  ['ep'+str(args['epochs'])] + ['drp'+str(args['dr_rate'])]

    name_sffx = '.'.join( l )
    outdir = Path(outdir) / (name_sffx + '_' + t)
    os.makedirs(outdir)
    return outdir

def run(args):
    base_model_dir = Path(args['base_model_dir'])
    tl_src = args['tl_src']
    tl_method = args['tl_method']
    trial = args['trial']

    ccl_fea_list = ['geneGE']
    drg_fea_list = ['DD']
    drg_subset = args['drg_subset']
    fea_sep = '_'

    model_name = args['model_name']
    epochs = args['epochs']
    batch_size = args['batch_size']
    dr_rate = args['dr_rate']
    opt_name = args['opt']
    base_lr = args['base_lr']
    max_lr = args['max_lr']
    gamma = args['gamma']
    skp_ep = args['skp_ep']

    n_jobs = args['n_jobs']
    verbose = True

    # Extract data sources used for base model training and transfer learning
    bs_src = str(base_model_dir).split('/')[-1].split('.')[0]
    args['bs_src'] = bs_src

    # Split of the dataset used for TRANSFER LEARNING
    bs_fold = 0

    # Transfer learning parameters
    keep_up_to = args['keep_up_to'] # feature extractor
    freeze_up_to = args['freeze_up_to'] # finetune

    # =====================================================
    #       Logger
    # =====================================================
    run_outdir = create_outdir(OUTDIR, args)
    lg = Logger(run_outdir/'logfile.log')
    lg.logger.info(f'File path: {file_path}')
    lg.logger.info(f'\n{pformat(args)}')

    # Dump args to file
    utils.dump_dict(args, run_outdir/'args.txt')

    # =====================================================
    #       Some global NN configs
    # =====================================================
    if opt_name == 'clr_trng1':
        clr = CyclicLR(base_lr=base_lr, max_lr=max_lr, mode='triangular')
    elif opt_name == 'clr_trng2':
        clr = CyclicLR(base_lr=base_lr, max_lr=max_lr, mode='triangular2')
    elif opt_name == 'clr_exp':
        clr = CyclicLR(base_lr=base_lr, max_lr=max_lr, mode='exp_range', gamma=gamma) # 0.99994; 0.99999994; 0.999994

    reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.75, patience=20, verbose=1, mode='auto',
                                  min_delta=0.0001, cooldown=3, min_lr=0.000000001)
    early_stop = EarlyStopping(monitor='val_loss', patience=100, verbose=1)

    # =====================================================
    #       Load data for Transfer Learning
    # =====================================================
    data = utils.load_data(file_path, src=tl_src,
            ccl_fea_list=ccl_fea_list, drg_fea_list=drg_fea_list,
            drg_subset=drg_subset,
            fea_sep=fea_sep, logger=lg.logger)

    if tl_src == 'PDM':
        main_folds_dir = Path(file_path/f'../../data/yitan/PDM_10Fold_Partition/trial_{trial}/')
        matched_to = bs_src
    else:
        main_folds_dir = Path(file_path/f'../../data/yitan/CCL_10Fold_Partition/{tl_src}/')
        matched_to = None

    # These lists contain scores for all folds
    all_bs_lgbm_scores = []
    all_bs_rf_scores = []
    #all_bs_nn_scores = []
    all_tl_scores = []

    # These lists contain preds for all folds
    all_bs_lgbm_preds = []
    all_bs_rf_preds = []
    #all_bs_nn_preds = []
    all_tl_preds = []

    for tl_fold in range(10):
        lg.logger.info('\n{}'.format('=' * 70))
        lg.logger.info('Start fold {}'.format(tl_fold))
        ids_path = main_folds_dir/f'cv_{tl_fold}'
        data_tr, data_vl, data_te = utils.get_splits_per_fold(data, ids_path, logger=None)

        xtr, ytr, mtr = utils.extract_data(data_tr, fea_list = ccl_fea_list+drg_fea_list, matched_to=matched_to)
        xvl, yvl, mvl = utils.extract_data(data_vl, fea_list = ccl_fea_list+drg_fea_list, matched_to=matched_to)
        xte, yte, mte = utils.extract_data(data_te, fea_list = ccl_fea_list+drg_fea_list, matched_to=matched_to)

        # Create dir to save results for the current fold
        fold_outdir = run_outdir/f'cv{tl_fold}'
        os.makedirs(fold_outdir)

        # =====================================================
        #       Scale (CV can start here) --> TODO: don't scale embeddeings
        # =====================================================
        scalerpath = base_model_dir/f'cv{bs_fold}'/'scaler.pkl'
        scaler = joblib.load(scalerpath)

        cols = xtr.columns
        xtr = pd.DataFrame( scaler.transform(xtr), columns=cols, dtype=np.float32 )
        xvl = pd.DataFrame( scaler.transform(xvl), columns=cols, dtype=np.float32 )
        xte = pd.DataFrame( scaler.transform(xte), columns=cols, dtype=np.float32 )
        # joblib.dump(scaler, outdir/'scaler.pkl')

        # =====================================================
        #      Train baseline (w/o transfer learning)
        # =====================================================
        lg.logger.info('\n{}'.format('-' * 50))
        lg.logger.info('Train LGBM (baseline) ...')
        baseline_lgbm_dir = fold_outdir/'baseline_lgbm'
        os.makedirs(baseline_lgbm_dir)

        # Define and train model
        init_kwargs = {'objective': 'regression', 'n_estimators': 100, 'n_jobs': n_jobs, 'random_state': SEED}
        model = lgb.LGBMModel(**init_kwargs)

        t0 = time()
        fit_kwargs = {'eval_set': (xvl, yvl), 'early_stopping_rounds': 10, 'verbose': False}
        model.fit(xtr, ytr, **fit_kwargs)
        lg.logger.info('Train time: {:.1f} mins'.format( (time()-t0)/60 ))

        # Predict
        pred_ytr = model.predict(xtr).squeeze()
        pred_yvl = model.predict(xvl).squeeze()
        pred_yte = model.predict(xte).squeeze()

        # Append preds
        ptr = mtr.copy(); ptr['fold']=tl_fold; ptr['phase']='tr'; ptr['auc_pred']=pred_ytr
        pvl = mvl.copy(); pvl['fold']=tl_fold; pvl['phase']='vl'; pvl['auc_pred']=pred_yvl
        pte = mte.copy(); pte['fold']=tl_fold; pte['phase']='te'; pte['auc_pred']=pred_yte
        all_bs_lgbm_preds.append( pd.concat([ptr, pvl, pte], axis=0) )

        # Append scores
        lg.logger.info('\nBaseline LGBM:')
        scores = utils.calc_scores(ytr, pred_ytr, yvl, pred_yvl, yte, pred_yte, logger=lg.logger)
        utils.dump_dict(scores, baseline_lgbm_dir/'lgbm_baseline_scores.txt')
        all_bs_lgbm_scores.append(scores) # agg scores
        del model, scores, pred_ytr, pred_yvl, pred_yte, ptr, pvl, pte

        # =====================================================
        #       Load base (pre-trained) model and predict w/o transfer learning
        # =====================================================
        # modelpath = base_model_dir/f'cv{bs_fold}'/'final_model.h5'
        # model = load_model(str(modelpath), custom_objects={'r2_krs': r2_krs})
        modelpath = base_model_dir/f'cv{bs_fold}'/'model_best.h5'
        model = load_model( str(modelpath) )
        plot_model(model, to_file=fold_outdir/'nn_model.png')

        # =====================================================
        #       Transfer learning
        # =====================================================
        # Reset model
        lr_new = 5e-4
        model.compile(loss='mean_squared_error', optimizer=SGD(lr=lr_new, momentum=0.9), metrics=['mae'])

        # Callbacks
        checkpointer = ModelCheckpoint(str(run_outdir/'model_best.h5'), verbose=0, save_weights_only=False, save_best_only=True)
        csv_logger = CSVLogger(fold_outdir/'training.log')

        # Callbacks list
        callbacks = [checkpointer, csv_logger, early_stop, reduce_lr]
        if 'clr' in opt_name: callbacks.append(clr)

        # -------------------------------
        # Choose transfer learning method
        # -------------------------------
        if tl_method=='fe':
            # Feature extractor
            # utils.print_trainable_layers(model, print_all=True)
            utils.pop_layers(model, keep_up_to=keep_up_to)
            # utils.print_trainable_layers(model, print_all=True)

            # Create feature extractor model
            fea_extractor_model = Model(inputs=model.input, outputs=model.layers[-1].output)

            # Extract featues
            xtr_fea_ext = fea_extractor_model.predict(xtr)
            xvl_fea_ext = fea_extractor_model.predict(xvl)
            xte_fea_ext = fea_extractor_model.predict(xte)
            # print(xvl_fea_ext.shape)

            ## Train final model on extracted features
            #lg.logger.info('\n{}'.format('-' * 50))
            #lg.logger.info('Train LGBM feature extractor ...')

            #init_kwargs = {'objective': 'regression', 'n_estimators': 100, 'n_jobs': n_jobs, 'random_state': SEED}
            #model = lgb.LGBMModel(**init_kwargs)

            #t0 = time()
            #fit_kwargs = {'eval_set': (xvl_fea_ext, yvl), 'early_stopping_rounds': 10, 'verbose': False}
            #model.fit(xtr_fea_ext, ytr, **fit_kwargs)
            #lg.logger.info('Train time: {:.1f} mins'.format( (time()-t0)/60 ))

            # Train final model on extracted features
            lg.logger.info('\n{}'.format('-' * 50))
            lg.logger.info('Train RF feature extractor ...')

            init_kwargs = {'n_estimators': 100, 'n_jobs': n_jobs, 'random_state': SEED, 'min_samples_split': 7}
            model = RandomForestRegressor(**init_kwargs)

            t0 = time()
            model.fit(xtr_fea_ext, ytr)
            lg.logger.info('Train time: {:.1f} mins'.format( (time()-t0)/60 ))

            # Predict
            pred_ytr = model.predict(xtr_fea_ext)
            pred_yvl = model.predict(xvl_fea_ext)
            pred_yte = model.predict(xte_fea_ext)

            # Append preds
            ptr = mtr.copy(); ptr['fold']=tl_fold; ptr['phase']='tr'; ptr['auc_pred'] = pred_ytr
            pvl = mvl.copy(); pvl['fold']=tl_fold; pvl['phase']='vl'; pvl['auc_pred'] = pred_yvl
            pte = mte.copy(); pte['fold']=tl_fold; pte['phase']='te'; pte['auc_pred'] = pred_yte
            all_tl_preds.append( pd.concat([ptr, pvl, pte], axis=0) )

            # Append scores
            lg.logger.info('\nScores Feature extractor LGBM:')
            tl_scores = utils.calc_scores(ytr, pred_ytr, yvl, pred_yvl, yte, pred_yte, logger=lg.logger)
            utils.dump_dict(tl_scores, outpath=fold_outdir/'fe_scores.txt')

        elif tl_method=='ft':
            # Finetune
            lg.logger.info('\n{}'.format('-' * 50))
            lg.logger.info('Finetune NN ...')

            # utils.print_trainable_layers(model, print_all=True)
            utils.freeze_layers(model, freeze_up_to=freeze_up_to)
            # utils.print_trainable_layers(model, print_all=True)

            # Fit params
            fit_kwargs = {'epochs': epochs, 'batch_size': batch_size, 'verbose': 1}
            # fit_kwargs['validation_data'] = (xvl, yvl)
            fit_kwargs['validation_split'] = 0.2
            fit_kwargs['callbacks'] = callbacks

            t0 = time()
            history = model.fit(xtr, ytr, **fit_kwargs)

            lg.logger.info('Train time: {:.1f} mins'.format( (time()-t0)/60 ))

            # Predict
            pred_ytr = model.predict(xtr).squeeze()
            pred_yvl = model.predict(xvl).squeeze()
            pred_yte = model.predict(xte).squeeze()

            # Append preds
            ptr = mtr.copy(); ptr['fold']=tl_fold; ptr['phase']='tr'; ptr['auc_pred']=pred_ytr
            pvl = mvl.copy(); pvl['fold']=tl_fold; pvl['phase']='vl'; pvl['auc_pred']=pred_yvl
            pte = mte.copy(); pte['fold']=tl_fold; pte['phase']='te'; pte['auc_pred']=pred_yte
            all_tl_preds.append( pd.concat([ptr, pvl, pte], axis=0) )

            # Append scores (transfer learning)
            lg.logger.info('\nScores using finetune:')
            tl_scores = utils.calc_scores(ytr, pred_ytr, yvl, pred_yvl, yte, pred_yte, logger=lg.logger)
            utils.dump_dict(tl_scores, outpath=fold_outdir/'ft_scores.txt')

            ml_models.plot_prfrm_metrics(history, title=f'Train base model {model_name}',
                                         skp_ep=skp_ep, add_lr=True, outdir=fold_outdir)
            ml_models.save_krs_history(history, fold_outdir)

        del model, pred_ytr, pred_yvl, pred_yte, ptr, pvl, pte
        all_tl_scores.append(tl_scores) # agg scores

    def scores_to_file(scores, outpath, rnd=5):
        """ Dump scores to file. """
        scores = pd.DataFrame.from_dict(scores).T
        scores.columns = ['fold'+str(f+1) for f in range(scores.shape[1])]
        scores.insert(loc=0, column='std', value=scores.std(axis=1))
        scores.insert(loc=0, column='mean', value=scores.iloc[:,1:].mean(axis=1))
        scores.index.name = 'metric'
        scores.reset_index(inplace=True)
        scores.round(rnd).to_csv(outpath, index=False)

    # Dump all scores
    scores_to_file(all_bs_lgbm_scores, run_outdir/'folds_bs_lgbm_scores.csv')
    scores_to_file(all_bs_rf_scores, run_outdir/'folds_bs_rf_scores.csv')
    scores_to_file(all_tl_scores, run_outdir/'folds_tl_scores.csv')

    # Dump all preds
    all_bs_lgbm_preds = pd.concat(all_bs_lgbm_preds, axis=0, ignore_index=True)
    all_bs_lgbm_preds.round(5).to_csv(run_outdir/'all_bs_lgbm_preds.csv', index=False)
    all_bs_rf_preds = pd.concat(all_bs_rf_preds, axis=0, ignore_index=True)
    all_bs_rf_preds.round(5).to_csv(run_outdir/'all_bs_rf_preds.csv', index=False)
    all_tl_preds = pd.concat(all_tl_preds, axis=0, ignore_index=True)
    all_tl_preds.round(5).to_csv(run_outdir/'all_tl_preds.csv', index=False)

    def preds_to_scores(preds, logger=None):
        scores = {}
        for ph in preds['phase'].unique():
            a = preds[ preds['phase']==ph ]
            scores[f'r2_{ph}'] = r2_score(a['auc'], a['auc_pred'])
            scores[f'mae_{ph}'] = mean_absolute_error(a['auc'], a['auc_pred'])
            scores[f'spr_rnk_corr_{ph}'] = spearmanr(a['auc'], a['auc_pred'])[0]

        scores = {k: scores[k] for k in sorted(scores.keys())}
        for k, v in scores.items(): scores[k] = round(v, 4)
        if logger is not None:
            for k, v, in scores.items(): logger.info(f'{k}: {v}')
        return scores

    lg.logger.info('\nLGBM basline scores:')
    lgbm_scores = preds_to_scores(all_bs_lgbm_preds, logger=lg.logger)
    lg.logger.info('\nRF basline scores:')
    rf_scores = preds_to_scores(all_bs_rf_preds, logger=lg.logger)
    lg.logger.info('\nTransfer learning scores:')
    tl_scores = preds_to_scores(all_tl_preds, logger=lg.logger)

    utils.dump_dict(lgbm_scores, run_outdir/'lgbm_baseline_scores.txt')
    utils.dump_dict(rf_scores, run_outdir/'rf_baseline_scores.txt')
    utils.dump_dict(tl_scores, run_outdir/'transfer_learn_scores.txt')

    lg.kill_logger()

def main(args):
    args = parse_args(args)
    args = vars(args)
    ret = run(args)

if __name__ == '__main__':
    """ __name__ == '__main__' explained: www.youtube.com/watch?v=sugvnHA7ElY """
    main(sys.argv[1:])


"""
函数：将CNU门完全分解
cnnot_decompose(cu_vector:表征地位的数组)  --->  result
result：分解结果，是一个通用门序列
"""

from QuantumCircuit.GivensDecompose.cnnot_decompose import *
from QuantumCircuit.Usage.hermite import *

def cnu_decompose(cu_vector, U):  # cu_vector表示了各个位置的地位，U是作用的效果

    ## 1是控制位，2是目标位，-1是无关位
    moment=cu_vector.copy()
    num=0  # 控制位的个数
    for i in range(len(cu_vector)):
        if cu_vector[i]==1:
            num=num+1
            control_pre=i
        elif cu_vector[i]==2:
            target_pre=i
    V=to_hermite(U)  # 将作用效果表示为矩阵V
    result=[]  # 结果储存在result里面

    if num==1:
        result=cu_decompose(U,control_pre,target_pre)
    else:
        ## 第一层循环，寻找目标位
        for target in range(len(cu_vector)):
            if moment[target]==2:

                ## 第二层循环，寻找控制位
                for control in range(len(cu_vector)):
                    if moment[control]==1:

                        ## 将线路分解
                        result=result+cu_decompose(V.copy(),control,target) # 第一个量子门是一个受控U门
                        result=result+cnnot_decompose(moment)  # 第二个量子门是一个少一阶的CNNOT门
                        result=result+cu_decompose(V.conjugate().transpose().copy(),control,target)  # 第三个量子门是一个受控U门
                        result=result+cnnot_decompose(moment)  # 第四个量子门是一个少一阶的CNNOT门
                        num=num-1  # 控制位减少1
                        moment[control] = -1  # 控制位变无关位

                        ## 如果减少一个控制位后为CU门，则直接给出
                        if num==1:
                            result=result+cu_decompose(V.copy(),control,target)  # 如果分解到只剩一个控制位，那么就是一个CU门
                            break

                        ## 否则继续寻找下一个控制位，对C^n-V门继续分解
                        else:
                            V = to_hermite(V)

                break  # 跳出循环

    return result  # 返回结果

## 用于测试结果
if __name__ == '__main__':
    result_test = cnu_decompose([1,-1,1,2,1],H)  # 输出结果
    print(result_test)  # 打印结果
    output_operator(result_test,5)


# config: utf8

import importlib
import os
import sys

from ... import config
from .module_scanner import ModuleScanner

class DirScanner(object):
    """
    扫描指定的目录，得到所有的服务元数据, 该目录一般是对应项目的根目录
    """

    def __init__(self, target_dir):
        self.cur_dir = os.path.abspath(os.curdir)
        self.target_dir = target_dir
        sys.path.append(target_dir)
        os.chdir(target_dir)

    def gather(self):
        """
        获取目标目录下的复合条件的所有类型
        :return:
        """
        target_dir = self.target_dir
        if config.outside_server:
            # 如果是生成独立项目，则需要在扫描时进入该子目录，扫描完成后退出来
            target_dir = os.path.join(config.outside_server_path, config.source_project_name)
        self.scan_file(target_dir, "")
        if config.outside_server:
            os.chdir(self.target_dir)
        return ModuleScanner().gather()

    def scan_file(self, target_dir, rel_path):
        """
        :param target_dir:
        :param rel_path
        :return:
        """

        # if os.path.exists(os.path.join(target_dir, "__init__.py")):
        #     self.import_file(rel_path, "")

        for entry in os.scandir(target_dir):
            if entry.is_file() and entry.name.endswith(".py"):
                self.import_file(rel_path, entry.name[:-3])
            elif entry.is_dir():
                # only python package dir
                next_dir = os.path.join(target_dir, entry.name)
                if not os.path.exists(os.path.join(next_dir, "__init__.py")):
                    continue

                # import the package first
                self.import_file(rel_path, entry.name)
                # then get into deeper
                self.scan_file(
                    next_dir,
                    ".".join(rel_path and [rel_path, entry.name] or [entry.name]))

    @staticmethod
    def import_file(target_dir: str, target_file: str):
        path_elem = target_dir and [target_dir, target_file] or [target_file]
        path = ".".join(path_elem)
        try:
            importlib.import_module(path)
        except Exception as e:
            if "_tkinter" not in str(e):
                print(("导入文件 %s 出错，错误信息为: %s" % (path, str(e))))

    def __del__(self):
        # sys.path.remove(self.cur_dir)
        # os.chdir(self.cur_dir)
        pass


dia = int(input("Ingrese un número: "))
mes = int(input("Ingrese un número: "))
año = int(input("Ingrese un número: "))
resultado = (f"{dia}/{mes}/{año}")

# dia

if dia <= 31 and dia > 0:
    print(f"dia {dia}")

else:
    print("no existe ese dia")

# mes

if mes <= 12 and  mes > 0:
    print(f"mes {mes}")

else:
    print("no existe ese mes")

# año

if año <= 2023 and año > 0:
    print(f"año {año}")

else:
    print("no existe ese año")

#resultado

if  dia <= 31 and dia > 0 and mes <= 12 and  mes > 0 and año <= 2023 and año > 0:
    print(f"estamos a {resultado}")

else:
    print("fecha invalida")


#lagrange
d=int(input("number of point:"))
n=int(input("polynomial order:"))
X=float(input("X:"))

x=[]

for i in range(d+1):
	print("cofficient of x_",i+1,":")
	x.append(float(input()))

y=[]
for i in range(d+1):
	print("coefficent of f(x)",i+1,":")
	y.append(float(input()))

I=[]
uper = 1
down = 1

for j in range(n):
	uper=1
	down=1
	for k in range(n):
		if(j!=k):
			uper *=(X-x[k])
			down *=(x[j]-x[k])

	I.append(float(uper/down))
print(I)

p=0.0
for h in range(0,n,1):
	p +=(y[h]*I[h])
print("result: ",p)


# coding: utf-8

# In[1]:

import numpy as np
import csv
import pandas

csv = pandas.read_csv(filepath_or_buffer="DataDaily.csv", sep=";")
csv

# In[2]:

mean = csv.mean()

# In[3]:

covmatr = csv.cov()

# In[4]:

matrixCov = covmatr.as_matrix()

matrixCov.shape
eigenvalues, eigenvectors = np.linalg.eigh(matrixCov)

# In[7]:

size = eigenvalues.size

eigenvalues[size - 3:size]

# In[9]:

#соответсвующие собственные векора eignvertor[]

b3 = eigenvectors[:, size-3]
lambda3 = eigenvalues[size-3]

b2 = eigenvectors[:, size-2]
lambda2 = eigenvalues[size-2]

b1 = eigenvectors[:, size-1]
lambda1 = eigenvalues[size-1]

print(b1)
print(lambda1)
print("------------")
print(b2)
print(lambda2)
print("------------")
print(b3)
print(lambda3)
print("------------")

# In[10]:

fac1 = [-2.45, -1.63, -0.82, 0, 0.82, 1.63, 2.45]
prob1 = [0.016, 0.094, 0.234, 0.313, 0.234, 0.094, 0.016]

fac2 = [-2, -1.000, 0.000 ,1.000 ,2.000]
prob2 = [0.062, 0.250, 0.370, 0.250, 0.062]

fac3 = [-1.410, 0.000, 1.410]
prob3 = [0.25, 0.5, 0.25]

# In[13]:

#iter method
import scipy.stats as stats

delta = 0.1
eps = 0.001

def iterStep(x, n, val):
    flag = False
    x[0] = val
    x[1] = invF(2*F(x[0]))
    for i in range(1, n-1):
        odd(i, x)
        even(i, x, flag)
    odd(n-1, x)
    print(G(x,n))

def IterMet(n, delta):
    x = np.zeros(2*n-1)
    flag = False
    iterStep(x, n, invF(2 ** (-n)))
    valueG = G(x, n)
    prevG = valueG
    while (abs(valueG) > eps or delta < 0.001):
        valueG = G(x, n)
        if (prevG*valueG < 0):
            delta /= 2
        prevG = valueG
        if (valueG > 0):
            iterStep(x, n, x[0] + delta)
        else:
            iterStep(x, n, x[0] - delta)
    print("Итоговая точность")
    print(G(x,n))
    print()
    return x

def invF(x):
    return stats.norm.ppf(x)

def F(x):
    return stats.norm.cdf(x)

def odd(i, x):
    x[2*i] =  2 * x[2*i-1] - x[2*i - 2]

def even(i, x, flag):
    value = -F(x[2*i-1]) + 2 * F(x[2*i])
    if (value > 1):
        print("error")
        print(2 * i + 1)
        print(value)
        flag = True
    if (value < 0):
        print("error")
        print(2 * i + 1)
        print(value)
        flag = True
    x[2*i + 1] = invF(value)

def G(x, n):
    return F(x[2*n-3]) - 2*F(x[2*n-2]) + 1

x = IterMet(2, delta)
a3 = x[:3:2]

x = IterMet(4, delta)
a2 = x[:7:2]

x = IterMet(6, delta)
a1 = x[:11:2]

print()
print(a1)
print(a2)
print(a3)

# In[14]:

def probV(a, n):
    prob = np.zeros(n+1)
    prob[0] = F(a[0])
    for i in range(1,n):
        prob[i] = F(a[i]) - F(a[i-1])
    prob[n] = 1 - F(a[n-1])
    return prob

# In[15]:

probvecUpd1 = probV(a1, 6)

# In[16]:

probvecUpd2 = probV(a2, 4)

# In[17]:

probvecUpd3 = probV(a3, 2)

# In[18]:

import scipy.integrate as integrate
from scipy.integrate import quad

def integrand(x):
    return x*stats.norm.pdf(x)

def findvalue(n, a, b):
    x = np.zeros(n+1)
    x[0] , err = quad(integrand, a=-np.inf, b=a[0]) / b[0]
    for i in range (1,n):
        x[i], err =  quad(integrand, a=-a[i-1], b=a[i]) / b[i]
    x[n] , err =  quad(integrand, b=np.inf, a=a[n-1]) / b[n]
    return x

val1 = findvalue(6, a1, probvecUpd1)
val2 = findvalue(4, a2, probvecUpd2)
val3 = findvalue(2, a3, probvecUpd3)

val1 = val1.tolist()
probvecUpd1 = probvecUpd1.tolist()

val2 = val2.tolist()
probvecUpd2 = probvecUpd2.tolist()

val3 = val3.tolist()
probvecUpd3 = probvecUpd3.tolist()

print(val1)
print(probvecUpd1)
print()
print(val2)
print(probvecUpd2)
print()
print(val3)
print(probvecUpd3)

# In[19]:

csvmodel = pandas.read_csv(filepath_or_buffer="2k15day.csv", sep=";", index_col=0)
csvmodel

# In[20]:

times = csvmodel.index.size - 1
times

# In[21]:

import matplotlib.pyplot as plt
matrModel = csvmodel.as_matrix()

d = np.zeros(matrModel[0].size)
for i in range(0, len(d)):
    d[i] = 1000 / matrModel[0][i]
d

# In[24]:

P = np.zeros(len(matrModel))
deltaP = np.zeros(len(P) - 1)

for idx in range(0, len(matrModel)):
    for pos in range(0, len(matrModel[idx])):
        P[idx] += matrModel[idx][pos] * d[pos]

for idx in range(0, len(P) - 1):
    deltaP[idx] = round(P[idx+1] - P[idx])

deltaP

df = pandas.DataFrame({'DeltaP' : deltaP}, index=csvmodel.index[:times])

# In[25]:

#монте-карло
import math as math

def monteF():
    w1 = np.random.normal()
    w2 = np.random.normal()
    w3 = np.random.normal()
    arr = np.zeros(mean.size)
    for indx in range(0, mean.size):
        arr[indx] = montefunc(indx, w1, w2, w3)
    return arr

def montefunc(idx, w1, w2, w3):
    return math.exp(mean[idx] + math.sqrt(lambda1) * b1[idx] * w1 +
                   math.sqrt(lambda2) * b2[idx] * w2 +
                   math.sqrt(lambda3) * b3[idx] * w3)

# In[26]:

def func(prob1, fac1):
    rand = np.random.uniform()
    sum1 = 0
    for prob in prob1:
        sum1 += prob
        if rand < sum1:
            return fac1[prob1.index(prob)]
    return fac1[len(prob1) - 1]

# In[27]:

def funcScenario(prob1, fac1, prob2, fac2, prob3, fac3):
    w1 = func(prob1, fac1)
    w2 = func(prob2, fac2)
    w3 = func(prob3, fac3)
    arr = np.zeros(mean.size)
    for indx in range(0, mean.size):
        arr[indx] = montefunc(indx, w1, w2, w3)
    return arr

# In[28]:

#for Var
count = 500
shortfall = np.zeros(times)
alpha = 0.05
p =round(count * alpha)

varScenario = np.zeros(times)
for j in range(0,times):
    valueofP = []
    for i in range(0, count):
        valueofP.append(funcScenario(prob1, fac1,prob2,fac2,prob3,fac3))
    startv = matrModel[j] * d

    startp = np.dot(startv, np.ones(matrModel[j].size))

    value = np.zeros(count)

    for i in range(0, count):
        value[i] = np.dot(valueofP[i], startv)

    value.sort()
    varScenario[j] = value[p] - startp
    for i in range(0, p):
        shortfall[j] += value[i] - startp
    shortfall[j] /= p

# In[29]:

#for Var Updated
countf2 = 500

shortfallUpd = np.zeros(times)

varScenarioUpd = np.zeros(times)
for j in range(0,times):
    valueofP = []
    for i in range(0, count):
        valueofP.append(funcScenario(probvecUpd1, val1,probvecUpd2,val2,probvecUpd3,val3))
    startv = matrModel[j] * d

    startp = np.dot(startv, np.ones(matrModel[j].size))

    value = np.zeros(count)

    for i in range(0, count):
        value[i] = np.dot(valueofP[i], startv)

    value.sort()
    varScenarioUpd[j] = value[p] - startp
    for i in range(0, p):
        shortfallUpd[j] += value[i] - startp
    shortfallUpd[j] /= p

# In[30]:

var1 = -varScenario
var2 = -varScenarioUpd
deltap1 = -deltaP
for i in range(0, len(deltap1)):
    if deltap1[i] < 0:
        deltap1[i] = 0
title = "Var " + str(alpha)
df1 = pandas.DataFrame({'varScenario' : var1, 'varScenarioUpd' : var2, 'Loses' : deltap1 }, index=csvmodel.index[:times])
df1
df1.plot(kind="line", title=title)
plt.show()

# In[31]:

var1sh = -shortfall
var2sh = -shortfallUpd
deltap1 = -deltaP
for i in range(0, len(deltap1)):
    if deltap1[i] < 0:
        deltap1[i] = 0

df1 = pandas.DataFrame({'shortfall' : var1sh, 'shorfallUpd' : var2sh, 'Loses' : deltap1 }, index=csvmodel.index[:times])
df1
df1.plot(kind="line", title="Shortfall " + str(alpha))
plt.show()

# In[32]:

m2 =df1.shorfallUpd.mean()

# In[33]:

m1 = df1.shortfall.mean()

# In[34]:

dict1 = {'mean' : [m1, m2]}

# In[35]:

df3 = pandas.DataFrame(dict1, index=["shortfall", "shortfallUpd"] )
df3

# In[ ]:


"""
@author: Ming Ming Zhang, mmzhangist@gmail.com

Utilities
"""

import time
import random
import numpy as np
import skimage.io, skimage.color, skimage.transform

############################################################
#  Image Preprocessing
############################################################

def load_image(image_path, mode):
    """
    Loads an image into RGB or gray.

    Parameters
    ----------
    image_path : string
        The image file path.

    Returns
    -------
    image : numpy array, [h, w, 3] for RGB or [h, w] for gray
        Loaded image.

    """
    image = skimage.io.imread(image_path)

    assert mode in ['gray', 'rgb']
    if mode == 'rgb':
        # convert to RGB if it is grayscale
        if image.ndim != 3:
            # print('%s was grayscale'%image_path)
            image = skimage.color.gray2rgb(image)
        # convert to RGB if it is RGBA
        if image.shape[-1] == 4:
            # print('%s was RGBA'%image_path)
            image = image[..., :3]

    else:
        # convert to grayscale if it is RGB
        if image.ndim != 2:
            # print('%s was RGB'%image_path)
            image = skimage.color.rgb2gray(image)

    return image

def resize_image(
        image,
        shortest_side=512,
        longest_side=1024,
        upscale_factor=1.0,
        mode='crop'
        ):
    """
    Resizes an image without changing the aspect ratio.

    Parameters
    ----------
    image : numpy array, [height, width, channels]
        The image needed to be resized.
    shortest_side : integer, optional
        The shortest side of the resized image. Note that it only applies to
        the 'crop' mode. The default is 512.
    longest_side : integer, optional
        The longest side of the resized image. Note that it only applies to the
        'pad_square' mode. The default is 1024.
    upscale_factor : float, optional
        The scale factor >= 1.0 to upscale the image. The default is 1.0.
    mode : string, optional
        The resizing method in {'none'', 'pad_square', 'crop}. The default is
        'crop'.
        * 'none' : [height, width, channels], no resizing nor padding applied.
        * 'pad_square' : [longest_side, longest_side, channels], padded with 0
        to keep the same aspect ratio.
        * 'crop' : [shorest_side, shortest_side, channels].

    Returns
    -------
    image : numpy array, [resized_h, resized_w, channels]
        The resized image depending on the mode with the same data type as the
        input image.
    window : tuple
        The corner coordinates (y1, x1, y2, x2) indicates the location of the
        resized image before padding.
    scale : float
        The scale factor from original to resized image, and used in the later
        resize_mask().
    padding : list
        The padding applied to the original image in the form of pixels
        [(top, bottom), (left, right), (0, 0)], and used in the later
        resize_mask().
    crop : tuple
        The coordinates (y1, x1, h, w) indicates the location of the
        cropped image over the resized image, and used in the later
        resize_mask().

    """
    assert mode in ['none', 'pad_square', 'crop']

    image_dtype = image.dtype
    h, w = image.shape[:2]
    window = (0, 0, h, w)
    scale = 1.0
    if image.ndim == 3:
        padding = [(0,0), (0,0), (0,0)]
    else:
        padding = [(0,0), (0,0)]
    crop = None

    if mode == 'none':
        return image, window, scale, padding, crop

    # upscale for all modes, scale >= 1.0
    scale = max(1.0, shortest_side / min(h, w))
    if scale < upscale_factor:
        scale = upscale_factor

    # downscale only if mode == 'pad_square', scale < 1.0
    if mode == 'pad_square':
        max_side = max(h, w)
        if round(max_side * scale) > longest_side:
            scale = longest_side / max_side

    # resize image using bilinear
    if scale != 1.0:
        image = skimage.transform.resize(
            image,
            output_shape=(round(h * scale), round(w * scale)),
            preserve_range=True,
            anti_aliasing=False)

    if mode == 'pad_square':
        h, w = image.shape[:2]
        top_pad = (longest_side - h) // 2
        bottom_pad = longest_side - h - top_pad
        left_pad = (longest_side - w) // 2
        right_pad = longest_side - w - left_pad
        if image.ndim == 3:
            padding = [(top_pad, bottom_pad), (left_pad, right_pad), (0, 0)]
        else:
            padding = [(top_pad, bottom_pad), (left_pad, right_pad)]
        image = np.pad(image, padding)
        window = (top_pad, left_pad, h + top_pad, w + left_pad)

    else:
        h, w = image.shape[:2]
        # note that h (or w) - shortest_side maybe 0
        y = random.randint(0, (h - shortest_side))
        x = random.randint(0, (w - shortest_side))
        crop = (y, x, shortest_side, shortest_side)
        image = image[y:y + shortest_side, x:x + shortest_side]
        window = (0, 0, shortest_side, shortest_side)

    return image.astype(image_dtype), window, scale, padding, crop

############################################################
#  Dataset
############################################################

class Dataset(object):
    """
    Defines a dataset class.

    """

    def __init__(self):
        # image_info, list of dictionaries
        # {'id':image_id, 'path':path, 'class_name':class_name, ...}
        self.image_info = []

        # class_info, list of dictionaries
        # {'id':class_id, 'name':class_name}
        self.class_info = []

    def add_image(self, image_id, path, class_name, **kwargs):
        """
        Adds image information to the dataset.

        Parameters
        ----------
        image_id : string/integer
            The image ID.
        path : string
            The image path.
        class_name : string
            The corresponding class name.
        **kwargs : string/integer
            Additional information, e.g., image's height, width and so on.

        Returns
        -------
        None.

        """
        image_info = {'id':image_id, 'path':path, 'class_name':class_name, }
        image_info.update(kwargs)
        self.image_info.append(image_info)

    def add_class(self, class_id, class_name):
        """
        Adds class information to the dataset.

        Parameters
        ----------
        class_id : integer
            The class ID.
        class_name : string
            The corresponding class name. Augmented class names have the forms:
                * name_rot_n : rotate n degree where n in [90,180,270]
                * name_flip_lr : flip horizontally
                * name_flip_ud : flip vertically

        Returns
        -------
        None.

        """
        for info in self.class_info:
            if info['id'] == class_id:
                # skip if class_id already existed
                return
        self.class_info.append({'id':class_id, 'name':class_name})

    def prepare(self):
        """
        Prepares the dataset and needs to be called before using it.

        Returns
        -------
        None.

        """
        # info from class_info and image_info
        self.num_classes = len(self.class_info)
        self.class_ids = np.arange(self.num_classes)
        self.class_names = [
            a_class_info['name'] for a_class_info in self.class_info]
        self.num_images = len(self.image_info)
        self.image_ids = np.arange(self.num_images)

    def get_ds_info(self):
        """
        Gets the dataset information.

        Returns
        -------
        class_names : list
            Each element is a name corresponding to the class id.

        """
        print('There are %d images and %d classes.' \
              % (self.num_images, self.num_classes))
        return self.class_names

    def get_img_info(self, image_id):
        """
        Gets an image information.

        Parameters
        ----------
        image_id : integer
            An image id from image_ids.

        Returns
        -------
        image_info : dictionary
            The image information with keys 'id', 'path' and so on; see
            add_image().

        """
        return self.image_info[image_id]

    def image_name2id(self, image_id_str):
        """
        Gets the image id from the name of image.

        Parameters
        ----------
        image_id_str : string
            The name of image, image_info['id'].

        Returns
        -------
        image_id : integer
            The corresponding image id.

        """
        for image_id in self.image_ids:
            if self.get_img_info(image_id)['id'] == image_id_str:
                return image_id

    def class_name2id(self, class_name):
        """
        Gets the class id from the name of class.

        Parameters
        ----------
        class_name : string
            The given class name.

        Returns
        -------
        integer
            The corresponding class id.

        """
        for class_id in self.class_ids:
            if class_name == self.class_info[class_id]['name']:
                return self.class_info[class_id]['id']

    def class2images(self, class_id):
        """
        Get image ids from the class id. It needs to be re-defined in a
        subclass; otherwise it won't be efficient.

        Parameters
        ----------
        class_id : integer
            The given class id.

        Returns
        -------
        image_ids : list
            The set of image ids for the given class id.

        """
        image_ids = []
        for image_id in self.image_ids:
            class_name = self.get_img_info(image_id)['class_name']
            if self.class_name2id(class_name) == class_id:
                image_ids.append(image_id)
        return image_ids

    def load_data(
            self,
            image_id,
            img_mode,
            shortest_side=84,
            longest_side=84,
            upscale_factor=1.0,
            resize_mode='pad_square',
            verbose=0
            ):
        """
        Loads preprocessed image, class ids and other information.

        Parameters
        ----------
        image_id : integer
            The image id from image_ids.
        img_mode : string
            Process image to either in 'rgb' or 'gray'.
        shortest_side, longest_side, upscale_factor, resize_mode :
            See resize_image().
        verbose : binary, optional
            Whether to print out the preprocessing time. The default is 0.

        Returns
        -------
        image1 : numpy array, [resized_h, resized_w, 3] for RGB or
        [resized_h, resized_w] for gray
            The preprocessed image.
        class_id : integer
            The class id for the image.
        cache : list
            Includes image path, class name, window, scale, padding, crop,
            original image shape and preprocessed image shape.

        """
        # load image
        image_path = self.get_img_info(image_id)['path']
        t1 = time.time()
        image = load_image(image_path, img_mode)
        t2 = time.time()
        if verbose:
            print('loading image: %fs' %(t2-t1))
        image_shape = image.shape

        # resize image
        t1 = time.time()
        image1, window, scale, padding, crop = resize_image(
            image,
            shortest_side,
            longest_side,
            upscale_factor,
            resize_mode)
        t2 = time.time()
        if verbose:
            print('resize mode:', resize_mode)
            print('resizing image: %fs' %(t2-t1))

        # augment if needed
        class_name = self.get_img_info(image_id)['class_name']
        if 'rot' in class_name.split('_'):
            angle = int(class_name.split('_')[-1])
            k = angle / 90
            t1 = time.time()
            # image1 = skimage.transform.rotate(image1, angle)
            image1 = np.rot90(image1, k)
            t2 = time.time()
            if verbose:
                print('rotating image: %fs' %(t2-t1))
        elif 'flip' in class_name.split('_'):
            if 'lr' in class_name.split('_'):
                t1 = time.time()
                image1 = np.fliplr(image1)
                t2 = time.time()
            if 'ud' in class_name.split('_'):
                t1 = time.time()
                image1 = np.flipud(image1)
                t2 = time.time()
            if verbose:
                print('fliping image: %fs' %(t2-t1))

        cache = (
            image_path,
            class_name,
            window,
            scale,
            padding,
            crop,
            image_shape,
            image1.shape)
        class_id = self.class_name2id(class_name)
        return image1, class_id, cache


from datetime import datetime, timedelta
import dateutil.parser
from pytz import timezone
import re
from math import floor, ceil, radians, sin, cos, atan2, sqrt

def haversine(lat1, lon1, lat2, lon2):
    R = 6367444.7
    phi1 = radians(lat1)
    phi2 = radians(lat2)
    delta_phi = radians(lat2 - lat1)
    delta_lambda = radians(lon2 - lon1)
    sin_delta_p = sin(delta_phi / 2.)
    sin_delta_l = sin(delta_lambda / 2.)
    a = sin_delta_p * sin_delta_p + cos(phi1) * cos(phi2) * sin_delta_l * sin_delta_l
    c = 2. * atan2(sqrt(a), sqrt(1. - a));
    return R * c;

def camel_case_to_py(txt):
    retval = ''
    for c in txt:
        if c.isupper():
            retval += '_%s' % c.lower()
        else:
            retval += c
    return retval

def attributes_to_fields(fields, obj, data, remap = None):
    for field in fields:
        k = camel_case_to_py(field)
        if remap is None:
            setattr(obj, k, data[field])
        else:
            setattr(obj, k, remap(data[field]))

def parse_timedelta(txt):
    RGX = re.compile('^((?P<hours>\d+):)?((?P<minutes>\d+):)?(?P<seconds>\d+(\.\d+)?)')
    match = RGX.match(txt)
    if not match:
        return None
    parms = {'hours': 0, 'minutes': 0, 'seconds': 0.0}
    for key, val in match.groupdict().items():
        if val and key in parms:
            parms[key] = float(val)
    return timedelta(**parms)

class ActivityTags(object):
    TERRAIN_TRAIL = 'TRAIL'
    EMOTION_UNSTOPPABLE = 'UNSTOPPABLE'
    WEATHER_PARTLY_SUNNY = 'PARTLY_SUNNY'

    def load(self, json_data):
        d = {}
        for item in json_data:
            d[item['tagType'].lower()] = item['tagValue']

        attributes_to_fields(['terrain', 'emotion', 'weather'], self, d)
        attributes_to_fields(['temperature'], self, d, int)

    def __init__(self):
        super(ActivityTags, self).__init__()
        self.temperature = None
        self.terrain = None
        self.emotion = None
        self.weather = None

class ActivityMetricsSummary(object):
    def load(self, json_data):
        attributes_to_fields(['calories', 'fuel', 'steps'], self, json_data, int)
        attributes_to_fields(['distance'], self, json_data, float)
        attributes_to_fields(['duration'], self, json_data, parse_timedelta)

    def __init__(self):
        super(ActivityMetricsSummary, self).__init__()
        self.calories = None
        self.fuel = None
        self.distance = None
        self.steps = None
        self.duration = None
        self.elevation_loss = None
        self.elevation_gain = None
        self.elevation_max = None
        self.elevation_min = None

class ActivityMetric(object):
    # Other metric types: https://developer.nike.com/documentation/api-docs/reference/interval-and-summary-metric-types.html
    METRIC_GPS = '__GPS__' # Not defined by Nike+
    METRIC_TIME = '__TIME__' # Not defined by Nike+
    METRIC_DISTANCE = 'DISTANCE'
    METRIC_SPEED = 'SPEED'
    METRIC_GPSSIGNALSTRENGTH = 'GPSSIGNALSTRENGTH'
    METRIC_HEARTRATE = 'HEARTRATE'
    METRIC_FUEL = 'FUEL'
    UNIT_SEC = 'SEC'
    UNIT_MIN = 'MIN'

    @classmethod
    def interpolate(cls, alpha, zero, one):
        return (1. - alpha) * zero + alpha * one

    def load(self, json_data):
        attributes_to_fields(['intervalUnit', 'metricType'], self, json_data)
        self.interval = int(json_data['intervalMetric'])
        if self.interval_unit == ActivityMetric.UNIT_MIN:
            self.interval *= 60
            self.interval_unit = ActivityMetric.UNIT_SEC

        self.values = list(map(float, json_data['values']))

    def sample(self, idx):
        if idx < 0:
            return self.values[0]
        elif idx >= len(self.values) - 1:
            return self.values[-1]
        elif float(int(idx)) == idx:
            return self.values[int(idx)]
        else:
            val_prev = self.values[int(floor(idx))]
            val_next = self.values[int(ceil(idx))]
            alpha = idx - floor(idx)
            return self.__class__.interpolate(alpha, val_prev, val_next)

    def resample_uniform(self, new_interval):
        unit = new_interval / self.interval
        new_values = []
        x = 0.
        while x <= len(self.values) - 1:
            new_values.append(self.sample(x))
            x += unit
        self.values = new_values
        self.interval = new_interval

    def resample(self, idxs, new_interval_secs):
        new_values = []
        for i in idxs:
            new_values.append(self.sample(i))
        self.values = new_values
        self.interval = new_interval_secs

    def __init__(self):
        super(ActivityMetric, self).__init__()
        self.metric_type = None
        self.interval_unit = None
        self.interval = None
        self.values = None

class ActivityMetricGPS(ActivityMetric):
    @classmethod
    def interpolate(cls, alpha, zero, one):
        return {
            'latitude': (1. - alpha) * zero['latitude'] + alpha * one['latitude'],
            'longitude': (1. - alpha) * zero['longitude'] + alpha * one['longitude'],
            'elevation': (1. - alpha) * zero['elevation'] + alpha * one['elevation']
        }

    def compute_distance(self, max_dist):
        self.values[0]['distance'] = 0.0
        prev_lat = self.values[0]['latitude']
        prev_lon = self.values[0]['longitude']
        prev_dist = 0.0
        for i in range(1, len(self.values)):
            lat = self.values[i]['latitude']
            lon = self.values[i]['longitude']
            prev_dist += haversine(prev_lat, prev_lon, lat, lon) / 1000.
            self.values[i]['distance'] = prev_dist
            prev_lat, prev_lon = lat, lon
        last_dist = self.values[-1]['distance']
        scale_factor = max_dist / last_dist
        for i in range(0, len(self.values)):
            self.values[i]['distance'] *= scale_factor
        return last_dist - max_dist

    def map_dist_to_indices(self, metric_dist):
        retval = []
        mdist_i = 0
        prev_mdist = 0.
        n_mdist = len(metric_dist.values)
        for item in self.values:
            dist = item['distance']
            while mdist_i < n_mdist and metric_dist.values[mdist_i] < dist:
                prev_mdist = metric_dist.values[mdist_i]
                mdist_i += 1
            if mdist_i >= n_mdist:
                retval.append(n_mdist - 1)
            if metric_dist.values[mdist_i] == dist:
                retval.append(mdist_i)
                continue
            # interpolate
            assert(mdist_i > 0 and prev_mdist == metric_dist.values[mdist_i - 1])
            assert(dist >= prev_mdist)
            alpha = (dist - prev_mdist) / (metric_dist.values[mdist_i] - prev_mdist)
            retval.append(float(mdist_i) - 1. + alpha)
            assert(abs(metric_dist.sample(retval[-1]) - dist) < 0.001)
        return retval

    def load(self, json_data):
        attributes_to_fields(['elevationLoss', 'elevationGain', 'elevationMax', 'elevationMin'], self, json_data, float)
        attributes_to_fields(['intervalUnit'], self, json_data)
        self.interval = int(json_data['intervalMetric'])
        self.values = json_data['waypoints']

    def __init__(self):
        super(ActivityMetricGPS, self).__init__()
        self.elevation_loss = None
        self.elevation_gain = None
        self.elevation_min = None
        self.elevation_max = None

class ActivityMetrics(object):
    def load(self, json_data):
        for json_metric in json_data:
            metric = ActivityMetric()
            metric.load(json_metric)
            self.all_metrics[metric.metric_type] = metric

    def synchronize_to_distance(self):
        assert(self.distance is not None)
        target_len = len(self.distance.values)
        for k in self.all_metrics:
            if k == ActivityMetric.METRIC_GPS or k == ActivityMetric.METRIC_DISTANCE:
                continue
            metric = self.all_metrics[k]
            metric.resample_uniform(float(self.distance.interval))
            if len(metric.values) > target_len:
                del metric.values[target_len:]
            else:
                metric.values += [metric.values[-1]] * (target_len - len(metric.values))

    def synchronize_to_gps(self):
        assert(self.gps is not None and self.distance is not None)
        self.gps.compute_distance(self.distance.values[-1])
        idxs = self.gps.map_dist_to_indices(self.distance)
        assert(len(idxs) == len(self.gps.values))
        for k in self.all_metrics:
            if k == ActivityMetric.METRIC_GPS or k == ActivityMetric.METRIC_DISTANCE:
                continue
            metric = self.all_metrics[k]
            if len(metric.values) != len(self.distance.values):
                metric.resample_uniform(float(self.distance.interval))
            metric.resample(idxs, self.gps.interval)
        self.distance.resample(idxs, self.gps.interval)

    def pack(self, metrics = None):
        if metrics is None:
            metrics = self.all_metrics.keys()

        # Make sure all the metrics are in sync
        any_metric = self.gps if self.gps is not None else self.all_metrics[metrics[0]]
        assert(any_metric.interval_unit == ActivityMetric.UNIT_SEC)
        for k in metrics:
            assert(len(self.all_metrics[k].values) == len(any_metric.values))
            assert(self.all_metrics[k].interval == any_metric.interval)
            assert(self.all_metrics[k].interval_unit == any_metric.interval_unit)

        packed_values = []
        for i in range(0, len(any_metric.values)):
            packed_values.append({})
            for k in metrics:
                packed_values[-1][k] = self.all_metrics[k].values[i]
                packed_values[-1][ActivityMetric.METRIC_TIME] = timedelta(
                    seconds=float(any_metric.interval) * float(i))
        return packed_values

    def __getattribute__(self, key):
        if key == 'distance':
            return self.all_metrics.get(ActivityMetric.METRIC_DISTANCE)
        elif key == 'speed':
            return self.all_metrics.get(ActivityMetric.METRIC_SPEED)
        elif key == 'gps_signal_strength':
            return self.all_metrics.get(ActivityMetric.METRIC_GPSSIGNALSTRENGTH)
        elif key == 'heart_rate':
            return self.all_metrics.get(ActivityMetric.METRIC_HEARTRATE)
        elif key == 'fuel':
            return self.all_metrics.get(ActivityMetric.METRIC_FUEL)
        elif key == 'gps':
            return self.all_metrics.get(ActivityMetric.METRIC_GPS)
        else:
            return super(ActivityMetrics, self).__getattribute__(key)

    def __init__(self):
        super(ActivityMetrics, self).__init__()
        self.all_metrics = {}

class ActivityData(object):
    # The remaining activity types: https://developer.nike.com/documentation/api-docs/reference/activity-types.html
    ACTIVITY_TYPE_RUN = 'RUN'
    STATUS_COMPLETE = 'COMPLETE'
    # The remaining device types: https://developer.nike.com/documentation/api-docs/reference/device-types.html
    DEVICE_TYPE_IPHONE = 'IPHONE'

    def load(self, json_data, gps_data = None):
        # Import trivial attributes
        attributes_to_fields(['activityId', 'activityType', 'status', 'deviceType'], self, json_data)
        attributes_to_fields(['isGpsActivity'], self, json_data, bool)
        self.metrics_summary.load(json_data['metricSummary'])
        self.tags.load(json_data['tags'])
        self.metrics.load(json_data['metrics'])
        # Cast time with the correct timezone
        tz = timezone(json_data['activityTimeZone'])
        self.start_time = tz.localize(dateutil.parser.parse(json_data['startTime'], ignoretz=True))
        if gps_data is not None:
            self.load_gps_data(gps_data)

    def load_gps_data(self, gps_data):
        gps = ActivityMetricGPS()
        gps.load(gps_data)
        self.metrics.all_metrics[ActivityMetric.METRIC_GPS] = gps
        self.metrics_summary.elevation_max = gps.elevation_max
        self.metrics_summary.elevation_min = gps.elevation_min
        self.metrics_summary.elevation_gain = gps.elevation_gain
        self.metrics_summary.elevation_loss = gps.elevation_loss

    def __init__(self):
        super(ActivityData, self).__init__()
        self.activity_id = None
        self.activity_type = None
        self.start_time = None
        self.status = None
        self.device_type = None
        self.is_gps_activity = None
        self.metrics_summary = ActivityMetricsSummary()
        self.metrics = ActivityMetrics()
        self.tags = ActivityTags()

if __name__ == '__main__':
    import simplejson
    import xml.dom.minidom as DOM

    with open('/Users/Spak/Desktop/last.json', 'r') as fs:
        gpsdata = simplejson.load(fs)
    with open('/Users/Spak/Desktop/last2.json', 'r') as fs:
        actdata = simplejson.load(fs)
    a = ActivityData()
    a.load(actdata, gpsdata)
    # diff = a.metrics.gps.compute_distance(a.metrics_summary.distance)
    # print('Difference between estimated length and computed length: %f m' % diff)
    # a.metrics.synchronize_to_distance()
    # # TEST
    # for k in a.metrics.all_metrics:
    #     if k == ActivityMetric.METRIC_GPS:
    #         continue
    #     assert(len(a.metrics.all_metrics[k].values) == len(a.metrics.distance.values))
    # # ----
    # idxs = a.metrics.gps.map_dist_to_indices(a.metrics.distance)
    # # TEST
    # for i, j in enumerate(idxs):
    #     assert(abs(a.metrics.distance.sample(j) - a.metrics.gps.values[i]['distance']) < 0.1)
    # # ----
    a.metrics.synchronize_to_gps()
    trackpoints = a.metrics.pack()

    # Convert to xml
    doc = DOM.Document()
    xml_trkseg = doc.createElement('trkseg')
    for tp in trackpoints:
        xml_tp = doc.createElement('trkpt')
        xml_tp.setAttribute('lat', str(tp[ActivityMetric.METRIC_GPS]['latitude']))
        xml_tp.setAttribute('lon', str(tp[ActivityMetric.METRIC_GPS]['longitude']))
        ele_tp = doc.createElement('ele')
        ele_tp.appendChild(doc.createTextNode(str(tp[ActivityMetric.METRIC_GPS]['elevation'])))
        xml_tp.appendChild(ele_tp)
        time_tp = doc.createElement('time')
        real_time = a.start_time + tp[ActivityMetric.METRIC_TIME]
        time_tp.appendChild(doc.createTextNode(real_time.isoformat()))
        xml_tp.appendChild(time_tp)
        ext_tp = doc.createElement('extensions')
        xml_tp.appendChild(ext_tp)
        heart_tp = doc.createElement('hr')
        heart_tp.appendChild(doc.createTextNode(str(int(tp[ActivityMetric.METRIC_HEARTRATE]))))
        ext_tp.appendChild(heart_tp)
        xml_trkseg.appendChild(xml_tp)
    xml_trk = doc.createElement('trk')
    xml_trk.appendChild(xml_trkseg)
    xml_gpx = doc.createElement('gpx')
    xml_gpx.setAttribute('version', '1.1')
    xml_gpx.setAttribute('creator', 'PyGPX')
    xml_gpx.appendChild(xml_trk)
    print("<?xml version=\"1.0\" ?>")
    print(xml_gpx.toprettyxml())


from flask import Flask
from flask import request
from faker import Faker
import csv

app = Flask(__name__)

@app.route('/')
def hello_world():
    return '
Hello, World
'

@app.route('/requirements/')
def get_requirements():
    with open('requirements.txt') as file:
        text = ''
        line = file.readline()

        while line != '':
            text += (line.strip()) + ' \n'
            line = file.readline()
        return text

@app.route('/generate-users/')
def generate_users():
    dict_name_email = {}
    fake = Faker()
    amount = request.args.get('amount', 100, type=int)
    for i in range(amount):
        dict_name_email[fake.name()] = fake.email()
    return dict_name_email

@app.route('/mean/')
def get_avg_value():
    list_index, list_height, list_weight = [], [], []
    with open('hw.csv') as file:
        reader = csv.reader(file)
        for row in reader:
            if row:
                list_index.append(row[0])
                list_height.append(row[1])
                list_weight.append(row[2])
        index = max(list_index[1:], key=int)
        avg_hight = (sum([float(i) for i in list_height[1:]]) * 2.54) / int(index)
        avg_weight = (sum([float(i) for i in list_weight[1:]]) * 0.454) / int(index)
    return f'Average height is {avg_hight} cm, average weight is {avg_weight} kg'

if __name__ == '__main__':
    app.run(debug=True)


#!/usr/bin/env python

from __future__ import absolute_import
import visa
import logging
import serial
import useserial
from sys import platform

class GPIBDetector ( object ) :
	def __init__ ( self ) :
		logger = logging.getLogger ( u'myLogger' )
		resources = [""] * 1
		try :
			self._rm1 = visa.ResourceManager ( )
			resources = self._rm1.list_resources ( )
		except :
			logger.debug ( u"  Failed to open ni-visa" )
		try :
			if useserial.haveserial :
			    self._rm2 = visa.ResourceManager ( u'@py' )
			    resources += self._rm2.list_resources ( )
		except :
			logger.debug ( u"  Failed to open py-visa" )

		self.identifiers = {}
		logger.debug ( u"  Probing devices..." )
		for res in resources:
			logger.debug ( u"   Found %s", res )
			if not ( res.startswith ( u"ASRL" ) or res.startswith ( u"GPIB" ) ) :
				continue

			dev = None
			if res.startswith ( u"ASRL" ) and useserial.haveserial :
				logger.debug ( u"   Opening serial connection to %s", res )
				try :
					# 5000 msecs needed to catch slow devices...
					dev = self._rm2.open_resource ( res, baud_rate = 19200, data_bits = 8, timeout = 5000 )
				except :
					logger.debug ( u"   Could not open serial connection to %s", res )
			if res.startswith ( u"GPIB" ) :
				logger.debug ( u"   Opening GPIB connection to %s", res )
				try :
					dev = self._rm1.open_resource ( res )
				except :
					logger.debug ( u"   Could not open GPIB connection to %s", res )
			if not ( dev == None ) :
				idn = dev.query ( u"*IDN?" )
				logger.debug ( u"   Got device identification: %s", idn )
				self.identifiers[res] = idn
				dev.close ( )

	def get_resname_for ( self, search ) :
		for key, value in self.identifiers.items ( ) :
			if search in value :
				return key
		return None

if __name__ == u"__main__" :
	import pprint

	detector = GPIBDetector ( )

	pprint.pprint ( detector.identifiers )


# ðŸš¨ Don't change the code below ðŸ‘‡
print("Welcome to the Love Calculator!")
name1 = input("What is your name? \n")
name2 = input("What is their name? \n")
# ðŸš¨ Don't change the code above ðŸ‘†

#Write your code below this line ðŸ‘‡

# Explaination of the formula
# https://www.buzzfeed.com/ariannarebolini/what-are-the-chances-your-crush-is-actually-your-true-love
# WARNING it is very stupid

both_names = name1.lower()+name2.lower()
left_digit = 0
right_digit = 0

for c in 'true':
    left_digit += both_names.count(c)
for c in 'love':
    right_digit += both_names.count(c)

love_score = str(left_digit) + str(right_digit)
love_score = int(love_score)

if love_score<10 or love_score>90:
    print(f'Your score is {love_score}, you go together like coke and mentos.')
elif love_score>=40 and love_score<=50:
    print(f'Your score is {love_score}, you are alright together.')
else:
    print(f'Your score is {love_score}.')


import time
import datetime

def remaining_time(just_finished, total, time):
    """Calculate the remaining timedelta
    INPUT:
        just_finished: the epoch that was just completed
        total: the total number of epochs that need to be completed
        time: current time of execution
    """
    assert just_finished > 0, "just_finished should equal 1 for the first epoch, not 0"
    epochs_left = total-just_finished
    return time / just_finished * epochs_left

def format_time(t):
    """ Format time t, in seconds, in HH:MM:SS
    """
    return time.strftime("%H:%M:%S", time.gmtime(t))

class Stopwatch(object):
    """ A simple stopwatch; you can start, stop, reset and check the time
    """

    def __init__(self, name="", start=False, t0=0):
        """Initialize the stopwatch
        INPUT:
            name="": the name used for debugging
            start=False: immediately start the stopwatch or not
            t0=0: the start time of the stopwatch
        """
        self.name = name
        self.__tcum = t0
        self.__t = 0
        self.__running = False
        if start:
            self.start()

    def reset(self, start=False):
        t_temp = self.get_time()
        self.__tcum = 0
        self.__t = 0
        self.__running = False
        if start:
            self.start()
        return t_temp

    def start(self):
        assert not self.__running, "Stopwatch {} is already running!".format(self.name)
        self.__running = True
        self.__t = time.time()

    def stop(self):
        assert self.__running, "Stopwatch {} is not running!".format(self.name)
        self.__running = False
        self.__tcum += time.time() - self.__t
        return self.__tcum

    def get_time(self):
        """ Get the elapsed time in seconds (float precision)
        """
        if not self.__running:
            return self.__tcum
        else:
            return self.__tcum + (time.time() - self.__t)

    def get_time_formatted(self, t=None):
        """ Get the elapsed time, formatted by HH:MM:SS
        """
        return format_time(self.get_time())

    def get_remaining_time_formatted(self, just_finished, total):
        return format_time(remaining_time(just_finished, total, self.get_time()))

if __name__ == "__main__":
    sw = Stopwatch(name="joost")
    sw.start()
    time.sleep(2)
    print("Elapsed time (should be plus-minus 2 second): {}".format(sw.get_time()))
    sw.stop()
    time.sleep(1)
    print("Elapsed time (should still be plus-minus 2 second): {}".format(sw.get_time()))
    print("Now formatted: {}".format(sw.get_time_formatted()))

    sw.reset()
    time.sleep(0.1)
    print("This should now be zero: {}".format(sw.get_time()))


#! /usr/bin/env python
"""
Script to copy a column between MS files
"""
import argparse
from argparse import RawTextHelpFormatter
import casacore.tables as pt
import numpy
import sys
import os

def copy_column_to_ms(ms, inputcol, outputcol, ms_from=None, use_compression=False):
    """
    Copies one column to another, within an MS file or between two MS files

    Parameters
    ----------
    ms : str
        MS file receiving copy
    inputcol : str
        Column name to copy from
    outputcol : str
        Column name to copy to
    ms_from : str, optional
        MS file to copy from. If None, the column is copied internally

    """
    t = pt.table(ms, readonly=False, ack=False)
    if ms_from is not None:
        tf = pt.table(ms_from, readonly=False, ack=False)
        data = tf.getcol(inputcol)
        desc = tf.getcoldesc(inputcol)
    else:
        data = t.getcol(inputcol)
        desc = t.getcoldesc(inputcol)

    # Add the output column if needed
    if outputcol not in t.colnames():
        if use_compression:
            # Set DyscoStMan to be storage manager for DATA and WEIGHT_SPECTRUM
            # We use a visibility bit rate of 16 and truncation of 1.5 sigma to keep the
            # compression noise below ~ 0.01 mJy, as estimated from Fig 4 of
            # Offringa (2016). For the weights, we use a bit rate of 12, as
            # recommended in Sec 4.4 of Offringa (2016)
            desc['name'] = outputcol
            dmi = {
                'SPEC': {
                    'dataBitCount': numpy.uint32(16),
                    'distribution': 'TruncatedGaussian',
                    'distributionTruncation': 1.5,
                    'normalization': 'RF',
                    'weightBitCount': numpy.uint32(12)},
                'NAME': '{}_dm'.format(outputcol),
                'SEQNR': 1,
                'TYPE': 'DyscoStMan'}
            desc['option'] = 1 # make a Direct column
            t.addcols(desc, dmi)
        else:
            desc['name'] = outputcol
            t.addcols(desc)

    if use_compression:
        # Replace flagged values with NaNs before compression
        flags = t.getcol('FLAG')
        flagged = numpy.where(flags)
        data[flagged] = numpy.NaN

    t.putcol(outputcol, data)
    t.flush()
    t.close()

def copy_column_to_bands(mslist, ms_from, inputcol, outputcol):
    """
    Copies one column from an MS file to multiple MS files (bands)

    Parameters
    ----------
    mslist : list
        MS files receiving copy
    ms_from : str
        MS file to copy from
    inputcol : str
        Column name to copy from
    outputcol : str
        Column name to copy to

    """
    datain = pt.table(ms_from)
    data = datain.getcol(inputcol, nrow=1)
    numberofchans = numpy.int(numpy.shape(data)[1])
    chanperms = numberofchans/numpy.int(len(mslist))

    for ms_id, ms in enumerate(mslist):
        if os.path.isdir(ms):
            data = datain.getcolslice(inputcol, [chanperms*ms_id,0], [(chanperms*(ms_id+1))-1,3])
            dataout = pt.table(ms, readonly=False)
            dataout.putcol(outputcol, data)
            dataout.flush()
            dataout.close()

def copy_column_from_bands(mslist, ms_to, inputcol, outputcol):
    """
    Copies one column from multiple MS files (bands) to a single MS file

    Note: the bands are assumed to be ordered by frequency, with a nonexisting
    file (e.g., 'dummy.ms') denoting missing bands

    Parameters
    ----------
    mslist : list
        MS files to copy from
    ms_to : str
        MS file receiving copy
    inputcol : str
        Column name to copy from
    outputcol : str
        Column name to copy to

    """
    dataout = pt.table(ms_to, readonly=False)
    data = dataout.getcol(outputcol, nrow=1)
    numberofchans = numpy.int(numpy.shape(data)[1])
    chanperms = numberofchans/numpy.int(len(mslist))

    for ms_id, ms in enumerate(mslist):
        if os.path.isdir(ms):
            datain = pt.table(ms, readonly=True)
            data = datain.getcol(inputcol)
            dataout.putcolslice(outputcol, data, [chanperms*ms_id,0], [(chanperms*(ms_id+1))-1,3])
            datain.close()
    dataout.flush()
    dataout.close()

def main(ms_from, ms_to, column_from, column_to, do_copy=True, use_compression=False):
    """
    Copy a column between MS files

    Parameters
    ----------
    ms_from : str
        Name of MS file to copy from
    ms_to : str or list
        Name of MS file or list of MS files to copy to. May be given as a list
        or as a string (e.g., '[ms1, ms2]'
    column_from : str
        Name of column to copy from
    column_to : str
        Name of column to copy to
    do_copy : bool, optional
        If False, the copy is NOT done (used to skip a copy step in a pipeline)
    use_compression : bool, optional
        If True, use Dysco compression

    """
    if type(do_copy) is str:
        if do_copy.lower() == 'true':
            do_copy = True
        else:
            do_copy = False
    if type(use_compression) is str:
        if use_compression.lower() == 'true':
            use_compression = True
        else:
            use_compression = False

    if not do_copy:
        print('Copy skipped (do_copy = False)')
        return

    if type(ms_to) is str:
        if '[' in ms_to:
            ms_to = ms_to.strip('[]').split(',')
            ms_to = [m.strip() for m in ms_to]

    if type(ms_from) is str:
        if '[' in ms_from:
            ms_from = ms_from.strip('[]').split(',')
            ms_from = [m.strip() for m in ms_from]

    if type(ms_to) is list and type(ms_from) is list:
        print('ERROR: ms_from and ms_to cannot both be lists')
        sys.exit(1)

    if type(ms_to) is list:
        # List means call copy_column_to_bands()
        copy_column_to_bands(ms_to, ms_from, column_from, column_to)
    elif type(ms_from) is list:
        # List means call copy_column_from_bands()
        copy_column_from_bands(ms_from, ms_to, column_from, column_to)
    else:
        if ms_to == ms_from:
            ms_from = None
        copy_column_to_ms(ms_to, column_from, column_to, ms_from, use_compression)

if __name__ == '__main__':
    descriptiontext = "Copy a column between MS files.\n"

    parser = argparse.ArgumentParser(description=descriptiontext, formatter_class=RawTextHelpFormatter)
    parser.add_argument('ms_from', help='name of the MS file to copy from')
    parser.add_argument('ms_to', help='name of the MS file to copy to')
    parser.add_argument('column_from', help='name of the column to copy from')
    parser.add_argument('column_to', help='name of the column to copy to')
    parser.add_argument('do_copy', help='Copy is done only if True')
    args = parser.parse_args()

    main(args.ms_from, args.ms_to, args.column_from, args.column_to,
        do_copy=args.do_copy)


# %%
import pandas as pd

# https://eresearch.fidelity.com/eresearch/markets_sectors/sectors/sectors_in_market.jhtml
market_cap_by_sector = pd.Series(
    {
        "Communication Services": 5.37,
        "Consumer Discretionary": 7.5,
        "Consumer Staples": 4.12,
        "Energy": 1.76,
        "Financials": 5.95,
        "Health Care": 6.89,
        "Industrials": 4.46,
        "IT": 12.31,
        "Materials": 2.1,
        "Real Estate": 1.35,
        "Utilities": 1.49,
    }
)

num_stock_by_sector = (30 * (market_cap_by_sector / market_cap_by_sector.sum())).round()
print(num_stock_by_sector)
# %%

import yfinance as yf

stock_list = [
    "T",
    "EA",
    "VZ",
    "BBY",
    "KMX",
    "CMG",
    "F",
    "KO",
    "WMT",
    "CVX",
    "JPM",
    "MS",
    "C",
    "JNJ",
    "MRK",
    "PFE",
    "CVS",
    "AAL",
    "FDX",
    "UPS",
    "AAPL",
    "AMD",
    "MSFT",
    "NVDA",
    "ORCL",
    "QCOM",
    "INTC",
    "EMN",
    "AVB",
    "SO",
]

stock_close = yf.download(stock_list, start="2010-01-01", end="2020-01-01")["Close"]
# print(stock_data.index[stock_data["Close"].isna().any(axis=1)]) # market closed on 2012-10-29
stock_close = stock_close.dropna(axis=0, how="all")

stock_ret = (stock_close - stock_close.shift()) / stock_close.shift()
stock_ret = stock_ret.dropna()
stock_cov = stock_ret.cov()
stock_corr = stock_ret.corr()
# %%
import os

newpath = os.getcwd() + "\\output"
if not os.path.exists(newpath):
    os.makedirs(newpath)

filename = newpath + "\\data.xlsx"
with pd.ExcelWriter(filename) as writer:
    stock_close.to_excel(writer, sheet_name="stock_close")
    stock_ret.to_excel(writer, sheet_name="stock_ret")
    stock_cov.to_excel(writer, sheet_name="stock_cov")
    stock_corr.to_excel(writer, sheet_name="stock_corr")


import unittest
import os

from dpctl.config import Config
from dpctl.cf import CF

class TestCF(unittest.TestCase):

    def setUp(self):
        self.config = Config(
            configPath=os.path.join(
                os.path.dirname(__file__),
                'data/dpctl.yaml'
            )
        )

    def test_cf_apply(self):
        cf = CF(self.config.get('providers', {}).get('cf'))
        self.assertEqual('cf push cf/manifest.yml', cf.apply())

if __name__ == '__main__':
    unittest.main()


import requests

bus_addr = '<bus_shelter_address>'

host = '<om2m_server_address>'
port = '8080'

ae_name = 'bus_shelter'
headers = {
    'X-M2M-Origin': '<om2m-id>:<om2m-passwd>',
    'Content-Type': '',
    'Cache-Control': 'no-cache',
}
containers = ['led1', 'led2', 'awning', 'inverter']

def init_script():
    # create ae
    headers['Content-Type'] = 'application/json;ty=2'
    data = {
        'm2m:ae': {
            'api': 'bus-shelter',
            'rn': ae_name,
            'lbl' : [],
            'rr': True
        }
    }
    res = requests.post(f'http://{host}:{port}/~/in-cse', json=data, headers=headers)
    print('[CREATE AE]', res.status_code)

    if res.status_code != 201:
        return 0
    ae_addr = res.json()['m2m:ae']['ri']

    for container in containers:
        # create container
        headers['Content-Type'] = 'application/json;ty=3'
        data = {
            'm2m:cnt': {
                'rn': container
            }
        }
        res = requests.post(f'http://{host}:{port}/~{ae_addr}', json=data, headers=headers)
        print(f'[CREATE {container} CONTAINER]', res.status_code)

        if res.status_code != 201:
            return ae_addr
        cnt_addr = res.json()['m2m:cnt']['ri']

        # create content instance
        headers['Content-Type'] = 'application/json;ty=4'
        data = {
            'm2m:cin': {
                'cnf': f'{container}-status',
                'con': 0
            }
        }
        res = requests.post(f'http://{host}:{port}/~{cnt_addr}', json=data, headers=headers)
        print(f'[CREATE {container} CONTENT INSTANCE]', res.status_code)
        if res.status_code != 201:
            return ae_addr

        # create subscription
        headers['Content-Type'] = 'application/json;ty=23'
        data = {
            'm2m:sub': {
                'rn': f'{container}-sub',
                'nu': [f'http://{bus_addr}:3002/{container}'],
                'nct': 2
            }
        }
        res = requests.post(f'http://{host}:{port}/~{cnt_addr}', json=data, headers=headers)
        print(f'[CREATE {container} SUBSCRIPTION]', res.status_code)
        if res.status_code != 201:
            return

    print('Successfully initialize OM2M server')

if __name__ == "__main__":
    ret = init_script()

    if ret is not 0:
        requests.delete(f'http://{host}:{port}/~{ret}', headers={'X-M2M-Origin': 'admin:admin', 'Cache-Control': 'no-cache'})


from collections import abc
import functools
import inspect
import sys

from keystoneclient import exceptions as keystone_exceptions
from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import excutils
from oslo_utils import uuidutils
import pecan
import wsme

from solum.i18n import _

LOG = logging.getLogger(__name__)

exc_log_opts = [
    cfg.BoolOpt('fatal_exception_format_errors',
                default=False,
                help='make exception message format errors fatal')
]

def list_opts():
    yield None, exc_log_opts

CONF = cfg.CONF
CONF.register_opts(exc_log_opts)

def wrap_exception(notifier=None, publisher_id=None, event_type=None,
                   level=None):
    """This decorator wraps a method to catch any exceptions.

    It logs the exception as well as optionally sending
    it to the notification system.
    """
    def inner(f):
        def wrapped(self, context, *args, **kw):
            # Don't store self or context in the payload, it now seems to
            # contain confidential information.
            try:
                return f(self, context, *args, **kw)
            except Exception as e:
                with excutils.save_and_reraise_exception():
                    if notifier:
                        call_dict = inspect.getcallargs(f, *args, **kw)
                        payload = dict(exception=e,
                                       private=dict(args=call_dict)
                                       )

                        # Use a temp vars so we don't shadow
                        # our outer definitions.
                        temp_level = level
                        if not temp_level:
                            temp_level = notifier.ERROR

                        temp_type = event_type
                        if not temp_type:
                            # If f has multiple decorators, they must use
                            # functools.wraps to ensure the name is
                            # propagated.
                            temp_type = f.__name__

                        notifier.notify(context, publisher_id, temp_type,
                                        temp_level, payload)

        return functools.wraps(f)(wrapped)
    return inner

OBFUSCATED_MSG = _('Your request could not be handled '
                   'because of a problem in the server. '
                   'Error Correlation id is: %s')

def wrap_controller_exception(func, func_server_error, func_client_error):
    """This decorator wraps controllers methods to handle exceptions:

    - if an unhandled Exception or a SolumException with an error code >=500
    is catched, raise a http 5xx ClientSideError and correlates it with a log
    message

    - if a SolumException is catched and its error code is <500, raise a http
    4xx and logs the exception in debug mode

    """
    @functools.wraps(func)
    def wrapped(*args, **kw):
        try:
            return func(*args, **kw)
        except Exception as excp:
            LOG.error(excp)
            http_error_code = 500
            if hasattr(excp, 'code'):
                http_error_code = excp.code

            if http_error_code >= 500:
                # log the error message with its associated
                # correlation id
                log_correlation_id = uuidutils.generate_uuid()
                LOG.error("%s:%s", log_correlation_id, str(excp))
                # raise a client error with an obfuscated message
                func_server_error(log_correlation_id, http_error_code)
            else:
                # raise a client error the original message
                func_client_error(excp, http_error_code)
    return wrapped

def wrap_wsme_controller_exception(func):
    """This decorator wraps wsme controllers to handle exceptions."""
    def _func_server_error(log_correlation_id, status_code):
        raise wsme.exc.ClientSideError(
            str(OBFUSCATED_MSG % log_correlation_id), status_code)

    def _func_client_error(excp, status_code):
        raise wsme.exc.ClientSideError(str(excp), status_code)

    return wrap_controller_exception(func,
                                     _func_server_error,
                                     _func_client_error)

def wrap_pecan_controller_exception(func):
    """This decorator wraps pecan controllers to handle exceptions."""
    def _func_server_error(log_correlation_id, status_code):
        pecan.response.status = status_code
        pecan.response.text = str(OBFUSCATED_MSG % log_correlation_id)
        # message body for errors is just a plain text message
        # The following code is functionally equivalent to calling:
        #
        #     pecan.override_template(None, "text/plain")
        #
        # We do it this way to work around a bug in our unit-test framework
        # in which the mocked request object isn't properly mocked in the pecan
        # core module (gilbert.plz@oracle.com)
        pecan.request.pecan['override_template'] = None
        pecan.request.pecan['override_content_type'] = 'text/plain'

    def _func_client_error(excp, status_code):
        pecan.response.status = status_code
        pecan.response.text = str(excp)

        # The following code is functionally equivalent to calling:
        #
        #     pecan.override_template(None, "text/plain")
        #
        # We do it this way to work around a bug in our unit-test framework
        # in which the mocked request object isn't properly mocked in the pecan
        # core module (gilbert.plz@oracle.com)
        pecan.request.pecan['override_template'] = None
        pecan.request.pecan['override_content_type'] = 'text/plain'

    return wrap_controller_exception(func,
                                     _func_server_error,
                                     _func_client_error)

def wrap_wsme_pecan_controller_exception(func):
    """Error handling for controllers decorated with wsmeext.pecan.wsexpose:

    Controllers wrapped with wsme_pecan.wsexpose don't throw
    exceptions but handle them internally. We need to intercept
    the response and mask potentially sensitive information.
    """

    @functools.wraps(func)
    def wrapped(*args, **kw):
        ret = func(*args, **kw)
        ismapping = isinstance(ret, abc.Mapping)
        if (pecan.response.status_code >= 500 and ismapping):

            log_correlation_id = uuidutils.generate_uuid()
            LOG.error("%s:%s", log_correlation_id, ret.get("faultstring",
                                                           "Unknown Error"))
            ret['faultstring'] = str(OBFUSCATED_MSG % log_correlation_id)
        return ret

    return wrapped

def wrap_keystone_exception(func):
    """Wrap keystone exceptions and throw Solum specific exceptions."""
    @functools.wraps(func)
    def wrapped(*args, **kw):
        try:
            return func(*args, **kw)
        except keystone_exceptions.AuthorizationFailure:
            raise AuthorizationFailure(
                client=func.__name__, message="reason: %s" % sys.exc_info()[1])
        except keystone_exceptions.ClientException:
            raise AuthorizationFailure(
                client=func.__name__,
                message="unexpected keystone client error occurred: %s"
                        % sys.exc_info()[1])
    return wrapped

class SolumException(Exception):
    """Base Solum Exception

    To correctly use this class, inherit from it and define
    a 'msg_fmt' property. That msg_fmt will get printf'd
    with the keyword arguments provided to the constructor.

    """
    message = _("An unknown exception occurred.")
    code = 500

    def __init__(self, **kwargs):
        self.kwargs = kwargs

        if CONF.fatal_exception_format_errors:
            assert isinstance(self.msg_fmt, str)

        try:
            self.message = self.msg_fmt % kwargs
        except KeyError:
            # kwargs doesn't match a variable in the message
            # log the issue and the kwargs
            LOG.exception(_('Exception in string format operation'),
                          extra=dict(
                              private=dict(
                                  msg=self.msg_fmt,
                                  args=kwargs
                                  )
                              )
                          )

            if CONF.fatal_exception_format_errors:
                raise

    def __str__(self):
        return self.message

class ResourceLimitExceeded(SolumException):
    msg_fmt = _("Resource limit exceeded. Reason: %(reason)s")

class BadRequest(SolumException):
    msg_fmt = _("The request is malformed. Reason: %(reason)s")
    code = 400

class ObjectNotFound(SolumException):
    msg_fmt = _("The %(name)s %(id)s could not be found.")

class ObjectNotUnique(SolumException):
    msg_fmt = _("The %(name)s already exists.")

class RequestForbidden(SolumException):
    msg_fmt = _("The request is forbidden. Reason: %(reason)s")
    code = 403

class ResourceNotFound(ObjectNotFound):
    msg_fmt = _("The %(name)s resource %(id)s could not be found.")
    code = 404

class ResourceExists(ObjectNotUnique):
    msg_fmt = _("The %(name)s resource already exists.")
    code = 409

class ResourceStillReferenced(SolumException):
    msg_fmt = _("The %(name)s resource cannot be deleted because one or more"
                " resources reference it.")
    code = 409

class UnsupportedMediaType(SolumException):
    msg_fmt = _("\'%(name)s\' is not a supported media type for the %(method)s"
                " method of this resource")
    code = 415

class Unprocessable(SolumException):
    msg_fmt = _("Server is incapable of processing the specified request.")
    code = 422

class PlanStillReferenced(ResourceStillReferenced):
    msg_fmt = _("Plan %(name)s cannot be deleted because one or more"
                " Assemblies reference it.")

class LPStillReferenced(ResourceStillReferenced):
    msg_fmt = _("Languagepack %(name)s cannot be deleted because one or more"
                " applications reference it.")

class NotImplemented(SolumException):
    msg_fmt = _("The requested operation is not implemented.")
    code = 501

class AuthorizationFailure(SolumException):
    msg_fmt = _("%(client)s connection failed. %(message)s")

class InvalidObjectSizeError(Exception):
    msg_fmt = _("Invalid object size.")

class MaxRetryReached(Exception):
    msg_fmt = _("Maximum retries has been reached.")


import regex

from typing import Dict, List, TypedDict
from aocd import get_data

NUMBERS_RE = regex.compile(r" (\d+)")

class RulesWithEntries(TypedDict):
    rules: Dict[str, str]
    entries: List[str]

def parse(raw: str) -> RulesWithEntries:
    """
    Precompute regex, `47: 7 10 | 5 11 \\n aaaaaaaa`
    -> `{'rules': {'47': '(?:(?:7 10 )|(?: 5 11))'} , 'entries': 'aaaaaaaa'}`.
    """
    raw_rules, raw_entries = raw.strip().split("\n\n")
    rules = {}
    for rule in raw_rules.split("\n"):
        key, under_rules = rule.split(":", 1)
        if under_rules[2] in "ab":
            rules[key] = under_rules[2]
        elif rule.find("|") != -1:
            rules[key] = f"(?:(?:{under_rules.replace(' |', ')|(?:')}))"
        else:
            rules[key] = f"(?:{under_rules})"
    return {"rules": rules, "entries": raw_entries.split("\n")}

def run(rules: Dict[str, str], entries: List[str]):
    """Compute the regex and count how many entry match it."""
    rule_0 = rules["0"]
    match = NUMBERS_RE.search(rule_0)
    while match:
        rule_0 = NUMBERS_RE.sub(rules[match[1]], rule_0, count=1)
        match = NUMBERS_RE.search(rule_0)
    rule_0_re = regex.compile(rule_0)
    return sum(1 for line in entries if rule_0_re.fullmatch(line))

def part_one(rules_entries: RulesWithEntries):
    """Valid word number with regex."""
    return run(rules_entries["rules"], rules_entries["entries"])

def part_two(rules_entries: RulesWithEntries):
    """Valid word number with a recursive patched regex."""
    patched_rules = dict(rules_entries["rules"])
    patched_rules.update({"8": " 42+?",
                          "11": "(?P<rec>(?: 42 31)|(?: 42(?&rec) 31))"})
    return run(patched_rules, rules_entries["entries"])

if __name__ == "__main__":
    print("--- Day 19: Monster Messages ---")
    puzzle = parse(get_data(day=19, year=2020))
    print("Part One:", part_one(puzzle))
    print("Part Two:", part_two(puzzle))


from typing import Union
from enum import Enum

from fastapi import FastAPI, Request

app = FastAPI()

# https://fastapi.tiangolo.com/es/advanced/custom-response/#redirectresponse
from fastapi.responses import RedirectResponse
@app.get("/")
def redirect_to_home(request: Request):
    #return {"raw_url": request.url._url}
    return RedirectResponse(request.url._url+"home")

@app.get("/hello")
def read_root():
    return {"Hello": "World"}

@app.get("/integer/{int_id}")
def read_item(int_id: int, q: Union[str, None] = None):
    return {"int_id": int_id, "q": q}

# https://fastapi.tiangolo.com/tutorial/path-params/#path-convertor
@app.get("/file/path/{file_path:path}")
async def show_file_path(file_path: str):
    return {"file_path": file_path}

# https://fastapi.tiangolo.com/advanced/custom-response/#fileresponse -> https://stackoverflow.com/a/62939520
from fastapi.responses import FileResponse
@app.get("/file/{file_path:path}")
async def respond_file_content(file_path: str):
    return FileResponse("app/"+file_path)

# https://fastapi.tiangolo.com/tutorial/path-params/#return-enumeration-members
class ModelName(str, Enum):
    bonus = "bonus"
    user = "user"
    group = "group"

@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
    if model_name is ModelName.bonus:
        return {"model_name": model_name, "message": "Seems like you got an BONus!"}

    if model_name.value == "user":
        return {"model_name": model_name, "message": "You want's to get the User?"}

    return {"model_name": model_name, "message": "That is the model you are looking for?"}

# https://fastapi.tiangolo.com/advanced/custom-response/#html-response
from fastapi.responses import HTMLResponse
@app.get("/home/", response_class=HTMLResponse)
async def read_items():
    return """

            <title>Some HTML in here</title>

Look, some HTML Markup!

    """