import yfinance
import pandas as pd
from hmmlearn.hmm import GaussianHMM,GMMHMM
import matplotlib.pyplot as plt
from ta_indicators import get_ta
from sklearn.pipeline import make_pipeline
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from mlxtend.feature_extraction import PrincipalComponentAnalysis
from sklearn.ensemble import ExtraTreesRegressor
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectFromModel
from random import shuffle
from itertools import product
import numpy as np
import warnings
import numpy as np
import namegenerator
import matplotlib
import sqlite3
from multiprocessing import Pool, cpu_count
from simple_trader_hmm import trader
from datetime import timedelta
warnings.simplefilter("ignore")

class pipeline():
    def __init__(self, run_type, params_dict = None):
        self.conn = sqlite3.connect('hmm_rolling.db')

        self.run_type = run_type

        self.pca_n_components = params_dict.get('pca_n_components', 3)
        self.k_features = params_dict.get('k_features', 3)
        self.train_length =  params_dict.get('train_length', 3)

        if self.run_type == 'find_features':
            # run decision tree and features finder algorithms
            self.name = params_dict.get('name', namegenerator.gen())

            self.cutoff_date =  params_dict.get('cutoff_date', '2017-01-01')

        elif self.run_type == 'rolling_test':
            # run test on new test data cutoffs using features already defined
            self.name = params_dict.get('name')
            self.features_found = params_dict.get('features')
            self.cutoff_date =  params_dict.get('cutoff_date')
            print('testing using\n', self.features_found, '\nand date of', self.cutoff_date)
        elif self.run_type == 'production':
            # read params from database
            self.production = True
            self.name = params_dict.get('name')
            pca_n_components, k_features, features_found = self.get_model_from_db()
            self.pca_n_components = pca_n_components
            self.k_features = k_features
            self.features_found = features_found
            print('using features', features_found)

        #self.cutoff_date = '2017-01-01'

        self.n_experiments = 30

        self.get_data()

        if self.run_type == 'production':
            # run production
            print('running production')
            self.run_pipeline()
            print('predicting completed')
        elif self.run_type == 'rolling_test':
            print('running test on other dates', self.cutoff_date)
            self.run_pipeline()
            if self.pipeline_failed == False:
                self.get_results()
                self.store_results()
        elif self.run_type == 'find_features':
            # run feature selection and test data prediction
            self.run_decision_tree()
            self.run_pipeline()
            if self.pipeline_failed == False:
                print('found model', self.features_found)
                self.get_results()
                self.store_results()

    def get_model_from_db(self):
        sql = 'select * from models_final where name == "%s"' % self.name
        df = pd.read_sql(sql, self.conn)
        pca_n_components = int(df['pca_n_components'].values[0])
        k_features = int(df['k_features'].values[0])
        features_found = eval(df['features'].values[0])
        return pca_n_components, k_features, features_found

    def store_results(self):
        self.results_df['name'] = self.name
        self.results_df['cutoff_date'] = str(self.cutoff_date)
        self.results_df['train_score'] = self.train_score
        self.results_df['test_score'] = self.test_score
        self.results_df['train_correl'] = self.train_correl
        self.results_df['test_correl'] = self.test_correl
        self.results_df['pca_n_components'] = self.pca_n_components
        self.results_df['k_features'] = self.k_features
        self.results_df['traing_length'] = self.train_length
        self.results_df['features'] = str(self.features_found)

        self.results_df.to_sql('models_final', self.conn, if_exists='append', index=False)
        print(self.results_df)

        #input()

    def run_pipeline(self, production=False):
        self.pipeline_failed = True
        self.max_score = -np.inf
        self.max_correl = -np.inf

        # create pipeline
        pipe_pca = make_pipeline(StandardScaler(),
                                PrincipalComponentAnalysis(n_components=self.pca_n_components),
                                #GMMHMM(n_components=3, covariance_type='full'))
                                GaussianHMM(n_components=3, covariance_type='full'))
        exp_num = 0
        if self.run_type == 'find features':
            print('finding features')
        while exp_num < self.n_experiments:

            train = self.clean_train.copy()
            test = self.clean_test.copy()
            means = []
            stddevs = []
            scores = []
            correls = []

            if self.run_type == 'find_features':
                # choose features
                shuffle(self.starting_features)
                test_cols = ['return'] + self.starting_features[0:self.k_features]

                if 'stoch' not in str(test_cols):
                    continue

            elif self.run_type == 'production' or self.run_type == 'rolling_test':
                test_cols = self.features_found

            # test features on training dataset
            pipe_pca.fit(train[ test_cols ])
            try:
                self.train_score = np.exp( pipe_pca.score(train[ test_cols ]) / len(train) ) * 100
            except:
                self.train_score = None
            train['state'] = pipe_pca.predict(train[test_cols])
            train = self.rename_states(train)
            if train is None:
                continue
            criteria_check = self.check_criteria(train)
            if criteria_check == False:
                continue

            # get the correlation between state and next day percent changes
            train['next_day'] = train['close'].shift(-1) / train['close'] - 1
            train_means = train.dropna().groupby(by='state')[['return', 'next_day']].mean()*100
            train_correl = train_means.corr()
            self.train_correl = train_correl['return']['next_day']

            # do the same for the test data
            pipe_pca.fit(test[ test_cols ])
            try:
                self.test_score = np.exp( pipe_pca.score(test[ test_cols ]) / len(test) ) * 100
            except:
                self.test_score = None
            test['state'] = pipe_pca.predict(test[test_cols])
            test = self.rename_states(test)

            if self.run_type == 'production':
                self.new_predictions = test.tail(30)
                return

            if self.run_type == 'find_features':
                if test is None:
                    continue
                criteria_check = self.check_criteria(test)
                if criteria_check == False:
                    continue

            # get the correlation between state and next day percent changes
            test['next_day'] = test['close'].shift(-1) / test['close'] - 1
            test_means = test.dropna().groupby(by='state')[['return', 'next_day']].mean()*100
            test_correl = test_means.corr()
            self.test_correl = test_correl['return']['next_day']

            exp_num = exp_num + 1

            if ( self.train_correl > self.max_correl and self.test_correl>0 ) or self.run_type == 'rolling_test':

                self.train_predicted = train
                self.test_predicted = test
                self.features_found = test_cols

                self.train_means = train_means
                self.test_means = test_means

                #print('model found on expirement number', exp_num)
                #print(self.features_found)

                self.max_correl = self.train_correl
                self.pipeline_failed = False

    def check_criteria(self, df):

        counts_check = int( len(df) *.1 )
        # ensure all three states are used
        counts = df.groupby(by='state')['state'].count()
        if not counts[counts<counts_check].empty or len(df.groupby(by='state'))<3:
            return False

        # get the correlation between state and next day percent changes
        df['next_day'] = df['close'].shift(-1) / df['close'] - 1
        correl = (df.dropna().groupby(by='state')[['return', 'next_day']].mean() * 100).corr()

        correl = correl['return']['next_day']

        if correl<.5:
            return False

        # ensure buy and strong buy returns and next returns are positive
        means = df.dropna().groupby(by='state')[['return', 'next_day']].mean() * 100

        if float(means[means.index == 0]['return'])>0 or float(means[means.index == 1]['return'])<0 or float(means[means.index == 2]['return'])<0:
            return False
        if float(means[means.index == 0]['return'])>0 or float(means[means.index == 1]['next_day'])<0 or float(means[means.index == 2]['next_day'])<0:
            return False

        return True

    def rename_states(self, df):
        # rename states accordingly
        state_nums = df.groupby(by='state').mean().sort_values(by='return')
        if len(state_nums)<3:
            return None

        state_nums['renamed_state'] = ['sell', 'buy', 'strong_buy']
        state_nums['renamed_state_nums'] = [0,1,2]

        for i in list(state_nums.index):
            #print('renaming state %s to state %s' % ( i, state_nums.loc[i]['renamed_state']))
            df.loc[df['state']==i, 'renamed_state'] = state_nums.loc[i]['renamed_state']
            df.loc[df['state']==i, 'renamed_state_num'] = state_nums.loc[i]['renamed_state_nums']

        df['state'] = df['renamed_state_num']
        #del df['renamed_state_num']

        return df

    def get_results(self):
        df = pd.DataFrame()

        self.train_means = self.train_means.unstack().to_frame().T
        self.train_means.columns = ['train_0_return', 'train_1_return', 'train_2_return', 'train_0_next_day', 'train_1_next_day', 'train_2_next_day', ]
        self.test_means = self.test_means.unstack().to_frame().T
        self.test_means.columns = ['test_0_return', 'test_1_return', 'test_2_return', 'test_0_next_day', 'test_1_next_day', 'test_2_next_day', ]

        self.results_df = pd.concat([self.train_means, self.test_means],axis=1)

        # store trades to be used in trader
        self.test_predicted['name'] = self.name
        self.test_predicted.to_sql('trades_final', self.conn, if_exists='append', index=False)

        safe_return = trader(self.name, 'QQQ', 'QLD').return_percentage
        moderate_return = trader(self.name, 'QQQ', 'TQQQ').return_percentage
        extreme_return = trader(self.name, 'QLD', 'TQQQ').return_percentage

        self.results_df['safe_return'] = safe_return
        self.results_df['moderate_return'] = moderate_return
        self.results_df['extreme_return'] = extreme_return

        self.test_predicted.plot.scatter(x='date',
                                        y='close',
                                        c='renamed_state_num',
                                        colormap='viridis')

        fig = matplotlib.pyplot.gcf()
        fig.set_size_inches(18.5, 10.5, forward=True)
        file_name = self.name+'_'+str(self.cutoff_date).replace('-','')
        print('plotting', file_name)

        plt.savefig('./plots_rolling/%s.png'% file_name )

    def get_data(self):
        stock_df = yfinance.Ticker('QQQ').history(period='max')
        stock_df = stock_df.reset_index()
        stock_df = get_ta(stock_df, volume=True, pattern=False)
        stock_df.columns = map(str.lower, stock_df.columns)
        stock_df["return"] = stock_df["close"].pct_change()
        stock_df.columns = map(str.lower, stock_df.columns)
        stock_df = stock_df.dropna()

        cutoff_datetime = pd.to_datetime(self.cutoff_date)

        start_train = cutoff_datetime - timedelta(days=365 * self.train_length)
        end_train = cutoff_datetime

        start_test = cutoff_datetime
        end_test = cutoff_datetime + timedelta(days=365 * 1)

        self.clean_train = stock_df[ (stock_df['date'] > start_train) & (stock_df['date'] < end_train) ]
        self.clean_test = stock_df[ (stock_df['date'] > start_test) & (stock_df['date'] < end_test) ]

    def run_decision_tree(self):

        # get features
        train = self.clean_train.copy()
        test = self.clean_test.copy()
        test_cols = train.columns.drop(['date','return'])
        X = train[test_cols]
        y = train['return']
        clf = ExtraTreesRegressor(n_estimators=50)
        clf = clf.fit(X, y)
        df = pd.DataFrame([test_cols, clf.feature_importances_]).T
        df.columns = ['feature', 'importances']
        df = df.sort_values(by='importances').tail(40)

        self.starting_features = list(df['feature'].tail(40).values)

def run_pipeline_class(params_dict):
    cutoff_dates = ['2017-01-01', '2018-01-01', '2019-01-01', ]

    params_dict['cutoff_date'] = cutoff_dates[0]
    x = pipeline('find_features', params_dict = params_dict)
    params_dict['name'] = x.name
    params_dict['features'] = x.features_found

    params_dict['cutoff_date'] = cutoff_dates[1]
    pipeline('rolling_test', params_dict)

    params_dict['cutoff_date'] = cutoff_dates[2]
    pipeline('rolling_test', params_dict)

if __name__ == '__main__':
    # create params list to iterate through
    #pca_n_components = list( range(3,15) )
    params_list_of_dicts = []
    pca_n_components = [3]
    simulations = [0,1,2,3]
    k_features = list( range(3,15) )

    #pca_n_components = [3]
    #simulations = [0,]
    #k_features = list( range(3,4) )

    train_length = [2,3,4,5,6,7]

    params_list = list(product( pca_n_components, k_features, train_length, simulations ))

    shuffle(params_list)

    for pca_n_components, k_features, train_length, _ in params_list:

        params_dict = {
                        'pca_n_components': pca_n_components,
                        'k_features': k_features,
                        'train_length': train_length,
                      }
        params_list_of_dicts.append(params_dict)

    p = Pool( int(cpu_count()-1) )
    p.map(run_pipeline_class, params_list_of_dicts)
    #run_pipeline_class(params_list_of_dicts[0])


from exchange.models import *
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw

img = Image.open(sketch.image.file)
draw = ImageDraw.Draw(img)
# font = ImageFont.truetype(<font-file>, <font-size>)
font = ImageFont.truetype("Spartan-Regular.ttf", 20)
subtitlefont = ImageFont.truetype("Spartan-SemiBold.ttf", 14)
#Should we use black or white text?
text_area = img.crop((20, img.height-40, 230, img.height-20)) #get the background of the text area
text_area.thumbnail((1, 1))
pixel = text_area.getpixel((0,0)) #shrink it to one pixel
gray_scale = (pixel[0]*0.2989 + pixel[1]*0.5870 + pixel[2]*0.1140) / 255 #calculate the grayscale val
if gray_scale < 0.5:
    rgb = (255, 255, 255)
else:
    rgb = (0,0,0)

draw.text((20, img.height-60),"Sign up for the March Exchange at",rgb,font=subtitlefont)
draw.text((20, img.height-40),"GraffExchange.com",rgb,font=font)
img.save('sample-out.jpg')

cropped_example


import unittest

from src.colour import Colour
from src.test_board_base import TestBoardBase, Contains, Die, Can, Cannot

class TestBoardIsMovePossible(TestBoardBase):

    def test_can_move_to_unoccupied_space(self):
        self.add_many_pieces(1, Colour.BLACK, 12)

        self.assert_piece_at(12, Can.move(6))

    def test_cannot_move_to_occupied_space(self):
        self.add_many_pieces(1, Colour.BLACK, 17)
        self.add_many_pieces(2, Colour.WHITE, 11)

        self.assert_piece_at(17, Cannot.move(6))

    def test_can_move_to_occupied_space_if_same_colour(self):
        self.add_many_pieces(1, Colour.WHITE, 17)
        self.add_many_pieces(2, Colour.WHITE, 11)

        self.assert_piece_at(17, Can.move(6))

    def test_can_take_piece(self):
        self.add_many_pieces(1, Colour.BLACK, 17)
        self.add_many_pieces(1, Colour.WHITE, 11)

        self.assert_piece_at(17, Can.move(6))

    def test_cannot_move_off_before_end_game(self):
        self.add_many_pieces(1, Colour.BLACK, 1)
        self.add_many_pieces(1, Colour.BLACK, 17)

        self.assert_piece_at(1, Cannot.move(6))

    def test_can_move_several_pieces_off_in_end_game(self):
        self.add_many_pieces(1, Colour.BLACK, 1)
        self.add_many_pieces(2, Colour.BLACK, 2)

        self.assert_piece_at(2, Can.move(2))
        self.board.move_piece(self.board.get_piece_at(2), 2)
        self.assert_piece_at(2, Can.move(2))
        self.board.move_piece(self.board.get_piece_at(2), 2)
        self.assert_piece_at(1, Can.move(2))

    def test_cannot_move_off_low_value_piece_too_soon(self):
        self.add_many_pieces(1, Colour.BLACK, 1)
        self.add_many_pieces(1, Colour.BLACK, 6)

        self.assert_piece_at(1, Cannot.move(5))

    def test_cannot_move_other_piece_if_there_is_a_taken_piece(self):
        self.add_many_pieces(1, Colour.WHITE, 0)
        self.add_many_pieces(1, Colour.WHITE, 6)

        self.assert_piece_at(6, Cannot.move(1))

    def test_can_move_taken_piece(self):
        self.add_many_pieces(1, Colour.WHITE, 0)
        self.add_many_pieces(1, Colour.WHITE, 6)

        self.assert_piece_at(0, Can.move(1))

class TestBoardMovePiece(TestBoardBase):

    def test_can_move_to_unoccupied_space(self):
        self.add_piece(Colour.WHITE, 12)

        self.move_piece_at(12, Die.roll_of(1))

        self.assert_location(12, Contains(0).pieces())
        self.assert_location(13, Contains(1).piece())

    def test_can_move_to_occupied_space_of_same_colour(self):
        self.add_piece(Colour.BLACK, 12)
        self.add_many_pieces(2, Colour.BLACK, 10)

        self.move_piece_at(12, Die.roll_of(2))

        self.assert_location(12, Contains(0).pieces())
        self.assert_location(10, Contains(3).pieces())

    def test_can_take_piece(self):
        self.add_piece(Colour.WHITE, 12)
        self.add_piece(Colour.BLACK, 15)

        self.move_piece_at(12, Die.roll_of(3))

        self.assert_location(12, Contains(0).pieces())
        self.assert_location(15, Contains(1).piece())
        self.assertEqual(self.board.get_piece_at(15).colour, Colour.WHITE)
        self.assert_location(25, Contains(1).piece())

    def test_can_move_piece_off(self):
        self.add_piece(Colour.WHITE, 22)

        self.move_piece_at(22, Die.roll_of(3))

        white_piece = self.board.get_pieces(Colour.WHITE)
        self.assertEqual(len(white_piece), 0)

    def test_can_move_piece_off_when_overshooting(self):
        self.add_piece(Colour.BLACK, 1)

        self.move_piece_at(1, Die.roll_of(6))

        black_pieces = self.board.get_pieces(Colour.BLACK)
        self.assertEqual(len(black_pieces), 0)

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


# append : Add an item to the end of the list
first_list = [1, 2, 3, 4]
first_list.append(5)
print(first_list)  # [1, 2, 3, 4, 5]

print("-----------------------------------------")

# extend : menambah banyak data sekaligus ke akhir list
first_list = [1, 2, 3, 4]

first_list.append([5, 6, 7, 8])
print(first_list) #[1, 2, 3, 4,   [5, 6, 7, 8]]

correct_list = [1, 2, 3, 4]

correct_list.extend([5, 6, 7, 8])
print(correct_list) # [1, 2, 3, 4, 5, 6, 7, 8, 9]

print("-----------------------------------------")

# insert : Menambah data ke posisi yg diinginkan
first_list = [1, 2, 3, 4]

first_list.insert(2, 'Hi!') #: maksudnya menambah String 'Hi'  di index ke 2
print(first_list) # [1, 2, 'Hi', 3, 4]
first_list.insert(-1, 'The end!')
print(first_list) # [1, 2, 'Hi!', 3, 'The end!', 4]

nums = [1, 2, 3, 4]
nums.insert(len(nums), "LAST")
print(nums) # [1, 2, 3, 4, 'LAST']

print("-----------------------------------------")

# clear : menghapus semua elemen di list
first_list = [1, 2, 3, 4]

first_list.clear()
print(first_list) # [ ]

print("-----------------------------------------")

# pop : Menghapus elemen yg ingin dihapus, if no index is specified, removes and return last item in the list
first_list = [1, 2, 3, 4]
first_list.pop() #4 : yg dihapus index terakhir yaitu 4
first_list.pop(1) #2 : yg dihapus index ke 1 yaitu 2

print("-----------------------------------------")

# remove: remove the first item from the list whose value is x, throws a ValueError if the item is not found
first_list = [1, 2, 3, 4, 4, 4]
first_list.remove(2) #: menghapus elemen yg valuenya = 2
print(first_list) # [1, 3, 4, 4, 4]
first_list.remove(4) #: karna 4 ada banyak, yg dihapus yg paling depan
print(first_list) # [1, 3, 4, 4]

print("-----------------------------------------")

# index : return the index of the specified item in the list
numbers = [6, 7, 8, 9, 10]

numbers.index(6) #1 : nyari tau elemen 6 ada di index keberapa, dan elemen 6 ada di index ke 1
numbers.index(9) #4

# Can specify start and end
numbers = [5, 5, 6, 7, 5, 8, 8, 9, 10]

numbers.index(5) #0 : elemen 5 yg paling awal ada di index ke -0
numbers.index(5, 1) #1 : elemen 5 yg kedua ada di index ke -1
numbers.index(5, 2) #4 : : elemen 5 yg ketiga ada di index ke -4

numbers.index(8, 6, 8) #6 : mencari elemen 8 yg ada diantara elemen 8 dan 6

print("-----------------------------------------")

# count : return the number of times x appears in the list
numbers = [1, 2, 3, 4, 3, 2, 1, 4, 10, 2]

numbers.count(2) #3 : elemen 2 muncul sebanyak 3 kali di list
numbers.count(21) #0 : elemen 21 tidak ada didalam list
numbers.count(3) #2: elemen 3 muncul sebanyak 2 kali di list

print("-----------------------------------------")

# reverse : reverse the element of the list (in-place)
first_list = [1, 2, 3, 4]
first_list.reverse()
print(first_list) #[4, 3, 2, 1]

print("-----------------------------------------")

# sort : sort the items of the list (in-place)
another_list = [6, 4, 1, 2, 5]
another_list.sort()
print(another_list) # [1, 2, 4, 5, 6]

print("-----------------------------------------")

# join : is commonly used to convert lists to strings
words = ['Coding', 'Is', 'Fun!']
print(' '.join(words)) # ‘Coding is Fun!’

# another example
name = ['Mr', 'Steele']
print('.   '.join(name)) #’Mr.  Steele’


# 10 ORE => 10 A
# 1 ORE => 1 B
# 7 A, 1 B => 1 C
# 7 A, 1 C => 1 D
# 7 A, 1 D => 1 E
# 7 A, 1 E => 1 FUEL

def parse_graph():
    def _p(i):
        num, ele = i.strip().split()
        return ele, int(num)
    reactions = {}
    with open('inputs/input14') as f:
        for line in f.readlines():
            inp, out = line.rstrip().split(' => ')
            left, right = list(map(_p, left.split(','))), _p(right)
            reactions[right[0]] = (right[1], left)
    return reactions

parse_graph()


'''
Created on 23-Apr-2017
Programming Assignment 1 of Week 6 from the Classification course of
Coursera Machine Learning Specialization
@author: sudheer
'''

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score

def remove_punctuation(text):
    import string
    translator = str.maketrans({key: None for key in string.punctuation})
    return text.translate(translator)

def apply_threshold(probabilities, threshold):
    return np.where(probabilities >= threshold, +1, -1)
    #return np.apply_along_axis(lambda probability: +1 if probability > threshold else -1,axis=1,arr=probabilities)

def plot_pr_curve(precision, recall, title):
    plt.rcParams['figure.figsize'] = 7, 5
    plt.locator_params(axis = 'x', nbins = 5)
    plt.plot(precision, recall, 'b-', linewidth=4.0, color = '#B0017F')
    plt.title(title)
    plt.xlabel('Precision')
    plt.ylabel('Recall')
    plt.rcParams.update({'font.size': 16})
    plt.show()

products = pd.read_csv('Data/Week6/amazon_baby.csv')
products = products.fillna({'review':''})
products['review_clean'] = products['review'].apply(remove_punctuation)

#Remove all the reviews with rating = 3, since they tend to have neutral sentiment
products = products[products['rating'] != 3]

#Assign a sentiment of 1 if rating is greater than 3, else -1
products['sentiment'] = products['rating'].apply(lambda rating: +1 if rating > 3 else -1 )

#Load the train and test indices
train_idx = pd.read_json('Data/Week6/train-idx.json').values[:,0]
test_idx = pd.read_json('Data/Week6/test-idx.json').values[:,0]

#Construct the train and test data
train_data = products.iloc[train_idx] #Extract the data using the indices
test_data = products.iloc[test_idx] #Extract the data using the indices

#Use this token pattern to keep single-letter words
vectorizer = CountVectorizer(token_pattern=r'\b\w+\b')
#First learn vocabulary from the training data and assign columns to words
#Then convert the training data into a sparse matrix
train_matrix = vectorizer.fit_transform(train_data['review_clean'])
#Convert the test data into a sparse matrix, using the same word-column mapping
test_matrix = vectorizer.transform(test_data['review_clean'])

#Test a sentiment classifier with logistic Regression
sentiment_model = LogisticRegression()
sentiment_model.fit(train_matrix, train_data['sentiment']) #Fit the model to the training data

#Compute the accuracy on the test data
accuracy = accuracy_score(y_true=test_data['sentiment'], y_pred=sentiment_model.predict(test_matrix))
print('Test accuracy: %s' %accuracy)

#A good model should beat the majority class classifier.
#Majority class in this dataset is the positve class.
baseline = len(test_data[test_data['sentiment'] == +1])/len(test_data)
print('Baseline accuracy (majority class classifier): %s' %baseline)

#Construct the confusion matrix
cmat = confusion_matrix(y_true=test_data['sentiment'].as_matrix(),
                         y_pred=sentiment_model.predict(test_matrix),
                         labels= sentiment_model.classes_)

print('target_label | predicted_label | count')
print('-------------+-----------------+------')
#Print out the confusion matrix
for i, target_label in enumerate(sentiment_model.classes_):
    for j, predicted_label in enumerate(sentiment_model.classes_):
        print('{0:^13} | {1:^15} | {2:5d}'.format(target_label, predicted_label, cmat[i,j]))

precision = precision_score(y_true=test_data['sentiment'].as_matrix(),
                             y_pred=sentiment_model.predict(test_matrix) )

print('Precision on test data is %s' %precision)

recall = recall_score(y_true=test_data['sentiment'], y_pred=sentiment_model.predict(test_matrix))

print('Recall on test data is %s' %recall )

#Vary the threshold
probabilities = sentiment_model.predict_proba(test_matrix)[:,1] #for class +1
threshold_5_prediction = apply_threshold(probabilities, 0.5)
threshold_9_prediction = apply_threshold(probabilities, 0.9)

print('Precision on test data with 0.5 threshold: %s' %precision_score(y_true=test_data['sentiment'].as_matrix(),
                                                                        y_pred=threshold_5_prediction))
print('Recall on test data with 0.5 threshold: %s' %recall_score(y_true=test_data['sentiment'].as_matrix(),
                                                                        y_pred=threshold_5_prediction))
print('Precision on test data with 0.9 threshold: %s' %precision_score(y_true=test_data['sentiment'].as_matrix(),
                                                                        y_pred=threshold_9_prediction))
print('Recall on test data with 0.9 threshold: %s' %recall_score(y_true=test_data['sentiment'].as_matrix(),
                                                                        y_pred=threshold_9_prediction))

#Precision recall Curve
threshold_values = np.linspace(0.5,1,num=100)

#For threshold in [0.5,1] compute the precision and recall
precision_all = []
recall_all = []
for threshold in threshold_values:
    precision = precision_score(y_true=test_data['sentiment'].as_matrix(),
                                          y_pred=apply_threshold(probabilities,threshold))
    recall = recall_score(y_true=test_data['sentiment'].as_matrix(),
                                    y_pred=apply_threshold(probabilities, threshold))
    print('Threshold: %s, Precision: %s, Recall: %s' %(threshold,precision,recall))
    precision_all.append(precision)
    recall_all.append(recall)

plot_pr_curve(precision_all, recall_all, 'Precision recall curve (all)')

#Among all the threshold values, what is the smallest value that achieves a precision of
#96.5 percent or higher


from kivy.uix.screenmanager import Screen, SlideTransition
from kivy.graphics import Line, Color
from kivy.properties import NumericProperty, ObjectProperty, StringProperty, BooleanProperty, ListProperty
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.image import Image
from kivy.uix.gridlayout import GridLayout
from kivy.resources import resource_find

import random as rand

# Import AI stuff
from .dotsandboxesAI.BoardEnvironment import BoardEnvironment
from .dotsandboxesAI.Agent import Agent
from .dotsandboxesAI.LeagueEnvironment import LeagueEnvironment
from time import sleep

def select_difficulty(auto=False):
    x = 0
    diffdict = {1: r'game_logic/dotsandboxesAI/qtables/easy.txt',
                2: r'game_logic/dotsandboxesAI/qtables/medium.txt',
                3: r'game_logic/dotsandboxesAI/qtables/hard.txt'}
    if not auto:
        while(x > 3 or x < 1):
            print("Select a difficulty:")
            print("1: Easy")
            print("2: Medium")
            print("3: Hard")
            x = int(input())

    else:
        x = rand.randint(1, 3)

    return diffdict[x]

class Dot(Image):
    """Custom widget inheriting from Image object. These are placed in the design/dotsandboxes.kv file

    Args:
        Image (kivy.uix.Image): Image widget
    """
    button_number = NumericProperty()
    def __init__(self, **kwargs):
        super(Dot, self).__init__(**kwargs)
        self.source = resource_find("images/dotsandboxes/dot.png")

class DotsAndBoxesScreen(Screen):
    """Screen object to be managed by ScreenManager object

    Args:
        Screen (kivy.uix.screenmanager.Screen): This inherits from kivy.relativelayout.RelativeLayout and uses that object's placement system. In the design file we used a gridlayout overwrite that placement system.

        The Object Property type lets kivy objects share variable names with the .kv files.
    """
    score = NumericProperty()
    ai_score = NumericProperty()
    game_grid = ObjectProperty(None)
    difficulty_setting = StringProperty("")
    match = StringProperty("")
    turn = BooleanProperty(True)
    piece = StringProperty("")
    lines = []
    dots = ListProperty()
    # dictionary mapping box scores to their image widget
    captured_boxes = []
    scoreboard = ObjectProperty(None)
    user_data = ObjectProperty(None)
    ai_data = ObjectProperty(None)
    first_league_run = True

    # a dictionary mapping dot numbers to acceptable dots to be paired with
    accepted_lines = {
        0: [1, 3],
        1: [0, 2, 4],
        2: [1, 5],
        3: [0, 6, 4],
        4: [1, 3, 5, 7],
        5: [2, 4, 8],
        6: [3, 7],
        7: [4, 6, 8],
        8: [7, 5]
    }

    # Map dots to lines in the board environment
    actual_lines = {
        (1, 2): 11,
        (0, 1): 10,
        (2, 5): 9,
        (1, 4): 8,
        (0, 3): 7,
        (4, 5): 6,
        (4, 3): 5,
        (5, 8): 4,
        (4, 7): 3,
        (3, 6): 2,
        (8, 7): 1,
        (6, 7): 0
    }

    start_dot = None

    def on_enter(self, *args):
        """Kivy Screen event listener that is run before the screen is entered

        Returns:
            None: Used to reset the board before entering the screen
        """

        self.clear_game_screen()
        self.board_env.reset()
        return super().on_enter(*args)

    def on_leave(self, *args):
        """Kivy Screen event listener that is run as the screen is left

        Returns:
            None:
        """
        self.restart()
        return super().on_leave(*args)

    def load_settings(self, diff, match):
        """
        Called whenever this screen is loaded
        self.lines is a list of tuples containing
        a line instruction object
        the start dot number
        the end dot number
        """

        self.difficulty_setting = diff
        self.match = match
        agent = Agent(resource_find(f"game_logic/dotsandboxesAI/qtables/{self.difficulty_setting.lower()}.txt"))
        self.board_env = BoardEnvironment(self, agent)
        self.scoreboard.size_hint_y = None

        # Load different settings based on game type
        if self.match == "Single Match":
            self.piece = self.board_env.turn
            if self.piece == "O":
                choice = [i for i, char in enumerate(self.board_env.board) if char == "X"][0]
                self.draw_ai_turn(choice, self.board_env.turn)

            # self.board_env.set_players(agent)
            self.board_env.print_board()
            self.scoreboard.height = 0
            self.ai_data.text, self.user_data.text = "", ""
            self.board_env.reset()
        else:
            # League Match
            self.first_league_run = True
            league = LeagueEnvironment(self.board_env, self)

            player_names = []
            board_agents = []
            league_agents = []

            player_names.append('learning strategy and tactics')
            board_agents.append(agent)
            league_agents.append(Agent(resource_find('game_logic/dotsandboxesAI/qtables/league.txt'), league))

            #player_names.append('learning tactics only')
            #board_agents.append(Agent(self.board_env, select_difficulty(True), 'max'))
            #league_agents.append(Agent(league, 'game_logic/dotsandboxesAI/qtables/league.txt', 'random'))

            #player_names.append('learning strategy only')
            #board_agents.append(Agent(self.board_env, select_difficulty(True), 'random'))
            #league_agents.append(Agent(league, 'game_logic/dotsandboxesAI/qtables/league.txt', 'max'))

            #player_names.append('no learning')
            #board_agents.append(Agent(self.board_env, select_difficulty(True), 'random'))
            #league_agents.append(Agent(league, 'game_logic/dotsandboxesAI/qtables/league.txt', 'random'))

            league.set_players(player_names, league_agents, board_agents)
            self.league_env = league
            self.scoreboard.height = 200
            for child in self.scoreboard.children:
                child.size_hint_y = None
                child.height = 200

            league.play_pair(self.first_league_run)
            self.first_league_run = False

    def menu(self):
        """Swap screen back to title screen
        """

        self.clear_game_screen()
        self.manager.transition = SlideTransition(direction="right")
        self.manager.current = "title"

    def restart(self):
        """This function is run whenever the "Restart Game" Button is pressed. Also used elsewhere
        """
        self.clear_game_screen()
        self.lines = []
        self.board_env.reset()
        self.piece = self.board_env.turn
        self.board_env.print_board()
        self.score, self.ai_score = 0, 0

    def league_restart(self):
        """This function is run whenever the "Restart Game" Button is pressed and the league environment is active
        """
        self.clear_game_screen()
        self.lines = []
        self.board_env.reset()
        self.league_env.reset_pair()
        self.league_env.play_pair(True)
        self.piece = self.board_env.turn
        self.board_env.print_board()
        self.score, self.ai_score = 0, 0

    def on_touch_down(self, touch):
        """Kivy event listener that is called when the user clicks in the Window

        Args:
            touch (kivy.MotionEvent): https://kivy.org/doc/stable/api-kivy.input.motionevent.html#kivy.input.motionevent.MotionEvent

            This function checks if any dot was clicked

        Returns:
        """
        # find what dot the mouse was over and save it to the start_dot property
        for i, _ in enumerate(self.dots):
            # if touch is within a box twice the radius of the dot, we draw
            if self.dots[i].collide_point(*touch.pos):
                self.start_dot = i
                break
        return super().on_touch_down(touch)

    def on_touch_up(self, touch):
        """kivy event listener that is called when the user lets go of the mouse or their touch

        Args:
            touch (kivy.MotionEvent): https://kivy.org/doc/stable/api-kivy.input.motionevent.html#kivy.input.motionevent.MotionEvent

            This function checks if any dot was clicked

        Returns:
        """
        # find what dot the mouse is over on mouse release and draw the appropriate line
        turn = self.board_env.turn
        if self.start_dot is None:
            return super().on_touch_up(touch)

        for dot_index, dot_obj in enumerate(self.dots):
            # if touch is within a box twice the radius of the dot, we draw
            if self.check_for_dot_click(touch, dot_index, dot_obj):
                with self.game_grid.canvas:
                    # save line to lines property to be updated on_size
                    points = list(self.dots[self.start_dot].center) + list(dot_obj.center)
                    # add half dot radius to x and y for the line because the dot position is measured from bottom left corner of dots (the radius of the dot is 10)
                    Color(1, 0, 0) if self.board_env.turn == "X" else Color(0,0,1)
                    self.lines.append((Line(points=points, width=3, group="lines"), self.start_dot, dot_index))

                # Add line to board environment
                # try except pairs to return line choice
                try:
                    choice = self.actual_lines[(self.start_dot, dot_index)]
                except KeyError:
                    choice = self.actual_lines[(dot_index, self.start_dot)]

                # play_game_turn returns true if the user scores
                # let ai move if user doesn't score
                if not self.board_env.play_game_turn(choice):
                    # Let AI think
                    sleep(.5)

                    if not self.board_env.is_full():
                        # Add AI move
                        self.board_env.play_game_turn()
                        self.board_env.print_board()
                    else:
                        self.is_full()

                # if the board is full, display the winner popup
                if self.board_env.is_full():
                    self.is_full()

                # change turn bool
                # self.turn = not self.turn
                self.start_dot = None
        return super().on_touch_up(touch)

    def check_for_dot_click(self, touch, dot_index, dot_obj):
        """Check if the user clicked a second dot valid with the current dot

        Args:
            touch (Touch): Kivy touch object
            dot_index (int): Index of dot we are checking
            dot_obj (kivy.Instruction): The object in memory that represents the dot drawing

        Returns:
            bool: Returns true if the dot that the user lets go of the mouse over is a valid pair with the dot from click
        """

        # warning monster bool
        return self.dots[dot_index].collide_point(*touch.pos) and self.start_dot is not None and dot_index in self.accepted_lines[self.start_dot] and self.check_dot_pair(dot_index, self.start_dot) in self.board_env.available_actions()

    def draw_ai_turn(self, choice, turn):
        """Draw the line based on AI turn. This function is called with the board environment method play_game_turn

        Args:
            choice (int): Choice decided by the AI.
        """
        actual_lines = {
            (1, 2): 11,
            (0, 1): 10,
            (2, 5): 9,
            (1, 4): 8,
            (0, 3): 7,
            (4, 5): 6,
            (4, 3): 5,
            (5, 8): 4,
            (4, 7): 3,
            (3, 6): 2,
            (8, 7): 1,
            (6, 7): 0
        }

        # Reverse the dictionary of lines and dots and find the dots based on the ai choice
        line_choice_dots = {value:key for key, value in actual_lines.items()}
        dots = line_choice_dots[choice] # get the entry in the dictionary that maps the line indexes to the dot indexes

        with self.game_grid.canvas:
            # save line to lines property to be updated on_size
            points = list(self.dots[dots[0]].center) + list(self.dots[dots[1]].center)
            # add half dot radius to x and y for the line because the dot position is measured from bottom left corner of dots (the radius of the dot is 10)
            # The amount added to i should be half of the dot_size set in the dotsandboxes.kv file
            Color(1, 0, 0) if turn == "X" else Color(0,0,1)

            line = Line(points=points, width=3, group="lines")
            self.lines.append((line, dots[0], dots[1]))

    def draw_captured_box(self, box_index, turn):

        # map box index to quadrant of grid
        boxes = {
            14:(0,1,3,4), # bottom left box
            15:(1,2,4,5), # bottom right box
            13:(4,5,8,7), # top right box
            12:(4,3,6,7) # top left box
        }

        avg_x, avg_y = 0, 0
        for dot_index in boxes[box_index]:
            #print(self.dots[dot_index].pos[0], self.dots[dot_index].pos[1])
            avg_x += self.dots[dot_index].center_x
            avg_y += self.dots[dot_index].center_y
        avg_x /= 4
        avg_y /= 4
        #print("Averages", avg_x, avg_y)
        color = "red" if turn == "X" else "blue"
        captured_box = Image(source=f"./images/dotsandboxes/{color}_{turn}.png", pos_hint={"center_x": avg_x/self.width, "center_y": avg_y/self.height})
        self.captured_boxes.append(captured_box)
        self.add_widget(captured_box)

    def is_full(self):
        """Display pop up when the board fills
        Called from within the self.board property of type BoardEnvironment

        Returns:
            None: Pop up that displays end condition of the game
            win
            lose
            tie
        """
        tie = self.ai_score == self.score

        winner_popup = Popup(size_hint=(0.8, 0.9), title="Winner Popup")
        # self.board.score_board is a dictionary of str:int with keys "X" and "O"
        if self.score > self.ai_score:
            text = "You are the winner"
            winner = True
        elif self.ai_score > self.score:
            text = "Computer is the winner"
            winner = False
        else:# it's a tie
            text = "There was a tie!"
            winner = None
        if self.match != "League Match":
            content = Button(text=text)
            self.board_env.print_board()
            content.bind(on_press=winner_popup.dismiss)
        else:
            content = Button(text=text)

            def play_on(pop_up_self):
                """functionality of button that shows at the end of a league Game

                Args:
                    pop_up_self (Button): This argument is the "self" call for the button we are binding the function to
                """
                self.league_env.play_pair_pt_2(winner, tie=tie)
                self.restart()
                self.league_env.play_pair(self.first_league_run)
                winner_popup.dismiss()

            content.bind(on_press=play_on)
        winner_popup.add_widget(content)
        winner_popup.open()

    def bet_options(self, options, message, func, AI_choice, cols=1):
        # creating grid for popup menu
        content = GridLayout(cols=cols, padding=50, spacing=50)
        # returning early if no options were passed to this function
        if len(options) == 0:
            return False
        # adding a button for each option with the option's text
        for option in options:
            content.add_widget(Button(text=option))
        # creating a popup with 'message' and 'content'
        option_popup = Popup(title=message, content=content, size_hint=(.8, .9), auto_dismiss=False)
        # function that will be called when a button is clicked
        def option_button(inner_self):
            # dismiss popup
            option_popup.dismiss()
            # grabbing the selected option
            result = inner_self.text
            # calling 'func' with the selected option and the AI's option
            self.league_env.play_pair_pt_1_5(result, AI_choice)
        # binding option_button button to each option
        for child in content.children:
            child.bind(on_press=option_button)
        # opening popup
        option_popup.open()

    def check_dot_pair(self, start, end):
        """Gives back the line index based on the pair of dots in kivy regardless of order from (dict) self.actual_lines

        Args:
            start (int): start dot index
            end (int): end dot index

        Returns:
            int: The index that cooresponds to a line in the BoardEnvironment's representation of the game board
        """
        try:
            return self.actual_lines[(start, end)]
        except KeyError:
            return self.actual_lines[(end, start)]

    def clear_game_screen(self):
        """Remove caputured box icons from screen
        """
        # clear lines
        self.game_grid.canvas.remove_group("lines")

        # clear captured boxes
        for box in self.captured_boxes:
            box.parent.remove_widget(box)
        self.captured_boxes = []

    def series_end(self, message):
        """Called when league series ends and displays final league betting information

        Args:
            message (str): Message sent by LeagueEnvironment with final betting info
        """
        content = GridLayout(cols=1, padding=50, spacing=50)
        content.add_widget(Button(text="Play again"))
        content.add_widget(Button(text="Return to menu"))
        series_end_popup = Popup(title=message, content=content, size_hint=(.8,.6 ), auto_dismiss=False)
        def play_again_button(inner_self):
            series_end_popup.dismiss()
            self.restart()
            self.clear_game_screen()
            self.league_env.play_pair(True)
        def end_game_button(inner_self):
            series_end_popup.dismiss()
            self.menu()
        content.children[1].bind(on_press=play_again_button)
        content.children[0].bind(on_press=end_game_button)
        series_end_popup.open()


from django import forms
import re

from django.core.exceptions import ValidationError

def validate_comma_separated_list(value):
    pattern = '[\\dа-яА-ЯёЁ]+'
    if re.search(pattern, value):
        raise ValidationError('Tags field contains non-Latin letters or digits')
    pattern = '[^,0-9a-zA-Z]+'
    if re.search(pattern, value):
        raise ValidationError('Tags field contains prohibited symbols')

class SearchForm(forms.Form):
    tags = forms.CharField(help_text='Enters tags separated by comma',
                           validators=[validate_comma_separated_list],
                           label='')


import mysql.connector

myDatabase = mysql.connector.connect(host="localhost", user="root", database="myDatabase")

myCursor = myDatabase.cursor()

sql = "update employee set salary=70000 where name='Varun'"
myCursor.execute(sql)

myDatabase.commit()


import pandas as pd
import matplotlib.pyplot as plt
import sys
import seaborn as sns
import warnings

#suppress any warnings
def fxn():
    warnings.warn("deprecated", DeprecationWarning)

with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    fxn()

warnings.simplefilter(action='ignore', category=FutureWarning)

#fragment length text file
frag_file=sys.argv[1]

#read in file, set columns
frag_df = pd.read_csv(frag_file,sep="\t",header=None)
frag_df.columns = ["sample_id", "fragment_length", "batch_id"]

#set max
max_value=frag_df["fragment_length"].max() + 5

#set id to character
frag_df['sample_id'] = frag_df.sample_id.astype(str)

#create facetgrid
plot = sns.FacetGrid(frag_df, col="batch_id", height=2, aspect=10, col_wrap = 1,sharex = False, sharey = False)

#create barplot: x=sampleid, y=frag length
plot1 = plot.map(sns.barplot,
                 'sample_id',
                 'fragment_length').fig.subplots_adjust(wspace=0.5, hspace=12)

#rotate x axis labels, shrink font
for axes in plot.axes.flat:
    _ = axes.set_xticklabels(axes.get_xticklabels(), rotation=90, Fontsize=5)

#add labels to plot
for ax in plot.axes:
    for p in ax.patches:
             ax.annotate("%.0f" % p.get_height(), (p.get_x() + p.get_width() / 2., p.get_height()),
                 ha='center', va='center', fontsize=5, color='black', xytext=(0, 5),
                 textcoords='offset points')

#remove x axis title
plot.set(xlabel=None)

#add title to plot
plot.fig.suptitle('Average Fragment Length by SampleID')

#reduce margins
plt.tight_layout()

#for testing, show
#plt.show()

#save plot to file
file_save = sys.argv[2]
plt.savefig(file_save)


# Función para contar la frecuencia de palabras en un texto
def contar_palabras(texto):
    # Dividir el texto en palabras
    palabras = texto.split()
    # Crear un diccionario para almacenar la frecuencia de palabras
    frecuencia_palabras = {}

    # Contar la frecuencia de cada palabra
    for palabra in palabras:
        # Eliminar signos de puntuación alrededor de la palabra
        palabra = palabra.strip('.,!?()[]{}":;')
        # Convertir la palabra a minúsculas para evitar diferencias entre mayúsculas y minúsculas
        palabra = palabra.lower()
        # Contar la frecuencia de la palabra y actualizar el diccionario
        frecuencia_palabras[palabra] = frecuencia_palabras.get(palabra, 0) + 1

    # Imprimir el diccionario de frecuencia de palabras
    print("Frecuencia de palabras:")
    for palabra, frecuencia in frecuencia_palabras.items():
        print(f"{palabra}: {frecuencia}")

# Pedir al usuario que ingrese un texto
texto = input("Ingrese un texto: ")

# Llamar a la función contar_palabras con el texto ingresado
contar_palabras(texto)


from django.conf.urls import patterns, url
from django.contrib import admin
from gm.views import *

admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'the_kingdom_gm.views.home', name='home'),
    # url(r'^blog/', include('blog.urls')),
    url(r'^$', gm_main),
    url(r'^login/$', gm_login),
    url(r'^main/$', gm_main),
    url(r'^manager_create/$', manager_create),
    url(r'^name/$', get_name),

)


from selenium.webdriver import  Chrome

from time import sleep

url = 'https://curso-python-selenium.netlify.app/aula_03.html'

browser = Chrome()
browser.get(url)

sleep(3)

a = browser.find_element_by_tag_name('a')

for click in range(10):
    p = browser.find_elements_by_tag_name('p')
    a.click()
    print(f'Valor de p: {p[-1].text} valor do clock: {click}')
    print(f'Valor de p: {p[-1].text == str(click)}')

print(f'Texto de A: {a.text}')
#browser.quit()


# Nama file: 7.interger.py
# Pembuat  : Bintang Syafrian Rizal - 24060122120031
# Tanggal  : 29 September 2022
# Deskripsi: Membuat fungsi-fungsi operasi dalam matematika dngan menggunakan rekursi

# Definisi dan Spesifikasi
# Pembagian : interger --> interger
# { bilint (n) menghitung deret bilangan interger: 1 + 2 + 3 + 4 + ...)

# Realisasi
def bilint(n):
    if n == 0:
        return 0
    else:
        return bilint(n-1) + n

print (bilint(3))


# %%
# Source node names
source = ['Penny', 'Penny', 'Amy', 'Bernadette', 'Bernadette', 'Sheldon', 'Sheldon', 'Sheldon', 'Rajesh']
# Target node names
target = ['Leonard', 'Amy', 'Bernadette', 'Rajesh', 'Howard', 'Howard', 'Leonard', 'Amy', 'Penny']
# Edge Weights
weight = [5, 3, 2, 2, 5, 2, 3, 5, 2]

# Import and Initialize
from d3blocks import D3Blocks
d3 = D3Blocks()
# Convert
adjmat = d3.vec2adjmat(source, target, weight)
# Print
print(adjmat)

# %%

# Load library
from d3blocks import D3Blocks

# Initialize
d3 = D3Blocks()
# Load stormofswords data sets
df = d3.import_example(data='stormofswords')

# %% Create network graph

# Initialize
d3 = D3Blocks()
# Network graph
d3.d3graph(df, charge=800, collision=2, showfig=True)
# d3.elasticgraph(df, charge=800, collision=2, scaler='zscore')
# Extract the node colors from the network graph.
node_colors = d3.D3graph.node_properties

# %%  Heatmap
# Initialize
d3 = D3Blocks()
# Create the heatmap but do not show it yet because we first need to adjust the colors
d3.heatmap(df, showfig=False)
# Update the colors of the network graph to be consistent with the colors
d3.node_properties

for i, label in enumerate(d3.node_properties['label']):
    if node_colors.get(label) is not None:
        d3.node_properties['color'].iloc[i] = node_colors.get(label)['color']

d3.show(showfig=True, figsize=[600, 600], filepath='c:/temp/heatmap.html', fontsize=8, scaler='zscore')

# %%  Sankey
# Initialize
d3 = D3Blocks()
# Create sankey graph
d3.sankey(df, filepath='c:/temp/sankey.html', showfig=True)


import unittest
from fractions import Fraction
from example import sum

# Basic pattern is to define inputs, run the code then assert the outcomes
class TestSum(unittest.TestCase):
    def test_list_int(self):
        """Test that it can sum a list of integers
        """
        data = [1, 2, 3]
        result = sum(data)
        self.assertEqual(result, 6)

    def test_list_fraction(self):
        """Test that it can add sum of fractions
        """
        data = [Fraction(1,4), Fraction(1,4), Fraction(2,5)]
        result = sum(data)
        self.assertNotEqual(result, 1)
        self.assertEqual(result, Fraction(9, 10))

    def test_bad_type(self):
        """Test that it raises the correct exception
        """
        data = "banana"
        with self.assertRaises(TypeError):
            result = sum(data)

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


import shelve

with shelve.open("bike") as bike:
    bike["make"] = "Honda"
    bike["model"] = "250 dream"
    bike["color"] = "red"

    for key in bike:
        print(key)
    print('=' * 40)

    print(bike["model"])
    print(bike["color"])


from tkinter import *

root = Tk()

root.title("Calculator")

Label1 = Label(root, text="CALCULATOR")
Label1.grid(row=0, columnspan=20)

equa = ""
equation = StringVar()

calculation = Entry(root, textvariable=equation,relief=RIDGE,justify='right', bd=20, bg="powder blue",font='arial 20 bold')

equation.set("")

calculation.grid(row=1, columnspan=8)

def ailachu():
    global equa
    equa = equa + str("ANSHUMAN")
    equation.set(equa)

def btnPress(num):
    global equa
    equa = equa + str(num)
    equation.set(equa)

def EqualPress():
    global equa
    total = str(eval(equa))
    equation.set(total)
    equa = ""

def ClearPress():
    global equa
    equa = ""
    equation.set("")

Button0 = Button(root, text="0", command=lambda: btnPress(0), borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Button0.grid(row=6, column=2,padx=10,pady=10)
Button1 = Button(root, text="1", command=lambda: btnPress(1), borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Button1.grid(row=3, column=1,padx=10,pady=10)
Button2 = Button(root, text="2", command=lambda: btnPress(2), borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Button2.grid(row=3, column=2,padx=10,pady=10)
Button3 = Button(root, text="3", command=lambda: btnPress(3), borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Button3.grid(row=3, column=3,padx=10,pady=10)
Button4 = Button(root, text="4", command=lambda: btnPress(4), borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Button4.grid(row=4, column=1,padx=10,pady=10)
Button5 = Button(root, text="5", command=lambda: btnPress(5), borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Button5.grid(row=4, column=2,padx=10,pady=10)
Button6 = Button(root, text="6", command=lambda: btnPress(6), borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Button6.grid(row=4, column=3,padx=10,pady=10)
Button7 = Button(root, text="7", command=lambda: btnPress(7), borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Button7.grid(row=5, column=1,padx=10,pady=10)
Button8 = Button(root, text="8", command=lambda: btnPress(8), borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Button8.grid(row=5, column=2,padx=10,pady=10)
Button9 = Button(root, text="9", command=lambda: btnPress(9), borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Button9.grid(row=5, column=3,padx=10,pady=10)
Plus = Button(root, text="+", command=lambda: btnPress("+"), borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Plus.grid(row=3, column=4,padx=10,pady=10)
Minus = Button(root, text="-", command=lambda: btnPress("-"), borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Minus.grid(row=4, column=4,padx=10,pady=10)
Multiply = Button(root, text="*", command=lambda: btnPress("*"), borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Multiply.grid(row=5, column=4,padx=10,pady=10)
Divide = Button(root, text="/", command=lambda: btnPress("/"), borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Divide.grid(row=6, column=4,padx=10,pady=10)
Equal = Button(root, text="=", command=EqualPress, borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Equal.grid(row=6, column=3,padx=10,pady=10)
Clear = Button(root, text="C", command=ClearPress, borderwidth=2, relief=SOLID,font='arial 20 bold',width=3,height=1,bg='black',fg='white')
Clear.grid(row=6, column=1,padx=10,pady=10)

ANS = Button(root, text="ANSHUMAN",command=ailachu, borderwidth=2, relief=SOLID,font='arial 20 bold',width=18,height=1,bg='black',fg='white')
ANS.grid(row=7, column=1,padx=10,pady=10,columnspan=8)

root.mainloop()


from flask import Flask
from http import HTTPStatus
from os import makedirs, path

def create_app(test_config=None) -> Flask:
    app = Flask(__name__, instance_relative_config=True)
    app.config.from_mapping(
        SECRET_KEY="dev",
        DATABASE=path.join(app.instance_path, "flaskr.sqlite")
    )

    if test_config is None:
        app.config.from_pyfile("config.py", silent=True)
    else:
        app.config.from_mapping(test_config)

    try:
        makedirs(app.instance_path)
    except OSError:
        pass

    @app.get("/hello")
    def hello() -> tuple[str, int]:
        return "Hello, World!", HTTPStatus.OK

    from flaskr import db
    db.init_app(app)

    from flaskr import auth
    app.register_blueprint(auth.blueprint)

    from flaskr import blog
    app.register_blueprint(blog.blueprint)
    app.add_url_rule("/", endpoint="index")

    return app


import datetime
from pymongoose import methods
from pymongoose.mongo_types import Types, Schema, MongoException, MongoError
from bson import json_util
from bson.objectid import ObjectId

roles = None

def role_model_init (db):
   global roles
   roles = db["roles"]

class Role(Schema):
    id = None
    name = None
    action = None

    def __init__(self, **kwargs):
        self.schema = {
            "name": {
                "type": Types.String,
                "required": True
            },
            "action": {
                "type": Types.String,
                "required": True
            }
        }

        if not "empty" in kwargs:
            self.id = ObjectId()
            self.name = super().get_default_value("name", kwargs)
            self.action = super().get_default_value("action", kwargs)

        self.iat = 0
        self.items_count = 0

    def __str__(self):
        return f"Role: {self.name}, Password: {self.action}"

    def fromJson(self, json_obj):
        self.id = super().extract("_id", json_obj)
        self.name = super().extract("name", json_obj)
        self.action = super().extract("action", json_obj)

    def toJson(self, full = True):
        json_obj =  {
            "name": self.name,
            "action": self.action
        }
        if full:
            json_obj["id"] = self.id
        return super().convert_json(json_obj) if full else json_obj

    def save(self, id = None):
        if not super().validate_required(self.toJson(False), super().schema):
            raise MongoException(message="Required fields missing", mongoError=MongoError.Required_field)
        else:
            json_obj = self.toJson(False)
            if id is not None:
                json_obj["_id"] = id

            self.id = roles.insert(json_obj)
        return self.id

    @staticmethod
    def exists(query):
        global roles
        retval = methods.exists(roles, query)
        return retval
    @staticmethod
    def find(query, select = None, populate=None, one=False):
        global roles
        retval = methods.find(roles, Role.schema, query, select, populate, one)
        if one:
            retval = Role.parse(retval)
        return retval

    @staticmethod
    def find_by_id(id, select = None, populate=None, one=False):
        global roles
        retval = methods.find_by_id(roles, Role.schema, id, select, populate)
        return Role.parse(retval)

    @staticmethod
    def update(query, update, many = False):
        global roles
        retval = methods.update(roles, query, update, many)
        return retval

    @staticmethod
    def delete(query, many = False):
        global roles
        retval = methods.delete(roles, query, many)
        return retval

    @staticmethod
    def parse(dictionary):
        role = Role()
        role.fromJson(dictionary)
        return role


import torch
from torch import nn
import os
from sklearn.model_selection import KFold
import src.datasets as ds
import src.models as m
from datetime import datetime
from sklearn.metrics import confusion_matrix, f1_score
import seaborn as sn
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

PROJECT_PATH = os.path.dirname(__file__)
TRAIN_LABELS = os.path.join(PROJECT_PATH, "data/processed/MDCT_SPLIT/train_labels.csv")
VAL_LABELS = os.path.join(PROJECT_PATH, "data/processed/MDCT_SPLIT/val_labels.csv")
MINIP_TRAIN = os.path.join(PROJECT_PATH, "data/processed/MDCT_SPLIT/MINIP/train")
MINIP_VAL = os.path.join(PROJECT_PATH, "data/processed/MDCT_SPLIT/MINIP/val")

# parts of code based on pytorch tutorial https://pytorch.org/tutorials/beginner/basics/optimization_tutorial.html
# and https://github.com/christianversloot/machine-learning-articles/blob/main/how-to-use-k-fold-cross-validation-with-pytorch.md

def train_loop(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)
    for batch, (X, y) in enumerate(dataloader):
        # Compute prediction and loss
        pred = model(X)
        loss = loss_fn(pred, y)

        # Backpropagation
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if batch % 100 == 0:
            loss, current = loss.item(), batch * len(X)
            print(f"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]")

def test_loop(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    test_loss, correct = 0, 0

    with torch.no_grad():
        for X, y in dataloader:
            pred = model(X)
            test_loss += loss_fn(pred, y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()

    test_loss /= num_batches
    correct /= size
    print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")

def reset_weights(model):
  '''
    Try resetting model weights to avoid
    weight leakage.
  '''
  for layer in model.children():
   if hasattr(layer, 'reset_parameters'):
    print(f'Reset trainable parameters of layer = {layer}')
    layer.reset_parameters()

def train_model(model, dataset, k_folds, learning_rate, weight_decay,  batch_size, epochs, loss_function, optimizer,
                class_weights=None, pretrained=False, save_model=False, metrics=None, manual_seed = None,
                log_notes=""):
    """
    Takes a neural network model and its hyperparameters to train it on a dataset.

    :param model: [class] Neural network model which should be trained
    :param dataset: [torch.utils.data.Dataset] Pytorch Dataset
    :param k_folds: [int] Number of folds to perform in k-fold cross validation
    :param learning_rate: [float] The learning rate with which the optimizer should step
    :param weight_decay: [float] Weight decay (L2 Penalty) for optimizer
    :param batch_size: [int] Number of samples in one batch
    :param epochs: [int] Number of epochs to perform in each fold.
    :param loss_function: [function] Pytorch loss function.
    :param optimizer: [function] Pytorch optimizer.
    :param class_weights: [torch.Tensor, str] If given, the loss function weights the classes according to the
    class_weights, if set to "auto_balance" the class_weights are automatically set to balance the classes.
    :param pretrained: [bool] Set to True if a pretrained Network is used, to avoid resetting pretrained parameters.
    :param save_model: [bool] Set to True if model should be saved to ./log/training_log.
    :param metrics: [list] Metrics to calculate and save.
    :param manual_seed: [int] If given, manual torch seed is set.
    :param log_notes: [string] String containing notes to add to log file.
    :return: None
    """

    # For fold results
    results = {}

    # Set fixed random number seed
    if manual_seed:
        torch.manual_seed(manual_seed)

    # Define the K-fold Cross Validator
    kfold = KFold(n_splits=k_folds, shuffle=True)

    # Init the neural network
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    network = model
    model = model.to(device=device)

    # create log folder
    now = datetime.now()
    LOG_DIR = os.path.join(PROJECT_PATH, "log/training_log", now.strftime("%Y_%m_%d__%H_%M_%S") + "_model_log")
    os.mkdir(LOG_DIR)

    # write to log file
    log_file = open(os.path.join(LOG_DIR, "model_log.txt") ,"w")
    log_file.write("k_folds = " + str(k_folds) + "\n" +
                   "learning_rate = " + str(learning_rate) + "\n" +
                   "batch_size = " + str(batch_size) + "\n" +
                   "epochs = " + str(epochs) + "\n" +
                   "loss_function = " + str(loss_function) + "\n" +
                   "optimizer = " + str(optimizer) + "\n" +
                   "class_weights = " + str(class_weights) + "\n" +
                   "pretrained = " + str(pretrained) + "\n" +
                   "manual_seed = " + str(manual_seed) + "\n" +
                   "model = " + str(model) + "\n\n" +
                   log_notes)
    log_file.close()

    # Add weights to loss function
    if class_weights is not None:
        if class_weights == "auto_balance":
            weights = dataset.balanced_class_weights()
            loss_function.weight = weights
            print(f"Class weights set to auto balance: {weights}")
        else:
            loss_function.weight = class_weights

    # Start print
    print('--------------------------------')

    # K-fold Cross Validation model evaluation
    for fold, (train_ids, test_ids) in enumerate(kfold.split(dataset)):
        # Print
        print(f'FOLD {fold+1}/{k_folds}')
        print('--------------------------------')

        # Losses for Plot
        train_losses = []
        test_losses = []

        # Accuracies for Plot
        train_accuracies = []
        test_accuracies = []

        # Sample elements randomly from a given list of ids, no replacement.
        train_subsampler = torch.utils.data.SubsetRandomSampler(train_ids)
        test_subsampler = torch.utils.data.SubsetRandomSampler(test_ids)

        # Define data loaders for training and testing data in this fold
        trainloader = torch.utils.data.DataLoader(
            dataset,
            batch_size=batch_size, sampler=train_subsampler)
        testloader = torch.utils.data.DataLoader(
            dataset,
            batch_size=batch_size, sampler=test_subsampler)

        # Reset weights
        if not pretrained:
            network.apply(reset_weights)
        else:
            for layer in model.fc.children():
                try:
                    torch.nn.init.xavier_uniform_(layer.weight)
                except AttributeError:
                    pass

        # Initialize optimizer
        optim = optimizer(network.parameters(), lr=learning_rate, weight_decay=weight_decay)

        # Run the training loop for defined number of epochs
        for epoch in range(0, epochs):

            # Print epoch
            print(f'Starting epoch {epoch + 1}/{epochs}')

            # Set current loss value
            current_loss = 0.0

            # epoch loss
            epoch_train_loss = 0.0

            # lists for F1 scores
            epoch_train_pred = []
            epoch_train_targets = []

            # Iterate over the DataLoaders batches for training data
            for i, data in enumerate(trainloader, 0):

                # Get inputs
                inputs, targets = data

                # Zero the gradients
                optim.zero_grad()

                # Perform forward pass
                outputs = network(inputs)

                # save output and targets
                epoch_train_pred.extend(outputs)
                epoch_train_targets.extend(targets)

                # Compute loss
                loss = loss_function(outputs, targets)

                # Perform backward pass
                loss.backward()

                # Perform optimization
                optim.step()

                # Print statistics
                current_loss += loss.item()
                epoch_train_loss += loss.item()/(len(trainloader)*batch_size)

                if i % 10 == 9:
                    print('Loss after mini-batch %5d: %.3f' %
                          (i + 1, current_loss / 100))
                    current_loss = 0.0

            train_losses.append(epoch_train_loss)

            # calculate F1 scores
            epoch_train_targets = [int(i) for i in epoch_train_targets]
            epoch_train_pred = [int(np.argmax(i.detach().numpy())) for i in epoch_train_pred]
            epoch_train_accuracy = f1_score(epoch_train_targets, epoch_train_pred, average='micro')
            epoch_train_macro_f1 = f1_score(epoch_train_targets, epoch_train_pred, average='macro')
            epoch_train_weighted_f1 = f1_score(epoch_train_targets, epoch_train_pred, average='weighted')

            train_accuracies.append(epoch_train_accuracy)
            # print epoch Train metrics
            print("\nEpoch Train Metrics\n")
            print(f"Accuracy: {int(epoch_train_accuracy*100)}%")
            print(f"Macro F1 Score: {int(epoch_train_macro_f1*100)}%")
            print(f"Weighted F1 Score: {int(epoch_train_weighted_f1*100)}%\n")

            # Evaluation for this epoch
            epoch_test_loss = 0.0
            epoch_test_pred = []
            epoch_test_targets = []

            with torch.no_grad():
                # Iterate over the test data and generate predictions
                for i, data in enumerate(testloader, 0):
                    # Get inputs
                    inputs, targets = data

                    # Generate outputs
                    outputs = network(inputs)

                    # save output and targets
                    epoch_test_pred.extend(outputs)
                    epoch_test_targets.extend(targets)

                    # calculate loss
                    epoch_test_loss += loss_function(outputs, targets)/(len(testloader)*batch_size)

            # add loss to test_losses list
            test_losses.append(epoch_test_loss)

            # calculate test F1 score
            epoch_test_targets = [int(i) for i in epoch_test_targets]
            epoch_test_pred = [int(np.argmax(i)) for i in epoch_test_pred]
            epoch_test_accuracy = f1_score(epoch_test_targets, epoch_test_pred, average='micro')
            epoch_test_macro_f1 = f1_score(epoch_test_targets, epoch_test_pred, average='macro')
            epoch_test_weighted_f1 = f1_score(epoch_test_targets, epoch_test_pred, average='weighted')

            # print epoch test metrics
            print("Epoch Test Metrics\n")
            print(f"Accuracy: {int(epoch_test_accuracy*100)}%")
            print(f"Macro F1 Score: {int(epoch_test_macro_f1*100)}%")
            print(f"Weighted F1 Score: {int(epoch_test_weighted_f1*100)}%\n")

            print("====================================\n")

        # Process is complete.
        print('Training process has finished.')

        # Print about testing
        print('Starting testing')

        # Saving the model
        if save_model:
            torch.save(network.state_dict(), os.path.join(LOG_DIR, f'model-fold-{fold}.pth'))

        # Evaluation for this fold
        y_pred = []
        y_true = []
        correct, total = 0, 0
        with torch.no_grad():

            # Iterate over the test data and generate predictions
            for i, data in enumerate(testloader, 0):

                # Get inputs
                inputs, targets = data
                y_true.extend(targets)
                # Generate outputs
                outputs = network(inputs)
                y_pred.extend((torch.max(torch.exp(outputs), 1)[1]).data.cpu().numpy())
                # Set total and correct
                _, predicted = torch.max(outputs.data, 1)
                total += targets.size(0)
                correct += (predicted == targets).sum().item()

            # Print accuracy
            print('Accuracy for fold %d: %d %%' % (fold + 1, 100.0 * correct / total))
            print('--------------------------------')
            results[fold] = 100.0 * (correct / total)

        # Plot and save metrics
        if metrics:
            # confusion matrix
            # https://christianbernecker.medium.com/how-to-create-a-confusion-matrix-in-pytorch-38d06a7f04b7
            if 'confusion_matrix' in metrics:
                # Build confusion matrix
                cf_matrix = confusion_matrix(y_true, y_pred)
                # df_cm = pd.DataFrame(cf_matrix / np.sum(cf_matrix) * 10)
                df_cm = pd.DataFrame(cf_matrix)
                plt.figure(figsize=(12, 7))
                sn.heatmap(df_cm, annot=True, fmt='g')
                plt.ylabel("true")
                plt.xlabel("predicted")
                plt.title("Confusion Matrix")
                try:
                    os.mkdir(os.path.join(LOG_DIR, "confmat"))
                except FileExistsError:
                    pass
                plt.savefig(os.path.join(LOG_DIR, f"confmat/confmat_FOLD{fold + 1}.png"))

            if 'loss_plot' in metrics:
                plt.figure(figsize=(6, 4))
                plt.plot(range(epochs), train_losses, 'aquamarine', label='Train Loss')
                plt.plot(range(epochs), test_losses, 'orange', label='Test Loss')
                plt.legend(loc="upper left")
                plt.ylabel("loss")
                plt.xlabel("epochs")
                plt.title("Train and Test Loss")
                try:
                    os.mkdir(os.path.join(LOG_DIR, "loss_plot"))
                except FileExistsError:
                    pass
                plt.savefig(os.path.join(LOG_DIR, f"loss_plot/loss_plot_FOLD{fold + 1}.png"))

            if 'accuracy_plot' in metrics:
                plt.figure(figsize=(6, 4))
                plt.plot(range(epochs), train_accuracies, 'aquamarine', label='Train Accuracy')
                plt.plot(range(epochs), test_accuracies, 'orange', label='Test Accuracy')
                plt.legend(loc="upper left")
                plt.ylabel("accuracy in %")
                plt.xlabel("epochs")
                plt.ylim((0, 100))
                plt.title("Train and Test Accuracy")
                try:
                    os.mkdir(os.path.join(LOG_DIR, "accuracy_plot"))
                except FileExistsError:
                    pass
                plt.savefig(os.path.join(LOG_DIR, f"accuracy_plot/accuracy_plot_FOLD{fold + 1}.png"))

    # Print fold results
    print(f'K-FOLD CROSS VALIDATION RESULTS FOR {k_folds} FOLDS')
    print('--------------------------------')
    fold_sum = 0.0
    performance = ""
    for key, value in results.items():
        performance += f'Fold {key}: {value} % \n'
        fold_sum += value
    performance += f'Average: {fold_sum / len(results.items())} %'
    print(performance)

    # write to log file
    performance_file = open(os.path.join(LOG_DIR, "model_performance.txt") ,"w")
    performance_file.write("Performance:\n" + performance)
    performance_file.close()

# example run
train_model(model=m.AlexNetBN1,
            dataset=ds.minipAPAlexNet25,
            k_folds=5,
            learning_rate=1e-4,
            weight_decay=0,
            batch_size=10,
            epochs=30,
            loss_function=nn.CrossEntropyLoss(),
            optimizer=torch.optim.Adam,
            class_weights="auto_balance",
            pretrained=False,
            save_model=False,
            metrics=['confusion_matrix', 'loss_plot', 'accuracy_plot'],
            log_notes="AlexNetBN1 model with dataset minipAPAlexNet25")


'''Mediana de três valores. Escreva uma função que recebe três números como parâmetros e
retorna o valor da mediana desses parâmetros como seu resultado. Inclua um programa
principal que lê três valores do usuário e exibe a mediana destes valores.
Dica: a mediana é o valor do meio dos três valores quando eles são classificados em
ordem crescente. Ela pode ser encontrada usando comandos condicionais ou então com
um pouco de criatividade matemática (veja exercício 4 da lista 2).'''

def mediana(valor1, valor2, valor3):
    maior = max(valor1, valor2, valor3)
    menor = min(valor1, valor2, valor3)
    meio = ((valor1 + valor2 + valor3) - (maior + menor))
    print("A mediana é:", meio)

valor1 = int(input("Digite um valor:"))
valor2 = int(input("Digite um valor:"))
valor3 = int(input("Digite um valor:"))
mediana(valor1, valor2, valor3)


# @Time    : 2019/4/22 0:56
# @Author  : Noah
# @File    : asyncioDemo
# @Software: PyCharm
# @description: 是一个使用async / await语法编写并发代码的库

# 内置对异步IO的支持
import asyncio
import datetime
import time

from asyncio import CancelledError

###########################################################################
async def main():
    print("Hello ...")
    await asyncio.sleep(1)
    print("... World!")

asyncio.run(main())

###########################################################################
async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)

async def main():
    task1 = asyncio.create_task(
        say_after(1, 'hello')
    )
    task2 = asyncio.create_task(
        say_after(2, 'world')
    )
    print(f"started at {time.strftime('%X')}")

    await task1
    await task2

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

###########################################################################
async def nested():
    return 42

async def main():
    task = asyncio.create_task(nested())
    await task

asyncio.run(main())

###########################################################################
async def display_date():
    loop = asyncio.get_running_loop()
    end_time = loop.time() + 5.0

    while True:
        print(datetime.datetime.now())
        if (loop.time() + 1.0) >= end_time:
            break
        await asyncio.sleep(1)

asyncio.run(display_date())

###########################################################################
async def factorial(name, number):
    f = 1
    for i in range(2, number + 1):
        print(f"Task {name}: Compute factorial({i})...")
        await asyncio.sleep(1)
    print(f"Task {name}: factorial({number}) = {f}")

async def main():
    await asyncio.gather(
        factorial("A", 2),
        factorial("B", 3),
        factorial("C", 4),
    )

asyncio.run(main())

###########################################################################
async def something():
    pass

async def main():
    try:
        res = await asyncio.shield(something())
    except CancelledError:
        res = None

    try:
        await asyncio.wait_for(something(), timeout=1.0)
    except asyncio.TimeoutError:
        print("timeout!")

asyncio.run(main())

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

import asyncio

@asyncio.coroutine
def hello():
    print("Hello world!")
    yield from asyncio.sleep(1)
    print("Hello again!")

# 获取EventLoop:
loop = asyncio.get_event_loop()
# 执行coroutine
loop.run_until_complete(hello())
loop.close()

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


from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render
from rest_framework import status

class AuthMD(MiddlewareMixin):  # 验证登录
    def process_request(self, request):  # 请求之前
        ret={'errMsg':'', 'errCode':'', 'url':''}
        request_url = request.path_info

        if request_url == '/login/' or request.session.get("id"): #要登陆或已登录
            return None
        else:
            ret["errMsg"] = "用户未登录"
            ret["errCode"] = status.HTTP_400_BAD_REQUEST
            ret["url"] = "login/"
        # 错误提示
        return render(request, 'user/error.html', ret)


import os
import tempfile

import numpy as np
from pytest import approx

import gimpenums
from pgimp.GimpFile import GimpFile, LayerType, ColorMap, GimpFileType
from pgimp.util import file
from pgimp.util.TempFile import TempFile

rgb_file = GimpFile(file.relative_to(__file__, 'test-resources/rgb.xcf'))
"""
The file rgb.xcf contains a 3x2 image with white 'Background' layer and 'Red', 'Green', 'Blue' layers with differing
opacity. The layer 'Background' contains a black pixel at y=0, x=1, the others pixels are white.
"""

def test_layer_to_numpy():
    actual = rgb_file.layer_to_numpy('Background')
    expected = np.array([
        [[255, 255, 255], [0, 0, 0], [255, 255, 255]],
        [[255, 255, 255], [255, 255, 255], [255, 255, 255]],
    ], dtype=np.uint8)

    assert np.all(expected == actual)
    assert actual.shape == (2, 3, 3)

def test_layers_to_numpy():
    use_temp_file_values = [True, False]
    for use_temp_file in use_temp_file_values:
        with TempFile('.xcf') as f:
            gimp_file = GimpFile(f) \
                .create('Red', np.zeros(shape=(1, 2, 3), dtype=np.uint8)) \
                .add_layer_from_numpy('Green', np.ones(shape=(1, 2, 3), dtype=np.uint8) * 127) \
                .add_layer_from_numpy('Blue', np.ones(shape=(1, 2, 3), dtype=np.uint8) * 255)
            np_array = gimp_file.layers_to_numpy(['Red', 'Green', 'Blue'], use_temp_file=use_temp_file)

        assert (1, 2, 9) == np_array.shape
        assert np.all(np.array([
            [[0, 0, 0, 127, 127, 127, 255, 255, 255], [0, 0, 0, 127, 127, 127, 255, 255, 255]],
        ], dtype=np.uint8) == np_array)

def test_create():
    filename = file.relative_to(__file__, 'test-resources/test-create.xcf')
    layer_bg = np.array([
        [[255, 255, 255], [0, 0, 0], [255, 255, 255]],
        [[255, 255, 255], [255, 255, 255], [255, 255, 255]],
    ], dtype=np.uint8)

    gimp_file = GimpFile(filename)
    gimp_file.create('Background', layer_bg)

    exists = os.path.exists(filename)
    actual = gimp_file.layer_to_numpy('Background')
    os.remove(filename)

    assert exists
    assert np.all(layer_bg == actual)

def test_add_layers_from_numpy():
    with TempFile('.xcf') as f:
        gimp_file = GimpFile(f).create('Background', np.zeros(shape=(1, 2), dtype=np.uint8))
        gimp_file.add_layers_from_numpy(
            ['Layer 1', 'Layer 2'],
            np.ones(shape=(2, 1, 2), dtype=np.uint8) * 255,
            opacity=55.,
            visible=False,
            position='Background'
        )
        assert gimp_file.layer_names() == ['Layer 1', 'Layer 2', 'Background']

def test_add_layers_from_numpy_with_list_config():
    with TempFile('.xcf') as f:
        gimp_file = GimpFile(f).create('Background', np.zeros(shape=(1, 2), dtype=np.uint8))
        gimp_file.add_layers_from_numpy(
            ['Layer 1', 'Layer 2'],
            np.ones(shape=(2, 1, 2), dtype=np.uint8) * 255,
            opacity=[100., 55.],
            visible=[False, True],
            position='Background',
            blend_mode=gimpenums.NORMAL_MODE
        )
        assert gimp_file.layer_names() == ['Layer 1', 'Layer 2', 'Background']

def test_add_layer_from_numpy():
    tmp_file = tempfile.mktemp(suffix='.xcf')
    layer_bg = np.array([
        [[255, 255, 255], [0, 0, 0], [255, 255, 255]],
        [[255, 255, 255], [255, 255, 255], [255, 255, 255]],
    ], dtype=np.uint8)
    layer_fg = np.array([
        [[255, 255, 255], [255, 255, 255], [255, 255, 255]],
        [[255, 255, 255], [0, 0, 0], [255, 255, 255]],
    ], dtype=np.uint8)

    gimp_file = GimpFile(tmp_file)
    gimp_file.create('Background', layer_bg)
    gimp_file.add_layer_from_numpy('Foreground', layer_fg, opacity=55., visible=False)

    actual_bg = gimp_file.layer_to_numpy('Background')
    actual_fg = gimp_file.layer_to_numpy('Foreground')

    os.remove(tmp_file)

    assert np.all(layer_bg == actual_bg)
    assert np.all(layer_fg == actual_fg)

def test_add_layer_from_numpy_with_position_index():
    data = np.array([[[255, 255, 255]]], dtype=np.uint8)
    with TempFile('.xcf') as tmp_file:
        gimp_file = GimpFile(tmp_file)
        gimp_file.create('Background', data)
        gimp_file.add_layer_from_numpy('Layer 1', data, position=1)
        gimp_file.add_layer_from_numpy('Layer 2', data, position=1)

        assert gimp_file.layer_names() == ['Background', 'Layer 2', 'Layer 1']

def test_add_layer_from_numpy_with_position_layer_name():
    data = np.array([[[255, 255, 255]]], dtype=np.uint8)
    with TempFile('.xcf') as tmp_file:
        gimp_file = GimpFile(tmp_file)
        gimp_file.create('Background', data)
        gimp_file.add_layer_from_numpy('Layer 1', data, position='Background')
        gimp_file.add_layer_from_numpy('Layer 2', data, position='Background')

        assert gimp_file.layer_names() == ['Layer 1', 'Layer 2', 'Background']

def test_add_layer_from_file():
    with TempFile('.xcf') as dst, TempFile('.xcf') as src:
        layer_bg = np.array([
            [[255, 255, 255], [0, 0, 0], [255, 255, 255]],
            [[255, 255, 255], [255, 255, 255], [255, 255, 255]],
        ], dtype=np.uint8)
        position = 1

        src_file = GimpFile(src)
        src_file.create('Background', np.zeros(shape=(2, 3, 3), dtype=np.uint8))
        src_file.add_layer_from_numpy('Yellow', np.array([
            [[240, 255, 0], [240, 255, 0], [240, 255, 0]],
            [[240, 255, 0], [240, 255, 0], [240, 255, 0]],
        ], dtype=np.uint8))

        dst_file = GimpFile(dst)
        dst_file.create('Background', layer_bg)
        dst_file.add_layer_from_file(src_file, 'Yellow', new_name='Yellow (copied)', new_position=position)

        assert 'Yellow (copied)' == dst_file.layers()[position].name
        assert np.all([240, 255, 0] == dst_file.layer_to_numpy('Yellow (copied)'))

def test_merge_layer_from_file():
    with TempFile('.xcf') as dst, TempFile('.xcf') as src:
        layer_bg = np.array([
            [[255, 255, 255], [0, 0, 0], [255, 255, 255]],
            [[255, 255, 255], [255, 255, 255], [255, 255, 255]],
        ], dtype=np.uint8)

        src_file = GimpFile(src)
        src_file.create('Background', np.zeros(shape=(2, 3, 3), dtype=np.uint8))
        src_file.add_layer_from_numpy('Yellow', np.array([
            [[240, 255, 0], [240, 255, 0], [240, 255, 0]],
            [[240, 255, 0], [240, 255, 0], [240, 255, 0]],
        ], dtype=np.uint8))

        dst_file = GimpFile(dst)
        dst_file.create('Yellow', layer_bg)
        dst_file.merge_layer_from_file(src_file, 'Yellow')

        new_layer_contents = dst_file.layer_to_numpy('Yellow')

        assert np.all([240, 255, 0] == new_layer_contents)

def test_merge_layer_from_file_with_cleared_selection():
    src = file.relative_to(__file__, 'test-resources/selection.xcf')
    with TempFile('.xcf') as dst:
        src_file = GimpFile(src)
        dst_file = GimpFile(dst)
        dst_file.create('Background', np.zeros(shape=(3, 3, 3), dtype=np.uint8))
        dst_file.merge_layer_from_file(src_file, 'Background')

        new_layer_contents = dst_file.layer_to_numpy('Background')

        assert np.all(np.array([
            [[255, 255, 255], [255, 255, 255], [255, 255, 255]],
            [[255, 0, 0], [255, 0, 0], [255, 255, 255]],
            [[255, 255, 255], [255, 255, 255], [255, 255, 255]],
        ], dtype=np.uint8) == new_layer_contents)

def test_merge_layer_from_file_without_cleared_selection():
    src = file.relative_to(__file__, 'test-resources/selection.xcf')
    with TempFile('.xcf') as dst:
        src_file = GimpFile(src)
        dst_file = GimpFile(dst)
        dst_file.create('Background', np.zeros(shape=(3, 3, 3), dtype=np.uint8))
        dst_file.merge_layer_from_file(src_file, 'Background', clear_selection=False)

        new_layer_contents = dst_file.layer_to_numpy('Background')

        assert np.all(np.array([
            [[0, 0, 0], [0, 0, 0], [0, 0, 0]],
            [[255, 0, 0], [255, 0, 0], [0, 0, 0]],
            [[0, 0, 0], [0, 0, 0], [0, 0, 0]],
        ], dtype=np.uint8) == new_layer_contents)

def test_layers():
    layers = rgb_file.layers()

    assert ['Blue', 'Green', 'Red', 'Background'] == list(map(lambda x: x.name, layers))
    assert [0, 1, 2, 3] == list(map(lambda x: x.position, layers))
    assert [False, False, False, True] == list(map(lambda x: x.visible, layers))
    assert [23.92156862745098, 40.3921568627451, 52.54901960784314, 100.0] == list(map(lambda x: approx(x.opacity), layers))

def test_convert_to_indexed_using_predefined_colormap():
    tmp_file = tempfile.mktemp(suffix='.xcf')
    values = np.array([[i for i in range(0, 256)]], dtype=np.uint8)
    assert (1, 256) == values.shape

    gimp_file = GimpFile(tmp_file)
    gimp_file.create_indexed('Background', values, ColorMap.JET)
    gimp_file.add_layer_from_numpy('Values', values, type=LayerType.INDEXED)

    layer_bg = gimp_file.layer_to_numpy('Background')
    layer_values = gimp_file.layer_to_numpy('Values')

    os.remove(tmp_file)

    assert (1, 256, 1) == layer_bg.shape
    assert np.all(values == layer_bg[:, :, 0])
    assert (1, 256, 1) == layer_values.shape
    assert np.all(values == layer_values[:, :, 0])

def test_convert_to_indexed_using_custom_colormap():
    tmp_file = tempfile.mktemp(suffix='.xcf')
    values = np.array([[i for i in range(0, 256)]], dtype=np.uint8)
    assert (1, 256) == values.shape
    colormap = np.array([[255, 0, 0], [0, 255, 0], [0, 0, 255], *[[i, i, i] for i in range(3, 256)]], dtype=np.uint8)
    assert (256, 3) == colormap.shape

    gimp_file = GimpFile(tmp_file)
    gimp_file.create_indexed('Background', values, colormap=colormap)
    gimp_file.add_layer_from_numpy('Values', values, type=LayerType.INDEXED)

    layer_bg = gimp_file.layer_to_numpy('Background')
    layer_values = gimp_file.layer_to_numpy('Values')

    os.remove(tmp_file)

    assert (1, 256, 1) == layer_bg.shape
    assert np.all(values == layer_bg[:, :, 0])
    assert (1, 256, 1) == layer_values.shape
    assert np.all(values == layer_values[:, :, 0])

def test_remove_layer():
    tmp_file = tempfile.mktemp(suffix='.xcf')
    layer = np.array([
        [[255, 255, 255], [0, 0, 0], [255, 255, 255]],
        [[255, 255, 255], [255, 255, 255], [255, 255, 255]],
    ], dtype=np.uint8)

    gimp_file = GimpFile(tmp_file)
    gimp_file.create('Background', layer)
    gimp_file.add_layer_from_numpy('Layer', layer)
    all_layers = gimp_file.layer_names()

    gimp_file.remove_layer('Background')
    remaining_layers1 = gimp_file.layer_names()
    gimp_file.remove_layer('Layer')
    remaining_layers2 = gimp_file.layer_names()

    os.remove(tmp_file)

    assert ['Layer', 'Background'] == all_layers
    assert ['Layer'] == remaining_layers1
    assert [] == remaining_layers2

def test_copy():
    with TempFile('.xcf') as original, TempFile('.xcf') as copy:
        original_file = GimpFile(original).create('Background', np.zeros(shape=(2, 2), dtype=np.uint8))
        copied_file = original_file.copy(copy)
        original_file.add_layer_from_numpy('New', np.zeros(shape=(2, 2), dtype=np.uint8))
        assert ['Background'] == copied_file.layer_names()
        assert ['New', 'Background'] == original_file.layer_names()

def test_dimensions():
    assert (3, 2) == rgb_file.dimensions()

def test_create_from_template():
    with TempFile('.xcf') as original, TempFile('.xcf') as created:
        original_file = GimpFile(original).create('Background', np.zeros(shape=(3, 2), dtype=np.uint8))
        created_file = GimpFile(created).create_from_template(original_file)
        assert [] == created_file.layer_names()
        assert (2, 3) == created_file.dimensions()

def test_create_empty():
    with TempFile('.xcf') as f:
        gimp_file = GimpFile(f).create_empty(3, 2, GimpFileType.RGB)
        assert (3, 2) == gimp_file.dimensions()
        assert [] == gimp_file.layer_names()

def test_create_from_file():
    test_export()

def test_export():
    with TempFile('.xcf') as xcf, TempFile('.png') as png,  TempFile('.jpg') as jpg, TempFile('.xcf') as from_png:
        gimp_file = GimpFile(xcf) \
            .create('Background', np.zeros(shape=(1, 1), dtype=np.uint8)) \
            .add_layer_from_numpy('Foreground', np.ones(shape=(1, 1), dtype=np.uint8) * 255, opacity=50.) \
            # 50% opacity results in uint8 of 127 or 128 depending on the implementation -> needs test tolerance

        gimp_file.export(png)  # saved as grayscale with alpha (identify -format '%[channels]' FILE)
        gimp_file.export(jpg)

        reimported_np_from_png = GimpFile(from_png).create_from_file(png, layer_name='Image').layer_to_numpy('Image')
        assert np.isclose(reimported_np_from_png[0, 0, 0], 127.5, atol=0.5)
        assert reimported_np_from_png[0, 0, 1] == 255

        reimported_np_from_jpg = GimpFile(from_png).create_from_file(jpg, layer_name='Image').layer_to_numpy('Image')
        assert np.isclose([127.5], reimported_np_from_jpg, atol=0.5)


#coding:utf-8
'''
Created on 2018年9月23日

@author: You Nannan
'''

import os
import datetime
import math

def mkdirIfNotExist(theDir):
    folder = os.path.exists(theDir)
    if not folder:
        os.makedirs(theDir)

def readListFromFile(filename):
    '''从filename中读取列表或字典'''
    with open(filename) as file_object:
        theListStr = file_object.read()
    return eval(theListStr)

def writeListToFile(filename, theList, isRepr = True):
    '''向filename中写入列表或字典'''
    with open(filename, "w") as file_object:
        if isRepr is True:
            file_object.write(repr(theList))
        else:
            file_object.write(str(theList))

def getDaysList(beginDate, endDate):
    '''获取从[beginDate,endDate)中的所有日期列表'''
    theDaysList = []
    iDate = beginDate
    while iDate < endDate:
        theDaysList.append(iDate)
        iDate += datetime.timedelta(days=1)
    return theDaysList

def getClassName(theValue):
    theClassName = str(type(theValue))[8:-2]
    theClassName = theClassName[theClassName.rfind(".") + 1:]
    return theClassName

def getExpectedStandard(theList):
    '''计算theList样本序列的期望和标准差，此处的标准差是总体标准差，不是样本标准差'''
    theCount = len(theList)
    if theCount < 1:
        return None
    if theCount == 1:
        return [theList[0], 0.0]

    theSum = 0.0
    for i in range(theCount):
        theSum += theList[i]
    theExpected = theSum / theCount
    theSum = 0.0
    for i in range(theCount):
        theSum += (theList[i] - theExpected)**2
    theStandard = math.sqrt(theSum / (theCount - 1)) #这里的标准差是总体标准差，而不是样本标准差，所以除以(theCount - 1)而不是除以theCount
    return [theExpected, theStandard]


import uuid

from django.conf import settings
from django.contrib.auth.models import User
from django.db import models

# Create your models here.
from django.utils import timezone
# User = settings.AUTH_USER

class Room(models.Model):
    name = models.CharField('Room Name', max_length=256, unique=True)
    description = models.TextField('Description', null=True, blank=True)
    created_date = models.DateTimeField(auto_now_add=True)

class Message(models.Model):
    uuid_id = models.UUIDField(default=uuid.uuid3, primary_key=True)
    time = models.DateTimeField(auto_now_add=True)
    sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sent_messages')
    text = models.TextField(max_length=1024)
    room = models.ForeignKey(Room, related_name="chat_messages", on_delete=models.CASCADE)
    seen = models.BooleanField(default=False)
    seen_time = models.DateTimeField(null=True, blank=True)
    delivered = models.BooleanField(default=False)

    def set_seen(self):
        if not self.seen:
            self.seen = True
            self.seen_time = timezone.now()
            self.save()

    def set_delivered(self):
        if not self.delivered:
            self.delivered = True
            self.save()

    class Meta:
        ordering = ['-time']
        get_latest_by = ['-time']